feat(services): add delete button to remove service from DB

- Add trash icon button with confirmation dialog on service list
- DELETE /services/{service} hard-deletes service, its songs, and non-info slides
- Service will be recreated on next CTS sync
This commit is contained in:
Thorsten Bus 2026-03-02 13:25:52 +01:00
parent bb25b3b98d
commit f561c0ada9

View file

@ -19,6 +19,9 @@ const toastType = ref('info')
const confirmDialog = ref(false)
const confirmWarnings = ref([])
const confirmServiceId = ref(null)
const deleteDialog = ref(false)
const deleteServiceId = ref(null)
const deleteServiceTitle = ref('')
const finalizing = ref(false)
const showArchived = computed(() => props.archived)
@ -128,6 +131,30 @@ function reopenService(serviceId) {
})
}
function promptDeleteService(service) {
deleteServiceId.value = service.id
deleteServiceTitle.value = service.title
deleteDialog.value = true
}
function cancelDeleteService() {
deleteDialog.value = false
deleteServiceId.value = null
deleteServiceTitle.value = ''
}
function confirmDeleteService() {
router.delete(route('services.destroy', deleteServiceId.value), {
preserveScroll: true,
onSuccess: () => {
deleteDialog.value = false
deleteServiceId.value = null
deleteServiceTitle.value = ''
showToast('Service wurde gelöscht.', 'success')
},
})
}
async function downloadService(serviceId) {
try {
const response = await fetch(route('services.download', serviceId), {
@ -340,6 +367,14 @@ function stateIconClass(isDone) {
>
Herunterladen
</button>
<button
data-testid="service-list-delete-button"
type="button"
class="inline-flex items-center justify-center rounded-md border border-red-300 bg-red-50 px-3 py-1.5 text-xs font-semibold text-red-800 transition hover:bg-red-100"
@click="promptDeleteService(service)"
>
Löschen
</button>
</template>
<template v-else>
@ -360,6 +395,14 @@ function stateIconClass(isDone) {
>
Abschließen
</button>
<button
data-testid="service-list-delete-button"
type="button"
class="inline-flex items-center justify-center rounded-md border border-red-300 bg-red-50 px-3 py-1.5 text-xs font-semibold text-red-800 transition hover:bg-red-100"
@click="promptDeleteService(service)"
>
Löschen
</button>
</template>
</div>
</td>
@ -425,5 +468,45 @@ function stateIconClass(isDone) {
</div>
</Transition>
</Teleport>
<Teleport to="body">
<Transition
enter-active-class="transition duration-200 ease-out"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition duration-150 ease-in"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div
v-if="deleteDialog"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4"
@click.self="cancelDeleteService"
>
<div class="w-full max-w-md rounded-xl bg-white p-6 shadow-xl">
<h3 class="text-lg font-semibold text-gray-900">Service löschen?</h3>
<p class="mt-2 text-sm text-gray-600">
{{ deleteServiceTitle }}" wird gelöscht und beim nächsten Sync aus ChurchTools neu erstellt.
</p>
<div class="mt-5 flex justify-end gap-3">
<button
type="button"
class="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 transition hover:bg-gray-50"
@click="cancelDeleteService"
>
Abbrechen
</button>
<button
type="button"
class="rounded-md border border-red-300 bg-red-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-red-700"
@click="confirmDeleteService"
>
Löschen
</button>
</div>
</div>
</div>
</Transition>
</Teleport>
</AuthenticatedLayout>
</template>