From 8890dd70b85efa90964410ebffc4c007bd4b3842 Mon Sep 17 00:00:00 2001 From: Sean Morley Date: Tue, 16 Dec 2025 17:30:00 -0500 Subject: [PATCH] feat: add compact display option to LocationCard and enhance lodging filtering in CollectionItineraryPlanner --- .../src/lib/components/LocationCard.svelte | 37 ++++++--- .../CollectionItineraryPlanner.svelte | 76 ++++++++++++------- .../src/routes/collections/[id]/+page.svelte | 1 + 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/frontend/src/lib/components/LocationCard.svelte b/frontend/src/lib/components/LocationCard.svelte index 20c7fab8..49ac20e2 100644 --- a/frontend/src/lib/components/LocationCard.svelte +++ b/frontend/src/lib/components/LocationCard.svelte @@ -30,6 +30,7 @@ export let user: User | null; export let collection: Collection | null = null; export let readOnly: boolean = false; + export let compact: boolean = false; // For compact grid display in itinerary let isCollectionModalOpen: boolean = false; let isWarningModalOpen: boolean = false; @@ -268,12 +269,22 @@ -
+
-
+
{adventure.name} @@ -288,14 +299,12 @@ {#if (adventure.user && adventure.user.uuid == user?.uuid) || (collection && user && collection.shared_with?.includes(user.uuid)) || (collection && user && collection.user == user.uuid)} - + {/if}
-
+
{#if adventure.location}
diff --git a/frontend/src/lib/components/locations/CollectionItineraryPlanner.svelte b/frontend/src/lib/components/locations/CollectionItineraryPlanner.svelte index 7e5f4092..0e1dac1c 100644 --- a/frontend/src/lib/components/locations/CollectionItineraryPlanner.svelte +++ b/frontend/src/lib/components/locations/CollectionItineraryPlanner.svelte @@ -51,21 +51,32 @@ const targetDate = DateTime.fromISO(dateISO).startOf('day'); + // Helper: only include lodging that has been added to the itinerary + function isLodgingScheduled(lodgingId: any): boolean { + return !!collection.itinerary?.some((it) => { + const objectType = it.item?.type || ''; + return objectType === 'lodging' && it.object_id === lodgingId; + }); + } + return collection.lodging.filter((lodging) => { + // Only consider lodging entries that have both check-in and check-out if (!lodging.check_in || !lodging.check_out) return false; + // Skip lodgings that are not scheduled in the itinerary + if (!isLodgingScheduled(lodging.id)) return false; + // Extract just the date portion (YYYY-MM-DD) to avoid timezone shifts - // check_in/check_out are stored as UTC midnight (e.g., "2025-06-28T00:00:00Z") const checkInDateStr = lodging.check_in.split('T')[0]; const checkOutDateStr = lodging.check_out.split('T')[0]; const checkIn = DateTime.fromISO(checkInDateStr).startOf('day'); const checkOut = DateTime.fromISO(checkOutDateStr).startOf('day'); - // The guest is staying overnight if: - // 1. The target date is AFTER the check-in date (not on check-in day - that's when we show full card) - // 2. The target date is BEFORE the check-out date (on check-out day they leave, no overnight) - return targetDate > checkIn && targetDate < checkOut; + // The guest is staying overnight if the target date is between + // check-in (inclusive) and check-out (exclusive). This includes the + // check-in night as requested. + return targetDate >= checkIn && targetDate < checkOut; }); } @@ -247,7 +258,7 @@
-
+
{#if day.items.length === 0}
handleDndConsider(dayIndex, e)} on:finalize={(e) => handleDndFinalize(dayIndex, e)} - class="space-y-4" + class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3" > {#each day.items as item, index (item.id)} {@const objectType = item.item?.type || ''} @@ -276,7 +289,7 @@ {@const isDraggingShadow = item[SHADOW_ITEM_MARKER_PROPERTY_NAME]}
-
+
- {index + 1} + #{index + 1}
{#if multiDay && objectType === 'lodging'} -
-
+
+
- Overnight + Multi-day
{/if} - -
+ +
{#if objectType === 'location'} - + {:else if objectType === 'transportation'} {:else if objectType === 'lodging'} @@ -429,9 +449,9 @@

-
+
{#each unscheduledItems as { type, item }} -
+