feat: AI chat system with LangGraph, multi-step patient flows, and appointment rescheduling
- Add floating chat window Hand-off to AI toggle (per-patient) and after-hours AI toggle (global) - Add LangGraph-powered appointment reminder flow: AI introduces itself, classifies YES/NO, handles confirmation with appointment date/time - Add multi-step rescheduling flow: ASAP vs next week, tomorrow offer, Mon/Tue/Wed picker, morning/afternoon time slot — automatically updates appointment in DB - Add new patient / after-hours flow: new vs existing patient, dental insurance check, MassHealth Selenium eligibility check (auto-uses saved member ID + DOB for existing patients), self-pay fallback - Add AI Chat Settings page (Settings → Advanced) with editable greeting templates and LangGraph flow diagrams for both reminder and new-patient flows - Add Schedule a New Patient template option in chat window, starts new-patient conversation flow - Add GET/PUT endpoints for AI handoff, after-hours handoff, and AI chat templates - Add multilingual support (7 languages) across all AI reply nodes with LLM generation and hardcoded fallbacks - Add pending reschedule in-memory store and conversation stage tracking across all flows Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import {
|
||||
Phone,
|
||||
PhoneCall,
|
||||
@@ -22,6 +23,7 @@ import {
|
||||
MessageSquare,
|
||||
Send,
|
||||
X,
|
||||
MoonStar,
|
||||
} from "lucide-react";
|
||||
import { SmsTemplateDialog } from "@/components/patient-connection/sms-template-diaog";
|
||||
import { MessageThread } from "@/components/patient-connection/message-thread";
|
||||
@@ -35,8 +37,36 @@ export default function PatientConnectionPage() {
|
||||
const [selectedPatient, setSelectedPatient] = useState<Patient | null>(null);
|
||||
const [isSmsDialogOpen, setIsSmsDialogOpen] = useState(false);
|
||||
const [showMessaging, setShowMessaging] = useState(false);
|
||||
const [afterHoursEnabled, setAfterHoursEnabled] = useState(true);
|
||||
const { toast } = useToast();
|
||||
|
||||
useQuery<{ enabled: boolean }>({
|
||||
queryKey: ["/api/twilio/after-hours-handoff"],
|
||||
queryFn: async () => {
|
||||
const res = await apiRequest("GET", "/api/twilio/after-hours-handoff");
|
||||
return res.json();
|
||||
},
|
||||
onSuccess: (data: { enabled: boolean }) => setAfterHoursEnabled(data.enabled),
|
||||
} as any);
|
||||
|
||||
const afterHoursMutation = useMutation({
|
||||
mutationFn: async (enabled: boolean) =>
|
||||
apiRequest("PUT", "/api/twilio/after-hours-handoff", { enabled }),
|
||||
onSuccess: (_: any, enabled: boolean) => {
|
||||
toast({
|
||||
title: enabled ? "After-hours AI enabled" : "After-hours AI disabled",
|
||||
description: enabled
|
||||
? "AI will automatically handle messages outside office hours."
|
||||
: "After-hours messages will not receive an automatic AI reply.",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const handleAfterHoursToggle = (enabled: boolean) => {
|
||||
setAfterHoursEnabled(enabled);
|
||||
afterHoursMutation.mutate(enabled);
|
||||
};
|
||||
|
||||
const toggleMobileMenu = () => {
|
||||
setIsMobileMenuOpen(!isMobileMenuOpen);
|
||||
};
|
||||
@@ -175,6 +205,16 @@ export default function PatientConnectionPage() {
|
||||
Search and communicate with patients
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* After-hours AI toggle */}
|
||||
<div className="flex items-center gap-2 px-4 py-2 rounded-lg border bg-white shadow-sm">
|
||||
<MoonStar className={`h-4 w-4 ${afterHoursEnabled ? "text-primary" : "text-muted-foreground"}`} />
|
||||
<span className="text-sm font-medium">Hand off to AI after hours</span>
|
||||
<Switch
|
||||
checked={afterHoursEnabled}
|
||||
onCheckedChange={handleAfterHoursToggle}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import { OfficeHoursCard } from "@/components/settings/office-hours-card";
|
||||
import { OfficeContactCard } from "@/components/settings/office-contact-card";
|
||||
import { ProcedureTimeslotCard } from "@/components/settings/procedure-timeslot-card";
|
||||
import { InsuranceContactCard } from "@/components/settings/insurance-contact-card";
|
||||
import { AiChatSettingsCard } from "@/components/settings/ai-chat-settings-card";
|
||||
|
||||
type SectionId =
|
||||
| "staff"
|
||||
@@ -29,6 +30,7 @@ type SectionId =
|
||||
| "programs"
|
||||
| "twilio"
|
||||
| "ai"
|
||||
| "aichat"
|
||||
| "officehours"
|
||||
| "officecontact"
|
||||
| "proceduretimeslot"
|
||||
@@ -259,6 +261,9 @@ export default function SettingsPage() {
|
||||
case "ai":
|
||||
return <AiSettingsCard />;
|
||||
|
||||
case "aichat":
|
||||
return <AiChatSettingsCard />;
|
||||
|
||||
case "officehours":
|
||||
return <OfficeHoursCard />;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user