feat(marketing): Add page type configuration and validation for marketing wizard

- Add page type selection (company or organization) with dynamic form fields
- Implement conditional validation for company-specific fields (language, company name, country)
- Update HeroStep with URL pattern validation for GIF file input
- Modify page submission to include page type and related configuration data
- Enhance form handling with react-hook-form for page type configuration
- Add input groups and select components for page type configuration section
This commit is contained in:
AmirReza Jamali
2025-11-09 17:01:52 +03:30
parent 4f7b258533
commit ed18d86960
2 changed files with 142 additions and 2 deletions
@@ -2,6 +2,7 @@
import InputGroup from "@/components/FormElements/InputGroup";
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import { REGEX } from "@/constants/regex";
import { FormErrorMessages } from "@/constants/Texts";
import { forwardRef, useImperativeHandle } from "react";
import useHeroStepPresenter from "./useHeroStepPresenter";
@@ -113,6 +114,7 @@ const HeroStep = forwardRef((props, ref) => {
<InputGroup
{...register("gifFile", {
required: { message: FormErrorMessages.required, value: true },
pattern: {message: FormErrorMessages.invalidPattern, value: REGEX.URL}
})}
label="GIF File URL"
name="gifFile"
+140 -2
View File
@@ -1,10 +1,14 @@
"use client";
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb";
import InputGroup from "@/components/FormElements/InputGroup";
import { Select } from "@/components/FormElements/select";
import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import Stepper, { Step } from "@/components/ui/Stepper";
import { FormErrorMessages } from "@/constants/Texts";
import { useCreateCms } from "@/hooks/queries/useCmsQueries";
import { BreadcrumbItem } from "@/types/shared";
import { useRef, useState } from "react";
import { useForm } from "react-hook-form";
import BenefitsStep from "./_components/BenefitsStep";
import ChallengesStep from "./_components/ChallengesStep";
import ChartStep from "./_components/ChartStep";
@@ -13,6 +17,13 @@ import FeaturesStep from "./_components/FeaturesStep";
import FooterStep from "./_components/FooterStep";
import HeroStep from "./_components/HeroStep";
interface IPageTypeFields {
page_type: "company" | "organization";
language?: string;
company_name?: string;
country?: string;
}
const Marketing = () => {
const [step, setStep] = useState(0);
const [formData, setFormData] = useState<any>({});
@@ -24,6 +35,20 @@ const Marketing = () => {
const contactsRef = useRef<any>(null);
const footerRef = useRef<any>(null);
const {
register: registerPageType,
watch: watchPageType,
formState: { errors: pageTypeErrors },
getValues: getPageTypeValues,
} = useForm<IPageTypeFields>({
defaultValues: {
page_type: "company",
},
});
const pageType = watchPageType("page_type");
const isCompany = pageType === "company";
const { mutate: createCms, isPending } = useCreateCms();
const breadcrumbItems: BreadcrumbItem[] = [
@@ -120,9 +145,21 @@ const Marketing = () => {
const handleSubmitAll = async () => {
const allData = await collectAllStepsData();
console.log("All collected data:", allData);
const pageTypeData = getPageTypeValues();
const finalData = {
...allData,
page_type: pageTypeData.page_type,
...(pageTypeData.page_type === "company" && {
language: pageTypeData.language,
company_name: pageTypeData.company_name,
country: pageTypeData.country,
}),
};
createCms(allData, {
console.log("All collected data:", finalData);
createCms(finalData, {
onSuccess: () => {
console.log("CMS created successfully");
},
@@ -179,6 +216,107 @@ const Marketing = () => {
<>
<Breadcrumb items={breadcrumbItems} />
<ShowcaseSection title="Create Marketing page">
{/* Page Type Selection */}
<div className="mb-6 rounded-xl bg-gray-1 p-6 dark:bg-gray-7">
<h3 className="mb-4 text-lg font-semibold text-dark dark:text-white">
Page Configuration
</h3>
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2">
<Select
{...registerPageType("page_type", {
required: { message: FormErrorMessages.required, value: true },
})}
name="page_type"
label="Page Type"
required
items={[
{ value: "company", label: "Company" },
{ value: "organization", label: "Organization" },
]}
/>
{pageTypeErrors.page_type && (
<p className="mt-1 text-sm text-red-500">
{pageTypeErrors.page_type.message}
</p>
)}
<InputGroup
{...registerPageType("language", {
required: isCompany
? { message: FormErrorMessages.required, value: true }
: false,
minLength: isCompany
? { value: 2, message: FormErrorMessages.minLength(2) }
: undefined,
maxLength: isCompany
? { value: 10, message: FormErrorMessages.maxLength(10) }
: undefined,
})}
label="Language"
name="language"
type="text"
placeholder="Enter Language (e.g., en, ar)"
disabled={!isCompany}
required={isCompany}
/>
{pageTypeErrors.language && (
<p className="mt-1 text-sm text-red-500">
{pageTypeErrors.language.message}
</p>
)}
<InputGroup
{...registerPageType("company_name", {
required: isCompany
? { message: FormErrorMessages.required, value: true }
: false,
minLength: isCompany
? { value: 2, message: FormErrorMessages.minLength(2) }
: undefined,
maxLength: isCompany
? { value: 200, message: FormErrorMessages.maxLength(200) }
: undefined,
})}
label="Company Name"
name="company_name"
type="text"
placeholder="Enter Company Name"
disabled={!isCompany}
required={isCompany}
/>
{pageTypeErrors.company_name && (
<p className="mt-1 text-sm text-red-500">
{pageTypeErrors.company_name.message}
</p>
)}
<InputGroup
{...registerPageType("country", {
required: isCompany
? { message: FormErrorMessages.required, value: true }
: false,
minLength: isCompany
? { value: 2, message: FormErrorMessages.minLength(2) }
: undefined,
maxLength: isCompany
? { value: 100, message: FormErrorMessages.maxLength(100) }
: undefined,
})}
label="Country"
name="country"
type="text"
placeholder="Enter Country"
disabled={!isCompany}
required={isCompany}
/>
{pageTypeErrors.country && (
<p className="mt-1 text-sm text-red-500">
{pageTypeErrors.country.message}
</p>
)}
</div>
</div>
{/* Render all steps but only show the current one */}
<div style={{ display: step === 0 ? "block" : "none" }}>
<HeroStep ref={heroRef} />