All checks were successful
Deploy to Netlify / Deploy to Netlify (push) Successful in 1m51s
172 lines
5.5 KiB
TypeScript
172 lines
5.5 KiB
TypeScript
import {
|
|
PolarAngleAxis,
|
|
PolarGrid,
|
|
PolarRadiusAxis,
|
|
Radar,
|
|
RadarChart,
|
|
} from "recharts";
|
|
import { useAverages, useGrades, type User } from "~/lib/api";
|
|
import { ChartContainer, ChartTooltip, ChartTooltipContent } from "../ui/chart";
|
|
import { Award } from "lucide-react";
|
|
import { useState } from "react";
|
|
import { Tabs, TabsList, tabsStyle, TabsTrigger } from "../ui/tabs";
|
|
import AverageChart from "./average-chart";
|
|
import GradesChart from "./grades-chart";
|
|
|
|
const periods = [
|
|
{
|
|
id: "YEAR",
|
|
label: "Cette année",
|
|
},
|
|
{
|
|
id: "TRIMESTER",
|
|
label: "Ce trimestre",
|
|
},
|
|
{
|
|
id: "MONTH",
|
|
label: "Ce mois",
|
|
},
|
|
];
|
|
|
|
export default function GradesPage({ user }: { user: User }) {
|
|
const [period, setPeriod] = useState(periods[0].id);
|
|
|
|
const { grades, averages, subjects, isLoading, isError } = useGrades(period);
|
|
const {
|
|
subjectAverages,
|
|
globalAverage,
|
|
isLoading: loading,
|
|
isError: error,
|
|
} = useAverages(period);
|
|
|
|
return (
|
|
<div className="space-y-6 pb-20 md:pb-0">
|
|
{/* Tabs */}
|
|
<Tabs
|
|
defaultValue={periods[0].id}
|
|
value={period}
|
|
onValueChange={setPeriod}
|
|
className="max-w-md w-full"
|
|
>
|
|
<TabsList className="w-full p-0 bg-background justify-start border-b rounded-none">
|
|
{periods.map((period) => (
|
|
<TabsTrigger
|
|
key={period.id}
|
|
value={period.id}
|
|
className={tabsStyle}
|
|
>
|
|
{period.label}
|
|
</TabsTrigger>
|
|
))}
|
|
</TabsList>
|
|
</Tabs>
|
|
|
|
{isNaN(globalAverage) ? (
|
|
<div className="text-center text-muted-foreground">
|
|
Aucune note disponible pour cette période.
|
|
</div>
|
|
) : isLoading || loading ? (
|
|
<div className="flex items-center justify-center h-64">
|
|
<span className="text-muted-foreground">Chargement...</span>
|
|
</div>
|
|
) : isError || error ? (
|
|
<div className="text-center text-red-500">
|
|
Une erreur est survenue lors de la récupération des données.
|
|
</div>
|
|
) : (
|
|
<>
|
|
{/* Global average */}
|
|
<div className="bg-muted/50 rounded-lg p-4 space-y-2">
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-xs md:text-sm font-medium text-muted-foreground">
|
|
Moyenne générale
|
|
</span>
|
|
<Award className="h-4 w-4 text-muted-foreground" />
|
|
</div>
|
|
<div className="text-xl md:text-2xl font-bold">
|
|
{globalAverage} / 20
|
|
</div>
|
|
</div>
|
|
|
|
{/* Charts - Mobile First Layout */}
|
|
<div className="space-y-8">
|
|
{/* Grade Trends */}
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h2 className="text-lg md:text-xl font-semibold">
|
|
Votre progression
|
|
</h2>
|
|
<p className="text-sm text-muted-foreground">
|
|
Suivez vos notes au fil du temps
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="bg-muted/50 rounded-lg py-4">
|
|
<GradesChart grades={grades} subjects={subjects} user={user} />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Grade Trends */}
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h2 className="text-lg md:text-xl font-semibold">
|
|
Vos moyennes par matière
|
|
</h2>
|
|
<p className="text-sm text-muted-foreground">
|
|
Comparez vos moyennes par matière
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="bg-muted/50 rounded-lg py-4">
|
|
<AverageChart
|
|
averages={averages}
|
|
subjects={subjects}
|
|
user={user}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Radar chart */}
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h2 className="text-lg md:text-xl font-semibold">
|
|
Vos points forts
|
|
</h2>
|
|
<p className="text-sm text-muted-foreground">
|
|
Visualisez vos performances par matière
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="bg-muted/50 rounded-lg py-4">
|
|
<ChartContainer
|
|
config={{}}
|
|
className="h-full w-full -ml-6 max-w-2xl"
|
|
>
|
|
<RadarChart
|
|
data={subjectAverages}
|
|
margin={{ top: 10, right: 10, bottom: 10, left: 10 }}
|
|
>
|
|
<PolarGrid />
|
|
<PolarAngleAxis dataKey="subject" />
|
|
<PolarRadiusAxis angle={90} domain={[0, 20]} />
|
|
<Radar
|
|
name="Moyenne"
|
|
dataKey="average"
|
|
stroke="var(--chart-2)"
|
|
fill="var(--chart-2)"
|
|
fillOpacity={0.3}
|
|
/>
|
|
<ChartTooltip content={<ChartTooltipContent />} />
|
|
</RadarChart>
|
|
</ChartContainer>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|