import React, { useEffect, useMemo, useState } from 'react'; import { Link as RouterLink, useLocation } from 'react-router-dom'; import '../../styles/sparta-styles.css'; import { usePublicSettings } from '../../hooks/usePublicSettings'; import { useClubTheme } from '../../contexts/ClubThemeContext'; import { getNavigationItems, NavigationItem, seedDefaultNavigation } from '../../services/navigation'; import { getCategories, Category } from '../../services/public'; import { assetUrl } from '../../utils/url'; import { useTranslation } from 'react-i18next'; // Minimal NavLink type used to render items type NavLink = { label: string; to?: string; items?: { label: string; to: string }[]; external?: boolean }; const SpartaNavbar: React.FC = () => { const { t } = useTranslation(); const { data: settings } = usePublicSettings(); const theme = useClubTheme(); const location = useLocation(); const [mobileOpen, setMobileOpen] = useState(false); const [dynamicNavItems, setDynamicNavItems] = useState([]); const [navLoading, setNavLoading] = useState(true); const [navCategories, setNavCategories] = useState(null); // Load dynamic navigation useEffect(() => { let active = true; (async () => { try { const items = await getNavigationItems(); if (active && Array.isArray(items)) { const publicItems = items.filter(item => !item.requires_admin); if (publicItems.length === 0) { try { await seedDefaultNavigation(); const newItems = await getNavigationItems(); if (active && Array.isArray(newItems)) { const publicNewItems = newItems.filter(item => !item.requires_admin); setDynamicNavItems(publicNewItems); } } catch { setDynamicNavItems([]); } } else { setDynamicNavItems(publicItems); } } } catch { // leave empty, fallback will handle } finally { if (active) setNavLoading(false); } })(); return () => { active = false }; }, []); // Load categories (for Blog dropdown fallback) useEffect(() => { let active = true; (async () => { try { const cats = await getCategories(); if (active && Array.isArray(cats) && cats.length > 0) { setNavCategories(cats); } else if (active && Array.isArray(settings?.categories)) { setNavCategories(settings!.categories as any); } } catch { if (active && Array.isArray(settings?.categories)) { setNavCategories(settings!.categories as any); } } })(); return () => { active = false }; }, [settings?.categories]); const isPathActive = (to?: string) => { if (!to) return false; return location.pathname === to || location.pathname.startsWith((to || '') + '/'); }; const convertToNavLink = (item: NavigationItem): NavLink => { // Map known Czech labels to translation keys const getTranslatedLabel = (label: string) => { const labelMap: Record = { 'Domů': 'nav.home', 'Aktuality': 'nav.news', 'Zápasy': 'nav.matches', 'Hráči': 'nav.players', 'Fotogalerie': 'nav.gallery', 'Videa': 'nav.videos', 'Kontakt': 'nav.contact', 'O klubu': 'nav.about', 'Aktivity': 'nav.activities', 'Sponzoři': 'nav.sponsors', 'Články': 'nav.news', 'Blog': 'nav.news', 'Kalendář': 'nav.calendar', 'Tabulky': 'nav.table' }; const translationKey = labelMap[label]; return translationKey ? t(translationKey) : label; }; const link: NavLink = { label: getTranslatedLabel(item.label), to: item.url || '#', external: item.type === 'external', }; if (item.type === 'dropdown' && item.children && item.children.length > 0) { link.items = item.children.map(child => ({ label: getTranslatedLabel(child.label), to: child.url || '#' })); } return link; }; const categoryItems = useMemo(() => { const source = Array.isArray(navCategories) && navCategories.length > 0 ? navCategories : []; return source.map((cat: any) => ({ label: cat.name, to: cat.url || (cat.id ? `/blog?category_id=${cat.id}` : (cat.slug ? `/blog?category=${encodeURIComponent(cat.slug)}` : '/blog')) })); }, [navCategories]); const NAV_LINKS: NavLink[] = useMemo(() => { if (!navLoading && dynamicNavItems.length > 0) { const navLinks = dynamicNavItems.map(convertToNavLink); if (categoryItems.length > 0) { const idx = navLinks.findIndex(l => l.label === 'Články' || l.label === 'Blog' || l.to === '/blog'); if (idx !== -1) navLinks[idx] = { ...navLinks[idx], items: categoryItems }; } return navLinks; } // Fallback minimal menu const links: NavLink[] = [ { label: 'Domů', to: '/' }, ...(settings?.show_about_in_nav === false ? [] : [{ label: 'O klubu', to: '/o-klubu' } as NavLink]), { label: 'Kalendář', to: '/kalendar' }, { label: 'Zápasy', to: '/zapasy' }, { label: 'Aktivity', to: '/aktivity' }, { label: 'Hráči', to: '/hraci' }, categoryItems.length > 0 ? { label: 'Články', to: '/blog', items: categoryItems } : { label: 'Články', to: '/blog' }, { label: 'Videa', to: '/videa' }, { label: settings?.gallery_label || t('nav.gallery'), to: '/galerie' }, ...(settings?.shop_url ? [{ label: 'Fanshop', to: settings.shop_url, external: true } as NavLink] : []), { label: 'Sponzoři', to: '/sponzori' }, { label: 'Kontakt', to: '/kontakt' }, ]; return links; }, [navLoading, dynamicNavItems, settings?.show_about_in_nav, settings?.shop_url, settings?.gallery_label, categoryItems]); const logoUrl = (assetUrl(settings?.club_logo_url || theme.logoUrl) || settings?.club_logo_url || theme.logoUrl) || '/dist/img/logo-club-empty.svg'; const clubName = settings?.club_name || theme.name || 'Klub'; return (
{/* Burger toggle for mobile */} {/* Brand */} setMobileOpen(false)}> {clubName} {/* Links */}
); }; export default SpartaNavbar;