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:
@@ -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"
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
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: () => {
|
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} />
|
||||||
|
|||||||
Reference in New Issue
Block a user