+
+
+ {STATUS_LABELS[wo.status] || wo.status}
+
+ {wo.overdue && (
+
+ En retard · {formatDate(wo.due_date)}
+
+ )}
+ {PRIORITY_LABELS[wo.priority]}
+
+
+ {wo.title}
+
+ {wo.client_name}
+ {wo.equipment_name && · {wo.equipment_name}}
+
+ {wo.description && (
+ {wo.description}
+ )}
+
+ {(wo.client_address || wo.client_phone) && (
+
+ )}
+
+ {noteOpen && (
+
+ )}
+ {noteSaved && (
+ Note ajoutée au journal ✓
+ )}
+
+
+ {(wo.status === 'open' || wo.status === 'assigned') && (
+
+ )}
+ {wo.status === 'in_progress' && (
+
+ )}
+ {done && (
+
+ )}
+ {!noteOpen && (
+
+ )}
+
+ Détails →
+
+
+
+ );
+}
+
+export default function Journee() {
+ const [data, setData] = useState(null);
+ const [loadError, setLoadError] = useState('');
+ const [actionError, setActionError] = useState('');
+
+ const latest = useRef(0);
+
+ const load = useCallback(async () => {
+ const mine = ++latest.current;
+ try {
+ const res = await axios.get('/api/work-orders/my-day', { params: { date: localDate(), tz: timeZone() }, timeout: 15000 });
+ if (mine !== latest.current) return; // a newer refresh already answered
+ setData(res.data);
+ setLoadError('');
+ } catch (err) {
+ if (mine !== latest.current) return;
+ setLoadError(err.response?.data?.error
+ || (err.request ? 'Connexion impossible : vérifiez votre réseau puis actualisez' : 'Impossible de charger votre journée'));
+ }
+ }, []);
+
+ useEffect(() => { load(); }, [load]);
+ // A phone keeps this tab alive overnight and between jobs: refresh on return so the
+ // day (and the "En retard" flags) never stay on yesterday.
+ useEffect(() => {
+ const onVisible = () => { if (document.visibilityState === 'visible') load(); };
+ document.addEventListener('visibilitychange', onVisible);
+ return () => document.removeEventListener('visibilitychange', onVisible);
+ }, [load]);
+ // Tells the phone landing redirect (App.jsx) that this session already started here.
+ useEffect(() => { try { sessionStorage.setItem('journee-landed', '1'); } catch { /* ignore */ } }, []);
+
+ const handleError = (msg) => { setActionError(msg); load(); };
+ const onChanged = async () => { setActionError(''); await load(); };
+
+ const orders = data?.workOrders || [];
+ const todo = orders.filter(w => w.status !== 'done');
+ const finished = orders.filter(w => w.status === 'done');
+ const today = new Date().toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long' });
+
+ return (
+
+
+
+ {(loadError || actionError) && (
+
+ {loadError || actionError}
+
+ )}
+
+ {!data && !loadError &&
Chargement…
}
+
+ {data && orders.length === 0 && (
+
+
🎉
+
Rien de prévu pour aujourd'hui.
+
+ Voir tous les bons de service
+
+
+ )}
+
+ {todo.length > 0 && (
+ <>
+
À faire · {todo.length}
+
+ >
+ )}
+
+ {finished.length > 0 && (
+ <>
+
Terminés aujourd'hui · {finished.length}
+
+ {finished.map(wo => )}
+
+ >
+ )}
+
+ );
+}