Refactor entry editor and add some new types to it

This commit is contained in:
Wroclaw 2023-12-18 23:14:15 +01:00
parent 0151a6c713
commit b12e91ed13
2 changed files with 92 additions and 14 deletions

View file

@ -1,15 +1,25 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
type optionalMap<Optional> = Optional extends true ? undefined : string | number; import FormClient from "~/components/formClient.vue";
// type typeMap<Type extends string = {};
export type fieldDefinition<Optional extends boolean = boolean> = { type optionalMap<Optional, type> = Optional extends true ? undefined | type : type;
type typeMap = {
"text": string,
"password": string,
"number": number,
"boolean": boolean,
"none": undefined,
"client": `${bigint}`
};
export type fieldDefinition<Optional extends boolean = boolean, type extends keyof typeMap = keyof typeMap> = {
key: string, key: string,
label?: string, label?: string,
type: "text" | "password" | "number", type: type,
optional?: Optional, optional?: Optional,
value?: optionalMap<Optional>, value?: optionalMap<Optional, typeMap[type]>,
} }
const props = defineProps<{ const props = defineProps<{
@ -22,7 +32,7 @@ const emit = defineEmits<{
(e: "updateSubModelValue", key: fieldDefinition["key"], value: fieldDefinition["value"]): void, (e: "updateSubModelValue", key: fieldDefinition["key"], value: fieldDefinition["value"]): void,
}>(); }>();
const modelValue = ref<{[key: string]: string | number | undefined}>({}); const modelValue = ref<{[key: string]: string | number | boolean | undefined}>({});
for (const i of props.fields) { for (const i of props.fields) {
modelValue.value[i.key] = i.value; modelValue.value[i.key] = i.value;
@ -39,12 +49,43 @@ emit("update:modelValue", modelValue.value);
</script> </script>
<template> <template>
<VTextField <div v-for="i of fields" :key="i.key">
v-for="i of fields" <VTextField
:key="i.key" v-if="i.type == 'text'"
:model-value="modelValue[i.key]" :model-value="modelValue[i.key]"
:label="i.label" :label="i.label"
:type="i.type" type="text"
@update:model-value="v => updateModel(i.key, v)" @update:model-value="v => updateModel(i.key, v)"
/> />
<VTextField
v-if="i.type == 'password'"
:model-value="modelValue[i.key]"
:label="i.label"
type="password"
@update:model-value="v => updateModel(i.key, v)"
/>
<VTextField
v-if="i.type == 'number'"
:model-value="modelValue[i.key]"
:label="i.label"
type="number"
@update:model-value="v => updateModel(i.key, Number(v))"
/>
<v-checkbox
v-if="i.type == 'boolean'"
:label="i.label"
:model-value="modelValue[i.key]"
@update:model-value="v => updateModel(i.key, Boolean(v))"
/>
<p v-if="i.type == 'none'">
{{ i.label }}
</p>
<FormClient
v-if="i.type == 'client'"
:model-value="modelValue[i.key] as `${bigint}`"
:label="i.label"
:optional="i.optional"
@update:model-value="v => updateModel(i.key, v)"
/>
</div>
</template> </template>

37
components/formClient.vue Normal file
View file

@ -0,0 +1,37 @@
<script setup lang="ts">
import { useFetch, createError } from '#app';
const props = defineProps<{
label?: string,
optional?: boolean,
modelValue?: `${bigint}`,
}>();
// eslint-disable-next-line func-call-spacing
const emit = defineEmits<{
(e: "update:modelValue", value: `${bigint}`): void,
}>();
// FIXME: allow to search all clients instead of newest 50 (needs api call)
const clientsRequest = await useFetch("/api/clients");
if (clientsRequest.error.value) throw createError(clientsRequest.error.value?.data ?? "");
const clients = clientsRequest.data.value?.map((e) => {
return {
value: e.id,
title: e.name ?? `[null] (${e.id})`,
props: {
subtitle: e.address,
},
};
}) ?? [];
</script>
<template>
<v-autocomplete
:label="label ?? 'Client'"
:model-value="modelValue"
:items="clients"
:clearable="optional"
@update:model-value="v => emit('update:modelValue', v)"
/>
</template>