Because it's getting better all the time, including by adding the ability to get new resources when they get created over SSE.
128 lines
2.8 KiB
Vue
128 lines
2.8 KiB
Vue
<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 {
|
|
background-color: #e9ecef;
|
|
border-radius: 10px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
|
|
height: 400px;
|
|
margin-top: 20px;
|
|
position: relative;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<div class="card shadow-sm mb-3">
|
|
<div class="card-header bg-white pane-header">Communication Workbench</div>
|
|
<div class="card-body">
|
|
<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>
|
|
<div
|
|
v-if="!selectedCommunication"
|
|
class="d-flex flex-column align-items-center justify-content-center text-muted"
|
|
>
|
|
<i class="bi bi-hand-index fs-1"></i>
|
|
<p class="mt-2">Select a report to view details</p>
|
|
</div>
|
|
|
|
<div class="h-100 d-flex flex-column" v-else>
|
|
<CardResource
|
|
:resource="resource"
|
|
v-for="(resource, index) in sortedByCreated(
|
|
selectedCommunication.related,
|
|
)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
|
|
import CardResource from "@/components/CardResource.vue";
|
|
import TimeRelative from "@/components/TimeRelative.vue";
|
|
import Map, { LngLatBounds } from "@/map/Map.vue";
|
|
import Layer from "@/map/Layer.vue";
|
|
import Source from "@/map/Source.vue";
|
|
import { useSessionStore } from "@/store/session";
|
|
import type { Marker } from "@/types";
|
|
import type {
|
|
Bounds,
|
|
Communication,
|
|
PublicReport,
|
|
ResourceStub,
|
|
User,
|
|
} from "@/type/api";
|
|
|
|
interface Emits {
|
|
(e: "viewImage", index: number): void;
|
|
}
|
|
interface Props {
|
|
loading: boolean;
|
|
mapBounds?: LngLatBounds;
|
|
mapMarkers: Marker[];
|
|
selectedCommunication: Communication | undefined;
|
|
selectedReport: PublicReport | undefined;
|
|
}
|
|
|
|
const emit = defineEmits<Emits>();
|
|
const props = defineProps<Props>();
|
|
const session = useSessionStore();
|
|
function openPhotoViewer(index: number) {
|
|
emit("viewImage", index);
|
|
}
|
|
function sortedByCreated(resources: ResourceStub[]): ResourceStub[] {
|
|
return resources.sort((a: ResourceStub, b: ResourceStub): number => {
|
|
return a.created.getTime() - b.created.getTime();
|
|
});
|
|
}
|
|
</script>
|