From d51a795191f89e26b20b319914b21caaa84e3502 Mon Sep 17 00:00:00 2001 From: iamkiddy Date: Mon, 1 Dec 2025 18:26:33 +0000 Subject: [PATCH] Refactor ContactSection and submitContactForm to streamline form submission process. Simplify input handling by using a single object for contact data and enhance error messaging for better user feedback. Update appointment detail rendering in Booking component for improved UI consistency. --- app/(admin)/admin/booking/[id]/page.tsx | 16 +++--- components/ContactSection.tsx | 28 +++------- lib/actions/auth.ts | 70 ++++--------------------- lib/schema/auth.ts | 10 ++++ 4 files changed, 36 insertions(+), 88 deletions(-) diff --git a/app/(admin)/admin/booking/[id]/page.tsx b/app/(admin)/admin/booking/[id]/page.tsx index fe60ede..e781e5b 100644 --- a/app/(admin)/admin/booking/[id]/page.tsx +++ b/app/(admin)/admin/booking/[id]/page.tsx @@ -389,13 +389,13 @@ export default function AppointmentDetailPage() { className={`p-4 rounded-xl border ${isDark ? "bg-gray-700/50 border-gray-600" : "bg-gray-50 border-gray-200"}`} >
-
+

{match.day_name || "Unknown Day"}

{formatShortDate(match.date || match.date_obj || "")} -

+

{match.available_slots && Array.isArray(match.available_slots) && match.available_slots.length > 0 && ( @@ -408,19 +408,19 @@ export default function AppointmentDetailPage() { }; const normalizedSlot = String(slot).toLowerCase().trim(); return ( - + > {timeSlotLabels[normalizedSlot] || slot} - + ); })} -
- )} + + )} ))} - + )} diff --git a/components/ContactSection.tsx b/components/ContactSection.tsx index 77381d3..0e08023 100644 --- a/components/ContactSection.tsx +++ b/components/ContactSection.tsx @@ -2,7 +2,7 @@ import { motion, useInView } from "framer-motion"; import { useRef, useState } from "react"; -import { Send, Loader2 } from "lucide-react"; +import { Send } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; @@ -29,20 +29,15 @@ export function ContactSection() { setIsSubmitting(true); try { - await submitContactForm({ - name: formData.name, - email: formData.email, - phone: formData.phone, - message: formData.message, - }); - + await submitContactForm(formData); toast.success("Message Sent Successfully", { description: "Thank you for reaching out. We'll get back to you soon!", }); setFormData({ name: "", email: "", phone: "", message: "" }); } catch (error) { - toast.error("Failed to Send Message", { - description: error instanceof Error ? error.message : "Please try again later.", + const errorMessage = error instanceof Error ? error.message : "Failed to send message. Please try again."; + toast.error("Error Sending Message", { + description: errorMessage, }); } finally { setIsSubmitting(false); @@ -227,17 +222,8 @@ export function ContactSection() { className="w-full cursor-pointer bg-gradient-to-r from-rose-500 to-pink-600 text-white transition-all hover:from-rose-600 hover:to-pink-700 hover:scale-[1.02] disabled:opacity-50 disabled:cursor-not-allowed" size="lg" > - {isSubmitting ? ( - <> - - Sending... - - ) : ( - <> - - Send Message - - )} + + {isSubmitting ? "Sending..." : "Send Message"} diff --git a/lib/actions/auth.ts b/lib/actions/auth.ts index 06c2d54..f1de991 100644 --- a/lib/actions/auth.ts +++ b/lib/actions/auth.ts @@ -9,6 +9,7 @@ import type { ResetPasswordInput, TokenRefreshInput, UpdateProfileInput, + ContactInput, } from "@/lib/schema/auth"; import type { AuthResponse, ApiError, AuthTokens, User } from "@/lib/models/auth"; @@ -439,67 +440,18 @@ export async function updateProfile(input: UpdateProfileInput): Promise { throw new Error("Invalid profile response format"); } -export interface ContactFormInput { - name: string; - email: string; - phone: string; - message: string; -} - -export interface ContactFormResponse { - message?: string; - success?: boolean; -} - /** - * Submit contact form (public endpoint - no authentication required) + * Submit contact form */ -export async function submitContactForm( - data: ContactFormInput -): Promise { - try { - const response = await fetch(API_ENDPOINTS.auth.contact, { - method: "POST", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - }, - body: JSON.stringify({ - name: data.name.trim(), - email: data.email.trim().toLowerCase(), - phone: data.phone.trim(), - message: data.message.trim(), - }), - }); +export async function submitContactForm(input: ContactInput): Promise<{ message: string }> { + const response = await fetch(API_ENDPOINTS.auth.contact, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(input), + }); - // Handle empty responses - const contentType = response.headers.get("content-type"); - let responseData: any; - - if (contentType && contentType.includes("application/json")) { - const text = await response.text(); - responseData = text ? JSON.parse(text) : {}; - } else { - const text = await response.text(); - responseData = text ? { message: text } : {}; - } - - if (!response.ok) { - // Check for authentication error specifically - if (response.status === 401 || response.status === 403) { - throw new Error("Contact form submission requires authentication. Please contact support if this is a public form."); - } - - const error: ApiError = responseData; - throw new Error(extractErrorMessage(error)); - } - - return responseData; - } catch (error) { - if (error instanceof Error) { - throw error; - } - throw new Error("Failed to submit contact form. Please try again later."); - } + return handleResponse<{ message: string }>(response); } diff --git a/lib/schema/auth.ts b/lib/schema/auth.ts index f77813f..b7b7f44 100644 --- a/lib/schema/auth.ts +++ b/lib/schema/auth.ts @@ -87,3 +87,13 @@ export const updateProfileSchema = z.object({ export type UpdateProfileInput = z.infer; +// Contact Form Schema +export const contactSchema = z.object({ + name: z.string().min(1, "Name is required"), + email: z.string().email("Invalid email address"), + phone: z.string().min(1, "Phone number is required"), + message: z.string().min(1, "Message is required"), +}); + +export type ContactInput = z.infer; + -- 2.39.5