2 Commits
2 changed files with 31 additions and 7 deletions
+19 -6
View File
@@ -29,6 +29,16 @@ const prevPage = () => {
if (currentPage.value > 1) currentPage.value--
}
const { data: mapOpenDataResponse, pending: mapPending } = useAsyncData(
'open-data-map-reports',
() => getOpenDataReports({ page: 1, per_page: 200 }),
{ lazy: true }
)
const mapVisibleReports = computed(() =>
(mapOpenDataResponse.value?.reports || []).filter((report) => isWithinBariBounds(report.latitude, report.longitude))
)
const currentView = ref<'grid' | 'map'>('grid')
const mapContainer = ref<HTMLElement | null>(null)
let leaflet: typeof import('leaflet') | null = null
@@ -66,12 +76,12 @@ const renderMapMarkers = async () => {
clearMarkers()
if (visibleReports.value.length === 0) {
if (mapVisibleReports.value.length === 0) {
map.setView(BARI_CENTER, 12)
return
}
visibleReports.value.forEach((report) => {
mapVisibleReports.value.forEach((report) => {
const marker = L.circleMarker([report.latitude, report.longitude], {
radius: 8,
weight: 2,
@@ -93,7 +103,7 @@ const renderMapMarkers = async () => {
markers.push(marker)
})
const fitBounds: LatLngBoundsExpression = visibleReports.value.map((report) => [report.latitude, report.longitude])
const fitBounds: LatLngBoundsExpression = mapVisibleReports.value.map((report) => [report.latitude, report.longitude])
map.fitBounds(fitBounds, { padding: [32, 32], maxZoom: 15 })
}
@@ -130,7 +140,7 @@ watch(currentView, async (view) => {
}
})
watch(visibleReports, async () => {
watch(mapVisibleReports, async () => {
if (currentView.value === 'map' && map) {
await renderMapMarkers()
}
@@ -266,7 +276,10 @@ onBeforeUnmount(() => {
<div v-show="!pending && currentView === 'map'" class="map-view-wrapper">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
<p class="text-muted mb-0">Mappa pubblica delle segnalazioni nell'area di Bari.</p>
<span class="badge bg-light text-dark border">{{ visibleReports.length }} punti</span>
<span class="badge bg-light text-dark border">
<template v-if="mapPending">Caricamento...</template>
<template v-else>{{ mapVisibleReports.length }} punti</template>
</span>
</div>
<ClientOnly>
<div ref="mapContainer" class="open-data-map rounded border"></div>
@@ -305,4 +318,4 @@ onBeforeUnmount(() => {
line-height: 1.4;
min-width: 12rem;
}
</style>
</style>
+12 -1
View File
@@ -69,6 +69,12 @@ const handleSubmitFeedback = async () => {
const isOwner = computed(() => report.value?.user_id === user.value?.id)
const canFeedback = computed(() => report.value?.status === 'RESOLVED')
const canChat = computed(() => {
if (!report.value) return false
const closedStatuses = ['RESOLVED', 'CLOSED', 'REJECTED']
return !closedStatuses.includes(report.value.status)
})
const statusMeta: Record<string, { label: string; tone: string }> = {
OPEN: { label: 'Aperta', tone: 'info' },
UNDER_REVIEW: { label: 'In revisione', tone: 'warning' },
@@ -210,7 +216,12 @@ const formatDate = (dateString: string): string => {
<MessageList :messages="messages"/>
<MessageComposer @send="handleSendMessage"/>
<MessageComposer v-if="canChat" @send="handleSendMessage"/>
<div v-else class="alert alert-secondary mt-3 mb-0 text-center small">
La chat è disabilitata poiché la segnalazione è in stato
<strong>{{ statusMeta[report.status]?.label || report.status }}</strong>.
</div>
</div>
</div>
</div>