Architecture Frontend
Pourquoi calculer le statut côté client ?
- Le problème d'une base de données : Si on stockait le statut "En retard" dans SQLite, il faudrait un script de fond (Cron Job) tournant chaque minute pour mettre à jour la base dès qu'une date limite est franchie.
- La solution React : La base de données ne fournit que des faits immuables (la date de rendu requise et l'existence ou non d'une soumission).
- Évaluation à la volée : C'est le navigateur de l'étudiant qui, au moment précis d'afficher la page, compare ces données avec son horloge actuelle. L'état est toujours garanti 100% exact et à jour.
/* Les données "brutes" fournies par l'API (Backend) */
const donneeServeur = {
id: 42,
nom: "SAE 301 - Développement",
date_rendu: "2023-12-01T23:59:00", // Le fait (Date limite)
rendu_id: null // Le fait (Travail non rendu)
};
// Le Frontend prend ces données et calcule le contexte
// en fonction de la variable d'environnement (new Date()).
React / frontend/src/App.jsx
L'algorithme de détermination
- Fonction Pure :
determinerStatut(sae) prend un objet en entrée et renvoie toujours le même résultat pour les mêmes conditions temporelles.
- Règle 1 (Priorité absolue) : Si un identifiant de rendu existe, la SAE est "Terminée" (Vert), peu importe les dates.
- Règle 2 (Tolérance) : Si aucune date limite n'est spécifiée par le professeur, elle reste perpétuellement "En cours".
- Règle 3 (Échéance) : On convertit la chaîne ISO de la BDD en un objet
Date() JavaScript pour le comparer mathématiquement (<) avec l'instant T. Si le délai est dépassé, c'est "En retard" (Rouge).
/* Algorithme d'évaluation des priorités */
const determinerStatut = (sae) => {
// 1. Validation de la soumission (Priorité Haute)
if (sae.rendu_id || (selectedRendu && selectedSae?.id === sae.id)) {
return { texte: 'Terminée', couleur: 'success' };
}
// 2. Gestion des SAE ouvertes sans deadline
if (!sae.date_rendu) {
return { texte: 'En cours', couleur: 'primary' };
}
// 3. Comparaison temporelle en temps réel
const isRetard = new Date(sae.date_rendu) < new Date();
if (isRetard) {
return { texte: 'En retard', couleur: 'danger' };
}
// 4. Par défaut (Date future, non rendu)
return { texte: 'En cours', couleur: 'primary' };
};
React / frontend/src/App.jsx
Connexion avec le système de filtre
- State Array : Les cases à cocher de l'interface ajoutent ou retirent des mots-clés dans un tableau
filtresStatut (ex: ['En cours', 'En retard']).
- Interception : Dans la fonction de préparation de la grille (
getSaesTriees), chaque SAE est passée dans la moulinette de determinerStatut.
- Inclusion : Si le texte du statut renvoyé est inclus dans les préférences de l'utilisateur, la SAE est affichée. Sinon, elle disparaît instantanément.
/* L'état React (Ce qui est coché par l'utilisateur) */
const [filtresStatut, setFiltresStatut] = useState(['En cours', 'En retard', 'Terminée']);
/* Application du filtre dans le pipeline de rendu */
const getSaesTriees = (listeASorter) => {
return [...listeASorter].filter(sae => {
// Les enseignants et admins voient tout
if (role !== 'etudiant') return true;
// On calcule le statut exact à cet instant
const statutCalcule = determinerStatut(sae).texte;
// On vérifie si ce statut fait partie des filtres actifs
return filtresStatut.includes(statutCalcule);
})
// ... enchaînement avec .sort() pour les dates
};
React / frontend/src/App.jsx
Rendu Visuel et Badges
- Déstructuration : La fonction de calcul renvoie un objet contenant le
texte exact à afficher et la couleur de la classe CSS.
- Template Literals : L'attribut
className de la balise HTML est construit dynamiquement (ex: badge-danger, badge-success) pour lier la logique JavaScript à la feuille de style (App.css).
{/* À l'intérieur du composant Map qui génère la grille */}
{getSaesTriees(saes).map(sae => {
// Appel de l'algorithme une seule fois par carte
const statut = determinerStatut(sae);
return (
{sae.classe_cible}
{/* Injection dynamique de la classe et du label */}
{statut.texte}
{sae.nom}
{/* ... */}
);
})}