// Rôle : point d'entrée React, assemble données, routes, shell et overlays. import React, { useCallback, useEffect, useState } from "react"; import { createRoot } from "react-dom/client"; import "./styles/main.scss"; import { AppOverlays } from "./components/AppOverlays.jsx"; import { Shell } from "./components/Shell.jsx"; import { ToolboxDrawer } from "./features/toolboxes/ToolboxPages.jsx"; import { useIndexedToolboxes } from "./features/toolboxes/storage/useIndexedToolboxes.js"; import { useToolboxActions } from "./features/toolboxes/useToolboxActions.js"; import { useAppData } from "./hooks/useAppData.js"; import { useGameFilters } from "./hooks/useGameFilters.js"; import { useTimerAlerts } from "./hooks/useTimerAlerts.js"; import { RouteContent } from "./router/RouteContent.jsx"; import { useHashRoute } from "./router/hashRouter.js"; import { normalizeTimerData } from "./features/toolboxes/storage/toolboxStorage.js"; function App() { const route = useHashRoute(); const { siteContent, siteContentError, games, gamesError, mhwilds, diablo4 } = useAppData(route); const [filters, setFilters] = useGameFilters(); const [confirmModal, setConfirmModal] = useState(null); const [createModal, setCreateModal] = useState(null); const [linkModalGameId, setLinkModalGameId] = useState(""); const [drawerGameId, setDrawerGameId] = useState(""); const [image, setImage] = useState(null); const [notifications, setNotifications] = useState([]); const [storageError, setStorageError] = useState(""); const store = useIndexedToolboxes((message) => setStorageError(message)); const notify = useCallback((message) => { setNotifications((current) => [ { id: `${Date.now()}-${Math.random().toString(36).slice(2)}`, message }, ...current ].slice(0, 5)); }, []); const dismissNotification = useCallback((notificationId) => { setNotifications((current) => current.filter((notification) => notification.id !== notificationId)); }, []); useEffect(() => { function handleNotification(event) { if (event.detail?.message) notify(event.detail.message); } window.addEventListener("sokkog:notify", handleNotification); return () => window.removeEventListener("sokkog:notify", handleNotification); }, [notify]); const t = (key, { capitalize = false } = {}) => { const value = mhwilds.translations[key] || String(key || "").replace(/_/g, " "); return capitalize ? value.charAt(0).toUpperCase() + value.slice(1) : value; }; const getGame = (gameId) => games.find((item) => item.id === gameId); const getToolboxGameId = (toolbox) => Object.entries(store.links).find(([, toolboxId]) => toolboxId === toolbox?.id)?.[0] || ""; const getToolboxGame = (toolbox) => getGame(getToolboxGameId(toolbox)); const actions = useToolboxActions({ store, notify, setCreateModal, setConfirmModal, setLinkModalGameId, setDrawerGameId, setImage }); useTimerAlerts({ toolboxes: store.toolboxes, moduleData: store.moduleData, links: store.links, route, drawerGameId, normalizeTimerData, textContent: siteContent?.toolboxes?.modules?.timer, notify }); if (!siteContent) { return ( Contenu indisponible {siteContentError || "Chargement du contenu..."} ); } return ( {drawerGameId && ( )} ); } createRoot(document.querySelector("#app")).render();
{siteContentError || "Chargement du contenu..."}