File size: 2,399 Bytes
ec5ee81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// All data comes from the Python backend (supermaster API). Nothing talks to SUMO directly.
import { useEffect, useState } from "react";

export async function api(path, options = {}) {
  const headers = new Headers(options.headers || {});
  try {
    const token = sessionStorage.getItem("traffix-operator-token");
    if (token) headers.set("Authorization", `Bearer ${token}`);
  } catch { /* sessionStorage may be unavailable in private browser modes */ }
  if (options.body && !headers.has("Content-Type")) headers.set("Content-Type", "application/json");
  const res = await fetch(`/api${path}`, { ...options, headers });
  if (!res.ok) {
    const text = await res.text();
    let detail = text;
    try { detail = JSON.parse(text).detail || text; } catch { /* not JSON */ }
    if (typeof detail !== "string") detail = JSON.stringify(detail);   // FastAPI 422: a list of objects
    throw new Error(`${res.status} ${detail}`);
  }
  return res.json();
}

// Polls the live snapshot once per second.
export function useLive() {
  const [state, setState] = useState({ status: "idle" });
  useEffect(() => {
    let alive = true;
    const tick = async () => {
      try {
        const s = await api("/state");
        if (alive) setState(s);
      } catch {
        if (alive) setState({ status: "offline" });
      }
    };
    tick();
    const id = setInterval(tick, 1000);
    return () => { alive = false; clearInterval(id); };
  }, []);
  return state;
}

export function useOnce(path, deps = []) {
  const [data, setData] = useState(null);
  useEffect(() => {
    if (!path) { setData(null); return; }        // nothing to fetch yet
    api(path).then(setData).catch(() => setData(null));
  }, deps);
  return data;
}

export const PERSONAS = [
  { id: "pedestrian", path: "/pedestrian", name: "Ferjani", role: "Pedestrian" },
  { id: "car_driver", path: "/driver", name: "Faycel", role: "Car driver" },
  { id: "bus_passenger", path: "/passenger", name: "Mamadou", role: "Bus passenger" },
  { id: "bus_driver", path: "/bus-driver", name: "Hédi", role: "Bus driver" },
  { id: "emergency_crew", path: "/emergency", name: "Touhami", role: "Ambulance crew" },
  { id: "operator", path: "/operator", name: "Kamel", role: "Traffic operator" },
  { id: "analyst", path: "/analyst", name: "Tahani", role: "Incident analyst" },
];