import React, { useRef, useState, useEffect, useCallback, memo } from 'react'; import { Card, CardHeader, CardContent, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; import { MapPin, Star } from 'lucide-react'; import { Skeleton } from '@/components/ui/skeleton'; const isValidCoordinate = (coord: number) => { return typeof coord === 'number' && !isNaN(coord) && isFinite(coord); }; const loadGoogleMapsScript = (callback: () => void) => { if (window.google && window.google.maps) { callback(); return; } const existingScript = document.getElementById('googleMapsScript'); if (existingScript) { existingScript.remove(); } window.initMap = callback; const script = document.createElement('script'); script.id = 'googleMapsScript'; script.src = `https://maps.googleapis.com/maps/api/js?key=${process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY}&libraries=places,marker&callback=initMap`; script.async = true; script.defer = true; document.head.appendChild(script); }; const MapComponent = React.memo(({ center, places }: { center: { lat: number; lng: number }, places: any[] }) => { const mapRef = useRef(null); const [mapError, setMapError] = useState(null); const googleMapRef = useRef(null); const markersRef = useRef([]); const initializeMap = useCallback(async () => { if (mapRef.current && isValidCoordinate(center.lat) && isValidCoordinate(center.lng)) { const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; if (!googleMapRef.current) { googleMapRef.current = new Map(mapRef.current, { center: center, zoom: 14, mapId: "347ff92e0c7225cf", }); } else { googleMapRef.current.setCenter(center); } markersRef.current.forEach(marker => marker.map = null); markersRef.current = []; places.forEach((place) => { if (isValidCoordinate(place.location.lat) && isValidCoordinate(place.location.lng)) { const marker = new AdvancedMarkerElement({ map: googleMapRef.current, position: place.location, title: place.name, }); markersRef.current.push(marker); } }); } else { setMapError('Invalid coordinates provided'); } }, [center, places]); useEffect(() => { loadGoogleMapsScript(() => { try { initializeMap(); } catch (error) { console.error('Error initializing map:', error); setMapError('Failed to initialize Google Maps'); } }); return () => { markersRef.current.forEach(marker => marker.map = null); }; }, [initializeMap]); if (mapError) { return
{mapError}
; } return
; }); MapComponent.displayName = 'MapComponent'; const MapSkeleton = () => ( ); const PlaceDetails = ({ place }: { place: any }) => (

{place.name}

{place.vicinity}

{place.rating && ( {place.rating} ({place.user_ratings_total}) )}
); const MapEmbed = memo(({ location, zoom = 15 }: { location: string, zoom?: number }) => { const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY; const mapUrl = `https://www.google.com/maps/embed/v1/place?key=${apiKey}&q=${encodeURIComponent(location)}&zoom=${zoom}`; return (
); }); MapEmbed.displayName = 'MapEmbed'; const FindPlaceResult = memo(({ result }: { result: any }) => { const place = result.candidates[0]; const location = `${place.geometry.location.lat},${place.geometry.location.lng}`; return ( {place.name}

Address: {place.formatted_address}

{place.rating && (
Rating: {place.rating}
)} {place.opening_hours && (

Open now: {place.opening_hours.open_now ? 'Yes' : 'No'}

)}
); }); FindPlaceResult.displayName = 'FindPlaceResult'; const TextSearchResult = React.memo(({ result }: { result: any }) => { const centerLocation = result.results[0]?.geometry?.location; const mapLocation = centerLocation ? `${centerLocation.lat},${centerLocation.lng}` : ''; return ( Text Search Results {mapLocation && } Place Details
{result.results.map((place: any, index: number) => ( ))}
); }); TextSearchResult.displayName = 'TextSearchResult'; export { MapComponent, MapSkeleton, FindPlaceResult, TextSearchResult };