feat: preloading, error handing

This commit is contained in:
opbnq-q
2025-03-09 04:25:25 -07:00
parent 9e49d16a43
commit f648b4b171
10 changed files with 112 additions and 76 deletions

View File

@@ -7,16 +7,20 @@ import { manyStructsView } from '../utils/structs/structs-view.util';
import { type UnwrapRef } from 'vue';
import { toDate, toTimestamp } from '../utils/date/converters.util';
import MultiSelect from '../components/selects/MultiSelect.vue';
import { alertWindow } from '../utils/js/alert.utils';
import type { Validate } from '../types/validate.type';
const showCreate = defineModel<boolean>('show')
const createItem = defineModel<T>('item')
const items = defineModel<UnwrapRef<T[]>>('items')
const props = defineProps<{
scheme: Scheme<T>,
getDefaults: () => Partial<T>,
service: IService<T>,
updateMode?: boolean
validate: Validate<T>
items: T[]
load(): Promise<T[]>
}>()
type Key = keyof T
@@ -27,63 +31,74 @@ const emits = defineEmits<{
(e: 'onSaveUpdate', data: T): void
(e: 'onSaveCreate', data: T): void
}>()
async function handleSave() {
const mode = props.updateMode ? 'update' : 'create';
const result = props.validate(createItem.value as T, mode);
if (result.status === 'error') {
alertWindow(result.message);
return;
}
try {
if (props.updateMode) {
await props.service.update.call(props.service, createItem.value as T);
await emits('onSaveUpdate', createItem.value as T);
await emits('onSave', createItem.value as T);
} else {
await props.service.create.call(props.service, createItem.value as T);
await emits('onSaveCreate', createItem.value as T);
await emits('onSave', createItem.value as T);
}
} catch (e) {
alertWindow(e.message);
return
}
props.load()
showCreate.value = false;
}
</script>
<template>
<Dialog v-model:visible="showCreate">
<div class="flex flex-col justify-center gap-5">
<div class="flex flex-col justify-start gap-5 min-h-[40vh]">
<div v-for="key in keys" v-show="!props.scheme[key].hidden && !props.scheme[key].readonly"
class="flex items-center gap-5">
<h1 class="w-[200px]">{{ props.scheme[key].russian }}</h1>
<div>
<div v-if="props.scheme[key]?.customWindow?.[props.updateMode ? 'update' : 'create']">
<slot :name="<string>key + (props.updateMode ? 'Update' : 'Create')"></slot>
</div>
<div v-else-if="props.scheme[key]?.customWindow?.common">
<slot :name="<string>key"></slot>
</div>
<InputNumber class="w-[300px]" v-model:model-value="<number>createItem![key]"
v-else-if="props.scheme[key]?.type?.primitive === 'number'" />
<InputText class="w-[300px]" v-model:model-value="<string>createItem![key]"
v-else-if="props.scheme[key].type?.primitive === 'string'" />
<DatePicker class="w-[300px]" :default-value="toDate(createItem![key] as number)" @value-change="v => {
createItem![key] = toTimestamp(v as Date) as any
}" show-time
v-else-if="props.scheme[key].type?.primitive === 'date'" />
<Textarea class="w-[300px]" v-model="<string>createItem![key]"
v-else-if="props.scheme[key].type?.primitive === 'multiple'" />
<ToggleSwitch class="w-[300px]" v-model:model-value="<boolean>createItem![key]"
v-else-if="props.scheme[key].type?.primitive === 'boolean'" />
<Select v-else-if="props.scheme[key].type?.nested?.values && !props.scheme[key]?.many"
v-model:model-value="createItem![key]" :options="props.scheme[key].type.nested.values"
:placeholder="`Выберите ${props.scheme[key].russian}`" class="w-[300px]">
<template #option="{ option }">
{{ manyStructsView(option, props.scheme[key].type.nested.field) }}
</template>
<template #value="{ value }">
{{ manyStructsView(value, props.scheme[key].type.nested.field) }}
</template>
</Select>
<MultiSelect v-else-if="props.scheme[key].type?.nested?.values && props.scheme[key]?.many" class="w-[300px]"
v-model="<T[]>createItem![key]" :options="props.scheme[key].type.nested.values"
:path="props.scheme[key].type.nested.field" :entity-id="props.scheme.entityId" />
<div v-if="props.scheme[key]?.customWindow?.[props.updateMode ? 'update' : 'create']">
<slot :name="<string>key + (props.updateMode ? 'Update' : 'Create')"></slot>
</div>
<div v-else-if="props.scheme[key]?.customWindow?.common">
<slot :name="<string>key"></slot>
</div>
<InputNumber class="w-[300px]" v-model:model-value="<number>createItem![key]"
v-else-if="props.scheme[key]?.type?.primitive === 'number'" />
<InputText class="w-[300px]" v-model:model-value="<string>createItem![key]"
v-else-if="props.scheme[key].type?.primitive === 'string'" />
<DatePicker class="w-[300px]" :default-value="toDate(createItem![key] as number)" @value-change="v => {
createItem![key] = toTimestamp(v as Date) as any
}" show-time v-else-if="props.scheme[key].type?.primitive === 'date'" />
<Textarea class="w-[300px]" v-model="<string>createItem![key]"
v-else-if="props.scheme[key].type?.primitive === 'multiple'" />
<ToggleSwitch class="w-[300px]" v-model:model-value="<boolean>createItem![key]"
v-else-if="props.scheme[key].type?.primitive === 'boolean'" />
<Select v-else-if="props.scheme[key].type?.nested?.values && !props.scheme[key]?.many"
v-model:model-value="createItem![key]" :options="props.scheme[key].type.nested.values"
:placeholder="`Выберите ${props.scheme[key].russian}`" class="w-[300px]">
<template #option="{ option }">
{{ manyStructsView(option, props.scheme[key].type.nested.field) }}
</template>
<template #value="{ value }">
{{ manyStructsView(value, props.scheme[key].type.nested.field) }}
</template>
</Select>
<MultiSelect v-else-if="props.scheme[key].type?.nested?.values && props.scheme[key]?.many"
class="w-[300px]" v-model="<T[]>createItem![key]" :options="props.scheme[key].type.nested.values"
:path="props.scheme[key].type.nested.field" :entity-id="props.scheme.entityId" />
</div>
</div>
<template #footer>
<Button severity="success" @click="async () => {
if (props.updateMode) {
await props.service.update(createItem as T)
await emits('onSaveUpdate', createItem as T)
await emits('onSave', createItem as T)
} else {
await props.service.create(createItem as T)
await emits('onSaveCreate', createItem as T)
await emits('onSave', createItem as T)
}
items = await props.service.readAll() as UnwrapRef<T[]>
showCreate = false
}">Сохранить</Button>
<Button severity="success" class="mt-5" @click="handleSave">Сохранить</Button>
</template>
</Dialog>
</template>