Update src/components/sections/contact/ContactSplit.tsx

This commit is contained in:
2026-03-03 04:48:20 +00:00
parent d7328e33c6
commit fde80376be

View File

@@ -1,171 +1,123 @@
"use client";
import React, { useState } from "react";
import { cn } from "@/lib/utils";
import ContactForm from "@/components/form/ContactForm";
import MediaContent from "@/components/shared/MediaContent";
import HeroBackgrounds, { type HeroBackgroundVariantProps } from "@/components/background/HeroBackgrounds";
import { cls } from "@/lib/utils";
import { useButtonAnimation } from "@/components/hooks/useButtonAnimation";
import { LucideIcon } from "lucide-react";
import { sendContactEmail } from "@/utils/sendContactEmail";
import type { ButtonAnimationType } from "@/types/button";
type ContactSplitBackgroundProps = Extract<
HeroBackgroundVariantProps,
| { variant: "plain" }
| { variant: "animated-grid" }
| { variant: "canvas-reveal" }
| { variant: "cell-wave" }
| { variant: "downward-rays-animated" }
| { variant: "downward-rays-animated-grid" }
| { variant: "downward-rays-static" }
| { variant: "downward-rays-static-grid" }
| { variant: "gradient-bars" }
| { variant: "radial-gradient" }
| { variant: "rotated-rays-animated" }
| { variant: "rotated-rays-animated-grid" }
| { variant: "rotated-rays-static" }
| { variant: "rotated-rays-static-grid" }
| { variant: "sparkles-gradient" }
>;
interface ContactSplitProps {
title: string;
description: string;
tag: string;
tagIcon?: LucideIcon;
tagAnimation?: ButtonAnimationType;
background: ContactSplitBackgroundProps;
useInvertedBackground: boolean;
imageSrc?: string;
videoSrc?: string;
imageAlt?: string;
videoAriaLabel?: string;
mediaPosition?: "left" | "right";
mediaAnimation: ButtonAnimationType;
inputPlaceholder?: string;
buttonText?: string;
termsText?: string;
onSubmit?: (email: string) => void;
ariaLabel?: string;
className?: string;
containerClassName?: string;
contentClassName?: string;
contactFormClassName?: string;
tagClassName?: string;
titleClassName?: string;
descriptionClassName?: string;
formWrapperClassName?: string;
formClassName?: string;
inputClassName?: string;
buttonClassName?: string;
buttonTextClassName?: string;
termsClassName?: string;
mediaWrapperClassName?: string;
mediaClassName?: string;
export interface ContactSplitProps {
tag?: string;
title: string;
description: string;
background?: { variant: string };
useInvertedBackground?: boolean;
imageSrc?: string;
videoSrc?: string;
imageAlt?: string;
videoAriaLabel?: string;
mediaAnimation?: "none" | "opacity" | "slide-up" | "blur-reveal";
mediaPosition?: "left" | "right";
inputPlaceholder?: string;
buttonText?: string;
termsText?: string;
onSubmit?: (email: string) => void;
className?: string;
containerClassName?: string;
contentClassName?: string;
contactFormClassName?: string;
tagClassName?: string;
titleClassName?: string;
descriptionClassName?: string;
formWrapperClassName?: string;
formClassName?: string;
inputClassName?: string;
buttonClassName?: string;
buttonTextClassName?: string;
termsClassName?: string;
mediaWrapperClassName?: string;
mediaClassName?: string;
}
const ContactSplit = ({
title,
description,
tag,
tagIcon,
tagAnimation,
background,
useInvertedBackground,
imageSrc,
videoSrc,
imageAlt = "",
videoAriaLabel = "Contact section video",
mediaPosition = "right",
mediaAnimation,
inputPlaceholder = "Enter your email",
buttonText = "Sign Up",
termsText = "By clicking Sign Up you're confirming that you agree with our Terms and Conditions.",
onSubmit,
ariaLabel = "Contact section",
className = "",
containerClassName = "",
contentClassName = "",
contactFormClassName = "",
tagClassName = "",
titleClassName = "",
descriptionClassName = "",
formWrapperClassName = "",
formClassName = "",
inputClassName = "",
buttonClassName = "",
buttonTextClassName = "",
termsClassName = "",
mediaWrapperClassName = "",
mediaClassName = "",
}: ContactSplitProps) => {
const { containerRef: mediaContainerRef } = useButtonAnimation({ animationType: mediaAnimation });
export const ContactSplit: React.FC<ContactSplitProps> = ({
tag,
title,
description,
imageSrc,
videoSrc,
imageAlt = "", mediaPosition = "right", inputPlaceholder = "Enter your email", buttonText = "Sign Up", termsText,
useInvertedBackground = false,
className,
containerClassName,
contentClassName,
tagClassName,
titleClassName,
descriptionClassName,
formWrapperClassName,
formClassName,
inputClassName,
buttonClassName,
buttonTextClassName,
termsClassName,
mediaWrapperClassName,
mediaClassName
}) => {
const [email, setEmail] = useState("");
const handleSubmit = async (email: string) => {
try {
await sendContactEmail({ email });
console.log("Email send successfully");
} catch (error) {
console.error("Failed to send email:", error);
}
};
const handleFormSubmit = (e: React.FormEvent) => {
e.preventDefault();
setEmail("");
};
const contactContent = (
<div className="relative card rounded-theme-capped p-6 py-15 md:py-6 flex items-center justify-center">
<ContactForm
tag={tag}
tagIcon={tagIcon}
tagAnimation={tagAnimation}
title={title}
description={description}
useInvertedBackground={useInvertedBackground}
inputPlaceholder={inputPlaceholder}
buttonText={buttonText}
termsText={termsText}
onSubmit={handleSubmit}
centered={true}
className={cls("w-full", contactFormClassName)}
tagClassName={tagClassName}
titleClassName={titleClassName}
descriptionClassName={descriptionClassName}
formWrapperClassName={cls("w-full md:w-8/10 2xl:w-7/10", formWrapperClassName)}
formClassName={formClassName}
inputClassName={inputClassName}
buttonClassName={buttonClassName}
buttonTextClassName={buttonTextClassName}
termsClassName={termsClassName}
/>
<div className="absolute inset w-full h-full z-0 rounded-theme-capped overflow-hidden" >
<HeroBackgrounds {...background} />
return (
<div
className={cn(
"w-full py-20 px-4", useInvertedBackground && "bg-accent/10", containerClassName
)}
>
<div className={cn("max-w-6xl mx-auto", contentClassName)}>
<div className={cn("grid grid-cols-1 md:grid-cols-2 gap-12 items-center", className)}>
{mediaPosition === "left" && imageSrc && (
<div className={cn("order-first", mediaWrapperClassName)}>
<img src={imageSrc} alt={imageAlt} className={cn("w-full rounded-lg", mediaClassName)} />
</div>
</div>
);
)}
const mediaContent = (
<div ref={mediaContainerRef} className={cls("overflow-hidden rounded-theme-capped card h-130", mediaWrapperClassName)}>
<MediaContent
imageSrc={imageSrc}
videoSrc={videoSrc}
imageAlt={imageAlt}
videoAriaLabel={videoAriaLabel}
imageClassName={cls("relative z-1 w-full h-full object-cover", mediaClassName)}
/>
</div>
);
<div className={cn("space-y-6", contactFormClassName)}>
{tag && <p className={cn("text-sm font-semibold text-accent", tagClassName)}>{tag}</p>}
<h2 className={cn("text-4xl font-bold", titleClassName)}>{title}</h2>
<p className={cn("text-lg text-muted-foreground", descriptionClassName)}>{description}</p>
return (
<section aria-label={ariaLabel} className={cls("relative py-20 w-full", useInvertedBackground && "bg-foreground", className)}>
<div className={cls("w-content-width mx-auto relative z-10", containerClassName)}>
<div className={cls("grid grid-cols-1 md:grid-cols-2 gap-6 md:auto-rows-fr", contentClassName)}>
{mediaPosition === "left" && mediaContent}
{contactContent}
{mediaPosition === "right" && mediaContent}
</div>
<form onSubmit={handleFormSubmit} className={cn("space-y-4", formWrapperClassName)}>
<div className={cn("space-y-2", formClassName)}>
<input
type="email"
placeholder={inputPlaceholder}
value={email}
onChange={(e) => setEmail(e.target.value)}
className={cn(
"w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-primary", inputClassName
)}
required
/>
<button
type="submit"
className={cn(
"w-full px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors", buttonClassName
)}
>
<span className={buttonTextClassName}>{buttonText}</span>
</button>
</div>
</form>
{termsText && <p className={cn("text-xs text-muted-foreground", termsClassName)}>{termsText}</p>}
</div>
{mediaPosition === "right" && imageSrc && (
<div className={cn("order-last", mediaWrapperClassName)}>
<img src={imageSrc} alt={imageAlt} className={cn("w-full rounded-lg", mediaClassName)} />
</div>
</section>
);
)}
</div>
</div>
</div>
);
};
ContactSplit.displayName = "ContactSplit";
export default ContactSplit;