"use client"; /** * MENU PAGE — Premium Sidebar Navigation */ import { useEffect, useRef, useState, useMemo } from "react"; import { menuCategories } from "@/lib/menu-data"; import { buildCartLineFromMenuItem } from "@/application/cart/cart-line-builder"; import type { MenuItem } from "@/domain/menu/entities"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import { motion } from "framer-motion"; import Navbar from "@/components/Navbar"; import PageHeader from "@/components/PageHeader"; import Footer from "@/components/Footer"; import { useCart } from "@/components/CartContext"; import WishlistButton from "@/components/WishlistButton"; import { useLanguage } from "@/lib/language-context"; import { getTranslation } from "@/lib/translations"; import { getCategoryName, getMenuItemDescription, getMenuItemName, } from "@/application/i18n/menu-localization"; import { dishImageUrl, getMenuPosterSrc, getMenuPosterCandidates, applyNextImageFallback, } from "@/lib/assets"; import { playHoverSound } from "@/lib/sounds"; import DishDetailsModal from "@/components/DishDetailsModal"; import { hasDishDetailModal } from "@/domain/menu/dish-details"; gsap.registerPlugin(ScrollTrigger); export default function MenuPage() { const [activeCategory, setActiveCategory] = useState("All"); const [searchQuery, setSearchQuery] = useState(""); const [showVegetarianOnly, setShowVegetarianOnly] = useState(false); const [isMobile, setIsMobile] = useState(false); const [detailItem, setDetailItem] = useState(null); const categoryListRef = useRef(null); const { addToCart } = useCart(); const { language } = useLanguage(); const t = getTranslation(language); // Sidebar categories const sidebarCategories = [ { id: "All", name: t.menu.allDishes || "All Dishes" }, ...menuCategories.map((cat) => ({ id: cat.id, name: getCategoryName(language, cat.id, cat.name), })), ]; // Filtering logic const filteredCategories = useMemo(() => { return menuCategories .map((category) => { let items = category.items; // Sidebar filter if (activeCategory !== "All" && category.id !== activeCategory) { items = []; } // Search if (searchQuery.trim()) { const q = searchQuery.toLowerCase().trim(); items = items.filter((item) => { const localizedName = getMenuItemName(language, item).toLowerCase(); const localizedDescription = getMenuItemDescription(language, t, item).toLowerCase(); return ( localizedName.includes(q) || localizedDescription.includes(q) || item.name.toLowerCase().includes(q) ); }); } // Vegetarian if (showVegetarianOnly) { items = items.filter((item) => item.isVegetarian); } return { ...category, items }; }) .filter((category) => category.items.length > 0); }, [searchQuery, showVegetarianOnly, activeCategory, language, t]); const handleCategorySelect = (id: string) => { setActiveCategory(id); window.scrollTo({ top: 220, behavior: "smooth" }); }; const getItemDescription = (item: MenuItem) => getMenuItemDescription(language, t, item); const getItemName = (item: MenuItem) => getMenuItemName(language, item); const openDishDetails = (item: MenuItem) => { setDetailItem(item); }; /** Detail-modal dishes use their photo on the card; video plays only in the modal. */ const getCardImageSrc = (item: MenuItem, categoryId: string) => hasDishDetailModal(item.id, categoryId) && item.image ? dishImageUrl(item.image) : getMenuPosterSrc(item); const getCardImageCandidates = (item: MenuItem, categoryId: string) => hasDishDetailModal(item.id, categoryId) && item.image ? [dishImageUrl(item.image), ...getMenuPosterCandidates(item)] : getMenuPosterCandidates(item); const renderMenuPrice = (item: MenuItem) => { if (item.pricing === "weight") { return (
{item.pricePerHalfKg ?? item.price}
{t.menu.perHalfKg}
{item.pricePerKg} {t.menu.perKg}
); } return (
{item.price}
KR
); }; // isMobile detection - used to enable advanced desktop hover effects + sounds only on desktop useEffect(() => { const updateMobile = () => setIsMobile(window.innerWidth < 768); updateMobile(); window.addEventListener("resize", updateMobile); return () => window.removeEventListener("resize", updateMobile); }, []); useEffect(() => { const container = categoryListRef.current; if (!container) return; const activeButton = container.querySelector( `[data-category-id="${activeCategory}"]` ); if (!activeButton) return; const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; activeButton.scrollIntoView({ behavior: prefersReducedMotion ? "auto" : "smooth", block: "nearest", inline: "center", }); }, [activeCategory]); return (
{/* Main Layout */}
{/* BEAUTIFUL SIDEBAR */}
EXPLORE OUR

Signature Categories

{/* Smooth scroll: horizontal on mobile, vertical on desktop when list exceeds viewport */}
{sidebarCategories.map((cat) => { const isActive = activeCategory === cat.id; const itemCount = cat.id === "All" ? menuCategories.reduce((sum, c) => sum + c.items.length, 0) : menuCategories.find(c => c.id === cat.id)?.items.length || 0; return ( ); })}
{/* MAIN CONTENT */}
{/* Search + Vegetarian Filter */}
setSearchQuery(e.target.value)} className="w-full md:w-80 rounded-2xl border border-[#e5e1d7] bg-white px-5 py-3 text-sm placeholder:text-[#8A8478] focus:border-[#c99a2e] focus:ring-2 focus:ring-[#c99a2e]/20 transition-all" /> {(searchQuery || showVegetarianOnly || activeCategory !== "All") && ( )}
{/* Menu Items */} {filteredCategories.length === 0 ? (
{t.menu.noResults}
) : ( filteredCategories.map((category) => (
{getCategoryName(language, category.id, category.name)}
{category.items.length} {t.menu.dishes}
{category.items.map((item) => { const usesDetailModal = hasDishDetailModal(item.id, category.id); return ( addToCart(buildCartLineFromMenuItem(item)) } whileHover={!isMobile ? { y: -4, boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)", transition: { type: "spring", stiffness: 300, damping: 20 } } : {}} whileTap={{ scale: 0.985 }} > {/* Media - Always poster for performance. Advanced desktop hover effect (scale + lift + glow) + subtle sound. Mobile uses simple scale. */}
{ e.stopPropagation(); openDishDetails(item); } : undefined } onMouseEnter={() => { if (!isMobile) playHoverSound(); }} > { applyNextImageFallback( e.target as HTMLImageElement, getCardImageCandidates(item, category.id), (e.target as HTMLImageElement).src ); }} /> {/* Subtle gradient + hover shine overlay for advanced desktop feel */}
{!isMobile && (
)}

{getItemName(item)}

{renderMenuPrice(item)}
{usesDetailModal ? ( ) : ( item.description && (

{getItemDescription(item)}

) )}
{item.isVegetarian && ( VEGETARIAN )}
); })}
)) )}
); }