feat: chat window, preferred language, insurance contact, and AI call eligibility

- Schedule: right-click Chat option opens floating SMS chat window
- Chat window: SMS template selector with appointment date/time pre-filled
- Chat window: office name and phone pulled from Settings > Office Contact
- Chat window: Preferred Language selector (English, Spanish, Portuguese,
  Mandarin, Cantonese, Arabic, Haitian Creole) with fully translated templates
  and locale-aware date/time formatting
- Patient form: Preferred Language field (add/edit), default English
- Settings > Office Contact: added Dental Office Name field
- Settings > Advanced: Insurance Contact page (CRUD — company name + phone)
- Prisma schema: preferredLanguage on Patient, officeName on OfficeContact,
  new InsuranceContact model
- Patient management: Upload Patient Document moved below Patient Records
- Insurance Eligibility: AI Call Insurance collapsible section; insurance
  company and phone auto-populated from saved Insurance Contacts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gitead
2026-05-07 16:42:37 -04:00
parent dd0df4a435
commit 16429320fa
16 changed files with 977 additions and 115 deletions

View File

@@ -6,6 +6,7 @@ import { apiRequest, queryClient } from "@/lib/queryClient";
type OfficeContact = {
id?: number;
officeName?: string | null;
receptionistName?: string | null;
dentistName?: string | null;
phoneNumber?: string | null;
@@ -16,6 +17,7 @@ type OfficeContact = {
export function OfficeContactCard() {
const { toast } = useToast();
const [officeName, setOfficeName] = useState("");
const [receptionistName, setReceptionistName] = useState("");
const [dentistName, setDentistName] = useState("");
const [phoneNumber, setPhoneNumber] = useState("");
@@ -33,6 +35,7 @@ export function OfficeContactCard() {
useEffect(() => {
if (contact) {
setOfficeName(contact.officeName ?? "");
setReceptionistName(contact.receptionistName ?? "");
setDentistName(contact.dentistName ?? "");
setPhoneNumber(contact.phoneNumber ?? "");
@@ -61,7 +64,7 @@ export function OfficeContactCard() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
saveMutation.mutate({ receptionistName, dentistName, phoneNumber, email, fax });
saveMutation.mutate({ officeName, receptionistName, dentistName, phoneNumber, email, fax });
};
return (
@@ -78,6 +81,17 @@ export function OfficeContactCard() {
<p className="text-sm text-gray-400">Loading...</p>
) : (
<form className="space-y-4" onSubmit={handleSubmit}>
<div>
<label className="block text-sm font-medium">Dental Office Name</label>
<input
type="text"
value={officeName}
onChange={(e) => setOfficeName(e.target.value)}
className="mt-1 p-2 border rounded w-full text-sm"
placeholder="e.g. Summit Dental Care"
/>
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<label className="block text-sm font-medium">Receptionist Name</label>