Files
DentalManagement2025/apps/Frontend/src/components/patients/patient-form.tsx
2025-05-08 21:27:29 +05:30

310 lines
9.8 KiB
TypeScript

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { insertPatientSchema, InsertPatient, Patient, updatePatientSchema, UpdatePatient } from "@shared/schema";
import { useAuth } from "@/hooks/use-auth";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
interface PatientFormProps {
patient?: Patient;
extractedInfo?: {
firstName: string;
lastName: string;
dateOfBirth: string;
insuranceId: string;
};
onSubmit: (data: InsertPatient | UpdatePatient) => void;
}
export function PatientForm({ patient, extractedInfo, onSubmit }: PatientFormProps) {
const { user } = useAuth();
const isEditing = !!patient;
const schema = isEditing ? updatePatientSchema : insertPatientSchema.extend({
userId: z.number().optional(),
});
// Merge extracted info into default values if available
const defaultValues = {
firstName: extractedInfo?.firstName || "",
lastName: extractedInfo?.lastName || "",
dateOfBirth: extractedInfo?.dateOfBirth || "",
gender: "",
phone: "",
email: "",
address: "",
city: "",
zipCode: "",
insuranceProvider: "",
insuranceId: extractedInfo?.insuranceId || "",
groupNumber: "",
policyHolder: "",
allergies: "",
medicalConditions: "",
status: "active",
userId: user?.id,
};
const form = useForm<InsertPatient | UpdatePatient>({
resolver: zodResolver(schema),
defaultValues: patient || defaultValues,
});
const handleSubmit = (data: InsertPatient | UpdatePatient) => {
onSubmit(data);
};
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
{/* Personal Information */}
<div>
<h4 className="text-md font-medium text-gray-700 mb-3">Personal Information</h4>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="firstName"
render={({ field }) => (
<FormItem>
<FormLabel>First Name *</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="lastName"
render={({ field }) => (
<FormItem>
<FormLabel>Last Name *</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="dateOfBirth"
render={({ field }) => (
<FormItem>
<FormLabel>Date of Birth *</FormLabel>
<FormControl>
<Input type="date" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="gender"
render={({ field }) => (
<FormItem>
<FormLabel>Gender *</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value as string}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select gender" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="male">Male</SelectItem>
<SelectItem value="female">Female</SelectItem>
<SelectItem value="other">Other</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
{/* Contact Information */}
<div>
<h4 className="text-md font-medium text-gray-700 mb-3">Contact Information</h4>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem>
<FormLabel>Phone Number *</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" {...field} value={field.value || ''} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="address"
render={({ field }) => (
<FormItem className="md:col-span-2">
<FormLabel>Address</FormLabel>
<FormControl>
<Input {...field} value={field.value || ''} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="city"
render={({ field }) => (
<FormItem>
<FormLabel>City</FormLabel>
<FormControl>
<Input {...field} value={field.value || ''} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="zipCode"
render={({ field }) => (
<FormItem>
<FormLabel>ZIP Code</FormLabel>
<FormControl>
<Input {...field} value={field.value || ''} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
{/* Insurance Information */}
<div>
<h4 className="text-md font-medium text-gray-700 mb-3">Insurance Information</h4>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
control={form.control}
name="insuranceProvider"
render={({ field }) => (
<FormItem>
<FormLabel>Insurance Provider</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value as string || ''}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select provider" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="placeholder">Select provider</SelectItem>
<SelectItem value="delta">Delta Dental</SelectItem>
<SelectItem value="metlife">MetLife</SelectItem>
<SelectItem value="cigna">Cigna</SelectItem>
<SelectItem value="aetna">Aetna</SelectItem>
<SelectItem value="other">Other</SelectItem>
<SelectItem value="none">None</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="insuranceId"
render={({ field }) => (
<FormItem>
<FormLabel>Insurance ID</FormLabel>
<FormControl>
<Input {...field} value={field.value || ''} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="groupNumber"
render={({ field }) => (
<FormItem>
<FormLabel>Group Number</FormLabel>
<FormControl>
<Input {...field} value={field.value || ''} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="policyHolder"
render={({ field }) => (
<FormItem>
<FormLabel>Policy Holder (if not self)</FormLabel>
<FormControl>
<Input {...field} value={field.value || ''} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
{/* Hidden submit button for form validation */}
<button type="submit" className="hidden" aria-hidden="true"></button>
</form>
</Form>
);
}