"use client"; import { useEffect, useState } from "react"; import { Button, Input, Select, Badge } from "@/components/ui"; interface Member { id: string; userId: string; email: string; role: string; displayName: string; } interface Family { id: string; name: string; tier: string; maxChildren: number; maxMembers: number; createdAt: string; userCount: number; childCount: number; members: Member[]; } export default function AdminFamilies() { const [families, setFamilies] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(""); const [tierFilter, setTierFilter] = useState("all"); const [showMembers, setShowMembers] = useState(null); const [addMember, setAddMember] = useState<{familyId: string; email: string; role: string; name: string} | null>(null); useEffect(() => { fetchFamilies(); }, []); const fetchFamilies = async () => { try { const res = await fetch("/api/admin/families", { credentials: "include" }); const data = await res.json(); if (data.error) { console.error("API error:", data.error); } setFamilies(data.families || []); } catch (err) { console.error("Failed to fetch families:", err); } setLoading(false); }; const handleCreateFamily = async () => { const name = prompt("Family name:"); if (!name) return; try { const res = await fetch("/api/admin/families", { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify({ name }), }); if (res.ok) fetchFamilies(); } catch (err) { console.error("Failed to create:", err); } }; const handleAddMember = async () => { if (!addMember?.email || !addMember?.familyId) return; try { const res = await fetch("/api/admin/families", { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify(addMember), }); if (res.ok) { fetchFamilies(); setAddMember(null); } } catch (err) { console.error("Failed to add member:", err); } }; const handleRemoveMember = async (memberId: string) => { if (!confirm("Remove this member?")) return; try { const res = await fetch(`/api/admin/families?memberId=${memberId}`, { method: "DELETE", credentials: "include", }); if (res.ok) fetchFamilies(); } catch (err) { console.error("Failed to remove:", err); } }; const filteredFamilies = families.filter((f) => { const matchesSearch = f.name.toLowerCase().includes(search.toLowerCase()); const matchesTier = tierFilter === "all" || f.tier === tierFilter; return matchesSearch && matchesTier; }); const exportCSV = () => { const headers = ["Name", "Tier", "Users", "Children", "Max Children", "Max Members", "Created"]; const rows = filteredFamilies.map((f) => [ f.name, f.tier, f.userCount, f.childCount, f.maxChildren, f.maxMembers, f.createdAt, ]); 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 = "families.csv"; a.click(); }; if (loading) { return (
Loading...
); } return (

Families

{families.length} total families

{/* Filters */}
setSearch(e.target.value)} className="flex-1" />
{/* Table */}
{filteredFamilies.map((family) => ( <> {showMembers === family.id && ( )} ))}
Family Tier Users Children Limits Created
{family.name}
{family.id}
{family.tier} {family.childCount} {family.maxChildren} kids, {family.maxMembers} members {family.createdAt?.slice(0, 10)}
setAddMember({familyId: family.id, email: e.target.value, role: "caregiver", name: ""})} className="flex-1" />
{(family.members || []).map((m) => (
{m.email} ({m.role})
))}
{filteredFamilies.length === 0 && (
No families found
)}
); }