136 lines
5.9 KiB
Vue
136 lines
5.9 KiB
Vue
<script setup>
|
||
import {
|
||
NButton, NFlex, NForm, NFormItem, NInput, NSelect,
|
||
NText, NDynamicInput, NAlert, NTag,
|
||
} from 'naive-ui'
|
||
import {
|
||
TbReportAnalytics, TbLayoutDashboard,
|
||
} from 'vue-icons-plus/tb'
|
||
import AppLayout from '../../../Layouts/AppLayout.vue'
|
||
import AppContainer from '../../../Components/AppContainer.vue'
|
||
import SectionCard from '../../../Components/SectionCard.vue'
|
||
import PageBanner from '../../../Components/PageBanner.vue'
|
||
import SectionEditor from './Components/SectionEditor.vue'
|
||
import { useForm, Link, usePage } from '@inertiajs/vue3'
|
||
import { computed } from 'vue'
|
||
|
||
const props = defineProps({
|
||
template: { type: Object, default: null },
|
||
sources: { type: Array, default: () => [] },
|
||
})
|
||
|
||
const page = usePage()
|
||
const flash = computed(() => page.props.flash ?? {})
|
||
|
||
const isEdit = computed(() => !!props.template)
|
||
|
||
const createSection = () => ({
|
||
source: props.sources[0]?.key ?? null,
|
||
title: '',
|
||
columns: [],
|
||
filters: [],
|
||
})
|
||
|
||
const form = useForm({
|
||
name: props.template?.name ?? '',
|
||
sections: props.template?.sections?.length ? props.template.sections : [createSection()],
|
||
required_permissions: props.template?.requiredPermissions ?? [],
|
||
})
|
||
|
||
const visibilityOptions = [
|
||
{ label: 'Дежурный врач', value: 'report.view' },
|
||
{ label: 'Старшая медсестра', value: 'nurse.report.view' },
|
||
]
|
||
|
||
const submit = () => {
|
||
if (isEdit.value) {
|
||
form.put(`/admin/report-templates/${props.template.id}`)
|
||
} else {
|
||
form.post('/admin/report-templates/new')
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<AppLayout>
|
||
<AppContainer>
|
||
|
||
<NAlert v-if="flash.success" type="success" closable style="margin-bottom: 4px;">
|
||
{{ flash.success }}
|
||
</NAlert>
|
||
|
||
<PageBanner
|
||
:title="isEdit ? template.name : 'Новый шаблон отчёта'"
|
||
:icon="TbReportAnalytics"
|
||
:color="isEdit ? null : 'default'"
|
||
:breadcrumbs="[
|
||
{ label: 'Администратор', href: '/admin', icon: TbLayoutDashboard, tag: Link },
|
||
{ label: 'Шаблоны отчётов', href: '/admin/report-templates', icon: TbReportAnalytics, tag: Link },
|
||
]"
|
||
>
|
||
<template #meta>
|
||
<NText depth="3" style="font-size: 13px;">
|
||
{{ isEdit ? 'Редактирование шаблона' : 'Название → секции с данными → кому виден' }}
|
||
</NText>
|
||
</template>
|
||
<template #actions>
|
||
<NButton :tag="Link" href="/admin/report-templates">Отмена</NButton>
|
||
<NButton type="primary" :loading="form.processing" @click="submit">
|
||
{{ isEdit ? 'Сохранить' : 'Создать шаблон' }}
|
||
</NButton>
|
||
</template>
|
||
</PageBanner>
|
||
|
||
<NFlex vertical :size="16">
|
||
|
||
<SectionCard title="1 · Название и видимость">
|
||
<NFlex :size="16" :wrap="true">
|
||
<NForm label-placement="top" style="flex: 2; min-width: 280px;">
|
||
<NFormItem label="Название отчёта" :feedback="form.errors.name" :validation-status="form.errors.name ? 'error' : undefined" style="margin-bottom: 0;">
|
||
<NInput v-model:value="form.name" placeholder="Например: Сводка по отделению" />
|
||
</NFormItem>
|
||
</NForm>
|
||
<NForm label-placement="top" style="flex: 1; min-width: 280px;">
|
||
<NFormItem label="Кому виден отчёт" style="margin-bottom: 0;">
|
||
<NSelect
|
||
v-model:value="form.required_permissions"
|
||
:options="visibilityOptions"
|
||
multiple
|
||
placeholder="Все с доступом к отчётам"
|
||
clearable
|
||
/>
|
||
</NFormItem>
|
||
</NForm>
|
||
</NFlex>
|
||
<NText depth="3" style="font-size: 12px; display: block; margin-top: 4px;">
|
||
Ничего не выбрано — отчёт увидят все, у кого есть доступ к разделу «Отчёты»
|
||
</NText>
|
||
</SectionCard>
|
||
|
||
<SectionCard title="2 · Секции с данными">
|
||
<NText v-if="form.errors.sections" type="error" style="display: block; margin-bottom: 8px; font-size: 12px;">
|
||
{{ form.errors.sections }}
|
||
</NText>
|
||
<NDynamicInput
|
||
v-model:value="form.sections"
|
||
:on-create="createSection"
|
||
item-style="margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid var(--n-border-color, rgba(255,255,255,.08));"
|
||
>
|
||
<template #default="{ index, value }">
|
||
<NFlex vertical :size="8" style="width: 100%;">
|
||
<NTag size="small" round :bordered="false">Секция {{ index + 1 }}</NTag>
|
||
<SectionEditor :section="value" :sources="sources" />
|
||
</NFlex>
|
||
</template>
|
||
<template #create-button-default>
|
||
Добавить секцию
|
||
</template>
|
||
</NDynamicInput>
|
||
</SectionCard>
|
||
|
||
</NFlex>
|
||
|
||
</AppContainer>
|
||
</AppLayout>
|
||
</template>
|