* связка таблицы архива с пациентами
* добавил разграничение карт по типам баз * модель для хранения изменений статуса карт * добавил окно с просмотром выдачи карты * добавил фильтрацию вывода карт
This commit is contained in:
222
resources/js/Composables/useMedicalHistoryFilter.js
Normal file
222
resources/js/Composables/useMedicalHistoryFilter.js
Normal file
@@ -0,0 +1,222 @@
|
||||
// composables/useMedicalHistoryFilter.js
|
||||
import { router, usePage } from '@inertiajs/vue3'
|
||||
import {ref, computed, watch} from 'vue'
|
||||
import { stringifyQuery } from 'ufo'
|
||||
import {format, isValid, parse, parseISO} from 'date-fns'
|
||||
import {useDebounceFn} from "@vueuse/core";
|
||||
|
||||
export const useMedicalHistoryFilter = (filters) => {
|
||||
const page = usePage()
|
||||
|
||||
// Реактивные фильтры с начальными значениями из URL
|
||||
const filtersRef = ref({
|
||||
search: filters?.search || '',
|
||||
date_extract_from: filters?.date_extract_from || null,
|
||||
date_extract_to: filters?.date_extract_to || null,
|
||||
page: filters?.page || 1,
|
||||
page_size: filters?.page_size || 15,
|
||||
sort_by: filters?.sort_by || 'date_extract',
|
||||
sort_order: filters?.sort_order || 'desc',
|
||||
view_type: filters?.view_type || 'archive'
|
||||
})
|
||||
|
||||
const meta = computed(() => page.props.cards?.meta || {})
|
||||
const isLoading = ref(false)
|
||||
|
||||
// Форматирование даты для URL
|
||||
const formatDateForUrl = (date) => {
|
||||
if (!date) return null
|
||||
if (date instanceof Date) {
|
||||
return format(date, 'yyyy-MM-dd')
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
// Навигация с фильтрами
|
||||
const applyFilters = (updates = {}, resetPage = false) => {
|
||||
// Обновляем фильтры
|
||||
Object.assign(filtersRef.value, updates)
|
||||
|
||||
// Если сбрасываем фильтры, обнуляем страницу
|
||||
if (resetPage) {
|
||||
filtersRef.value.page = 1
|
||||
}
|
||||
|
||||
// Подготавливаем параметры для URL
|
||||
const params = {
|
||||
search: filtersRef.value.search || null,
|
||||
date_extract_from: formatDateForUrl(filtersRef.value.date_extract_from),
|
||||
date_extract_to: formatDateForUrl(filtersRef.value.date_extract_to),
|
||||
page: filtersRef.value.page,
|
||||
page_size: filtersRef.value.page_size,
|
||||
sort_by: filtersRef.value.sort_by,
|
||||
sort_order: filtersRef.value.sort_order,
|
||||
view_type: filtersRef.value.view_type,
|
||||
}
|
||||
|
||||
// Очищаем пустые значения
|
||||
const cleanParams = Object.fromEntries(
|
||||
Object.entries(params).filter(([_, value]) =>
|
||||
value !== undefined && value !== null && value !== ''
|
||||
)
|
||||
)
|
||||
|
||||
const query = stringifyQuery(cleanParams)
|
||||
|
||||
isLoading.value = true
|
||||
router.visit(`/${query ? `?${query}` : ''}`, {
|
||||
preserveState: true,
|
||||
preserveScroll: true,
|
||||
onFinish: () => {
|
||||
isLoading.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Дебаунсированный поиск
|
||||
const debouncedSearch = useDebounceFn((value) => {
|
||||
applyFilters({ search: value }, true)
|
||||
}, 500)
|
||||
|
||||
// Обработчики событий
|
||||
const handleSearch = (value) => {
|
||||
filtersRef.value.search = value
|
||||
debouncedSearch(value)
|
||||
}
|
||||
|
||||
// Конвертация строки даты в timestamp для NaiveUI
|
||||
const convertToTimestamp = (dateString) => {
|
||||
if (!dateString) return null
|
||||
|
||||
try {
|
||||
// Предполагаем формат yyyy-MM-dd
|
||||
const date = parse(dateString, 'yyyy-MM-dd', new Date())
|
||||
return isValid(date) ? date.getTime() : null
|
||||
} catch (error) {
|
||||
console.error('Error converting date to timestamp:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// Конвертация timestamp в строку для URL
|
||||
const convertTimestampToString = (timestamp) => {
|
||||
if (!timestamp) return null
|
||||
|
||||
try {
|
||||
const date = new Date(timestamp)
|
||||
return isValid(date) ? format(date, 'yyyy-MM-dd') : null
|
||||
} catch (error) {
|
||||
console.error('Error converting timestamp to string:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const dateRange = ref([
|
||||
filtersRef.value.date_extract_from ? convertToTimestamp(filtersRef.value.date_extract_from) : null,
|
||||
filtersRef.value.date_extract_to ? convertToTimestamp(filtersRef.value.date_extract_to) : null
|
||||
])
|
||||
|
||||
const handleDateRangeChange = (timestamps) => {
|
||||
dateRange.value = timestamps || [null, null]
|
||||
|
||||
const updates = {
|
||||
date_extract_from: timestamps?.[0] ? convertTimestampToString(timestamps[0]) : null,
|
||||
date_extract_to: timestamps?.[1] ? convertTimestampToString(timestamps[1]) : null
|
||||
}
|
||||
|
||||
Object.assign(filtersRef.value, updates)
|
||||
applyFilters(updates, true)
|
||||
}
|
||||
|
||||
const handleStatusChange = (status) => {
|
||||
applyFilters({ status }, true)
|
||||
}
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
applyFilters({ page })
|
||||
}
|
||||
|
||||
const handlePageSizeChange = (size) => {
|
||||
applyFilters({ page_size: size, page: 1 })
|
||||
}
|
||||
|
||||
const handleViewTypeChange = (view_type) => {
|
||||
applyFilters({ view_type, page: 1 })
|
||||
}
|
||||
|
||||
const handleSortChange = (sorter) => {
|
||||
applyFilters({
|
||||
sort_by: sorter.columnKey,
|
||||
sort_order: sorter.order
|
||||
})
|
||||
}
|
||||
|
||||
const resetAllFilters = () => {
|
||||
filtersRef.value = {
|
||||
search: '',
|
||||
date_extract_from: null,
|
||||
date_extract_to: null,
|
||||
page: 1,
|
||||
page_size: 15,
|
||||
sort_by: 'created_at',
|
||||
sort_order: 'desc',
|
||||
view_type: 'archive',
|
||||
}
|
||||
applyFilters({}, true)
|
||||
}
|
||||
|
||||
// Активные фильтры для отображения
|
||||
const activeFilters = computed(() => {
|
||||
const active = []
|
||||
if (filtersRef.value.search) {
|
||||
active.push({ key: 'search', label: `Поиск: ${filtersRef.value.search}` })
|
||||
}
|
||||
if (filtersRef.value.date_extract_from || filtersRef.value.date_extract_to) {
|
||||
const from = filtersRef.value.date_extract_from ? format(parseISO(filtersRef.value.date_extract_from), 'dd.MM.yyyy') : ''
|
||||
const to = filtersRef.value.date_extract_to ? format(parseISO(filtersRef.value.date_extract_to), 'dd.MM.yyyy') : ''
|
||||
active.push({ key: 'date', label: `Дата: ${from} - ${to}` })
|
||||
}
|
||||
// Добавьте другие фильтры по необходимости
|
||||
return active
|
||||
})
|
||||
|
||||
// Следим за изменениями в page.props.filters
|
||||
watch(
|
||||
() => page.props.filters,
|
||||
(newFilters) => {
|
||||
if (newFilters) {
|
||||
// Сохраняем все фильтры, включая search!
|
||||
filtersRef.value = {
|
||||
...filtersRef.value,
|
||||
...newFilters
|
||||
}
|
||||
|
||||
// Синхронизируем dateRange с фильтрами
|
||||
const formattedDate = [
|
||||
newFilters.date_extract_from ? convertToTimestamp(newFilters.date_extract_from) : null,
|
||||
newFilters.date_extract_to ? convertToTimestamp(newFilters.date_extract_to) : null
|
||||
]
|
||||
|
||||
dateRange.value = formattedDate.every(date => date === null) ? null : formattedDate
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
)
|
||||
|
||||
return {
|
||||
filtersRef,
|
||||
meta,
|
||||
isLoading,
|
||||
activeFilters,
|
||||
dateRange,
|
||||
handleViewTypeChange,
|
||||
handleSearch,
|
||||
handleDateRangeChange,
|
||||
handleStatusChange,
|
||||
handlePageChange,
|
||||
handlePageSizeChange,
|
||||
handleSortChange,
|
||||
resetAllFilters,
|
||||
applyFilters
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user