187 lines
4.7 KiB
Vue
187 lines
4.7 KiB
Vue
|
<script setup lang="ts">
|
||
|
/* global $fetch */
|
||
|
import { ref, type Ref } from "vue";
|
||
|
import { VBtn } from "vuetify/components";
|
||
|
import type { NuxtError } from "#app";
|
||
|
|
||
|
import Alerts, { type AlertData } from "~/components/alerts.vue";
|
||
|
import { type fieldDefinition } from "~/components/entryEditor.vue";
|
||
|
|
||
|
import { definePageMeta, useFetch, createError, useRoute, navigateTo } from "#imports";
|
||
|
|
||
|
definePageMeta({ middleware: ["auth"] });
|
||
|
const route = useRoute();
|
||
|
|
||
|
const alerts = ref<Array<AlertData>>([]);
|
||
|
|
||
|
const ordersRequest = await useFetch("/api/orders");
|
||
|
if (ordersRequest.error.value) throw createError(ordersRequest.error.value?.data ?? "");
|
||
|
const orders = ordersRequest.data as Ref<NonNullable<typeof ordersRequest.data.value>>;
|
||
|
|
||
|
const countRequest = await useFetch("/api/orders/count");
|
||
|
if (countRequest.error.value) throw createError(countRequest.error.value?.data ?? "");
|
||
|
const count = countRequest.data as Ref<NonNullable<typeof countRequest.data.value>>;
|
||
|
|
||
|
const createMode = ref<boolean>(route.query?.create === "1");
|
||
|
|
||
|
async function rowClicked(client: string, edit = false) {
|
||
|
await navigateTo({
|
||
|
path: `/order/${client}`,
|
||
|
query: { edit: edit ? 1 : undefined },
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async function rowDelete(client: string) {
|
||
|
try {
|
||
|
await $fetch(`/api/orders/${client}` as "api/orders/:id", {
|
||
|
method: "DELETE",
|
||
|
});
|
||
|
orders.value = orders.value.filter(e => e.id !== client);
|
||
|
count.value.count--;
|
||
|
} catch (e) {
|
||
|
alerts.value.push({ text: (e as NuxtError).message, type: "error" });
|
||
|
console.log(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const loadingMore = ref<boolean>(false);
|
||
|
async function loadBefore() {
|
||
|
loadingMore.value = true;
|
||
|
|
||
|
try {
|
||
|
orders.value.push(...await $fetch("/api/orders", {
|
||
|
query: {
|
||
|
before: orders.value[orders.value.length - 1].id,
|
||
|
},
|
||
|
}));
|
||
|
} catch (e) {
|
||
|
alerts.value.push({ text: (e as NuxtError).message });
|
||
|
console.error(e);
|
||
|
}
|
||
|
loadingMore.value = false;
|
||
|
}
|
||
|
|
||
|
function editorFields(): fieldDefinition[] {
|
||
|
return [
|
||
|
{ key: "clientId", type: "client", label: "Client" },
|
||
|
{ key: "draft", type: "boolean", label: "Draft", value: true },
|
||
|
{ key: "imported_products", type: "none", label: "imported_produts - TBA" },
|
||
|
{ key: "work", type: "none", label: "work - TBA" },
|
||
|
];
|
||
|
}
|
||
|
|
||
|
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];
|
||
|
formData.value.imported_products = [];
|
||
|
formData.value.work = [];
|
||
|
}
|
||
|
|
||
|
async function handleSubmit() {
|
||
|
submitting.value = true;
|
||
|
normalizeForm();
|
||
|
try {
|
||
|
const result = await $fetch(
|
||
|
"/api/orders", {
|
||
|
method: "POST",
|
||
|
body: formData.value,
|
||
|
},
|
||
|
);
|
||
|
} catch (e) {
|
||
|
console.error(e);
|
||
|
submitting.value = false;
|
||
|
return;
|
||
|
}
|
||
|
submitting.value = false;
|
||
|
createMode.value = false;
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<template>
|
||
|
<Alerts :alerts="alerts" />
|
||
|
<VDialog
|
||
|
v-model="createMode"
|
||
|
:persistent="submitting"
|
||
|
:activator="formButton as unknown as (Element | null) ?? undefined"
|
||
|
width="auto"
|
||
|
>
|
||
|
<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="['Orders']" />
|
||
|
<VSpacer />
|
||
|
<div class="text-h4">
|
||
|
There are {{ count?.count }} orders in the database.
|
||
|
</div>
|
||
|
<VBtn
|
||
|
ref="formButton"
|
||
|
>
|
||
|
Create
|
||
|
</VBtn>
|
||
|
</VCol>
|
||
|
</VRow>
|
||
|
<VRow>
|
||
|
<VCol cols="12">
|
||
|
<VCard>
|
||
|
<VTable>
|
||
|
<thead>
|
||
|
<tr>
|
||
|
<th>Client</th>
|
||
|
<th>Draft</th>
|
||
|
<th />
|
||
|
</tr>
|
||
|
</thead>
|
||
|
<pagedTable
|
||
|
buttons
|
||
|
:records="orders"
|
||
|
:fields="['client', 'Draft']"
|
||
|
record-key="id"
|
||
|
@click="(id) => rowClicked(id, false)"
|
||
|
@click:edit="(id) => rowClicked(id, true)"
|
||
|
@click:delete="(id) => rowDelete(id)"
|
||
|
/>
|
||
|
</VTable>
|
||
|
</VCard>
|
||
|
<VCol>
|
||
|
<VBtn
|
||
|
v-if="orders.length < count.count"
|
||
|
color="primary"
|
||
|
:loading="loadingMore"
|
||
|
@click="loadBefore"
|
||
|
>
|
||
|
Load more
|
||
|
</VBtn>
|
||
|
</VCol>
|
||
|
</VCol>
|
||
|
</VRow>
|
||
|
</template>
|