Wroclaw
500a9ad595
All checks were successful
Build dev / build (push) Successful in 52s
This fixes an issue when user does not click the form field. it is not being defined, meaning the field will not be updated.
213 lines
6.2 KiB
Vue
213 lines
6.2 KiB
Vue
<script setup lang="ts">
|
|
/* global $fetch */
|
|
import { useRoute, useFetch, createError } from "nuxt/app";
|
|
import { ref, type Ref } from "vue";
|
|
|
|
import { VBtn, VForm } from "vuetify/components";
|
|
import PagedList from "~/components/pagedList.vue";
|
|
import Snowflake from "~/utils/snowflake";
|
|
import OrderView from "~/components/orderView.vue";
|
|
import EntryEditor, { type fieldDefinition } from "~/components/entryEditor.vue";
|
|
|
|
const route = useRoute();
|
|
const id = route.params.id;
|
|
|
|
const clientRequest = await useFetch(`/api/clients/${id}` as "/api/clients/:id");
|
|
if (clientRequest.error.value) throw createError(clientRequest.error.value?.data ?? "");
|
|
type Client = NonNullable<typeof clientRequest.data.value>;
|
|
const client = clientRequest.data as Ref<Client>;
|
|
|
|
const clientOrdersRequest = await useFetch(`/api/clients/${id}/orders` as "/api/clients/:id/orders");
|
|
if (clientOrdersRequest.error.value) throw createError(clientOrdersRequest.error.value?.data ?? "");
|
|
type OrderSummary = NonNullable<typeof clientOrdersRequest.data.value>;
|
|
const clientOrders = clientOrdersRequest.data as Ref<OrderSummary>;
|
|
|
|
type Order = Awaited<ReturnType<typeof useFetch<void, any, "/api/orders/:id", "get">>>["data"]["value"];
|
|
|
|
// cache
|
|
const orders = ref<Map<string, {
|
|
loading: boolean,
|
|
value?: Order
|
|
}>>(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;
|
|
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 ?? "" },
|
|
];
|
|
}
|
|
|
|
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;
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<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>
|
|
<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">
|
|
<VCard class="mx-auto">
|
|
<VList>
|
|
<VListItem
|
|
v-if="client.address"
|
|
prepend-icon="mdi-map-marker"
|
|
>
|
|
<VListItemTitle class="text-wrap">
|
|
{{ client.address }}
|
|
</VListItemTitle>
|
|
</VListItem>
|
|
<VListItem
|
|
v-if="client.phone"
|
|
prepend-icon="mdi-phone"
|
|
>
|
|
<VListItemTitle class="text-wrap">
|
|
{{ client.phone }}
|
|
</VListItemTitle>
|
|
</VListItem>
|
|
<VListItem
|
|
v-if="client.email"
|
|
prepend-icon="mdi-email"
|
|
>
|
|
<VListItemTitle class="text-wrap">
|
|
{{ client.email }}
|
|
</VListItemTitle>
|
|
</VListItem>
|
|
</VList>
|
|
<template #actions>
|
|
<VBtn
|
|
ref="formButton"
|
|
>
|
|
edit
|
|
</VBtn>
|
|
</template>
|
|
</VCard>
|
|
<span class="font-italic text-caption">Created {{ getCreationDate() }}</span>
|
|
</VCol>
|
|
<VCol cols="12" md="8">
|
|
<PagedList
|
|
:records="clientOrders"
|
|
record-key="id"
|
|
record-value="id"
|
|
@update:model-value="updatePagedListVModel"
|
|
>
|
|
<template #title="i">
|
|
<VRow>
|
|
<VCol>{{ new Date(Number(new Snowflake(BigInt((i.record.id))).timestamp)).toLocaleDateString() }}</VCol>
|
|
<VCol>{{ i.record.value }} PLN</VCol>
|
|
<VCol>
|
|
{{ i.record.imported_products_count }}
|
|
products,
|
|
{{ i.record.work_count }}
|
|
works
|
|
</VCol>
|
|
</VRow>
|
|
</template>
|
|
<template #text="i">
|
|
<VProgressLinear
|
|
:height="orders.get(i.record.id)?.loading ?? true ? undefined : 0"
|
|
absolute
|
|
:progress="orders.get(i.record.id)?.loading ?? true"
|
|
:indeterminate="orders.get(i.record.id)?.loading ?? true"
|
|
/>
|
|
<OrderView :order="orders.get(i.record.id)?.value" />
|
|
</template>
|
|
</PagedList>
|
|
</VCol>
|
|
</VRow>
|
|
</template>
|