refactor: fix indentation
This commit is contained in:
@@ -6,12 +6,10 @@ import BIIcon from "~/components/BIIcon.vue";
|
||||
const route = useRoute()
|
||||
const isMobileMenuOpen = ref(false)
|
||||
|
||||
// 1. Close menu on route change
|
||||
watch(() => route.path, () => {
|
||||
isMobileMenuOpen.value = false
|
||||
})
|
||||
|
||||
// 2. Prevent body scroll when mobile menu is open
|
||||
watch(isMobileMenuOpen, (isOpen) => {
|
||||
if (typeof document !== 'undefined') {
|
||||
if (isOpen) {
|
||||
@@ -22,7 +20,6 @@ watch(isMobileMenuOpen, (isOpen) => {
|
||||
}
|
||||
})
|
||||
|
||||
// 3. Failsafe: Re-enable scrolling if the component is destroyed while menu is open
|
||||
onUnmounted(() => {
|
||||
if (typeof document !== 'undefined') {
|
||||
document.body.style.overflow = ''
|
||||
@@ -151,7 +148,6 @@ const panelLabel = computed(() => user.value?.role?.toUpperCase() === 'ADMIN' ?
|
||||
<div class="close-div">
|
||||
<button class="btn close-menu" type="button" @click="isMobileMenuOpen = false">
|
||||
<span class="visually-hidden">Nascondi la navigazione</span>
|
||||
<!-- FIXED: Added color="black" so it's visible on white -->
|
||||
<BIIcon name="it-close-big" color="black"/>
|
||||
</button>
|
||||
</div>
|
||||
@@ -200,7 +196,6 @@ const panelLabel = computed(() => user.value?.role?.toUpperCase() === 'ADMIN' ?
|
||||
background-color: rgb(0, 76.5, 153);
|
||||
}
|
||||
|
||||
/* --- MOBILE MENU FIXES --- */
|
||||
@media (max-width: 991.98px) {
|
||||
.overlay {
|
||||
position: fixed;
|
||||
@@ -241,7 +236,6 @@ const panelLabel = computed(() => user.value?.role?.toUpperCase() === 'ADMIN' ?
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
/* FIXED: Removed the border-bottom here */
|
||||
.close-div {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
@@ -130,7 +130,6 @@ const removeFile = (idx: number) => {
|
||||
font-size: 0.55rem;
|
||||
}
|
||||
|
||||
/* Stili specifici richiesti per la chat */
|
||||
.chat-textarea {
|
||||
resize: none !important;
|
||||
height: 48px;
|
||||
|
||||
@@ -55,7 +55,6 @@ const reportHref = (report: Report) => `${props.detailBasePath}/${report.id}`
|
||||
<td class="report-table-id">#{{ report.id }}</td>
|
||||
<td class="text-nowrap">{{ report.category_name || '-' }}</td>
|
||||
<td>
|
||||
<!-- Added inline-block, text-truncate (for ellipsis), and max-width 10ch -->
|
||||
<span class="report-address d-inline-block text-truncate align-middle" style="max-width: 10ch;" :title="report.address">
|
||||
{{ report.address || '-' }}
|
||||
</span>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'
|
||||
import type { Map as LeafletMap, CircleMarker, LatLngBoundsExpression } from 'leaflet'
|
||||
import { BARI_BOUNDS, BARI_CENTER, isWithinBariBounds } from '~/utils/bari'
|
||||
|
||||
// 1. API Fetching Logic
|
||||
const { getOpenDataReports } = usePublic()
|
||||
|
||||
// Reactive pagination state
|
||||
@@ -34,14 +33,12 @@ const prevPage = () => {
|
||||
if (currentPage.value > 1) currentPage.value--
|
||||
}
|
||||
|
||||
// 2. View Toggle (Grid vs Map)
|
||||
const currentView = ref<'grid' | 'map'>('grid')
|
||||
const mapContainer = ref<HTMLElement | null>(null)
|
||||
let leaflet: typeof import('leaflet') | null = null
|
||||
let map: LeafletMap | null = null
|
||||
let markers: CircleMarker[] = []
|
||||
|
||||
// 3. Helper to style status badges
|
||||
const getStatusBadge = (status: string) => {
|
||||
switch (status) {
|
||||
case 'RESOLVED': return { class: 'bg-success', text: 'Risolto', icon: 'it-check-circle' }
|
||||
|
||||
@@ -44,7 +44,6 @@ const statusMeta: Record<string, string> = {
|
||||
CLOSED: 'Chiusa'
|
||||
}
|
||||
|
||||
// Mappa delle transizioni (Equivalente al backend C++)
|
||||
const statusTransitions: Record<string, string[]> = {
|
||||
OPEN: ['UNDER_REVIEW', 'REJECTED'],
|
||||
UNDER_REVIEW: ['ASSIGNED', 'REJECTED'],
|
||||
@@ -65,15 +64,12 @@ const availableStatuses: { value: ReportStatus, label: string }[] = [
|
||||
{ value: 'CLOSED', label: 'Chiusa' }
|
||||
]
|
||||
|
||||
// Computed per ottenere solo gli stati di destinazione validi
|
||||
const selectableStatuses = computed(() => {
|
||||
if (!report.value?.status) return []
|
||||
const allowed = statusTransitions[report.value.status] || []
|
||||
return availableStatuses.filter(s => allowed.includes(s.value))
|
||||
})
|
||||
|
||||
// Logica per consentire il link di intervento
|
||||
// Corrisponde alla query: SELECT id FROM assignments WHERE report_id = ? AND ended_at IS NULL
|
||||
const canCreateInterventionLink = computed(() => {
|
||||
if (summary.value?.assignments && Array.isArray(summary.value.assignments)) {
|
||||
return summary.value.assignments.some((a: any) => !a.ended_at)
|
||||
@@ -81,7 +77,6 @@ const canCreateInterventionLink = computed(() => {
|
||||
return ['ASSIGNED', 'IN_PROGRESS'].includes(report.value?.status)
|
||||
})
|
||||
|
||||
// Form Cambia Stato
|
||||
const newStatus = ref<ReportStatus>('IN_PROGRESS')
|
||||
const statusNote = ref('')
|
||||
const isUpdatingStatus = ref(false)
|
||||
@@ -100,13 +95,12 @@ const isRevokeInterventionModalOpen = ref(false)
|
||||
|
||||
// Messaggi
|
||||
const isSubmittingMessage = ref(false)
|
||||
const flaggedMessageIds = ref<number[]>([]) // Array locale per evitare lo spam di segnalazioni
|
||||
const flaggedMessageIds = ref<number[]>([])
|
||||
const isFlagMessageModalOpen = ref(false)
|
||||
const messageToFlag = ref<Message | null>(null)
|
||||
const isFlaggingMessage = ref(false)
|
||||
const isFlaggingMessageId = computed(() => isFlaggingMessage.value ? messageToFlag.value?.id : null)
|
||||
|
||||
// Inizializza lo stato nel form (seleziona automaticamente la prima transizione disponibile)
|
||||
watch(() => report.value?.status, (val) => {
|
||||
if (val) {
|
||||
const allowed = statusTransitions[val] || []
|
||||
@@ -236,7 +230,6 @@ const handleSendMessage = async (msgText: string, files: File[]) => {
|
||||
const canFlagMessage = (message: Message) => {
|
||||
if (!user.value) return false
|
||||
const isCitizenMessage = message.user_id !== user.value.id && message.user_id === report.value?.user_id
|
||||
// Non permettere di segnalare se l'id del messaggio è già nell'array (anti-spam)
|
||||
const isAlreadyFlagged = flaggedMessageIds.value.includes(message.id)
|
||||
return isCitizenMessage && !isAlreadyFlagged
|
||||
}
|
||||
@@ -244,7 +237,6 @@ const canFlagMessage = (message: Message) => {
|
||||
const handleFlagMessage = (message: Message) => {
|
||||
if (!canFlagMessage(message)) return
|
||||
|
||||
// Apri il modale per chiedere conferma
|
||||
messageToFlag.value = message
|
||||
isFlagMessageModalOpen.value = true
|
||||
}
|
||||
@@ -257,7 +249,7 @@ const executeFlagMessage = async () => {
|
||||
await flagMessage(reportId, messageToFlag.value.id, {
|
||||
reason: 'Messaggio segnalato da operatore responsabile per verifica moderazione',
|
||||
})
|
||||
// Aggiungi l'id all'array anti-spam locale così l'utente non può più segnalarlo in questa sessione
|
||||
|
||||
flaggedMessageIds.value.push(messageToFlag.value.id)
|
||||
|
||||
isFlagMessageModalOpen.value = false
|
||||
@@ -578,7 +570,6 @@ const formattedInterventionLinkExpiry = computed(() =>
|
||||
@confirm="handleRevokeInterventionLink"
|
||||
/>
|
||||
|
||||
<!-- Nuovo Modale per Conferma Segnalazione -->
|
||||
<ConfirmModal
|
||||
:open="isFlagMessageModalOpen"
|
||||
title="Segnala messaggio"
|
||||
|
||||
@@ -56,7 +56,6 @@ const handleSendMessage = async () => {
|
||||
|
||||
isSubmittingMessage.value = true
|
||||
try {
|
||||
// Gestione mock di file, nella realtà si usa FormData o simile
|
||||
await addMessage(reportId, { body: newMessage.value })
|
||||
|
||||
// Pulisci i campi
|
||||
@@ -421,7 +420,6 @@ const formatDate = (dateString: string): string => {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* Stili specifici per l'input della Chat per gestire le tue richieste visive */
|
||||
.chat-textarea {
|
||||
resize: none !important;
|
||||
height: 48px;
|
||||
|
||||
Reference in New Issue
Block a user