first commit

This commit is contained in:
Dhananjaya99
2026-09-28 11:48:14 +05:30
commit a1b870fa8a
242 changed files with 39483 additions and 0 deletions
+143
View File
@@ -0,0 +1,143 @@
"use client"
import * as React from "react"
import { BanknoteIcon, TrendingUpIcon, UsersIcon } from "lucide-react"
import { getAttendanceCounts } from "@/lib/api/attendance"
import { getMemberInvoices } from "@/lib/api/invoices"
import { getMonthlyRevenue, getStatSummary } from "@/lib/api/stats"
import { formatCurrency } from "@/lib/format"
import {
DEMO_ATTENDANCE_COUNTS,
DEMO_REVENUE,
DEMO_STAT_SUMMARY,
DEMO_SUBSCRIPTIONS,
} from "@/lib/demo/mock-data"
import { useFetch } from "@/lib/use-fetch"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { AttendanceChartCard } from "@/components/hexa/attendance-chart-card"
import { PageHeader } from "@/components/hexa/page-header"
import { RevenueChartCard } from "@/components/hexa/revenue-chart-card"
import { StatCard } from "@/components/hexa/stat-card"
import { ProfitLossView } from "@/components/hexa/views/profit-loss-view"
interface ReportsViewProps {
/** Sandbox demo mode: local in-memory data, no API calls. */
demo?: boolean
}
function ReportsView({ demo = false }: ReportsViewProps) {
const summary = useFetch(demo ? async () => DEMO_STAT_SUMMARY : getStatSummary)
const revenue = useFetch(demo ? async () => DEMO_REVENUE : getMonthlyRevenue)
const counts = useFetch(demo ? async () => DEMO_ATTENDANCE_COUNTS : () => getAttendanceCounts())
const invoices = useFetch(demo ? async () => [] : getMemberInvoices)
const paidTotal = demo
? DEMO_SUBSCRIPTIONS.filter((s) => s.paymentStatus === "Paid").reduce((sum, s) => sum + s.paidAmount, 0)
: (invoices.data ?? [])
.filter((i) => i.status.toLowerCase() === "paid")
.reduce((sum, i) => sum + i.amount, 0)
const pendingTotal = demo
? DEMO_SUBSCRIPTIONS.filter((s) => s.paymentStatus !== "Paid").reduce((sum, s) => sum + s.balance, 0)
: (invoices.data ?? [])
.filter((i) => i.status.toLowerCase() === "pending")
.reduce((sum, i) => sum + i.amount, 0)
const growthHint = (pct: number) => `${pct >= 0 ? "+" : ""}${pct.toFixed(1)}% vs last month`
return (
<div className="flex flex-col gap-4">
<PageHeader title="Reports" description="Revenue, attendance, and member trends" />
<div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
<StatCard
icon={BanknoteIcon}
tone="green"
label="Total Revenue"
value={formatCurrency(summary.data?.totalRevenue ?? 0)}
hint="All time"
/>
<StatCard
icon={TrendingUpIcon}
tone="blue"
label="This Month"
value={formatCurrency(summary.data?.thisMonthRevenue ?? 0)}
hint={growthHint(summary.data?.revenueGrowthPercentage ?? 0)}
/>
<StatCard
icon={UsersIcon}
label="Total Members"
value={summary.data?.totalCustomerCount ?? 0}
hint={growthHint(summary.data?.customerGrowthPercentage ?? 0)}
/>
<StatCard
icon={BanknoteIcon}
tone="amber"
label="Outstanding"
value={formatCurrency(pendingTotal)}
hint={`${formatCurrency(paidTotal)} collected`}
/>
</div>
<Tabs defaultValue="revenue">
<TabsList className="w-full sm:w-auto">
<TabsTrigger value="revenue" className="flex-1 sm:flex-none">Revenue</TabsTrigger>
<TabsTrigger value="attendance" className="flex-1 sm:flex-none">Attendance</TabsTrigger>
<TabsTrigger value="members" className="flex-1 sm:flex-none">Members</TabsTrigger>
<TabsTrigger value="profit-loss" className="flex-1 sm:flex-none">Profit &amp; Loss</TabsTrigger>
</TabsList>
<TabsContent value="revenue" className="mt-3">
<RevenueChartCard data={revenue.data} loading={demo ? false : revenue.loading} title="Monthly revenue (12 months)" />
</TabsContent>
<TabsContent value="attendance" className="mt-3">
<AttendanceChartCard
data={counts.data}
loading={demo ? false : counts.loading}
title="Most active members (this month)"
limit={10}
/>
</TabsContent>
<TabsContent value="members" className="mt-3">
<div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
<StatCard
icon={UsersIcon}
label="Total"
value={summary.data?.totalCustomerCount ?? 0}
hint="All members"
/>
<StatCard
icon={UsersIcon}
tone="blue"
label="This Month"
value={summary.data?.thisMonthCustomerCount ?? 0}
hint="New joiners"
/>
<StatCard
icon={UsersIcon}
tone="amber"
label="Last Month"
value={summary.data?.lastMonthCustomerCount ?? 0}
hint="Previous period"
/>
<StatCard
icon={TrendingUpIcon}
tone="green"
label="Growth"
value={`${(summary.data?.customerGrowthPercentage ?? 0).toFixed(1)}%`}
hint="Month over month"
/>
</div>
</TabsContent>
<TabsContent value="profit-loss" className="mt-3">
<ProfitLossView demo={demo} />
</TabsContent>
</Tabs>
</div>
)
}
export { ReportsView }