"use client"; import React, { useState, useEffect, Suspense } from "react"; import { useQuery } from "@apollo/client"; import ReCAPTCHA from "react-google-recaptcha"; import Heading from "../components/reuseableUI/heading"; import Breadcrumb from "../components/reuseableUI/breadcrumb"; import PrimaryButton from "../components/reuseableUI/primaryButton"; import Toast from "../components/reuseableUI/Toast"; import { SpinnerIcon } from "../utils/svgs/spinnerIcon"; import { ErrorTag } from "../components/reuseableUI/errorTag"; import { useRecaptcha } from "@/hooks/useRecaptcha"; import { useAppConfiguration } from "../components/providers/ServerAppConfigurationProvider"; import { GET_CONTACT_PAGE, type ContactPageData, } from "@/graphql/queries/getContactPage"; import EditorRenderer from "../components/richText/EditorRenderer"; function ContactUsInner() { const [formData, setFormData] = useState>({}); const [fieldErrors, setFieldErrors] = useState>({}); const [apiError, setApiError] = useState(null); const [showSuccessToast, setShowSuccessToast] = useState(false); const [loading, setLoading] = useState(false); const [recaptchaValue, setRecaptchaValue] = useState(null); const { recaptchaRef, resetRecaptcha } = useRecaptcha(); const config = useAppConfiguration(); const { data, loading: queryLoading, error, } = useQuery(GET_CONTACT_PAGE, { variables: { first: 1 }, }); const contactPageData: ContactPageData | null = React.useMemo(() => { if (!data?.pages?.edges?.length) return null; const node = data.pages.edges[0].node; const metadata = node.metadata.reduce( (acc: Record, item: { key: string; value: string }) => { acc[item.key] = item.value; return acc; }, {} ); return { id: node.id, title: node.title, content: node.content, contactFormEnabled: metadata.contact_form === "true", productInquiryFormEnabled: metadata.product_inquiry_form === "true", recaptchaEnabled: metadata.reCAPTCHA === "true", fields: metadata.fields ? metadata.fields.split(",").map((f: string) => f.trim()) : [], description: metadata.description || null, emailTo: metadata.email_to || null, emailCc: metadata.email_cc || null, emailBcc: metadata.email_bcc || null, emailSubject: metadata.email_subject || null, successMessage: metadata.success_message || null, }; }, [data]); useEffect(() => { if (contactPageData?.fields) { const initialFormData: Record = {}; contactPageData.fields.forEach((field) => { const fieldKey = field.toLowerCase().replace(/[^a-z0-9]/g, ""); initialFormData[fieldKey] = ""; }); setFormData(initialFormData); } }, [contactPageData]); const handleChange = ( e: React.ChangeEvent ) => { if (e.target.type === "number" && e.target.value.length <= 17) { setFormData({ ...formData, [e.target.name]: e.target.value, }); } else if (e.target.type !== "number") { setFormData({ ...formData, [e.target.name]: e.target.value, }); } // Clear field error when user starts typing if (fieldErrors[e.target.name]) { setFieldErrors({ ...fieldErrors, [e.target.name]: "", }); } }; const getFieldKey = (field: string): string => { return field.toLowerCase().replace(/[^a-z0-9]/g, ""); }; const getFieldPlaceholder = (field: string): string => { const placeholders: Record = { name: "Enter Your Full Name", email: "Enter Your Email", phone: "Enter Your Phone Number", subject: "Enter Subject", message: "Type your message here...", }; const key = getFieldKey(field); return placeholders[key] || `Enter ${field}`; }; const validateEmail = (email: string): boolean => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setApiError(null); setShowSuccessToast(false); setFieldErrors({}); const errors: Record = {}; let hasError = false; // Validate all fields if ( contactPageData?.fields .find((f) => f.toLowerCase() === "address line 2") ?.toLowerCase() !== "address line 2" ) { contactPageData?.fields.forEach((field) => { const fieldKey = getFieldKey(field); const value = formData[fieldKey]; if (!value || !value.trim()) { errors[fieldKey] = `${field} is required.`; hasError = true; } else if (fieldKey === "email" && !validateEmail(value)) { errors[fieldKey] = "Please enter a valid email address."; hasError = true; } }); } // Validate reCAPTCHA if enabled if (contactPageData?.recaptchaEnabled && !recaptchaValue) { errors.recaptcha = "Please complete the reCAPTCHA verification."; hasError = true; } if (hasError) { setFieldErrors(errors); return; } setLoading(true); try { // Prepare email message const emailMessage: Record = {}; contactPageData?.fields.forEach((field) => { const fieldKey = getFieldKey(field); emailMessage[fieldKey] = formData[fieldKey]; }); // Prepare email recipients const recipients: string[] = []; if (contactPageData?.emailTo) { recipients.push( ...contactPageData.emailTo.split(",").map((e) => e.trim()) ); } const ccRecipients: string[] = []; if (contactPageData?.emailCc) { ccRecipients.push( ...contactPageData.emailCc.split(",").map((e) => e.trim()) ); } const bccRecipients: string[] = []; if (contactPageData?.emailBcc) { bccRecipients.push( ...contactPageData.emailBcc.split(",").map((e) => e.trim()) ); } const response = await fetch("/api/form-submission", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ formType: "contact", pageSlug: "contact", data: emailMessage, metadata: { to: recipients, cc: ccRecipients.length > 0 ? ccRecipients : undefined, bcc: bccRecipients.length > 0 ? bccRecipients : undefined, subject: contactPageData?.emailSubject || "Contact Form Submission", }, timestamp: new Date().toISOString(), }), }); if (!response.ok) { throw new Error("Failed to submit form"); } // Show success toast setShowSuccessToast(true); // Reset form const resetFormData: Record = {}; contactPageData?.fields.forEach((field) => { const fieldKey = getFieldKey(field); resetFormData[fieldKey] = ""; }); setFormData(resetFormData); // Reset reCAPTCHA if (contactPageData?.recaptchaEnabled) { setRecaptchaValue(null); resetRecaptcha(); } // Scroll to top to see the toast window.scrollTo({ top: 0, behavior: "smooth" }); } catch (err) { console.error("Contact form submission error:", err); setApiError("Failed to send your message. Please try again later."); // Reset reCAPTCHA on error if (contactPageData?.recaptchaEnabled) { setRecaptchaValue(null); resetRecaptcha(); } } finally { setLoading(false); } }; if (queryLoading) { return (
{SpinnerIcon}
); } if (error || !contactPageData) { return (

Unable to load contact page. Please try again later.

); } // Function to check if description contains unrendered template variables const hasTemplateVariables = (html: string | null): boolean => { if (!html) return false; // Check for common template syntax patterns return /\{\{[^}]+\}\}|\$\{[^}]+\}|\{%[^%]+%\}/.test(html); }; // Clean description of template variables for display const cleanDescription = (html: string | null): string | null => { if (!html) return null; if (!hasTemplateVariables(html)) return html; // Remove lines containing template variables const tempDiv = document.createElement("div"); tempDiv.innerHTML = html; // Remove elements containing template syntax const walker = document.createTreeWalker(tempDiv, NodeFilter.SHOW_TEXT); const nodesToRemove: Node[] = []; let node: Node | null = walker.nextNode(); while (node !== null) { if (node.textContent && hasTemplateVariables(node.textContent)) { let parent = node.parentElement; while (parent && parent !== tempDiv) { if (parent.tagName === "LI") { nodesToRemove.push(parent); break; } parent = parent.parentElement; } if (!nodesToRemove.find((n) => n === node?.parentElement)) { nodesToRemove.push(node.parentElement || node); } } node = walker.nextNode(); } nodesToRemove.forEach((n) => n.parentElement?.removeChild(n)); return tempDiv.innerHTML || null; }; const displayDescription = cleanDescription(contactPageData.description); return (
{/* Success Toast */} {showSuccessToast && ( <>
]*>/g, "") : "Thank you for contacting us. We will get back to you soon." } type="success" duration={5000} onClose={() => setShowSuccessToast(false)} />
)}
{/* The route-level server component renders the single H1 for SEO. */}
{displayDescription && ( <>
)} {contactPageData.contactFormEnabled && (
{contactPageData.fields.map((field) => { const fieldKey = getFieldKey(field); const isMessageField = fieldKey === "message"; if (isMessageField) return null; return (
{fieldErrors[fieldKey] && (
{fieldErrors[fieldKey]}
)}
); })}
{contactPageData.fields.some( (field) => getFieldKey(field) === "message" ) && (