feat(calendar): enhance event handling with timezone support and filtering capabilities

This commit is contained in:
Sean Morley
2025-06-18 19:03:32 -04:00
parent 8b108c5797
commit eef8c92e82
20 changed files with 793 additions and 70 deletions

View File

@@ -8,6 +8,8 @@
import DeleteWarning from './DeleteWarning.svelte';
import { LODGING_TYPES_ICONS } from '$lib';
import { formatDateInTimezone } from '$lib/dateUtils';
import { formatAllDayDate } from '$lib/dateUtils';
import { isAllDay } from '$lib';
const dispatch = createEventDispatcher();
@@ -96,8 +98,8 @@
>
<div class="card-body p-6 space-y-4">
<!-- Header -->
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
<h2 class="text-xl font-bold truncate">{lodging.name}</h2>
<div class="flex flex-col gap-3">
<h2 class="text-xl font-bold break-words">{lodging.name}</h2>
<div class="flex flex-wrap gap-2">
<div class="badge badge-secondary">
{$t(`lodging.${lodging.type}`)}
@@ -122,10 +124,15 @@
<div class="flex items-center gap-2">
<span class="text-sm font-medium">{$t('adventures.dates')}:</span>
<p class="text-sm">
{formatDateInTimezone(lodging.check_in, lodging.timezone)}
{formatDateInTimezone(lodging.check_out, lodging.timezone)}
{#if lodging.timezone}
<span class="ml-1 text-xs opacity-60">({lodging.timezone})</span>
{#if isAllDay(lodging.check_in)}
{formatAllDayDate(lodging.check_in)}
{formatAllDayDate(lodging.check_out)}
{:else}
{formatDateInTimezone(lodging.check_in, lodging.timezone)}
{formatDateInTimezone(lodging.check_out, lodging.timezone)}
{#if lodging.timezone}
<span class="ml-1 text-xs opacity-60">({lodging.timezone})</span>
{/if}
{/if}
</p>
</div>

View File

@@ -22,19 +22,7 @@
label: string;
};
const LODGING_TYPES: LodgingType[] = [
{ value: 'hotel', label: 'Hotel' },
{ value: 'hostel', label: 'Hostel' },
{ value: 'resort', label: 'Resort' },
{ value: 'bnb', label: 'Bed & Breakfast' },
{ value: 'campground', label: 'Campground' },
{ value: 'cabin', label: 'Cabin' },
{ value: 'apartment', label: 'Apartment' },
{ value: 'house', label: 'House' },
{ value: 'villa', label: 'Villa' },
{ value: 'motel', label: 'Motel' },
{ value: 'other', label: 'Other' }
];
let lodgingTimezone: string | undefined = lodging.timezone ?? undefined;
// Initialize hotel with values from lodgingToEdit or default values
function initializeLodging(lodgingToEdit: Lodging | null): Lodging {
@@ -304,7 +292,8 @@
type="lodging"
bind:utcStartDate={lodging.check_in}
bind:utcEndDate={lodging.check_out}
bind:selectedStartTimezone={lodging.timezone}
bind:selectedStartTimezone={lodgingTimezone}
{collection}
/>
<!-- Location Information -->

View File

@@ -147,6 +147,25 @@ export function formatUTCDate(utcDate: string | null): string {
return dateTime.toISO()?.slice(0, 16).replace('T', ' ') || '';
}
/**
* Format all-day date for display without timezone conversion
* @param dateString - Date string in ISO format (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS)
* @returns Formatted date string (e.g., "Jun 1, 2025")
*/
export function formatAllDayDate(dateString: string): string {
if (!dateString) return '';
// Extract just the date part and add midday time to avoid timezone issues
const datePart = dateString.split('T')[0];
const dateWithMidday = `${datePart}T12:00:00`;
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
}).format(new Date(dateWithMidday));
}
export const VALID_TIMEZONES = [
'Africa/Abidjan',
'Africa/Accra',