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
This commit is contained in:
AmirReza Jamali
2025-11-09 16:04:52 +03:30
parent 574a3a20ce
commit 4f7b258533
18 changed files with 283 additions and 159 deletions
+2
View File
@@ -0,0 +1,2 @@
{
}
@@ -33,7 +33,7 @@ const BenefitsStep = forwardRef((props, ref) => {
append={append} append={append}
remove={remove} remove={remove}
control={control} control={control}
fieldName="benefits" fieldName="cards"
defaultValues={{ icon: "", title: "", description: "" }} defaultValues={{ icon: "", title: "", description: "" }}
/> />
); );
@@ -33,7 +33,7 @@ const ChallengesStep = forwardRef((props, ref) => {
append={append} append={append}
remove={remove} remove={remove}
control={control} control={control}
fieldName="challenges" fieldName="cards"
defaultValues={{ icon: "", title: "", description: "" }} defaultValues={{ icon: "", title: "", description: "" }}
/> />
); );
@@ -25,8 +25,8 @@ const ChartStep = forwardRef((props, ref) => {
getData: () => getValues(), getData: () => getValues(),
})); }));
const chartTitle = watch("chart_title"); const chartTitle = watch("title");
const chartPoints = watch("chart_points"); const chartData = watch("data");
return ( return (
<form <form
@@ -39,40 +39,43 @@ const ChartStep = forwardRef((props, ref) => {
className="flex flex-col gap-5" className="flex flex-col gap-5"
> >
<InputGroup <InputGroup
{...register("chart_title", { {...register("title", {
required: { message: FormErrorMessages.required, value: true }, required: { message: FormErrorMessages.required, value: true },
})} })}
label="Chart Title" label="Chart Title"
name="chart_title" name="title"
required required
type="text" type="text"
placeholder="Enter Chart Title" placeholder="Enter Chart Title"
/> />
{errors.chart_title && ( {errors.title && (
<p className="mt-1 text-sm text-red-500"> <p className="mt-1 text-sm text-red-500">
{errors.chart_title.message} {errors.title.message}
</p> </p>
)} )}
<InputGroup <InputGroup
{...register("lost_amount", { {...register("missedAmount", {
required: { message: FormErrorMessages.required, value: true }, required: { message: FormErrorMessages.required, value: true },
valueAsNumber: true,
})} })}
label="Lost Amount" label="Missed Amount"
name="lost_amount" name="missedAmount"
required required
type="number" type="text"
placeholder="Enter Lost Amount" placeholder="Enter Missed Amount"
/> />
{errors.lost_amount && ( {errors.missedAmount && (
<p className="mt-1 text-sm text-red-500"> <p className="mt-1 text-sm text-red-500">
{errors.lost_amount.message} {errors.missedAmount.message}
</p> </p>
)} )}
</ShowcaseSection> </ShowcaseSection>
<ShowcaseSection title="Chart Preview"> <ShowcaseSection title="Chart Preview">
<ChartPreview <ChartPreview
series={chartPoints.filter((p) => p.x && p.y)} series={
chartData
?.filter((p) => p.key && p.value)
.map((p) => ({ x: p.key, y: p.value })) || []
}
title={chartTitle} title={chartTitle}
/> />
</ShowcaseSection> </ShowcaseSection>
@@ -80,31 +83,31 @@ const ChartStep = forwardRef((props, ref) => {
{fields.map((field, index) => ( {fields.map((field, index) => (
<div key={field.id} className="flex items-center gap-4"> <div key={field.id} className="flex items-center gap-4">
<InputGroup <InputGroup
{...register(`chart_points.${index}.x`, { {...register(`data.${index}.key`, {
required: { required: {
message: FormErrorMessages.required, message: FormErrorMessages.required,
value: true, value: true,
}, },
})} })}
label="X-axis" label="Key"
name={`chart_points.${index}.x`} name={`data.${index}.key`}
required required
type="text" type="text"
placeholder="Enter X-axis value" placeholder="Enter key"
/> />
<InputGroup <InputGroup
{...register(`chart_points.${index}.y`, { {...register(`data.${index}.value`, {
required: { required: {
message: FormErrorMessages.required, message: FormErrorMessages.required,
value: true, value: true,
}, },
valueAsNumber: true, valueAsNumber: true,
})} })}
label="Y-axis" label="Value"
name={`chart_points.${index}.y`} name={`data.${index}.value`}
required required
type="number" type="number"
placeholder="Enter Y-axis value" placeholder="Enter value"
/> />
<button <button
type="button" type="button"
@@ -118,7 +121,7 @@ const ChartStep = forwardRef((props, ref) => {
<button <button
type="button" type="button"
className="mt-6 flex w-fit items-center justify-center rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90" className="mt-6 flex w-fit items-center justify-center rounded-lg bg-primary p-[13px] font-medium text-white hover:bg-opacity-90"
onClick={() => append({ x: "", y: 0 })} onClick={() => append({ key: "", value: 0 })}
> >
Add point Add point
</button> </button>
@@ -44,11 +44,11 @@ const ContactsStep = forwardRef((props, ref) => {
placeholder="Enter Description" placeholder="Enter Description"
/> />
<InputGroup <InputGroup
{...register("submit_button_title")} {...register("submitButtonText")}
label="Submit Button Title" label="Submit Button Text"
name="submit_button_title" name="submitButtonText"
type="text" type="text"
placeholder="Enter Submit Button Title" placeholder="Enter Submit Button Text"
/> />
</div> </div>
</ShowcaseSection> </ShowcaseSection>
@@ -59,9 +59,9 @@ const ContactsStep = forwardRef((props, ref) => {
className="grid grid-cols-1 items-center gap-4 sm:grid-cols-2" className="grid grid-cols-1 items-center gap-4 sm:grid-cols-2"
> >
<InputGroup <InputGroup
{...register(`fields.${index}.field_name`)} {...register(`fields.${index}.name`)}
label="Field Name" label="Field Name"
name={`fields.${index}.field_name`} name={`fields.${index}.name`}
type="text" type="text"
placeholder="Field Name" placeholder="Field Name"
disabled disabled
@@ -33,7 +33,7 @@ const FeaturesStep = forwardRef((props, ref) => {
append={append} append={append}
remove={remove} remove={remove}
control={control} control={control}
fieldName="features" fieldName="cards"
defaultValues={{ icon: "", title: "", description: "" }} defaultValues={{ icon: "", title: "", description: "" }}
/> />
); );
@@ -41,18 +41,18 @@ const FooterStep = forwardRef((props, ref) => {
</p> </p>
)} )}
<InputGroup <InputGroup
{...register("phoneNumber")} {...register("phone")}
label="Phone Number" label="Phone Number"
name="phoneNumber" name="phone"
type="text" type="text"
placeholder="Enter Phone Number" placeholder="Enter Phone Number"
/> />
<InputGroup <InputGroup
{...register("address")} {...register("location")}
label="Address" label="Location"
name="address" name="location"
type="text" type="text"
placeholder="Enter Address" placeholder="Enter Location"
/> />
<TextAreaGroup <TextAreaGroup
label="Tagline" label="Tagline"
@@ -23,27 +23,6 @@ const HeroStep = forwardRef((props, ref) => {
title="Hero Information" title="Hero Information"
className="flex flex-col gap-5" className="flex flex-col gap-5"
> >
<InputGroup
{...register("key", {
required: { message: FormErrorMessages.required, value: true },
minLength: {
value: 2,
message: FormErrorMessages.minLength(2),
},
maxLength: {
value: 200,
message: FormErrorMessages.maxLength(200),
},
})}
label="Key"
name="key"
required
type="text"
placeholder="Enter Key"
/>
{errors.key && (
<p className="mt-1 text-sm text-red-500">{errors.key.message}</p>
)}
<InputGroup <InputGroup
{...register("title", { {...register("title", {
required: { message: FormErrorMessages.required, value: true }, required: { message: FormErrorMessages.required, value: true },
@@ -86,7 +65,7 @@ const HeroStep = forwardRef((props, ref) => {
</p> </p>
)} )}
<InputGroup <InputGroup
{...register("button_text", { {...register("buttonText", {
required: { message: FormErrorMessages.required, value: true }, required: { message: FormErrorMessages.required, value: true },
minLength: { minLength: {
value: 2, value: 2,
@@ -98,18 +77,18 @@ const HeroStep = forwardRef((props, ref) => {
}, },
})} })}
label="Button Text" label="Button Text"
name="button_text" name="buttonText"
required required
type="text" type="text"
placeholder="Enter Button Text" placeholder="Enter Button Text"
/> />
{errors.button_text && ( {errors.buttonText && (
<p className="mt-1 text-sm text-red-500"> <p className="mt-1 text-sm text-red-500">
{errors.button_text.message} {errors.buttonText.message}
</p> </p>
)} )}
<InputGroup <InputGroup
{...register("button_link", { {...register("buttonLink", {
required: { message: FormErrorMessages.required, value: true }, required: { message: FormErrorMessages.required, value: true },
minLength: { minLength: {
value: 2, value: 2,
@@ -121,14 +100,29 @@ const HeroStep = forwardRef((props, ref) => {
}, },
})} })}
label="Button Link" label="Button Link"
name="button_link" name="buttonLink"
required required
type="url" type="url"
placeholder="Enter Button Link" placeholder="Enter Button Link"
/> />
{errors.button_link && ( {errors.buttonLink && (
<p className="mt-1 text-sm text-red-500"> <p className="mt-1 text-sm text-red-500">
{errors.button_link.message} {errors.buttonLink.message}
</p>
)}
<InputGroup
{...register("gifFile", {
required: { message: FormErrorMessages.required, value: true },
})}
label="GIF File URL"
name="gifFile"
required
type="text"
placeholder="Enter GIF File URL"
/>
{errors.gifFile && (
<p className="mt-1 text-sm text-red-500">
{errors.gifFile.message}
</p> </p>
)} )}
</ShowcaseSection> </ShowcaseSection>
@@ -5,14 +5,14 @@ import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
import { ShowcaseSection } from "@/components/Layouts/showcase-section"; import { ShowcaseSection } from "@/components/Layouts/showcase-section";
import { FormErrorMessages } from "@/constants/Texts"; import { FormErrorMessages } from "@/constants/Texts";
import { import {
Control, Control,
FieldErrors, FieldErrors,
FieldValues, FieldValues,
Path, Path,
UseFieldArrayAppend, UseFieldArrayAppend,
UseFieldArrayRemove, UseFieldArrayRemove,
UseFormHandleSubmit, UseFormHandleSubmit,
UseFormRegister, UseFormRegister,
} from "react-hook-form"; } from "react-hook-form";
interface IProps<T extends FieldValues> { interface IProps<T extends FieldValues> {
@@ -52,24 +52,24 @@ const SectionStep = <T extends FieldValues>({
className="flex flex-col gap-5" className="flex flex-col gap-5"
> >
<InputGroup <InputGroup
{...register("section_title" as Path<T>, { {...register("title" as Path<T>, {
required: { message: FormErrorMessages.required, value: true }, required: { message: FormErrorMessages.required, value: true },
})} })}
label="Section Title" label="Section Title"
name="section_title" name="title"
required required
type="text" type="text"
placeholder="Enter Section Title" placeholder="Enter Section Title"
/> />
{errors.section_title && ( {errors.title && (
<p className="mt-1 text-sm text-red-500"> <p className="mt-1 text-sm text-red-500">
{errors.section_title.message as string} {errors.title.message as string}
</p> </p>
)} )}
<TextAreaGroup <TextAreaGroup
label="Section Description" label="Section Description"
{...register("section_description" as Path<T>)} {...register("description" as Path<T>)}
name="section_description" name="description"
placeholder="Enter Section Description" placeholder="Enter Section Description"
/> />
</ShowcaseSection> </ShowcaseSection>
@@ -80,35 +80,35 @@ const SectionStep = <T extends FieldValues>({
className="grid grid-cols-1 gap-4 sm:grid-cols-2" className="grid grid-cols-1 gap-4 sm:grid-cols-2"
> >
<InputGroup <InputGroup
{...register(`${fieldName}.${index}.icon` as Path<T>, { {...register(`cards.${index}.icon` as Path<T>, {
required: { required: {
message: FormErrorMessages.required, message: FormErrorMessages.required,
value: true, value: true,
}, },
})} })}
label="Icon" label="Icon"
name={`${fieldName}.${index}.icon`} name={`cards.${index}.icon`}
required required
type="text" type="text"
placeholder="Enter Icon URL or name" placeholder="Enter Icon URL or name"
/> />
<InputGroup <InputGroup
{...register(`${fieldName}.${index}.title` as Path<T>, { {...register(`cards.${index}.title` as Path<T>, {
required: { required: {
message: FormErrorMessages.required, message: FormErrorMessages.required,
value: true, value: true,
}, },
})} })}
label="Title" label="Title"
name={`${fieldName}.${index}.title`} name={`cards.${index}.title`}
required required
type="text" type="text"
placeholder="Enter Title" placeholder="Enter Title"
/> />
<TextAreaGroup <TextAreaGroup
{...register(`${fieldName}.${index}.description` as Path<T>)} {...register(`cards.${index}.description` as Path<T>)}
label="Description" label="Description"
name={`${fieldName}.${index}.description`} name={`cards.${index}.description`}
placeholder="Enter Description" placeholder="Enter Description"
className="sm:col-span-2" className="sm:col-span-2"
/> />
@@ -2,9 +2,9 @@
import { useFieldArray, useForm } from "react-hook-form"; import { useFieldArray, useForm } from "react-hook-form";
export interface IBenefitsStepFields { export interface IBenefitsStepFields {
section_title: string; title: string;
section_description: string; description: string;
benefits: { cards: {
icon: string; icon: string;
title: string; title: string;
description: string; description: string;
@@ -21,13 +21,13 @@ const useBenefitsStepPresenter = () => {
getValues, getValues,
} = useForm<IBenefitsStepFields>({ } = useForm<IBenefitsStepFields>({
defaultValues: { defaultValues: {
benefits: [{ icon: "", title: "", description: "" }], cards: [{ icon: "", title: "", description: "" }],
}, },
}); });
const { fields, append, remove } = useFieldArray({ const { fields, append, remove } = useFieldArray({
control, control,
name: "benefits", name: "cards",
}); });
const onSubmit = (data: IBenefitsStepFields) => { const onSubmit = (data: IBenefitsStepFields) => {
@@ -2,9 +2,9 @@
import { useFieldArray, useForm } from "react-hook-form"; import { useFieldArray, useForm } from "react-hook-form";
export interface IChallengesStepFields { export interface IChallengesStepFields {
section_title: string; title: string;
section_description: string; description: string;
challenges: { cards: {
icon: string; icon: string;
title: string; title: string;
description: string; description: string;
@@ -18,16 +18,16 @@ const useChallengesStepPresenter = () => {
control, control,
watch, watch,
formState: { errors }, formState: { errors },
getValues getValues,
} = useForm<IChallengesStepFields>({ } = useForm<IChallengesStepFields>({
defaultValues: { defaultValues: {
challenges: [{ icon: "", title: "", description: "" }], cards: [{ icon: "", title: "", description: "" }],
}, },
}); });
const { fields, append, remove } = useFieldArray({ const { fields, append, remove } = useFieldArray({
control, control,
name: "challenges", name: "cards",
}); });
const onSubmit = (data: IChallengesStepFields) => { const onSubmit = (data: IChallengesStepFields) => {
@@ -49,8 +49,8 @@ const useChallengesStepPresenter = () => {
control, control,
watch, watch,
getValues, getValues,
collectData collectData,
}; };
}; };
export default useChallengesStepPresenter; export default useChallengesStepPresenter;
@@ -2,9 +2,9 @@
import { useFieldArray, useForm } from "react-hook-form"; import { useFieldArray, useForm } from "react-hook-form";
export interface IChartStepFields { export interface IChartStepFields {
chart_title: string; title: string;
lost_amount: number; missedAmount: string;
chart_points: { x: string; y: number }[]; data: { key: string; value: number }[];
} }
const useChartStepPresenter = () => { const useChartStepPresenter = () => {
@@ -14,16 +14,16 @@ const useChartStepPresenter = () => {
control, control,
watch, watch,
formState: { errors }, formState: { errors },
getValues getValues,
} = useForm<IChartStepFields>({ } = useForm<IChartStepFields>({
defaultValues: { defaultValues: {
chart_points: [{ x: "", y: 0 }], data: [{ key: "", value: 0 }],
}, },
}); });
const { fields, append, remove } = useFieldArray({ const { fields, append, remove } = useFieldArray({
control, control,
name: "chart_points", name: "data",
}); });
const onSubmit = (data: IChartStepFields) => { const onSubmit = (data: IChartStepFields) => {
@@ -45,7 +45,7 @@ const useChartStepPresenter = () => {
control, control,
watch, watch,
getValues, getValues,
collectData collectData,
}; };
}; };
@@ -4,9 +4,9 @@ import { useFieldArray, useForm } from "react-hook-form";
export interface IContactsStepFields { export interface IContactsStepFields {
title: string; title: string;
description: string; description: string;
submit_button_title: string; submitButtonText: string;
fields: { fields: {
field_name: string; name: string;
label: string; label: string;
placeholder: string; placeholder: string;
required: boolean; required: boolean;
@@ -19,25 +19,24 @@ const useContactsStepPresenter = () => {
handleSubmit, handleSubmit,
control, control,
getValues, getValues,
formState: { errors }, formState: { errors },
} = useForm<IContactsStepFields>({ } = useForm<IContactsStepFields>({
defaultValues: { defaultValues: {
fields: [ fields: [
{ {
field_name: "first_name", name: "first_name",
label: "", label: "",
placeholder: "", placeholder: "",
required: false, required: false,
}, },
{ {
field_name: "last_name", name: "last_name",
label: "", label: "",
placeholder: "", placeholder: "",
required: false, required: false,
}, },
{ field_name: "email", label: "", placeholder: "", required: false }, { name: "email", label: "", placeholder: "", required: false },
{ field_name: "phone", label: "", placeholder: "", required: false }, { name: "phone", label: "", placeholder: "", required: false },
], ],
}, },
}); });
@@ -2,9 +2,9 @@
import { useFieldArray, useForm } from "react-hook-form"; import { useFieldArray, useForm } from "react-hook-form";
export interface IFeaturesStepFields { export interface IFeaturesStepFields {
section_title: string; title: string;
section_description: string; description: string;
features: { cards: {
icon: string; icon: string;
title: string; title: string;
description: string; description: string;
@@ -18,16 +18,16 @@ const useFeaturesStepPresenter = () => {
control, control,
watch, watch,
formState: { errors }, formState: { errors },
getValues getValues,
} = useForm<IFeaturesStepFields>({ } = useForm<IFeaturesStepFields>({
defaultValues: { defaultValues: {
features: [{ icon: "", title: "", description: "" }], cards: [{ icon: "", title: "", description: "" }],
}, },
}); });
const { fields, append, remove } = useFieldArray({ const { fields, append, remove } = useFieldArray({
control, control,
name: "features", name: "cards",
}); });
const onSubmit = (data: IFeaturesStepFields) => { const onSubmit = (data: IFeaturesStepFields) => {
@@ -49,8 +49,8 @@ const useFeaturesStepPresenter = () => {
control, control,
watch, watch,
getValues, getValues,
collectData collectData,
}; };
}; };
export default useFeaturesStepPresenter; export default useFeaturesStepPresenter;
@@ -2,10 +2,10 @@ import { useForm } from "react-hook-form";
interface FooterFormValues { interface FooterFormValues {
email: string; email: string;
phoneNumber?: string; phone: string;
address?: string; location: string;
tagline?: string; tagline: string;
copyright?: string; copyright: string;
} }
const useFooterStepPresenter = () => { const useFooterStepPresenter = () => {
@@ -13,7 +13,7 @@ const useFooterStepPresenter = () => {
register, register,
handleSubmit, handleSubmit,
formState: { errors }, formState: { errors },
getValues getValues,
} = useForm<FooterFormValues>(); } = useForm<FooterFormValues>();
const onSubmit = (data: FooterFormValues) => { const onSubmit = (data: FooterFormValues) => {
@@ -29,9 +29,9 @@ const useFooterStepPresenter = () => {
handleSubmit, handleSubmit,
onSubmit, onSubmit,
errors, errors,
collectData, collectData,
getValues, getValues,
}; };
}; };
export default useFooterStepPresenter; export default useFooterStepPresenter;
@@ -2,11 +2,11 @@
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
export interface IHeroStepFields { export interface IHeroStepFields {
key: string;
title: string; title: string;
description: string; description: string;
button_text: string; buttonText: string;
button_link: string; buttonLink: string;
gifFile: string;
} }
const useHeroStepPresenter = () => { const useHeroStepPresenter = () => {
@@ -30,9 +30,4 @@ const useHeroStepPresenter = () => {
}; };
}; };
(useHeroStepPresenter as any).collectData = async () => {
const { getValues } = useForm<IHeroStepFields>();
return getValues();
};
export default useHeroStepPresenter; export default useHeroStepPresenter;
+80 -20
View File
@@ -15,6 +15,7 @@ import HeroStep from "./_components/HeroStep";
const Marketing = () => { const Marketing = () => {
const [step, setStep] = useState(0); const [step, setStep] = useState(0);
const [formData, setFormData] = useState<any>({});
const heroRef = useRef<any>(null); const heroRef = useRef<any>(null);
const chartRef = useRef<any>(null); const chartRef = useRef<any>(null);
const featuresRef = useRef<any>(null); const featuresRef = useRef<any>(null);
@@ -40,7 +41,7 @@ const Marketing = () => {
}, },
]; ];
const collectAllStepsData = async () => { const saveCurrentStepData = async () => {
const refs = [ const refs = [
heroRef, heroRef,
chartRef, chartRef,
@@ -51,26 +52,57 @@ const Marketing = () => {
footerRef, footerRef,
]; ];
const allData: any = { const keys = [
hero: {}, "hero",
chart: {}, "chart",
features: {}, "features",
challenges: {}, "challenges",
benefits: {}, "advantages",
contacts: {}, "contact",
footer: {}, "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 = [ const keys = [
"hero", "hero",
"chart", "chart",
"features", "features",
"challenges", "challenges",
"benefits", "advantages",
"contacts", "contact",
"footer", "footer",
]; ];
// Collect any remaining data from refs
for (let i = 0; i < refs.length; i++) { for (let i = 0; i < refs.length; i++) {
const ref = refs[i]; const ref = refs[i];
if (ref?.current?.getData) { if (ref?.current?.getData) {
@@ -104,48 +136,76 @@ const Marketing = () => {
{ {
title: "Hero", title: "Hero",
description: "Create the hero section", description: "Create the hero section",
content: <HeroStep ref={heroRef} />, content: <></>,
}, },
{ {
title: "Chart", title: "Chart",
description: "Create the chart", description: "Create the chart",
content: <ChartStep ref={chartRef} />, content: <></>,
}, },
{ {
title: "Features", title: "Features",
description: "Add features", description: "Add features",
content: <FeaturesStep ref={featuresRef} />, content: <></>,
}, },
{ {
title: "Challenges", title: "Challenges",
description: "Create challenges section", description: "Create challenges section",
content: <ChallengesStep ref={challengesRef} />, content: <></>,
}, },
{ {
title: "Benefits", title: "Benefits",
description: "create benefits section", description: "create benefits section",
content: <BenefitsStep ref={benefitsRef} />, content: <></>,
}, },
{ {
title: "Contacts", title: "Contacts",
description: "Create contacts section", description: "Create contacts section",
content: <ContactsStep ref={contactsRef} />, content: <></>,
}, },
{ {
title: "Footer", title: "Footer",
description: "Add footer information", description: "Add footer information",
content: <FooterStep ref={footerRef} />, content: <></>,
}, },
]; ];
const handleStepChange = async (newStep: number) => {
await saveCurrentStepData();
setStep(newStep);
};
return ( return (
<> <>
<Breadcrumb items={breadcrumbItems} /> <Breadcrumb items={breadcrumbItems} />
<ShowcaseSection title="Create Marketing page"> <ShowcaseSection title="Create Marketing page">
{/* Render all steps but only show the current one */}
<div style={{ display: step === 0 ? "block" : "none" }}>
<HeroStep ref={heroRef} />
</div>
<div style={{ display: step === 1 ? "block" : "none" }}>
<ChartStep ref={chartRef} />
</div>
<div style={{ display: step === 2 ? "block" : "none" }}>
<FeaturesStep ref={featuresRef} />
</div>
<div style={{ display: step === 3 ? "block" : "none" }}>
<ChallengesStep ref={challengesRef} />
</div>
<div style={{ display: step === 4 ? "block" : "none" }}>
<BenefitsStep ref={benefitsRef} />
</div>
<div style={{ display: step === 5 ? "block" : "none" }}>
<ContactsStep ref={contactsRef} />
</div>
<div style={{ display: step === 6 ? "block" : "none" }}>
<FooterStep ref={footerRef} />
</div>
<Stepper <Stepper
steps={steps} steps={steps}
currentStep={step} currentStep={step}
onStepChange={setStep} onStepChange={handleStepChange}
/> />
<div className="mt-6 flex justify-end gap-4"> <div className="mt-6 flex justify-end gap-4">
<button <button
+71
View File
@@ -1,5 +1,75 @@
import { z } from "zod"; import { z } from "zod";
export const CmsCredentials = z.object({ advantages: z.object({
cards: z.array(
z.object({
description: z.string(),
icon: z.string(),
title: z.string(),
}),
),
description: z.string(),
title: z.string(),
}),
challenges: z.object({
cards: z.array(
z.object({
description: z.string(),
icon: z.string(),
title: z.string(),
}),
),
description: z.string(),
title: z.string(),
}),
chart: z.object({
data: z.array(
z.object({
key: z.string(),
value: z.number(),
}),
),
missedAmount: z.string(),
title: z.string(),
}),
contact: z.object({
description: z.string(),
fields: z.array(
z.object({
label: z.string(),
name: z.string(),
placeholder: z.string(),
required: z.boolean(),
}),
),
submitButtonText: z.string(),
title: z.string(),
}),
features: z.object({
cards: z.array(
z.object({
description: z.string(),
icon: z.string(),
title: z.string(),
}),
),
description: z.string(),
title: z.string(),
}),
footer: z.object({
copyright: z.string(),
email: z.string(),
location: z.string(),
phone: z.string(),
tagline: z.string(),
}),
hero: z.object({
buttonLink: z.string(),
buttonText: z.string(),
description: z.string(),
gifFile: z.string(),
title: z.string(),
})})
const CmsSchema = z.object({ const CmsSchema = z.object({
cms: z.array( cms: z.array(
z.object({ z.object({
@@ -82,3 +152,4 @@ const CmsSchema = z.object({
), ),
}); });
export type TCmsResponse = z.infer<typeof CmsSchema>; export type TCmsResponse = z.infer<typeof CmsSchema>;
export type TCmsCredentials = z.infer<typeof CmsCredentials>