feat: Afficher la couleur des matières dans l'emploi du temps élève et parent
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled

L'admin pouvait attribuer une couleur à chaque matière, mais cette
couleur n'était utilisée que dans la vue admin de l'emploi du temps.
Les APIs élève et parent ne renvoyaient pas cette information, ce qui
donnait un affichage générique (gris/bleu) pour tous les créneaux.

L'API renvoie désormais subjectColor dans chaque créneau, et les vues
jour/semaine/widget/détails affichent la bordure colorée correspondante.
Le marqueur "Prochain cours" conserve sa priorité visuelle via une
surcharge CSS variable.
This commit is contained in:
2026-03-09 11:20:50 +01:00
parent bda63bd98c
commit 81e97c4f3b
27 changed files with 188 additions and 70 deletions

View File

@@ -0,0 +1,63 @@
import { browser } from '$app/environment';
const LAST_SYNC_KEY = 'classeo:schedule:lastSync';
let lastSyncValue = $state<string | null>(
browser ? localStorage.getItem(LAST_SYNC_KEY) : null
);
/**
* Vérifie si le navigateur est actuellement hors ligne.
*/
export function isOffline(): boolean {
if (!browser) return false;
return !navigator.onLine;
}
/**
* Enregistre la date de dernière synchronisation de l'EDT.
*/
export function recordSync(): void {
if (!browser) return;
const now = new Date().toISOString();
localStorage.setItem(LAST_SYNC_KEY, now);
lastSyncValue = now;
}
/**
* Récupère la date de dernière synchronisation de l'EDT (réactif via $state).
*/
export function getLastSyncDate(): string | null {
return lastSyncValue;
}
/**
* Pré-charge 30 jours d'EDT en cache Service Worker (7 passés + 23 futurs).
*
* Appelé en arrière-plan pour alimenter le cache offline (AC5).
* Les requêtes sont interceptées par le SW (NetworkFirst)
* et les réponses sont automatiquement mises en cache.
*/
export async function prefetchScheduleDays(
fetchFn: (date: string) => Promise<unknown>,
today: Date = new Date()
): Promise<void> {
const CONCURRENCY = 5;
const PAST_DAYS = 7;
const FUTURE_DAYS = 23;
const dates: string[] = [];
for (let i = -PAST_DAYS; i <= FUTURE_DAYS; i++) {
const date = new Date(today);
date.setDate(date.getDate() + i);
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
dates.push(`${y}-${m}-${d}`);
}
for (let i = 0; i < dates.length; i += CONCURRENCY) {
const batch = dates.slice(i, i + CONCURRENCY);
await Promise.allSettled(batch.map((dateStr) => fetchFn(dateStr)));
}
}