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:
@@ -3,6 +3,7 @@ import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { format } from "date-fns";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
import { APPOINTMENT_TYPES } from "@/utils/appointmentTypeUtils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Form,
|
||||
@@ -70,6 +71,10 @@ export function AppointmentForm({
|
||||
const t = appointment?.type ?? "";
|
||||
return t.startsWith("other:") ? t.slice(6) : "";
|
||||
});
|
||||
// Track whether the user explicitly changed the type during this edit session.
|
||||
// Used to set typeLocked so the auto-sync won't overwrite a deliberate choice.
|
||||
const originalType = useRef<string>(appointment?.type ?? "");
|
||||
const [typeChangedByUser, setTypeChangedByUser] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => {
|
||||
@@ -295,6 +300,8 @@ export function AppointmentForm({
|
||||
startTime: data.startTime,
|
||||
endTime: data.endTime,
|
||||
type: resolvedType,
|
||||
// Lock the type when the user has explicitly changed it on an existing appointment
|
||||
...(appointment && typeChangedByUser ? { typeLocked: true } : {}),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -522,6 +529,7 @@ export function AppointmentForm({
|
||||
onValueChange={(val) => {
|
||||
field.onChange(val);
|
||||
if (val !== "other") setOtherTypeDesc("");
|
||||
if (val !== originalType.current) setTypeChangedByUser(true);
|
||||
}}
|
||||
value={field.value}
|
||||
defaultValue={field.value}
|
||||
@@ -532,16 +540,9 @@ export function AppointmentForm({
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="checkup">Checkup</SelectItem>
|
||||
<SelectItem value="cleaning">Cleaning</SelectItem>
|
||||
<SelectItem value="filling">Filling</SelectItem>
|
||||
<SelectItem value="extraction">Extraction</SelectItem>
|
||||
<SelectItem value="root-canal">Root Canal</SelectItem>
|
||||
<SelectItem value="crown">Crown</SelectItem>
|
||||
<SelectItem value="dentures">Dentures</SelectItem>
|
||||
<SelectItem value="consultation">Consultation</SelectItem>
|
||||
<SelectItem value="emergency">Emergency</SelectItem>
|
||||
<SelectItem value="other">Other</SelectItem>
|
||||
{APPOINTMENT_TYPES.map((t) => (
|
||||
<SelectItem key={t.value} value={t.value}>{t.label}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{field.value === "other" && (
|
||||
|
||||
Reference in New Issue
Block a user