import { useState, useMemo } from 'react'; import { useSeoMeta } from '@unhead/react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { RouteDialog } from '@/components/RouteDialog'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { useSkateSpots } from '@/hooks/useSkateSpots'; import { useFoodSpots } from '@/hooks/useFoodSpots'; import { Utensils, MapPin, Phone, Globe, Clock, Navigation, Coffee, Beer, ChefHat, } from 'lucide-react'; import type { FoodSpot } from '@/lib/types'; import { sanitizeUrl, sanitizeTel } from '@/lib/sanitizeUrl'; import { useTranslation } from '@/contexts/language'; const FOOD_TYPE_ICONS: Record> = { restaurant: ChefHat, cafe: Coffee, fast_food: Utensils, bar: Beer, pub: Beer, food_court: Utensils, }; const FOOD_TYPE_KEYS: Record = { restaurant: 'placesUi.food.restaurant', cafe: 'placesUi.food.cafe', fast_food: 'placesUi.food.fastFood', bar: 'placesUi.food.bar', pub: 'placesUi.food.pub', food_court: 'placesUi.food.foodCourt', }; function FoodSpotCard({ spot }: { spot: FoodSpot }) { const { t } = useTranslation(); const Icon = FOOD_TYPE_ICONS[spot.type] || Utensils; const [showRoute, setShowRoute] = useState(false); // In-app routing only — no external map handoff. const handleDirections = () => setShowRoute(true); return (
{spot.name}
{FOOD_TYPE_KEYS[spot.type] ? t(FOOD_TYPE_KEYS[spot.type]) : spot.type} {spot.cuisine && ( {spot.cuisine} )}
{spot.distance !== undefined && ( {spot.distance < 1 ? `${Math.round(spot.distance * 1000)}m` : `${spot.distance.toFixed(1)}km`} )}
{spot.address && (
{spot.address}
)} {spot.openingHours && (
{spot.openingHours}
)}
{spot.phone && sanitizeTel(spot.phone) && ( )} {spot.website && sanitizeUrl(spot.website) && ( )}
); } function FoodSpotSkeleton() { return (
); } export default function FoodPage() { const { t } = useTranslation(); useSeoMeta({ title: t('seoUi.foodTitle'), description: t('seoUi.foodDesc'), }); const { data: spots, isLoading: spotsLoading } = useSkateSpots(50); const [selectedSpotId, setSelectedSpotId] = useState(null); const selectedSpot = useMemo(() => { if (!selectedSpotId || !spots) return null; return spots.find((s) => s.id === selectedSpotId) || null; }, [selectedSpotId, spots]); const { data: foodSpots, isLoading: foodLoading, } = useFoodSpots(selectedSpot?.geohash, 1); return ( <>
{/* Header */}

{t('placesUi.food.title')}

{t('placesUi.food.subtitle')}

{/* Spot selector */}
{selectedSpot && (
{t('placesUi.food.locationLabel')}{' '} {selectedSpot.location || t('placesUi.food.unknown')}
)}
{/* Food results */} {!selectedSpotId ? (

{t('placesUi.food.selectSpotTitle')}

{t('placesUi.food.selectSpotDesc')}

) : foodLoading ? (
{Array.from({ length: 6 }).map((_, i) => ( ))}
) : foodSpots && foodSpots.length > 0 ? ( <>

{t('placesUi.food.placesFound', { count: foodSpots.length, spot: selectedSpot?.title ?? '' })}

{foodSpots.map((spot) => ( ))}
) : (

{t('placesUi.food.noneFound')}

{t('placesUi.food.noneFoundDesc')}

)}
); }