'use client'; import { useEffect, useState } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { createClient } from '@/lib/supabase/client'; import BottleGrid from "@/components/BottleGrid"; import AuthForm from "@/components/AuthForm"; import OfflineIndicator from "@/components/OfflineIndicator"; import { useI18n } from "@/i18n/I18nContext"; import { useAuth } from "@/context/AuthContext"; import { useSession } from "@/context/SessionContext"; import TastingHub from "@/components/TastingHub"; import { Sparkles, Loader2, Search, SlidersHorizontal } from "lucide-react"; import { BottomNavigation } from '@/components/BottomNavigation'; import ScanAndTasteFlow from '@/components/ScanAndTasteFlow'; import UserStatusBadge from '@/components/UserStatusBadge'; import { getActiveSplits } from '@/services/split-actions'; import SplitCard from '@/components/SplitCard'; import HeroBanner from '@/components/HeroBanner'; import QuickActionsGrid from '@/components/QuickActionsGrid'; import { checkIsAdmin } from '@/services/track-api-usage'; export default function Home() { const supabase = createClient(); const router = useRouter(); const searchParams = useSearchParams(); const [bottles, setBottles] = useState([]); const { user, isLoading: isAuthLoading } = useAuth(); const [isInternalLoading, setIsInternalLoading] = useState(false); const [fetchError, setFetchError] = useState(null); const { t } = useI18n(); const { activeSession } = useSession(); const [isFlowOpen, setIsFlowOpen] = useState(false); const [isTastingHubOpen, setIsTastingHubOpen] = useState(false); const [capturedFile, setCapturedFile] = useState(null); const [hasMounted, setHasMounted] = useState(false); const [publicSplits, setPublicSplits] = useState([]); const [searchQuery, setSearchQuery] = useState(''); useEffect(() => { setHasMounted(true); }, []); const handleImageSelected = (file: File) => { setCapturedFile(file); setIsFlowOpen(true); }; useEffect(() => { if (!isAuthLoading && user) { fetchCollection(); } else if (!isAuthLoading && !user) { setBottles([]); } }, [user, isAuthLoading]); useEffect(() => { getActiveSplits().then(res => { if (res.success && res.splits) { setPublicSplits(res.splits); } }); const handleCollectionUpdated = () => { console.log('[Home] Collection update event received, refreshing...'); fetchCollection(); }; window.addEventListener('collection-updated', handleCollectionUpdated); return () => { window.removeEventListener('collection-updated', handleCollectionUpdated); }; }, []); const fetchCollection = async () => { setIsInternalLoading(true); try { const { data, error } = await supabase .from('bottles') .select(` *, tastings ( created_at, rating ) `) .order('created_at', { ascending: false }); if (error) throw error; console.log(`Fetched ${data?.length || 0} bottles from Supabase`); const processedBottles = (data || []).map(bottle => { const lastTasted = bottle.tastings && bottle.tastings.length > 0 ? bottle.tastings.reduce((latest: string, current: any) => new Date(current.created_at) > new Date(latest) ? current.created_at : latest, bottle.tastings[0].created_at ) : null; return { ...bottle, last_tasted: lastTasted }; }); setBottles(processedBottles); } catch (err: any) { console.warn('[Home] Fetch collection error:', err?.message); const isNetworkError = !navigator.onLine || err?.name === 'TypeError' || err?.message?.includes('Failed to fetch'); if (!isNetworkError) { setFetchError(err?.message || 'Unknown error'); } } finally { setIsInternalLoading(false); } }; const handleLogout = async () => { await supabase.auth.signOut(); }; // Filter bottles by search query const filteredBottles = bottles.filter(bottle => { if (!searchQuery.trim()) return true; const query = searchQuery.toLowerCase(); return ( bottle.name?.toLowerCase().includes(query) || bottle.distillery?.toLowerCase().includes(query) || bottle.category?.toLowerCase().includes(query) ); }); if (!hasMounted) { return (
); } // Guest / Login View if (!user) { return (

DRAMLOG

{t('home.tagline')}

{publicSplits.length > 0 && (

{t('splits.publicExplore')}

{publicSplits.map((split) => ( router.push(`/splits/${split.slug}`)} /> ))}
)}
); } const isLoading = isAuthLoading || isInternalLoading; // Authenticated Home View - New Layout return (
{/* Scrollable Content Area */}
{/* 1. Header */}

DRAMLOG

{activeSession && (
Live: {activeSession.name}
)}
{/* 2. Hero Banner (optional) */}
{/* 3. Quick Actions Grid */}
{/* 4. Sticky Search Bar */}
setSearchQuery(e.target.value)} className="w-full pl-9 pr-4 py-2.5 bg-zinc-900 border border-zinc-800 rounded-xl text-sm text-white placeholder-zinc-600 focus:outline-hidden focus:border-orange-600/50 focus:ring-1 focus:ring-orange-600/20" />
{/* 5. Collection */}

{t('home.collection')}

{filteredBottles.length} {t('home.bottleCount')}
{isLoading ? (
) : fetchError ? (

{t('common.error')}

{fetchError}

) : filteredBottles.length > 0 ? ( ) : bottles.length > 0 ? (

No bottles match your search

) : null}
{/* Footer */}
{/* Bottom Navigation with FAB */} window.scrollTo({ top: 0, behavior: 'smooth' })} onShelf={() => document.getElementById('collection')?.scrollIntoView({ behavior: 'smooth' })} onTastings={() => setIsTastingHubOpen(true)} onProfile={() => router.push('/settings')} onScan={handleImageSelected} /> setIsTastingHubOpen(false)} /> setIsFlowOpen(false)} imageFile={capturedFile} onBottleSaved={() => fetchCollection()} />
); }