"use client"; import { BarChart, LineChart, PieChart, ProductTable, SummaryCard, } from "@/components/organisms/analytics"; import type { PieSlice } from "@/components/organisms/analytics"; import { calcChange, formatCurrency, formatCurrencyFull, } from "@/lib/analytics-utils"; import { MENU_CATEGORIES, MOCK_PRODUCT_SALES, MOCK_REVENUE_DAILY, MOCK_REVENUE_MONTHLY, MOCK_REVENUE_WEEKLY, MOCK_REVENUE_YEARLY, } from "@/lib/constants"; import type { AnalyticsPeriod, RevenueDataPoint } from "@/lib/types"; import Link from "next/link"; import { useMemo, useState } from "react"; // ─── Constants ──────────────────────────────────────────────────────────────── const PERIOD_LABELS: Record = { day: "By day", week: "By week", month: "By month", year: "By year", }; const CATEGORY_COLORS = [ "#6F4E37", "#C8973A", "#A0785A", "#8B6914", "#D4A96A", "#4A3728", "#F0D9A8", "#A08060", "#3D2B1F", ]; const REVENUE_MAP: Record = { day: MOCK_REVENUE_DAILY, week: MOCK_REVENUE_WEEKLY, month: MOCK_REVENUE_MONTHLY, year: MOCK_REVENUE_YEARLY, }; const CHART_TYPES = ["line", "bar", "pie"] as const; type ChartType = (typeof CHART_TYPES)[number]; const CHART_META: Record = { line: { icon: "fa-chart-line", label: "Line" }, bar: { icon: "fa-chart-bar", label: "Bar" }, pie: { icon: "fa-chart-pie", label: "Pie" }, }; // ─── Category filter select ─────────────────────────────────────────────────── function CategorySelect({ value, onChange, label = "Category:", }: { value: string; onChange: (v: string) => void; label?: string; }) { const categories = MENU_CATEGORIES.filter((c) => c.id !== "all"); return (
); } // ─── Main Page ──────────────────────────────────────────────────────────────── export default function AnalyticsPage() { const [period, setPeriod] = useState("month"); const [activeChart, setActiveChart] = useState("line"); const [categoryFilter, setCategoryFilter] = useState("all"); // Revenue data for selected period const revenueData = REVENUE_MAP[period]; // Split into halves for bar comparison const half = Math.floor(revenueData.length / 2); const barCurrent = revenueData.slice(half); const barPrevious = revenueData.slice(0, half).slice(0, barCurrent.length); // Filtered product sales const filteredSales = useMemo( () => categoryFilter === "all" ? MOCK_PRODUCT_SALES : MOCK_PRODUCT_SALES.filter((p) => p.category === categoryFilter), [categoryFilter], ); // Summary stats const totalRevenue = revenueData.reduce((s, d) => s + d.revenue, 0); const totalOrders = revenueData.reduce((s, d) => s + d.orders, 0); const totalProfit = filteredSales.reduce((s, d) => s + d.profit, 0); const avgOrderValue = totalOrders > 0 ? totalRevenue / totalOrders : 0; // Period-over-period comparisons const curRevenue = barCurrent.reduce((s, d) => s + d.revenue, 0); const prevRevenue = barPrevious.reduce((s, d) => s + d.revenue, 0); const curOrders = barCurrent.reduce((s, d) => s + d.orders, 0); const prevOrders = barPrevious.reduce((s, d) => s + d.orders, 0); const revComp = calcChange(curRevenue, prevRevenue); const ordComp = calcChange(curOrders, prevOrders); const proComp = calcChange(curRevenue * 0.65, prevRevenue * 0.65); // Pie data: revenue by category const pieData = useMemo((): PieSlice[] => { const byCategory: Record = {}; MOCK_PRODUCT_SALES.forEach((p) => { byCategory[p.category] = (byCategory[p.category] ?? 0) + p.revenue; }); return Object.entries(byCategory) .map(([catId, rev], i) => ({ label: MENU_CATEGORIES.find((c) => c.id === catId)?.name ?? catId, value: rev, color: CATEGORY_COLORS[i % CATEGORY_COLORS.length], })) .sort((a, b) => b.value - a.value); }, []); // Top 5 products const top5 = useMemo( () => [...filteredSales].sort((a, b) => b.revenue - a.revenue).slice(0, 5), [filteredSales], ); // Totals for summary row const filteredRevenue = filteredSales.reduce((s, d) => s + d.revenue, 0); const filteredProfit = filteredSales.reduce((s, d) => s + d.profit, 0); const filteredUnits = filteredSales.reduce((s, d) => s + d.unitsSold, 0); const avgMargin = filteredSales.length > 0 ? filteredSales.reduce((s, d) => s + d.profitMargin, 0) / filteredSales.length : 0; return (
{/* ── Page Header ── */}

Financial Statistics & Analytics

Financial Analytics Dashboard

{/* Period selector */}
{(Object.keys(PERIOD_LABELS) as AnalyticsPeriod[]).map((p) => ( ))}
{/* ── Summary Cards ── */}

Overview

{/* ── Revenue Chart ── */}

Revenue Chart

{CHART_TYPES.map((t) => ( ))}
{activeChart === "line" && ( <>

Revenue over time — {PERIOD_LABELS[period]}

)} {activeChart === "bar" && ( <>

Comparing revenue of the first and second half of the current period

)} {activeChart === "pie" && ( <>

Revenue share by product category

)}
{/* ── Top 5 Products ── */}

Top best-selling products

{top5.map((p, i) => { const pct = (p.revenue / top5[0].revenue) * 100; return (
{i + 1} {p.name}
{p.unitsSold} cups {formatCurrency(p.revenue)}
); })}
{/* ── Full Product Table ── */}

Detailed product analytics

Click column headers to sort. Showing {filteredSales.length}{" "} products.

{/* Summary row */}
Total revenue: {formatCurrencyFull(filteredRevenue)}
Total profit: {formatCurrencyFull(filteredProfit)}
Total units: {filteredUnits.toLocaleString()} cups
Avg. profit margin:{" "} {avgMargin.toFixed(1)}%
); }