From b67bb1e1834c5330a1922104efa8029ff44e1344 Mon Sep 17 00:00:00 2001 From: DMleadgen Date: Fri, 10 Apr 2026 13:20:41 -0600 Subject: [PATCH] fix: degrade phone followups without calendar creds --- .../phone-agent/followup-reminder/route.ts | 62 ++++++++++++------- .../phone-agent/followup-slots/route.ts | 14 ++++- lib/google-calendar.ts | 9 +++ 3 files changed, 62 insertions(+), 23 deletions(-) diff --git a/app/api/internal/phone-agent/followup-reminder/route.ts b/app/api/internal/phone-agent/followup-reminder/route.ts index aca50c9c..5bef862d 100644 --- a/app/api/internal/phone-agent/followup-reminder/route.ts +++ b/app/api/internal/phone-agent/followup-reminder/route.ts @@ -5,6 +5,7 @@ import { requirePhoneAgentInternalAuth } from "@/app/api/internal/phone-calls/sh import { buildSameDayReminderWindow, createFollowupReminderEvent, + isGoogleCalendarConfigured, } from "@/lib/google-calendar" import { normalizePhoneE164, splitDisplayName } from "@/lib/phone-normalization" @@ -69,6 +70,7 @@ export async function POST(request: Request) { const company = String(body.company || "").trim() const reason = String(body.reason || "").trim() const summaryText = String(body.summaryText || "").trim() + const calendarConfigured = isGoogleCalendarConfigured() let startAt: Date let endAt: Date @@ -90,24 +92,36 @@ export async function POST(request: Request) { } } - const reminder = await createFollowupReminderEvent({ - title: buildReminderTitle({ - kind, - callerName, - company, - phone: normalizedPhone || String(body.phone || "").trim(), - }), - description: buildReminderDescription({ - callerName, - company, - phone: normalizedPhone || String(body.phone || "").trim(), - reason, - summaryText, - adminCallUrl, - }), - startAt, - endAt, - }) + if (kind === "scheduled" && !calendarConfigured) { + return NextResponse.json( + { error: "Google Calendar follow-up scheduling is not configured" }, + { status: 503 } + ) + } + + const reminder = calendarConfigured + ? await createFollowupReminderEvent({ + title: buildReminderTitle({ + kind, + callerName, + company, + phone: normalizedPhone || String(body.phone || "").trim(), + }), + description: buildReminderDescription({ + callerName, + company, + phone: normalizedPhone || String(body.phone || "").trim(), + reason, + summaryText, + adminCallUrl, + }), + startAt, + endAt, + }) + : { + eventId: "", + htmlLink: "", + } let contactProfileId: string | undefined if (normalizedPhone) { @@ -135,19 +149,23 @@ export async function POST(request: Request) { reminderRequestedAt: Date.now(), reminderStartAt: startAt.getTime(), reminderEndAt: endAt.getTime(), - reminderCalendarEventId: reminder.eventId, + reminderCalendarEventId: reminder.eventId || undefined, reminderCalendarHtmlLink: reminder.htmlLink || undefined, - reminderNote: reason || summaryText || undefined, + reminderNote: + reason || + summaryText || + (!calendarConfigured ? "Manual follow-up reminder created without Google Calendar." : undefined), }) return NextResponse.json({ success: true, + calendarConfigured, reminder: { kind, startAt: startAt.toISOString(), endAt: endAt.toISOString(), - eventId: reminder.eventId, - htmlLink: reminder.htmlLink, + eventId: reminder.eventId || null, + htmlLink: reminder.htmlLink || null, }, call, }) diff --git a/app/api/internal/phone-agent/followup-slots/route.ts b/app/api/internal/phone-agent/followup-slots/route.ts index 6dfeb2fe..23759e72 100644 --- a/app/api/internal/phone-agent/followup-slots/route.ts +++ b/app/api/internal/phone-agent/followup-slots/route.ts @@ -1,6 +1,9 @@ import { NextResponse } from "next/server" import { requirePhoneAgentInternalAuth } from "@/app/api/internal/phone-calls/shared" -import { listFutureCallbackSlots } from "@/lib/google-calendar" +import { + isGoogleCalendarConfigured, + listFutureCallbackSlots, +} from "@/lib/google-calendar" export async function POST(request: Request) { const authError = await requirePhoneAgentInternalAuth(request) @@ -15,9 +18,18 @@ export async function POST(request: Request) { ? Math.min(body.limit, 5) : 3 + if (!isGoogleCalendarConfigured()) { + return NextResponse.json({ + success: true, + calendarConfigured: false, + slots: [], + }) + } + const slots = await listFutureCallbackSlots(limit) return NextResponse.json({ success: true, + calendarConfigured: true, slots, }) } catch (error) { diff --git a/lib/google-calendar.ts b/lib/google-calendar.ts index 19b2fc6f..cf6583cb 100644 --- a/lib/google-calendar.ts +++ b/lib/google-calendar.ts @@ -84,6 +84,15 @@ function getRequiredConfig() { } } +export function isGoogleCalendarConfigured() { + try { + getRequiredConfig() + return true + } catch { + return false + } +} + function getLocalDateTime(date: Date, timeZone = getTimeZone()): LocalDateTime { const formatter = new Intl.DateTimeFormat("en-US", { timeZone,