feat: update authentication flow and user navigation
This commit is contained in:
@@ -1,144 +0,0 @@
|
||||
<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 { getCategories } = useAdmin()
|
||||
const { user } = useAuth()
|
||||
|
||||
// Fetch categories
|
||||
const { data: categoriesData } = await useAsyncData('categories', () =>
|
||||
getCategories()
|
||||
)
|
||||
const categories = computed(() => categoriesData.value?.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 text-center">
|
||||
<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>
|
||||
@@ -0,0 +1,115 @@
|
||||
<script setup lang="ts">
|
||||
import type { Report } from '~/types/api'
|
||||
|
||||
definePageMeta({
|
||||
middleware: 'auth',
|
||||
})
|
||||
|
||||
useHead({ title: 'Le mie segnalazioni - Visione' })
|
||||
|
||||
const { getReports } = useReports()
|
||||
|
||||
const page = ref(1)
|
||||
const perPage = ref(10)
|
||||
const filterStatus = ref('')
|
||||
|
||||
const { data: reportsRes, pending } = useAsyncData('citizen-reports-list', () => getReports({}))
|
||||
|
||||
const reports = computed<Report[]>(() => reportsRes.value?.reports || [])
|
||||
const filteredReports = computed(() => {
|
||||
if (!filterStatus.value) return reports.value
|
||||
if (filterStatus.value === 'IN_PROGRESS') {
|
||||
return reports.value.filter((report) => report.status === 'IN_PROGRESS' || report.status === 'ASSIGNED')
|
||||
}
|
||||
return reports.value.filter((report) => report.status === filterStatus.value)
|
||||
})
|
||||
|
||||
const paginatedReports = computed(() => {
|
||||
const start = (page.value - 1) * perPage.value
|
||||
return filteredReports.value.slice(start, start + perPage.value)
|
||||
})
|
||||
|
||||
const handleStatusFilter = (status: string) => {
|
||||
filterStatus.value = status === 'all' ? '' : status
|
||||
page.value = 1
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="bg-light border-bottom py-4 mb-4">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3">
|
||||
<div>
|
||||
<h1 class="h3 font-weight-bold mb-1">Le mie segnalazioni</h1>
|
||||
<p class="text-muted mb-0">Consulta stato, cronologia e conversazioni con gli operatori.</p>
|
||||
</div>
|
||||
<NuxtLink to="/reports/new" class="btn btn-primary">
|
||||
<BIIcon name="it-plus-circle" size="sm" color="white" class="me-2" />
|
||||
Nuova segnalazione
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container mb-5">
|
||||
<div class="d-flex flex-wrap gap-2 align-items-center mb-3">
|
||||
<div class="btn-group" role="group" aria-label="Filtri segnalazioni">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="filterStatus === '' ? 'btn-primary' : 'btn-outline-primary'"
|
||||
@click="handleStatusFilter('all')"
|
||||
>
|
||||
Tutte
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="filterStatus === 'OPEN' ? 'btn-primary' : 'btn-outline-primary'"
|
||||
@click="handleStatusFilter('OPEN')"
|
||||
>
|
||||
Aperte
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="filterStatus === 'IN_PROGRESS' ? 'btn-primary' : 'btn-outline-primary'"
|
||||
@click="handleStatusFilter('IN_PROGRESS')"
|
||||
>
|
||||
In corso
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="filterStatus === 'RESOLVED' ? 'btn-primary' : 'btn-outline-primary'"
|
||||
@click="handleStatusFilter('RESOLVED')"
|
||||
>
|
||||
Risolte
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="pending" class="text-center py-5">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Caricamento...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="filteredReports.length === 0" class="alert alert-info" role="alert">
|
||||
Nessuna segnalazione trovata.
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<ReportTable :reports="paginatedReports" action-label="Apri segnalazione" />
|
||||
<Pagination
|
||||
v-if="filteredReports.length > perPage"
|
||||
:current-page="page"
|
||||
:per-page="perPage"
|
||||
:total-items="filteredReports.length"
|
||||
@page-change="page = $event"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,102 @@
|
||||
<script setup lang="ts">
|
||||
import type { CreateReportRequest } from '~/types/api'
|
||||
|
||||
definePageMeta({
|
||||
middleware: 'auth',
|
||||
})
|
||||
|
||||
useHead({ title: 'Nuova segnalazione - Visione' })
|
||||
|
||||
const router = useRouter()
|
||||
const { createReport, uploadMedia } = useReports()
|
||||
const { getCategories } = useAdmin()
|
||||
const { user } = useAuth()
|
||||
|
||||
const { data: categoriesData } = await useAsyncData('categories', () => getCategories())
|
||||
const categories = computed(() => categoriesData.value?.categories || [])
|
||||
|
||||
const isLoading = ref(false)
|
||||
const errorMessage = ref('')
|
||||
|
||||
const handleReportSubmit = async (reportData: CreateReportRequest, mediaFiles: File[]) => {
|
||||
isLoading.value = true
|
||||
errorMessage.value = ''
|
||||
|
||||
try {
|
||||
const response = await createReport({
|
||||
...reportData,
|
||||
media: [],
|
||||
})
|
||||
|
||||
if (response.ok && response.report_id) {
|
||||
if (mediaFiles.length > 0) {
|
||||
try {
|
||||
const formData = new FormData()
|
||||
mediaFiles.forEach((file) => formData.append('files', file))
|
||||
await uploadMedia(response.report_id, formData)
|
||||
} catch (error) {
|
||||
console.error('Media upload failed:', error)
|
||||
}
|
||||
}
|
||||
|
||||
await router.push(`/reports/${response.report_id}`)
|
||||
}
|
||||
} catch (error: any) {
|
||||
errorMessage.value = error.data?.message || 'Errore durante la creazione della segnalazione. Riprova.'
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="it-hero-wrapper it-primary-bg hero-compact">
|
||||
<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">Nuova segnalazione</h1>
|
||||
<p class="text-white mt-2 lead">
|
||||
Descrivi il problema urbano, indica la posizione e allega eventuali media.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-lg-8">
|
||||
<div v-if="errorMessage" class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
{{ errorMessage }}
|
||||
<button type="button" class="btn-close" aria-label="Chiudi" @click="errorMessage = ''"></button>
|
||||
</div>
|
||||
|
||||
<ReportForm :categories="categories" :is-loading="isLoading" @submit="handleReportSubmit" />
|
||||
</div>
|
||||
|
||||
<aside class="col-12 col-lg-4">
|
||||
<div class="card card-bg mb-4">
|
||||
<div class="card-body">
|
||||
<h2 class="h6 card-title mb-3">Account segnalante</h2>
|
||||
<p class="mb-1"><strong>{{ user?.first_name }} {{ user?.last_name }}</strong></p>
|
||||
<p class="small text-muted mb-0">{{ user?.email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="callout callout-highlight callout-primary">
|
||||
<div class="callout-title d-flex align-items-center">
|
||||
<BIIcon name="it-info-circle" size="sm" color="primary" class="me-2" />
|
||||
Privacy
|
||||
</div>
|
||||
<p>
|
||||
I tuoi dati personali non saranno pubblicati. Gli operatori li useranno solo per gestire la segnalazione.
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user