'use client'; import { useState, useEffect } from 'react'; import dynamic from 'next/dynamic'; import { Plus, Loader2 } from 'lucide-react'; import { useMutation } from '@tanstack/react-query'; import { Providers } from './providers'; import { Loading } from '@/components/Loading'; import ReviewModal from '@/components/ReviewModal'; import SearchPanel from '@/components/SearchPanel'; import { restaurantApi, Restaurant, CreateRatingData, PlaceSearchResult } from '@/lib/api'; // Dynamic import for Map to avoid SSR issues const Map = dynamic(() => import('@/components/Map'), { ssr: false, loading: () =>
, }); // Type for API errors type ApiError = { response?: { data?: { error?: string; }; }; }; function HomePage() { const [userLocation, setUserLocation] = useState<{ lat: number; lng: number } | null>(null); const [selectedRestaurant, setSelectedRestaurant] = useState(null); const [showSearchResults, setShowSearchResults] = useState(false); const [searchResultsMinimized, setSearchResultsMinimized] = useState(false); const [searchResults, setSearchResults] = useState([]); const [restaurants, setRestaurants] = useState([]); // Get user's location useEffect(() => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { setUserLocation({ lat: position.coords.latitude, lng: position.coords.longitude }); }, (error) => { console.error('Error getting location:', error); // Default to NYC setUserLocation({ lat: 40.7128, lng: -74.0060 }); } ); } else { setUserLocation({ lat: 40.7128, lng: -74.0060 }); } }, []); // Add rating mutation const addRatingMutation = useMutation({ mutationFn: ({ restaurantId, data }: { restaurantId: number; data: CreateRatingData }) => restaurantApi.addRating(restaurantId, data), onSuccess: async () => { // Refresh restaurants list if (userLocation) { const updatedRestaurants = await restaurantApi.getNearby(userLocation.lat, userLocation.lng); setRestaurants(updatedRestaurants); } alert('Toast rating added! 🍞'); }, onError: (error: unknown) => { const apiError = error as ApiError; alert(apiError.response?.data?.error || 'Failed to add rating'); }, }); // Search places mutation const searchMutation = useMutation({ mutationFn: async () => { const searchPlaces = await restaurantApi.searchPlaces(userLocation!.lat, userLocation!.lng, 2000); // All places are now auto-created as restaurants, so fetch the updated list const updatedRestaurants = await restaurantApi.getNearby(userLocation!.lat, userLocation!.lng); setRestaurants(updatedRestaurants); return searchPlaces; }, onSuccess: (data) => { setSearchResults(data); setShowSearchResults(true); setSelectedRestaurant(null); // Close any open restaurant panel }, onError: (error: unknown) => { const apiError = error as ApiError; alert(apiError.response?.data?.error || 'Failed to search for places'); }, }); // Update toast status mutation const updateToastStatusMutation = useMutation({ mutationFn: ({ restaurantId, hasToast }: { restaurantId: number; hasToast: boolean }) => restaurantApi.updateToastStatus(restaurantId, hasToast), onSuccess: async () => { // Refresh restaurants if (userLocation) { const updatedRestaurants = await restaurantApi.getNearby(userLocation.lat, userLocation.lng); setRestaurants(updatedRestaurants); } }, onError: (error: unknown) => { const apiError = error as ApiError; alert(apiError.response?.data?.error || 'Failed to update toast status'); }, }); const handleAddRating = async (data: CreateRatingData) => { if (!selectedRestaurant) return; await addRatingMutation.mutateAsync({ restaurantId: selectedRestaurant.id, data }); }; if (!userLocation) { return ; } return (
{/* Header */}
🍞

LocalToast

Find and rate the best toast in town!

{/* Main Content */}
updateToastStatusMutation.mutate({ restaurantId, hasToast }) } /> {/* Loading indicator */} {searchMutation.isPending && (
Searching for toast spots...
)} {/* Restaurant count - moved to top right */} {restaurants.length > 0 && !searchMutation.isPending && (

{restaurants.length} toast spot{restaurants.length !== 1 ? 's' : ''} nearby 🍞

)} {/* Review Modal */} {selectedRestaurant && ( setSelectedRestaurant(null)} onSubmit={handleAddRating} /> )} {/* Search results panel */} {showSearchResults && ( <> {searchResultsMinimized ? ( // Minimized state - just a bar at the bottom
setSearchResultsMinimized(false)}>

{searchResults.length} search results (click to expand)

) : ( // Full search panel setSearchResultsMinimized(true)} onToastStatusUpdate={(restaurantId, hasToast) => updateToastStatusMutation.mutate({ restaurantId, hasToast }) } onRestaurantClick={(restaurantId) => { const restaurant = restaurants.find(r => r.id === restaurantId); if (restaurant) { setSelectedRestaurant(restaurant); // Don't minimize - let user continue browsing } }} /> )} )}
); } export default function Page() { return ( ); }