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 InputGroup from "@/components/FormElements/InputGroup";
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area"; import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import { REGEX } from "@/constants/regex";
import { FormErrorMessages } from "@/constants/Texts"; import { FormErrorMessages } from "@/constants/Texts";
import { forwardRef, useImperativeHandle } from "react"; import { forwardRef, useImperativeHandle } from "react";
import useHeroStepPresenter from "./useHeroStepPresenter"; import useHeroStepPresenter from "./useHeroStepPresenter";
@@ -113,6 +114,7 @@ const HeroStep = forwardRef((props, ref) => {
<InputGroup <InputGroup
{...register("gifFile", { {...register("gifFile", {
required: { message: FormErrorMessages.required, value: true }, required: { message: FormErrorMessages.required, value: true },
pattern: {message: FormErrorMessages.invalidPattern, value: REGEX.URL}
})} })}
label="GIF File URL" label="GIF File URL"
name="gifFile" name="gifFile"
+140 -2
View File
@@ -1,10 +1,14 @@
"use client"; "use client";
import Breadcrumb from "@/components/Breadcrumbs/Breadcrumb"; 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 { ShowcaseSection } from "@/components/Layouts/showcase-section";
import Stepper, { Step } from "@/components/ui/Stepper"; import Stepper, { Step } from "@/components/ui/Stepper";
import { FormErrorMessages } from "@/constants/Texts";
import { useCreateCms } from "@/hooks/queries/useCmsQueries"; import { useCreateCms } from "@/hooks/queries/useCmsQueries";
import { BreadcrumbItem } from "@/types/shared"; import { BreadcrumbItem } from "@/types/shared";
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import { useForm } from "react-hook-form";
import BenefitsStep from "./_components/BenefitsStep"; import BenefitsStep from "./_components/BenefitsStep";
import ChallengesStep from "./_components/ChallengesStep"; import ChallengesStep from "./_components/ChallengesStep";
import ChartStep from "./_components/ChartStep"; import ChartStep from "./_components/ChartStep";
@@ -13,6 +17,13 @@ import FeaturesStep from "./_components/FeaturesStep";
import FooterStep from "./_components/FooterStep"; import FooterStep from "./_components/FooterStep";
import HeroStep from "./_components/HeroStep"; import HeroStep from "./_components/HeroStep";
interface IPageTypeFields {
page_type: "company" | "organization";
language?: string;
company_name?: string;
country?: string;
}
const Marketing = () => { const Marketing = () => {
const [step, setStep] = useState(0); const [step, setStep] = useState(0);
const [formData, setFormData] = useState<any>({}); const [formData, setFormData] = useState<any>({});
@@ -24,6 +35,20 @@ const Marketing = () => {
const contactsRef = useRef<any>(null); const contactsRef = useRef<any>(null);
const footerRef = 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 { mutate: createCms, isPending } = useCreateCms();
const breadcrumbItems: BreadcrumbItem[] = [ const breadcrumbItems: BreadcrumbItem[] = [
@@ -120,9 +145,21 @@ const Marketing = () => {
const handleSubmitAll = async () => { const handleSubmitAll = async () => {
const allData = await collectAllStepsData(); const allData = await collectAllStepsData();
console.log("All collected data:", allData); const pageTypeData = getPageTypeValues();
createCms(allData, { const finalData = {
...allData,
page_type: pageTypeData.page_type,
...(pageTypeData.page_type === "company" && {
language: pageTypeData.language,
company_name: pageTypeData.company_name,
country: pageTypeData.country,
}),
};
console.log("All collected data:", finalData);
createCms(finalData, {
onSuccess: () => { onSuccess: () => {
console.log("CMS created successfully"); console.log("CMS created successfully");
}, },
@@ -179,6 +216,107 @@ const Marketing = () => {
<> <>
<Breadcrumb items={breadcrumbItems} /> <Breadcrumb items={breadcrumbItems} />
<ShowcaseSection title="Create Marketing page"> <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 */} {/* Render all steps but only show the current one */}
<div style={{ display: step === 0 ? "block" : "none" }}> <div style={{ display: step === 0 ? "block" : "none" }}>
<HeroStep ref={heroRef} /> <HeroStep ref={heroRef} />