feat: appointment type inference, procedure codes on cards, claim attachment fixes
- Add appointment type categories matching insurance claim form (recall, filling, pedo, dentures, implant, endo, crown, perio, extraction, ortho, consultation, emergency, other) - Auto-infer appointment type from CDT codes with priority rules (endo > implant > crown > ...) - typeLocked flag prevents auto-overwrite when user manually sets type - Show appointment type label and procedure codes on schedule cards - Background sync on /day route retroactively fixes stale appointment types - Fix PUT /api/claims/:id to save claimFiles (previously silently dropped) - Auto-link AppointmentFile records to ClaimFile when claim is created or updated - Fix D5750 (denture reline) CDT range to map correctly to dentures category - Fix typeLocked Zod rejection in appointment update route Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
import { apiRequest, queryClient } from "@/lib/queryClient";
|
||||
import {
|
||||
MultipleFileUploadZone,
|
||||
MultipleFileUploadZoneHandle,
|
||||
@@ -62,6 +62,7 @@ import {
|
||||
DirectComboButtons,
|
||||
RegularComboButtons,
|
||||
} from "@/components/procedure/procedure-combo-buttons";
|
||||
import { inferTypeFromProcedureCodes, getAppointmentTypeLabel } from "@/utils/appointmentTypeUtils";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import {
|
||||
AlertDialog,
|
||||
@@ -1487,8 +1488,23 @@ export function ClaimForm({
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!data.success) throw new Error("Failed to save procedures");
|
||||
|
||||
// Auto-infer appointment type from saved procedure codes
|
||||
const codes = filteredServiceLines.map((l) => l.procedureCode ?? "").filter(Boolean);
|
||||
const inferredType = inferTypeFromProcedureCodes(codes);
|
||||
if (inferredType && appointmentId) {
|
||||
try {
|
||||
await apiRequest("PATCH", `/api/appointments/${appointmentId}/type`, { type: inferredType });
|
||||
// Refresh the schedule view so the new type shows on the card immediately
|
||||
queryClient.invalidateQueries({ queryKey: ["appointments", "day"] });
|
||||
} catch {
|
||||
// Non-fatal: type update is best-effort
|
||||
}
|
||||
}
|
||||
|
||||
const attachMsg = attachments.length ? ` and ${attachments.length} attachment(s)` : "";
|
||||
toast({ title: "Procedures saved", description: `${data.count} procedure(s)${attachMsg} saved.` });
|
||||
const typeMsg = inferredType ? ` · Type → ${getAppointmentTypeLabel(inferredType)}` : "";
|
||||
toast({ title: "Procedures saved", description: `${data.count} procedure(s)${attachMsg} saved${typeMsg}.` });
|
||||
onClose();
|
||||
} catch (err: any) {
|
||||
toast({ title: "Save failed", description: err?.message ?? "Failed to save procedures.", variant: "destructive" });
|
||||
|
||||
Reference in New Issue
Block a user