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 (
)}
{
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 */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+