diff --git a/frontend/src/routes/collections/[id]/+page.svelte b/frontend/src/routes/collections/[id]/+page.svelte
index a63dbe5..b6ffac3 100644
--- a/frontend/src/routes/collections/[id]/+page.svelte
+++ b/frontend/src/routes/collections/[id]/+page.svelte
@@ -136,6 +136,66 @@
let adventures: Adventure[] = [];
+ // Add this after your existing MapLibre markers
+
+ // Add this after your existing MapLibre markers
+
+ // Create line data from orderedItems
+ $: lineData = createLineData(orderedItems);
+
+ // Function to create GeoJSON line data from ordered items
+ function createLineData(
+ items: Array<{
+ item: Adventure | Transportation | Lodging | Note | Checklist;
+ start: string;
+ end: string;
+ }>
+ ) {
+ if (items.length < 2) return null;
+
+ const coordinates: [number, number][] = [];
+
+ // Extract coordinates from each item
+ for (const orderItem of items) {
+ const item = orderItem.item;
+
+ if (
+ 'origin_longitude' in item &&
+ 'origin_latitude' in item &&
+ 'destination_longitude' in item &&
+ 'destination_latitude' in item &&
+ item.origin_longitude &&
+ item.origin_latitude &&
+ item.destination_longitude &&
+ item.destination_latitude
+ ) {
+ // For Transportation, add both origin and destination points
+ coordinates.push([item.origin_longitude, item.origin_latitude]);
+ coordinates.push([item.destination_longitude, item.destination_latitude]);
+ } else if ('longitude' in item && 'latitude' in item && item.longitude && item.latitude) {
+ // Handle Adventure and Lodging types
+ coordinates.push([item.longitude, item.latitude]);
+ }
+ }
+
+ // Only create line data if we have at least 2 coordinates
+ if (coordinates.length >= 2) {
+ return {
+ type: 'Feature' as const,
+ properties: {
+ name: 'Itinerary Path',
+ description: 'Path connecting chronological items'
+ },
+ geometry: {
+ type: 'LineString' as const,
+ coordinates: coordinates
+ }
+ };
+ }
+
+ return null;
+ }
+
let numVisited: number = 0;
let numAdventures: number = 0;
@@ -169,6 +229,63 @@
}
}
+ let orderedItems: Array<{
+ item: Adventure | Transportation | Lodging;
+ type: 'adventure' | 'transportation' | 'lodging';
+ start: string; // ISO date string
+ end: string; // ISO date string
+ }> = [];
+
+ $: {
+ // Reset ordered items
+ orderedItems = [];
+
+ // Add Adventures (using visit dates)
+ adventures.forEach((adventure) => {
+ adventure.visits.forEach((visit) => {
+ orderedItems.push({
+ item: adventure,
+ start: visit.start_date,
+ end: visit.end_date,
+ type: 'adventure'
+ });
+ });
+ });
+
+ // Add Transportation
+ transportations.forEach((transport) => {
+ if (transport.date) {
+ // Only add if date exists
+ orderedItems.push({
+ item: transport,
+ start: transport.date,
+ end: transport.end_date || transport.date, // Use end_date if available, otherwise use date,
+ type: 'transportation'
+ });
+ }
+ });
+
+ // Add Lodging
+ lodging.forEach((lodging) => {
+ if (lodging.check_in) {
+ // Only add if check_in exists
+ orderedItems.push({
+ item: lodging,
+ start: lodging.check_in,
+ end: lodging.check_out || lodging.check_in, // Use check_out if available, otherwise use check_in,
+ type: 'lodging'
+ });
+ }
+ });
+
+ // Sort all items chronologically by start date
+ orderedItems.sort((a, b) => {
+ const dateA = new Date(a.start).getTime();
+ const dateB = new Date(b.start).getTime();
+ return dateA - dateB;
+ });
+ }
+
$: {
numAdventures = adventures.length;
numVisited = adventures.filter((adventure) => adventure.is_visited).length;
@@ -994,6 +1111,19 @@
{/if}
{/each}
+ {#if lineData}
+
{orderedItem.type}
+ {#if orderedItem.type === 'adventure'} + {#if orderedItem.item && 'images' in orderedItem.item} +