"use client"; import { useState, useEffect } from "react"; import { Download, Calendar } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { fetchProfitAndLoss, type ProfitAndLossData } from "@/lib/supabase/reports-actions"; import PageSkeleton from "./PageSkeleton"; const PERIOD_OPTIONS = [ { label: "This Month", value: "this-month" }, { label: "Last Month", value: "last-month" }, { label: "This Quarter", value: "this-quarter" }, { label: "This Year", value: "this-year" }, ]; function getPeriodDates(period: string): { start: string; end: string } { const now = new Date(); const y = now.getFullYear(); const m = now.getMonth(); switch (period) { case "this-month": return { start: `${y}-${String(m + 1).padStart(2, "0")}-01`, end: `${y}-${String(m + 1).padStart(2, "0")}-${new Date(y, m + 1, 0).getDate()}` }; case "last-month": { const lm = m === 0 ? 11 : m - 1; const ly = m === 0 ? y - 1 : y; const lastDay = new Date(y, m, 0).getDate(); return { start: `${ly}-${String(lm + 1).padStart(2, "0")}-01`, end: `${ly}-${String(lm + 1).padStart(2, "0")}-${lastDay}` }; } case "this-quarter": { const qm = Math.floor(m / 3) * 3; return { start: `${y}-${String(qm + 1).padStart(2, "0")}-01`, end: `${y}-${String(Math.min(qm + 3, 12)).padStart(2, "0")}-${new Date(y, qm + 3, 0).getDate()}` }; } case "this-year": return { start: `${y}-01-01`, end: `${y}-12-31` }; default: return { start: `${y}-01-01`, end: `${y}-12-31` }; } } function formatCurrency(amount: number): string { return `$${amount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } export default function ReportsPLPage() { const [period, setPeriod] = useState("this-year"); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const { start, end } = getPeriodDates(period); let cancelled = false; fetchProfitAndLoss(start, end) .then((d) => { if (!cancelled) setData(d); }) .catch(() => {}) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [period]); if (loading) return ; if (!data) return null; return (
{/* Controls */}
{/* Summary cards */}

Revenue

{formatCurrency(data.revenue.total)}

Gross Profit

{formatCurrency(data.grossProfit)}

Operating Expenses

{formatCurrency(data.operatingExpenses.total)}

Net Profit

= 0 ? "text-emerald-600" : "text-red-600"}`}> {formatCurrency(data.netProfit)}

{/* Detailed P&L Statement */}

Profit & Loss Statement

{/* Revenue */}

Revenue

{data.revenue.byMonth.length > 0 ? ( data.revenue.byMonth.map((m) => (
{m.month} {formatCurrency(m.amount)}
)) ) : (

No revenue recorded

)}
Total Revenue {formatCurrency(data.revenue.total)}
{/* Cost of Sales */}

Cost of Sales

{data.costOfSales.items.length > 0 ? ( data.costOfSales.items.map((item) => (
{item.name} -{formatCurrency(item.amount)}
)) ) : (

No cost of sales tracked

)}
Gross Profit {formatCurrency(data.grossProfit)} ({data.grossMargin.toFixed(1)}%)
{/* Operating Expenses */}

Operating Expenses

{data.operatingExpenses.byCategory.length > 0 ? ( data.operatingExpenses.byCategory.map((item) => (
{item.category} -{formatCurrency(item.amount)}
)) ) : (

No operating expenses

)}
Total Operating Expenses -{formatCurrency(data.operatingExpenses.total)}
{/* Net Profit */}
Net Profit = 0 ? "text-emerald-600" : "text-red-600"}`}> {formatCurrency(data.netProfit)}
Net margin = 0 ? "text-emerald-600" : "text-red-600"}`}> {data.netMargin.toFixed(1)}%
); }