diff --git a/app/contact/page.tsx b/app/contact/page.tsx new file mode 100644 index 0000000..d2f8f6d --- /dev/null +++ b/app/contact/page.tsx @@ -0,0 +1,6 @@ +import { Contact } from "@/components/pages/contact"; +import React from "react"; + +export default function Page() { + return ; +} diff --git a/app/page.tsx b/app/page.tsx index b5fc280..71136c5 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,7 @@ import { AboutUs, Banner, + Blog, Line, OurService, Statistics, @@ -10,14 +11,15 @@ import { export default function Home() { return ( -
+
); } diff --git a/components/pages/contact/contactHeader.tsx b/components/pages/contact/contactHeader.tsx new file mode 100644 index 0000000..f7aa0d3 --- /dev/null +++ b/components/pages/contact/contactHeader.tsx @@ -0,0 +1,24 @@ +import DotAnimatsiya from "@/components/dot/DotAnimatsiya"; +import React from "react"; + +export default function ContactHeader() { + return ( +
+
+ + + CONTACT US + +
+

+ GET IN TOUCH +

+

+ We'd love to hear from you. Please fill out this form. +

+
+ ); +} diff --git a/components/pages/contact/index.ts b/components/pages/contact/index.ts new file mode 100644 index 0000000..666c50a --- /dev/null +++ b/components/pages/contact/index.ts @@ -0,0 +1 @@ +export { Contact } from "./main"; diff --git a/components/pages/contact/main.tsx b/components/pages/contact/main.tsx new file mode 100644 index 0000000..bccc311 --- /dev/null +++ b/components/pages/contact/main.tsx @@ -0,0 +1,319 @@ +"use client"; + +import React from "react"; + +import { useState } from "react"; +import Image from "next/image"; +import { Mail, MapPin, Phone, Check } from "lucide-react"; +import ContactHeader from "./contactHeader"; + +interface FormData { + firstName: string; + lastName: string; + email: string; + subject: string; + message: string; + agreeToPolicy: boolean; +} + +interface FormErrors { + firstName?: string; + lastName?: string; + email?: string; + subject?: string; + message?: string; + agreeToPolicy?: string; +} + +export function Contact() { + const [formData, setFormData] = useState({ + firstName: "", + lastName: "", + email: "", + subject: "", + message: "", + agreeToPolicy: false, + }); + const [errors, setErrors] = useState({}); + const [isSubmitting, setIsSubmitting] = useState(false); + const [submitStatus, setSubmitStatus] = useState< + "idle" | "success" | "error" + >("idle"); + + const validateForm = (): boolean => { + const newErrors: FormErrors = {}; + + if (!formData.firstName.trim()) { + newErrors.firstName = "First name is required"; + } + if (!formData.lastName.trim()) { + newErrors.lastName = "Last name is required"; + } + if (!formData.email.trim()) { + newErrors.email = "Email is required"; + } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { + newErrors.email = "Please enter a valid email"; + } + if (!formData.subject.trim()) { + newErrors.subject = "Subject is required"; + } + if (!formData.message.trim()) { + newErrors.message = "Message is required"; + } + if (!formData.agreeToPolicy) { + newErrors.agreeToPolicy = "You must agree to the privacy policy"; + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleChange = ( + e: React.ChangeEvent, + ) => { + const { name, value } = e.target; + setFormData((prev) => ({ ...prev, [name]: value })); + if (errors[name as keyof FormErrors]) { + setErrors((prev) => ({ ...prev, [name]: undefined })); + } + }; + + const handleCheckboxChange = () => { + setFormData((prev) => ({ ...prev, agreeToPolicy: !prev.agreeToPolicy })); + if (errors.agreeToPolicy) { + setErrors((prev) => ({ ...prev, agreeToPolicy: undefined })); + } + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!validateForm()) return; + + setIsSubmitting(true); + setSubmitStatus("idle"); + + try { + const response = await fetch("/api/contact", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(formData), + }); + + if (response.ok) { + setSubmitStatus("success"); + setFormData({ + firstName: "", + lastName: "", + email: "", + subject: "", + message: "", + agreeToPolicy: false, + }); + } else { + setSubmitStatus("error"); + } + } catch { + setSubmitStatus("error"); + } finally { + setIsSubmitting(false); + } + }; + + const contactInfo = [ + { + icon: Mail, + title: "EMAIL", + detail: "support@fireforce", + }, + { + icon: MapPin, + title: "OUR LOCATION", + detail: "Jl. Dr. Ir. Soekarno No. 99x Tabanan - Bali", + }, + { + icon: Phone, + title: "PHONE", + detail: "+123-456-7890", + }, + ]; + + return ( +
+ {/* Background Image */} +
+ Contact background + {/* Radial Gradient Overlay */} +
+
+ + {/* Content */} +
+ + + {/* Form */} +
+ {/* First Row - Names */} +
+
+ + {errors.firstName && ( +

{errors.firstName}

+ )} +
+
+ + {errors.lastName && ( +

{errors.lastName}

+ )} +
+
+ + {/* Second Row - Email & Subject */} +
+
+ + {errors.email && ( +

{errors.email}

+ )} +
+
+ + {errors.subject && ( +

{errors.subject}

+ )} +
+
+ + {/* Message Textarea */} +
+