feat: schedule page SMS reminders with AI follow-up and reschedule column

- Add Text Reminder for Column button with per-column checkboxes and AI follow-up toggle (default on)
- Batch reminder endpoint resolves {firstName}, {officeName}, {appointmentDate}, {appointmentTime} from AI chat templates
- Add Reschedule for Column UI (logic TBD)
- Move Download Claim PDF for Column below Reschedule for Column
- Add reminderSms template field to AI Chat Settings with variable hints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gitead
2026-05-09 23:17:05 -04:00
parent 112529155c
commit 585b448b6e
5 changed files with 226 additions and 7 deletions

View File

@@ -12,6 +12,7 @@ type AiChatTemplates = {
newPatientGreeting: string;
generalFallback: string;
rescheduleGreeting: string;
reminderSms: string;
};
type OfficeContact = {
@@ -19,6 +20,8 @@ type OfficeContact = {
};
const DEFAULTS = {
reminderSms:
"Hi {firstName}, this is a reminder from {officeName}. You have an appointment on {appointmentDate} at {appointmentTime}. Please reply YES to confirm or NO to reschedule. Thank you!",
reminderGreeting:
"Hi! My name is Lisa, the dedicated AI assistant at {officeName}. I can confirm or reschedule your appointment and answer general questions 24/7. How can I help you today?",
newPatientGreeting:
@@ -36,6 +39,7 @@ function preview(text: string, officeName: string) {
export function AiChatTemplatesCard() {
const { toast } = useToast();
const [reminderSms, setReminderSms] = useState(DEFAULTS.reminderSms);
const [reminderGreeting, setReminderGreeting] = useState(DEFAULTS.reminderGreeting);
const [newPatientGreeting, setNewPatientGreeting] = useState(DEFAULTS.newPatientGreeting);
const [generalFallback, setGeneralFallback] = useState(DEFAULTS.generalFallback);
@@ -67,6 +71,7 @@ export function AiChatTemplatesCard() {
useEffect(() => {
if (templates && !initialized.current) {
initialized.current = true;
setReminderSms(templates.reminderSms || DEFAULTS.reminderSms);
setReminderGreeting(templates.reminderGreeting || DEFAULTS.reminderGreeting);
setNewPatientGreeting(templates.newPatientGreeting || DEFAULTS.newPatientGreeting);
setGeneralFallback(templates.generalFallback || DEFAULTS.generalFallback);
@@ -95,6 +100,7 @@ export function AiChatTemplatesCard() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
saveMutation.mutate({
reminderSms: reminderSms.trim() || DEFAULTS.reminderSms,
reminderGreeting: reminderGreeting.trim() || DEFAULTS.reminderGreeting,
newPatientGreeting: newPatientGreeting.trim() || DEFAULTS.newPatientGreeting,
generalFallback: generalFallback.trim() || DEFAULTS.generalFallback,
@@ -105,6 +111,15 @@ export function AiChatTemplatesCard() {
const officeName = officeContact?.officeName?.trim() || "";
const templates_list = [
{
key: "reminderSms" as const,
icon: <CalendarCheck className="h-4 w-4 text-primary" />,
label: "Reminder SMS Text",
description: "Outgoing text sent from the Schedule page. Supports: {firstName}, {officeName}, {appointmentDate}, {appointmentTime}.",
value: reminderSms,
onChange: setReminderSms,
placeholder: DEFAULTS.reminderSms,
},
{
key: "reminder" as const,
icon: <CalendarCheck className="h-4 w-4 text-primary" />,
@@ -152,9 +167,12 @@ export function AiChatTemplatesCard() {
<h3 className="text-lg font-semibold">AI Chat Templates</h3>
</div>
<p className="text-sm text-muted-foreground">
Customize how your AI assistant introduces itself and responds to patients. Use{" "}
Customize the reminder SMS and AI reply templates. Available variables:{" "}
<code className="bg-muted px-1 py-0.5 rounded text-xs font-mono">{"{firstName}"}</code>{" "}
<code className="bg-muted px-1 py-0.5 rounded text-xs font-mono">{"{officeName}"}</code>{" "}
as a placeholder it will be replaced automatically with your dental office name.
<code className="bg-muted px-1 py-0.5 rounded text-xs font-mono">{"{appointmentDate}"}</code>{" "}
<code className="bg-muted px-1 py-0.5 rounded text-xs font-mono">{"{appointmentTime}"}</code>{" "}
replaced automatically when reminders are sent.
</p>
{/* Office name hint */}
@@ -208,6 +226,7 @@ export function AiChatTemplatesCard() {
variant="ghost"
className="text-xs text-muted-foreground"
onClick={() => {
setReminderSms(DEFAULTS.reminderSms);
setReminderGreeting(DEFAULTS.reminderGreeting);
setNewPatientGreeting(DEFAULTS.newPatientGreeting);
setGeneralFallback(DEFAULTS.generalFallback);