Écran référent : vraie page responsive, référent correctement calculé

Deux bugs sur l'écran référent (/mobile-referent) :

- Il était resté à l'étape maquette (`PhoneFrame`/`DesignNote`, cadre de
  téléphone à taille fixe) alors que la vue bénévole avait déjà été
  convertie en vraie page responsive. Repli sur `positions.data[0]` en
  l'absence de poste géré par le compte connecté : un référent qui
  n'est encore désigné sur aucun poste se voyait quand même affiché
  comme référent du premier poste de l'édition (« Accueil artistes »
  dans les données de démo) au lieu de voir qu'il n'en a aucun.

Réécriture de `MobileLeadPage.tsx` en page responsive (mobile d'abord,
`sm:` pour l'élargissement, comme `MobileVolunteerPage.tsx`) : plus de
maquette de téléphone, une carte par poste réellement géré
(`Position.lead_account_id === account.id`, sans repli), créneau en
cours ou à venir calculé sur l'heure réelle (nouveau hook partagé
`useNowMinutes`, extrait de la vue bénévole), équipe affectée avec
pointage présent/absent (toujours local à l'écran : le pointage sur
site reste hors périmètre, CLAUDE.md §5). État vide explicite si le
compte n'est référent d'aucun poste.

`PhoneFrame`/`DesignNote` n'avaient plus d'autre utilisateur : supprimés
avec leurs clés i18n devenues mortes.

Non inclus dans ce commit (édités en parallèle par l'utilisateur, laissés
en l'état) : backend/app/seed.py, frontend/tailwind.config.js.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
This commit is contained in:
AdamThomas
2026-09-15 23:42:48 +02:00
co-authored by Claude Sonnet 5
parent a78aad58e2
commit 9e0be07726
5 changed files with 171 additions and 162 deletions
+3 -15
View File
@@ -1,9 +1,10 @@
import { Fragment, useEffect, useMemo, useState } from 'react';
import { Fragment, useMemo } from 'react';
import { useVolunteer, useVolunteerPlanning } from '@/api/hooks';
import { useAuth } from '@/auth/auth-context';
import { ErrorNote, Loading } from '@/components/state';
import { hourRangeLabel, longDayLabel, naiveMinutes, nowNaiveMinutes } from '@/lib/time';
import { hourRangeLabel, longDayLabel, naiveMinutes } from '@/lib/time';
import { useNowMinutes } from '@/lib/useNowMinutes';
import { t } from '@/i18n';
// Page réellement consultée par le bénévole (accueil de son rôle, cf.
@@ -15,19 +16,6 @@ import { t } from '@/i18n';
// de gris clair, lisibilité plein soleil), cibles tactiles ≥ 52 px de haut,
// une seule action par créneau.
// Rafraîchit « maintenant » assez souvent pour que le repère bouge de façon
// perceptible sans re-rendre à outrance.
const NOW_REFRESH_MS = 30_000;
function useNowMinutes(): number {
const [minutes, setMinutes] = useState(() => nowNaiveMinutes());
useEffect(() => {
const id = setInterval(() => setMinutes(nowNaiveMinutes()), NOW_REFRESH_MS);
return () => clearInterval(id);
}, []);
return minutes;
}
function NowLine() {
return (
<div className="flex items-center gap-2 px-1" aria-hidden="true">