// Admin Analytics Dashboard - Real metrics and business insights "use client"; import { useEffect, useEffectEvent, useCallback, useReducer } from "react"; import Link from "next/link"; import { formatDate } from "@/lib/format-date"; import { analytics } from "@/lib/analytics"; import { getAnalyticsMetrics, getRevenueChart, getTopProducts, getRecentOrders, getCustomerGrowth, getConversionFunnel, type AnalyticsMetrics, type RevenueDataPoint, type ProductPerformance, type RecentOrder, type CustomerGrowth, type ConversionFunnel, } from "@/actions/analytics"; function getTrend(avgPrice: number) { if (avgPrice > 10) return "up"; if (avgPrice < 5) return "down"; return "stable"; } interface MetricCardProps { title: string; value: string | number; change: number; trend: "up" | "down" | "stable"; icon: React.ReactNode; } function MetricCard({ title, value, change, trend, icon }: MetricCardProps) { return (

{title}

{typeof value === "number" ? value.toLocaleString() : value}

{icon}
{trend === "up" ? "↑" : trend === "down" ? "↓" : "→"} {change > 0 ? "+" : ""}{change}% vs last period
); } interface RevenueChartProps { data: RevenueDataPoint[]; totalRevenue: number; avgOrder: number; } function RevenueChart({ data, totalRevenue, avgOrder }: RevenueChartProps) { const maxRevenue = Math.max(...data.map(d => d.revenue), 1); return (

Revenue Overview

{data.length > 0 ? ( <>
{data.map((item, i) => (
{new Date(item.date).toLocaleDateString("en-US", { month: "short", day: "numeric" })}
))}
Total Revenue

${totalRevenue.toLocaleString()}

Avg. Order

${avgOrder.toFixed(2)}

) : (

No revenue data available yet

)}
); } interface TopProductsTableProps { products: ProductPerformance[]; } function TopProductsTable({ products }: TopProductsTableProps) { if (products.length === 0) { return (

Top Products

No product data available yet

); } return (

Top Products

{products.map((product, i) => ( ))}
Product Sales Revenue Trend
📦
{product.product_name}
{product.units_sold} ${product.revenue.toFixed(2)} {getTrend(product.avg_price) === "up" ? "↑" : getTrend(product.avg_price) === "down" ? "↓" : "→"}
); } interface RecentOrdersTableProps { orders: RecentOrder[]; } function RecentOrdersTable({ orders }: RecentOrdersTableProps) { return (

Recent Orders

View all →
{orders.length > 0 ? (
{orders.map((order, i) => ( ))}
Order Customer Amount Status Date
{order.id.slice(0, 8)} {order.customer_name || "Guest"} ${order.subtotal.toFixed(2)} {order.status} {formatDate(order.created_at)}
) : (

No orders yet

)}
); } interface CustomerGrowthChartProps { data: CustomerGrowth; } function CustomerGrowthChart({ data }: CustomerGrowthChartProps) { const growthPercent = data.growth_rate || 0; const circumference = 2 * Math.PI * 56; const offset = circumference - (Math.abs(growthPercent) / 100) * circumference; return (

Customer Growth

{growthPercent > 0 ? "+" : ""}{growthPercent}% vs last month

{data.total_customers}

Total

+{data.new_this_month}

New

{data.retention_rate}%

Retention

); } interface ConversionFunnelProps { data: ConversionFunnel[]; } function ConversionFunnel({ data }: ConversionFunnelProps) { return (

Conversion Funnel

{data.length > 0 ? (
{data.map((step, i) => (
{step.stage}
{step.count.toLocaleString()} ({step.rate}%)
))}
) : (

No funnel data available

)}
); } // ---- useReducer state ---- type State = { isLoading: boolean; error: string | null; metrics: AnalyticsMetrics; revenueData: RevenueDataPoint[]; topProducts: ProductPerformance[]; recentOrders: RecentOrder[]; customerGrowth: CustomerGrowth; conversionFunnel: ConversionFunnel[]; }; type Action = | { type: "FETCH_START" } | { type: "FETCH_SUCCESS"; metrics: AnalyticsMetrics; revenueData: RevenueDataPoint[]; topProducts: ProductPerformance[]; recentOrders: RecentOrder[]; customerGrowth: CustomerGrowth; conversionFunnel: ConversionFunnel[] } | { type: "FETCH_ERROR"; error: string }; const initialMetrics: AnalyticsMetrics = { total_revenue: 0, revenue_change: 0, total_orders: 0, orders_change: 0, active_customers: 0, customers_change: 0, avg_order_value: 0, aov_change: 0, }; const initialCustomerGrowth: CustomerGrowth = { total_customers: 0, new_this_month: 0, retention_rate: 0, growth_rate: 0, }; const initialState: State = { isLoading: true, error: null, metrics: initialMetrics, revenueData: [], topProducts: [], recentOrders: [], customerGrowth: initialCustomerGrowth, conversionFunnel: [], }; function reducer(state: State, action: Action): State { switch (action.type) { case "FETCH_START": return { ...state, isLoading: true, error: null }; case "FETCH_SUCCESS": return { ...state, isLoading: false, metrics: action.metrics, revenueData: action.revenueData, topProducts: action.topProducts, recentOrders: action.recentOrders, customerGrowth: action.customerGrowth, conversionFunnel: action.conversionFunnel, }; case "FETCH_ERROR": return { ...state, isLoading: false, error: action.error }; } } export default function AnalyticsDashboard({ brandId }: { brandId?: string }) { const [state, dispatch] = useReducer(reducer, initialState); const fetchAllData = useCallback(async () => { dispatch({ type: "FETCH_START" }); try { const [ metricsData, revenueChartData, productsData, ordersData, growthData, funnelData, ] = await Promise.all([ getAnalyticsMetrics(30), getRevenueChart(30), getTopProducts(5), getRecentOrders(10), getCustomerGrowth(), getConversionFunnel(), ]); dispatch({ type: "FETCH_SUCCESS", metrics: metricsData, revenueData: revenueChartData, topProducts: productsData, recentOrders: ordersData, customerGrowth: growthData, conversionFunnel: funnelData, }); } catch (err) { console.error("Failed to fetch analytics:", err); dispatch({ type: "FETCH_ERROR", error: err instanceof Error ? err.message : "Failed to load analytics" }); } }, []); // useEffectEvent so we always call the latest fetchAllData without // re-running the effect every time the parent re-renders. const fetchAllDataEffect = useEffectEvent(() => { fetchAllData(); }); useEffect(() => { analytics.featureUsed("analytics_dashboard", { brand_id: brandId }); // Wrap in requestAnimationFrame to avoid sync setState requestAnimationFrame(() => { fetchAllDataEffect(); }); }, [brandId]); if (state.isLoading) { return ; } if (state.error) { return ; } return (
); } function LoadingState() { return (
); } function ErrorState({ error, onRetry }: { error: string; onRetry: () => void }) { return (

{error}

); } function DashboardHeader({ onRefresh }: { onRefresh: () => void }) { return (

Analytics

Track your business performance and growth

); } function MetricsRow({ metrics }: { metrics: AnalyticsMetrics }) { return (
= 0 ? "up" : "down"} icon={ } /> = 0 ? "up" : "down"} icon={ } /> = 0 ? "up" : "down"} icon={ } /> = 0 ? "up" : "down"} icon={ } />
); } type ChartsRowProps = { revenueData: RevenueDataPoint[]; totalRevenue: number; avgOrder: number; customerGrowth: CustomerGrowth; }; function ChartsRow({ revenueData, totalRevenue, avgOrder, customerGrowth }: ChartsRowProps) { return (
); } type TablesRowProps = { topProducts: ProductPerformance[]; recentOrders: RecentOrder[]; }; function TablesRow({ topProducts, recentOrders }: TablesRowProps) { return (
); }