248 lines
6.3 KiB
Vue
248 lines
6.3 KiB
Vue
<style scoped>
|
|
body {
|
|
background-color: #f8f9fa;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
body > .container-fluid {
|
|
flex: 1;
|
|
}
|
|
.progress-bar {
|
|
background-color: #0d6efd;
|
|
transition: width 0.3s ease;
|
|
}
|
|
.reference-number {
|
|
text-align: center;
|
|
color: #6c757d;
|
|
font-size: 0.9rem;
|
|
margin-top: 24px;
|
|
}
|
|
</style>
|
|
<template>
|
|
<router-view v-slot="{ Component }">
|
|
<LoadingOverlay :is-loading="isLoading" loading-text="Loading report">
|
|
<template v-if="!isLoading">
|
|
<component
|
|
:is="Component"
|
|
:district="district"
|
|
@doAddress="doAddress"
|
|
@doContact="doContact"
|
|
@doEvidence="doEvidence"
|
|
@doPermission="doPermission"
|
|
@doSubmit="doSubmit"
|
|
:isUploading="isUploading"
|
|
:publicID="report?.public_id ?? 'unset'"
|
|
v-model="report"
|
|
/>
|
|
</template>
|
|
</LoadingOverlay>
|
|
</router-view>
|
|
<!-- Reference Number -->
|
|
<div class="reference-number" v-if="report && report.public_id">
|
|
<small>
|
|
Reference number: <strong>{{ report.public_id }}</strong>
|
|
</small>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, onMounted, ref } from "vue";
|
|
import { computedAsync } from "@vueuse/core";
|
|
import { useRouter } from "vue-router";
|
|
|
|
import type { Image } from "@/components/ImageUpload.vue";
|
|
import { useRoutes } from "@/rmo/route/use";
|
|
import { useStoreDistrict } from "@/rmo/store/district";
|
|
import { useStoreLocal } from "@/store/local";
|
|
import { useStoreLocation } from "@/store/location";
|
|
import { useStorePublicReport } from "@/rmo/store/publicreport";
|
|
import Intro from "@/rmo/content/compliance/Intro.vue";
|
|
import LoadingOverlay from "@/components/LoadingOverlay.vue";
|
|
import {
|
|
type ComplianceUpdate,
|
|
type District,
|
|
PublicReport,
|
|
PublicReportCompliance,
|
|
PublicReportComplianceOptions,
|
|
} from "@/type/api";
|
|
import { Contact, Address, Location, PermissionType } from "@/type/api";
|
|
|
|
interface Props {
|
|
public_id: string;
|
|
}
|
|
|
|
const district = ref<District | undefined>(undefined);
|
|
const isLoading = ref<boolean>(true);
|
|
const isUploading = ref<boolean>(false);
|
|
const props = defineProps<Props>();
|
|
const report = ref<PublicReportCompliance | undefined>(undefined);
|
|
const router = useRouter();
|
|
const routes = useRoutes();
|
|
const storeDistrict = useStoreDistrict();
|
|
const storeLocal = useStoreLocal();
|
|
const storeLocation = useStoreLocation();
|
|
const storePublicReport = useStorePublicReport();
|
|
async function createReport(client_id: string, district_uri: string) {
|
|
let content = {
|
|
client_id: client_id,
|
|
district: district_uri,
|
|
location: {
|
|
accuracy: 0,
|
|
latitude: 0,
|
|
longitude: 0,
|
|
},
|
|
};
|
|
const resp = await fetch("/api/rmo/compliance", {
|
|
body: JSON.stringify(content),
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
method: "POST",
|
|
});
|
|
if (!resp.ok) {
|
|
const content = await resp.text();
|
|
console.error("Failed to create compliance report", resp.status, content);
|
|
return;
|
|
}
|
|
const body = await resp.json();
|
|
storeLocal.setExistingComplianceReportURI(body.uri);
|
|
report.value!.public_id = body.public_id;
|
|
report.value!.uri = body.uri;
|
|
}
|
|
function doAddress() {
|
|
if (!report.value) {
|
|
console.log("can't do address, null report");
|
|
return;
|
|
}
|
|
console.log("address done", report.value.address);
|
|
isUploading.value = true;
|
|
updateReport({
|
|
address: report.value.address,
|
|
}).finally(() => {
|
|
isUploading.value = false;
|
|
});
|
|
}
|
|
function doEvidence(images: Image[]) {
|
|
if (!report.value) {
|
|
console.log("can't do evidence, null report");
|
|
return;
|
|
}
|
|
(async () => {
|
|
isUploading.value = true;
|
|
let todo = [uploadImages(images)];
|
|
if (report.value && report.value.comments) {
|
|
todo.push(
|
|
updateReport({
|
|
comments: report.value.comments,
|
|
}),
|
|
);
|
|
}
|
|
await Promise.all(todo);
|
|
isUploading.value = false;
|
|
})();
|
|
}
|
|
function doContact() {
|
|
if (!report.value) {
|
|
console.log("can't do contact, null report");
|
|
return;
|
|
}
|
|
console.log(
|
|
"contact",
|
|
JSON.stringify(report.value.reporter),
|
|
report.value.reporter,
|
|
);
|
|
isUploading.value = true;
|
|
updateReport({
|
|
reporter: report.value.reporter,
|
|
}).finally(() => {
|
|
isUploading.value = false;
|
|
});
|
|
}
|
|
async function doMounted() {
|
|
const r = await storePublicReport.byID(props.public_id);
|
|
report.value = r as PublicReportCompliance;
|
|
const d = await storeDistrict.byURI(r.district);
|
|
district.value = d;
|
|
isLoading.value = false;
|
|
const pr = r as PublicReportCompliance;
|
|
if (pr.submitted) {
|
|
router.replace(routes.ComplianceComplete(r.public_id));
|
|
}
|
|
}
|
|
function doPermission() {
|
|
if (!report.value) {
|
|
console.log("can't do permission, null report");
|
|
return;
|
|
}
|
|
console.log("report.value.has_dog", report.value.has_dog);
|
|
isUploading.value = true;
|
|
updateReport({
|
|
access_instructions: report.value.access_instructions,
|
|
availability_notes: report.value.availability_notes,
|
|
gate_code: report.value.gate_code,
|
|
has_dog: report.value.has_dog,
|
|
permission_type: report.value.permission_type,
|
|
wants_scheduled: report.value.wants_scheduled,
|
|
}).finally(() => {
|
|
isUploading.value = false;
|
|
});
|
|
}
|
|
function doSubmit() {
|
|
console.log("submit", report.value);
|
|
storeLocal.delExistingComplianceReportURI();
|
|
updateReport({
|
|
submitted: new Date().toISOString(),
|
|
});
|
|
}
|
|
async function updateReport(updates: ComplianceUpdate) {
|
|
if (!(report.value && report.value.uri)) {
|
|
console.log("Refusing to update report without URI");
|
|
return;
|
|
}
|
|
storePublicReport.update(report.value.uri, updates);
|
|
}
|
|
async function updateLocation() {
|
|
if (!report.value) return;
|
|
const loc = await storeLocation.get();
|
|
report.value.location = loc.coords;
|
|
updateReport({
|
|
location: report.value.location,
|
|
});
|
|
}
|
|
async function uploadImages(images: Image[]) {
|
|
if (images.length == 0) return;
|
|
if (!report.value) return;
|
|
|
|
isUploading.value = true;
|
|
const formData = new FormData();
|
|
images.map(async (image, index) => {
|
|
formData.append(`image[${index}]`, image.file, image.name);
|
|
});
|
|
const url = `${report.value.uri}/image`;
|
|
const response = await fetch(url, {
|
|
body: formData,
|
|
method: "POST",
|
|
});
|
|
if (!response.ok) {
|
|
const content = await response.text();
|
|
console.error(
|
|
"Failed to POST images",
|
|
url,
|
|
response.status,
|
|
response.statusText,
|
|
content,
|
|
);
|
|
isUploading.value = false;
|
|
return;
|
|
}
|
|
isUploading.value = false;
|
|
// after everything is done update the report so that we see the correct number of images
|
|
// on the report summary
|
|
const r = await storePublicReport.fetchByURI(report.value.uri);
|
|
Object.assign(report.value, r);
|
|
}
|
|
onMounted(() => {
|
|
doMounted();
|
|
});
|
|
</script>
|