Files
fitaiProto/apps/admin/src/components/reports/UserReport.tsx
T
2026-03-19 03:37:15 +01:00

137 lines
4.1 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { UserReport as UserReportType } from "@fitai/shared";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { WeeklyCheckInsCard } from "./WeeklyCheckInsCard";
import { NutritionSummaryCard } from "./NutritionSummaryCard";
import { HydrationSummaryCard } from "./HydrationSummaryCard";
import { GoalsSummaryCard } from "./GoalsSummaryCard";
import { RecommendationsCard } from "./RecommendationsCard";
import { Button } from "@/components/ui/button";
import { Download } from "lucide-react";
interface UserReportProps {
userId: string;
startDate: string;
endDate: string;
}
export function UserReport({ userId, startDate, endDate }: UserReportProps) {
const [report, setReport] = useState<UserReportType | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetchReport();
}, [userId, startDate, endDate]);
const fetchReport = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(
`/api/reports/user/${userId}?startDate=${startDate}&endDate=${endDate}`,
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || "Failed to fetch report");
}
const data = await response.json();
setReport(data);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to load report");
console.error("Report fetch error:", err);
} finally {
setLoading(false);
}
};
const handleExportPDF = () => {
if (!report) return;
const filename = `FitAI_Report_${report.user.firstName}_${report.user.lastName}_${startDate}_${endDate}.pdf`;
const url = `/api/reports/user/${userId}?startDate=${startDate}&endDate=${endDate}&format=pdf`;
// Open in new tab to trigger download
window.open(url, "_blank");
};
if (loading) {
return (
<Card>
<CardContent className="flex items-center justify-center h-64">
<div className="text-lg text-gray-600">Loading report...</div>
</CardContent>
</Card>
);
}
if (error) {
return (
<Card>
<CardContent className="flex items-center justify-center h-64">
<div className="text-lg text-red-600">{error}</div>
</CardContent>
</Card>
);
}
if (!report) {
return (
<Card>
<CardContent className="flex items-center justify-center h-64">
<div className="text-lg text-gray-600">No report data available</div>
</CardContent>
</Card>
);
}
return (
<div className="space-y-6">
{/* Report Header */}
<Card>
<CardHeader>
<div className="flex justify-between items-center">
<div>
<CardTitle className="text-2xl">
{report.user.firstName} {report.user.lastName}
</CardTitle>
<p className="text-sm text-gray-600 mt-1">
{report.user.email} • {report.client?.membershipType || "N/A"}{" "}
Member
</p>
<p className="text-xs text-gray-500 mt-1">
Report Period: {report.reportPeriod.startDate} to{" "}
{report.reportPeriod.endDate}
</p>
</div>
<Button onClick={handleExportPDF} variant="default">
<Download className="w-4 h-4 mr-2" />
Export PDF
</Button>
</div>
</CardHeader>
</Card>
{/* Report Sections */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<WeeklyCheckInsCard weeklyCheckIns={report.weeklyCheckIns} />
<NutritionSummaryCard nutrition={report.nutrition} />
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<HydrationSummaryCard hydration={report.hydration} />
<GoalsSummaryCard goals={report.goals} />
</div>
<div className="grid grid-cols-1 gap-6">
<RecommendationsCard recommendations={report.recommendations} />
</div>
</div>
);
}