This commit is contained in:
parent
8b203908a0
commit
725945d95c
22 changed files with 381 additions and 135 deletions
|
|
@ -61,21 +61,21 @@
|
|||
</div>
|
||||
<div class="col-md-6">
|
||||
<label
|
||||
v-if="report.reporter.has_email"
|
||||
v-if="report.reporter.emails.length"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-envelope"></i>
|
||||
<a :href="'mailto:' + report.reporter.email">{{
|
||||
report.reporter.email
|
||||
<a :href="'mailto:' + report.reporter.emails[0]">{{
|
||||
report.reporter.emails[0]
|
||||
}}</a>
|
||||
</label>
|
||||
<label
|
||||
v-if="report.reporter.has_phone"
|
||||
v-if="report.reporter.phones.length"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-phone"></i>
|
||||
<a :href="'tel:+' + report.reporter.phone">{{
|
||||
report.reporter.phone
|
||||
<a :href="'tel:+' + report.reporter.phones[0]">{{
|
||||
report.reporter.phones[0]
|
||||
}}</a>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@
|
|||
<div
|
||||
v-if="
|
||||
!(
|
||||
selectedReport?.reporter.has_email ||
|
||||
selectedReport?.reporter.has_phone
|
||||
selectedReport?.reporter.emails.length ||
|
||||
selectedReport?.reporter.phones.length
|
||||
)
|
||||
"
|
||||
class="mb-3"
|
||||
|
|
@ -91,8 +91,8 @@
|
|||
</div>
|
||||
<div
|
||||
v-if="
|
||||
selectedReport?.reporter.has_email ||
|
||||
selectedReport?.reporter.has_phone
|
||||
selectedReport?.reporter.emails.length ||
|
||||
selectedReport?.reporter.phones.length
|
||||
"
|
||||
class="mb-3"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -87,13 +87,13 @@
|
|||
</div>
|
||||
<div class="col-md-6">
|
||||
<label
|
||||
v-if="report.owner.has_email"
|
||||
v-if="report.owner.emails.length"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-envelope"></i>
|
||||
</label>
|
||||
<label
|
||||
v-if="report.owner.has_phone"
|
||||
v-if="report.owner.phones.length"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-phone"></i>
|
||||
|
|
|
|||
|
|
@ -248,10 +248,8 @@ const hasCompleteResponse = computed(() => {
|
|||
r.images.length > 0 ||
|
||||
r.permission_type == PermissionType.GRANTED ||
|
||||
r.reporter.name ||
|
||||
r.reporter.phone ||
|
||||
r.reporter.has_phone ||
|
||||
r.reporter.email ||
|
||||
r.reporter.has_email
|
||||
r.reporter.phones.length ||
|
||||
r.reporter.emails.length
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
id="contact-phone"
|
||||
name="phone"
|
||||
placeholder="(555) 123-4567"
|
||||
v-model="modelValue.reporter.phone"
|
||||
v-model="modelValue.reporter.phone.number"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
<div
|
||||
class="alert alert-primary"
|
||||
role="alert"
|
||||
v-if="modelValue.reporter.has_email"
|
||||
v-if="modelValue.reporter.email != ''"
|
||||
>
|
||||
You've already added an email address to this report. If you alter the
|
||||
email below, it will replace the current email address.
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@
|
|||
<div
|
||||
class="summary-value"
|
||||
v-if="
|
||||
modelValue.reporter?.phone || modelValue.reporter?.has_phone
|
||||
modelValue.reporter?.phone || modelValue.reporter?.phone != ''
|
||||
"
|
||||
>
|
||||
{{ modelValue.reporter.phone }}
|
||||
|
|
@ -216,7 +216,7 @@
|
|||
<div
|
||||
class="summary-value"
|
||||
v-if="
|
||||
modelValue.reporter?.email || modelValue.reporter?.has_email
|
||||
modelValue.reporter?.email || modelValue.reporter?.email != ''
|
||||
"
|
||||
>
|
||||
{{ modelValue.reporter?.email }}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { shallowRef } from "vue";
|
||||
import { ref, shallowRef } from "vue";
|
||||
|
||||
import { SSEManager, SSEMessageResource } from "@/SSEManager";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
|
|
@ -8,6 +8,8 @@ import { apiClient } from "@/client";
|
|||
import {
|
||||
Communication,
|
||||
type CommunicationDTO,
|
||||
Contact,
|
||||
type ContactDTO,
|
||||
PublicReport,
|
||||
type PublicReportDTO,
|
||||
} from "@/type/api";
|
||||
|
|
@ -22,6 +24,7 @@ function createResourceStore<dto, full extends uriHaver>(
|
|||
from_json: jsonConverter<dto, full>,
|
||||
) {
|
||||
const _resourceByURI = shallowRef<Map<string, full>>(new Map());
|
||||
const _resourceFetchAll = ref<Promise<full[]> | null>(null);
|
||||
const _resourceFetchByURI = shallowRef<Map<string, Promise<full> | null>>(
|
||||
new Map(),
|
||||
);
|
||||
|
|
@ -33,20 +36,25 @@ function createResourceStore<dto, full extends uriHaver>(
|
|||
}
|
||||
});
|
||||
|
||||
async function byAll(): Promise<full[]> {
|
||||
const cur = _resourceFetchAll.value;
|
||||
if (cur) {
|
||||
return cur;
|
||||
}
|
||||
return fetchAll();
|
||||
}
|
||||
async function byID(id: string): Promise<full> {
|
||||
const uri = uriFromID(id);
|
||||
const cur = _resourceFetchByURI.value.get(uri);
|
||||
if (cur) {
|
||||
return cur;
|
||||
}
|
||||
return fetchByID(id);
|
||||
return byURI(uri);
|
||||
}
|
||||
async function byURI(uri: string): Promise<full> {
|
||||
const cur = _resourceFetchByURI.value.get(uri);
|
||||
let cur = _resourceFetchByURI.value.get(uri);
|
||||
if (cur) {
|
||||
return cur;
|
||||
}
|
||||
return fetchByURI(uri);
|
||||
cur = fetchByURI(uri);
|
||||
_resourceFetchByURI.value.set(uri, cur);
|
||||
return cur;
|
||||
}
|
||||
async function fetchAll(): Promise<full[]> {
|
||||
const sessionStore = useSessionStore();
|
||||
|
|
@ -88,9 +96,12 @@ function createResourceStore<dto, full extends uriHaver>(
|
|||
return `${api_base}/${id}`;
|
||||
}
|
||||
return {
|
||||
byAll,
|
||||
byID,
|
||||
byURI,
|
||||
fetchAll,
|
||||
fetchByID,
|
||||
fetchByURI,
|
||||
loadingURI,
|
||||
};
|
||||
}
|
||||
|
|
@ -101,6 +112,11 @@ export const useStoreResource = defineStore("resource", () => {
|
|||
"/communication",
|
||||
Communication.fromJSON,
|
||||
),
|
||||
contact: createResourceStore<ContactDTO, Contact>(
|
||||
"sync:contact",
|
||||
"/contact",
|
||||
Contact.fromJSON,
|
||||
),
|
||||
publicreport: createResourceStore<PublicReportDTO, PublicReport>(
|
||||
"sync:publicreport",
|
||||
"/publicreport",
|
||||
|
|
|
|||
|
|
@ -77,28 +77,47 @@ export class Bounds {
|
|||
}
|
||||
}
|
||||
export interface ContactOptions {
|
||||
can_sms: boolean;
|
||||
email?: string;
|
||||
has_email: boolean;
|
||||
has_phone: boolean;
|
||||
emails?: string[];
|
||||
name?: string;
|
||||
phone?: string;
|
||||
phones?: Phone[];
|
||||
uri?: string;
|
||||
}
|
||||
export interface Phone {
|
||||
can_sms: boolean;
|
||||
e164: string;
|
||||
}
|
||||
export interface PhoneReporter {
|
||||
can_sms: boolean;
|
||||
number: string;
|
||||
}
|
||||
export class Contact {
|
||||
can_sms: boolean;
|
||||
email: string;
|
||||
has_email: boolean;
|
||||
has_phone: boolean;
|
||||
emails: string[];
|
||||
name: string;
|
||||
phone: string;
|
||||
phones: Phone[];
|
||||
uri: string;
|
||||
constructor(options?: ContactOptions) {
|
||||
this.can_sms = options?.can_sms ?? false;
|
||||
this.email = options?.email ?? "";
|
||||
this.has_email = options?.has_email ?? false;
|
||||
this.has_phone = options?.has_phone ?? false;
|
||||
this.emails = options?.emails ?? [];
|
||||
this.name = options?.name ?? "";
|
||||
this.phone = options?.phone ?? "";
|
||||
this.phones = options?.phones ?? [];
|
||||
this.uri = options?.uri ?? "";
|
||||
}
|
||||
static fromJSON(json: ContactDTO): Contact {
|
||||
return new Contact(json);
|
||||
}
|
||||
}
|
||||
export interface ContactDTO {
|
||||
name: string;
|
||||
emails: string[];
|
||||
phones: Phone[];
|
||||
uri: string;
|
||||
}
|
||||
export class ContactReporter {
|
||||
constructor(
|
||||
public name: string,
|
||||
public email: string,
|
||||
public phone: Phone,
|
||||
public uri: string,
|
||||
) {}
|
||||
}
|
||||
export interface District {
|
||||
name: string;
|
||||
|
|
@ -195,7 +214,7 @@ export interface ComplianceUpdate {
|
|||
//images?: Image[];
|
||||
location?: Location;
|
||||
permission_type?: string;
|
||||
reporter?: Contact;
|
||||
reporter?: ContactReporter;
|
||||
submitted?: string;
|
||||
//uri: string;
|
||||
wants_scheduled?: boolean;
|
||||
|
|
@ -212,7 +231,7 @@ export interface PublicReportDTO {
|
|||
location: Location;
|
||||
log: LogEntryDTO[];
|
||||
public_id: string;
|
||||
reporter: Contact;
|
||||
reporter: ContactReporter;
|
||||
status: string;
|
||||
type: string;
|
||||
uri: string;
|
||||
|
|
@ -224,7 +243,7 @@ export interface PublicReportUpdate {
|
|||
images?: Image[];
|
||||
location?: Location;
|
||||
public_id?: string;
|
||||
reporter?: Contact;
|
||||
reporter?: ContactReporter;
|
||||
status?: string;
|
||||
type?: string;
|
||||
uri?: string;
|
||||
|
|
@ -242,7 +261,7 @@ export interface PublicReportOptions {
|
|||
location: Location;
|
||||
log: LogEntry[];
|
||||
public_id: string;
|
||||
reporter: Contact;
|
||||
reporter: ContactReporter;
|
||||
status: string;
|
||||
type: string;
|
||||
uri: string;
|
||||
|
|
@ -254,7 +273,7 @@ export class PublicReport {
|
|||
images: Image[];
|
||||
log: LogEntry[];
|
||||
public_id: string;
|
||||
reporter: Contact;
|
||||
reporter: ContactReporter;
|
||||
status: string;
|
||||
type: string;
|
||||
uri: string;
|
||||
|
|
@ -266,7 +285,7 @@ export class PublicReport {
|
|||
this.images = options?.images ?? [];
|
||||
this.log = options?.log ?? [];
|
||||
this.public_id = options?.public_id ?? "";
|
||||
this.reporter = options?.reporter ?? new Contact();
|
||||
this.reporter = options?.reporter ?? new ContactReporter();
|
||||
this.status = options?.status ?? "";
|
||||
this.type = options?.type ?? "";
|
||||
this.uri = options?.uri ?? "";
|
||||
|
|
|
|||
|
|
@ -12,8 +12,16 @@
|
|||
</ThreeColumn>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computedAsync } from "@vueuse/core";
|
||||
|
||||
import ThreeColumn from "@/components/layout/ThreeColumn.vue";
|
||||
import ReviewContactColumnAction from "@/components/ReviewContactColumnAction.vue";
|
||||
import ReviewContactColumnDetail from "@/components/ReviewContactColumnDetail.vue";
|
||||
import ReviewContactColumnList from "@/components/ReviewContactColumnList.vue";
|
||||
import { useStoreResource } from "@/store/resource";
|
||||
|
||||
const storeResource = useStoreResource();
|
||||
const contacts = computedAsync(() => {
|
||||
return storeResource.contact.byAll();
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue