parcoursmob-default-theme/web/layouts/dashboard/_partials/drivers-map-widget.html

175 lines
7.3 KiB
HTML

{{define "drivers_map_widget"}}
<div class="bg-white overflow-hidden shadow rounded-2xl">
<div class="p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg leading-6 font-medium text-gray-900">
Carte des conducteurs
</h3>
</div>
<div id="drivers-map" class="w-full rounded-lg overflow-hidden border border-gray-200" style="height: 500px;"></div>
<div class="mt-4 flex items-center justify-center gap-6 text-sm">
{{if moduleAvailable "solidarity_transport"}}
<div class="flex items-center">
<div class="w-6 h-6 rounded-co bg-co-blue border border-white shadow-md mr-2"></div>
<span class="text-gray-700">Transport solidaire ({{len .solidarity_drivers}})</span>
</div>
{{end}}
{{if moduleAvailable "organized_carpool"}}
<div class="flex items-center">
<div class="w-6 h-6 rounded-co bg-co-green border border-white shadow-md mr-2"></div>
<span class="text-gray-700">Covoiturage solidaire ({{len .organized_carpool_drivers}})</span>
</div>
{{end}}
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Check if map libraries are available
if (typeof maplibregl === 'undefined' || typeof pmtiles === 'undefined') {
console.warn('Map libraries not available');
return;
}
// Initialize PMTiles protocol
let protocol = new pmtiles.Protocol();
maplibregl.addProtocol("pmtiles", protocol.tile);
// Initialize map centered on France with protomaps style
const map = new maplibregl.Map({
container: 'drivers-map',
style: '/public/maps/protomaps-light/style.json',
center: [2.3522, 48.8566], // Paris
zoom: 5
});
map.addControl(new maplibregl.NavigationControl(), 'top-right');
const bounds = new maplibregl.LngLatBounds();
let hasMarkers = false;
map.on('load', function() {
// Add solidarity transport drivers
{{if moduleAvailable "solidarity_transport"}}
const solidarityDrivers = [
{{range .solidarity_drivers}}
{{if .Data.address}}
{
name: '{{.Data.first_name}} {{.Data.last_name}}',
coordinates: {{if and .Data.address.geometry .Data.address.geometry.coordinates}}[{{index .Data.address.geometry.coordinates 0}}, {{index .Data.address.geometry.coordinates 1}}]{{else}}null{{end}},
address: {{if .Data.address.properties}}'{{.Data.address.properties.label}}'{{else}}''{{end}},
type: 'solidarity-transport',
driverId: '{{.ID}}'
},
{{end}}
{{end}}
].filter(d => d.coordinates !== null);
solidarityDrivers.forEach(function(driver) {
// Create custom marker element matching compact search style
const el = document.createElement('div');
el.className = 'w-8 h-8 rounded-co bg-co-blue border border-white shadow-md flex items-center justify-center cursor-pointer';
// User icon matching compact search
el.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
`;
const marker = new maplibregl.Marker({element: el})
.setLngLat(driver.coordinates)
.setPopup(new maplibregl.Popup({offset: 25, className: 'rounded-lg'})
.setHTML(`
<div class="p-3">
<a href="/app/solidarity-transport/drivers/${driver.driverId}" class="font-semibold text-sm text-gray-900 hover:text-co-blue">${driver.name}</a>
<p class="text-xs text-gray-600 mt-1">${driver.address}</p>
<p class="text-xs text-co-blue font-medium mt-2">Transport solidaire</p>
</div>
`))
.addTo(map);
bounds.extend(driver.coordinates);
hasMarkers = true;
});
{{end}}
// Add organized carpool drivers
{{if moduleAvailable "organized_carpool"}}
const organizedCarpoolDrivers = [
{{range .organized_carpool_drivers}}
{{if .Data.address}}
{
name: '{{.Data.first_name}} {{.Data.last_name}}',
coordinates: {{if and .Data.address.geometry .Data.address.geometry.coordinates}}[{{index .Data.address.geometry.coordinates 0}}, {{index .Data.address.geometry.coordinates 1}}]{{else}}null{{end}},
address: {{if .Data.address.properties}}'{{.Data.address.properties.label}}'{{else}}''{{end}},
type: 'organized-carpool',
driverId: '{{.ID}}'
},
{{end}}
{{end}}
].filter(d => d.coordinates !== null);
organizedCarpoolDrivers.forEach(function(driver) {
// Create custom marker element matching compact search style
const el = document.createElement('div');
el.className = 'w-8 h-8 rounded-co bg-co-green border border-white shadow-md flex items-center justify-center cursor-pointer';
// User icon matching compact search
el.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
`;
const marker = new maplibregl.Marker({element: el})
.setLngLat(driver.coordinates)
.setPopup(new maplibregl.Popup({offset: 25, className: 'rounded-lg'})
.setHTML(`
<div class="p-3">
<a href="/app/organized-carpool/drivers/${driver.driverId}" class="font-semibold text-sm text-gray-900 hover:text-co-green">${driver.name}</a>
<p class="text-xs text-gray-600 mt-1">${driver.address}</p>
<p class="text-xs text-co-green font-medium mt-2">Covoiturage solidaire</p>
</div>
`))
.addTo(map);
bounds.extend(driver.coordinates);
hasMarkers = true;
});
{{end}}
// Fit map to markers bounds with padding
if (hasMarkers) {
map.fitBounds(bounds, {
padding: 50,
maxZoom: 12
});
}
});
});
</script>
<style>
.maplibregl-popup-content {
padding: 0;
border-radius: 0.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.maplibregl-popup-close-button {
font-size: 20px;
padding: 4px;
color: #6B7280;
}
.maplibregl-popup-close-button:hover {
background-color: #F3F4F6;
color: #111827;
}
</style>
{{end}}