REBELLION2002's picture
Deploy live TraffiX app (fix/live-container-ci e8a6317, showcase network omitted)
ec5ee81 verified
Raw History Blame Contribute Delete
2.4 kB
// 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" },
];