import { useEffect, useMemo, useCallback } from "react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { RouterProvider } from "@tanstack/react-router"; import { ToastContainer } from "react-toastify"; import { useUserProfileStore, useUserStore, } from "./context/zustand-store/userStore"; import { makeRouter } from "./routes/routes"; import { useDarkMode } from "./hooks/useDarkMode"; import { ItemWithSubItems } from "./types/userPermissions"; import { useFetchProfile } from "./hooks/useFetchProfile"; import { getInspectionMenuItems } from "./screen/SideBar"; const versionNumber = "/src/version.txt"; import "./index.css"; import "react-toastify/dist/ReactToastify.css"; import { checkIsMobile } from "./utils/checkIsMobile"; const queryClient = new QueryClient(); function AppContent() { const auth = useUserStore((s) => s.auth); const { profile } = useUserProfileStore(); const { getProfile } = useFetchProfile(); useEffect(() => { if (auth && !profile) { getProfile(); } }, [auth, profile, getProfile]); return null; } export default function App() { const auth = useUserStore((s) => s.auth); const { profile } = useUserProfileStore(); const [isDark] = useDarkMode(); const menuItems: ItemWithSubItems[] = useMemo(() => { const userPermissions = profile?.permissions || []; const permissionsArray = Array.isArray(userPermissions) ? userPermissions.filter((p): p is string => typeof p === "string") : []; return getInspectionMenuItems(permissionsArray); }, [profile?.permissions]); const router = useMemo(() => { try { const newRouter = makeRouter(auth ?? null); if (!newRouter) { console.error("Router creation returned null"); return makeRouter(null); } return newRouter; } catch (error) { console.error("Router creation error:", error); try { return makeRouter(null); } catch (fallbackError) { console.error("Fallback router creation failed:", fallbackError); return null; } } }, [auth, menuItems]); const hardRefresh = useCallback(() => { const url = new URL(window.location.href); url.searchParams.set("refresh", Date.now().toString()); window.location.href = url.toString(); }, []); const runWhenIdle = useCallback((fn: () => void) => { const ric = (window as any).requestIdleCallback; if (typeof ric === "function") { ric(fn); } else { setTimeout(fn, 300); } }, []); useEffect(() => { let aborted = false; const controller = new AbortController(); const checkVersion = () => { if (document.visibilityState !== "visible") return; fetch(versionNumber + `?_=${Date.now()}`, { signal: controller.signal, cache: "no-store", }) .then((res) => res.text()) .then(async (txt) => { if (aborted) return; const latest = txt.trim(); const stored = localStorage.getItem("AppVersion"); if (latest && latest !== stored) { localStorage.setItem("AppVersion", latest); const clearAndReload = async () => { if ("caches" in window) { const names = await caches.keys(); for (const n of names) { await caches.delete(n).catch(() => undefined); } } setTimeout(hardRefresh, 200); }; runWhenIdle(clearAndReload); } }) .catch(() => {}); }; runWhenIdle(checkVersion); return () => { aborted = true; controller.abort(); }; }, [hardRefresh, runWhenIdle]); useEffect(() => { const url = new URL(window.location.href); if (url.searchParams.has("refresh")) { url.searchParams.delete("refresh"); window.history.replaceState( {}, document.title, url.pathname + url.search ); } }, []); if (!router) { return (