feat: redesign itinerary flow and add catppuccin mocha theme
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
import { t } from 'svelte-i18n';
|
||||
import { addToast } from '$lib/toasts';
|
||||
import Globe from '~icons/mdi/globe';
|
||||
import { TRANSPORTATION_TYPES_ICONS } from '$lib';
|
||||
|
||||
export let collection: Collection;
|
||||
export let user: any;
|
||||
@@ -396,6 +397,74 @@
|
||||
return value.includes('T') ? value.split('T')[0] : value;
|
||||
}
|
||||
|
||||
function getTransportationIcon(type: string | null | undefined) {
|
||||
if (type && type in TRANSPORTATION_TYPES_ICONS) {
|
||||
return TRANSPORTATION_TYPES_ICONS[type as keyof typeof TRANSPORTATION_TYPES_ICONS];
|
||||
}
|
||||
return '🚗';
|
||||
}
|
||||
|
||||
function formatTransportationDuration(minutes: number | null | undefined): string | null {
|
||||
if (minutes === null || minutes === undefined || Number.isNaN(minutes)) return null;
|
||||
const safeMinutes = Math.max(0, Math.floor(minutes));
|
||||
const hours = Math.floor(safeMinutes / 60);
|
||||
const mins = safeMinutes % 60;
|
||||
const parts = [] as string[];
|
||||
if (hours) parts.push(`${hours}h`);
|
||||
parts.push(`${mins}m`);
|
||||
return parts.join(' ');
|
||||
}
|
||||
|
||||
function formatTransportationDistance(distanceKm: number | null | undefined): string | null {
|
||||
if (distanceKm === null || distanceKm === undefined || Number.isNaN(distanceKm)) return null;
|
||||
if (distanceKm < 10) return `${distanceKm.toFixed(1)} km`;
|
||||
return `${Math.round(distanceKm)} km`;
|
||||
}
|
||||
|
||||
function editTransportationInline(transportation: Transportation) {
|
||||
handleEditTransportation({ detail: transportation } as CustomEvent<Transportation>);
|
||||
}
|
||||
|
||||
async function removeItineraryEntry(item: CollectionItineraryItem) {
|
||||
if (!item?.id) return;
|
||||
try {
|
||||
const res = await fetch(`/api/itineraries/${item.id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
if (!res.ok) throw new Error('Failed to remove itinerary item');
|
||||
handleRemoveItineraryItem(new CustomEvent('removeFromItinerary', { detail: item }) as any);
|
||||
addToast('info', $t('itinerary.item_remove_success'));
|
||||
} catch (error) {
|
||||
console.error('Error removing itinerary item:', error);
|
||||
addToast('error', $t('itinerary.item_remove_error'));
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteTransportationFromItinerary(
|
||||
item: CollectionItineraryItem,
|
||||
transportation: Transportation
|
||||
) {
|
||||
const confirmed = window.confirm($t('adventures.transportation_delete_confirm'));
|
||||
if (!confirmed) return;
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/transportations/${transportation.id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error('Failed to delete transportation');
|
||||
|
||||
addToast('info', $t('transportation.transportation_deleted'));
|
||||
handleItemDelete(new CustomEvent('delete', { detail: transportation.id }) as any);
|
||||
} catch (error) {
|
||||
console.error('Failed to delete transportation:', error);
|
||||
addToast('error', $t('transportation.transportation_delete_error'));
|
||||
}
|
||||
}
|
||||
|
||||
function upsertNote(note: Note) {
|
||||
const notes = collection.notes ? [...collection.notes] : [];
|
||||
const idx = notes.findIndex((n) => n.id === note.id);
|
||||
@@ -1944,7 +2013,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Actions: saving indicator + Add dropdown -->
|
||||
<!-- Actions: saving indicator + day quick actions -->
|
||||
<div class="flex-none ml-3 flex items-start gap-2">
|
||||
{#if savingDay === day.date}
|
||||
<div>
|
||||
@@ -1956,111 +2025,19 @@
|
||||
{/if}
|
||||
|
||||
{#if canModify}
|
||||
<div class="dropdown z-30">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-square btn-sm btn-outline p-1"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
title={$t('adventures.add')}
|
||||
>
|
||||
<Plus class="w-5 h-5" />
|
||||
</button>
|
||||
<ul
|
||||
class="dropdown-content menu p-2 shadow bg-base-300 rounded-box w-56"
|
||||
role="menu"
|
||||
>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="w-full text-left"
|
||||
on:click={() => {
|
||||
linkModalTargetDate = day.date;
|
||||
linkModalDisplayDate = day.displayDate;
|
||||
isItineraryLinkModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('itinerary.link_existing_item')}
|
||||
</button>
|
||||
</li>
|
||||
<li class="menu-title">{$t('adventures.create_new')}</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="w-full text-left"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
locationToEdit = null;
|
||||
locationBeingUpdated = null;
|
||||
isLocationModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('locations.location')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="w-full text-left"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
lodgingToEdit = null;
|
||||
lodgingBeingUpdated = null;
|
||||
isLodgingModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.lodging')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="w-full text-left"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
isTransportationModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.transportation')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="w-full text-left"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
isNoteModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.note')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
class="w-full text-left"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
isChecklistModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.checklist')}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-outline"
|
||||
disabled={true}
|
||||
title={$t('itinerary.optimize')}
|
||||
>
|
||||
{$t('itinerary.optimize')}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Day Items -->
|
||||
<!-- Day Items (vertical timeline with ordered stops) -->
|
||||
<div>
|
||||
{#if day.items.length === 0}
|
||||
<div
|
||||
@@ -2082,7 +2059,7 @@
|
||||
}}
|
||||
on:consider={(e) => handleDndConsider(dayIndex, e)}
|
||||
on:finalize={(e) => handleDndFinalize(dayIndex, e)}
|
||||
class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3"
|
||||
class="space-y-3"
|
||||
>
|
||||
{#each day.items as item, index (item.id)}
|
||||
{@const objectType = item.item?.type || ''}
|
||||
@@ -2091,173 +2068,223 @@
|
||||
{@const isDraggingShadow = item[SHADOW_ITEM_MARKER_PROPERTY_NAME]}
|
||||
|
||||
<div
|
||||
class="group relative transition-all duration-200 pointer-events-auto h-full {isDraggingShadow
|
||||
class="group relative transition-all duration-200 pointer-events-auto {isDraggingShadow
|
||||
? 'opacity-40 scale-95'
|
||||
: ''}"
|
||||
animate:flip={{ duration: flipDurationMs }}
|
||||
>
|
||||
{#if resolvedObj}
|
||||
<!-- Drag Handle Container -->
|
||||
{#if canModify}
|
||||
<div
|
||||
class="absolute left-2 top-2 z-20 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
|
||||
title={$t('itinerary.drag_to_reorder')}
|
||||
>
|
||||
<div class="flex gap-3">
|
||||
<div class="relative flex flex-col items-center shrink-0 pt-1">
|
||||
<div
|
||||
class="itinerary-drag-handle btn btn-circle btn-xs btn-ghost bg-base-100/80 backdrop-blur-sm shadow-sm hover:bg-base-200 cursor-grab active:cursor-grabbing"
|
||||
aria-label={$t('itinerary.drag_to_reorder')}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="w-7 h-7 rounded-full bg-primary text-primary-content text-xs font-bold flex items-center justify-center"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-3 w-3"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 8h16M4 16h16"
|
||||
/>
|
||||
</svg>
|
||||
{index + 1}
|
||||
</div>
|
||||
{#if index < day.items.length - 1}
|
||||
<div class="w-px bg-base-300 flex-1 min-h-10 mt-1"></div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Order Badge
|
||||
<div class="absolute right-2 top-2 z-10">
|
||||
<div
|
||||
class="badge badge-primary badge-sm font-bold shadow-md"
|
||||
title="Item order"
|
||||
>
|
||||
#{index + 1}
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Multi-day indicator for lodging -->
|
||||
{#if multiDay && objectType === 'lodging'}
|
||||
<div class="absolute left-2 bottom-2 z-10">
|
||||
<div class="badge badge-info badge-xs gap-1 shadow-sm">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-3 w-3"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
<div class="relative flex-1 min-w-0">
|
||||
{#if canModify}
|
||||
<div
|
||||
class="absolute left-0 top-0 z-20 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
|
||||
title={$t('itinerary.drag_to_reorder')}
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="text-xs">{$t('itinerary.multi_day')}</span>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div
|
||||
class="itinerary-drag-handle btn btn-circle btn-xs btn-ghost bg-base-100/80 backdrop-blur-sm shadow-sm hover:bg-base-200 cursor-grab active:cursor-grabbing"
|
||||
aria-label={$t('itinerary.drag_to_reorder')}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-3 w-3"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 8h16M4 16h16"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Card with smooth transition and proper sizing for grid -->
|
||||
<div class="transition-all duration-200 h-full">
|
||||
<!-- Display the appropriate card based on type -->
|
||||
{#if objectType === 'location'}
|
||||
<LocationCard
|
||||
adventure={resolvedObj}
|
||||
on:edit={handleEditLocation}
|
||||
on:delete={handleItemDelete}
|
||||
on:duplicate={handleDuplicateLocation}
|
||||
itineraryItem={item}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:moveToGlobal={(e) => moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
{user}
|
||||
{collection}
|
||||
compact={true}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{:else if objectType === 'transportation'}
|
||||
<TransportationCard
|
||||
transportation={resolvedObj}
|
||||
{user}
|
||||
{collection}
|
||||
on:delete={handleItemDelete}
|
||||
itineraryItem={item}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:edit={handleEditTransportation}
|
||||
on:moveToGlobal={(e) => moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{:else if objectType === 'lodging'}
|
||||
<LodgingCard
|
||||
lodging={resolvedObj}
|
||||
{user}
|
||||
{collection}
|
||||
itineraryItem={item}
|
||||
on:delete={handleItemDelete}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:edit={handleEditLodging}
|
||||
on:moveToGlobal={(e) => moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{:else if objectType === 'note'}
|
||||
<!-- @ts-ignore - TypeScript can't narrow union type properly -->
|
||||
<NoteCard
|
||||
note={resolvedObj}
|
||||
{user}
|
||||
{collection}
|
||||
on:delete={handleItemDelete}
|
||||
itineraryItem={item}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:edit={handleEditNote}
|
||||
on:moveToGlobal={(e) => moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{:else if objectType === 'checklist'}
|
||||
<!-- @ts-ignore - TypeScript can't narrow union type properly -->
|
||||
<ChecklistCard
|
||||
checklist={resolvedObj}
|
||||
{user}
|
||||
{collection}
|
||||
on:delete={handleItemDelete}
|
||||
itineraryItem={item}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:edit={handleEditChecklist}
|
||||
on:moveToGlobal={(e) => moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{/if}
|
||||
{#if objectType === 'transportation'}
|
||||
<div class="rounded-xl border border-base-300 bg-base-100 px-4 py-3">
|
||||
<div class="flex items-center justify-between gap-3 mb-2">
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<span class="text-lg"
|
||||
>{getTransportationIcon(resolvedObj.type)}</span
|
||||
>
|
||||
<p class="font-semibold truncate">{resolvedObj.name}</p>
|
||||
<span class="badge badge-outline badge-sm truncate">
|
||||
{$t(`transportation.modes.${resolvedObj.type}`) ||
|
||||
resolvedObj.type}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-xs opacity-70 flex items-center gap-2 shrink-0">
|
||||
{#if formatTransportationDuration(resolvedObj.travel_duration_minutes)}
|
||||
<span
|
||||
>{formatTransportationDuration(
|
||||
resolvedObj.travel_duration_minutes
|
||||
)}</span
|
||||
>
|
||||
{/if}
|
||||
{#if formatTransportationDistance(resolvedObj.distance)}
|
||||
<span>{formatTransportationDistance(resolvedObj.distance)}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm opacity-80 truncate">
|
||||
{resolvedObj.from_location || '—'} → {resolvedObj.to_location ||
|
||||
'—'}
|
||||
</div>
|
||||
{#if canModify}
|
||||
<div class="mt-2 flex flex-wrap gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => editTransportationInline(resolvedObj)}
|
||||
>
|
||||
{$t('transportation.edit')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() =>
|
||||
handleOpenDayPickerForItem(
|
||||
'transportation',
|
||||
resolvedObj,
|
||||
true,
|
||||
day.date
|
||||
)}
|
||||
>
|
||||
{$t('itinerary.change_day')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() =>
|
||||
moveItemToGlobal('transportation', resolvedObj.id)}
|
||||
>
|
||||
{$t('itinerary.move_to_trip_context') || 'Move to Trip Context'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-ghost"
|
||||
on:click={() => removeItineraryEntry(item)}
|
||||
>
|
||||
{$t('itinerary.remove_from_itinerary')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-error btn-outline"
|
||||
on:click={() =>
|
||||
deleteTransportationFromItinerary(item, resolvedObj)}
|
||||
>
|
||||
{$t('adventures.delete')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
{#if multiDay && objectType === 'lodging'}
|
||||
<div class="mb-2">
|
||||
<div class="badge badge-info badge-xs gap-1 shadow-sm">
|
||||
<span class="text-xs">{$t('itinerary.multi_day')}</span>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if objectType === 'location'}
|
||||
<LocationCard
|
||||
adventure={resolvedObj}
|
||||
on:edit={handleEditLocation}
|
||||
on:delete={handleItemDelete}
|
||||
on:duplicate={handleDuplicateLocation}
|
||||
itineraryItem={item}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:moveToGlobal={(e) =>
|
||||
moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
{user}
|
||||
{collection}
|
||||
compact={true}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{:else if objectType === 'lodging'}
|
||||
<LodgingCard
|
||||
lodging={resolvedObj}
|
||||
{user}
|
||||
{collection}
|
||||
itineraryItem={item}
|
||||
on:delete={handleItemDelete}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:edit={handleEditLodging}
|
||||
on:moveToGlobal={(e) =>
|
||||
moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{:else if objectType === 'note'}
|
||||
<NoteCard
|
||||
note={resolvedObj}
|
||||
{user}
|
||||
{collection}
|
||||
on:delete={handleItemDelete}
|
||||
itineraryItem={item}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:edit={handleEditNote}
|
||||
on:moveToGlobal={(e) =>
|
||||
moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{:else if objectType === 'checklist'}
|
||||
<ChecklistCard
|
||||
checklist={resolvedObj}
|
||||
{user}
|
||||
{collection}
|
||||
on:delete={handleItemDelete}
|
||||
itineraryItem={item}
|
||||
on:removeFromItinerary={handleRemoveItineraryItem}
|
||||
on:edit={handleEditChecklist}
|
||||
on:moveToGlobal={(e) =>
|
||||
moveItemToGlobal(e.detail.type, e.detail.id)}
|
||||
on:changeDay={(e) =>
|
||||
handleOpenDayPickerForItem(
|
||||
e.detail.type,
|
||||
e.detail.item,
|
||||
e.detail.forcePicker,
|
||||
day.date
|
||||
)}
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Fallback for unresolved items -->
|
||||
@@ -2269,6 +2296,108 @@
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if canModify}
|
||||
<div class="mt-4 pt-4 border-t border-base-300 border-dashed">
|
||||
<div class="flex items-center justify-between gap-3 flex-wrap">
|
||||
<p class="text-sm opacity-70">{$t('itinerary.add_place')}</p>
|
||||
<div class="dropdown dropdown-end z-30">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-outline"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<Plus class="w-4 h-4" />
|
||||
{$t('adventures.add')}
|
||||
</button>
|
||||
<ul
|
||||
class="dropdown-content menu p-2 shadow bg-base-300 rounded-box w-56"
|
||||
role="menu"
|
||||
>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
on:click={() => {
|
||||
linkModalTargetDate = day.date;
|
||||
linkModalDisplayDate = day.displayDate;
|
||||
isItineraryLinkModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('itinerary.link_existing_item')}
|
||||
</button>
|
||||
</li>
|
||||
<li class="menu-title">{$t('adventures.create_new')}</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
locationToEdit = null;
|
||||
locationBeingUpdated = null;
|
||||
isLocationModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('locations.location')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
lodgingToEdit = null;
|
||||
lodgingBeingUpdated = null;
|
||||
isLodgingModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.lodging')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
isTransportationModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.transportation')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
isNoteModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.note')}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
on:click={() => {
|
||||
pendingAddDate = day.date;
|
||||
isChecklistModalOpen = true;
|
||||
}}
|
||||
>
|
||||
{$t('adventures.checklist')}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Overnight Lodging + Dated Trip-wide Indicators (share row to save space) -->
|
||||
|
||||
@@ -462,6 +462,7 @@ export let themes = [
|
||||
{ name: 'night', label: 'Night' },
|
||||
{ name: 'forest', label: 'Forest' },
|
||||
{ name: 'aqua', label: 'Aqua' },
|
||||
{ name: 'catppuccinMocha', label: 'Catppuccin Mocha' },
|
||||
{ name: 'aestheticLight', label: 'Aesthetic Light' },
|
||||
{ name: 'aestheticDark', label: 'Aesthetic Dark' },
|
||||
{ name: 'northernLights', label: 'Northern Lights' }
|
||||
@@ -601,6 +602,7 @@ export function getIsDarkMode() {
|
||||
const isDark =
|
||||
theme === 'dark' ||
|
||||
theme === 'night' ||
|
||||
theme === 'catppuccinMocha' ||
|
||||
theme === 'aestheticDark' ||
|
||||
theme === 'northernLights' ||
|
||||
theme === 'forest' ||
|
||||
|
||||
@@ -704,6 +704,7 @@
|
||||
"aqua": "أكوا",
|
||||
"dark": "مظلم",
|
||||
"dim": "خافت",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "غابة",
|
||||
"light": "ضوء",
|
||||
"night": "ليلة",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "سياق الرحلة",
|
||||
"trip_context_info": "تنطبق عناصر سياق الرحلة على الرحلة بأكملها — على سبيل المثال المواقع التي تمثل الوجهة نفسها، أو الملاحظات العامة، أو قوائم التعبئة المهمة للرحلة بأكملها.",
|
||||
"unscheduled_items": "العناصر غير المجدولة",
|
||||
"unscheduled_items_desc": "ترتبط هذه العناصر بهذه الرحلة ولكن لم تتم إضافتها إلى يوم محدد بعد."
|
||||
"unscheduled_items_desc": "ترتبط هذه العناصر بهذه الرحلة ولكن لم تتم إضافتها إلى يوم محدد بعد.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,6 +481,7 @@
|
||||
"aqua": "Aqua",
|
||||
"dark": "Dunkel",
|
||||
"dim": "Düster",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Wald",
|
||||
"light": "Hell",
|
||||
"night": "Nacht",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Reisekontext",
|
||||
"trip_context_info": "Reisekontextelemente gelten für die gesamte Reise – zum Beispiel Orte, die das Ziel selbst darstellen, allgemeine Notizen oder Packlisten, die für die gesamte Reise wichtig sind.",
|
||||
"unscheduled_items": "Ungeplante Einträge",
|
||||
"unscheduled_items_desc": "Diese Einträge sind mit dieser Reise verknüpft, wurden aber noch keinem bestimmten Tag hinzugefügt."
|
||||
"unscheduled_items_desc": "Diese Einträge sind mit dieser Reise verknüpft, wurden aber noch keinem bestimmten Tag hinzugefügt.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1096,7 +1096,9 @@
|
||||
"failed_to_add_to_trip_context": "Failed to add item to trip context",
|
||||
"remove_from_trip_context": "Remove from Context",
|
||||
"drag_to_reorder": "Drag to reorder",
|
||||
"add_to_day": "Add to day"
|
||||
"add_to_day": "Add to day",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
},
|
||||
"common": {
|
||||
"show_less": "Hide details",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"aqua": "Agua",
|
||||
"dark": "Oscuro",
|
||||
"dim": "Oscuro",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Bosque",
|
||||
"light": "Luz",
|
||||
"night": "Noche",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Contexto del viaje",
|
||||
"trip_context_info": "Los elementos del contexto del viaje se aplican a todo el viaje; por ejemplo, ubicaciones que son el destino en sí, notas generales o listas de equipaje que son importantes para todo el viaje.",
|
||||
"unscheduled_items": "Artículos no programados",
|
||||
"unscheduled_items_desc": "Estos elementos están vinculados a este viaje pero aún no se han agregado a un día específico."
|
||||
"unscheduled_items_desc": "Estos elementos están vinculados a este viaje pero aún no se han agregado a un día específico.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,6 +481,7 @@
|
||||
"aqua": "Aqua",
|
||||
"dark": "Sombre",
|
||||
"dim": "Faible",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Forêt",
|
||||
"light": "Lumière",
|
||||
"night": "Nuit",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context_info": "Les éléments de contexte du voyage s'appliquent à l'ensemble du voyage, par exemple les lieux qui constituent la destination elle-même, les notes générales ou les listes de colisage importantes pour l'ensemble du voyage.",
|
||||
"unscheduled_items": "Éléments non planifiés",
|
||||
"unscheduled_items_desc": "Ces éléments sont liés à ce voyage mais n'ont pas encore été ajoutés à un jour spécifique.",
|
||||
"link_existing_item": "Lier un élément existant"
|
||||
"link_existing_item": "Lier un élément existant",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"aestheticDark": "Esztétikus sötét",
|
||||
"aqua": "Akvamarin",
|
||||
"northernLights": "Sarki fény",
|
||||
"dim": "Halvány"
|
||||
"dim": "Halvány",
|
||||
"catppuccinMocha": "Catppuccin Mocha"
|
||||
},
|
||||
"navigation": "Navigáció",
|
||||
"worldtravel": "Világutazás"
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Utazási kontextus",
|
||||
"trip_context_info": "Az utazási kontextus elemei az egész utazásra vonatkoznak – például olyan helyek, amelyek maga az úti cél, általános megjegyzések vagy csomaglisták, amelyek az egész utazás szempontjából fontosak.",
|
||||
"unscheduled_items": "Nem ütemezett tételek",
|
||||
"unscheduled_items_desc": "Ezek az elemek ehhez az utazáshoz kapcsolódnak, de még nem adták hozzá egy adott naphoz."
|
||||
"unscheduled_items_desc": "Ezek az elemek ehhez az utazáshoz kapcsolódnak, de még nem adták hozzá egy adott naphoz.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,6 +481,7 @@
|
||||
"aqua": "Aqua",
|
||||
"dark": "Buio",
|
||||
"dim": "Fioco",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Foresta",
|
||||
"light": "Leggero",
|
||||
"night": "Notte",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Contesto del viaggio",
|
||||
"trip_context_info": "Gli elementi contestuali del viaggio si applicano all'intero viaggio, ad esempio luoghi che rappresentano la destinazione stessa, note generali o liste di cose da portare importanti per l'intero viaggio.",
|
||||
"unscheduled_items": "Elementi non pianificati",
|
||||
"unscheduled_items_desc": "Questi elementi sono collegati a questo viaggio ma non sono ancora stati aggiunti a un giorno specifico."
|
||||
"unscheduled_items_desc": "Questi elementi sono collegati a questo viaggio ma non sono ancora stati aggiunti a un giorno specifico.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,6 +704,7 @@
|
||||
"aqua": "アクア",
|
||||
"dark": "暗い",
|
||||
"dim": "薄暗い",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "森",
|
||||
"light": "ライト",
|
||||
"night": "夜",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "旅行のコンテキスト",
|
||||
"trip_context_info": "旅行コンテキスト項目は、旅行全体に適用されます。たとえば、目的地そのものである場所、一般的なメモ、旅行全体にとって重要な持ち物リストなどです。",
|
||||
"unscheduled_items": "予定外の項目",
|
||||
"unscheduled_items_desc": "これらのアイテムはこの旅行にリンクされていますが、まだ特定の日に追加されていません。"
|
||||
"unscheduled_items_desc": "これらのアイテムはこの旅行にリンクされていますが、まだ特定の日に追加されていません。",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,6 +644,7 @@
|
||||
"aqua": "아쿠아",
|
||||
"dark": "어두운",
|
||||
"dim": "어둑한",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "숲",
|
||||
"light": "빛",
|
||||
"night": "밤",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "여행 상황",
|
||||
"trip_context_info": "여행 컨텍스트 항목은 전체 여행에 적용됩니다. 예를 들어 목적지 자체인 위치, 일반 참고 사항, 전체 여행에 중요한 짐 목록 등이 있습니다.",
|
||||
"unscheduled_items": "예정되지 않은 품목",
|
||||
"unscheduled_items_desc": "이 항목은 이 여행에 연결되어 있지만 아직 특정 날짜에 추가되지 않았습니다."
|
||||
"unscheduled_items_desc": "이 항목은 이 여행에 연결되어 있지만 아직 특정 날짜에 추가되지 않았습니다.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,6 +481,7 @@
|
||||
"aqua": "Aqua",
|
||||
"dark": "Donker",
|
||||
"dim": "Duister",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Woud",
|
||||
"light": "Licht",
|
||||
"night": "Nacht",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Reiscontext",
|
||||
"trip_context_info": "Reiscontextitems zijn van toepassing op de hele reis, bijvoorbeeld locaties die de bestemming zelf vormen, algemene opmerkingen of paklijsten die belangrijk zijn voor de hele reis.",
|
||||
"unscheduled_items": "Niet-geplande items",
|
||||
"unscheduled_items_desc": "Deze items zijn gekoppeld aan deze reis, maar nog niet toegevoegd aan een specifieke dag."
|
||||
"unscheduled_items_desc": "Deze items zijn gekoppeld aan deze reis, maar nog niet toegevoegd aan een specifieke dag.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"aqua": "Aqua",
|
||||
"dark": "Mørk",
|
||||
"dim": "Svak",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Skog",
|
||||
"light": "Lys",
|
||||
"night": "Natt",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Turkontekst",
|
||||
"trip_context_info": "Turkontekstelementer gjelder for hele turen – for eksempel steder som er selve destinasjonen, generelle notater eller pakkelister som er viktige for hele turen.",
|
||||
"unscheduled_items": "Ikke-planlagte elementer",
|
||||
"unscheduled_items_desc": "Disse elementene er knyttet til denne turen, men har ikke blitt lagt til en bestemt dag ennå."
|
||||
"unscheduled_items_desc": "Disse elementene er knyttet til denne turen, men har ikke blitt lagt til en bestemt dag ennå.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"aqua": "Aqua",
|
||||
"dark": "Ciemny",
|
||||
"dim": "Ciemny",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Las",
|
||||
"light": "Światło",
|
||||
"night": "Noc",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Kontekst podróży",
|
||||
"trip_context_info": "Elementy kontekstu podróży dotyczą całej podróży — na przykład lokalizacje będące samym celem podróży, uwagi ogólne lub listy rzeczy do spakowania ważne dla całej podróży.",
|
||||
"unscheduled_items": "Niezaplanowane pozycje",
|
||||
"unscheduled_items_desc": "Te elementy są powiązane z tą podróżą, ale nie zostały jeszcze dodane do konkretnego dnia."
|
||||
"unscheduled_items_desc": "Te elementy są powiązane z tą podróżą, ale nie zostały jeszcze dodane do konkretnego dnia.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,6 +704,7 @@
|
||||
"aqua": "Aqua",
|
||||
"dark": "Escuro",
|
||||
"dim": "Escurecido",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Floresta",
|
||||
"light": "Claro",
|
||||
"night": "Noite",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Contexto da viagem",
|
||||
"trip_context_info": "Os itens de contexto da viagem aplicam-se a toda a viagem — por exemplo, locais que são o próprio destino, notas gerais ou listas de embalagem que são importantes para toda a viagem.",
|
||||
"unscheduled_items": "Itens não programados",
|
||||
"unscheduled_items_desc": "Esses itens estão vinculados a esta viagem, mas ainda não foram adicionados a um dia específico."
|
||||
"unscheduled_items_desc": "Esses itens estão vinculados a esta viagem, mas ainda não foram adicionados a um dia específico.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"aqua": "Аква",
|
||||
"dark": "Темный",
|
||||
"dim": "Тусклый",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Лес",
|
||||
"light": "Свет",
|
||||
"night": "Ночь",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context_info": "Элементы контекста поездки применяются ко всей поездке — например, места, которые являются пунктом назначения, общие заметки или упаковочные листы, важные для всей поездки.",
|
||||
"unscheduled_items": "Незапланированные предметы",
|
||||
"unscheduled_items_desc": "Эти элементы связаны с этой поездкой, но еще не добавлены к определенному дню.",
|
||||
"link_existing_item": "Связать существующий элемент"
|
||||
"link_existing_item": "Связать существующий элемент",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"aestheticDark": "Estetická tmavá",
|
||||
"aqua": "Aqua",
|
||||
"northernLights": "Polárna žiara",
|
||||
"dim": "Tlmená"
|
||||
"dim": "Tlmená",
|
||||
"catppuccinMocha": "Catppuccin Mocha"
|
||||
},
|
||||
"navigation": "Navigácia",
|
||||
"worldtravel": "Svetové cestovanie"
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Kontext cesty",
|
||||
"trip_context_info": "Kontextové položky cesty sa vzťahujú na celú cestu – napríklad miesta, ktoré sú samotným cieľom, všeobecné poznámky alebo zoznamy balíkov, ktoré sú dôležité pre celú cestu.",
|
||||
"unscheduled_items": "Neplánované položky",
|
||||
"unscheduled_items_desc": "Tieto položky sú spojené s touto cestou, ale zatiaľ neboli pridané ku konkrétnemu dňu."
|
||||
"unscheduled_items_desc": "Tieto položky sú spojené s touto cestou, ale zatiaľ neboli pridané ku konkrétnemu dňu.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,6 +481,7 @@
|
||||
"aqua": "Vatten",
|
||||
"dark": "Mörk",
|
||||
"dim": "Dämpad",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Skog",
|
||||
"light": "Ljus",
|
||||
"night": "Natt",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Resans sammanhang",
|
||||
"trip_context_info": "Resans kontextobjekt gäller för hela resan – till exempel platser som är själva destinationen, allmänna anteckningar eller packlistor som är viktiga för hela resan.",
|
||||
"unscheduled_items": "Oschemalagda objekt",
|
||||
"unscheduled_items_desc": "Dessa objekt är länkade till denna resa men har inte lagts till en specifik dag än."
|
||||
"unscheduled_items_desc": "Dessa objekt är länkade till denna resa men har inte lagts till en specifik dag än.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"aestheticDark": "Estetik Karanlık",
|
||||
"aqua": "Su",
|
||||
"northernLights": "Kuzey Işıkları",
|
||||
"dim": "Loş"
|
||||
"dim": "Loş",
|
||||
"catppuccinMocha": "Catppuccin Mocha"
|
||||
},
|
||||
"navigation": "Navigasyon",
|
||||
"worldtravel": "Dünya Seyahati"
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Seyahat İçeriği",
|
||||
"trip_context_info": "Seyahat bağlamı öğeleri seyahatin tamamı için geçerlidir; örneğin varış noktasının kendisi olan konumlar, genel notlar veya seyahatin tamamı için önemli olan paket listeleri.",
|
||||
"unscheduled_items": "Planlanmamış Öğeler",
|
||||
"unscheduled_items_desc": "Bu öğeler bu geziye bağlı ancak henüz belirli bir güne eklenmedi."
|
||||
"unscheduled_items_desc": "Bu öğeler bu geziye bağlı ancak henüz belirli bir güne eklenmedi.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -705,6 +705,7 @@
|
||||
"aqua": "Аква",
|
||||
"dark": "Темний",
|
||||
"dim": "тьмяний",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "Ліс",
|
||||
"light": "світло",
|
||||
"night": "ніч",
|
||||
@@ -1138,6 +1139,8 @@
|
||||
"trip_context": "Контекст поїздки",
|
||||
"trip_context_info": "Елементи контексту подорожі застосовуються до всієї подорожі — наприклад, місця, які є самим пунктом призначення, загальні примітки або пакувальні листи, важливі для всієї подорожі.",
|
||||
"unscheduled_items": "Позапланові пункти",
|
||||
"unscheduled_items_desc": "Ці елементи пов’язані з цією поїздкою, але ще не додані до певного дня."
|
||||
"unscheduled_items_desc": "Ці елементи пов’язані з цією поїздкою, але ще не додані до певного дня.",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"aqua": "水色",
|
||||
"dark": "深色",
|
||||
"dim": "昏暗",
|
||||
"catppuccinMocha": "Catppuccin Mocha",
|
||||
"forest": "森林",
|
||||
"light": "浅色",
|
||||
"night": "夜色",
|
||||
@@ -1098,7 +1099,9 @@
|
||||
"remove_from_trip_context": "从上下文中删除",
|
||||
"drag_to_reorder": "拖动以重新排序",
|
||||
"add_to_day": "添加到日期",
|
||||
"add_to_trip_context": "添加旅行背景"
|
||||
"add_to_trip_context": "添加旅行背景",
|
||||
"optimize": "Optimize",
|
||||
"add_place": "+ Add place"
|
||||
},
|
||||
"collections": {
|
||||
"all_items": "所有项目",
|
||||
|
||||
Reference in New Issue
Block a user