import React, { Suspense, lazy, useEffect } from "react" import { Layout, Space, Button, Tag, Spin } from "antd" import { MenuFoldOutlined, MenuUnfoldOutlined, FullscreenOutlined, FullscreenExitOutlined, LeftOutlined, } from "@ant-design/icons" import { Routes, Route, Navigate, useLocation, useNavigate } from "react-router-dom" import { useTranslation } from "react-i18next" import { WindowControls } from "./WindowControls" import appLogo from "../assets/logoHD.svg" const loadHome = () => import("./Home") const loadStudentManager = () => import("./StudentManager") const loadSettings = () => import("./Settings") const loadReasonManager = () => import("./ReasonManager") const loadScoreManager = () => import("./ScoreManager") const loadAutoScoreManager = () => import("./AutoScoreManager") const loadLeaderboard = () => import("./Leaderboard") const loadSettlementHistory = () => import("./SettlementHistory") const loadRewardSettings = () => import("./RewardSettings") const loadBoardManager = () => import("./BoardManager") const loadPluginManager = () => import("./PluginManager") const Home = lazy(() => loadHome().then((m) => ({ default: m.Home }))) const StudentManager = lazy(() => loadStudentManager().then((m) => ({ default: m.StudentManager }))) const Settings = lazy(() => loadSettings().then((m) => ({ default: m.Settings }))) const ReasonManager = lazy(() => loadReasonManager().then((m) => ({ default: m.ReasonManager }))) const ScoreManager = lazy(() => loadScoreManager().then((m) => ({ default: m.ScoreManager }))) const AutoScoreManager = lazy(loadAutoScoreManager) const Leaderboard = lazy(() => loadLeaderboard().then((m) => ({ default: m.Leaderboard }))) const SettlementHistory = lazy(() => loadSettlementHistory().then((m) => ({ default: m.SettlementHistory })) ) const RewardSettings = lazy(() => loadRewardSettings().then((m) => ({ default: m.RewardSettings }))) const BoardManager = lazy(() => loadBoardManager().then((m) => ({ default: m.BoardManager }))) const PluginManager = lazy(() => loadPluginManager().then((m) => ({ default: m.PluginManager }))) const warmupRouteChunks = () => Promise.allSettled([ loadHome(), loadStudentManager(), loadSettings(), loadReasonManager(), loadScoreManager(), loadAutoScoreManager(), loadLeaderboard(), loadSettlementHistory(), loadRewardSettings(), loadBoardManager(), loadPluginManager(), ]) const { Content } = Layout interface ContentAreaProps { permission: "admin" | "points" | "view" hasAnyPassword: boolean onAuthClick: () => void onLogout: () => void showWindowControls: boolean isPortraitMode: boolean isMobileDevice: boolean sidebarCollapsed: boolean floatingExpand: boolean floatingExpanded: boolean onToggleSidebar: () => void immersiveMode: boolean isHomePage: boolean onToggleImmersiveMode: () => void showSidebarToggle?: boolean bottomInset?: number } export function ContentArea({ permission, hasAnyPassword, onAuthClick, onLogout, showWindowControls, isPortraitMode, isMobileDevice, sidebarCollapsed, floatingExpand, floatingExpanded, onToggleSidebar, immersiveMode, isHomePage, onToggleImmersiveMode, showSidebarToggle = true, bottomInset = 0, }: ContentAreaProps): React.JSX.Element { const { t } = useTranslation() const location = useLocation() const navigate = useNavigate() const isSubPage = location.pathname !== "/" && !location.pathname.startsWith("/home") const shouldAnimateSubPage = isPortraitMode && isSubPage const normalizedPath = location.pathname === "/" ? "/home" : location.pathname const isBoardPage = normalizedPath.startsWith("/boards") const isMobileHeaderMode = isPortraitMode && isMobileDevice && !immersiveMode const isPrimaryMobilePage = normalizedPath.startsWith("/home") || normalizedPath.startsWith("/settings") const showMobileBack = isMobileHeaderMode && !isPrimaryMobilePage const mobilePageTitle = (() => { if (normalizedPath.startsWith("/home")) return t("sidebar.home") if (normalizedPath.startsWith("/students")) return t("sidebar.students") if (normalizedPath.startsWith("/score")) return t("sidebar.score") if (normalizedPath.startsWith("/auto-score")) return t("sidebar.autoScore") if (normalizedPath.startsWith("/boards")) return t("sidebar.boards") if (normalizedPath.startsWith("/leaderboard")) return t("sidebar.leaderboard") if (normalizedPath.startsWith("/settlements")) return t("sidebar.settlements") if (normalizedPath.startsWith("/reasons")) return t("sidebar.reasons") if (normalizedPath.startsWith("/reward-settings")) return t("sidebar.rewardSettings") if (normalizedPath.startsWith("/plugins")) return t("sidebar.plugins") if (normalizedPath.startsWith("/settings")) return t("sidebar.settings") return "SecScore" })() const handleMobileBack = () => { if (window.history.length > 1) { navigate(-1) return } navigate("/settings") } useEffect(() => { let cancelled = false let timer: ReturnType | undefined const runWarmup = () => { if (cancelled) return warmupRouteChunks().catch(() => void 0) } if ("requestIdleCallback" in window) { ;(window as any).requestIdleCallback(runWarmup, { timeout: 1500 }) } else { timer = setTimeout(runWarmup, 300) } return () => { cancelled = true if (timer) clearTimeout(timer) } }, []) const permissionTag = ( {permission === "admin" ? t("permissions.admin") : permission === "points" ? t("permissions.points") : t("permissions.view")} ) return (
{isMobileHeaderMode ? (
{showMobileBack && (
) : ( !immersiveMode && showSidebarToggle && (
{immersiveMode && (
SecScore SecScore
)}
{(immersiveMode || (isHomePage && !isMobileDevice)) && ( )}
{showWindowControls && }
} >
} /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } />
) }