"use client"; import { useEffect, useState } from "react"; import { Select } from "@/components/ui"; interface Stats { overview: { totalFamilies: number; totalUsers: number; totalChildren: number; proFamilies: number; freeFamilies: number; mrr: number; avgRevenuePerUser: number; }; conversions: { freeToPro: number; conversionRate: number; }; growth: { familiesByDay: { date: string; count: number }[]; usersByDay: { date: string; count: number }[]; }; childrenByAge: { ageGroup: string; count: number }[]; } export default function AdminDashboard() { const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [period, setPeriod] = useState("30"); useEffect(() => { fetchStats(); }, [period]); const fetchStats = async () => { try { const res = await fetch(`/api/admin/stats?period=${period}`); const data = await res.json(); setStats(data); } catch (err) { console.error("Failed to fetch stats:", err); } setLoading(false); }; if (loading || !stats) { return (
Loading...
); } return (
{/* Header */}

Dashboard

Platform overview and analytics

{/* Overview Cards */}
{/* Revenue & Tier Stats */}

Revenue Overview

${stats.overview.mrr.toFixed(2)}
Monthly Recurring Revenue
{stats.overview.proFamilies}
Pro Families
{stats.overview.freeFamilies}
Free Families
${stats.overview.avgRevenuePerUser}
Avg Revenue per Family

Conversions

{stats.conversions.conversionRate}%
Free → Pro Conversion Rate
{/* Growth Charts */}
{/* Children by Age */} {stats.childrenByAge.length > 0 && (

Children by Age Group

{stats.childrenByAge.map((item) => (
{item.count}
{item.ageGroup} years
))}
)}
); } function StatCard({ label, value, icon, color, href }: { label: string; value: number | string; icon: string; color: string; href?: string }) { const colorClasses: Record = { rose: "text-rose-400", blue: "text-blue-400", amber: "text-amber-400", emerald: "text-emerald-400", }; const content = (
{icon}
{value}
{label}
); if (href) { return {content}; } return content; } function ChartCard({ title, data, icon }: { title: string; data: { date: string; count: number }[]; icon: string }) { const maxCount = Math.max(...data.map((d) => d.count), 1); return (

{icon} {title}

{data.slice(-14).map((d, i) => (
0 ? "4px" : "0" }} />
{d.date?.slice(5) || ""}
))}
{data.length === 0 && (
No data available
)}
); }