"use client"; import { useState, useEffect, FormEvent } from "react"; // Types for appointment data from CMS interface AppointmentHero { title: string; backgroundImage: string; subtitle: string; heading: string; description: string; } interface AppointmentForm { heading: string; fields: Array<{ name: string; label: string; type: string; placeholder: string; required: boolean; colClass: string; }>; submitButton: { text: string; icon: string; buttonClass: string; }; } interface AppointmentData { hero: AppointmentHero; visaOptions: string[]; form: AppointmentForm; } export default function AppointmentPage() { const [appointmentData, setAppointmentData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [formData, setFormData] = useState({ name: "", email: "", phone: "", address: "", appointmentDate: "", message: "", visaTypes: [] as string[], }); const [isSubmitting, setIsSubmitting] = useState(false); const [submitStatus, setSubmitStatus] = useState<{ type: "success" | "error" | null; message: string; }>({ type: null, message: "" }); // Calendar state const [currentDate, setCurrentDate] = useState(new Date()); const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001"; // Calendar helper functions const months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; const getDaysInMonth = (year: number, month: number) => { return new Date(year, month + 1, 0).getDate(); }; const getFirstDayOfMonth = (year: number, month: number) => { const day = new Date(year, month, 1).getDay(); // Convert Sunday (0) to 7 for Monday-first calendar return day === 0 ? 7 : day; }; const generateCalendarDays = () => { const year = currentDate.getFullYear(); const month = currentDate.getMonth(); const daysInMonth = getDaysInMonth(year, month); const firstDay = getFirstDayOfMonth(year, month); const today = new Date(); const days: React.ReactNode[] = []; // Empty cells for days before the first day of the month for (let i = 1; i < firstDay; i++) { days.push(
); } // Days of the month for (let day = 1; day <= daysInMonth; day++) { const isToday = day === today.getDate() && month === today.getMonth() && year === today.getFullYear(); days.push(
handleDateClick(year, month, day)} style={{ cursor: "pointer" }} > {day}
); } return days; }; const handleDateClick = (year: number, month: number, day: number) => { const selectedDate = new Date(year, month, day); const formattedDate = selectedDate.toISOString().split("T")[0]; setFormData((prev) => ({ ...prev, appointmentDate: formattedDate })); }; const handlePrevMonth = () => { setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1)); }; const handleNextMonth = () => { setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1)); }; // Fetch appointment data from CMS useEffect(() => { const fetchAppointmentData = async () => { try { const response = await fetch(`${apiUrl}/api/appointment`); const result = await response.json(); if (result.success && result.data) { setAppointmentData(result.data); } } catch (error) { console.error("Error fetching appointment data:", error); } finally { setIsLoading(false); } }; fetchAppointmentData(); }, [apiUrl]); const handleChange = ( e: React.ChangeEvent ) => { const { name, value } = e.target; setFormData((prev) => ({ ...prev, [name]: value })); }; const handleCheckboxChange = (visaType: string, checked: boolean) => { setFormData((prev) => ({ ...prev, visaTypes: checked ? [...prev.visaTypes, visaType] : prev.visaTypes.filter((v) => v !== visaType), })); }; const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setIsSubmitting(true); setSubmitStatus({ type: null, message: "" }); try { const response = await fetch(`${apiUrl}/api/appointment/submit`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(formData), }); const data = await response.json(); if (response.ok && data.success) { setSubmitStatus({ type: "success", message: data.message || "Thank you! Your appointment has been submitted.", }); // Reset form setFormData({ name: "", email: "", phone: "", address: "", appointmentDate: "", message: "", visaTypes: [], }); } else { setSubmitStatus({ type: "error", message: data.error || "Something went wrong. Please try again.", }); } } catch (error) { console.error("Submit error:", error); setSubmitStatus({ type: "error", message: "Network error. Please check your connection and try again.", }); } finally { setIsSubmitting(false); } }; // Get data with fallbacks const hero = appointmentData?.hero || { title: "Make Appointment", backgroundImage: "/assets/img/inner-page/breadcrumb.jpg", subtitle: "About Our Consultancy", heading: "Want to meet us for your need?", description: "24/7 customer support is always ready to answer all your questions", }; const visaOptions = appointmentData?.visaOptions || [ "Canada Immigration", "Tourist Visa", "Medical Visa", "Coaching", "Student Visa", "Spouse Visa", "Job Opportunity", "Exam", ]; const formSettings = appointmentData?.form || { heading: "Request Appointment", submitButton: { text: "Request Appointment", icon: "fa-solid fa-arrow-right", buttonClass: "theme-btn", }, }; // Get background image URL const backgroundImage = hero.backgroundImage?.startsWith("http") ? hero.backgroundImage : hero.backgroundImage?.startsWith("/") ? hero.backgroundImage : `/assets/img/inner-page/breadcrumb.jpg`; if (isLoading) { return (
Loading...
); } return ( <> {/* Breadcrumb-Wrapper Section Start */}
img

{hero.title}

{/* Appointment Section Start */}
{hero.subtitle && ( {hero.subtitle} )} {hero.heading && (

{hero.heading}

)}
Have any questions?
{hero.description &&

{hero.description}

}

{months[currentDate.getMonth()]} {currentDate.getFullYear()}

Mon
Tue
Wed
Thu
Fri
Sat
Sun
{generateCalendarDays()}
{/* Contact Section Start */}
{/* Status Message */} {submitStatus.type && (
{submitStatus.message}
)}
Your Name *
Your Email *
Your Phone
Your Address
Appointment Date
{visaOptions.length > 0 && (
{visaOptions.slice(0, Math.ceil(visaOptions.length / 2)).map((visa, index) => (
handleCheckboxChange(visa, e.target.checked) } />
))}
{visaOptions.slice(Math.ceil(visaOptions.length / 2)).map((visa, index) => (
handleCheckboxChange(visa, e.target.checked) } />
))}
)}
); }