Merge branch 'development' into main
This commit is contained in:
@@ -6,6 +6,20 @@
|
||||
import { t } from 'svelte-i18n';
|
||||
export let collection: Collection | null = null;
|
||||
|
||||
let fullStartDate: string = '';
|
||||
let fullEndDate: string = '';
|
||||
let fullStartDateOnly: string = '';
|
||||
let fullEndDateOnly: string = '';
|
||||
let allDay: boolean = true;
|
||||
|
||||
// Set full start and end dates from collection
|
||||
if (collection && collection.start_date && collection.end_date) {
|
||||
fullStartDate = `${collection.start_date}T00:00`;
|
||||
fullEndDate = `${collection.end_date}T23:59`;
|
||||
fullStartDateOnly = collection.start_date;
|
||||
fullEndDateOnly = collection.end_date;
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let images: { id: string; image: string; is_primary: boolean }[] = [];
|
||||
@@ -72,7 +86,7 @@
|
||||
|
||||
import ActivityComplete from './ActivityComplete.svelte';
|
||||
import CategoryDropdown from './CategoryDropdown.svelte';
|
||||
import { findFirstValue } from '$lib';
|
||||
import { findFirstValue, isAllDay } from '$lib';
|
||||
import MarkdownEditor from './MarkdownEditor.svelte';
|
||||
import ImmichSelect from './ImmichSelect.svelte';
|
||||
import Star from '~icons/mdi/star';
|
||||
@@ -379,7 +393,10 @@
|
||||
let new_start_date: string = '';
|
||||
let new_end_date: string = '';
|
||||
let new_notes: string = '';
|
||||
|
||||
// Function to add a new visit.
|
||||
function addNewVisit() {
|
||||
// If an end date isn’t provided, assume it’s the same as start.
|
||||
if (new_start_date && !new_end_date) {
|
||||
new_end_date = new_start_date;
|
||||
}
|
||||
@@ -391,15 +408,31 @@
|
||||
addToast('error', $t('adventures.no_start_date'));
|
||||
return;
|
||||
}
|
||||
// Convert input to UTC if not already.
|
||||
if (new_start_date && !new_start_date.includes('Z')) {
|
||||
new_start_date = new Date(new_start_date).toISOString();
|
||||
}
|
||||
if (new_end_date && !new_end_date.includes('Z')) {
|
||||
new_end_date = new Date(new_end_date).toISOString();
|
||||
}
|
||||
|
||||
// If the visit is all day, force the times to midnight.
|
||||
if (allDay) {
|
||||
new_start_date = new_start_date.split('T')[0] + 'T00:00:00.000Z';
|
||||
new_end_date = new_end_date.split('T')[0] + 'T00:00:00.000Z';
|
||||
}
|
||||
|
||||
adventure.visits = [
|
||||
...adventure.visits,
|
||||
{
|
||||
start_date: new_start_date,
|
||||
end_date: new_end_date,
|
||||
notes: new_notes,
|
||||
id: ''
|
||||
id: '' // or generate an id as needed
|
||||
}
|
||||
];
|
||||
|
||||
// Clear the input fields.
|
||||
new_start_date = '';
|
||||
new_end_date = '';
|
||||
new_notes = '';
|
||||
@@ -669,13 +702,23 @@
|
||||
on:change={() => (constrainDates = !constrainDates)}
|
||||
/>
|
||||
{/if}
|
||||
<span class="label-text">{$t('adventures.all_day')}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="toggle toggle-primary"
|
||||
id="constrain_dates"
|
||||
name="constrain_dates"
|
||||
bind:checked={allDay}
|
||||
/>
|
||||
</label>
|
||||
<div class="flex gap-2 mb-1">
|
||||
{#if !constrainDates}
|
||||
{#if !allDay}
|
||||
<input
|
||||
type="date"
|
||||
type="datetime-local"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Start Date"
|
||||
placeholder={$t('adventures.start_date')}
|
||||
min={constrainDates ? fullStartDate : ''}
|
||||
max={constrainDates ? fullEndDate : ''}
|
||||
bind:value={new_start_date}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
@@ -685,10 +728,12 @@
|
||||
}}
|
||||
/>
|
||||
<input
|
||||
type="date"
|
||||
type="datetime-local"
|
||||
class="input input-bordered w-full"
|
||||
placeholder={$t('adventures.end_date')}
|
||||
bind:value={new_end_date}
|
||||
min={constrainDates ? fullStartDate : ''}
|
||||
max={constrainDates ? fullEndDate : ''}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
@@ -701,8 +746,8 @@
|
||||
type="date"
|
||||
class="input input-bordered w-full"
|
||||
placeholder={$t('adventures.start_date')}
|
||||
min={collection?.start_date}
|
||||
max={collection?.end_date}
|
||||
min={constrainDates ? fullStartDateOnly : ''}
|
||||
max={constrainDates ? fullEndDateOnly : ''}
|
||||
bind:value={new_start_date}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
@@ -716,8 +761,8 @@
|
||||
class="input input-bordered w-full"
|
||||
placeholder={$t('adventures.end_date')}
|
||||
bind:value={new_end_date}
|
||||
min={collection?.start_date}
|
||||
max={collection?.end_date}
|
||||
min={constrainDates ? fullStartDateOnly : ''}
|
||||
max={constrainDates ? fullEndDateOnly : ''}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
@@ -741,6 +786,31 @@
|
||||
}}
|
||||
></textarea>
|
||||
</div>
|
||||
{#if !allDay}
|
||||
<div role="alert" class="alert shadow-lg bg-neutral mt-2 mb-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
class="stroke-info h-6 w-6 shrink-0"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
></path>
|
||||
</svg>
|
||||
<span>
|
||||
{$t('lodging.current_timezone')}:
|
||||
{(() => {
|
||||
const tz = new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
const [continent, city] = tz.split('/');
|
||||
return `${continent} (${city.replace('_', ' ')})`;
|
||||
})()}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex gap-2">
|
||||
<button type="button" class="btn btn-neutral" on:click={addNewVisit}
|
||||
@@ -749,24 +819,86 @@
|
||||
</div>
|
||||
|
||||
{#if adventure.visits.length > 0}
|
||||
<h2 class=" font-bold text-xl mt-2">{$t('adventures.my_visits')}</h2>
|
||||
<h2 class="font-bold text-xl mt-2">{$t('adventures.my_visits')}</h2>
|
||||
{#each adventure.visits as visit}
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
<div class="flex gap-2 items-center">
|
||||
<p>
|
||||
{new Date(visit.start_date).toLocaleDateString(undefined, {
|
||||
timeZone: 'UTC'
|
||||
})}
|
||||
{#if isAllDay(visit.start_date)}
|
||||
<!-- For all-day events, show just the date -->
|
||||
{new Date(visit.start_date).toLocaleDateString(undefined, {
|
||||
timeZone: 'UTC'
|
||||
})}
|
||||
{:else}
|
||||
<!-- For timed events, show date and time -->
|
||||
{new Date(visit.start_date).toLocaleDateString()} ({new Date(
|
||||
visit.start_date
|
||||
).toLocaleTimeString()})
|
||||
{/if}
|
||||
</p>
|
||||
{#if visit.end_date && visit.end_date !== visit.start_date}
|
||||
<p>
|
||||
{new Date(visit.end_date).toLocaleDateString(undefined, {
|
||||
timeZone: 'UTC'
|
||||
})}
|
||||
{#if isAllDay(visit.end_date)}
|
||||
<!-- For all-day events, show just the date -->
|
||||
{new Date(visit.end_date).toLocaleDateString(undefined, {
|
||||
timeZone: 'UTC'
|
||||
})}
|
||||
{:else}
|
||||
<!-- For timed events, show date and time -->
|
||||
{new Date(visit.end_date).toLocaleDateString()} ({new Date(
|
||||
visit.end_date
|
||||
).toLocaleTimeString()})
|
||||
{/if}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-neutral"
|
||||
on:click={() => {
|
||||
// Determine if this is an all-day event
|
||||
const isAllDayEvent = isAllDay(visit.start_date);
|
||||
allDay = isAllDayEvent;
|
||||
|
||||
if (isAllDayEvent) {
|
||||
// For all-day events, use date only
|
||||
new_start_date = visit.start_date.split('T')[0];
|
||||
new_end_date = visit.end_date.split('T')[0];
|
||||
} else {
|
||||
// For timed events, format properly for datetime-local input
|
||||
const startDate = new Date(visit.start_date);
|
||||
const endDate = new Date(visit.end_date);
|
||||
|
||||
// Format as yyyy-MM-ddThh:mm
|
||||
new_start_date =
|
||||
startDate.getFullYear() +
|
||||
'-' +
|
||||
String(startDate.getMonth() + 1).padStart(2, '0') +
|
||||
'-' +
|
||||
String(startDate.getDate()).padStart(2, '0') +
|
||||
'T' +
|
||||
String(startDate.getHours()).padStart(2, '0') +
|
||||
':' +
|
||||
String(startDate.getMinutes()).padStart(2, '0');
|
||||
|
||||
new_end_date =
|
||||
endDate.getFullYear() +
|
||||
'-' +
|
||||
String(endDate.getMonth() + 1).padStart(2, '0') +
|
||||
'-' +
|
||||
String(endDate.getDate()).padStart(2, '0') +
|
||||
'T' +
|
||||
String(endDate.getHours()).padStart(2, '0') +
|
||||
':' +
|
||||
String(endDate.getMinutes()).padStart(2, '0');
|
||||
}
|
||||
|
||||
new_notes = visit.notes;
|
||||
adventure.visits = adventure.visits.filter((v) => v !== visit);
|
||||
}}
|
||||
>
|
||||
{$t('lodging.edit')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-error"
|
||||
|
||||
@@ -189,10 +189,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Form Actions -->
|
||||
|
||||
{#if !collection.start_date && !collection.end_date}
|
||||
<div class="mt-4">
|
||||
<div role="alert" class="alert alert-neutral">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
class="h-6 w-6 shrink-0 stroke-current"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
></path>
|
||||
</svg>
|
||||
<span>{$t('adventures.collection_no_start_end_date')}</span>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{$t('adventures.save_next')}
|
||||
{$t('notes.save')}
|
||||
</button>
|
||||
<button type="button" class="btn" on:click={close}>
|
||||
{$t('about.close')}
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium text-sm">{$t('adventures.dates')}:</span>
|
||||
<p>
|
||||
{new Date(lodging.check_in).toLocaleString('en-US', {
|
||||
{new Date(lodging.check_in).toLocaleString(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
@@ -132,7 +132,7 @@
|
||||
minute: 'numeric'
|
||||
})}
|
||||
-
|
||||
{new Date(lodging.check_out).toLocaleString('en-US', {
|
||||
{new Date(lodging.check_out).toLocaleString(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
|
||||
@@ -7,7 +7,15 @@
|
||||
import { t } from 'svelte-i18n';
|
||||
import DeleteWarning from './DeleteWarning.svelte';
|
||||
// import ArrowDownThick from '~icons/mdi/arrow-down-thick';
|
||||
import { TRANSPORTATION_TYPES_ICONS } from '$lib';
|
||||
|
||||
function getTransportationIcon(type: string) {
|
||||
if (type in TRANSPORTATION_TYPES_ICONS) {
|
||||
return TRANSPORTATION_TYPES_ICONS[type as keyof typeof TRANSPORTATION_TYPES_ICONS];
|
||||
} else {
|
||||
return '🚗';
|
||||
}
|
||||
}
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let transportation: Transportation;
|
||||
@@ -106,7 +114,9 @@
|
||||
<h2 class="card-title text-lg font-semibold truncate">{transportation.name}</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="badge badge-secondary">
|
||||
{$t(`transportation.modes.${transportation.type}`)}
|
||||
{$t(`transportation.modes.${transportation.type}`) +
|
||||
' ' +
|
||||
getTransportationIcon(transportation.type)}
|
||||
</div>
|
||||
{#if transportation.type == 'plane' && transportation.flight_number}
|
||||
<div class="badge badge-neutral-200">{transportation.flight_number}</div>
|
||||
@@ -128,7 +138,7 @@
|
||||
{#if transportation.date}
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium text-sm">{$t('adventures.start')}:</span>
|
||||
<p>{new Date(transportation.date).toLocaleString(undefined, { timeZone: 'UTC' })}</p>
|
||||
<p>{new Date(transportation.date).toLocaleString()}</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -146,7 +156,7 @@
|
||||
{#if transportation.end_date}
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-medium text-sm">{$t('adventures.end')}:</span>
|
||||
<p>{new Date(transportation.end_date).toLocaleString(undefined, { timeZone: 'UTC' })}</p>
|
||||
<p>{new Date(transportation.end_date).toLocaleString()}</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -16,10 +16,15 @@
|
||||
|
||||
let constrainDates: boolean = false;
|
||||
|
||||
// Format date as local datetime
|
||||
// Convert an ISO date to a datetime-local value in local time.
|
||||
function toLocalDatetime(value: string | null): string {
|
||||
if (!value) return '';
|
||||
const date = new Date(value);
|
||||
return date.toISOString().slice(0, 16); // Format: YYYY-MM-DDTHH:mm
|
||||
// Adjust the time by subtracting the timezone offset.
|
||||
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
||||
// Return format YYYY-MM-DDTHH:mm
|
||||
return date.toISOString().slice(0, 16);
|
||||
}
|
||||
|
||||
let transportation: Transportation = {
|
||||
@@ -185,6 +190,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert local dates to UTC
|
||||
if (transportation.date && !transportation.date.includes('Z')) {
|
||||
transportation.date = new Date(transportation.date).toISOString();
|
||||
}
|
||||
if (transportation.end_date && !transportation.end_date.includes('Z')) {
|
||||
transportation.end_date = new Date(transportation.end_date).toISOString();
|
||||
}
|
||||
|
||||
if (transportation.type != 'plane') {
|
||||
transportation.flight_number = '';
|
||||
}
|
||||
@@ -422,6 +435,29 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div role="alert" class="alert shadow-lg bg-neutral mt-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
class="stroke-info h-6 w-6 shrink-0"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
></path>
|
||||
</svg>
|
||||
<span>
|
||||
{$t('lodging.current_timezone')}:
|
||||
{(() => {
|
||||
const tz = new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
const [continent, city] = tz.split('/');
|
||||
return `${continent} (${city.replace('_', ' ')})`;
|
||||
})()}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -70,34 +70,65 @@ export function groupAdventuresByDate(
|
||||
// Initialize all days in the range
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const dateString = getLocalDateString(currentDate);
|
||||
groupedAdventures[dateString] = [];
|
||||
}
|
||||
|
||||
adventures.forEach((adventure) => {
|
||||
adventure.visits.forEach((visit) => {
|
||||
if (visit.start_date) {
|
||||
const adventureDate = new Date(visit.start_date).toISOString().split('T')[0];
|
||||
if (visit.end_date) {
|
||||
const endDate = new Date(visit.end_date).toISOString().split('T')[0];
|
||||
// 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);
|
||||
|
||||
// Loop through all days and include adventure if it falls within the range
|
||||
// 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];
|
||||
|
||||
// Loop through all days in the range
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const currentDateStr = getLocalDateString(currentDate);
|
||||
|
||||
// Include the current day if it falls within the adventure date range
|
||||
if (dateString >= adventureDate && dateString <= endDate) {
|
||||
if (groupedAdventures[dateString]) {
|
||||
groupedAdventures[dateString].push(adventure);
|
||||
if (currentDateStr >= startDateStr && currentDateStr <= endDateStr) {
|
||||
if (groupedAdventures[currentDateStr]) {
|
||||
groupedAdventures[currentDateStr].push(adventure);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (groupedAdventures[adventureDate]) {
|
||||
// If there's no end date, add adventure to the start date only
|
||||
groupedAdventures[adventureDate].push(adventure);
|
||||
} else {
|
||||
// Handle regular events with time components
|
||||
const adventureStartDate = new Date(visit.start_date);
|
||||
const adventureDateStr = getLocalDateString(adventureStartDate);
|
||||
|
||||
if (visit.end_date) {
|
||||
const adventureEndDate = new Date(visit.end_date);
|
||||
const endDateStr = getLocalDateString(adventureEndDate);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -106,6 +137,20 @@ export function groupAdventuresByDate(
|
||||
return groupedAdventures;
|
||||
}
|
||||
|
||||
function getLocalDateString(date: Date): string {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
// Helper to check if a given date string represents midnight (all-day)
|
||||
// Improved isAllDay function to handle different ISO date formats
|
||||
export function isAllDay(dateStr: string): boolean {
|
||||
// Check for various midnight formats in UTC
|
||||
return dateStr.endsWith('T00:00:00Z') || dateStr.endsWith('T00:00:00.000Z');
|
||||
}
|
||||
|
||||
export function groupTransportationsByDate(
|
||||
transportations: Transportation[],
|
||||
startDate: Date,
|
||||
@@ -116,22 +161,22 @@ export function groupTransportationsByDate(
|
||||
// Initialize all days in the range
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const dateString = getLocalDateString(currentDate);
|
||||
groupedTransportations[dateString] = [];
|
||||
}
|
||||
|
||||
transportations.forEach((transportation) => {
|
||||
if (transportation.date) {
|
||||
const transportationDate = new Date(transportation.date).toISOString().split('T')[0];
|
||||
const transportationDate = getLocalDateString(new Date(transportation.date));
|
||||
if (transportation.end_date) {
|
||||
const endDate = new Date(transportation.end_date).toISOString().split('T')[0];
|
||||
|
||||
// Loop through all days and include transportation if it falls within the range
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const dateString = getLocalDateString(currentDate);
|
||||
|
||||
// Include the current day if it falls within the transportation date range
|
||||
if (dateString >= transportationDate && dateString <= endDate) {
|
||||
@@ -157,35 +202,32 @@ export function groupLodgingByDate(
|
||||
): Record<string, Lodging[]> {
|
||||
const groupedTransportations: Record<string, Lodging[]> = {};
|
||||
|
||||
// Initialize all days in the range
|
||||
// Initialize all days in the range using local dates
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const dateString = getLocalDateString(currentDate);
|
||||
groupedTransportations[dateString] = [];
|
||||
}
|
||||
|
||||
transportations.forEach((transportation) => {
|
||||
if (transportation.check_in) {
|
||||
const transportationDate = new Date(transportation.check_in).toISOString().split('T')[0];
|
||||
// Use local date string conversion
|
||||
const transportationDate = getLocalDateString(new Date(transportation.check_in));
|
||||
if (transportation.check_out) {
|
||||
const endDate = new Date(transportation.check_out).toISOString().split('T')[0];
|
||||
const endDate = getLocalDateString(new Date(transportation.check_out));
|
||||
|
||||
// Loop through all days and include transportation if it falls within the range
|
||||
// Loop through all days and include transportation if it falls within the transportation date range
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const dateString = getLocalDateString(currentDate);
|
||||
|
||||
// Include the current day if it falls within the transportation date range
|
||||
if (dateString >= transportationDate && dateString <= endDate) {
|
||||
if (groupedTransportations[dateString]) {
|
||||
groupedTransportations[dateString].push(transportation);
|
||||
}
|
||||
groupedTransportations[dateString].push(transportation);
|
||||
}
|
||||
}
|
||||
} else if (groupedTransportations[transportationDate]) {
|
||||
// If there's no end date, add transportation to the start date only
|
||||
groupedTransportations[transportationDate].push(transportation);
|
||||
}
|
||||
}
|
||||
@@ -201,19 +243,18 @@ export function groupNotesByDate(
|
||||
): Record<string, Note[]> {
|
||||
const groupedNotes: Record<string, Note[]> = {};
|
||||
|
||||
// Initialize all days in the range
|
||||
// Initialize all days in the range using local dates
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const dateString = getLocalDateString(currentDate);
|
||||
groupedNotes[dateString] = [];
|
||||
}
|
||||
|
||||
notes.forEach((note) => {
|
||||
if (note.date) {
|
||||
const noteDate = new Date(note.date).toISOString().split('T')[0];
|
||||
|
||||
// Add note to the appropriate date group if it exists
|
||||
// Use the date string as is since it's already in "YYYY-MM-DD" format.
|
||||
const noteDate = note.date;
|
||||
if (groupedNotes[noteDate]) {
|
||||
groupedNotes[noteDate].push(note);
|
||||
}
|
||||
@@ -230,19 +271,18 @@ export function groupChecklistsByDate(
|
||||
): Record<string, Checklist[]> {
|
||||
const groupedChecklists: Record<string, Checklist[]> = {};
|
||||
|
||||
// Initialize all days in the range
|
||||
// Initialize all days in the range using local dates
|
||||
for (let i = 0; i < numberOfDays; i++) {
|
||||
const currentDate = new Date(startDate);
|
||||
currentDate.setUTCDate(startDate.getUTCDate() + i);
|
||||
const dateString = currentDate.toISOString().split('T')[0];
|
||||
currentDate.setDate(startDate.getDate() + i);
|
||||
const dateString = getLocalDateString(currentDate);
|
||||
groupedChecklists[dateString] = [];
|
||||
}
|
||||
|
||||
checklists.forEach((checklist) => {
|
||||
if (checklist.date) {
|
||||
const checklistDate = new Date(checklist.date).toISOString().split('T')[0];
|
||||
|
||||
// Add checklist to the appropriate date group if it exists
|
||||
// Use the date string as is since it's already in "YYYY-MM-DD" format.
|
||||
const checklistDate = checklist.date;
|
||||
if (groupedChecklists[checklistDate]) {
|
||||
groupedChecklists[checklistDate].push(checklist);
|
||||
}
|
||||
@@ -338,6 +378,17 @@ export let LODGING_TYPES_ICONS = {
|
||||
other: '❓'
|
||||
};
|
||||
|
||||
export let TRANSPORTATION_TYPES_ICONS = {
|
||||
car: '🚗',
|
||||
plane: '✈️',
|
||||
train: '🚆',
|
||||
bus: '🚌',
|
||||
boat: '⛵',
|
||||
bike: '🚲',
|
||||
walking: '🚶',
|
||||
other: '❓'
|
||||
};
|
||||
|
||||
export function getAdventureTypeLabel(type: string) {
|
||||
// return the emoji ADVENTURE_TYPE_ICONS label for the given type if not found return ? emoji
|
||||
if (type in ADVENTURE_TYPE_ICONS) {
|
||||
|
||||
Reference in New Issue
Block a user