'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 */}
);
}
export default function Page() {
return (
);
}