diff --git a/apps/website/app/[locale]/contact/page.tsx b/apps/website/app/[locale]/contact/page.tsx new file mode 100644 index 0000000..a562935 --- /dev/null +++ b/apps/website/app/[locale]/contact/page.tsx @@ -0,0 +1,308 @@ +"use client"; + +import { useState } from "react"; +import { useTranslations } from "next-intl"; +import { Container } from "@/components/Container"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { trackGAEvent } from "@/components/analitycs"; +import AnimatedGridPattern from "@/components/ui/animated-grid-pattern"; +import { cn } from "@/lib/utils"; + +interface ContactFormData { + inquiryType: "" | "support" | "sales" | "other"; + name: string; + email: string; + company: string; + message: string; +} + +export default function ContactPage() { + const t = useTranslations("Contact"); + const [isSubmitting, setIsSubmitting] = useState(false); + const [isSubmitted, setIsSubmitted] = useState(false); + const [formData, setFormData] = useState({ + inquiryType: "", + name: "", + email: "", + company: "", + message: "", + }); + const [errors, setErrors] = useState>({}); + + const validateForm = (): boolean => { + const newErrors: Record = {}; + + if (!formData.inquiryType) { + newErrors.inquiryType = t("errors.inquiryTypeRequired"); + } + if (!formData.name.trim()) { + newErrors.name = t("errors.nameRequired"); + } + if (!formData.email.trim()) { + newErrors.email = t("errors.emailRequired"); + } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { + newErrors.email = t("errors.emailInvalid"); + } + if (!formData.company.trim()) { + newErrors.company = t("errors.companyRequired"); + } + if (!formData.message.trim()) { + newErrors.message = t("errors.messageRequired"); + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!validateForm()) { + return; + } + + setIsSubmitting(true); + + try { + const response = await fetch("/api/contact", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(formData), + }); + + if (response.ok) { + // Track successful form submission + trackGAEvent({ + action: "Contact Form Submitted", + category: "Contact", + label: formData.inquiryType, + }); + + // Reset form and show success + setFormData({ + inquiryType: "", + name: "", + email: "", + company: "", + message: "", + }); + setErrors({}); + setIsSubmitted(true); + } else { + throw new Error("Failed to submit form"); + } + } catch (error) { + console.error("Error submitting form:", error); + alert(t("errorMessage")); + } finally { + setIsSubmitting(false); + } + }; + + const handleInputChange = (field: keyof ContactFormData, value: any) => { + setFormData((prev) => ({ ...prev, [field]: value })); + // Clear error when user starts typing + if (errors[field]) { + setErrors((prev) => { + const newErrors = { ...prev }; + delete newErrors[field]; + return newErrors; + }); + } + }; + + if (isSubmitted) { + return ( +
+ +
+

+ {t("successTitle")} +

+

+ {t("successMessage")} +

+
+ +
+
+
+
+ ); + } + + return ( +
+ + +
+
+

+ {t("title")} +

+

+ {t("description")} +

+
+ +
+
+ + + {errors.inquiryType && ( +

{errors.inquiryType}

+ )} +
+ +
+
+ + handleInputChange("name", e.target.value)} + placeholder={t("fields.name.placeholder")} + /> + {errors.name && ( +

{errors.name}

+ )} +
+ +
+ + handleInputChange("email", e.target.value)} + placeholder={t("fields.email.placeholder")} + /> + {errors.email && ( +

{errors.email}

+ )} +
+
+ +
+ + handleInputChange("company", e.target.value)} + placeholder={t("fields.company.placeholder")} + /> + {errors.company && ( +

{errors.company}

+ )} +
+ +
+ +