import { useState } from 'react' import { MapContainer, TileLayer, CircleMarker, Popup } from 'react-leaflet' import { useQuery } from '@tanstack/react-query' import api from '../lib/api' import 'leaflet/dist/leaflet.css' interface Opportunity { state: string municipality: string latitude: number longitude: number topic: string urgency: string confidence: number meeting_date: string title?: string bill_id?: string session?: string latest_action?: string } const urgencyColors: Record = { critical: '#dc2626', high: '#f97316', medium: '#fbbf24', low: '#22c55e', } export default function Heatmap() { const [selectedState, setSelectedState] = useState(null) const [selectedTopic, setSelectedTopic] = useState(null) const { data: opportunities, isLoading } = useQuery({ queryKey: ['opportunities', selectedState, selectedTopic], queryFn: async () => { const params = new URLSearchParams() if (selectedState) params.append('state', selectedState) if (selectedTopic) params.append('topic', selectedTopic) const response = await api.get(`/opportunities?${params}`) return response.data.opportunities || [] }, }) if (isLoading) { return
Loading map...
} return (
{/* Filters */}
{/* Legend */}

Urgency Level

{Object.entries(urgencyColors).map(([level, color]) => (
{level}
))}
{/* Map */}
{opportunities?.map((opp, idx) => (

{opp.municipality}, {opp.state}

{opp.title && (

Bill: {opp.bill_id} - {opp.title.substring(0, 100)} {opp.title.length > 100 ? '...' : ''}

)}

Topic: {opp.topic.replace(/_/g, ' ')}

Urgency: {opp.urgency}

Confidence: {(opp.confidence * 100).toFixed(0)}%

Last Updated: {new Date(opp.meeting_date).toLocaleDateString()}

{opp.latest_action && (

Status: {opp.latest_action.substring(0, 80)} {opp.latest_action.length > 80 ? '...' : ''}

)}
))}
{/* Summary */}

Summary

Showing {opportunities?.length || 0} advocacy opportunities {selectedState && ` in ${selectedState}`} {selectedTopic && ` for ${selectedTopic.replace(/_/g, ' ')}`}

) }