// Root app & router function App() { const [page, setPage] = useState(() => { const h = window.location.hash.replace("#", ""); return ["dashboard","alerts","team","rules","instructions","tasks","config"].includes(h) ? h : "dashboard"; }); const [alerts, setAlerts] = useState(ALERTS); const { push: pushToast, node: toastNode } = useToasts(); const dismissAlert = (id) => { setAlerts((a) => a.map(x => x.id === id ? { ...x, status: "dismissed" } : x)); pushToast("Алерт скрыт", "info"); }; useEffect(() => { const onHash = () => { const h = window.location.hash.replace("#", ""); if (["dashboard","alerts","team","rules","instructions","tasks","config"].includes(h)) setPage(h); }; window.addEventListener("hashchange", onHash); return () => window.removeEventListener("hashchange", onHash); }, []); const nav = (p) => { setPage(p); window.location.hash = p; window.scrollTo({ top: 0, behavior: "instant" }); }; const activeAlerts = alerts.filter(a => a.status === "active"); const criticalCount = activeAlerts.filter(a => a.severity === "critical").length; let content; switch (page) { case "dashboard": content = ; break; case "alerts": content = ; break; case "team": content = ; break; case "rules": content = ; break; case "instructions": content = ; break; case "tasks": content = ; break; case "config": content = ; break; default: content = ; } return (
{page === "dashboard" && }
{content}
{toastNode}
); } // Запуск React теперь в boot.jsx — он сначала fetch'ит данные с backend, // потом монтирует . Если backend недоступен — остаются mock-данные // из data.jsx (UI всегда жив). Раньше было: // const root = ReactDOM.createRoot(document.getElementById("app")); // root.render();