This commit is contained in:
2025-03-07 20:41:21 +07:00
parent bf7037f4e8
commit 96b814d54a
52 changed files with 6643 additions and 782 deletions

View File

@@ -0,0 +1,94 @@
<script setup lang="ts" generic="T extends IEntity">
import { Button, DatePicker, Dialog, InputNumber, InputText, MultiSelect, Select, Textarea, ToggleSwitch } from 'primevue';
import type { IEntity } from '../types/entity.type';
import type { Scheme } from '../types/scheme.type';
import type { IService } from '../types/service.type';
import { manyStructsView } from '../utils/structs/structs-view.util';
import { type UnwrapRef } from 'vue';
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
}>()
type Key = keyof T
const keys = Object.keys(props.scheme) as Key[]
const emits = defineEmits<{
(e: 'onSave', data: any): void
(e: 'onSaveUpdate', data: any): void
(e: 'onSaveCreate', data: any): void
}>()
</script>
<template>
<Dialog v-model:visible="showCreate">
<div class="flex flex-col justify-center gap-5">
<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]" v-model:model-value="<Date>createItem![key]"
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].type?.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?.many" v-model:model-value="createItem![key]"
:options="props.scheme[key].type?.nested?.values"
class="w-[300px] h-11"
:placeholder="`Выберите ${props.scheme[key].russian}`">
<template #option="{ option }">
{{ manyStructsView(option, props.scheme[key]?.type?.nested?.field) }}
</template>
<template #value="{ value }">
{{ manyStructsView(value, props.scheme[key]?.type?.nested?.field) }}
</template>
</MultiSelect>
</div>
</div>
</div>
<template #footer>
<Button severity="success" @click="async () => {
if (props.updateMode) {
props.service.update(createItem as T)
emits('onSaveUpdate', createItem as T)
emits('onSave', createItem as T)
} else {
props.service.create(createItem as T)
emits('onSaveCreate', createItem as T)
emits('onSave', createItem as T)
}
items = await service.readAll() as UnwrapRef<T[]>
showCreate = false
}">Сохранить</Button>
</template>
</Dialog>
</template>

View File

@@ -0,0 +1,155 @@
<script setup lang="ts" generic="T extends IEntity">
import { onMounted, ref, watch, type UnwrapRef } from "vue";
import type { TableProps } from "../types/table-props.type";
import { DataTable, Column, Button } from "primevue";
import { manyStructsView } from "../utils/structs/structs-view.util";
import type { TableEmits } from "../types/table-emits.type";
import FloatingButton from "../components/buttons/FloatingButton.vue";
import type { IEntity } from "../types/entity.type";
import DialogWindow from "./DialogWindow.vue";
const props = defineProps<TableProps<T>>();
const items = ref<T[]>([]);
onMounted(async () => {
items.value = await props.service.readAll();
});
type Key = keyof T;
const keys = Object.keys(props.scheme) as Key[];
const emits = defineEmits<TableEmits>();
const showCreate = ref(false);
const createItem = ref<null | T>(null);
const showUpdate = ref(false);
const updateItem = ref<null | T>(null);
watch(showUpdate, (value) => {
if (!value) {
updateItem.value = null;
}
});
watch(updateItem, (value) => {
if (value) {
showUpdate.value = true;
} else {
showUpdate.value = false;
}
});
watch(showCreate, (value) => {
if (value) {
createItem.value = props.getDefaults();
} else {
createItem.value = null;
}
});
watch(createItem, (value) => {
if (value) {
showCreate.value = true;
} else {
showCreate.value = false;
}
});
const handleFloatingButtonClick = () => {
emits('onCreateOpen')
emits('onOpen')
showCreate.value = true;
};
const slots = defineSlots();
const createSlotName = (key: any) => key + "Create";
const updateSlotName = (key: any) => key + "Update";
</script>
<template>
<DialogWindow
:scheme="props.scheme"
:service="props.service"
:get-defaults="props.getDefaults"
v-model:item="<T>createItem"
v-model:show="showCreate"
v-model:items="items"
@on-save="data => emits('onSave', data)"
@on-save-create="data => emits('onSaveCreate', data)"
>
<template v-for="key in keys" #[key]>
<slot :name="<string>key"></slot>
</template>
<template v-for="key in keys" #[createSlotName(key)]>
<slot :name="createSlotName(key)"></slot>
</template>
</DialogWindow>
<DialogWindow
:scheme="props.scheme"
update-mode
:service="props.service"
:get-defaults="props.getDefaults"
v-model:item="<T>updateItem"
v-model:show="showUpdate"
v-model:items="items"
@on-save="data => emits('onSave', data)"
@on-save-update="data => emits('onSaveUpdate', data)"
>
<template v-for="key in keys" #[key]>
<slot :name="<string>key"></slot>
</template>
<template v-for="key in keys" #[updateSlotName(key)]>
<slot :name="updateSlotName(key)"></slot>
</template>
</DialogWindow>
<div>
<DataTable :value="<[]>items">
<template #header v-if="props.name">
<p>{{ props.name }}</p>
</template>
<template v-for="key in keys">
<Column
:header="props.scheme[key]?.russian"
v-if="!props.scheme[key].hidden"
>
<template #body="{ data }">
<p>
{{
manyStructsView(
data[key],
props.scheme[key]?.type?.nested?.field,
)
}}
</p>
</template>
</Column>
</template>
<Column header="Действия">
<template #body="{ data }">
<div class="flex gap-2">
<Button
severity="secondary"
icon="pi pi-pencil"
@click="() => {
emits('onUpdateOpen')
emits('onOpen')
updateItem = data
}"
></Button>
<Button
severity="danger"
icon="pi pi-trash"
@click="async () => {
emits('onDelete', data)
await props.service.delete(data.Id)
items = await props.service.readAll() as UnwrapRef<T[]>
}"
></Button>
</div>
</template>
</Column>
</DataTable>
<FloatingButton @click="handleFloatingButtonClick" />
</div>
</template>