111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
"use client";
|
|
|
|
import { WeeklyCheckInStats } from "@fitai/shared";
|
|
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
|
import {
|
|
BarChart,
|
|
Bar,
|
|
XAxis,
|
|
YAxis,
|
|
CartesianGrid,
|
|
Tooltip,
|
|
Legend,
|
|
ResponsiveContainer,
|
|
} from "recharts";
|
|
|
|
interface WeeklyCheckInsCardProps {
|
|
weeklyCheckIns: WeeklyCheckInStats[];
|
|
}
|
|
|
|
export function WeeklyCheckInsCard({
|
|
weeklyCheckIns,
|
|
}: WeeklyCheckInsCardProps) {
|
|
const totalCheckIns = weeklyCheckIns.reduce(
|
|
(sum, week) => sum + week.totalCheckIns,
|
|
0,
|
|
);
|
|
const totalTimeMinutes = weeklyCheckIns.reduce(
|
|
(sum, week) => sum + week.totalTimeMinutes,
|
|
0,
|
|
);
|
|
const avgTimeMinutes =
|
|
totalCheckIns > 0 ? Math.round(totalTimeMinutes / totalCheckIns) : 0;
|
|
|
|
const chartData = weeklyCheckIns.map((week) => ({
|
|
week: week.weekStart,
|
|
checkIns: week.totalCheckIns,
|
|
timeMinutes: week.totalTimeMinutes,
|
|
}));
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Weekly Check-ins</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-blue-600">
|
|
{totalCheckIns}
|
|
</div>
|
|
<div className="text-xs text-gray-600">Total Check-ins</div>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-green-600">
|
|
{Math.floor(totalTimeMinutes / 60)}h {totalTimeMinutes % 60}m
|
|
</div>
|
|
<div className="text-xs text-gray-600">Total Time</div>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-purple-600">
|
|
{avgTimeMinutes}m
|
|
</div>
|
|
<div className="text-xs text-gray-600">Avg Duration</div>
|
|
</div>
|
|
</div>
|
|
|
|
{chartData.length > 0 ? (
|
|
<div className="h-64">
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<BarChart data={chartData}>
|
|
<CartesianGrid strokeDasharray="3 3" />
|
|
<XAxis dataKey="week" />
|
|
<YAxis />
|
|
<Tooltip />
|
|
<Legend />
|
|
<Bar dataKey="checkIns" fill="#3c82e6" name="Check-ins" />
|
|
<Bar dataKey="timeMinutes" fill="#10b981" name="Minutes" />
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
) : (
|
|
<div className="h-64 flex items-center justify-center text-gray-500">
|
|
No check-in data available
|
|
</div>
|
|
)}
|
|
|
|
{weeklyCheckIns.length > 0 && (
|
|
<div className="space-y-2">
|
|
<h4 className="text-sm font-semibold">Weekly Breakdown</h4>
|
|
<div className="space-y-1">
|
|
{weeklyCheckIns.slice(-4).map((week) => (
|
|
<div
|
|
key={week.weekStart}
|
|
className="flex justify-between items-center text-sm"
|
|
>
|
|
<span className="text-gray-600">
|
|
{week.weekStart} - {week.weekEnd}
|
|
</span>
|
|
<span className="font-medium">
|
|
{week.totalCheckIns} check-ins • {week.totalTimeMinutes} min
|
|
</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|