feat: allow organizer overbooking with confirmation dialog
Remove capacity and status validation from organizer assign flow so organizers can intentionally overbook shifts. Log overbooked assignments for audit trail. Volunteer claims still enforce hard limits. Frontend shows a warning banner when a shift is full and requires confirmation before overbooking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,15 @@ const assignError = ref<string | null>(null)
|
||||
const showSuccess = ref(false)
|
||||
const successName = ref('')
|
||||
|
||||
// Overbooking confirmation
|
||||
const pendingPerson = ref<AssignablePerson | null>(null)
|
||||
const showOverbookConfirm = ref(false)
|
||||
|
||||
const isShiftFull = computed(() => {
|
||||
if (!props.shift) return false
|
||||
return props.shift.filled_slots >= props.shift.slots_total
|
||||
})
|
||||
|
||||
// Clear error on filter changes
|
||||
watch([searchQuery, showOnlyAvailable, selectedCrowdType], () => {
|
||||
assignError.value = null
|
||||
@@ -102,10 +111,30 @@ function getInitials(name: string) {
|
||||
.slice(0, 2)
|
||||
}
|
||||
|
||||
async function handleAssign(person: AssignablePerson) {
|
||||
function handleAssign(person: AssignablePerson) {
|
||||
if (!props.shift) return
|
||||
assignError.value = null
|
||||
|
||||
if (isShiftFull.value) {
|
||||
pendingPerson.value = person
|
||||
showOverbookConfirm.value = true
|
||||
return
|
||||
}
|
||||
|
||||
executeAssign(person)
|
||||
}
|
||||
|
||||
function confirmOverbook() {
|
||||
if (pendingPerson.value) {
|
||||
executeAssign(pendingPerson.value)
|
||||
}
|
||||
showOverbookConfirm.value = false
|
||||
pendingPerson.value = null
|
||||
}
|
||||
|
||||
async function executeAssign(person: AssignablePerson) {
|
||||
if (!props.shift) return
|
||||
|
||||
try {
|
||||
await assignPerson({
|
||||
sectionId: props.sectionId,
|
||||
@@ -168,6 +197,18 @@ async function handleAssign(person: AssignablePerson) {
|
||||
|
||||
<VDivider class="mb-4" />
|
||||
|
||||
<!-- Overbooking warning -->
|
||||
<VAlert
|
||||
v-if="isShiftFull"
|
||||
type="warning"
|
||||
variant="tonal"
|
||||
density="compact"
|
||||
class="mb-3"
|
||||
>
|
||||
<strong>Shift is vol</strong> — {{ shift.filled_slots }}/{{ shift.slots_total }}
|
||||
plekken bezet. Je kunt nog steeds iemand toewijzen, maar de shift wordt overbezet.
|
||||
</VAlert>
|
||||
|
||||
<!-- Error alert -->
|
||||
<VAlert
|
||||
v-if="assignError"
|
||||
@@ -352,6 +393,40 @@ async function handleAssign(person: AssignablePerson) {
|
||||
</VCard>
|
||||
</VDialog>
|
||||
|
||||
<!-- Overbook confirmation -->
|
||||
<VDialog
|
||||
v-model="showOverbookConfirm"
|
||||
max-width="420"
|
||||
>
|
||||
<VCard>
|
||||
<VCardTitle class="text-h6 pt-5 px-5">
|
||||
Shift overbezetten?
|
||||
</VCardTitle>
|
||||
<VCardText class="px-5">
|
||||
Deze shift heeft {{ shift?.slots_total }} plekken en
|
||||
{{ shift?.filled_slots }} zijn bezet. Wil je
|
||||
<strong>{{ pendingPerson?.name }}</strong> toch toewijzen?
|
||||
</VCardText>
|
||||
<VCardActions class="px-5 pb-5">
|
||||
<VSpacer />
|
||||
<VBtn
|
||||
variant="tonal"
|
||||
@click="showOverbookConfirm = false"
|
||||
>
|
||||
Annuleren
|
||||
</VBtn>
|
||||
<VBtn
|
||||
color="warning"
|
||||
variant="flat"
|
||||
:loading="isAssigning"
|
||||
@click="confirmOverbook"
|
||||
>
|
||||
Toch toewijzen
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
|
||||
<VSnackbar
|
||||
v-model="showSuccess"
|
||||
color="success"
|
||||
|
||||
Reference in New Issue
Block a user