From e3ff872b5c1f1b57078d5f7e8b6d4c3e9e2286f0 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Mon, 23 Jun 2025 22:46:39 +0200 Subject: [PATCH] Refactor ClientSchedule to mutable types Use a single mutable location, event, slot, etc, for each unique resource that keeps track of the local editable client copy and the server copy of the data contained in it. This makes it much simpler to update these data structures as I can take advantage of the v-model bindings in Vue.js and work with the system instead of against it. --- components/TableScheduleEventSlots.vue | 66 +- components/TableScheduleEvents.vue | 38 +- components/TableScheduleLocations.vue | 38 +- components/TableScheduleRoles.vue | 42 +- components/TableScheduleShiftSlots.vue | 56 +- components/TableScheduleShifts.vue | 49 +- components/Timetable.vue | 24 +- pages/edit.vue | 2 +- plugins/payload-client-map.ts | 8 +- stores/schedules.ts | 2 +- utils/client-entity.ts | 82 ++ utils/client-map.nuxt.test.ts | 7 +- utils/client-map.ts | 24 +- utils/client-schedule.nuxt.test.ts | 627 ++++++++----- utils/client-schedule.ts | 1181 ++++++++++++------------ utils/client-user.ts | 92 +- 16 files changed, 1213 insertions(+), 1125 deletions(-) create mode 100644 utils/client-entity.ts diff --git a/components/TableScheduleEventSlots.vue b/components/TableScheduleEventSlots.vue index 303b00d..e3d6650 100644 --- a/components/TableScheduleEventSlots.vue +++ b/components/TableScheduleEventSlots.vue @@ -91,41 +91,39 @@ {{ status(es) }} @@ -185,7 +183,7 @@ {{ es.end.diff(es.start).toFormat('hh:mm') }} {{ es.name }} {{ status(es) }} - {{ es.location.id }} + {{ es.locationId }} @@ -213,7 +211,7 @@ interface EventSlot { event: ClientScheduleEvent, slot: ClientScheduleEventSlot, name: string, - location: ClientScheduleLocation, + locationId: Id, assigned: Set, start: DateTime, end: DateTime, @@ -290,48 +288,30 @@ function durationFromTime(time: string) { return duration; } const newEventName = ref(""); -function editEvent( - eventSlot: EventSlot, - edits: Parameters[1], -) { - schedule.value.editEvent(eventSlot.event, edits); -} function editEventSlot( eventSlot: EventSlot, edits: { - deleted?: boolean, start?: string, end?: string, duration?: string, locationId?: Id, - assigned?: Set, } ) { - const computedEdits: Parameters[1] = { - deleted: edits.deleted, - assigned: edits.assigned, - }; if (edits.start) { const start = DateTime.fromISO(edits.start, { zone: accountStore.activeTimezone, locale: accountStore.activeLocale }); - computedEdits.start = start; - computedEdits.end = start.plus(eventSlot.end.diff(eventSlot.start)); + eventSlot.slot.start = start; + eventSlot.slot.end = start.plus(eventSlot.end.diff(eventSlot.start)); } if (edits.end !== undefined) { - computedEdits.end = endFromTime(eventSlot.start, edits.end); + eventSlot.slot.end = endFromTime(eventSlot.start, edits.end); } if (edits.duration !== undefined) { - computedEdits.end = eventSlot.start.plus(durationFromTime(edits.duration)); + eventSlot.slot.end = eventSlot.start.plus(durationFromTime(edits.duration)); } if (edits.locationId !== undefined) { - const location = schedule.value.locations.get(edits.locationId); - if (location) - computedEdits.locations = [location]; + eventSlot.slot.locationIds = new Set([edits.locationId]); } - schedule.value.editEventSlot(eventSlot.slot, computedEdits); -} -function revertEventSlot(id: Id) { - schedule.value.restoreEventSlot(id); } function newEventSlot(options: { start?: DateTime, end?: DateTime } = {}) { const name = newEventName.value; @@ -341,8 +321,7 @@ function newEventSlot(options: { start?: DateTime, end?: DateTime } = {}) { alert("Invalid event"); return; } - const location = schedule.value.locations.get(newEventLocation.value!); - if (!location) { + if (newEventLocation.value === undefined) { alert("Invalid location"); return; } @@ -367,18 +346,19 @@ function newEventSlot(options: { start?: DateTime, end?: DateTime } = {}) { alert("Invalid start and/or end time"); return; } - const slot = new ClientScheduleEventSlot( + const slot = ClientScheduleEventSlot.create( + schedule.value, schedule.value.nextClientId--, - false, event.id, start, end, - [location], + new Set([newEventLocation.value]), new Set(), 0, ); + schedule.value.eventSlots.set(slot.id, slot); + event.slotIds.add(slot.id); newEventName.value = ""; - schedule.value.setEventSlot(slot); } const oneHourMs = 60 * 60 * 1000; @@ -399,8 +379,8 @@ const eventSlots = computed(() => { for (const slot of event.slots.values()) { if (props.eventSlotFilter && !props.eventSlotFilter(slot)) continue; - for (const location of slot.locations) { - if (props.locationId !== undefined && location.id !== props.locationId) + for (const locationId of slot.locationIds) { + if (props.locationId !== undefined && locationId !== props.locationId) continue; data.push({ type: "slot", @@ -409,7 +389,7 @@ const eventSlots = computed(() => { event, slot, name: event.name, - location, + locationId, assigned: slot.assigned ?? [], start: slot.start, end: slot.end, diff --git a/components/TableScheduleEvents.vue b/components/TableScheduleEvents.vue index 746e39b..546150c 100644 --- a/components/TableScheduleEvents.vue +++ b/components/TableScheduleEvents.vue @@ -22,17 +22,15 @@ @@ -41,7 +39,7 @@ :disabled="!accountStore.canEditPublic" :value="!event.crew" :checked="!event.crew" - @change="editEvent(event, { crew: !($event as any).target.value })" + @change="event.crew = !($event.target as HTMLInputElement).value" > {{ event.slots.size ? event.slots.size : "" }} @@ -49,12 +47,12 @@ @@ -111,8 +109,7 @@