diff --git a/src/components/call-desk/appointment-form.tsx b/src/components/call-desk/appointment-form.tsx new file mode 100644 index 0000000..9f77daf --- /dev/null +++ b/src/components/call-desk/appointment-form.tsx @@ -0,0 +1,335 @@ +import { useState } from 'react'; +import { CalendarPlus02 } from '@untitledui/icons'; +import { SlideoutMenu } from '@/components/application/slideout-menus/slideout-menu'; +import { Input } from '@/components/base/input/input'; +import { Select } from '@/components/base/select/select'; +import { TextArea } from '@/components/base/textarea/textarea'; +import { Checkbox } from '@/components/base/checkbox/checkbox'; +import { Button } from '@/components/base/buttons/button'; + +type AppointmentFormProps = { + isOpen: boolean; + onOpenChange: (open: boolean) => void; + callerNumber?: string | null; + leadName?: string | null; + leadId?: string | null; + onSaved?: () => void; +}; + +const clinicItems = [ + { id: 'koramangala', label: 'Global Hospital - Koramangala' }, + { id: 'whitefield', label: 'Global Hospital - Whitefield' }, + { id: 'indiranagar', label: 'Global Hospital - Indiranagar' }, +]; + +const departmentItems = [ + { id: 'cardiology', label: 'Cardiology' }, + { id: 'gynecology', label: 'Gynecology' }, + { id: 'orthopedics', label: 'Orthopedics' }, + { id: 'general-medicine', label: 'General Medicine' }, + { id: 'ent', label: 'ENT' }, + { id: 'dermatology', label: 'Dermatology' }, + { id: 'pediatrics', label: 'Pediatrics' }, + { id: 'oncology', label: 'Oncology' }, +]; + +const doctorItems = [ + { id: 'dr-sharma', label: 'Dr. Sharma' }, + { id: 'dr-patel', label: 'Dr. Patel' }, + { id: 'dr-kumar', label: 'Dr. Kumar' }, + { id: 'dr-reddy', label: 'Dr. Reddy' }, + { id: 'dr-singh', label: 'Dr. Singh' }, +]; + +const genderItems = [ + { id: 'male', label: 'Male' }, + { id: 'female', label: 'Female' }, + { id: 'other', label: 'Other' }, +]; + +const timeSlotItems = [ + { id: '09:00', label: '9:00 AM' }, + { id: '09:30', label: '9:30 AM' }, + { id: '10:00', label: '10:00 AM' }, + { id: '10:30', label: '10:30 AM' }, + { id: '11:00', label: '11:00 AM' }, + { id: '11:30', label: '11:30 AM' }, + { id: '14:00', label: '2:00 PM' }, + { id: '14:30', label: '2:30 PM' }, + { id: '15:00', label: '3:00 PM' }, + { id: '15:30', label: '3:30 PM' }, + { id: '16:00', label: '4:00 PM' }, +]; + +export const AppointmentForm = ({ + isOpen, + onOpenChange, + callerNumber, + leadName, + leadId, + onSaved, +}: AppointmentFormProps) => { + const [patientName, setPatientName] = useState(leadName ?? ''); + const [patientPhone, setPatientPhone] = useState(callerNumber ?? ''); + const [age, setAge] = useState(''); + const [gender, setGender] = useState(null); + const [clinic, setClinic] = useState(null); + const [department, setDepartment] = useState(null); + const [doctor, setDoctor] = useState(null); + const [date, setDate] = useState(''); + const [timeSlot, setTimeSlot] = useState(null); + const [chiefComplaint, setChiefComplaint] = useState(''); + const [isReturning, setIsReturning] = useState(false); + const [source, setSource] = useState('Inbound Call'); + const [agentNotes, setAgentNotes] = useState(''); + + const [isSaving, setIsSaving] = useState(false); + const [error, setError] = useState(null); + + const handleSave = async () => { + if (!date || !timeSlot || !doctor || !department) { + setError('Please fill in the required fields: date, time, doctor, and department.'); + return; + } + + setIsSaving(true); + setError(null); + + try { + const { apiClient } = await import('@/lib/api-client'); + + // Combine date + time slot into ISO datetime + const scheduledAt = new Date(`${date}T${timeSlot}:00`).toISOString(); + + const doctorLabel = doctorItems.find((d) => d.id === doctor)?.label ?? doctor; + const departmentLabel = departmentItems.find((d) => d.id === department)?.label ?? department; + + // Create appointment on platform + await apiClient.graphql( + `mutation CreateAppointment($data: AppointmentCreateInput!) { + createAppointment(data: $data) { id } + }`, + { + data: { + scheduledAt, + durationMinutes: 30, + appointmentType: 'CONSULTATION', + appointmentStatus: 'SCHEDULED', + doctorName: doctorLabel, + department: departmentLabel, + reasonForVisit: chiefComplaint || null, + ...(leadId ? { patientId: leadId } : {}), + }, + }, + ); + + // Update lead status if we have a matched lead + if (leadId) { + await apiClient + .graphql( + `mutation UpdateLead($id: ID!, $data: LeadUpdateInput!) { + updateLead(id: $id, data: $data) { id } + }`, + { + id: leadId, + data: { + leadStatus: 'APPOINTMENT_SET', + lastContactedAt: new Date().toISOString(), + }, + }, + ) + .catch((err: unknown) => console.warn('Failed to update lead:', err)); + } + + onSaved?.(); + } catch (err) { + console.error('Failed to create appointment:', err); + setError(err instanceof Error ? err.message : 'Failed to create appointment. Please try again.'); + } finally { + setIsSaving(false); + } + }; + + return ( + + {({ close }) => ( + <> + +
+
+ +
+
+

Book Appointment

+

Schedule a new patient visit

+
+
+
+ + +
+ {/* Patient Info */} +
+ + Patient Information + +
+ + + +
+ + +
+ + + + {/* Divider */} +
+ + {/* Appointment Details */} +
+ + Appointment Details + +
+ + + + + + + +
+ + +
+ +