mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2026-01-14 17:39:07 -05:00
feat: enhance lodging management with date validation and update messages
This commit is contained in:
@@ -716,11 +716,13 @@ class UltraSlimCollectionSerializer(serializers.ModelSerializer):
|
||||
location__collections=obj
|
||||
).select_related('user').prefetch_related('location')
|
||||
|
||||
return ContentImageSerializer(
|
||||
serializer = ContentImageSerializer(
|
||||
images,
|
||||
many=True,
|
||||
context={'request': self.context.get('request')}
|
||||
).data
|
||||
)
|
||||
# Filter out None values from the serialized data
|
||||
return [image for image in serializer.data if image is not None]
|
||||
|
||||
def get_location_count(self, obj):
|
||||
"""Get count of locations in this collection"""
|
||||
|
||||
@@ -306,7 +306,7 @@
|
||||
<figure class="aspect-square bg-base-200 overflow-hidden">
|
||||
<img
|
||||
src={image.image_url}
|
||||
alt="Image from Immich"
|
||||
alt="Immich"
|
||||
class="w-full h-full object-cover transition-transform group-hover:scale-105"
|
||||
loading="lazy"
|
||||
/>
|
||||
|
||||
@@ -593,6 +593,7 @@
|
||||
// If we updated the item's date, update local state directly
|
||||
if (updateItemDate) {
|
||||
const isoDate = `${dateISO}T00:00:00`;
|
||||
const nextDayISO = DateTime.fromISO(dateISO).plus({ days: 1 }).toISODate();
|
||||
|
||||
if (objectType === 'location') {
|
||||
// For locations, create a new visit locally
|
||||
@@ -620,15 +621,59 @@
|
||||
}
|
||||
} else if (objectType === 'transportation') {
|
||||
if (collection.transportations) {
|
||||
collection.transportations = collection.transportations.map((t) =>
|
||||
t.id === objectId ? { ...t, date: isoDate } : t
|
||||
);
|
||||
collection.transportations = collection.transportations.map((t) => {
|
||||
if (t.id === objectId) {
|
||||
// If end_date exists and is before the new start date, set it to next day
|
||||
let newEndDate = t.end_date;
|
||||
if (newEndDate) {
|
||||
const endDate = DateTime.fromISO(newEndDate);
|
||||
const startDate = DateTime.fromISO(isoDate);
|
||||
if (endDate < startDate) {
|
||||
// Check if original end_date has a time component (not all-day)
|
||||
const hasTime = !newEndDate.includes('T00:00:00');
|
||||
if (hasTime && t.end_timezone) {
|
||||
// Set to 9am in the end timezone
|
||||
newEndDate = DateTime.fromISO(nextDayISO, { zone: t.end_timezone })
|
||||
.set({ hour: 9, minute: 0, second: 0 })
|
||||
.toISO();
|
||||
} else {
|
||||
// All-day event, keep at UTC 0
|
||||
newEndDate = `${nextDayISO}T00:00:00`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { ...t, date: isoDate, end_date: newEndDate };
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
} else if (objectType === 'lodging') {
|
||||
if (collection.lodging) {
|
||||
collection.lodging = collection.lodging.map((l) =>
|
||||
l.id === objectId ? { ...l, check_in: isoDate } : l
|
||||
);
|
||||
collection.lodging = collection.lodging.map((l) => {
|
||||
if (l.id === objectId) {
|
||||
// If check_out exists and is before the new check_in, set it to next day
|
||||
let newCheckOut = l.check_out;
|
||||
if (newCheckOut) {
|
||||
const checkOut = DateTime.fromISO(newCheckOut);
|
||||
const checkIn = DateTime.fromISO(isoDate);
|
||||
if (checkOut < checkIn) {
|
||||
// Check if original check_out has a time component (not all-day)
|
||||
const hasTime = !newCheckOut.includes('T00:00:00');
|
||||
if (hasTime && l.timezone) {
|
||||
// Set to 9am in the lodging timezone
|
||||
newCheckOut = DateTime.fromISO(nextDayISO, { zone: l.timezone })
|
||||
.set({ hour: 9, minute: 0, second: 0 })
|
||||
.toISO();
|
||||
} else {
|
||||
// All-day event, keep at UTC 0
|
||||
newCheckOut = `${nextDayISO}T00:00:00`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { ...l, check_in: isoDate, check_out: newCheckOut };
|
||||
}
|
||||
return l;
|
||||
});
|
||||
}
|
||||
} else if (objectType === 'note') {
|
||||
if (collection.notes) {
|
||||
|
||||
@@ -745,10 +745,6 @@
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex gap-3 justify-end pt-4">
|
||||
<button class="btn btn-neutral-200 gap-2" on:click={handleBack}>
|
||||
<ArrowLeftIcon class="w-5 h-5" />
|
||||
{$t('adventures.back')}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-primary gap-2"
|
||||
disabled={!lodging.name || !lodging.type || isReverseGeocoding}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
// Icons
|
||||
import ArrowLeftIcon from '~icons/mdi/arrow-left';
|
||||
import CloseIcon from '~icons/mdi/close';
|
||||
import CheckIcon from '~icons/mdi/check';
|
||||
|
||||
import { addToast } from '$lib/toasts';
|
||||
import ImageManagement from '../ImageManagement.svelte';
|
||||
@@ -16,8 +16,8 @@
|
||||
export let attachments: Attachment[] = [];
|
||||
export let itemName: string = '';
|
||||
export let itemId: string = '';
|
||||
export let measurementSystem: 'metric' | 'imperial' = 'metric';
|
||||
export let user: User | null = null;
|
||||
// export let measurementSystem: 'metric' | 'imperial' = 'metric';
|
||||
// export let user: User | null = null;
|
||||
|
||||
// Component state
|
||||
let immichIntegration: boolean = false;
|
||||
@@ -95,8 +95,8 @@
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary gap-2" on:click={handleClose}>
|
||||
<CloseIcon class="w-5 h-5" />
|
||||
{$t('about.close')}
|
||||
<CheckIcon class="w-5 h-5" />
|
||||
{$t('adventures.done')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -258,14 +258,12 @@
|
||||
bind:images={lodging.images}
|
||||
bind:attachments={lodging.attachments}
|
||||
itemName={lodging.name}
|
||||
{user}
|
||||
on:back={() => {
|
||||
steps[1].selected = false;
|
||||
steps[0].selected = true;
|
||||
}}
|
||||
on:close={() => close()}
|
||||
itemId={lodging.id}
|
||||
measurementSystem={user?.measurement_system || 'metric'}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -963,6 +963,8 @@
|
||||
"load_more": "Load More",
|
||||
"immich_error": "Error updating Immich integration",
|
||||
"immich_disabled": "Immich integration disabled successfully!",
|
||||
"immich_updated": "Immich integration updated successfully!",
|
||||
"immich_enabled": "Immich integration enabled successfully!",
|
||||
"disable": "Disable",
|
||||
"server_url": "Immich Server URL",
|
||||
"api_note": "Note: this must be the URL to the Immich API server so it likely ends with /api unless you have a custom config.",
|
||||
|
||||
Reference in New Issue
Block a user