owltide/components/DiffScheduleShift.vue
Hornwitser 1d2edf7535 Add dialog showing diff of changes to save
Add a save dialog at the bottom of the screen that is present whenever
there are unsaved changes.  This dialog provides a diff between the
client and server state so that the user can easily confirm the changes
they are about to make are the correct changes before applying them to
the server.
2025-06-30 15:43:15 +02:00

96 lines
2.4 KiB
Vue

<template>
<div>
<h4>{{ state }} {{ shift.name }}</h4>
<DiffFieldString
title="Name"
:before="shift.serverName"
:after="shift.name"
:state
/>
<DiffFieldEntityId
title="Role"
:before="shift.serverRoleId"
:after="shift.roleId"
:entities="schedule.roles"
:state
/>
<DiffFieldString
title="Description"
:before="shift.serverDescription"
:after="shift.description"
:state
/>
<DiffScheduleShiftSlot
v-for="[state, slot] in slots"
:key="slot.id"
:slot
:schedule
:state
/>
</div>
</template>
<script lang="ts" setup>
const props = defineProps<{
shift: ClientScheduleShift,
schedule: ClientSchedule,
}>();
const state = computed(() => {
if (props.shift.deleted) return "deleted";
if (props.shift.isNew()) return "created";
return "modified";
});
const slots = computed((): [
"deleted" | "created" | "modified", ClientScheduleShiftSlot
][] => {
const afterIds = props.shift.slotIds;
const beforeIds = props.shift.serverSlotIds;
if (state.value === "deleted") {
return (
[...beforeIds]
.map(id => props.schedule.shiftSlots.get(id))
.filter(slot => slot !== undefined)
.map(slot => ["deleted", slot] as ["deleted", ClientScheduleShiftSlot])
);
}
if (state.value === "created") {
return (
[...afterIds]
.map(id => props.schedule.shiftSlots.get(id))
.filter(slot => slot !== undefined)
.map(slot => ["created", slot] as ["created", ClientScheduleShiftSlot])
);
}
const added = [...toRaw(afterIds).difference(beforeIds)]
.map(id => props.schedule.shiftSlots.get(id))
.filter(slot => slot !== undefined)
.filter(slot => !slot.deleted)
.map(slot => ["created", slot] as ["created", ClientScheduleShiftSlot])
;
const removed = [...new Set(
[...toRaw(beforeIds).difference(afterIds)]
.map(id => props.schedule.shiftSlots.get(id))
.filter(slot => slot !== undefined)
).union(
new Set(
[...afterIds]
.map(id => props.schedule.shiftSlots.get(id))
.filter(slot => slot !== undefined)
.filter(slot => slot.deleted)
)
)]
.map(slot => ["deleted", slot] as ["deleted", ClientScheduleShiftSlot])
;
const modified = [...toRaw(afterIds).intersection(beforeIds)]
.map(id => props.schedule.shiftSlots.get(id))
.filter(slot => slot !== undefined)
.filter(slot => slot.isModified() && !slot.deleted)
.map(slot => ["modified", slot] as ["modified", ClientScheduleShiftSlot])
;
return [
...added,
...removed,
...modified,
];
});
</script>