2026-03-22 06:40:31 +00:00
|
|
|
<style scoped>
|
|
|
|
|
.badge-larvae {
|
|
|
|
|
background-color: #ffc107;
|
|
|
|
|
color: #000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.badge-pupae {
|
|
|
|
|
background-color: #fd7e14;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.badge-adult {
|
|
|
|
|
background-color: #dc3545;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
.details-section {
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
}
|
|
|
|
|
.icon-standing-water {
|
|
|
|
|
color: #0dcaf0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.icon-nuisance {
|
|
|
|
|
color: #dc3545;
|
|
|
|
|
}
|
|
|
|
|
.map-container {
|
2026-04-27 20:53:46 +00:00
|
|
|
background-color: #e9ecef;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
|
2026-03-22 06:40:31 +00:00
|
|
|
height: 400px;
|
2026-04-27 20:53:46 +00:00
|
|
|
margin-top: 20px;
|
|
|
|
|
position: relative;
|
2026-03-22 06:40:31 +00:00
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|
2026-03-22 06:27:18 +00:00
|
|
|
<template>
|
2026-03-22 10:14:48 +00:00
|
|
|
<div class="card shadow-sm mb-3">
|
|
|
|
|
<div class="card-header bg-white pane-header">Communication Workbench</div>
|
|
|
|
|
<div class="card-body">
|
2026-04-28 14:49:02 +00:00
|
|
|
<div class="map-container">
|
|
|
|
|
<Map :bounds="mapBounds" :markers="mapMarkers">
|
|
|
|
|
<Layer
|
|
|
|
|
id="parcel"
|
|
|
|
|
:minzoom="14"
|
|
|
|
|
:paint="{ 'line-color': '#0f0' }"
|
|
|
|
|
source="tegola"
|
|
|
|
|
sourceLayer="parcel"
|
|
|
|
|
type="line"
|
|
|
|
|
/>
|
|
|
|
|
<Layer
|
|
|
|
|
id="service-area"
|
|
|
|
|
:paint="{ 'line-color': '#f00' }"
|
|
|
|
|
source="tegola"
|
|
|
|
|
sourceLayer="service-area-bounds"
|
|
|
|
|
type="line"
|
|
|
|
|
/>
|
|
|
|
|
<Source
|
|
|
|
|
id="tegola"
|
|
|
|
|
type="vector"
|
|
|
|
|
:tiles="[
|
|
|
|
|
session.urls?.tegola +
|
|
|
|
|
'maps/nidus/{z}/{x}/{y}?id=' +
|
|
|
|
|
session.organization?.id,
|
|
|
|
|
]"
|
|
|
|
|
/>
|
|
|
|
|
</Map>
|
|
|
|
|
</div>
|
2026-04-02 01:07:55 +00:00
|
|
|
<div
|
2026-04-28 14:49:02 +00:00
|
|
|
v-if="!selectedCommunication"
|
|
|
|
|
class="d-flex flex-column align-items-center justify-content-center text-muted"
|
2026-04-02 01:07:55 +00:00
|
|
|
>
|
2026-04-28 14:49:02 +00:00
|
|
|
<i class="bi bi-hand-index fs-1"></i>
|
|
|
|
|
<p class="mt-2">Select a report to view details</p>
|
2026-03-22 10:14:48 +00:00
|
|
|
</div>
|
2026-03-22 06:27:18 +00:00
|
|
|
|
2026-04-28 14:49:02 +00:00
|
|
|
<div class="h-100 d-flex flex-column" v-else>
|
|
|
|
|
<PublicReportCard
|
|
|
|
|
v-if="selectedReport"
|
|
|
|
|
:report="selectedReport"
|
|
|
|
|
@viewImage="openPhotoViewer"
|
|
|
|
|
/>
|
|
|
|
|
<p v-else>Loading details...</p>
|
2026-03-22 06:27:18 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { computed } from "vue";
|
2026-04-28 14:49:02 +00:00
|
|
|
|
|
|
|
|
import PublicReportCard from "@/components/PublicReportCard.vue";
|
|
|
|
|
import TimeRelative from "@/components/TimeRelative.vue";
|
2026-04-27 20:53:46 +00:00
|
|
|
import Map, { LngLatBounds } from "@/map/Map.vue";
|
|
|
|
|
import Layer from "@/map/Layer.vue";
|
|
|
|
|
import Source from "@/map/Source.vue";
|
2026-03-31 14:52:53 +00:00
|
|
|
import { useSessionStore } from "@/store/session";
|
2026-04-28 14:49:02 +00:00
|
|
|
import type { Marker } from "@/types";
|
|
|
|
|
import type { Bounds, Communication, PublicReport, User } from "@/type/api";
|
2026-03-22 06:27:18 +00:00
|
|
|
|
2026-03-22 07:16:42 +00:00
|
|
|
interface Emits {
|
2026-03-31 14:52:53 +00:00
|
|
|
(e: "viewImage", index: number): void;
|
2026-03-22 07:16:42 +00:00
|
|
|
}
|
2026-03-22 06:27:18 +00:00
|
|
|
interface Props {
|
|
|
|
|
loading: boolean;
|
2026-04-27 20:53:46 +00:00
|
|
|
mapBounds?: LngLatBounds;
|
2026-03-22 19:30:11 +00:00
|
|
|
mapMarkers: Marker[];
|
2026-03-22 06:27:18 +00:00
|
|
|
selectedCommunication: Communication | null;
|
2026-04-28 14:49:02 +00:00
|
|
|
selectedReport: PublicReport | undefined;
|
2026-03-22 06:27:18 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-22 07:16:42 +00:00
|
|
|
const emit = defineEmits<Emits>();
|
2026-03-22 06:27:18 +00:00
|
|
|
const props = defineProps<Props>();
|
2026-03-31 14:52:53 +00:00
|
|
|
const session = useSessionStore();
|
|
|
|
|
function openPhotoViewer(index: number) {
|
2026-03-22 07:16:42 +00:00
|
|
|
emit("viewImage", index);
|
|
|
|
|
}
|
2026-03-22 06:27:18 +00:00
|
|
|
</script>
|