feat(admin): add delete functionality for areas, categories, and teams in admin panel

This commit is contained in:
gabdevele
2026-06-15 15:50:05 +02:00 Unverified
parent caa014b33f
commit 0808f763cf
9 changed files with 538 additions and 45 deletions
+58 -18
View File
@@ -9,7 +9,7 @@ definePageMeta({
useHead({ title: 'Aree - Admin' })
const { getAreas, createArea, updateArea } = useAdmin()
const { getAreas, createArea, updateArea, deleteArea } = useAdmin()
const { data: areasRes, pending, refresh } = useAsyncData('admin-areas', () => getAreas())
const isCreating = ref(false)
@@ -20,6 +20,9 @@ const formData = reactive({
geojson: ''
})
const jsonError = ref('')
const actionError = ref('')
const deletingAreaId = ref<number | null>(null)
const areaPendingDelete = ref<any | null>(null)
// Map variables
let map: any = null
@@ -29,8 +32,10 @@ const mapPoints = ref<[number, number][]>([])
const modalTitle = computed(() => editingAreaId.value ? 'Modifica Area' : 'Nuova Area')
const submitLabel = computed(() => editingAreaId.value ? 'Salva Modifiche' : 'Crea Area')
const isEditing = computed(() => editingAreaId.value !== null)
const areas = computed(() => areasRes.value?.areas || [])
const openCreateModal = () => {
actionError.value = ''
editingAreaId.value = null
formData.name = ''
formData.description = ''
@@ -98,6 +103,7 @@ const loadPolygonFromGeoJson = (boundaryGeojson: any) => {
}
const openEditModal = (area: any) => {
actionError.value = ''
editingAreaId.value = area.id
formData.name = area.name || ''
formData.description = area.description || ''
@@ -218,22 +224,45 @@ const handleCreate = async () => {
if (res.ok) {
await refresh()
closeCreateModal()
actionError.value = ''
}
} catch (err) {
console.error('Failed to save area', err)
alert('Errore durante il salvataggio dell\'area.')
actionError.value = 'Errore durante il salvataggio dell\'area.'
}
}
const handleToggleAreaActive = async (area: any) => {
const askDeleteArea = (area: any) => {
areaPendingDelete.value = area
}
const closeDeleteAreaModal = () => {
if (deletingAreaId.value) return
areaPendingDelete.value = null
}
const handleDeleteArea = async () => {
if (!areaPendingDelete.value) return
const area = areaPendingDelete.value
deletingAreaId.value = area.id
actionError.value = ''
try {
const res = await updateArea(area.id, { active: !area.active })
const res = await deleteArea(area.id)
if (res.ok) {
if (editingAreaId.value === area.id) {
closeCreateModal()
}
await refresh()
areaPendingDelete.value = null
}
} catch (err) {
console.error('Failed to update area status', err)
alert('Errore durante l\'aggiornamento dello stato area.')
} catch (err: any) {
console.error('Failed to delete area', err)
actionError.value = err?.data?.message || 'Errore durante eliminazione area.'
} finally {
deletingAreaId.value = null
}
}
</script>
@@ -255,10 +284,14 @@ const handleToggleAreaActive = async (area: any) => {
<div class="spinner-border text-primary" role="status"></div>
</div>
<div v-else-if="!areasRes?.areas || areasRes.areas.length === 0" class="alert alert-info">
<div v-else-if="areas.length === 0" class="alert alert-info">
Nessuna area configurata.
</div>
<div v-if="actionError" class="alert alert-danger">
{{ actionError }}
</div>
<div v-else class="table-responsive">
<table class="table table-hover align-middle bg-white shadow-sm rounded">
<thead class="table-light">
@@ -266,20 +299,15 @@ const handleToggleAreaActive = async (area: any) => {
<th>ID</th>
<th>Nome</th>
<th>Descrizione</th>
<th>Stato</th>
<th>GeoJSON</th>
<th class="text-end">Azioni</th>
</tr>
</thead>
<tbody>
<tr v-for="area in areasRes.areas" :key="area.id">
<tr v-for="area in areas" :key="area.id">
<td>{{ area.id }}</td>
<td><strong>{{ area.name }}</strong></td>
<td>{{ area.description || '-' }}</td>
<td>
<span v-if="area.active" class="badge bg-success">Attiva</span>
<span v-else class="badge bg-secondary">Inattiva</span>
</td>
<td>
<span v-if="area.boundary_geojson" class="badge border border-primary text-primary">Configurato</span>
<span v-else class="badge border border-danger text-danger">Mancante</span>
@@ -289,11 +317,12 @@ const handleToggleAreaActive = async (area: any) => {
Modifica
</button>
<button
class="btn btn-sm"
:class="area.active ? 'btn-outline-secondary' : 'btn-outline-success'"
@click="handleToggleAreaActive(area)"
class="btn btn-sm btn-outline-danger ms-2"
:disabled="deletingAreaId === area.id"
@click="askDeleteArea(area)"
>
{{ area.active ? 'Disattiva' : 'Attiva' }}
<span v-if="deletingAreaId === area.id" class="spinner-border spinner-border-sm me-1"></span>
Elimina
</button>
</td>
</tr>
@@ -360,6 +389,17 @@ const handleToggleAreaActive = async (area: any) => {
</div>
</div>
</div>
<ConfirmModal
:open="areaPendingDelete !== null"
title="Elimina area"
:message="areaPendingDelete ? `Vuoi eliminare area \\\"${areaPendingDelete.name}\\\"? Operazione irreversibile.` : ''"
confirm-label="Elimina area"
confirm-class="btn-danger"
:pending="deletingAreaId !== null"
@cancel="closeDeleteAreaModal"
@confirm="handleDeleteArea"
/>
</div>
</template>