"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; import { useTheme } from "next-themes"; import { BookOpen, Calendar, Package, ChefHat, User, FolderOpen, ShoppingCart, Shield, Search, Compass, Menu, Sun, Moon, Monitor, Apple, LifeBuoy, Settings, LogOut } from "lucide-react"; import { cn } from "@/lib/utils"; import { Button, buttonVariants } from "@/components/ui/button"; import type { FeaturePrefs } from "@/lib/feature-prefs"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Sheet, SheetClose, SheetContent, SheetHeader, SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { NotificationBell } from "@/components/social/notification-bell"; import { MessagesNavLink } from "@/components/social/messages-nav-link"; import { authClient } from "@/lib/auth/client"; import { useTranslations } from "next-intl"; const NAV_ITEMS = [ { href: "/recipes", key: "recipes", icon: BookOpen, feature: null }, { href: "/explore", key: "explore", icon: Search, feature: null }, { href: "/collections", key: "collections", icon: FolderOpen, feature: "collections" }, { href: "/meal-plan", key: "mealPlan", icon: Calendar, feature: "mealPlan" }, { href: "/nutrition", key: "nutrition", icon: Apple, feature: "nutrition" }, { href: "/pantry", key: "pantry", icon: Package, feature: "pantry" }, { href: "/shopping-lists", key: "shopping", icon: ShoppingCart, feature: "shoppingLists" }, ] as const; export function Nav() { const pathname = usePathname(); const router = useRouter(); const { data: session } = authClient.useSession(); const isAdmin = (session?.user as { role?: string } | undefined)?.role === "admin"; const username = (session?.user as { username?: string } | undefined)?.username; const { theme, setTheme } = useTheme(); const t = useTranslations("nav"); // Defaults to "everything on" until the fetch resolves, matching the // backend default — avoids a flash of items disappearing on load for the // (much more common) case where a user hasn't hidden anything. const [featurePrefs, setFeaturePrefs] = useState({ nutrition: true, pantry: true, mealPlan: true, shoppingLists: true, collections: true, messages: true, }); useEffect(() => { function load() { fetch("/api/v1/users/me/feature-prefs") .then((res) => (res.ok ? res.json() : null)) .then((json) => { if (json?.data) setFeaturePrefs(json.data); }) .catch(() => {}); } load(); // Settings → Features saves on the same origin without a full nav // remount, so it fires this event to make the change visible immediately // rather than only on the next page load. window.addEventListener("epicure:feature-prefs-changed", load); return () => window.removeEventListener("epicure:feature-prefs-changed", load); }, []); const visibleNavItems = NAV_ITEMS.filter((item) => item.feature === null || featurePrefs[item.feature]); const THEME_OPTIONS = [ { value: "light", icon: Sun, label: t("lightMode") }, { value: "dark", icon: Moon, label: t("darkMode") }, { value: "system", icon: Monitor, label: t("systemMode") }, ] as const; return (
} > {t("menu")} Epicure Epicure
{featurePrefs.messages && } {username && ( {t("viewProfile")} )} {t("settings")} {t("support")}
{THEME_OPTIONS.map(({ value, icon: Icon, label }) => ( ))}
{isAdmin && ( <> {t("admin")} )} { void authClient.signOut({ fetchOptions: { onSuccess: () => { router.push("/login"); router.refresh(); }, }, }); }} > {t("signOut")}
); }