Files
tasteby/frontend/src/components/MapView.tsx
joungmin 36bec10bd0 Initial commit: Tasteby - YouTube restaurant map service
Backend (FastAPI + Oracle ADB), Frontend (Next.js), daemon worker.
Features: channel/video/restaurant management, semantic search,
Google OAuth, user reviews.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:47:19 +09:00

76 lines
2.1 KiB
TypeScript

"use client";
import { useCallback, useState } from "react";
import {
APIProvider,
Map,
AdvancedMarker,
InfoWindow,
} from "@vis.gl/react-google-maps";
import type { Restaurant } from "@/lib/api";
const SEOUL_CENTER = { lat: 37.5665, lng: 126.978 };
const API_KEY = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || "";
interface MapViewProps {
restaurants: Restaurant[];
onSelectRestaurant?: (r: Restaurant) => void;
}
export default function MapView({ restaurants, onSelectRestaurant }: MapViewProps) {
const [selected, setSelected] = useState<Restaurant | null>(null);
const handleMarkerClick = useCallback(
(r: Restaurant) => {
setSelected(r);
onSelectRestaurant?.(r);
},
[onSelectRestaurant]
);
return (
<APIProvider apiKey={API_KEY}>
<Map
defaultCenter={SEOUL_CENTER}
defaultZoom={12}
mapId="tasteby-map"
className="h-full w-full"
>
{restaurants.map((r) => (
<AdvancedMarker
key={r.id}
position={{ lat: r.latitude, lng: r.longitude }}
onClick={() => handleMarkerClick(r)}
/>
))}
{selected && (
<InfoWindow
position={{ lat: selected.latitude, lng: selected.longitude }}
onCloseClick={() => setSelected(null)}
>
<div className="max-w-xs p-1">
<h3 className="font-bold text-base">{selected.name}</h3>
{selected.cuisine_type && (
<p className="text-sm text-gray-600">{selected.cuisine_type}</p>
)}
{selected.address && (
<p className="text-xs text-gray-500 mt-1">{selected.address}</p>
)}
{selected.price_range && (
<p className="text-xs text-gray-500">{selected.price_range}</p>
)}
<button
onClick={() => onSelectRestaurant?.(selected)}
className="mt-2 text-sm text-blue-600 hover:underline"
>
</button>
</div>
</InfoWindow>
)}
</Map>
</APIProvider>
);
}