From 365b7f5bdd04be3d3289a66f80fcf031c1d59b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ama=C3=ABl=20Kesteman?= Date: Thu, 8 Jan 2026 14:53:12 +0100 Subject: [PATCH] =?UTF-8?q?Feat:=20D=C3=A9placement=20stats=20athl=C3=A8te?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front_end/src/components/StatsAthlete.tsx | 94 +++++++++++++++++++++++ front_end/src/components/object/user.tsx | 12 ++- 2 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 front_end/src/components/StatsAthlete.tsx diff --git a/front_end/src/components/StatsAthlete.tsx b/front_end/src/components/StatsAthlete.tsx new file mode 100644 index 0000000..e2f136f --- /dev/null +++ b/front_end/src/components/StatsAthlete.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import { Athlete, Session } from "../classes"; +import { calculStatsAthlete, niveauAlerte, StatsAthlete } from "../utils/athleteUtils" + +interface AthleteStatsProps { + athlete: Athlete; + sessions: Session[]; +} + +function StatAthlete({ athlete, sessions }: AthleteStatsProps) { + const [dateDebut, setDateDebut] = React.useState(new Date()); + const [dateFin, setDateFin] = React.useState(new Date()); + const [seuilCritique, setSeuilCritique] = React.useState(0); + const [seuilMax, setSeuilMax] = React.useState(0); + const [stats, setStats] = React.useState(null); + + const dateToDatetimeLocal = (date: Date) => { + const pad = (n: number) => n.toString().padStart(2, "0"); + return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`; + }; + + const handleCalculerStats = () => { + const statsCalculees = calculStatsAthlete(sessions, athlete, dateDebut, dateFin); + setStats(statsCalculees); + }; + + return ( +
+ + + + + + + + + + + {stats && ( +
+

Statistiques de {athlete.nom}

+

Nombre total de sessions : {stats.nbSessions}

+

Sessions par semaine : {stats.nbSessionsPerWeek.toFixed(2)}

+

Statut : {niveauAlerte(stats, seuilCritique, seuilMax)}

+ + {stats.distributions.size > 0 && ( + <> +

Distribution des activités :

+
    + {Array.from(stats.distributions.entries()).map(([nomActivite, count]) => ( +
  • + {nomActivite} : {count} session(s) +
  • + ))} +
+ + )} +
+ )} +
+ ); +} + +export default StatAthlete; \ No newline at end of file diff --git a/front_end/src/components/object/user.tsx b/front_end/src/components/object/user.tsx index 6b73283..c8efdf4 100644 --- a/front_end/src/components/object/user.tsx +++ b/front_end/src/components/object/user.tsx @@ -8,7 +8,7 @@ import {delay} from "../../requetes"; import CreateActivite from '../createActivite'; import { useLocalData } from '../../context/useLocalData'; import ObjectSession from './session'; - +import StatAthlete from '../StatsAthlete'; type Props = { admin?:Admin|null; @@ -115,12 +115,16 @@ function ObjectUser({admin=null,athlete=null,coach=null}:Props){ {user.sessions.map((session,index)=>( ))} - + {athlete !== null && ( +
+ +
+ )} - } - + } + ) }