import { useEffect, useState } from 'react'; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from '@/components/ui/sheet'; import { Button } from '@/components/ui/button'; import { useNavPreferences, MIDDLE_SLOTS, type NavTab, } from '@/hooks/useNavPreferences'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useTranslation } from '@/contexts/language'; import { cn } from '@/lib/utils'; import { MapPin, User, Lock, ArrowUp, ArrowDown, RotateCcw, Check, Sparkles } from 'lucide-react'; interface CustomizeNavSheetProps { open: boolean; onOpenChange: (open: boolean) => void; } /** * Bottom-sheet editor for the mobile nav bar. * * Layout model: Map (fixed left) · 3 user-picked · Profile (fixed right). * The user toggles up to 3 destinations from the catalog and can reorder them. * Draft state is local until "Done", so changes feel deliberate and cancelable. */ export function CustomizeNavSheet({ open, onOpenChange }: CustomizeNavSheetProps) { const { middleIds, setMiddleIds, reset, catalog } = useNavPreferences(); const { user } = useCurrentUser(); const { t } = useTranslation(); // Local draft so we can cancel without persisting. const [draft, setDraft] = useState(middleIds); // Re-seed the draft whenever the sheet opens. useEffect(() => { if (open) setDraft(middleIds); // eslint-disable-next-line react-hooks/exhaustive-deps }, [open]); const isLoggedIn = !!user; const full = draft.length >= MIDDLE_SLOTS; const label = (tab: NavTab) => (tab.labelKey ? t(tab.labelKey) : tab.label); const toggle = (id: string) => { setDraft((prev) => { if (prev.includes(id)) return prev.filter((x) => x !== id); if (prev.length >= MIDDLE_SLOTS) return prev; // full — ignore return [...prev, id]; }); }; const move = (id: string, dir: -1 | 1) => { setDraft((prev) => { const idx = prev.indexOf(id); const next = idx + dir; if (idx < 0 || next < 0 || next >= prev.length) return prev; const copy = [...prev]; [copy[idx], copy[next]] = [copy[next], copy[idx]]; return copy; }); }; const save = () => { setMiddleIds(draft); onOpenChange(false); }; const handleReset = () => { reset(); // reset() writes defaults; reseed draft from the same default source. setDraft(['lab', 'events', 'crews']); }; // Resolve draft ids to tabs for the preview & reorder list. const draftTabs = draft .map((id) => catalog.find((c) => c.id === id)) .filter((c): c is NavTab => !!c); return ( Customize your bar Pick the {MIDDLE_SLOTS} tabs you use most. Everything else stays in the menu. {/* Live preview */}

Preview

{/* Fixed Map */} {/* Middle draft */} {Array.from({ length: MIDDLE_SLOTS }).map((_, i) => { const tab = draftTabs[i]; if (!tab) { return (
+ Empty
); } return ; })} {/* Fixed Profile */}
{/* Reorder chosen tabs */} {draftTabs.length > 0 && (

Order ({draft.length}/{MIDDLE_SLOTS})

{draftTabs.map((tab, i) => (
{label(tab)}
))}
)} {/* Catalog picker */}

Available tabs

{full && ( Bar full — remove one to swap )}
{catalog.map((tab) => { const selected = draft.includes(tab.id); const gatedOut = tab.authOnly && !isLoggedIn; const disabled = gatedOut || (!selected && full); return ( ); })}
{/* Footer actions */}
); } function PreviewSlot({ icon: Icon, label, locked, accent, }: { icon: NavTab['icon']; label: string; locked?: boolean; accent: string; }) { return (
{locked && ( )} {label}
); }