search: per-leg colored polylines + transit whole-day toggle
This commit is contained in:
@@ -2481,6 +2481,41 @@ a {
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transit-whole-day-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.65rem 1rem;
|
||||||
|
background-color: #dcfce7;
|
||||||
|
color: #166534;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transit-whole-day-toggle:hover {
|
||||||
|
background-color: #bbf7d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transit-whole-day-toggle.is-active {
|
||||||
|
background-color: #f3f4f6;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transit-whole-day-toggle.is-active:hover {
|
||||||
|
background-color: #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transit-whole-day-toggle img {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.transit-journey {
|
.transit-journey {
|
||||||
background-color: #f9fafb;
|
background-color: #f9fafb;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
|||||||
@@ -26,6 +26,16 @@
|
|||||||
<div class="accordion-inner">
|
<div class="accordion-inner">
|
||||||
<template x-if="results.public_transit?.number > 0">
|
<template x-if="results.public_transit?.number > 0">
|
||||||
<div class="transit-journeys">
|
<div class="transit-journeys">
|
||||||
|
<!-- Toggle Pareto best-options vs full-day listing. Reloads
|
||||||
|
the page with transit_whole_day flipped; the backend
|
||||||
|
switches transit-routing from PlanPareto to PlanProfile
|
||||||
|
across the requested day. -->
|
||||||
|
<button type="button" class="transit-whole-day-toggle"
|
||||||
|
:class="transitWholeDay ? 'is-active' : ''"
|
||||||
|
@click="toggleTransitWholeDay()">
|
||||||
|
{{ if $iconBus }}<img src="{{ $iconBus.RelPermalink }}" alt="" />{{ end }}
|
||||||
|
<span x-text="transitWholeDay ? 'Voir les meilleures options' : 'Voir tous les trajets de la journée'"></span>
|
||||||
|
</button>
|
||||||
<template x-for="(journey, index) in results.public_transit.results" :key="index">
|
<template x-for="(journey, index) in results.public_transit.results" :key="index">
|
||||||
<div class="transit-journey" @click="selectItem('transit', index, journey)" :class="{ 'active': isSelected('transit', index) }">
|
<div class="transit-journey" @click="selectItem('transit', index, journey)" :class="{ 'active': isSelected('transit', index) }">
|
||||||
<!-- En-tête du trajet -->
|
<!-- En-tête du trajet -->
|
||||||
@@ -422,14 +432,14 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Déterminer la couleur et le style selon le type de leg
|
// Déterminer la couleur et le style selon le type de leg.
|
||||||
|
// routeColor is already canonical "#RRGGBB" (transit-routing
|
||||||
|
// emits it that way; the parcoursmob adapter normalises Transitous
|
||||||
|
// to match). No extra '#' prefix.
|
||||||
const isWalk = leg.mode === 'WALK';
|
const isWalk = leg.mode === 'WALK';
|
||||||
let lineColor = '#888888'; // Gris par défaut pour la marche
|
const lineColor = isWalk
|
||||||
|
? '#888888'
|
||||||
if (!isWalk) {
|
: (leg.routeColor || '#283959');
|
||||||
// Utiliser la couleur de la route si disponible
|
|
||||||
lineColor = leg.routeColor ? '#' + leg.routeColor : '#283959';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter le layer
|
// Ajouter le layer
|
||||||
map.addLayer({
|
map.addLayer({
|
||||||
|
|||||||
@@ -51,6 +51,17 @@
|
|||||||
destination: data.destination || null,
|
destination: data.destination || null,
|
||||||
departureDate: data.departure_date || '',
|
departureDate: data.departure_date || '',
|
||||||
departureTime: data.departure_time || '',
|
departureTime: data.departure_time || '',
|
||||||
|
transitWholeDay: data.transit_whole_day || false,
|
||||||
|
|
||||||
|
toggleTransitWholeDay() {
|
||||||
|
const u = new URL(window.location.href);
|
||||||
|
if (u.searchParams.get('transit_whole_day') === '1') {
|
||||||
|
u.searchParams.delete('transit_whole_day');
|
||||||
|
} else {
|
||||||
|
u.searchParams.set('transit_whole_day', '1');
|
||||||
|
}
|
||||||
|
window.location.href = u.toString();
|
||||||
|
},
|
||||||
|
|
||||||
get departureLabel() {
|
get departureLabel() {
|
||||||
return this.departure?.properties?.label || this.departure?.properties?.name || 'Départ';
|
return this.departure?.properties?.label || this.departure?.properties?.name || 'Départ';
|
||||||
@@ -77,83 +88,11 @@
|
|||||||
(r.local_solutions?.number || 0);
|
(r.local_solutions?.number || 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// showJourneyOnMap is intentionally a no-op: the real route
|
||||||
|
// rendering lives in window.showJourneyRoute (search-results.html),
|
||||||
|
// invoked by selectionManager.selectItem.
|
||||||
showJourneyOnMap(journey, index) {
|
showJourneyOnMap(journey, index) {
|
||||||
console.log('showJourneyOnMap called', index, journey);
|
|
||||||
this.selectedJourney = index;
|
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 });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user