'use client' import { useLoadScript, GoogleMap, Marker, InfoWindow } from '@react-google-maps/api' import { useState, useCallback, useEffect } from 'react' import { MapPin } from 'lucide-react' import type { OutbreakReport } from '@/lib/outbreakReport' const libraries: ('places' | 'drawing' | 'geometry' | 'visualization')[] = ['places'] interface GoogleMapProps { reports?: OutbreakReport[] onMapClick?: (lat: number, lng: number) => void center?: { lat: number; lng: number } zoom?: number /** When false, hides the floating “click map” hint (parent may show its own). Default true. */ showMapClickHint?: boolean /** Called when the Google Map instance is ready (e.g. to trigger resize after layout changes). */ onMapReady?: (map: google.maps.Map) => void /** Maps API fullscreen control; set false when the parent provides its own fullscreen. Default true. */ fullscreenControl?: boolean } const mapContainerStyle = { width: '100%', height: '100%', } const defaultCenter = { lat: 39.8283, // Center of US lng: -98.5795, } const defaultZoom = 4 export default function GoogleMapComponent({ reports = [], onMapClick, center = defaultCenter, zoom = defaultZoom, showMapClickHint = true, onMapReady, fullscreenControl = true, }: GoogleMapProps) { const [selectedReport, setSelectedReport] = useState(null) const [mapCenter, setMapCenter] = useState(center) const [loadingTimeout, setLoadingTimeout] = useState(false) const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || '' const { isLoaded, loadError } = useLoadScript({ googleMapsApiKey: apiKey, libraries, }) // Add timeout to prevent infinite loading useEffect(() => { if (!isLoaded && !loadError && apiKey) { const timer = setTimeout(() => { setLoadingTimeout(true) }, 8000) // 8 second timeout return () => clearTimeout(timer) } else { setLoadingTimeout(false) } }, [isLoaded, loadError, apiKey]) const handleMapClick = useCallback( (e: google.maps.MapMouseEvent) => { if (e.latLng && onMapClick) { onMapClick(e.latLng.lat(), e.latLng.lng()) } }, [onMapClick] ) const handleMapLoad = useCallback( (map: google.maps.Map) => { onMapReady?.(map) }, [onMapReady] ) const getSeverityColor = (severity: string) => { switch (severity) { case 'high': return '#ef4444' case 'medium': return '#f97316' case 'low': return '#eab308' default: return '#64748b' } } // Create marker icons - only create when map is loaded const createMarkerIcon = useCallback((color: string) => { if (!isLoaded || typeof google === 'undefined' || !google.maps) { return undefined } // Create a canvas-based circle icon - most reliable method const canvas = document.createElement('canvas') canvas.width = 24 canvas.height = 24 const ctx = canvas.getContext('2d') if (!ctx) return undefined // Draw filled circle ctx.beginPath() ctx.arc(12, 12, 10, 0, 2 * Math.PI) ctx.fillStyle = color ctx.fill() // Draw white border ctx.strokeStyle = '#ffffff' ctx.lineWidth = 3 ctx.stroke() const dataUrl = canvas.toDataURL() return { url: dataUrl, scaledSize: new google.maps.Size(24, 24), anchor: new google.maps.Point(12, 12), } }, [isLoaded]) if (loadError || loadingTimeout) { return (

Map Unavailable

{apiKey ? 'Google Maps API key may be invalid or restricted' : 'Google Maps API key not configured'}

Outbreak reporting will work once the map loads

) } if (!isLoaded) { return (

Loading Google Maps...

{!apiKey && (

No API key configured

)}
) } return (