canina/frontend/application/app/ClientLayout.tsx
2026-08-06 23:15:25 +03:30

135 lines
5.1 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import Header from "../components/Header";
import Footer from "../components/Footer";
import { NetworkBanner } from "../components/NetworkBanner";
import { Toaster } from "sonner";
import { usePathname, useRouter } from 'next/navigation';
import CartDrawer from "../components/CartDrawer";
import LoginModal from "../components/LoginModal";
import AuthModal from "../components/AuthModal";
import B2BPortal from "../components/B2BPortal";
import { useUserStore } from "../lib/store/userStore";
import { useSettingsStore } from "../lib/store/settingsStore";
import { useUIStore } from "../lib/store/uiStore";
import MaintenancePage from "../components/MaintenancePage";
import { NavigationTarget } from "../lib/types";
export default function ClientLayout({ children }: { children: React.ReactNode }) {
const isCartOpen = useUIStore((state) => state.isCartOpen);
const isLoginModalOpen = useUIStore((state) => state.isLoginModalOpen);
const isB2BPortalOpen = useUIStore((state) => state.isB2BPortalOpen);
const advisorData = useUIStore((state) => state.advisorData);
const setCartOpen = useUIStore((state) => state.setCartOpen);
const setLoginModalOpen = useUIStore((state) => state.setLoginModalOpen);
const setB2BPortalOpen = useUIStore((state) => state.setB2BPortalOpen);
const clearAdvisorData = useUIStore((state) => state.clearAdvisorData);
const pathname = usePathname();
const router = useRouter();
const fetchProfile = useUserStore((state) => state.fetchProfile);
const role = useUserStore((state) => state.role);
const isAuthModalOpen = useUserStore((state) => state.isAuthModalOpen);
const setAuthModalOpen = useUserStore((state) => state.setAuthModalOpen);
const fetchSettings = useSettingsStore((state) => state.fetchSettings);
const getText = useSettingsStore((state) => state.getText);
useEffect(() => {
fetchSettings();
const token = localStorage.getItem('accessToken');
if (token) {
fetchProfile().catch(e => console.error("Auth init failed:", e));
} else {
useUserStore.getState().logout();
}
}, [fetchProfile, fetchSettings]);
// Check Maintenance Mode (Admin / Partner bypass)
const isMaintenanceMode = getText('MAINTENANCE_MODE', 'false') === 'true' || getText('maintenance_mode', 'false') === 'true';
const isAdmin = role === 'User_Partner' || (typeof window !== 'undefined' && Boolean(localStorage.getItem('adminToken')));
if (isMaintenanceMode && !isAdmin) {
return <MaintenancePage />;
}
// Derived currentView from pathname for Header
let currentView = "home";
if (pathname?.includes("/shop")) currentView = "shop";
if (pathname?.includes("/wiki")) currentView = "wiki";
if (pathname?.includes("/profile")) currentView = "profile";
if (pathname?.includes("/checkout")) currentView = "checkout";
if (pathname?.includes("/dashboard")) currentView = "user-dashboard";
const handleNavigate = (v: NavigationTarget) => {
if (typeof v === 'object' && v !== null) {
if (v.view === 'profile') router.push('/profile');
if (v.view === 'order-tracking') router.push('/order/tracking');
if (v.view === 'home') router.push('/');
} else if (typeof v === 'string') {
if (v === 'home') router.push('/');
else if (v === 'user-dashboard') router.push('/dashboard');
else router.push(`/${v}`);
}
};
const navigateToShop = (category: string = "all", search: string = "") => {
const params = new URLSearchParams();
if (category && category !== "all") params.set("category", category);
if (search) params.set("search", search);
const newUrl = params.toString() ? `/shop?${params.toString()}` : "/shop";
router.push(newUrl);
};
const handleSearch = (q: string) => {
router.push(`/search?q=${encodeURIComponent(q)}`);
};
return (
<>
<NetworkBanner />
<Header
onNavigate={handleNavigate}
onShopNavigate={navigateToShop}
currentView={currentView}
onCartOpen={() => setCartOpen(true)}
onSearch={handleSearch}
onB2BOpen={() => setB2BPortalOpen(true)}
/>
<main className="min-h-screen">
{children}
</main>
<Footer onNavigate={handleNavigate} onShopNavigate={navigateToShop} onB2BOpen={() => setB2BPortalOpen(true)} />
{isB2BPortalOpen && <B2BPortal onClose={() => setB2BPortalOpen(false)} />}
<CartDrawer
isOpen={isCartOpen}
onClose={() => setCartOpen(false)}
onCheckout={() => { setCartOpen(false); router.push('/checkout'); }}
onShopNavigate={navigateToShop}
/>
<LoginModal
isOpen={isLoginModalOpen}
onClose={() => {
setLoginModalOpen(false);
clearAdvisorData();
}}
onLogin={() => {
setLoginModalOpen(false);
}}
petName={advisorData?.name as string | undefined}
isAdvisorContext={!!advisorData}
/>
<AuthModal
isOpen={isAuthModalOpen}
onClose={() => setAuthModalOpen(false)}
/>
<Toaster position="top-center" expand={true} richColors closeButton />
</>
);
}