116 lines
3.4 KiB
TypeScript
116 lines
3.4 KiB
TypeScript
"use client";
|
|
|
|
import { UserGrowthChart } from "@/components/charts/UserGrowthChart";
|
|
import { MembershipDistributionChart } from "@/components/charts/MembershipDistributionChart";
|
|
import { RevenueChart } from "@/components/charts/RevenueChart";
|
|
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
|
import { useAnalytics } from "@/hooks/use-api";
|
|
|
|
interface AnalyticsDashboardProps {
|
|
gymId?: string;
|
|
}
|
|
|
|
export function AnalyticsDashboard({ gymId }: AnalyticsDashboardProps) {
|
|
const { data: analytics, isLoading } = useAnalytics(6, gymId);
|
|
|
|
const userGrowthData = analytics?.userGrowth ?? [];
|
|
const membershipData = analytics?.membershipDistribution ?? [];
|
|
const revenueData = analytics?.revenue ?? [];
|
|
|
|
const totalUsers =
|
|
userGrowthData.length > 0
|
|
? userGrowthData[userGrowthData.length - 1].value
|
|
: 0;
|
|
const totalRevenue = revenueData.reduce((sum, item) => sum + item.value, 0);
|
|
const activeMembers = membershipData.reduce(
|
|
(sum, item) => sum + item.value,
|
|
0,
|
|
);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="flex justify-center items-center h-64">
|
|
<div className="text-lg">Loading analytics...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6 w-full">
|
|
<h2 className="text-2xl font-bold">Analytics Dashboard</h2>
|
|
|
|
{/* Key Metrics */}
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
<Card>
|
|
<CardContent>
|
|
<div className="text-center">
|
|
<div className="text-3xl font-bold text-blue-600">
|
|
{totalUsers}
|
|
</div>
|
|
<div className="text-gray-600">Total Users</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardContent>
|
|
<div className="text-center">
|
|
<div className="text-3xl font-bold text-green-600">
|
|
${totalRevenue.toLocaleString()}
|
|
</div>
|
|
<div className="text-gray-600">Total Revenue</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardContent>
|
|
<div className="text-center">
|
|
<div className="text-3xl font-bold text-purple-600">
|
|
{activeMembers}
|
|
</div>
|
|
<div className="text-gray-600">Active Members</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* Charts */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-lg font-semibold">User Growth</h3>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<UserGrowthChart data={userGrowthData} />
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-lg font-semibold">Membership Distribution</h3>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<MembershipDistributionChart data={membershipData} />
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-lg font-semibold">Monthly Revenue</h3>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<RevenueChart
|
|
data={revenueData.map((item) => ({
|
|
category: item.label,
|
|
value: item.value,
|
|
color: item.color,
|
|
}))}
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|