import { useState, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Marker, Popup } from 'react-map-gl/maplibre'; import type { OsintItem } from '../services/osint'; const CAT_COLOR: Record = { maritime_accident: '#ef4444', fishing: '#22c55e', maritime_traffic: '#3b82f6', military: '#f97316', shipping: '#eab308', }; const CAT_ICON: Record = { maritime_accident: '🚨', fishing: '🐟', maritime_traffic: '🚢', military: '🎯', shipping: '🚢', }; function useTimeAgo() { const { t } = useTranslation(); return (ts: number): string => { const diff = Date.now() - ts; const m = Math.floor(diff / 60000); if (m < 60) return t('time.minutesAgo', { count: m }); const h = Math.floor(m / 60); if (h < 24) return t('time.hoursAgo', { count: h }); return t('time.daysAgo', { count: Math.floor(h / 24) }); }; } interface Props { osintFeed: OsintItem[]; currentTime: number; } const THREE_HOURS = 3 * 60 * 60 * 1000; const ONE_HOUR = 3600000; const MAP_CATEGORIES = new Set(['maritime_accident', 'fishing', 'maritime_traffic', 'shipping', 'military']); export function OsintMapLayer({ osintFeed, currentTime }: Props) { const [selected, setSelected] = useState(null); const { t } = useTranslation(); const timeAgo = useTimeAgo(); const geoItems = useMemo(() => osintFeed.filter( (item): item is OsintItem & { lat: number; lng: number } => item.lat != null && item.lng != null && MAP_CATEGORIES.has(item.category) && (currentTime - item.timestamp) < THREE_HOURS ), [osintFeed, currentTime]); return ( <> {geoItems.map(item => { const color = CAT_COLOR[item.category] || '#888'; const isRecent = currentTime - item.timestamp < ONE_HOUR; return ( { e.originalEvent.stopPropagation(); setSelected(item); }}>
{CAT_ICON[item.category] || '📰'}
{isRecent && (
NEW
)}
); })} {selected && selected.lat != null && selected.lng != null && ( setSelected(null)} closeOnClick={false} anchor="bottom" maxWidth="320px" className="gl-popup">
{CAT_ICON[selected.category] || '📰'} OSINT
{selected.title}
{selected.category.replace('_', ' ').toUpperCase()} {selected.source} {timeAgo(selected.timestamp)}
{selected.url && ( {t('osintMap.viewOriginal')} )}
)} ); }