From 4f7b258533ec8cfd2af3c9f03da77e3f9e04c90f Mon Sep 17 00:00:00 2001 From: AmirReza Jamali Date: Sun, 9 Nov 2025 16:04:52 +0330 Subject: [PATCH] refactor(marketing): Standardize step components and data structure - Rename field names across step components for consistency - Update chart step to use more generic data structure - Modify input field names to follow consistent naming convention - Refactor chart step to use key-value pairs instead of x-y coordinates - Update form field names in multiple marketing wizard steps - Improve type consistency and naming across marketing wizard components --- .vscode/settings.json | 2 + .../create/_components/BenefitsStep.tsx | 2 +- .../create/_components/ChallengesStep.tsx | 2 +- .../create/_components/ChartStep.tsx | 51 ++++----- .../create/_components/ContactsStep.tsx | 12 +-- .../create/_components/FeaturesStep.tsx | 2 +- .../create/_components/FooterStep.tsx | 12 +-- .../marketing/create/_components/HeroStep.tsx | 52 ++++----- .../create/_components/SectionStep.tsx | 40 +++---- .../_components/useBenefitsStepPresenter.ts | 10 +- .../_components/useChallengesStepPresenter.ts | 16 +-- .../_components/useChartStepPresenter.ts | 14 +-- .../_components/useContactsStepPresenter.ts | 13 ++- .../_components/useFeaturesStepPresenter.ts | 16 +-- .../_components/useFooterStepPresenter.ts | 16 +-- .../_components/useHeroStepPresenter.ts | 11 +- src/app/marketing/create/page.tsx | 100 ++++++++++++++---- src/lib/api/types/TCms.ts | 71 +++++++++++++ 18 files changed, 283 insertions(+), 159 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/src/app/marketing/create/_components/BenefitsStep.tsx b/src/app/marketing/create/_components/BenefitsStep.tsx index 9265bba..1b3e527 100644 --- a/src/app/marketing/create/_components/BenefitsStep.tsx +++ b/src/app/marketing/create/_components/BenefitsStep.tsx @@ -33,7 +33,7 @@ const BenefitsStep = forwardRef((props, ref) => { append={append} remove={remove} control={control} - fieldName="benefits" + fieldName="cards" defaultValues={{ icon: "", title: "", description: "" }} /> ); diff --git a/src/app/marketing/create/_components/ChallengesStep.tsx b/src/app/marketing/create/_components/ChallengesStep.tsx index 4cca940..8bdc53e 100644 --- a/src/app/marketing/create/_components/ChallengesStep.tsx +++ b/src/app/marketing/create/_components/ChallengesStep.tsx @@ -33,7 +33,7 @@ const ChallengesStep = forwardRef((props, ref) => { append={append} remove={remove} control={control} - fieldName="challenges" + fieldName="cards" defaultValues={{ icon: "", title: "", description: "" }} /> ); diff --git a/src/app/marketing/create/_components/ChartStep.tsx b/src/app/marketing/create/_components/ChartStep.tsx index 14d5eb5..f34bddd 100644 --- a/src/app/marketing/create/_components/ChartStep.tsx +++ b/src/app/marketing/create/_components/ChartStep.tsx @@ -25,8 +25,8 @@ const ChartStep = forwardRef((props, ref) => { getData: () => getValues(), })); - const chartTitle = watch("chart_title"); - const chartPoints = watch("chart_points"); + const chartTitle = watch("title"); + const chartData = watch("data"); return (
{ className="flex flex-col gap-5" > - {errors.chart_title && ( + {errors.title && (

- {errors.chart_title.message} + {errors.title.message}

)} - {errors.lost_amount && ( + {errors.missedAmount && (

- {errors.lost_amount.message} + {errors.missedAmount.message}

)} p.x && p.y)} + series={ + chartData + ?.filter((p) => p.key && p.value) + .map((p) => ({ x: p.key, y: p.value })) || [] + } title={chartTitle} /> @@ -80,31 +83,31 @@ const ChartStep = forwardRef((props, ref) => { {fields.map((field, index) => (
diff --git a/src/app/marketing/create/_components/ContactsStep.tsx b/src/app/marketing/create/_components/ContactsStep.tsx index 1ab4257..a5172d1 100644 --- a/src/app/marketing/create/_components/ContactsStep.tsx +++ b/src/app/marketing/create/_components/ContactsStep.tsx @@ -44,11 +44,11 @@ const ContactsStep = forwardRef((props, ref) => { placeholder="Enter Description" />
@@ -59,9 +59,9 @@ const ContactsStep = forwardRef((props, ref) => { className="grid grid-cols-1 items-center gap-4 sm:grid-cols-2" > { append={append} remove={remove} control={control} - fieldName="features" + fieldName="cards" defaultValues={{ icon: "", title: "", description: "" }} /> ); diff --git a/src/app/marketing/create/_components/FooterStep.tsx b/src/app/marketing/create/_components/FooterStep.tsx index 002d50f..1834211 100644 --- a/src/app/marketing/create/_components/FooterStep.tsx +++ b/src/app/marketing/create/_components/FooterStep.tsx @@ -41,18 +41,18 @@ const FooterStep = forwardRef((props, ref) => {

)} { title="Hero Information" className="flex flex-col gap-5" > - - {errors.key && ( -

{errors.key.message}

- )} {

)} { }, })} label="Button Text" - name="button_text" + name="buttonText" required type="text" placeholder="Enter Button Text" /> - {errors.button_text && ( + {errors.buttonText && (

- {errors.button_text.message} + {errors.buttonText.message}

)} { }, })} label="Button Link" - name="button_link" + name="buttonLink" required type="url" placeholder="Enter Button Link" /> - {errors.button_link && ( + {errors.buttonLink && (

- {errors.button_link.message} + {errors.buttonLink.message} +

+ )} + + {errors.gifFile && ( +

+ {errors.gifFile.message}

)} diff --git a/src/app/marketing/create/_components/SectionStep.tsx b/src/app/marketing/create/_components/SectionStep.tsx index c9ec7a3..0f1d610 100644 --- a/src/app/marketing/create/_components/SectionStep.tsx +++ b/src/app/marketing/create/_components/SectionStep.tsx @@ -5,14 +5,14 @@ import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area"; import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import { FormErrorMessages } from "@/constants/Texts"; import { - Control, - FieldErrors, - FieldValues, - Path, - UseFieldArrayAppend, - UseFieldArrayRemove, - UseFormHandleSubmit, - UseFormRegister, + Control, + FieldErrors, + FieldValues, + Path, + UseFieldArrayAppend, + UseFieldArrayRemove, + UseFormHandleSubmit, + UseFormRegister, } from "react-hook-form"; interface IProps { @@ -52,24 +52,24 @@ const SectionStep = ({ className="flex flex-col gap-5" > , { + {...register("title" as Path, { required: { message: FormErrorMessages.required, value: true }, })} label="Section Title" - name="section_title" + name="title" required type="text" placeholder="Enter Section Title" /> - {errors.section_title && ( + {errors.title && (

- {errors.section_title.message as string} + {errors.title.message as string}

)} )} - name="section_description" + {...register("description" as Path)} + name="description" placeholder="Enter Section Description" /> @@ -80,35 +80,35 @@ const SectionStep = ({ className="grid grid-cols-1 gap-4 sm:grid-cols-2" > , { + {...register(`cards.${index}.icon` as Path, { required: { message: FormErrorMessages.required, value: true, }, })} label="Icon" - name={`${fieldName}.${index}.icon`} + name={`cards.${index}.icon`} required type="text" placeholder="Enter Icon URL or name" /> , { + {...register(`cards.${index}.title` as Path, { required: { message: FormErrorMessages.required, value: true, }, })} label="Title" - name={`${fieldName}.${index}.title`} + name={`cards.${index}.title`} required type="text" placeholder="Enter Title" /> )} + {...register(`cards.${index}.description` as Path)} label="Description" - name={`${fieldName}.${index}.description`} + name={`cards.${index}.description`} placeholder="Enter Description" className="sm:col-span-2" /> diff --git a/src/app/marketing/create/_components/useBenefitsStepPresenter.ts b/src/app/marketing/create/_components/useBenefitsStepPresenter.ts index 922c832..ee8d9c1 100644 --- a/src/app/marketing/create/_components/useBenefitsStepPresenter.ts +++ b/src/app/marketing/create/_components/useBenefitsStepPresenter.ts @@ -2,9 +2,9 @@ import { useFieldArray, useForm } from "react-hook-form"; export interface IBenefitsStepFields { - section_title: string; - section_description: string; - benefits: { + title: string; + description: string; + cards: { icon: string; title: string; description: string; @@ -21,13 +21,13 @@ const useBenefitsStepPresenter = () => { getValues, } = useForm({ defaultValues: { - benefits: [{ icon: "", title: "", description: "" }], + cards: [{ icon: "", title: "", description: "" }], }, }); const { fields, append, remove } = useFieldArray({ control, - name: "benefits", + name: "cards", }); const onSubmit = (data: IBenefitsStepFields) => { diff --git a/src/app/marketing/create/_components/useChallengesStepPresenter.ts b/src/app/marketing/create/_components/useChallengesStepPresenter.ts index 91576df..fe23048 100644 --- a/src/app/marketing/create/_components/useChallengesStepPresenter.ts +++ b/src/app/marketing/create/_components/useChallengesStepPresenter.ts @@ -2,9 +2,9 @@ import { useFieldArray, useForm } from "react-hook-form"; export interface IChallengesStepFields { - section_title: string; - section_description: string; - challenges: { + title: string; + description: string; + cards: { icon: string; title: string; description: string; @@ -18,16 +18,16 @@ const useChallengesStepPresenter = () => { control, watch, formState: { errors }, - getValues + getValues, } = useForm({ defaultValues: { - challenges: [{ icon: "", title: "", description: "" }], + cards: [{ icon: "", title: "", description: "" }], }, }); const { fields, append, remove } = useFieldArray({ control, - name: "challenges", + name: "cards", }); const onSubmit = (data: IChallengesStepFields) => { @@ -49,8 +49,8 @@ const useChallengesStepPresenter = () => { control, watch, getValues, - collectData - }; + collectData, + }; }; export default useChallengesStepPresenter; diff --git a/src/app/marketing/create/_components/useChartStepPresenter.ts b/src/app/marketing/create/_components/useChartStepPresenter.ts index c533546..18a2797 100644 --- a/src/app/marketing/create/_components/useChartStepPresenter.ts +++ b/src/app/marketing/create/_components/useChartStepPresenter.ts @@ -2,9 +2,9 @@ import { useFieldArray, useForm } from "react-hook-form"; export interface IChartStepFields { - chart_title: string; - lost_amount: number; - chart_points: { x: string; y: number }[]; + title: string; + missedAmount: string; + data: { key: string; value: number }[]; } const useChartStepPresenter = () => { @@ -14,16 +14,16 @@ const useChartStepPresenter = () => { control, watch, formState: { errors }, - getValues + getValues, } = useForm({ defaultValues: { - chart_points: [{ x: "", y: 0 }], + data: [{ key: "", value: 0 }], }, }); const { fields, append, remove } = useFieldArray({ control, - name: "chart_points", + name: "data", }); const onSubmit = (data: IChartStepFields) => { @@ -45,7 +45,7 @@ const useChartStepPresenter = () => { control, watch, getValues, - collectData + collectData, }; }; diff --git a/src/app/marketing/create/_components/useContactsStepPresenter.ts b/src/app/marketing/create/_components/useContactsStepPresenter.ts index 297b3cd..0101dce 100644 --- a/src/app/marketing/create/_components/useContactsStepPresenter.ts +++ b/src/app/marketing/create/_components/useContactsStepPresenter.ts @@ -4,9 +4,9 @@ import { useFieldArray, useForm } from "react-hook-form"; export interface IContactsStepFields { title: string; description: string; - submit_button_title: string; + submitButtonText: string; fields: { - field_name: string; + name: string; label: string; placeholder: string; required: boolean; @@ -19,25 +19,24 @@ const useContactsStepPresenter = () => { handleSubmit, control, getValues, - formState: { errors }, } = useForm({ defaultValues: { fields: [ { - field_name: "first_name", + name: "first_name", label: "", placeholder: "", required: false, }, { - field_name: "last_name", + name: "last_name", label: "", placeholder: "", required: false, }, - { field_name: "email", label: "", placeholder: "", required: false }, - { field_name: "phone", label: "", placeholder: "", required: false }, + { name: "email", label: "", placeholder: "", required: false }, + { name: "phone", label: "", placeholder: "", required: false }, ], }, }); diff --git a/src/app/marketing/create/_components/useFeaturesStepPresenter.ts b/src/app/marketing/create/_components/useFeaturesStepPresenter.ts index 1dcca68..dfc581c 100644 --- a/src/app/marketing/create/_components/useFeaturesStepPresenter.ts +++ b/src/app/marketing/create/_components/useFeaturesStepPresenter.ts @@ -2,9 +2,9 @@ import { useFieldArray, useForm } from "react-hook-form"; export interface IFeaturesStepFields { - section_title: string; - section_description: string; - features: { + title: string; + description: string; + cards: { icon: string; title: string; description: string; @@ -18,16 +18,16 @@ const useFeaturesStepPresenter = () => { control, watch, formState: { errors }, - getValues + getValues, } = useForm({ defaultValues: { - features: [{ icon: "", title: "", description: "" }], + cards: [{ icon: "", title: "", description: "" }], }, }); const { fields, append, remove } = useFieldArray({ control, - name: "features", + name: "cards", }); const onSubmit = (data: IFeaturesStepFields) => { @@ -49,8 +49,8 @@ const useFeaturesStepPresenter = () => { control, watch, getValues, - collectData - }; + collectData, + }; }; export default useFeaturesStepPresenter; diff --git a/src/app/marketing/create/_components/useFooterStepPresenter.ts b/src/app/marketing/create/_components/useFooterStepPresenter.ts index 30a9459..fde1b0d 100644 --- a/src/app/marketing/create/_components/useFooterStepPresenter.ts +++ b/src/app/marketing/create/_components/useFooterStepPresenter.ts @@ -2,10 +2,10 @@ import { useForm } from "react-hook-form"; interface FooterFormValues { email: string; - phoneNumber?: string; - address?: string; - tagline?: string; - copyright?: string; + phone: string; + location: string; + tagline: string; + copyright: string; } const useFooterStepPresenter = () => { @@ -13,7 +13,7 @@ const useFooterStepPresenter = () => { register, handleSubmit, formState: { errors }, - getValues + getValues, } = useForm(); const onSubmit = (data: FooterFormValues) => { @@ -29,9 +29,9 @@ const useFooterStepPresenter = () => { handleSubmit, onSubmit, errors, - collectData, - getValues, - }; + collectData, + getValues, + }; }; export default useFooterStepPresenter; \ No newline at end of file diff --git a/src/app/marketing/create/_components/useHeroStepPresenter.ts b/src/app/marketing/create/_components/useHeroStepPresenter.ts index 5221b49..5e7d74f 100644 --- a/src/app/marketing/create/_components/useHeroStepPresenter.ts +++ b/src/app/marketing/create/_components/useHeroStepPresenter.ts @@ -2,11 +2,11 @@ import { useForm } from "react-hook-form"; export interface IHeroStepFields { - key: string; title: string; description: string; - button_text: string; - button_link: string; + buttonText: string; + buttonLink: string; + gifFile: string; } const useHeroStepPresenter = () => { @@ -30,9 +30,4 @@ const useHeroStepPresenter = () => { }; }; -(useHeroStepPresenter as any).collectData = async () => { - const { getValues } = useForm(); - return getValues(); -}; - export default useHeroStepPresenter; diff --git a/src/app/marketing/create/page.tsx b/src/app/marketing/create/page.tsx index 42c6507..ce4fb8f 100644 --- a/src/app/marketing/create/page.tsx +++ b/src/app/marketing/create/page.tsx @@ -15,6 +15,7 @@ import HeroStep from "./_components/HeroStep"; const Marketing = () => { const [step, setStep] = useState(0); + const [formData, setFormData] = useState({}); const heroRef = useRef(null); const chartRef = useRef(null); const featuresRef = useRef(null); @@ -40,7 +41,7 @@ const Marketing = () => { }, ]; - const collectAllStepsData = async () => { + const saveCurrentStepData = async () => { const refs = [ heroRef, chartRef, @@ -51,26 +52,57 @@ const Marketing = () => { footerRef, ]; - const allData: any = { - hero: {}, - chart: {}, - features: {}, - challenges: {}, - benefits: {}, - contacts: {}, - footer: {}, - }; + const keys = [ + "hero", + "chart", + "features", + "challenges", + "advantages", + "contact", + "footer", + ]; + + const currentRef = refs[step]; + if (currentRef?.current?.getData) { + try { + const data = await currentRef.current.getData(); + setFormData((prev: any) => ({ + ...prev, + [keys[step]]: data, + })); + } catch (error) { + console.error(`Error collecting data from step ${step}:`, error); + } + } + }; + + const collectAllStepsData = async () => { + // First save current step data + await saveCurrentStepData(); + + const refs = [ + heroRef, + chartRef, + featuresRef, + challengesRef, + benefitsRef, + contactsRef, + footerRef, + ]; + + const allData: any = { ...formData }; const keys = [ "hero", "chart", "features", "challenges", - "benefits", - "contacts", + "advantages", + "contact", "footer", ]; + // Collect any remaining data from refs for (let i = 0; i < refs.length; i++) { const ref = refs[i]; if (ref?.current?.getData) { @@ -104,48 +136,76 @@ const Marketing = () => { { title: "Hero", description: "Create the hero section", - content: , + content: <>, }, { title: "Chart", description: "Create the chart", - content: , + content: <>, }, { title: "Features", description: "Add features", - content: , + content: <>, }, { title: "Challenges", description: "Create challenges section", - content: , + content: <>, }, { title: "Benefits", description: "create benefits section", - content: , + content: <>, }, { title: "Contacts", description: "Create contacts section", - content: , + content: <>, }, { title: "Footer", description: "Add footer information", - content: , + content: <>, }, ]; + const handleStepChange = async (newStep: number) => { + await saveCurrentStepData(); + setStep(newStep); + }; + return ( <> + {/* Render all steps but only show the current one */} +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+