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, } })