- Create report creation page with step-by-step media uploads and categories loading - Create report details view page with history events log and messaging section - Implement MessageComposer and MessageList components for chat workflow - Implement MediaUploader with drag-and-drop support, file type, and size validation - Implement Pagination component with dynamic buttons and ellipsis support - Implement user profile settings summary page and notifications listing page
149 lines
4.9 KiB
Vue
149 lines
4.9 KiB
Vue
<script setup lang="ts">
|
|
import type { CreateReportRequest } from '~/types/api'
|
|
|
|
definePageMeta({
|
|
middleware: 'auth',
|
|
})
|
|
|
|
useHead({ title: 'Crea Segnalazione - Visione' })
|
|
|
|
const router = useRouter()
|
|
const { createReport, uploadMedia } = useReports()
|
|
const { user } = useAuth()
|
|
|
|
// Fetch categories
|
|
const { data: categoriesData } = await useAsyncData('categories', () =>
|
|
$fetch('/api/v1/admin/categories')
|
|
)
|
|
const categories = computed(() => (categoriesData.value as any)?.categories || [])
|
|
|
|
// 👇 Manteniamo una sola dichiarazione per queste variabili
|
|
const isLoading = ref(false)
|
|
const errorMessage = ref('')
|
|
|
|
// 👇 Manteniamo una sola funzione handleReportSubmit
|
|
const handleReportSubmit = async (reportData: CreateReportRequest, mediaFiles: File[]) => {
|
|
isLoading.value = true
|
|
errorMessage.value = ''
|
|
|
|
try {
|
|
// Step 1: Carica i file media se presenti
|
|
let uploadedMediaUrls: string[] = []
|
|
|
|
if (mediaFiles.length > 0) {
|
|
console.log('📸 Media files to upload:', mediaFiles)
|
|
}
|
|
|
|
// Step 2: Crea la segnalazione
|
|
const response = await createReport({
|
|
...reportData,
|
|
media: uploadedMediaUrls, // Se l'API richiede stringhe pre-uploadate, va bene. Altrimenti passa array vuoto.
|
|
})
|
|
|
|
if (response.ok) {
|
|
// Step 3: Se ha media, carica dopo la creazione usando l'ID
|
|
if (mediaFiles.length > 0 && response.report_id) {
|
|
try {
|
|
const formData = new FormData()
|
|
mediaFiles.forEach((file) => {
|
|
formData.append('files', file)
|
|
})
|
|
|
|
await uploadMedia(response.report_id, formData)
|
|
console.log('✅ Media uploaded successfully')
|
|
} catch (err) {
|
|
console.error('⚠️ Media upload failed (non-critical):', err)
|
|
}
|
|
}
|
|
|
|
console.log('✅ Segnalazione creata:', response.report_id)
|
|
|
|
// Redirect al dettaglio della segnalazione
|
|
await router.push(`/reports/${response.report_id}`)
|
|
}
|
|
} catch (error: any) {
|
|
errorMessage.value = error.data?.message || 'Errore durante la creazione della segnalazione. Riprova.'
|
|
console.error('❌ Error creating report:', error)
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<!-- HERO -->
|
|
<div class="it-hero-wrapper it-primary-bg">
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="it-hero-text-wrapper p-4">
|
|
<h1 class="text-white font-weight-bold">Segnala un problema</h1>
|
|
<p class="text-white mt-2 lead">
|
|
Aiutaci a migliorare la città condividendo i disservizi che noti
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- CONTENUTO -->
|
|
<div class="container my-5">
|
|
<div class="row">
|
|
<div class="col-12 col-lg-8 offset-lg-2">
|
|
|
|
<!-- CALLOUT INFO -->
|
|
<div class="callout callout-highlight callout-primary mb-4">
|
|
<div class="callout-title">
|
|
<BIIcon name="it-info-circle" />
|
|
La tua segnalazione è anonima
|
|
</div>
|
|
<p>
|
|
I tuoi dati personali non saranno visibili pubblicamente. La segnalazione verrà elaborata dagli operatori comunali e potrai tracciare lo stato dell'intervento in tempo reale.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- ERRORE GLOBALE -->
|
|
<div v-if="errorMessage" class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
{{ errorMessage }}
|
|
<button type="button" class="btn-close" @click="errorMessage = ''"></button>
|
|
</div>
|
|
|
|
<!-- INFO UTENTE -->
|
|
<div class="card card-bg mb-4">
|
|
<div class="card-body">
|
|
<h6 class="card-title font-weight-bold mb-3">
|
|
<BIIcon name="it-user" size="sm" color="primary" class="me-2" />
|
|
Stai segnalando come:
|
|
</h6>
|
|
<div class="small">
|
|
<strong>{{ user?.first_name }} {{ user?.last_name }}</strong><br>
|
|
<span class="text-muted">{{ user?.email }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FORM PRINCIPALE -->
|
|
<ReportForm :categories="categories" :is-loading="isLoading" @submit="handleReportSubmit" />
|
|
|
|
<!-- NOTE LEGALI -->
|
|
<div class="alert alert-info mt-5" role="alert">
|
|
<small class="d-block">
|
|
Sottoponendo questa segnalazione accetti i nostri <NuxtLink to="/privacy" target="_blank">Termini di Servizio</NuxtLink>
|
|
e l'<NuxtLink to="/privacy" target="_blank">Informativa sulla Privacy</NuxtLink>.
|
|
Le segnalazioni con contenuti abusivi o offensivi verranno rimosse e l'utente potrebbe essere sanzionato.
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.it-primary-bg {
|
|
background: linear-gradient(135deg, #006f9d 0%, #003d5c 100%);
|
|
}
|
|
</style> |