import { Outlet, useNavigate, useLocation } from "react-router-dom"; import { Sidebar } from "./Sidebar"; import { createContext, useContext, useState, useEffect } from "react"; import { Menu, X, Code2, Timer } from "lucide-react"; import { cn } from "@/lib/utils"; import { CanvasBackground } from "./CanvasBackground"; export const SidebarContext = createContext<{ isCollapsed: boolean; setIsCollapsed: (v: boolean) => void; isMobileOpen: boolean; setIsMobileOpen: (v: boolean) => void; }>({ isCollapsed: false, setIsCollapsed: () => {}, isMobileOpen: false, setIsMobileOpen: () => {} }); export const useSidebar = () => useContext(SidebarContext); export const AppLayout = () => { const [isCollapsed, setIsCollapsed] = useState(false); const [isMobileOpen, setIsMobileOpen] = useState(false); const navigate = useNavigate(); const location = useLocation(); const [timeLeft, setTimeLeft] = useState(null); useEffect(() => { const checkTimer = () => { if (!location.pathname.startsWith("/multirag")) { setTimeLeft(null); return; } const start = localStorage.getItem("multirag_session_start"); const duration = localStorage.getItem("multirag_session_duration"); if (start && duration) { const elapsed = Math.floor((Date.now() - parseInt(start)) / 1000); const remaining = parseInt(duration) - elapsed; if (remaining > 0) { setTimeLeft(remaining); } else { localStorage.removeItem("multirag_session_start"); localStorage.removeItem("multirag_session_duration"); localStorage.removeItem("multirag_thread_id"); setTimeLeft(null); window.dispatchEvent(new Event("storage")); navigate("/"); } } else { setTimeLeft(null); } }; checkTimer(); window.addEventListener("storage", checkTimer); const interval = setInterval(checkTimer, 1000); return () => { window.removeEventListener("storage", checkTimer); clearInterval(interval); }; }, [location.pathname, navigate]); const formatTime = (seconds: number) => { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${mins}:${secs < 10 ? "0" : ""}${secs}`; }; const isUrgent = timeLeft !== null && timeLeft <= 60; // Auto-collapse on smaller screens useEffect(() => { const handleResize = () => { if (window.innerWidth < 1024) { setIsCollapsed(true); } else { setIsCollapsed(false); setIsMobileOpen(false); } }; handleResize(); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, []); return (
{timeLeft !== null && (
{formatTime(timeLeft)}
)} {/* Mobile Header */}
{/* Logo — icon + text */}
ML Learner
{/* Spacer for symmetry */}
{/* Sidebar Overlay for Mobile */} {isMobileOpen && (
setIsMobileOpen(false)} /> )} {/* 3D WebGL Background Layer */} {/* Main content shifts using margin so it never overlaps or leaves a gap */}
); };