WorkshopTasker/pages/client/[id].vue

214 lines
6.2 KiB
Vue
Raw Normal View History

2023-05-11 06:03:22 +02:00
<script setup lang="ts">
2023-05-24 09:40:45 +02:00
/* global $fetch */
2023-05-11 06:03:22 +02:00
import { useRoute, useFetch, createError } from "nuxt/app";
import { ref, type Ref } from "vue";
2023-05-11 06:03:22 +02:00
2023-05-24 09:40:45 +02:00
import { VBtn, VForm } from "vuetify/components";
2023-05-11 06:03:22 +02:00
import PagedList from "~/components/pagedList.vue";
2023-05-24 09:40:45 +02:00
import Snowflake from "~/utils/snowflake";
import OrderView from "~/components/orderView.vue";
import EntryEditor, { type fieldDefinition } from "~/components/entryEditor.vue";
2023-05-11 06:03:22 +02:00
const route = useRoute();
const id = route.params.id;
const clientRequest = await useFetch(`/api/clients/${id}` as "/api/clients/:id");
2023-05-11 06:03:22 +02:00
if (clientRequest.error.value) throw createError(clientRequest.error.value?.data ?? "");
type Client = NonNullable<typeof clientRequest.data.value>;
const client = clientRequest.data as Ref<Client>;
2023-05-11 06:03:22 +02:00
const clientOrdersRequest = await useFetch(`/api/clients/${id}/orders` as "/api/clients/:id/orders");
2023-05-24 09:40:45 +02:00
if (clientOrdersRequest.error.value) throw createError(clientOrdersRequest.error.value?.data ?? "");
type OrderSummary = NonNullable<typeof clientOrdersRequest.data.value>;
const clientOrders = clientOrdersRequest.data as Ref<OrderSummary>;
2023-05-24 09:40:45 +02:00
type Order = Awaited<ReturnType<typeof useFetch<void, any, "/api/orders/:id", "get">>>["data"]["value"];
// cache
2023-05-24 09:40:45 +02:00
const orders = ref<Map<string, {
loading: boolean,
value?: Order
2023-05-24 09:40:45 +02:00
}>>(new Map());
for (const i of clientOrders.value)
orders.value.set(i.id, { loading: false });
async function loadOrder(id: string) {
const entry = orders.value.get(id);
if (!entry) throw createError(`excepted order entry for ${id}`);
entry.loading = true;
// @ts-expect-error
entry.value = await $fetch(`/api/orders/${id}` as "/api/order/:id", {
method: "GET",
}) as Order;
2023-05-24 09:40:45 +02:00
entry.loading = false;
}
let lastPagedListVModel: Array<string> = [];
function updatePagedListVModel(element: Array<string>) {
const justOpened = element.filter(e => !lastPagedListVModel.includes(e));
for (const i of justOpened) loadOrder(i);
lastPagedListVModel = element;
}
const editMode = ref<boolean>(route.query?.edit === "1");
function editorFields(): Array<fieldDefinition> {
return [
{ key: "name", type: "text", label: "Name", value: client.value.name ?? "" },
{ key: "address", type: "text", label: "Address", value: client.value.address ?? "" },
{ key: "phone", type: "text", label: "Phone", value: client.value.phone ?? "" },
{ key: "email", type: "text", label: "E-mail", value: client.value.email ?? "" },
2023-05-24 09:40:45 +02:00
];
}
const submitting = ref<boolean>(false);
// const updateForm = ref<VForm | null>(null);
const formButton = ref<VBtn | null>(null);
const formData = ref<any>({});
function normalizeForm() {
for (const i in formData.value)
formData.value[i] = formData.value[i] === "" ? null : formData.value[i];
}
async function handleSubmit() {
submitting.value = true;
normalizeForm();
try {
const result = await $fetch(
`/api/clients/${client.value.id}` as "/api/clients/:id", {
method: "PATCH",
body: formData.value,
},
);
client.value = result;
} catch (e) {
console.error(e);
submitting.value = false;
return;
}
submitting.value = false;
editMode.value = false;
}
function getCreationDate() {
const date = new Date(Number(new Snowflake(BigInt(client.value.id)).timestamp.toString())).toLocaleDateString();
return date;
}
2023-05-11 06:03:22 +02:00
</script>
<template>
2023-05-24 09:40:45 +02:00
<VDialog
v-model="editMode"
:persistent="submitting"
:activator="formButton as unknown as (Element | null) ?? undefined"
width="auto"
>
<VCard width="400px" :loading="submitting">
<VCardTitle>
Edit client
</VCardTitle>
<VForm
ref="updateForm"
:disabled="submitting"
class="px-4"
>
<EntryEditor
:fields="editorFields()"
@update-sub-model-value="(k, v) => { formData[k] = v; }"
/>
</VForm>
<VCardActions>
<VBtn
color="primary"
@click="handleSubmit"
>
Submit
</VBtn>
</VCardActions>
</VCard>
</VDialog>
2023-05-11 06:03:22 +02:00
<VRow>
<VCol cols="12">
<div
class="text-h4"
:class="client.name === null ? ['font-italic'] : []"
>
{{ client.name ?? "[none]" }}
</div>
</VCol>
</VRow>
<VRow>
<VCol md="4" cols="12">
2023-05-24 09:40:45 +02:00
<VCard class="mx-auto">
2023-05-11 06:03:22 +02:00
<VList>
<VListItem
v-if="client.address"
prepend-icon="mdi-map-marker"
>
<VListItemTitle class="text-wrap">
{{ client.address }}
</VListItemTitle>
</VListItem>
<VListItem
2023-05-24 09:40:45 +02:00
v-if="client.phone"
prepend-icon="mdi-phone"
2023-05-11 06:03:22 +02:00
>
<VListItemTitle class="text-wrap">
2023-05-24 09:40:45 +02:00
{{ client.phone }}
2023-05-11 06:03:22 +02:00
</VListItemTitle>
</VListItem>
<VListItem
2023-05-24 09:40:45 +02:00
v-if="client.email"
prepend-icon="mdi-email"
2023-05-11 06:03:22 +02:00
>
<VListItemTitle class="text-wrap">
2023-05-24 09:40:45 +02:00
{{ client.email }}
2023-05-11 06:03:22 +02:00
</VListItemTitle>
</VListItem>
</VList>
2023-05-24 09:40:45 +02:00
<template #actions>
<VBtn
ref="formButton"
>
edit
</VBtn>
</template>
2023-05-11 06:03:22 +02:00
</VCard>
2023-05-24 09:40:45 +02:00
<span class="font-italic text-caption">Created {{ getCreationDate() }}</span>
2023-05-11 06:03:22 +02:00
</VCol>
<VCol cols="12" md="8">
<PagedList
2023-05-24 09:40:45 +02:00
:records="clientOrders"
record-key="id"
record-value="id"
@update:model-value="updatePagedListVModel"
2023-05-11 06:03:22 +02:00
>
<template #title="i">
2023-05-24 09:40:45 +02:00
<VRow>
<VCol>{{ new Date(Number(new Snowflake(BigInt((i.record.id))).timestamp)).toLocaleDateString() }}</VCol>
<VCol>{{ i.record.value }} PLN</VCol>
2023-05-24 09:40:45 +02:00
<VCol>
{{ i.record.imported_products_count }}
2023-05-24 09:40:45 +02:00
products,
{{ i.record.work_count }}
2023-05-24 09:40:45 +02:00
works
</VCol>
</VRow>
</template>
<template #text="i">
<VProgressLinear
:height="orders.get(i.record.id)?.loading ?? true ? undefined : 0"
2023-05-24 09:40:45 +02:00
absolute
:progress="orders.get(i.record.id)?.loading ?? true"
:indeterminate="orders.get(i.record.id)?.loading ?? true"
2023-05-24 09:40:45 +02:00
/>
<OrderView :order="orders.get(i.record.id)?.value" />
2023-05-11 06:03:22 +02:00
</template>
</PagedList>
</VCol>
</VRow>
</template>