💄 Trip itinerary: alternate day colors

This commit is contained in:
itskovacs 2025-08-06 22:09:30 +02:00
parent eedc3c576d
commit 1f4c1ae6cc

View File

@ -81,7 +81,7 @@ export class TripComponent implements AfterViewInit {
map?: L.Map; map?: L.Map;
markerClusterGroup?: L.MarkerClusterGroup; markerClusterGroup?: L.MarkerClusterGroup;
hoveredElement?: HTMLElement; hoveredElement?: HTMLElement;
tripMapAntLayer?: L.LayerGroup<any>; tripMapAntLayer?: L.FeatureGroup;
tripMapAntLayerDayID?: number; tripMapAntLayerDayID?: number;
readonly menuTripActionsItems: MenuItem[] = [ readonly menuTripActionsItems: MenuItem[] = [
@ -186,13 +186,13 @@ export class TripComponent implements AfterViewInit {
this.trip = trip; this.trip = trip;
this.flattenTripDayItems(); this.flattenTripDayItems();
this.updateTotalPrice(); this.updateTotalPrice();
this.setupMap(settings); this.initMap(settings);
}), }),
) )
.subscribe(); .subscribe();
} }
setupMap(settings: Settings): void { initMap(settings: Settings): void {
const contentMenuItems = [ const contentMenuItems = [
{ {
text: "Copy coordinates", text: "Copy coordinates",
@ -321,8 +321,9 @@ export class TripComponent implements AfterViewInit {
setTimeout(() => { setTimeout(() => {
this.map?.invalidateSize(); this.map?.invalidateSize();
this.resetMapBounds(); if (!this.tripMapAntLayer) this.resetMapBounds();
}, 50); else this.map?.fitBounds(this.tripMapAntLayer.getBounds());
}, 10);
} }
updateTotalPrice(n?: number) { updateTotalPrice(n?: number) {
@ -376,11 +377,44 @@ export class TripComponent implements AfterViewInit {
} }
} }
highlightTripPath( toggleTripDaysHighlight() {
items: { text: string; lat: number; lng: number; isPlace: boolean }[], if (this.tripMapAntLayerDayID == -1) {
layerId: number, this.map?.removeLayer(this.tripMapAntLayer!);
antDelay = 400, this.tripMapAntLayerDayID = undefined;
): void { this.tripMapAntLayer = undefined;
this.resetMapBounds();
return;
}
if (!this.trip) return;
const items = this.trip.days
.flatMap((day, idx) =>
day.items
.sort((a, b) => a.time.localeCompare(b.time))
.map((item) => {
let data = {
text: item.text,
isPlace: !!item.place,
idx: idx,
};
if (item.lat && item.lng)
return {
...data,
lat: item.lat,
lng: item.lng,
};
if (item.place)
return {
...data,
lat: item.place.lat,
lng: item.place.lng,
};
return undefined;
}),
)
.filter((n) => n !== undefined);
if (items.length < 2) { if (items.length < 2) {
this.utilsService.toast( this.utilsService.toast(
"info", "info",
@ -390,18 +424,37 @@ export class TripComponent implements AfterViewInit {
return; return;
} }
this.map?.fitBounds( const dayGroups: { [idx: number]: any } = {};
items.map((c) => [c.lat, c.lng]), items.forEach((item) => {
{ padding: [30, 30] }, if (!dayGroups[item.idx]) dayGroups[item.idx] = [];
); dayGroups[item.idx].push(item);
});
const layGroup = L.featureGroup();
const COLORS: string[] = [
"#e6194b",
"#3cb44b",
"#ffe119",
"#4363d8",
"#9a6324",
"#f58231",
"#911eb4",
"#46f0f0",
"#f032e6",
"#bcf60c",
"#fabebe",
"#008080",
"#e6beff",
"#808000",
];
Object.values(dayGroups).forEach((group, idx) => {
const path = antPath( const path = antPath(
items.map((c) => [c.lat, c.lng]), group.map((day: any) => [day.lat, day.lng]),
{ {
delay: antDelay, delay: 600,
dashArray: [10, 20], dashArray: [10, 20],
weight: 5, weight: 5,
color: "#0000FF", color: COLORS[idx % 14],
pulseColor: "#FFFFFF", pulseColor: "#FFFFFF",
paused: false, paused: false,
reverse: false, reverse: false,
@ -409,11 +462,16 @@ export class TripComponent implements AfterViewInit {
}, },
); );
const layGroup = L.layerGroup();
layGroup.addLayer(path); layGroup.addLayer(path);
items.forEach((item) => { group.forEach((day: any) => {
if (!item.isPlace) layGroup.addLayer(tripDayMarker(item)); if (!day.isPlace) layGroup.addLayer(tripDayMarker(day));
}); });
});
this.map?.fitBounds(
items.map((c) => [c.lat, c.lng]),
{ padding: [30, 30] },
);
if (this.tripMapAntLayer) { if (this.tripMapAntLayer) {
this.map?.removeLayer(this.tripMapAntLayer); this.map?.removeLayer(this.tripMapAntLayer);
@ -425,40 +483,7 @@ export class TripComponent implements AfterViewInit {
}, 200); }, 200);
this.tripMapAntLayer = layGroup; this.tripMapAntLayer = layGroup;
this.tripMapAntLayerDayID = layerId; this.tripMapAntLayerDayID = -1; //Hardcoded value for global trace
}
toggleTripDaysHighlight() {
if (this.tripMapAntLayerDayID == -1) {
this.map?.removeLayer(this.tripMapAntLayer!);
this.tripMapAntLayerDayID = undefined;
this.resetMapBounds();
return;
}
if (!this.trip) return;
const items = this.trip.days
.flatMap((day) => day.items.sort((a, b) => a.time.localeCompare(b.time)))
.map((item) => {
if (item.lat && item.lng)
return {
text: item.text,
lat: item.lat,
lng: item.lng,
isPlace: !!item.place,
};
if (item.place)
return {
text: item.text,
lat: item.place.lat,
lng: item.place.lng,
isPlace: true,
};
return undefined;
})
.filter((n) => n !== undefined);
this.highlightTripPath(items, -1, 600); //Hardcoded value for global trace
} }
toggleTripDayHighlightPathDay(day_id: number) { toggleTripDayHighlightPathDay(day_id: number) {
@ -466,6 +491,7 @@ export class TripComponent implements AfterViewInit {
if (this.tripMapAntLayerDayID == day_id) { if (this.tripMapAntLayerDayID == day_id) {
this.map?.removeLayer(this.tripMapAntLayer!); this.map?.removeLayer(this.tripMapAntLayer!);
this.tripMapAntLayerDayID = undefined; this.tripMapAntLayerDayID = undefined;
this.tripMapAntLayer = undefined;
this.resetMapBounds(); this.resetMapBounds();
return; return;
} }
@ -495,7 +521,51 @@ export class TripComponent implements AfterViewInit {
}) })
.filter((n) => n !== undefined); .filter((n) => n !== undefined);
this.highlightTripPath(items, day_id); if (items.length < 2) {
this.utilsService.toast(
"info",
"Info",
"Not enough values to map an itinerary",
);
return;
}
this.map?.fitBounds(
items.map((c) => [c.lat, c.lng]),
{ padding: [30, 30] },
);
const path = antPath(
items.map((c) => [c.lat, c.lng]),
{
delay: 400,
dashArray: [10, 20],
weight: 5,
color: "#0000FF",
pulseColor: "#FFFFFF",
paused: false,
reverse: false,
hardwareAccelerated: true,
},
);
const layGroup = L.featureGroup();
layGroup.addLayer(path);
items.forEach((item) => {
if (!item.isPlace) layGroup.addLayer(tripDayMarker(item));
});
if (this.tripMapAntLayer) {
this.map?.removeLayer(this.tripMapAntLayer);
this.tripMapAntLayerDayID = undefined;
}
setTimeout(() => {
layGroup.addTo(this.map!);
}, 200);
this.tripMapAntLayer = layGroup;
this.tripMapAntLayerDayID = day_id;
} }
onRowClick(item: FlattenedTripItem) { onRowClick(item: FlattenedTripItem) {