From fc47313b8a9fbde42e990ab94834e05fa0ca9e4b Mon Sep 17 00:00:00 2001 From: gabdevele Date: Thu, 18 Jun 2026 18:05:49 +0200 Subject: [PATCH] feat: enhance feedback handling and status checks in report management --- app/pages/admin/moderation.vue | 2 + app/pages/operator/reports/[id].vue | 64 +++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/app/pages/admin/moderation.vue b/app/pages/admin/moderation.vue index 1211c11..8fd07c9 100644 --- a/app/pages/admin/moderation.vue +++ b/app/pages/admin/moderation.vue @@ -60,6 +60,7 @@ const handleResolve = async () => { resolution_note: resolveModal.note || undefined }) + resolveModal.pending = false await refresh() closeResolveModal() } catch (err) { @@ -90,6 +91,7 @@ const handleDismiss = async () => { try { await updateModerationFlag(dismissModal.flagId, { status: 'DISMISSED' }) + dismissModal.pending = false await refresh() closeDismissModal() } catch (err) { diff --git a/app/pages/operator/reports/[id].vue b/app/pages/operator/reports/[id].vue index 979dc3c..ddfd88f 100644 --- a/app/pages/operator/reports/[id].vue +++ b/app/pages/operator/reports/[id].vue @@ -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 = { 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([]) @@ -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(() =>
+
+ {{ actionError }} +
+
+ {{ actionSuccess }} +
+
@@ -495,9 +529,12 @@ const formattedInterventionLinkExpiry = computed(() => @flag="handleFlagMessage" />
- Messaggistica disponibile dopo la presa in carico. + {{ isFinalStatus ? 'Messaggistica non disponibile per segnalazioni concluse o rifiutate.' : 'Messaggistica disponibile dopo la presa in carico.' }} +
+ +
+ Messaggistica non disponibile per segnalazioni concluse o rifiutate.
-
@@ -529,9 +566,12 @@ const formattedInterventionLinkExpiry = computed(() =>
- +
+ Assegnazione team non disponibile per segnalazioni concluse o rifiutate. +
@@ -597,7 +637,7 @@ const formattedInterventionLinkExpiry = computed(() => -