import React from 'react'; import { useLocation } from 'react-router-dom'; import { YStack, XStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { Pressable } from '@tamagui/react-native-web-lite'; import { Home, CheckSquare, Image as ImageIcon, User, LayoutDashboard } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useAdminTheme } from '../theme'; import { adminPath } from '../../constants'; const ICON_SIZE = 24; export const BOTTOM_NAV_HEIGHT = 70; export const BOTTOM_NAV_PADDING = 8; export type NavKey = 'home' | 'tasks' | 'uploads' | 'profile'; export function BottomNav({ active, onNavigate }: { active: NavKey; onNavigate: (key: NavKey) => void }) { const { t } = useTranslation('mobile'); const location = useLocation(); const theme = useAdminTheme(); const navRef = React.useRef(null); // Modern Glass Background const navSurface = theme.glassSurfaceStrong ?? theme.surfaceMuted ?? theme.surface; const navBorder = theme.glassBorder ?? theme.border; const navShadow = theme.glassShadow ?? theme.shadow; const [pressedKey, setPressedKey] = React.useState(null); const isDeepHome = active === 'home' && location.pathname !== adminPath('/mobile/dashboard'); const items: Array<{ key: NavKey; icon: React.ComponentType<{ size?: number; color?: string; strokeWidth?: number }>; label: string }> = [ { key: 'home', icon: isDeepHome ? LayoutDashboard : Home, label: t('nav.home', 'Home') }, { key: 'tasks', icon: CheckSquare, label: t('nav.tasks', 'Photo tasks') }, { key: 'uploads', icon: ImageIcon, label: t('nav.uploads', 'Uploads') }, { key: 'profile', icon: User, label: t('nav.profile', 'Profile') }, ]; const setBottomOffset = React.useCallback(() => { if (typeof document === 'undefined' || !navRef.current) { return; } const height = Math.ceil(navRef.current.getBoundingClientRect().height); document.documentElement.style.setProperty('--admin-bottom-nav-offset', `${height}px`); }, []); React.useLayoutEffect(() => { if (typeof window === 'undefined') { return; } setBottomOffset(); const handleResize = () => setBottomOffset(); if (typeof ResizeObserver !== 'undefined' && navRef.current) { const observer = new ResizeObserver(() => setBottomOffset()); observer.observe(navRef.current); window.addEventListener('resize', handleResize); return () => { observer.disconnect(); window.removeEventListener('resize', handleResize); document.documentElement.style.removeProperty('--admin-bottom-nav-offset'); }; } window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); document.documentElement.style.removeProperty('--admin-bottom-nav-offset'); }; }, [setBottomOffset]); return ( {items.map((item) => { const activeState = item.key === active; const isPressed = pressedKey === item.key; const IconCmp = item.icon; // Dynamic Styles const color = activeState ? theme.primary : theme.muted; const strokeWidth = activeState ? 2.5 : 2; return ( onNavigate(item.key)} onPressIn={() => setPressedKey(item.key)} onPressOut={() => setPressedKey(null)} onPointerLeave={() => setPressedKey(null)} style={{ flex: 1 }} > {activeState && ( )} {item.label} ); })} ); }