import React, { useEffect, useState } from 'react'; import { MapContainer, TileLayer, Marker, Popup, CircleMarker } from 'react-leaflet'; import * as turf from '@turf/turf'; import 'leaflet/dist/leaflet.css'; /** * Campaign Map Component * Visualize geospatial content coverage */ interface Location { id: string; lat: number; lng: number; city?: string; state?: string; content_generated?: boolean; } interface CampaignMapProps { geoData?: { type: string; features: any[]; }; defaultCenter?: [number, number]; defaultZoom?: number; } export default function CampaignMap({ geoData, defaultCenter = [39.8283, -98.5795], // Center of USA defaultZoom = 4 }: CampaignMapProps) { const [locations, setLocations] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { fetchLocations(); }, []); async function fetchLocations() { try { const token = localStorage.getItem('godToken') || ''; const res = await fetch('/api/god/sql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-God-Token': token }, body: JSON.stringify({ query: ` SELECT id::text, ST_Y(location::geometry) as lat, ST_X(location::geometry) as lng, city, state, content_generated FROM geo_locations WHERE location IS NOT NULL LIMIT 1000 ` }) }); if (!res.ok) { setIsLoading(false); return; } const data = await res.json(); setLocations(data.rows || []); setIsLoading(false); } catch (error) { console.error('Failed to fetch locations:', error); setIsLoading(false); } } if (isLoading) { return (
Loading map data...
); } return (
{/* Tile Layer (Map Background) */} {/* Location Markers */} {locations.map((location) => (
{location.city || 'Unknown'}, {location.state || '??'}
Status: {location.content_generated ? '✅ Generated' : '⏳ Pending'}
{location.lat.toFixed(4)}, {location.lng.toFixed(4)}
))}
); }