423 lines
14 KiB
JavaScript
423 lines
14 KiB
JavaScript
import { defineStore } from "pinia";
|
||
import { useTimestamp } from "@vueuse/core";
|
||
import { computed, ref } from "vue";
|
||
import { router } from "@inertiajs/vue3";
|
||
|
||
const patientStatuses = [
|
||
'mis-plan',
|
||
'mis-emergency',
|
||
'mis-observation',
|
||
'mis-reanimation',
|
||
'mis-outcome-discharged',
|
||
'mis-outcome-deceased',
|
||
'mis-outcome-transferred',
|
||
'special-plan',
|
||
'special-emergency',
|
||
'special-observation',
|
||
'special-reanimation',
|
||
'special-outcome-discharged',
|
||
'special-outcome-deceased',
|
||
'special-outcome-transferred',
|
||
]
|
||
|
||
const createEmptyPatients = () => Object.fromEntries(patientStatuses.map((status) => [status, []]))
|
||
const createStatusCounts = () => {
|
||
const extended = {
|
||
'mis-outcome': 0,
|
||
'special-outcome': 0,
|
||
}
|
||
|
||
return {
|
||
...Object.fromEntries(patientStatuses.map((status) => [status, 0])),
|
||
...extended,
|
||
}
|
||
}
|
||
const createStatusStates = () => Object.fromEntries(patientStatuses.map((status) => [status, {
|
||
page: 1,
|
||
perPage: status.includes('observation') ? 1000 : 20,
|
||
total: 0,
|
||
search: '',
|
||
loading: false,
|
||
loaded: false,
|
||
}]))
|
||
|
||
export const useReportStore = defineStore('reportStore', () => {
|
||
const timestampNow = useTimestamp()
|
||
const reportFormRef = ref(null)
|
||
|
||
const _timestampCurrent = ref(null)
|
||
const timestampCurrent = computed({
|
||
get: () => _timestampCurrent.value === null ? timestampNow.value : _timestampCurrent.value,
|
||
set: (value) => {
|
||
_timestampCurrent.value = value
|
||
}
|
||
})
|
||
|
||
const timestampCurrentRange = ref([null, null])
|
||
const dataOnReport = ref(null)
|
||
const openedCollapsible = ref([])
|
||
const reportInfo = ref({ userId: null })
|
||
const isLoadReportInfo = ref(false)
|
||
const isDragActive = ref(false)
|
||
const patientsData = ref(createEmptyPatients())
|
||
const statusCounts = ref(createStatusCounts())
|
||
const statusStates = ref(createStatusStates())
|
||
const countsLoading = ref(false)
|
||
const reportForm = ref({})
|
||
const departmentUsers = ref([])
|
||
const unwantedEvents = ref([])
|
||
|
||
const patientColumns = [
|
||
{ title: '№', width: '80', key: 'num' },
|
||
{ title: 'ФИО', width: '320', key: 'fullname' },
|
||
{ title: 'Возраст', key: 'age' },
|
||
{ title: 'Д/р', key: 'birth_date' },
|
||
{ title: 'Д/п', key: 'admitted_at' },
|
||
{ title: 'Диагноз', key: 'mkb.ds' }
|
||
]
|
||
|
||
const addRowNumbers = (data, page = 1, perPage = 15) => {
|
||
if (!Array.isArray(data)) return data
|
||
|
||
const startFrom = ((page - 1) * perPage) + 1
|
||
|
||
return data.map((item, index) => ({
|
||
...item,
|
||
num: startFrom + index
|
||
}))
|
||
}
|
||
|
||
const applyMetricsFromDepartment = (department) => {
|
||
reportForm.value.metrika_item_3 = department?.recipientCount ?? 0
|
||
reportForm.value.metrika_item_7 = department?.extractCount ?? 0
|
||
reportForm.value.metrika_item_8 = department?.currentCount ?? 0
|
||
reportForm.value.metrika_item_9 = department?.deadCount ?? 0
|
||
reportForm.value.metrika_item_10 = department?.surgicalCount?.[0] ?? 0
|
||
reportForm.value.metrika_item_11 = department?.surgicalCount?.[1] ?? 0
|
||
reportForm.value.metrika_item_17 = department?.countStaff ?? 0
|
||
}
|
||
|
||
const initializeFromPage = (pageProps) => {
|
||
reportInfo.value = {
|
||
...reportInfo.value,
|
||
...pageProps,
|
||
}
|
||
|
||
unwantedEvents.value = [...(pageProps.report?.unwantedEvents ?? [])]
|
||
patientsData.value = createEmptyPatients()
|
||
statusCounts.value = createStatusCounts()
|
||
statusStates.value = createStatusStates()
|
||
openedCollapsible.value = []
|
||
|
||
if (pageProps.report?.isHeadOrAdmin) {
|
||
timestampCurrentRange.value = [pageProps.dates.startAt, pageProps.dates.endAt]
|
||
} else {
|
||
timestampCurrentRange.value = [pageProps.dates.endAt, pageProps.dates.endAt]
|
||
}
|
||
|
||
applyMetricsFromDepartment(pageProps.department)
|
||
}
|
||
|
||
const getColumnsByKey = (keys) => keys.map((key) => patientColumns.find(item => item.key === key))
|
||
|
||
const getStatusState = (status) => statusStates.value[status]
|
||
|
||
const getPatientsCount = (status) => {
|
||
if (Object.prototype.hasOwnProperty.call(statusCounts.value, status)) {
|
||
return statusCounts.value[status]
|
||
}
|
||
return patientsData.value[status]?.length ?? 0
|
||
}
|
||
|
||
const getObservationPatientsForSubmit = () => ([
|
||
...(patientsData.value['mis-observation'] ?? []),
|
||
...(patientsData.value['special-observation'] ?? []),
|
||
])
|
||
|
||
const findPatientById = (patientId) => {
|
||
for (const status of patientStatuses) {
|
||
const patient = patientsData.value[status]?.find((item) => item.id === patientId)
|
||
if (patient) {
|
||
return patient
|
||
}
|
||
}
|
||
|
||
return null
|
||
}
|
||
|
||
const removeObservationPatientLocally = (patientId) => {
|
||
for (const status of ['mis-observation', 'special-observation']) {
|
||
const index = patientsData.value[status]?.findIndex((item) => item.id === patientId) ?? -1
|
||
if (index !== -1) {
|
||
patientsData.value[status].splice(index, 1)
|
||
const state = getStatusState(status)
|
||
if (state && state.total > 0) state.total -= 1
|
||
return
|
||
}
|
||
}
|
||
}
|
||
|
||
const loadPatientsByStatus = async (status, { resetPage = false } = {}) => {
|
||
const state = getStatusState(status)
|
||
if (!state) return
|
||
if (state.loading) return
|
||
|
||
if (resetPage) {
|
||
state.page = 1
|
||
}
|
||
|
||
state.loading = true
|
||
|
||
try {
|
||
const response = await axios.post('/api/mis/patients', {
|
||
status,
|
||
departmentId: reportInfo.value?.department?.department_id,
|
||
startAt: reportInfo.value?.dates?.startAt,
|
||
endAt: reportInfo.value?.dates?.endAt,
|
||
page: state.page,
|
||
perPage: state.perPage,
|
||
search: state.search || undefined,
|
||
})
|
||
|
||
patientsData.value[status] = addRowNumbers(
|
||
response.data?.data ?? [],
|
||
state.page,
|
||
state.perPage
|
||
)
|
||
|
||
state.total = response.data?.meta?.total ?? patientsData.value[status].length
|
||
statusCounts.value[status] = state.total
|
||
state.loaded = true
|
||
} finally {
|
||
state.loading = false
|
||
}
|
||
}
|
||
|
||
const loadStatusCount = async (status) => {
|
||
if (!Object.prototype.hasOwnProperty.call(statusCounts.value, status)) return
|
||
|
||
const response = await axios.post('/api/mis/patients/count', {
|
||
status,
|
||
departmentId: reportInfo.value?.department?.department_id,
|
||
startAt: reportInfo.value?.dates?.startAt,
|
||
endAt: reportInfo.value?.dates?.endAt,
|
||
})
|
||
|
||
statusCounts.value[status] = Number(response.data ?? 0)
|
||
}
|
||
|
||
const loadAllStatusCounts = async (force = false) => {
|
||
countsLoading.value = true
|
||
try {
|
||
const response = await axios.post('/api/mis/patients/counts', {
|
||
departmentId: reportInfo.value?.department?.department_id,
|
||
startAt: reportInfo.value?.dates?.startAt,
|
||
endAt: reportInfo.value?.dates?.endAt,
|
||
force,
|
||
})
|
||
|
||
const counts = response.data?.counts ?? {}
|
||
statusCounts.value = {
|
||
...createStatusCounts(),
|
||
...counts,
|
||
}
|
||
} finally {
|
||
countsLoading.value = false
|
||
}
|
||
}
|
||
|
||
const ensureStatusLoaded = async (status) => {
|
||
const state = getStatusState(status)
|
||
if (!state || state.loaded) return
|
||
await loadPatientsByStatus(status)
|
||
}
|
||
|
||
const setStatusSearch = async (status, search) => {
|
||
const state = getStatusState(status)
|
||
if (!state) return
|
||
state.search = search
|
||
await loadPatientsByStatus(status, { resetPage: true })
|
||
}
|
||
|
||
const setStatusPage = async (status, page) => {
|
||
const state = getStatusState(status)
|
||
if (!state) return
|
||
state.page = page
|
||
await loadPatientsByStatus(status)
|
||
}
|
||
|
||
const reloadReportPage = () => new Promise((resolve) => {
|
||
isLoadReportInfo.value = true
|
||
router.reload({
|
||
preserveScroll: true,
|
||
onSuccess: (page) => {
|
||
initializeFromPage(page.props)
|
||
},
|
||
onFinish: () => {
|
||
isLoadReportInfo.value = false
|
||
resolve()
|
||
},
|
||
})
|
||
})
|
||
|
||
const getDataOnReportDate = async () => {
|
||
await reloadReportPage()
|
||
}
|
||
|
||
const sendReportForm = (assignForm = null) => {
|
||
const form = {
|
||
metrics: reportForm.value,
|
||
observationPatients: getObservationPatientsForSubmit(),
|
||
unwantedEvents: unwantedEvents.value,
|
||
dates: [
|
||
timestampCurrentRange.value[0],
|
||
timestampCurrentRange.value[1]
|
||
],
|
||
userId: reportInfo.value.report.userId,
|
||
departmentId: reportInfo.value.department.department_id,
|
||
reportId: reportInfo.value.report.report_id,
|
||
...assignForm
|
||
}
|
||
|
||
router.post('/report', form, {
|
||
onSuccess: () => {
|
||
window.$message.success('Отчет сохранен')
|
||
}
|
||
})
|
||
}
|
||
|
||
const createManualPatient = async (payload) => {
|
||
await axios.post('/api/report/manual-patients', payload)
|
||
await reloadReportPage()
|
||
|
||
const status = `special-${payload.patient_kind}`
|
||
|
||
await Promise.all([
|
||
loadPatientsByStatus(status, { resetPage: true }),
|
||
loadAllStatusCounts(true),
|
||
])
|
||
}
|
||
|
||
const setManualPatientOutcome = async (departmentPatientId, payload) => {
|
||
await axios.post(`/api/report/manual-patients/${departmentPatientId}/outcome`, payload)
|
||
await reloadReportPage()
|
||
await loadAllStatusCounts(true)
|
||
}
|
||
|
||
const updateManualPatient = async (departmentPatientId, payload, options = {}) => {
|
||
await axios.patch(`/api/report/manual-patients/${departmentPatientId}`, {
|
||
...payload,
|
||
startAt: reportInfo.value?.dates?.startAt,
|
||
endAt: reportInfo.value?.dates?.endAt,
|
||
})
|
||
|
||
const reloadStatuses = Array.from(new Set((options.reloadStatuses ?? []).filter(Boolean)))
|
||
|
||
await reloadReportPage()
|
||
|
||
await Promise.all([
|
||
...reloadStatuses.map((status) => loadPatientsByStatus(status, { resetPage: true })),
|
||
loadAllStatusCounts(true),
|
||
])
|
||
}
|
||
|
||
const searchMisPatients = async (departmentId, query) => {
|
||
const response = await axios.get('/api/mis/patients/search', {
|
||
params: { departmentId, query }
|
||
})
|
||
|
||
return response.data
|
||
}
|
||
|
||
const searchMkb = async (query) => {
|
||
const response = await axios.get('/api/mis/mkb/search', {
|
||
params: { query }
|
||
})
|
||
|
||
return response.data
|
||
}
|
||
|
||
const searchMedicalServices = async (query) => {
|
||
const response = await axios.get('/api/mis/services/search', {
|
||
params: { query }
|
||
})
|
||
|
||
return response.data
|
||
}
|
||
|
||
const linkManualPatient = async (departmentPatientId, medicalHistoryId) => {
|
||
await axios.post(`/api/report/manual-patients/${departmentPatientId}/link`, {
|
||
medical_history_id: medicalHistoryId
|
||
})
|
||
await reloadReportPage()
|
||
}
|
||
|
||
const getManualPatientOperations = async (departmentPatientId) => {
|
||
const response = await axios.get(`/api/report/manual-patients/${departmentPatientId}/operations`)
|
||
return response.data ?? []
|
||
}
|
||
|
||
const createManualPatientOperation = async (departmentPatientId, payload) => {
|
||
const response = await axios.post(`/api/report/manual-patients/${departmentPatientId}/operations`, payload)
|
||
return response.data
|
||
}
|
||
|
||
const updateManualPatientOperation = async (departmentPatientId, operationId, payload) => {
|
||
const response = await axios.patch(`/api/report/manual-patients/${departmentPatientId}/operations/${operationId}`, payload)
|
||
return response.data
|
||
}
|
||
|
||
const deleteManualPatientOperation = async (departmentPatientId, operationId) => {
|
||
await axios.delete(`/api/report/manual-patients/${departmentPatientId}/operations/${operationId}`)
|
||
}
|
||
|
||
return {
|
||
reportFormRef,
|
||
timestampNow,
|
||
timestampCurrent,
|
||
timestampCurrentRange,
|
||
dataOnReport,
|
||
isLoadReportInfo,
|
||
patientColumns,
|
||
patientsData,
|
||
statusCounts,
|
||
statusStates,
|
||
countsLoading,
|
||
reportInfo,
|
||
reportForm,
|
||
departmentUsers,
|
||
unwantedEvents,
|
||
openedCollapsible,
|
||
isDragActive,
|
||
|
||
initializeFromPage,
|
||
getColumnsByKey,
|
||
getPatientsCount,
|
||
getStatusState,
|
||
getObservationPatientsForSubmit,
|
||
findPatientById,
|
||
removeObservationPatientLocally,
|
||
loadPatientsByStatus,
|
||
loadStatusCount,
|
||
loadAllStatusCounts,
|
||
ensureStatusLoaded,
|
||
setStatusSearch,
|
||
setStatusPage,
|
||
reloadReportPage,
|
||
getDataOnReportDate,
|
||
createManualPatient,
|
||
setManualPatientOutcome,
|
||
updateManualPatient,
|
||
searchMisPatients,
|
||
searchMkb,
|
||
searchMedicalServices,
|
||
linkManualPatient,
|
||
getManualPatientOperations,
|
||
createManualPatientOperation,
|
||
updateManualPatientOperation,
|
||
deleteManualPatientOperation,
|
||
sendReportForm,
|
||
addRowNumbers,
|
||
}
|
||
})
|