import i18n from '../../lang/i18n'; import { useState, useEffect, useRef } from 'react'; //Scaled markers - Bigger circles for stronger quakes //Color-coded by magnitude: //Yellow: M2.5-3 (minor) //Orange: M3-4 (light) //Deep Orange: M4-5 (moderate) //Red: M5-6 (strong) //Dark Red: M6-7 (major) //Very Dark Red: M7+ (great) export const metadata = { id: 'earthquakes', name: i18n.t('plugins.layers.earthquakes.name'), description: i18n.t('plugins.layers.earthquakes.description'), icon: '🌋', category: 'geology', defaultEnabled: false, defaultOpacity: 0.9, version: '1.2.0' }; export function useLayer({ enabled = false, opacity = 0.9, map = null }) { const [markersRef, setMarkersRef] = useState([]); const [earthquakeData, setEarthquakeData] = useState([]); const previousQuakeIds = useRef(new Set()); const isFirstLoad = useRef(true); // Fetch earthquake data useEffect(() => { if (!enabled) return; const fetchEarthquakes = async () => { try { // USGS GeoJSON feed - All earthquakes from last hour const response = await fetch( 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson' //'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson' ); const data = await response.json(); console.log('Earthquakes fetched:', data.features?.length || 0, 'quakes'); setEarthquakeData(data.features || []); } catch (err) { console.error('Earthquake data fetch error:', err); } }; fetchEarthquakes(); // Refresh every 5 minutes const interval = setInterval(fetchEarthquakes, 300000); //const interval = setInterval(fetchEarthquakes, 60000); return () => clearInterval(interval); }, [enabled]); // Add/remove markers with animation for new quakes useEffect(() => { if (!map || typeof L === 'undefined') return; // Clear old markers markersRef.forEach(marker => { try { map.removeLayer(marker); } catch (e) { // Already removed } }); setMarkersRef([]); if (!enabled || earthquakeData.length === 0) { console.log('Earthquakes: enabled=', enabled, 'data count=', earthquakeData.length); return; } const newMarkers = []; const currentQuakeIds = new Set(); earthquakeData.forEach(quake => { const coords = quake.geometry.coordinates; const props = quake.properties; const mag = props.mag; const lat = coords[1]; const lon = coords[0]; const depth = coords[2]; const quakeId = quake.id; currentQuakeIds.add(quakeId); // Skip if invalid coordinates if (!lat || !lon || isNaN(lat) || isNaN(lon)) return; // Check if this is a new earthquake (but not on first load) const isNew = !isFirstLoad.current && !previousQuakeIds.current.has(quakeId); // Calculate marker size based on magnitude (larger = stronger earthquake) // M1-2: 16px, M3: 20px, M4: 24px, M5: 28px, M6: 32px, M7+: 40px const size = Math.min(Math.max(mag * 6, 16), 40); // Color based on magnitude (gets redder with stronger quakes) let color; if (mag < 2) color = '#90EE90'; // Light green - micro else if (mag < 3) color = '#FFEB3B'; // Yellow - minor else if (mag < 4) color = '#FFA500'; // Orange - light else if (mag < 5) color = '#FF6600'; // Deep orange - moderate else if (mag < 6) color = '#FF3300'; // Red - strong else if (mag < 7) color = '#CC0000'; // Dark red - major else color = '#8B0000'; // Very dark red - great // Create earthquake icon with visible shake/wave symbol const waveIcon = ` `; const icon = L.divIcon({ className: 'earthquake-icon', html: `
| Location: | ${props.place || 'Unknown'} |
| Time: | ${timeStr} |
| Age: | ${ageStr} |
| Depth: | ${depth.toFixed(1)} km |
| Magnitude: | ${mag.toFixed(1)} |
| Status: | ${props.status || 'automatic'} |
| ⚠️ TSUNAMI WARNING | |