From 126761004cdadbf0708ea013a87663f793b2c28c Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sun, 16 Aug 2026 13:53:38 +0300 Subject: [PATCH] feat: enhance basemaps palette with Google Hybrid and Esri Clarity, remove carto, instant road approve update --- apps/web/src/pages/CompareView.tsx | 21 +++++++----- apps/web/src/pages/IntelligenceDashboard.tsx | 36 +++++++++++++------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/apps/web/src/pages/CompareView.tsx b/apps/web/src/pages/CompareView.tsx index 3b1fa6a..32c1efb 100644 --- a/apps/web/src/pages/CompareView.tsx +++ b/apps/web/src/pages/CompareView.tsx @@ -21,16 +21,19 @@ import { attachIconLoader } from '../utils/mapIcons'; // absolute — an empty default resolved to the app host, which serves no tiles. const TILES = (import.meta as any).env.VITE_TILES_URL || 'https://tiles.intaleqapp.com'; -type RefKey = 'google-sat' | 'esri-sat' | 'esri-streets' | 'osm' | 'here-sat' | 'here-streets' | 'carto-voyager'; +type RefKey = 'google-hybrid' | 'google-sat' | 'google-streets' | 'esri-sat' | 'esri-clarity' | 'esri-streets' | 'esri-topo' | 'osm' | 'here-sat' | 'here-streets'; const getRefs = (hereKey: string): Record => ({ - 'google-sat': { label: '🛰️ Google Satellite', tiles: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, - 'esri-sat': { label: '🛰️ Esri Satellite', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri, Maxar', maxzoom: 19 }, - 'esri-streets': { label: '🗺️ Esri Streets', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, - 'here-sat': { label: '🛰️ HERE Satellite', tiles: `https://maps.hereapi.com/v3/base/mc/{z}/{x}/{y}/jpeg?style=hybrid.day&apiKey=${hereKey || 'YOUR_HERE_API_KEY'}`, attribution: '© HERE Technologies', maxzoom: 19 }, - 'here-streets': { label: '🗺️ HERE Streets', tiles: `https://maps.hereapi.com/v3/base/mc/{z}/{x}/{y}/png8?style=explore.day&apiKey=${hereKey || 'YOUR_HERE_API_KEY'}`, attribution: '© HERE Technologies', maxzoom: 19 }, - 'carto-voyager': { label: '🎨 Carto Voyager', tiles: 'https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', attribution: '© CARTO, © OpenStreetMap', maxzoom: 19 }, - 'osm': { label: '🧭 OSM Standard', tiles: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: '© OpenStreetMap', maxzoom: 19 }, + 'google-hybrid': { label: '🛰️ Google Hybrid', tiles: 'https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, + 'google-sat': { label: '🛰️ Google Sat', tiles: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, + 'google-streets': { label: '🗺️ Google Streets', tiles: 'https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, + 'esri-sat': { label: '🛰️ Esri Satellite', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri, Maxar', maxzoom: 19 }, + 'esri-clarity': { label: '✨ Esri Clarity', tiles: 'https://clarity.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, + 'esri-streets': { label: '🗺️ Esri Streets', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, + 'esri-topo': { label: '🏔️ Esri Topo', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, + 'here-sat': { label: '🛰️ HERE Satellite', tiles: `https://maps.hereapi.com/v3/base/mc/{z}/{x}/{y}/jpeg?style=hybrid.day&apiKey=${hereKey || 'YOUR_HERE_API_KEY'}`, attribution: '© HERE Technologies', maxzoom: 19 }, + 'here-streets': { label: '🗺️ HERE Streets', tiles: `https://maps.hereapi.com/v3/base/mc/{z}/{x}/{y}/png8?style=explore.day&apiKey=${hereKey || 'YOUR_HERE_API_KEY'}`, attribution: '© HERE Technologies', maxzoom: 19 }, + 'osm': { label: '🧭 OSM Standard', tiles: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: '© OpenStreetMap', maxzoom: 19 }, }); const rasterStyle = (ref: { tiles: string; attribution: string; maxzoom: number }): any => ({ @@ -52,7 +55,7 @@ const CompareView: React.FC = () => { const [showKeyModal, setShowKeyModal] = useState(false); const [tempKey, setTempKey] = useState(''); - const [refKey, setRefKey] = useState('esri-sat'); + const [refKey, setRefKey] = useState('google-hybrid'); const [center, setCenter] = useState<{ lng: number; lat: number; zoom: number }>({ lng: 35.91, lat: 31.95, zoom: 15 }); const REFS = getRefs(hereApiKey); diff --git a/apps/web/src/pages/IntelligenceDashboard.tsx b/apps/web/src/pages/IntelligenceDashboard.tsx index e83abf0..ef8d440 100644 --- a/apps/web/src/pages/IntelligenceDashboard.tsx +++ b/apps/web/src/pages/IntelligenceDashboard.tsx @@ -5,13 +5,20 @@ import { Activity, Map as MapIcon, Settings, ShieldAlert, CheckCircle2, XCircle, interface CandidateRoad { id: string; uniqueDriverCount: number; totalPoints: number; lengthMeters: number; confidence: number; status: string; source?: string; name?: string; highway?: string; geometry?: any; } interface Closure { segmentId: string; sampleCount: number; lastUpdated: string; } -type RefKey = 'google-sat' | 'esri-sat' | 'esri-streets' | 'osm'; -const REFS: Record = { - 'google-sat': { label: '🛰️ Google Satellite', tiles: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, - 'esri-sat': { label: '🛰️ Esri Satellite', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri, Maxar', maxzoom: 19 }, - 'esri-streets': { label: '🗺️ Esri Streets', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, - 'osm': { label: '🧭 OSM Standard', tiles: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: '© OpenStreetMap', maxzoom: 19 }, -}; +type RefKey = 'google-hybrid' | 'google-sat' | 'google-streets' | 'esri-sat' | 'esri-clarity' | 'esri-streets' | 'esri-topo' | 'osm' | 'here-sat' | 'here-streets'; + +const getRefs = (hereKey: string): Record => ({ + 'google-hybrid': { label: '🛰️ Google Hybrid', tiles: 'https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, + 'google-sat': { label: '🛰️ Google Sat', tiles: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, + 'google-streets': { label: '🗺️ Google Streets', tiles: 'https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', attribution: '© Google', maxzoom: 20 }, + 'esri-sat': { label: '🛰️ Esri Satellite', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri, Maxar', maxzoom: 19 }, + 'esri-clarity': { label: '✨ Esri Clarity', tiles: 'https://clarity.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, + 'esri-streets': { label: '🗺️ Esri Streets', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, + 'esri-topo': { label: '🏔️ Esri Topo', tiles: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', attribution: '© Esri', maxzoom: 19 }, + 'here-sat': { label: '🛰️ HERE Satellite', tiles: `https://maps.hereapi.com/v3/base/mc/{z}/{x}/{y}/jpeg?style=hybrid.day&apiKey=${hereKey || 'YOUR_HERE_API_KEY'}`, attribution: '© HERE', maxzoom: 19 }, + 'here-streets': { label: '🗺️ HERE Streets', tiles: `https://maps.hereapi.com/v3/base/mc/{z}/{x}/{y}/png8?style=explore.day&apiKey=${hereKey || 'YOUR_HERE_API_KEY'}`, attribution: '© HERE', maxzoom: 19 }, + 'osm': { label: '🧭 OSM Standard', tiles: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: '© OpenStreetMap', maxzoom: 19 }, +}); const API = (import.meta as any).env.VITE_API_URL || '/api'; @@ -19,7 +26,7 @@ const cc = (c: number) => c >= 0.8 ? '#22c55e' : c >= 0.6 ? '#eab308' : '#f97316 const rasterStyle = (ref: any): any => ({ version: 8, - sources: { ref: { type: 'raster', tiles: [ref.tiles], tileSize: 256, maxzoom: ref.maxzoom } }, + sources: { ref: { type: 'raster', tiles: [ref.tiles], tileSize: 256, maxzoom: ref.maxzoom, attribution: ref.attribution } }, layers: [{ id: 'ref', type: 'raster', source: 'ref' }], }); @@ -32,10 +39,11 @@ const IntelligenceDashboard: React.FC = () => { const [loading, setLoading] = useState(true); const [apiKey, setApiKey] = useState(localStorage.getItem('map_admin_key') || ''); const [needsAuth, setNeedsAuth] = useState(!localStorage.getItem('map_admin_key')); - const [sel, setSel] = useState(null); + const [hereApiKey, setHereApiKey] = useState(localStorage.getItem('here_api_key') || ''); + const REFS = getRefs(hereApiKey); // Right Map State - const [refKey, setRefKey] = useState('google-sat'); + const [refKey, setRefKey] = useState('google-hybrid'); const leftMapRef = useRef(null); const rightMapRef = useRef(null); @@ -301,8 +309,12 @@ const IntelligenceDashboard: React.FC = () => { if (a === 'approve') { const d = await res.json().catch(() => ({} as any)); setMsg(d.connected ? '✅ Approved & wired into the network.' : '✅ Approved — drawn on the map.'); + candsRef.current = candsRef.current.map(c => c.id === id ? { ...c, status: 'approved' } : c); + pushMapData(); } else { setMsg('🚫 Rejected.'); + candsRef.current = candsRef.current.filter(c => c.id !== id); + pushMapData(); } setSel(null); (leftMapRef.current?.getSource('hl') as maplibregl.GeoJSONSource)?.setData({ type: 'FeatureCollection', features: [] }); @@ -575,9 +587,9 @@ const IntelligenceDashboard: React.FC = () => {
-
+
{(Object.keys(REFS) as Array).map(k => ( - ))}