forked from Wroclaw/WorkshopTasker
Refactor entry editor and add some new types to it
This commit is contained in:
parent
0151a6c713
commit
b12e91ed13
2 changed files with 92 additions and 14 deletions
|
@ -1,15 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
|
||||
type optionalMap<Optional> = Optional extends true ? undefined : string | number;
|
||||
// type typeMap<Type extends string = {};
|
||||
import FormClient from "~/components/formClient.vue";
|
||||
|
||||
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,
|
||||
label?: string,
|
||||
type: "text" | "password" | "number",
|
||||
type: type,
|
||||
optional?: Optional,
|
||||
value?: optionalMap<Optional>,
|
||||
value?: optionalMap<Optional, typeMap[type]>,
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -22,7 +32,7 @@ const emit = defineEmits<{
|
|||
(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) {
|
||||
modelValue.value[i.key] = i.value;
|
||||
|
@ -39,12 +49,43 @@ emit("update:modelValue", modelValue.value);
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<VTextField
|
||||
v-for="i of fields"
|
||||
:key="i.key"
|
||||
:model-value="modelValue[i.key]"
|
||||
:label="i.label"
|
||||
:type="i.type"
|
||||
@update:model-value="v => updateModel(i.key, v)"
|
||||
/>
|
||||
<div v-for="i of fields" :key="i.key">
|
||||
<VTextField
|
||||
v-if="i.type == 'text'"
|
||||
:model-value="modelValue[i.key]"
|
||||
:label="i.label"
|
||||
type="text"
|
||||
@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>
|
||||
|
|
37
components/formClient.vue
Normal file
37
components/formClient.vue
Normal 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>
|
Loading…
Reference in a new issue