stable: finalized GIS aesthetics and Syria/Jordan routing synchronization

This commit is contained in:
Hamza-Ayed
2026-03-28 04:12:01 +03:00
parent d6f3b41b53
commit 592af8ce5c
203 changed files with 9711 additions and 119 deletions
+199 -89
View File
@@ -3,12 +3,14 @@ import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
interface MapComponentProps {
onMapLoad: (map: maplibregl.Map) => void;
onMapClick?: (lat: number, lng: number) => void;
show3D?: boolean;
showPOIs?: boolean;
}
const MapComponent: React.FC<MapComponentProps> = ({
onMapLoad,
onMapClick,
show3D = false,
showPOIs = true
}) => {
@@ -25,7 +27,7 @@ const MapComponent: React.FC<MapComponentProps> = ({
}
// Toggle POI Layers
const poiLayers = ['poi-circles', 'place-labels'];
const poiLayers = ['poi-icons', 'place-labels'];
poiLayers.forEach(layerId => {
if (map.current!.getLayer(layerId)) {
map.current!.setLayoutProperty(layerId, 'visibility', showPOIs ? 'visible' : 'none');
@@ -45,6 +47,8 @@ const MapComponent: React.FC<MapComponentProps> = ({
);
}
const tilesUrl = (import.meta as any).env.VITE_TILES_URL || 'https://tiles.intaleqapp.com';
try {
map.current = new maplibregl.Map({
container: mapContainer.current,
@@ -55,17 +59,17 @@ const MapComponent: React.FC<MapComponentProps> = ({
sources: {
'local-osm-polygons': {
type: 'vector',
tiles: ['http://localhost:3001/planet_osm_polygon/{z}/{x}/{y}'],
tiles: [`${tilesUrl}/planet_osm_polygon/{z}/{x}/{y}`],
maxzoom: 14
},
'local-osm-lines': {
type: 'vector',
tiles: ['http://localhost:3001/planet_osm_line/{z}/{x}/{y}'],
tiles: [`${tilesUrl}/planet_osm_line/{z}/{x}/{y}`],
maxzoom: 14
},
'local-osm-points': {
type: 'vector',
tiles: ['http://localhost:3001/planet_osm_point/{z}/{x}/{y}'],
tiles: [`${tilesUrl}/planet_osm_point/{z}/{x}/{y}`],
maxzoom: 14
}
},
@@ -73,7 +77,7 @@ const MapComponent: React.FC<MapComponentProps> = ({
{
id: 'background',
type: 'background',
paint: { 'background-color': '#f2efea' }
paint: { 'background-color': '#f8f9fa' }
},
{
id: 'water-layer',
@@ -81,17 +85,34 @@ const MapComponent: React.FC<MapComponentProps> = ({
source: 'local-osm-polygons',
'source-layer': 'planet_osm_polygon',
filter: ['in', 'natural', 'water', 'lake', 'riverbank'],
paint: { 'fill-color': '#aadaff' }
paint: { 'fill-color': '#a3ccff' }
},
{
id: 'park-layer',
type: 'fill',
source: 'local-osm-polygons',
'source-layer': 'planet_osm_polygon',
filter: ['in', 'leisure', 'park', 'garden', 'nature_reserve'],
paint: { 'fill-color': '#c8facc' }
filter: ['in', 'leisure', 'park', 'garden', 'nature_reserve', 'pitch'],
paint: { 'fill-color': '#dcedc8' }
},
{
id: 'landuse-layer',
type: 'fill',
source: 'local-osm-polygons',
'source-layer': 'planet_osm_polygon',
filter: ["in", "landuse", "residential", "commercial", "industrial", "cemetery"],
paint: {
"fill-color": [
"match",
["get", "landuse"],
"residential", "#f1f3f4",
"commercial", "#f8f9fa",
"industrial", "#f1f3f4",
"cemetery", "#dcedc8",
"#f1f3f4"
]
}
},
// Building 3D - User toggleable
{
id: 'building-3d',
type: 'fill-extrusion',
@@ -103,67 +124,131 @@ const MapComponent: React.FC<MapComponentProps> = ({
visibility: show3D ? 'visible' : 'none'
},
paint: {
'fill-extrusion-color': '#d9d0c9',
'fill-extrusion-height': 40,
'fill-extrusion-color': '#e8eaed',
'fill-extrusion-height': 20,
'fill-extrusion-base': 0,
'fill-extrusion-opacity': 0.8
}
},
// ROAD BORDERS (Casing)
{
id: 'road-border-high',
id: 'road-casing-minor',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'primary', 'secondary', 'tertiary', 'motorway'],
filter: ['in', 'highway', 'residential', 'service', 'unclassified', 'living_street', 'pedestrian', 'path', 'track'],
paint: {
'line-color': '#ccc',
'line-width': [
'interpolate', ['exponential', 1.5], ['zoom'],
12, 3,
16, 12
] as any
}
},
// ROAD CORES
{
id: 'road-layer-low',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'residential', 'service', 'unclassified'],
paint: { 'line-color': '#ffffff', 'line-width': 1.5 }
},
{
id: 'road-layer-high',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'primary', 'secondary', 'tertiary'],
paint: {
'line-color': '#fff',
'line-width': [
'interpolate', ['exponential', 1.5], ['zoom'],
12, 1.5,
16, 8
] as any
'line-color': '#d4d4d4',
'line-width': ['interpolate', ['linear'], ['zoom'], 13, 1, 16, 8] as any
}
},
{
id: 'road-layer-motorway',
id: 'road-core-minor',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['==', 'highway', 'motorway'],
filter: ['in', 'highway', 'residential', 'service', 'unclassified', 'living_street', 'pedestrian', 'path', 'track'],
paint: {
'line-color': '#f7d499',
'line-width': [
'interpolate', ['exponential', 1.5], ['zoom'],
12, 2.5,
16, 10
] as any
'line-color': '#ffffff',
'line-width': ['interpolate', ['linear'], ['zoom'], 13, 0.5, 16, 6] as any
}
},
{
id: 'road-casing-tertiary',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'tertiary', 'tertiary_link'],
paint: {
'line-color': '#e0e0e0',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 1.5, 16, 12] as any
}
},
{
id: 'road-core-tertiary',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'tertiary', 'tertiary_link'],
paint: {
'line-color': '#ffffff',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 1, 16, 9] as any
}
},
{
id: 'road-casing-secondary',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'secondary', 'secondary_link'],
paint: {
'line-color': '#cfd8dc',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 2, 16, 14] as any
}
},
{
id: 'road-core-secondary',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'secondary', 'secondary_link'],
paint: {
'line-color': '#f1f5f9',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 1.5, 16, 11] as any
}
},
{
id: 'road-casing-primary',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'primary', 'primary_link'],
paint: {
'line-color': '#facc15',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 3, 16, 16] as any
}
},
{
id: 'road-core-primary',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'primary', 'primary_link'],
paint: {
'line-color': '#fefce8',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 2, 16, 12] as any
}
},
{
id: 'road-casing-motorway-trunk',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'motorway', 'motorway_link', 'trunk', 'trunk_link'],
paint: {
'line-color': '#fb923c',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 4, 16, 18] as any
}
},
{
id: 'road-core-motorway-trunk',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
filter: ['in', 'highway', 'motorway', 'motorway_link', 'trunk', 'trunk_link'],
paint: {
'line-color': '#ffedd5',
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 2.5, 16, 14] as any
}
},
{
id: 'route-line',
type: 'line',
source: 'local-osm-lines',
'source-layer': 'planet_osm_line',
layout: { 'line-cap': 'round', 'line-join': 'round' },
paint: { 'line-color': '#3b82f6', 'line-width': 6, 'line-opacity': 0.8 },
filter: ['==', 'id', -1]
},
{
id: 'road-labels',
type: 'symbol',
@@ -173,30 +258,19 @@ const MapComponent: React.FC<MapComponentProps> = ({
layout: {
'text-field': '{name}',
'text-font': ['Noto Sans Regular'],
'text-size': 11,
'text-size': 13,
'symbol-placement': 'line',
'text-letter-spacing': 0.05,
'text-padding': 15,
'text-allow-overlap': false, // Avoid "black cloud"
'text-padding': 5,
'text-allow-overlap': false,
'text-ignore-placement': false
},
paint: {
'text-color': '#444',
'text-halo-color': '#fff',
'text-halo-width': 1.5
'text-color': '#3c4043',
'text-halo-color': 'rgba(255, 255, 255, 0.8)',
'text-halo-width': 2
}
},
// ROUTE LAYER - Placeholder for navigation results
{
id: 'route-line',
type: 'line',
source: 'local-osm-lines', // Use a source that exists and can be updated
'source-layer': 'planet_osm_line',
layout: { 'line-cap': 'round', 'line-join': 'round' },
paint: { 'line-color': '#3b82f6', 'line-width': 6, 'line-opacity': 0.8 },
filter: ['==', 'id', -1] // Initially hide
},
// POI ICONS - Professional categorization
{
id: 'poi-icons',
type: 'symbol',
@@ -208,8 +282,7 @@ const MapComponent: React.FC<MapComponentProps> = ({
'icon-image': [
'coalesce',
[
'match',
['get', 'shop'],
'match', ['get', 'shop'],
'supermarket', 'grocery-15',
'convenience', 'grocery-15',
'pharmacy', 'pharmacy-15',
@@ -217,8 +290,7 @@ const MapComponent: React.FC<MapComponentProps> = ({
''
],
[
'match',
['get', 'amenity'],
'match', ['get', 'amenity'],
'restaurant', 'restaurant-15',
'cafe', 'cafe-15',
'bank', 'bank-15',
@@ -226,34 +298,31 @@ const MapComponent: React.FC<MapComponentProps> = ({
'grave_yard', 'cemetery-15',
'school', 'school-15',
'university', 'college-15',
'place_of_worship', 'religious-christian-15', // Fallback for general
'place_of_worship', 'religious-christian-15',
'hospital', 'hospital-15',
'fuel', 'fuel-15',
''
],
[
'match',
['get', 'historic'],
'match', ['get', 'historic'],
'monument', 'monument-15',
'ruins', 'attraction-15',
'archaeological_site', 'attraction-15',
''
],
[
'match',
['get', 'tourism'],
'match', ['get', 'tourism'],
'museum', 'museum-15',
'hotel', 'hotel-15',
'attraction', 'attraction-15',
''
],
[
'match',
['get', 'landuse'],
'match', ['get', 'landuse'],
'cemetery', 'cemetery-15',
''
],
'marker-15' // Ultimate fallback
'marker-15'
],
'icon-size': 1.1,
'icon-padding': 2,
@@ -270,21 +339,19 @@ const MapComponent: React.FC<MapComponentProps> = ({
type: 'symbol',
source: 'local-osm-points',
'source-layer': 'planet_osm_point',
minzoom: 14, // Only show text at higher zoom to avoid clutter
minzoom: 13,
layout: {
'text-field': '{name}',
'text-font': ['Noto Sans Regular'],
'text-size': 12,
'text-size': ['interpolate', ['linear'], ['zoom'], 13, 12, 16, 16] as any,
'text-offset': [0, 1.5],
'text-anchor': 'top',
'text-padding': 5,
'text-allow-overlap': false,
'visibility': showPOIs ? 'visible' : 'none'
},
paint: {
'text-color': '#111',
'text-halo-color': '#fff',
'text-halo-width': 1.5
'text-color': '#222',
'text-halo-color': 'rgba(255, 255, 255, 0.9)',
'text-halo-width': 2
}
}
]
@@ -298,6 +365,12 @@ const MapComponent: React.FC<MapComponentProps> = ({
onMapLoad(map.current!);
});
map.current.on('click', (e) => {
if (onMapClick) {
onMapClick(e.lngLat.lat, e.lngLat.lng);
}
});
map.current.on('error', (e) => {
console.error("MapComponent: Map Error:", e);
});
@@ -314,7 +387,44 @@ const MapComponent: React.FC<MapComponentProps> = ({
};
}, []);
return <div ref={mapContainer} style={{ width: '100%', height: '100%' }} />;
return (
<div ref={mapContainer} style={{ width: '100%', height: '100%', position: 'relative' }}>
{/* Intaleq Branding Watermark */}
<div
style={{
position: 'absolute',
bottom: '10px',
left: '10px',
zIndex: 10,
display: 'flex',
alignItems: 'center',
backgroundColor: 'rgba(255, 255, 255, 0.7)',
padding: '4px 8px',
borderRadius: '4px',
pointerEvents: 'none',
userSelect: 'none',
gap: '6px'
}}
>
<img
src="/intaleq-logo.png"
alt="Intaleq"
style={{ height: '16px', filter: 'drop-shadow(0 1px 1px rgba(0,0,0,0.1))' }}
/>
<span
style={{
fontSize: '10px',
fontWeight: 600,
color: '#3c4043',
letterSpacing: '0.02em',
textTransform: 'uppercase'
}}
>
Powered by Intaleq
</span>
</div>
</div>
);
};
export default MapComponent;