feat: enhance feedback handling and status checks in report management

This commit is contained in:
gabdevele
2026-06-18 18:05:49 +02:00 Unverified
parent 2c907044a3
commit fc47313b8a
2 changed files with 54 additions and 12 deletions
+52 -12
View File
@@ -46,6 +46,10 @@ const isTakenByCurrentOperator = computed(() => report.value?.assigned_operator_
const isOpenAndUnassigned = computed(() => report.value?.status === 'OPEN' && !report.value?.assigned_operator_id)
const isReadOnlyPreview = computed(() => !isTakenByCurrentOperator.value)
const canTakeReport = computed(() => isOpenAndUnassigned.value && !isTakenByCurrentOperator.value)
const isFinalStatus = computed(() => ['REJECTED', 'RESOLVED', 'CLOSED'].includes(report.value?.status || ''))
const canAssignTeam = computed(() => !isReadOnlyPreview.value && !isFinalStatus.value && teams.value.length > 0)
const canSendMessage = computed(() => !isReadOnlyPreview.value && !isFinalStatus.value)
const canChangeStatus = computed(() => !isReadOnlyPreview.value && !isFinalStatus.value && selectableStatuses.value.length > 0)
const statusMeta: Record<string, string> = {
OPEN: 'Aperta',
@@ -108,6 +112,8 @@ const interventionLinkError = ref('')
const interventionLinkSuccess = ref('')
const isRevokeInterventionModalOpen = ref(false)
const copyFeedback = ref('')
const actionError = ref('')
const actionSuccess = ref('')
const isSubmittingMessage = ref(false)
const flaggedMessageIds = ref<number[]>([])
@@ -140,6 +146,11 @@ const resetReportFlagForm = () => {
reportFlagError.value = ''
}
const clearActionFeedback = () => {
actionError.value = ''
actionSuccess.value = ''
}
const setPublicInterventionLink = (url?: string) => {
if (!url) {
interventionPublicLink.value = ''
@@ -158,21 +169,25 @@ const handleTakeReport = async () => {
if (!canTakeReport.value || !report.value) return
isTakingReport.value = true
clearActionFeedback()
try {
const res = await takeReport(report.value.id)
if (res.ok) {
await Promise.all([refreshReport(), refreshSummary()])
actionSuccess.value = 'Segnalazione presa in carico.'
}
} catch (e) {
} catch (e: any) {
console.error('Failed to take report', e)
actionError.value = e?.data?.message || 'Presa in carico non riuscita.'
} finally {
isTakingReport.value = false
}
}
const handleStatusUpdate = async () => {
if (isReadOnlyPreview.value) return
if (!canChangeStatus.value) return
isUpdatingStatus.value = true
clearActionFeedback()
try {
const res = await updateReportStatus(reportId, {
status: newStatus.value,
@@ -181,19 +196,22 @@ const handleStatusUpdate = async () => {
if (res.ok) {
statusNote.value = ''
await Promise.all([refreshReport(), refreshSummary()])
actionSuccess.value = 'Stato aggiornato con successo.'
}
} catch (e) {
} catch (e: any) {
console.error('Failed to update status', e)
actionError.value = e?.data?.message || 'Aggiornamento stato non riuscito.'
} finally {
isUpdatingStatus.value = false
}
}
const handleAssignTeam = async () => {
if (isReadOnlyPreview.value) return
if (!canAssignTeam.value) return
if (!selectedTeamId.value) return
isAssigning.value = true
clearActionFeedback()
try {
const res = await assignTeam(reportId, {
team_id: selectedTeamId.value
@@ -202,9 +220,11 @@ const handleAssignTeam = async () => {
isAssignModalOpen.value = false
selectedTeamId.value = null
await Promise.all([refreshReport(), refreshSummary()])
actionSuccess.value = 'Team assegnato con successo.'
}
} catch (e) {
} catch (e: any) {
console.error('Failed to assign team', e)
actionError.value = e?.data?.message || 'Assegnazione team non riuscita.'
} finally {
isAssigning.value = false
}
@@ -231,6 +251,7 @@ const copyInterventionLink = async () => {
const handleCreateInterventionLink = async () => {
if (!canCreateInterventionLink.value) return
isGeneratingInterventionLink.value = true
clearActionFeedback()
interventionLinkError.value = ''
interventionLinkSuccess.value = ''
@@ -264,6 +285,7 @@ const handleRevokeInterventionLink = async () => {
if (!interventionLink.value) return
isRevokingInterventionLink.value = true
clearActionFeedback()
interventionLinkError.value = ''
interventionLinkSuccess.value = ''
@@ -285,14 +307,17 @@ const handleRevokeInterventionLink = async () => {
}
const handleSendMessage = async (msgText: string, files: File[]) => {
if (isReadOnlyPreview.value) return
if (!canSendMessage.value) return
if (!msgText.trim() && files.length === 0) return
isSubmittingMessage.value = true
clearActionFeedback()
try {
await addMessage(reportId, { body: msgText })
await refreshMessages()
} catch (e) {
actionSuccess.value = 'Messaggio inviato.'
} catch (e: any) {
console.error('Failed to send message', e)
actionError.value = e?.data?.message || 'Invio messaggio non riuscito.'
} finally {
isSubmittingMessage.value = false
}
@@ -325,8 +350,10 @@ const executeFlagMessage = async () => {
flaggedMessageIds.value.push(messageToFlag.value.id)
isFlagMessageModalOpen.value = false
messageToFlag.value = null
} catch (e) {
actionSuccess.value = 'Messaggio segnalato alla moderazione.'
} catch (e: any) {
console.error('Failed to flag message', e)
actionError.value = e?.data?.message || 'Segnalazione messaggio non riuscita.'
} finally {
isFlaggingMessage.value = false
}
@@ -419,6 +446,13 @@ const formattedInterventionLinkExpiry = computed(() =>
</div>
<div class="container my-5">
<div v-if="actionError" class="alert alert-danger mb-4">
{{ actionError }}
</div>
<div v-if="actionSuccess" class="alert alert-success mb-4">
{{ actionSuccess }}
</div>
<div class="row g-4">
<div class="col-12 col-xl-7">
<div class="card card-bg border-0 shadow-sm mb-4">
@@ -495,9 +529,12 @@ const formattedInterventionLinkExpiry = computed(() =>
@flag="handleFlagMessage"
/>
<div v-if="isReadOnlyPreview" class="alert alert-secondary mt-3 mb-0 small">
Messaggistica disponibile dopo la presa in carico.
{{ isFinalStatus ? 'Messaggistica non disponibile per segnalazioni concluse o rifiutate.' : 'Messaggistica disponibile dopo la presa in carico.' }}
</div>
<MessageComposer v-else-if="canSendMessage" @send="handleSendMessage" />
<div v-else class="alert alert-secondary mt-3 mb-0 small">
Messaggistica non disponibile per segnalazioni concluse o rifiutate.
</div>
<MessageComposer v-else @send="handleSendMessage" />
</div>
</div>
</div>
@@ -529,9 +566,12 @@ const formattedInterventionLinkExpiry = computed(() =>
</div>
</div>
<div class="card-body pt-0" v-if="!isReadOnlyPreview">
<button class="btn btn-outline-primary w-100" @click="isAssignModalOpen = true" :disabled="teams.length === 0">
<button class="btn btn-outline-primary w-100" @click="isAssignModalOpen = true" :disabled="!canAssignTeam">
Assegna team
</button>
<div v-if="isFinalStatus" class="small text-muted mt-2">
Assegnazione team non disponibile per segnalazioni concluse o rifiutate.
</div>
</div>
</div>
@@ -597,7 +637,7 @@ const formattedInterventionLinkExpiry = computed(() =>
</div>
</template>
<template v-else-if="selectableStatuses.length > 0">
<template v-else-if="canChangeStatus">
<form @submit.prevent="handleStatusUpdate">
<div class="mb-3">
<label class="form-label">Nuovo Stato</label>