"use client"; import { useEffect, useRef, useState } from "react"; import { useRouter } from "next/navigation"; import { useAuthStore } from "@/stores/authStore"; import { Space, useSpaceStore } from "@/stores/spaceStore"; import Navbar from "@/components/Navbar"; import Sidebar from "@/components/Sidebar"; import SpaceSettingsModal from "@/components/SpaceSettingsModal"; import apiClient from "@/lib/apiClient"; export default function DashboardLayout({ children }: { children: React.ReactNode }) { const router = useRouter(); const ensureInitialized = useAuthStore((s) => s.ensureInitialized); const fetchSpaces = useSpaceStore((s) => s.fetchSpaces); const currentSpace = useSpaceStore((s) => s.currentSpace!); const [authChecked, setAuthChecked] = useState(false); const [showSidebar, setShowSidebar] = useState(false); const navbarRef = useRef(null); const [navbarHeight, setNavbarHeight] = useState(56); const [showCreateCategoryModal, setShowCreateCategoryModal] = useState(false); const [showSpaceSettingsModal, setShowSpaceSettingsModal] = useState(false); useEffect(() => { const theme = localStorage.getItem("theme") === "dark" ? "dark" : "light"; document.documentElement.setAttribute("data-bs-theme", theme); ensureInitialized().then(() => { if (!useAuthStore.getState().user) { router.replace("/login"); } else { setAuthChecked(true); fetchSpaces(); } }); }, []); useEffect(() => { const el = navbarRef.current; if (!el) return; setNavbarHeight(el.offsetHeight); const ro = new ResizeObserver(() => setNavbarHeight(el.offsetHeight)); ro.observe(el); return () => ro.disconnect(); }, [authChecked]); if (!authChecked) { return (
Loading…
); } function handleCreateCategory(name: string) { apiClient.post(`/api/v1/spaces/${currentSpace?.id}/categories`, { name }).then(() => { useSpaceStore.getState().fetchCategories(currentSpace?.id || ""); }); } function handleSpaceSaved(_updatedSpace: Space) { useSpaceStore.getState().fetchSpaces(); setShowSpaceSettingsModal(false); } function handleSpaceDeleted() { useSpaceStore.getState().fetchSpaces(); setShowSpaceSettingsModal(false); } return ( <>
setShowSidebar(false)} navbarHeight={navbarHeight} onOpenCreateCategory={() => setShowCreateCategoryModal(true)} onOpenSpaceSettings={() => setShowSpaceSettingsModal(true)} />
{children}
{showCreateCategoryModal && ( setShowCreateCategoryModal(false)} onSave={(name) => { handleCreateCategory(name); setShowCreateCategoryModal(false); }} /> )} {showSpaceSettingsModal && currentSpace && ( setShowSpaceSettingsModal(false)} onSaved={handleSpaceSaved} onDeleted={handleSpaceDeleted} /> )} ); } function CreateCategoryModal({ onClose, onSave }: { onClose: () => void; onSave: (name: string) => void }) { const [categoryName, setCategoryName] = useState(""); function handleKeyDown(e: React.KeyboardEvent) { if (e.key === "Enter") onSave(categoryName); } return (
e.target === e.currentTarget && onClose()} >
Create Category
setCategoryName(e.target.value)} onKeyDown={handleKeyDown} autoFocus />
); }