diff --git a/frontend/src/lib/components/DateRangeCollapse.svelte b/frontend/src/lib/components/DateRangeCollapse.svelte index 7ff595f..eeec650 100644 --- a/frontend/src/lib/components/DateRangeCollapse.svelte +++ b/frontend/src/lib/components/DateRangeCollapse.svelte @@ -263,7 +263,9 @@ {#if allDay} @@ -295,7 +297,11 @@ {#if localStartDate}
{#if allDay} diff --git a/frontend/src/lib/components/LodgingModal.svelte b/frontend/src/lib/components/LodgingModal.svelte index 5db3818..6eb97a2 100644 --- a/frontend/src/lib/components/LodgingModal.svelte +++ b/frontend/src/lib/components/LodgingModal.svelte @@ -7,6 +7,8 @@ import LocationDropdown from './LocationDropdown.svelte'; import DateRangeCollapse from './DateRangeCollapse.svelte'; import { isAllDay } from '$lib'; + // @ts-ignore + import { DateTime } from 'luxon'; const dispatch = createEventDispatcher(); @@ -85,19 +87,21 @@ lodging.timezone = lodgingTimezone || null; + console.log(lodgingTimezone); + // Auto-set end date if missing but start date exists if (lodging.check_in && !lodging.check_out) { - const startDate = new Date(lodging.check_in); - const nextDay = new Date(startDate); - nextDay.setDate(nextDay.getDate() + 1); - if (isAllDay(lodging.check_in)) { - // For all-day, set to next day at 00:00:00 - lodging.check_out = nextDay.toISOString().split('T')[0] + 'T00:00:00'; + // For all-day, just add one day and keep at UTC 00:00:00 + const start = DateTime.fromISO(lodging.check_in, { zone: 'utc' }); + const nextDay = start.plus({ days: 1 }); + lodging.check_out = nextDay.toISO(); } else { - // For timed events, set to next day at 9:00 AM - nextDay.setHours(9, 0, 0, 0); - lodging.check_out = nextDay.toISOString(); + // For timed events, set to next day at 9:00 AM in lodging's timezone, then convert to UTC + const start = DateTime.fromISO(lodging.check_in, { zone: lodging.timezone || 'utc' }); + const nextDay = start.plus({ days: 1 }); + const end = nextDay.set({ hour: 9, minute: 0, second: 0, millisecond: 0 }); + lodging.check_out = end.toUTC().toISO(); } } diff --git a/frontend/src/lib/index.ts b/frontend/src/lib/index.ts index 4f890e8..21bee80 100644 --- a/frontend/src/lib/index.ts +++ b/frontend/src/lib/index.ts @@ -70,66 +70,57 @@ export function groupAdventuresByDate( ): Record { const groupedAdventures: Record = {}; - // Initialize all days in the range + // Initialize all days in the range using DateTime for (let i = 0; i < numberOfDays; i++) { - const currentDate = new Date(startDate); - currentDate.setDate(startDate.getDate() + i); - const dateString = getLocalDateString(currentDate); + const currentDate = DateTime.fromJSDate(startDate).plus({ days: i }); + const dateString = currentDate.toISODate(); // 'YYYY-MM-DD' groupedAdventures[dateString] = []; } adventures.forEach((adventure) => { adventure.visits.forEach((visit) => { if (visit.start_date) { - // Check if this is an all-day event (both start and end at midnight) - const isAllDayEvent = - isAllDay(visit.start_date) && (visit.end_date ? isAllDay(visit.end_date) : false); + // Check if it's all-day: start has 00:00:00 AND (no end OR end also has 00:00:00) + const startHasZeros = visit.start_date.includes('T00:00:00'); + const endHasZeros = visit.end_date ? visit.end_date.includes('T00:00:00') : true; + const isAllDayEvent = startHasZeros && endHasZeros; - // For all-day events, we need to handle dates differently - if (isAllDayEvent && visit.end_date) { - // Extract just the date parts without time - const startDateStr = visit.start_date.split('T')[0]; - const endDateStr = visit.end_date.split('T')[0]; + let startDT: DateTime; + let endDT: DateTime; - // Loop through all days in the range - for (let i = 0; i < numberOfDays; i++) { - const currentDate = new Date(startDate); - currentDate.setDate(startDate.getDate() + i); - const currentDateStr = getLocalDateString(currentDate); + if (isAllDayEvent) { + // For all-day events, extract just the date part and ignore timezone + const dateOnly = visit.start_date.split('T')[0]; // Get 'YYYY-MM-DD' + startDT = DateTime.fromISO(dateOnly); // This creates a date without time/timezone - // Include the current day if it falls within the adventure date range - if (currentDateStr >= startDateStr && currentDateStr <= endDateStr) { - if (groupedAdventures[currentDateStr]) { - groupedAdventures[currentDateStr].push(adventure); - } - } - } + endDT = visit.end_date + ? DateTime.fromISO(visit.end_date.split('T')[0]) + : startDT; } else { - // Handle regular events with time components - const adventureStartDate = new Date(visit.start_date); - const adventureDateStr = getLocalDateString(adventureStartDate); + // For timed events, use timezone conversion + startDT = DateTime.fromISO(visit.start_date, { + zone: visit.timezone ?? 'UTC' + }); - if (visit.end_date) { - const adventureEndDate = new Date(visit.end_date); - const endDateStr = getLocalDateString(adventureEndDate); + endDT = visit.end_date + ? DateTime.fromISO(visit.end_date, { + zone: visit.timezone ?? 'UTC' + }) + : startDT; + } - // Loop through all days and include adventure if it falls within the range - for (let i = 0; i < numberOfDays; i++) { - const currentDate = new Date(startDate); - currentDate.setDate(startDate.getDate() + i); - const dateString = getLocalDateString(currentDate); + const startDateStr = startDT.toISODate(); + const endDateStr = endDT.toISODate(); - // Include the current day if it falls within the adventure date range - if (dateString >= adventureDateStr && dateString <= endDateStr) { - if (groupedAdventures[dateString]) { - groupedAdventures[dateString].push(adventure); - } - } - } - } else { - // If there's no end date, add adventure to the start date only - if (groupedAdventures[adventureDateStr]) { - groupedAdventures[adventureDateStr].push(adventure); + // Loop through all days in range + for (let i = 0; i < numberOfDays; i++) { + const currentDate = DateTime.fromJSDate(startDate).plus({ days: i }); + const currentDateStr = currentDate.toISODate(); + + // Include the current day if it falls within the adventure date range + if (currentDateStr >= startDateStr && currentDateStr <= endDateStr) { + if (groupedAdventures[currentDateStr]) { + groupedAdventures[currentDateStr].push(adventure); } } } diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 33308ba..c007da1 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -244,7 +244,9 @@ "done": "Erledigt", "loading_adventures": "Ladeabenteuer ...", "name_location": "Name, Ort", - "collection_contents": "Sammelinhalt" + "collection_contents": "Sammelinhalt", + "check_in": "Einchecken", + "check_out": "Kasse" }, "home": { "desc_1": "Entdecken, planen und erkunden Sie mühelos", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 82e2fa4..31c0614 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -98,6 +98,8 @@ "latitude": "Latitude", "visit": "Visit", "timed": "Timed", + "check_in": "Check In", + "check_out": "Check Out", "coordinates": "Coordinates", "copy_coordinates": "Copy Coordinates", "visits": "Visits", diff --git a/frontend/src/locales/es.json b/frontend/src/locales/es.json index 61f54e7..fcf8502 100644 --- a/frontend/src/locales/es.json +++ b/frontend/src/locales/es.json @@ -296,7 +296,9 @@ "done": "Hecho", "loading_adventures": "Cargando aventuras ...", "name_location": "Nombre, ubicación", - "collection_contents": "Contenido de la colección" + "collection_contents": "Contenido de la colección", + "check_in": "Registrarse", + "check_out": "Verificar" }, "worldtravel": { "all": "Todo", diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index c8412ce..9e61eb8 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -244,7 +244,9 @@ "done": "Fait", "loading_adventures": "Chargement des aventures ...", "name_location": "nom, emplacement", - "collection_contents": "Contenu de la collection" + "collection_contents": "Contenu de la collection", + "check_in": "Enregistrement", + "check_out": "Vérifier" }, "home": { "desc_1": "Découvrez, planifiez et explorez en toute simplicité", diff --git a/frontend/src/locales/it.json b/frontend/src/locales/it.json index 9a1060b..ce522e0 100644 --- a/frontend/src/locales/it.json +++ b/frontend/src/locales/it.json @@ -244,7 +244,9 @@ "done": "Fatto", "loading_adventures": "Caricamento di avventure ...", "name_location": "Nome, posizione", - "collection_contents": "Contenuto di raccolta" + "collection_contents": "Contenuto di raccolta", + "check_in": "Check -in", + "check_out": "Guardare" }, "home": { "desc_1": "Scopri, pianifica ed esplora con facilità", diff --git a/frontend/src/locales/ko.json b/frontend/src/locales/ko.json index 3b2cd2d..f23fc7b 100644 --- a/frontend/src/locales/ko.json +++ b/frontend/src/locales/ko.json @@ -244,7 +244,9 @@ "done": "완료", "loading_adventures": "적재 모험 ...", "name_location": "이름, 위치", - "collection_contents": "수집 내용" + "collection_contents": "수집 내용", + "check_in": "체크인", + "check_out": "체크 아웃" }, "auth": { "confirm_password": "비밀번호 확인", diff --git a/frontend/src/locales/nl.json b/frontend/src/locales/nl.json index e060694..ec06221 100644 --- a/frontend/src/locales/nl.json +++ b/frontend/src/locales/nl.json @@ -244,7 +244,9 @@ "done": "Klaar", "loading_adventures": "Adventuren laden ...", "name_location": "naam, locatie", - "collection_contents": "Verzamelingsinhoud" + "collection_contents": "Verzamelingsinhoud", + "check_in": "Inchecken", + "check_out": "Uitchecken" }, "home": { "desc_1": "Ontdek, plan en verken met gemak", diff --git a/frontend/src/locales/no.json b/frontend/src/locales/no.json index b703275..b3b3539 100644 --- a/frontend/src/locales/no.json +++ b/frontend/src/locales/no.json @@ -296,7 +296,9 @@ "done": "Ferdig", "loading_adventures": "Laster opp eventyr ...", "name_location": "Navn, plassering", - "collection_contents": "Samlingsinnhold" + "collection_contents": "Samlingsinnhold", + "check_in": "Sjekk inn", + "check_out": "Sjekk ut" }, "worldtravel": { "country_list": "Liste over land", diff --git a/frontend/src/locales/pl.json b/frontend/src/locales/pl.json index 51c0324..af72437 100644 --- a/frontend/src/locales/pl.json +++ b/frontend/src/locales/pl.json @@ -296,7 +296,9 @@ "loading_adventures": "Ładowanie przygód ...", "name_location": "Nazwa, lokalizacja", "delete_collection_warning": "Czy na pewno chcesz usunąć tę kolekcję? \nTego działania nie można cofnąć.", - "collection_contents": "Zawartość kolekcji" + "collection_contents": "Zawartość kolekcji", + "check_in": "Zameldować się", + "check_out": "Wymeldować się" }, "worldtravel": { "country_list": "Lista krajów", diff --git a/frontend/src/locales/ru.json b/frontend/src/locales/ru.json index 149d2f1..7d063fe 100644 --- a/frontend/src/locales/ru.json +++ b/frontend/src/locales/ru.json @@ -296,7 +296,9 @@ "done": "Сделанный", "loading_adventures": "Загрузка приключений ...", "name_location": "имя, местоположение", - "collection_contents": "Содержание коллекции" + "collection_contents": "Содержание коллекции", + "check_in": "Регистрироваться", + "check_out": "Проверить" }, "worldtravel": { "country_list": "Список стран", diff --git a/frontend/src/locales/sv.json b/frontend/src/locales/sv.json index 309b984..87d747c 100644 --- a/frontend/src/locales/sv.json +++ b/frontend/src/locales/sv.json @@ -244,7 +244,9 @@ "done": "Gjort", "loading_adventures": "Laddar äventyr ...", "name_location": "namn, plats", - "collection_contents": "Insamlingsinnehåll" + "collection_contents": "Insamlingsinnehåll", + "check_in": "Checka in", + "check_out": "Checka ut" }, "home": { "desc_1": "Upptäck, planera och utforska med lätthet", diff --git a/frontend/src/locales/zh.json b/frontend/src/locales/zh.json index f111b07..55a98ce 100644 --- a/frontend/src/locales/zh.json +++ b/frontend/src/locales/zh.json @@ -296,7 +296,9 @@ "done": "完毕", "loading_adventures": "加载冒险...", "name_location": "名称,位置", - "collection_contents": "收集内容" + "collection_contents": "收集内容", + "check_in": "报到", + "check_out": "查看" }, "auth": { "forgot_password": "忘记密码?",