58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
import { Button } from "@xtablo/ui/components/button";
|
|
import { MenuIcon } from "lucide-react";
|
|
import { useEffect, useState } from "react";
|
|
import { Outlet } from "react-router-dom";
|
|
import { twMerge } from "tailwind-merge";
|
|
import { SideNavigation } from "./NavigationBar";
|
|
import { OnboardingModal } from "./OnboardingModal";
|
|
|
|
const ONBOARDING_STORAGE_KEY = "xtablo-onboarding-completed";
|
|
|
|
export function Layout() {
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
|
const [showOnboarding, setShowOnboarding] = useState(false);
|
|
|
|
useEffect(() => {
|
|
// Check if user has completed onboarding
|
|
const hasCompletedOnboarding = localStorage.getItem(ONBOARDING_STORAGE_KEY);
|
|
if (!hasCompletedOnboarding) {
|
|
setShowOnboarding(true);
|
|
}
|
|
}, []);
|
|
|
|
const handleOnboardingComplete = () => {
|
|
localStorage.setItem(ONBOARDING_STORAGE_KEY, "true");
|
|
setShowOnboarding(false);
|
|
};
|
|
|
|
return (
|
|
<div className="flex h-screen">
|
|
<OnboardingModal open={showOnboarding} onComplete={handleOnboardingComplete} />
|
|
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className={twMerge(
|
|
"fixed z-50 md:hidden",
|
|
isMobileMenuOpen ? "top-2 left-55" : "top-2 left-4"
|
|
)}
|
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
|
>
|
|
<MenuIcon className="h-6 w-6" />
|
|
</Button>
|
|
|
|
<div
|
|
className={twMerge(
|
|
"fixed md:relative transition-all duration-300 z-40",
|
|
isMobileMenuOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"
|
|
)}
|
|
>
|
|
<SideNavigation isMobileMenuOpen={isMobileMenuOpen} />
|
|
</div>
|
|
|
|
<main className="flex-1 overflow-auto">
|
|
<Outlet />
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|