Files
onboard/resources/js/Pages/Statistic/Components/ModalDeathPatients.vue

168 lines
4.7 KiB
Vue

<script setup>
import {
NModal, NDataTable, NEmpty, NSpin, NDrawer, NDrawerContent, NInput, NIcon, NTooltip, NFlex, NText
} from 'naive-ui'
import { TbEye } from 'vue-icons-plus/tb'
import { format, formatDistanceStrict } from 'date-fns'
import { ru } from 'date-fns/locale'
import { computed, h, ref, watch } from 'vue'
import TooltipColumn from '../../Report/Components/DataTableColumns/TooltipColumn.vue'
import {usePage} from "@inertiajs/vue3";
const open = defineModel('open')
const loading = ref(true)
const deadPatients = ref([])
const currentPatient = ref(null)
const showDrawer = ref(false)
const startAt = computed(() => {
const urlParams = new URLSearchParams(window.location.search)
return urlParams.get('startAt')
})
const endAt = computed(() => {
const urlParams = new URLSearchParams(window.location.search)
return urlParams.get('endAt')
})
// Получаем уникальные отделения для фильтра
const departmentOptions = computed(() => {
const departments = new Set()
deadPatients.value.forEach(patient => {
if (patient.department_name) {
departments.add(patient.department_name)
}
})
return Array.from(departments).map(dept => ({
label: dept,
value: dept
}))
.sort((a, b) => a.label.localeCompare(b.label))
})
// Состояние для выбранных фильтров
const filteredDepartments = ref([])
// Отфильтрованные данные
const filteredPatients = computed(() => {
if (!filteredDepartments.value || filteredDepartments.value.length === 0) {
return deadPatients.value
}
return deadPatients.value.filter(
patient => filteredDepartments.value.includes(patient.department_name)
)
})
const columns = computed(() => [
{
title: '№',
key: 'index',
width: 30,
wrap: false,
render: (_, i) => i + 1,
},
{
title: 'ФИО',
key: 'full_name',
width: 200,
ellipsis: { tooltip: { arrow: false } },
},
{
title: 'Возраст',
key: 'age',
width: 80,
render: (row) => row.birth_date
? formatDistanceStrict(new Date(row.birth_date), new Date(), { locale: ru })
: '—',
},
{
title: 'Диагноз',
key: 'diagnosis',
width: 90,
render: (row) => {
return row.diagnosis_code
? h(TooltipColumn, { triggerText: row.diagnosis_code, contentText: row.diagnosis_name })
: '—'
},
},
{
title: 'Отделение',
key: 'department_name',
width: 220,
// Добавляем фильтр для множественного выбора
filterMultiple: true,
filterOptions: departmentOptions.value,
// Функция onFilter обновляет состояние фильтра
filter: (value, row) => {
return !!~row.department_name.indexOf(value)
},
},
])
const fetch = (startAt, endAt) => {
loading.value = true
axios.get('/api/statistics/reports/dead-patients', {
params: { startAt, endAt }
}).then((res) => {
deadPatients.value = res.data ?? []
// Сбрасываем фильтр при загрузке новых данных
filteredDepartments.value = []
}).finally(() => {
loading.value = false
})
}
watch(open, (open) => {
if (open) {
fetch(startAt.value, endAt.value)
}
})
</script>
<template>
<NModal
v-model:show="open"
title="Умершие"
preset="card"
:mask-closable="false"
:close-on-esc="false"
class="max-w-5xl h-[calc(100vh-220px)]"
id="modal-observable-patients"
>
<template v-if="loading">
<div class="flex items-center justify-center h-full">
<NSpin />
</div>
</template>
<template v-else-if="deadPatients.length">
<NDataTable
:columns="columns"
:data="filteredPatients"
table-layout="fixed"
size="small"
:loading="loading"
max-height="calc(100vh - 350px)"
:row-key="(row) => row.id"
/>
</template>
<template v-else>
<div class="h-full flex items-center justify-center">
<NEmpty description="Нет данных!" />
</div>
</template>
</NModal>
</template>
<style scoped>
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
font-size: var(--n-font-size);
}
:deep(.n-modal .v-binder-follower-content) {
position: fixed;
inset: auto auto auto auto;
}
</style>