import { useNavigate, useLocation, useMatch } from 'react-router-dom' import { useAddonStore } from '../../store/addonStore' import { useSettingsStore } from '../../store/settingsStore' import { useTranslation } from '../../i18n' import { LayoutGrid, CalendarDays, Globe, Compass, Plus } from 'lucide-react' import type { LucideIcon } from 'lucide-react' const ADDON_NAV: Record = { vacay: { icon: CalendarDays, labelKey: 'admin.addons.catalog.vacay.name' }, atlas: { icon: Globe, labelKey: 'admin.addons.catalog.atlas.name' }, journey: { icon: Compass, labelKey: 'admin.addons.catalog.journey.name' }, } interface NavItem { to: string; label: string; icon: LucideIcon } // The centre "+" means something different per context: inside a trip it adds a // place, on the journey list it starts a journey, inside a journey it adds an // entry — everywhere else it creates a new trip. Pages pick the intent up from // the ?create= query param. function useCreateAction(): { label: string; run: () => void } { const navigate = useNavigate() const { t } = useTranslation() const inTrip = useMatch('/trips/:id') const inJourney = useMatch('/journey/:id') const onJourneyList = useMatch('/journey') if (inTrip) { // On the Costs tab the "+" adds an expense; otherwise it adds a place. const tripTab = typeof sessionStorage !== 'undefined' ? sessionStorage.getItem(`trip-tab-${inTrip.params.id}`) : null if (tripTab === 'finanzplan') { return { label: t('costs.addExpense'), run: () => navigate(`/trips/${inTrip.params.id}?create=expense`) } } return { label: t('places.addPlace'), run: () => navigate(`/trips/${inTrip.params.id}?create=place`) } } if (inJourney) { return { label: t('journey.detail.addEntry'), run: () => navigate(`/journey/${inJourney.params.id}?create=entry`) } } if (onJourneyList) { return { label: t('journey.new'), run: () => navigate('/journey?create=1') } } return { label: t('dashboard.newTrip'), run: () => navigate('/dashboard?create=1') } } export default function BottomNav() { const { t } = useTranslation() const navigate = useNavigate() const darkMode = useSettingsStore(s => s.settings.dark_mode) const dark = darkMode === true || darkMode === 'dark' || (darkMode === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) const addons = useAddonStore(s => s.addons) const globalAddons = addons.filter(a => a.type === 'global' && a.enabled) const location = useLocation() const create = useCreateAction() const items: NavItem[] = [ { to: '/dashboard', label: t('nav.myTrips'), icon: LayoutGrid }, ...globalAddons.flatMap(addon => { const nav = ADDON_NAV[addon.id] return nav ? [{ to: `/${addon.id}`, label: t(nav.labelKey), icon: nav.icon }] : [] }), ] // Split the items so the raised "+" sits dead centre. const splitAt = Math.ceil(items.length / 2) const left = items.slice(0, splitAt) const right = items.slice(splitAt) const isActive = (to: string) => to === '/dashboard' ? location.pathname === '/dashboard' : location.pathname.startsWith(to) const renderItem = ({ to, label, icon: Icon }: NavItem) => { const active = isActive(to) return ( ) } return ( ) }