feat: add military bases map layer for Western Pacific

Add 18 US military bases (Japan, Guam, South Korea, Hawaii, Diego Garcia)
as a toggleable map layer. Follows the existing data center layer pattern:
static JSON → backend fetcher → slow-tier API → frontend GeoJSON layer.

Includes red circle markers with labels, click popups showing operator
and branch info, and a toggle in the left panel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
adust09
2026-03-16 00:33:35 +09:00
parent 130287bb49
commit 05de14af9d
11 changed files with 359 additions and 4 deletions
+22 -1
View File
@@ -2,7 +2,7 @@
// Extracted from MaplibreViewer to reduce component size and enable unit testing.
// Each function takes data arrays + optional helpers and returns a GeoJSON FeatureCollection or null.
import type { Earthquake, GPSJammingZone, FireHotspot, InternetOutage, DataCenter, GDELTIncident, LiveUAmapIncident, CCTVCamera, KiwiSDR, FrontlineGeoJSON, UAV, Satellite, Ship, ActiveLayers } from "@/types/dashboard";
import type { Earthquake, GPSJammingZone, FireHotspot, InternetOutage, DataCenter, MilitaryBase, GDELTIncident, LiveUAmapIncident, CCTVCamera, KiwiSDR, FrontlineGeoJSON, UAV, Satellite, Ship, ActiveLayers } from "@/types/dashboard";
import { classifyAircraft } from "@/utils/aircraftClassification";
import { MISSION_COLORS, MISSION_ICON_MAP } from "@/components/map/icons/SatelliteIcons";
@@ -195,6 +195,27 @@ export function buildDataCentersGeoJSON(datacenters?: DataCenter[]): FC {
};
}
// ─── Military Bases ─────────────────────────────────────────────────────────
export function buildMilitaryBasesGeoJSON(bases?: MilitaryBase[]): FC {
if (!bases?.length) return null;
return {
type: 'FeatureCollection',
features: bases.map((base, i) => ({
type: 'Feature' as const,
properties: {
id: `milbase-${i}`,
type: 'military_base',
name: base.name || 'Unknown',
country: base.country || '',
operator: base.operator || '',
branch: base.branch || '',
},
geometry: { type: 'Point' as const, coordinates: [base.lng, base.lat] }
}))
};
}
// ─── GDELT Incidents ────────────────────────────────────────────────────────
export function buildGdeltGeoJSON(gdelt?: GDELTIncident[], inView?: InViewFilter): FC {