import React, { useState, useEffect } from "react"; import { useParams, Link, useNavigate } from "react-router-dom"; import axios from "axios"; import { ArrowLeft, Clock, Calendar, Check, Phone, Mail, User, } from "lucide-react"; import { Button } from "../components/ui/button"; import { Badge } from "../components/ui/badge"; import { Input } from "../components/ui/input"; import { Textarea } from "../components/ui/textarea"; import { Label } from "../components/ui/label"; import { Separator } from "../components/ui/separator"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "../components/ui/dialog"; import { toast } from "sonner"; const API = `${process.env.REACT_APP_BACKEND_URL}/api`; const ServiceDetail = () => { const { id } = useParams(); const navigate = useNavigate(); const [service, setService] = useState(null); const [loading, setLoading] = useState(true); const [bookingOpen, setBookingOpen] = useState(false); const [submitting, setSubmitting] = useState(false); const [formData, setFormData] = useState({ name: "", email: "", phone: "", preferred_date: "", notes: "", }); const fetchService = async (silent = false) => { try { const response = await axios.get(`${API}/services/${id}`); setService(response.data); } catch (error) { console.error("Failed to fetch service:", error); } finally { if (!silent) setLoading(false); } }; useEffect(() => { fetchService(); }, [id]); // Auto-refresh every 5 seconds for real-time updates useEffect(() => { const interval = setInterval(() => { fetchService(true); }, 5000); return () => clearInterval(interval); }, [id]); // Refresh when user returns to the tab useEffect(() => { const handleVisibilityChange = () => { if (!document.hidden) { fetchService(); } }; document.addEventListener("visibilitychange", handleVisibilityChange); return () => document.removeEventListener("visibilitychange", handleVisibilityChange); }, [id]); const handleSubmit = async (e) => { e.preventDefault(); setSubmitting(true); try { await axios.post(`${API}/services/book`, { service_id: service.id, ...formData, }); toast.success( "Booking submitted successfully! We will contact you soon.", ); setBookingOpen(false); setFormData({ name: "", email: "", phone: "", preferred_date: "", notes: "", }); } catch (error) { toast.error("Failed to submit booking. Please try again."); } finally { setSubmitting(false); } }; if (loading) { return (
); } if (!service) { return (

Service not found

); } return (
{/* Breadcrumb */} Back to Services {/* Hero Image */}
{service.name} {service.category}
{/* Content */}

{service.name}

{/* What's Included */}

What's Included

    {[ "Free diagnostic assessment", "Quality replacement parts (if needed)", "Professional service by certified technicians", "30-day warranty on all repairs", "Post-service support", ].map((item, idx) => (
  • {item}
  • ))}
{/* Process */}

How It Works

{[ { step: "1", title: "Book", desc: "Schedule your appointment online", }, { step: "2", title: "Drop Off", desc: "Bring your device to our store", }, { step: "3", title: "Pick Up", desc: "Get your device back fixed", }, ].map((item, idx) => (
{item.step}

{item.title}

{item.desc}

))}
{/* Sidebar */}
{service.price > 0 ? "Starting from" : "Price"}

{service.price > 0 ? `$${service.price.toFixed(2)}` : "Contact for quote"}

Duration: {service.duration}
Book {service.name}
setFormData({ ...formData, name: e.target.value }) } required data-testid="booking-name" />
setFormData({ ...formData, email: e.target.value }) } required data-testid="booking-email" />
setFormData({ ...formData, phone: e.target.value }) } required data-testid="booking-phone" />
setFormData({ ...formData, preferred_date: e.target.value, }) } required data-testid="booking-date" />