import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { format, parse } from "date-fns"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; import { X, Calendar as CalendarIcon } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { Calendar } from "@/components/ui/calendar"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas"; import { z } from "zod"; import { useQuery } from "@tanstack/react-query"; import { apiRequest } from "@/lib/queryClient"; const PatientSchema = ( PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ appointments: true, }); type Patient = z.infer; interface ServiceLine { procedureCode: string; toothNumber: string; surface: string; quad: string; authNo: string; billedAmount: string; } interface ClaimFormProps { patientId?: number; extractedData?: Partial; onSubmit: (claimData: any) => void; onClose: () => void; } export function ClaimForm({ patientId, extractedData, onSubmit, onClose, }: ClaimFormProps) { const { toast } = useToast(); // Query patient if patientId provided const { data: fetchedPatient, isLoading, error } = useQuery({ queryKey: ["/api/patients/", patientId], queryFn: async () => { const res = await apiRequest("GET", `/api/patients/${patientId}`); if (!res.ok) throw new Error("Failed to fetch patient"); return res.json(); }, enabled: !!patientId, }); // Patient state - initialize from extractedData or null (new patient) const [patient, setPatient] = useState( extractedData ? ({ ...extractedData } as Patient) : null ); // Sync fetched patient when available useEffect(() => { if (fetchedPatient) { setPatient(fetchedPatient); } }, [fetchedPatient]); // Service date state const [serviceDateValue, setServiceDateValue] = useState(new Date()); const [serviceDate, setServiceDate] = useState(format(new Date(), "MM/dd/yy")); // Clinical notes state const [clinicalNotes, setClinicalNotes] = useState(""); // Doctor selection state const [doctor, setDoctor] = useState("doctor1"); // Service lines state with one empty default line const [serviceLines, setServiceLines] = useState([ { procedureCode: "", toothNumber: "", surface: "", quad: "", authNo: "", billedAmount: "", }, ]); // Update a field in serviceLines at index const updateServiceLine = ( index: number, field: keyof ServiceLine, value: string ) => { setServiceLines((prev) => { const updated = [...prev]; if (updated[index]) { updated[index][field] = value; } return updated; }); }; // Handle patient field changes (to make inputs controlled and editable) const updatePatientField = (field: keyof Patient, value: any) => { setPatient((prev) => (prev ? { ...prev, [field]: value } : null)); }; // Update service date when calendar date changes const onServiceDateChange = (date: Date | undefined) => { if (date) { setServiceDateValue(date); setServiceDate(format(date, "MM/dd/yy")); } }; // Determine patient date of birth format const formatDOB = (dob: string | undefined) => { if (!dob) return ""; if (/^\d{2}\/\d{2}\/\d{4}$/.test(dob)) return dob; // already MM/DD/YYYY if (/^\d{4}-\d{2}-\d{2}/.test(dob)) { const datePart = dob?.split("T")[0]; // safe optional chaining if (!datePart) return ""; const [year, month, day] = datePart.split("-"); return `${month}/${day}/${year}`; } return dob; }; return (
Insurance Claim Form
{/* Patient Information */}
updatePatientField("insuranceId", e.target.value)} disabled={isLoading} />
updatePatientField("dateOfBirth", e.target.value)} disabled={isLoading} />
updatePatientField("firstName", e.target.value)} disabled={isLoading} />
updatePatientField("lastName", e.target.value)} disabled={isLoading} />
{/* Clinical Notes Entry */}
setClinicalNotes(e.target.value)} />
{/* Service Lines */}

Service Lines

Procedure Code Tooth Number Surface Quadrant Auth No. Billed Amount
{/* Dynamic Rows */} {serviceLines.map((line, i) => (
updateServiceLine(i, "procedureCode", e.target.value) } /> updateServiceLine(i, "toothNumber", e.target.value) } /> updateServiceLine(i, "surface", e.target.value) } /> updateServiceLine(i, "authNo", e.target.value) } /> updateServiceLine(i, "billedAmount", e.target.value) } />
))}
{/* File Upload Section */}

Please note that file types with 4 or more character extensions are not allowed, such as .DOCX, .PPTX, or .XLSX

{/* Insurance Carriers */}

Insurance Carriers

); }