"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useTheme } from "@/app/ThemeProvider"; import { useFamily } from "@/app/FamilyProvider"; import { Button, Card, Input, Select, Badge } from "@/components/ui"; import { StorageMeter, MemberLimitBanner } from "@/components/StorageMeter"; interface Member { id: string; userId: string; role: string; displayName: string; name: string; email: string; } interface Invite { id: string; email: string; displayName: string; role: string; expiresAt: string; } export default function SettingsPage() { const router = useRouter(); const { theme, mode, setMode } = useTheme(); const { tier, memberCount, familyId, children, familyName: providerFamilyName, childId, child } = useFamily(); const [exporting, setExporting] = useState(false); const [themeOpen, setThemeOpen] = useState(false); const [inviteOpen, setInviteOpen] = useState(false); const [familyOpen, setFamilyOpen] = useState(true); const [members, setMembers] = useState([]); const [invites, setInvites] = useState([]); const [inviteEmail, setInviteEmail] = useState(""); const [inviteRole, setInviteRole] = useState("caregiver"); const [inviteLoading, setInviteLoading] = useState(false); const [pedPhone, setPedPhone] = useState(""); const [pedSaving, setPedSaving] = useState(false); // Check if can invite more members (client-side pre-check; server enforces) const canInvite = tier === "pro" || memberCount < 2; // Family name from provider or fallback const familyName = providerFamilyName || "My Family"; const themeOptions = [ { value: "light", label: "Light" }, { value: "dark", label: "Dark" }, { value: "system", label: "System" }, { value: "time", label: "Time of Day" }, ] as const; useEffect(() => { if (familyId) { fetchMembers(); fetchInvites(); fetch("/api/family").then(r => r.json()).then(d => { if (d.family?.pediatrician_phone) setPedPhone(d.family.pediatrician_phone); }).catch(() => {}); } }, [familyId]); const exportGrowthCSV = async () => { if (!childId) return; setExporting(true); try { const res = await fetch(`/api/growth?childId=${childId}`); const data = await res.json(); const records = data.growth || []; if (records.length === 0) { alert("No growth records to export."); return; } const headers = ["Date", "Weight (kg)", "Height (cm)", "Head (cm)", "Notes"]; const rows = records.map((r: { measured_at: string; weight_kg: number | null; height_cm: number | null; head_circumference_cm: number | null; notes: string | null }) => [ new Date(r.measured_at).toLocaleDateString(), r.weight_kg ?? "", r.height_cm ?? "", r.head_circumference_cm ?? "", r.notes ?? "", ]); const csv = [headers, ...rows].map(row => row.join(",")).join("\n"); const blob = new Blob([csv], { type: "text/csv" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `${child?.name || "child"}_growth_${new Date().toISOString().split("T")[0]}.csv`; a.click(); URL.revokeObjectURL(url); } catch { alert("Export failed. Please try again."); } setExporting(false); }; const savePedPhone = async () => { setPedSaving(true); await fetch("/api/family", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ pediatricianPhone: pedPhone }), }).catch(() => {}); setPedSaving(false); }; const fetchMembers = async () => { if (!familyId) return; try { const res = await fetch(`/api/family/members?familyId=${familyId}`); const data = await res.json(); setMembers(data.members || []); } catch (err) { console.error("Failed to fetch members:", err); } }; const fetchInvites = async () => { if (!familyId) return; try { const res = await fetch(`/api/invites?familyId=${familyId}`); const data = await res.json(); setInvites(data.invites || []); } catch (err) { console.error("Failed to fetch invites:", err); } }; const deleteInvite = async (inviteId: string) => { try { await fetch(`/api/invites/${inviteId}`, { method: "DELETE" }); setInvites(prev => prev.filter(i => i.id !== inviteId)); } catch (err) { console.error("Failed to delete invite:", err); } }; const sendInvite = async () => { if (!inviteEmail || !familyId) return; setInviteLoading(true); try { const res = await fetch("/api/invites", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ familyId: familyId, email: inviteEmail, role: inviteRole, displayName: inviteEmail.split("@")[0], }), }); const data = await res.json(); if (data.success) { setInviteEmail(""); fetchInvites(); } else if (data.reason === "member_limit_reached") { // Trigger re-render of the limit banner with fresh data fetchMembers(); } else { alert(data.error); } } catch (err) { console.error("Failed to send invite:", err); } setInviteLoading(false); }; return (

Settings

{/* My Profile Page */}

My Profile Page

Create your public product recommendation page

โ†’
{/* Notifications */}
๐Ÿ””
Notifications
โ†’ {/* Profile */}
๐Ÿ‘ค
Profile
โ†’ {/* Family - Single consolidated section */}
{familyOpen && (
{/* Family Info */}
{familyName}
{tier === "pro" ? "Pro Plan" : Free Plan} ยท {members.length} member{members.length !== 1 ? "s" : ""} ยท {children?.length || 0} child{children?.length !== 1 ? "ren" : ""}
{tier === "free" && ( )}
{/* Family Members */}
Family Members
{members.length > 0 ? (
{members.map((member) => (
{member.name || member.email}
{member.email}
{member.role}
))}
) : (

No family members

)}
{/* Storage usage meter */}
Storage
{/* Manage Children */} Manage Children โ†’
)}
{/* Invite Members */}
{inviteOpen && (
{/* Member limit banner */} {tier === "free" && !canInvite && (
)} {/* Pending invites */} {invites.length > 0 && (
Pending Invites
{invites.map((invite) => (
{invite.email}
Pending ยท expires {new Date(invite.expiresAt).toLocaleDateString()}
))}
)} {/* Add invite form */} {canInvite && (
setInviteEmail(e.target.value)} placeholder="Email address" />
)}
)}
{/* Theme */}
{themeOpen && (
{themeOptions.map((opt) => ( ))}
)}
{/* Pediatrician Phone */}
๐Ÿฅ
Pediatrician Phone

Shown on the emergency guide and in AI medical redirects.

setPedPhone(e.target.value)} placeholder="+91 98765 43210" className="flex-1" />
View Emergency Guide โ†’
{/* Export Data */} {/* App Version */}
App Version
Tia v1.0.0
); }