diff --git a/app/settings/page.tsx b/app/settings/page.tsx index d4894c1..8c08a7a 100644 --- a/app/settings/page.tsx +++ b/app/settings/page.tsx @@ -209,6 +209,110 @@ function SaveButton({ label = "Save changes" }: { label?: string }) { ); } +type InsuranceReminder = { + policyId: string; + name: string; + nextPaymentDate: string; + monthlyPremium: number; +}; + +function InsuranceReminderPreview() { + const [status, setStatus] = useState< + "loading" | "loaded" | "empty" | "unauthorized" | "error" + >("loading"); + const [reminders, setReminders] = useState([]); + const [error, setError] = useState(null); + + useEffect(() => { + let active = true; + + async function loadReminders() { + try { + const response = await fetch("/api/insurance/reminders"); + if (!active) return; + + if (response.status === 401 || response.status === 403) { + setStatus("unauthorized"); + setError("Connect your wallet to view upcoming insurance reminders."); + return; + } + + if (!response.ok) { + const body = await response.text(); + throw new Error(body || response.statusText); + } + + const data = (await response.json()) as InsuranceReminder[]; + if (!active) return; + + setReminders(data); + setStatus(data.length > 0 ? "loaded" : "empty"); + } catch (err) { + if (!active) return; + setStatus("error"); + setError(err instanceof Error ? err.message : String(err)); + } + } + + loadReminders(); + return () => { + active = false; + }; + }, []); + + return ( +
+
+
+

+ Insurance reminders +

+

+ Show upcoming or overdue premium payments for your active policies. +

+
+
+ {status === "loading" && "Loading…"} + {status === "empty" && "No reminders in the next 7 days."} + {status === "loaded" && `${reminders.length} reminder${reminders.length === 1 ? "" : "s"}`} + {status === "unauthorized" && "Sign in to view reminders."} + {status === "error" && "Unable to load reminders."} +
+
+ +
+ {status === "loaded" && + reminders.map((reminder) => ( +
+
+

+ {reminder.name} +

+ + Due {new Date(reminder.nextPaymentDate).toLocaleDateString()} + +
+

+ Premium: ${reminder.monthlyPremium.toFixed(2)} +

+
+ ))} + {status === "unauthorized" && ( +

{error}

+ )} + {status === "error" && ( +

+ {error ?? "Could not load insurance reminders."} +

+ )} +
+
+ ); +} + // ─── Sections ──────────────────────────────────────────────────────────────── function ProfileSection() { @@ -302,6 +406,12 @@ function NotificationsSection() { description="When you hit 25 %, 50 %, 75 %, or 100 % of a goal" defaultChecked /> + +

Channels