import { useState, useEffect, useCallback } from 'react'; import { getAppointmentsApi, deleteAppointmentApi } from '@/api/appointment'; import { exportToExcel } from '@/utils/exportToExcel'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'; import { Loader2, Trash, RefreshCw, Download, ChevronLeft, ChevronRight, Eye, CalendarDays } from 'lucide-react'; export default function AppointmentPage() { const [appointments, setAppointments] = useState([]); const [loading, setLoading] = useState(true); const [searchText, setSearchText] = useState(''); const [filterDoctor, setFilterDoctor] = useState(''); const [dateMode, setDateMode] = useState<'scheduled' | 'booked'>('scheduled'); const [filterDate, setFilterDate] = useState(''); const [startDate, setStartDate] = useState(''); const [endDate, setEndDate] = useState(''); const [createdDate, setCreatedDate] = useState(''); const [createdStartDate, setCreatedStartDate] = useState(''); const [createdEndDate, setCreatedEndDate] = useState(''); const [viewOpen, setViewOpen] = useState(false); const [viewData, setViewData] = useState(null); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [totalItems, setTotalItems] = useState(0); const [itemsPerPage, setItemsPerPage] = useState(10); const fetchAll = useCallback(async () => { setLoading(true); try { const res = await getAppointmentsApi( currentPage, itemsPerPage, filterDate, startDate, endDate, createdDate, createdStartDate, createdEndDate, searchText ); setAppointments(res?.data || []); setTotalPages(res?.pagination?.totalPages || 1); setTotalItems(res?.pagination?.total || 0); } catch (err) { console.error(err); } finally { setLoading(false); } }, [ currentPage, itemsPerPage, filterDate, startDate, endDate, createdDate, createdStartDate, createdEndDate, searchText, ]); useEffect(() => { fetchAll(); }, [fetchAll]); const filteredAppointments = appointments.filter((item) => { const matchesDoctor = filterDoctor ? item.doctor?.name?.toLowerCase().includes(filterDoctor.toLowerCase()) : true; return matchesDoctor; }); const handleModeChange = (newMode: 'scheduled' | 'booked') => { setDateMode(newMode); setFilterDate(''); setStartDate(''); setEndDate(''); setCreatedDate(''); setCreatedStartDate(''); setCreatedEndDate(''); setCurrentPage(1); }; useEffect(() => { setCurrentPage(1); }, [searchText, filterDoctor, filterDate, startDate, endDate, createdDate, createdStartDate, createdEndDate]); const indexOfFirstItem = (currentPage - 1) * itemsPerPage; function openView(item: any) { setViewData(item); setViewOpen(true); } async function handleDelete(id: number) { if (!confirm('Delete appointment?')) return; await deleteAppointmentApi(id); fetchAll(); } const handleExport = () => { const exportData = filteredAppointments.map((item) => ({ ID: item.id, Name: item.name, Phone: item.mobileNumber, Email: item.email, Doctor: item.doctor?.name, Department: item.department?.name, ScheduledDate: new Date(item.date).toLocaleDateString(), BookedDate: new Date(item.createdAt).toLocaleDateString(), Message: item.message, })); exportToExcel(exportData, 'appointments'); }; return (

Appointments

setSearchText(e.target.value)} className="text-base h-10" />
Specific Day dateMode === 'scheduled' ? setFilterDate(e.target.value) : setCreatedDate(e.target.value) } className="text-sm h-8 bg-background" disabled={dateMode === 'scheduled' ? !!startDate || !!endDate : !!createdStartDate || !!createdEndDate} />
From Range dateMode === 'scheduled' ? setStartDate(e.target.value) : setCreatedStartDate(e.target.value) } className="text-sm h-8 bg-background" disabled={dateMode === 'scheduled' ? !!filterDate : !!createdDate} />
To Range dateMode === 'scheduled' ? setEndDate(e.target.value) : setCreatedEndDate(e.target.value) } className="text-sm h-8 bg-background" disabled={dateMode === 'scheduled' ? !!filterDate : !!createdDate} />
Appointment Registrations
ID Patient Doctor Scheduled Date Booked Date Message Actions {loading ? ( ) : filteredAppointments.length === 0 ? ( No appointments found matching your selected criteria. ) : ( filteredAppointments.map((item) => ( {item.id}
{item.name}
{item.mobileNumber}
{item.doctor?.name || '-'}
{item.department?.name}
{new Date(item.date).toLocaleDateString()}
{new Date(item.createdAt).toLocaleDateString()}
{item.message || '-'}
)) )}
{!loading && totalItems > 0 && (
Showing {indexOfFirstItem + 1} to{' '} {Math.min(currentPage * itemsPerPage, totalItems)} of{' '} {totalItems} entries
Page {currentPage} of {totalPages}
)}
Appointment Details {viewData && (

Patient Information

{viewData.name}

{viewData.mobileNumber}

{viewData.email || 'No email provided'}

Key Datestamps

Scheduled: {new Date(viewData.date).toLocaleDateString()}

Record Created: {new Date(viewData.createdAt).toLocaleString()}

Doctor / Department

{viewData.doctor?.name || 'Not Assigned'}

{viewData.department?.name || 'General'}

Message from Patient

{viewData.message || 'No message provided.'}

)}
); }