update cuz presentation

This commit is contained in:
Wroclaw 2023-05-24 09:40:45 +02:00
parent 7a9e451739
commit 4e67cc4e19
29 changed files with 1065 additions and 88 deletions

View file

@ -1,9 +1,14 @@
<script setup lang="ts">
/* global $fetch */
import { useRoute, useFetch, createError } from "nuxt/app";
import { Ref } from "vue";
import { ref, Ref } from "vue";
import { VBtn, VForm } from "vuetify/components";
import PagedList from "~/components/pagedList.vue";
import { client as clientType } from "~/utils/types/database";
import Snowflake from "~/utils/snowflake";
import { client as clientType, order, orderSummary } from "~/utils/types/database";
import OrderView from "~/components/orderView.vue";
import EntryEditor, { fieldDefinition } from "~/components/entryEditor.vue";
const route = useRoute();
const id = route.params.id;
@ -11,11 +16,116 @@ const id = route.params.id;
const clientRequest = await useFetch(`/api/clients/${id}`);
if (clientRequest.error.value) throw createError(clientRequest.error.value?.data ?? "");
const client = clientRequest.data as Ref<clientType>;
console.log(client);
const clientOrdersRequest = await useFetch(`/api/clients/${id}/orders`);
if (clientOrdersRequest.error.value) throw createError(clientOrdersRequest.error.value?.data ?? "");
const clientOrders = clientOrdersRequest.data as Ref<Array<orderSummary>>;
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",
});
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 ?? undefined },
{ key: "address", type: "text", label: "Address", value: client.value.address ?? undefined },
{ key: "phone", type: "text", label: "Phone", value: client.value.phone ?? undefined },
{ key: "email", type: "text", label: "E-mail", value: client.value.email ?? undefined },
];
}
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
@ -28,7 +138,7 @@ console.log(client);
</VRow>
<VRow>
<VCol md="4" cols="12">
<VCard>
<VCard class="mx-auto">
<VList>
<VListItem
v-if="client.address"
@ -38,14 +148,6 @@ console.log(client);
{{ client.address }}
</VListItemTitle>
</VListItem>
<VListItem
v-if="client.email"
prepend-icon="mdi-email"
>
<VListItemTitle class="text-wrap">
{{ client.email }}
</VListItemTitle>
</VListItem>
<VListItem
v-if="client.phone"
prepend-icon="mdi-phone"
@ -54,19 +156,52 @@ console.log(client);
{{ 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="[{a: 'owo'}, {a: 'uwu'}, {a: 'qwq'}]"
record-key="a"
:records="clientOrders"
record-key="id"
record-value="id"
@update:model-value="updatePagedListVModel"
>
<template #text="i">
{{ i }}
</template>
<template #title="i">
{{ i }}
<VRow>
<VCol>{{ new Date(Number(new Snowflake(BigInt(((i.record) as orderSummary).id)).timestamp)).toLocaleDateString() }}</VCol>
<VCol>{{ ((i.record) as orderSummary).value }} PLN</VCol>
<VCol>
{{ ((i.record) as orderSummary).imported_products_count }}
products,
{{ ((i.record) as orderSummary).work_count }}
works
</VCol>
</VRow>
</template>
<template #text="i">
<VProgressLinear
:height="orders.get((i.record as orderSummary).id)?.loading ?? true ? undefined : 0"
absolute
:progress="orders.get((i.record as orderSummary).id)?.loading ?? true"
:indeterminate="orders.get((i.record as orderSummary).id)?.loading ?? true"
/>
<OrderView :order="(orders.get((i.record as orderSummary).id)?.value as order | undefined)" />
</template>
</PagedList>
</VCol>

View file

@ -1,12 +1,19 @@
<script setup lang="ts">
/* global $fetch */
import { useFetch, createError } from "nuxt/app";
import { ref, Ref } from "vue";
import { useFetch, createError, navigateTo, NuxtError, useRoute } from "nuxt/app";
import { ref, Ref, reactive } from "vue";
import { VBtn } from "vuetify/components";
import { definePageMeta } from "~/.nuxt/imports";
import { client as clientType } from "~/utils/types/database";
import pagedTable from "~/components/pagedTable.vue";
import Alerts, { AlertData } from "~/components/alerts.vue";
import { fieldDefinition } from "~/components/entryEditor.vue";
definePageMeta({ middleware: ["auth"] });
const route = useRoute();
const alerts = ref<Array<AlertData>>([]);
const clientsRequest = await useFetch("/api/clients");
if (clientsRequest.error.value) throw createError(clientsRequest.error.value?.data ?? "");
@ -16,8 +23,11 @@ const countRequest = await useFetch("/api/clients/count");
if (countRequest.error.value) throw createError(countRequest.error.value?.data ?? "");
const count = countRequest.data as Ref<NonNullable<typeof countRequest.data.value>>;
function rowClicked(client: string, edit = false) {
console.log(client);
async function rowClicked(client: string, edit = false) {
await navigateTo({
path: `/client/${client}`,
query: { edit: edit ? 1 : undefined },
});
}
async function rowDelete(client: string) {
@ -28,7 +38,7 @@ async function rowDelete(client: string) {
clients.value = clients.value.filter(e => e.id !== client);
count.value.count--;
} catch (e) {
// FIXME: show the error
alerts.value.push({ text: (e as NuxtError).message, type: "error" });
console.log(e);
}
}
@ -37,28 +47,98 @@ const loadingMore = ref<boolean>(false);
async function loadBefore() {
loadingMore.value = true;
clients.value.push(...await $fetch("/api/clients", {
query: {
before: clients.value[clients.value.length - 1].id,
},
}));
try {
clients.value.push(...await $fetch("/api/clients", {
query: {
before: clients.value[clients.value.length - 1].id,
},
}));
} catch (e) {
alerts.value.push({ text: (e as NuxtError).message });
console.error(e);
}
loadingMore.value = false;
}
const createMode = ref<boolean>(route.query?.create === "1");
function editorFields(): Array<fieldDefinition> {
return [
{ key: "name", type: "text", label: "Name" },
{ key: "address", type: "text", label: "Address" },
{ key: "phone", type: "text", label: "Phone" },
{ key: "email", type: "text", label: "E-mail" },
];
}
const submitting = ref<boolean>(false);
// const updateForm = ref<VForm | null>(null);
const formButton = ref<VBtn | null>(null);
const formData = ref<any>({
name: null,
address: null,
phone: null,
email: null,
});
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/", {
method: "POST",
body: formData.value,
},
);
} catch (e) {
console.error(e);
submitting.value = false;
return;
}
submitting.value = false;
createMode.value = false;
}
</script>
<template>
<VOverlay
model-value
origin="top center"
:scrim="false"
height="fit-content"
persistent
no-click-animation
<Alerts :alerts="alerts" />
<VDialog
v-model="createMode"
:persistent="submitting"
:activator="formButton as unknown as (Element | null) ?? undefined"
width="auto"
>
<VAlert class="alert">
owowowowowowowowo
</VAlert>
</VOverlay>
<VCard width="400px" :loading="submitting">
<VCardTitle>
Create 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>
<VBreadcrumbs :items="['Clients']" />
@ -66,6 +146,11 @@ async function loadBefore() {
<div class="text-h4">
There are {{ count?.count }} clients in the database.
</div>
<VBtn
ref="formButton"
>
Create
</VBtn>
</VCol>
</VRow>
<VRow>

View file

@ -3,7 +3,8 @@ import Test from '~/components/test.vue';
</script>
<template>
<h1>Hi mom!</h1><br>
<h1>Hi mom!</h1>
<br>
<Test />
<Test />
<Test />

View file

@ -124,6 +124,13 @@ updateUserInfo();
>
Logout
</VBtn>
<VBtn
v-if="loggedIn"
color="primary"
@click="navigateTo('/clients')"
>
go to clients
</VBtn>
</template>
</VCard>
</template>