Add search and PARCOURSMOB integration
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 40s
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 40s
This commit is contained in:
161
themes/mms43/layouts/recherche.html
Normal file
161
themes/mms43/layouts/recherche.html
Normal file
@@ -0,0 +1,161 @@
|
||||
{{ define "main" }}
|
||||
<!-- Placeholder pour les données hydratées par Parcoursmob -->
|
||||
<script id="dynamic-data" type="application/json"></script>
|
||||
|
||||
{{ $iconSearch := resources.Get "images/picto/search_24dp_1F1F1F_FILL0_wght400_GRAD0_opsz24.svg" }}
|
||||
{{ $iconArrow := resources.Get "images/picto/arrow_right_alt_24dp_1F1F1F_FILL1_wght400_GRAD0_opsz24.svg" }}
|
||||
|
||||
<section class="page-recherche" x-data="rechercheApp()" :class="{ 'has-results': searched }">
|
||||
<!-- Formulaire de recherche (caché en mobile si recherche effectuée) -->
|
||||
<div class="search-form-container" :class="{ 'hide-on-mobile-searched': searched }">
|
||||
{{ partial "search-block.html" (dict "showTitle" false "action" "/recherche/") }}
|
||||
</div>
|
||||
|
||||
<!-- Résultats de recherche -->
|
||||
<template x-if="searched">
|
||||
<div class="search-results-wrapper">
|
||||
<!-- Carte en premier sur mobile -->
|
||||
<div class="mobile-map-container">
|
||||
<div id="mobile-map"></div>
|
||||
</div>
|
||||
|
||||
<!-- Résumé compact de recherche (mobile uniquement) -->
|
||||
<div class="compact-search-summary">
|
||||
<a href="/recherche/" class="compact-search-content">
|
||||
<div class="compact-search-route">
|
||||
<span class="compact-search-place" x-text="departureLabel"></span>
|
||||
{{ if $iconArrow }}<img src="{{ $iconArrow.RelPermalink }}" alt="" class="compact-search-arrow" />{{ end }}
|
||||
<span class="compact-search-place" x-text="destinationLabel"></span>
|
||||
</div>
|
||||
<div class="compact-search-date" x-text="formatSearchDate()"></div>
|
||||
</a>
|
||||
<a href="/recherche/" class="compact-search-icon">
|
||||
{{ if $iconSearch }}<img src="{{ $iconSearch.RelPermalink }}" alt="Modifier la recherche" />{{ end }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{ partial "search-results.html" . }}
|
||||
</div>
|
||||
</template>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function rechercheApp() {
|
||||
const data = window.__PARCOURSMOB_DATA__ || {};
|
||||
|
||||
return {
|
||||
searched: data.searched || false,
|
||||
results: data.results || {},
|
||||
selectedJourney: null,
|
||||
departure: data.departure || null,
|
||||
destination: data.destination || null,
|
||||
departureDate: data.departure_date || '',
|
||||
departureTime: data.departure_time || '',
|
||||
|
||||
get departureLabel() {
|
||||
return this.departure?.properties?.label || this.departure?.properties?.name || 'Départ';
|
||||
},
|
||||
|
||||
get destinationLabel() {
|
||||
return this.destination?.properties?.label || this.destination?.properties?.name || 'Destination';
|
||||
},
|
||||
|
||||
formatSearchDate() {
|
||||
if (!this.departureDate) return '';
|
||||
const [year, month, day] = this.departureDate.split('-');
|
||||
const date = new Date(year, month - 1, day);
|
||||
const formatted = date.toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long' });
|
||||
return this.departureTime ? formatted + ' à ' + this.departureTime : formatted;
|
||||
},
|
||||
|
||||
get totalResults() {
|
||||
const r = this.results;
|
||||
return (r.solidarity_drivers?.number || 0) +
|
||||
(r.organized_carpools?.number || 0) +
|
||||
(r.public_transit?.number || 0) +
|
||||
(r.vehicles?.number || 0) +
|
||||
(r.local_solutions?.number || 0);
|
||||
},
|
||||
|
||||
showJourneyOnMap(journey, index) {
|
||||
console.log('showJourneyOnMap called', index, journey);
|
||||
this.selectedJourney = index;
|
||||
|
||||
if (!window.parcoursmobMap) {
|
||||
console.log('Map not found');
|
||||
return;
|
||||
}
|
||||
const map = window.parcoursmobMap;
|
||||
|
||||
// Supprimer l'ancien tracé s'il existe
|
||||
if (map.getSource('journey-route')) {
|
||||
map.removeLayer('journey-route-line');
|
||||
map.removeSource('journey-route');
|
||||
}
|
||||
|
||||
// Collecter toutes les coordonnées des legs
|
||||
const coordinates = [];
|
||||
|
||||
journey.legs.forEach(leg => {
|
||||
if (leg.legGeometry && leg.legGeometry.points) {
|
||||
try {
|
||||
const decoded = polyline.decode(leg.legGeometry.points);
|
||||
decoded.forEach(point => {
|
||||
const lng = point[1];
|
||||
const lat = point[0];
|
||||
if (lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180) {
|
||||
coordinates.push([lng, lat]);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Erreur décodage polyline:', e);
|
||||
}
|
||||
} else if (leg.from && leg.to) {
|
||||
const fromLng = leg.from.lon || leg.from.lng;
|
||||
const fromLat = leg.from.lat;
|
||||
const toLng = leg.to.lon || leg.to.lng;
|
||||
const toLat = leg.to.lat;
|
||||
|
||||
if (fromLat && fromLng) coordinates.push([fromLng, fromLat]);
|
||||
if (toLat && toLng) coordinates.push([toLng, toLat]);
|
||||
}
|
||||
});
|
||||
|
||||
if (coordinates.length < 2) return;
|
||||
|
||||
// Ajouter le tracé sur la carte
|
||||
map.addSource('journey-route', {
|
||||
type: 'geojson',
|
||||
data: {
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: coordinates
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
id: 'journey-route-line',
|
||||
type: 'line',
|
||||
source: 'journey-route',
|
||||
layout: {
|
||||
'line-join': 'round',
|
||||
'line-cap': 'round'
|
||||
},
|
||||
paint: {
|
||||
'line-color': '#283959',
|
||||
'line-width': 4
|
||||
}
|
||||
});
|
||||
|
||||
// Ajuster la vue pour montrer tout le tracé
|
||||
const bounds = new maplibregl.LngLatBounds();
|
||||
coordinates.forEach(coord => bounds.extend(coord));
|
||||
map.fitBounds(bounds, { padding: 50 });
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user