import { ref, computed } from "vue"; import type { Filter, ActiveFilters } from "../types"; /** * Composable для управления состоянием фильтров */ export function useFiltersState() { // Состояние const filters = ref([]); const isLoading = ref(false); const error = ref(null); const activeFilters = ref({}); // Отдельное состояние для range фильтров (products) const activeRangeFilters = ref>([]); // Состояние для range фильтров (не активных) const rangeFilters = ref>([]); // Вычисляемые свойства const hasFilters = computed(() => filters.value.length > 0); const hasActiveFilters = computed( () => Object.keys(activeFilters.value).length > 0 || activeRangeFilters.value.length > 0 ); const activeFiltersCount = computed(() => { const checkboxCount = Object.values(activeFilters.value).reduce((total, values) => { return total + (Array.isArray(values) ? values.length : 1); }, 0); const rangeCount = activeRangeFilters.value.length; return checkboxCount + rangeCount; }); /** * Устанавливает фильтры */ const setFilters = (newFilters: Filter[]) => { filters.value = newFilters; }; /** * Добавляет фильтр */ const addFilter = (filter: Filter) => { const existingIndex = filters.value.findIndex( (f) => f.code === filter.code ); if (existingIndex >= 0) { filters.value[existingIndex] = filter; } else { filters.value.push(filter); } }; /** * Удаляет фильтр */ const removeFilter = (filterCode: string) => { filters.value = filters.value.filter((f) => f.code !== filterCode); }; /** * Очищает все фильтры */ const clearFilters = () => { filters.value = []; }; /** * Применяет значение фильтра */ const applyFilterValue = ( filterCode: string, valueId: string, isSelected: boolean ) => { if (isSelected) { // Добавляем значение к активным фильтрам if (!activeFilters.value[filterCode]) { activeFilters.value[filterCode] = []; } if (Array.isArray(activeFilters.value[filterCode])) { const values = activeFilters.value[filterCode] as string[]; if (!values.includes(valueId)) { values.push(valueId); } } } else { // Удаляем значение из активных фильтров if ( activeFilters.value[filterCode] && Array.isArray(activeFilters.value[filterCode]) ) { const values = activeFilters.value[filterCode] as string[]; const index = values.indexOf(valueId); if (index >= 0) { values.splice(index, 1); } // Если фильтр пустой, удаляем его if (values.length === 0) { delete activeFilters.value[filterCode]; } } } }; /** * Удаляет значение фильтра */ const removeFilterValue = (filterCode: string, valueId: string) => { if ( activeFilters.value[filterCode] && Array.isArray(activeFilters.value[filterCode]) ) { const values = activeFilters.value[filterCode] as string[]; const index = values.indexOf(valueId); if (index >= 0) { values.splice(index, 1); } // Если фильтр пустой, удаляем его if (values.length === 0) { delete activeFilters.value[filterCode]; } } }; /** * Очищает все активные фильтры */ const clearActiveFilters = () => { activeFilters.value = {}; }; /** * Устанавливает активные фильтры */ const setActiveFilters = (newActiveFilters: ActiveFilters) => { activeFilters.value = { ...newActiveFilters }; }; /** * Проверяет, активно ли значение фильтра */ const isFilterValueActive = ( filterCode: string, valueId: string ): boolean => { if ( activeFilters.value[filterCode] && Array.isArray(activeFilters.value[filterCode]) ) { return (activeFilters.value[filterCode] as string[]).includes(valueId); } return false; }; /** * Получает активные значения для фильтра */ const getActiveValuesForFilter = (filterCode: string): string[] => { if ( activeFilters.value[filterCode] && Array.isArray(activeFilters.value[filterCode]) ) { return [...(activeFilters.value[filterCode] as string[])]; } return []; }; /** * Применяет range фильтр */ const applyRangeFilter = (filterCode: string, gte?: string, lte?: string) => { const existingIndex = activeRangeFilters.value.findIndex( (filter) => filter.code === filterCode ); if (gte || lte) { const rangeFilter = { code: filterCode, gte, lte }; if (existingIndex >= 0) { activeRangeFilters.value[existingIndex] = rangeFilter; } else { activeRangeFilters.value.push(rangeFilter); } } else { // Если оба значения пустые, удаляем фильтр if (existingIndex >= 0) { activeRangeFilters.value.splice(existingIndex, 1); } } }; /** * Удаляет range фильтр */ const removeRangeFilter = (filterCode: string) => { const index = activeRangeFilters.value.findIndex( (filter) => filter.code === filterCode ); if (index >= 0) { activeRangeFilters.value.splice(index, 1); } }; /** * Получает активный range фильтр */ const getActiveRangeFilter = (filterCode: string): { gte?: string; lte?: string } | null => { const filter = activeRangeFilters.value.find( (filter) => filter.code === filterCode ); return filter ? { gte: filter.gte, lte: filter.lte } : null; }; /** * Очищает все range фильтры */ const clearRangeFilters = () => { activeRangeFilters.value = []; }; /** * Устанавливает range фильтры */ const setRangeFilters = (rangeFilters: Array<{ code: string; gte?: string; lte?: string }>) => { activeRangeFilters.value = [...rangeFilters]; }; /** * Устанавливает доступные range фильтры */ const setAvailableRangeFilters = (newRangeFilters: Array<{ code: string; name: string; gte: string; lte: string }>) => { rangeFilters.value = [...newRangeFilters]; }; /** * Добавляет доступный range фильтр */ const addRangeFilter = (rangeFilter: { code: string; name: string; gte: string; lte: string }) => { const existingIndex = rangeFilters.value.findIndex( (f) => f.code === rangeFilter.code ); if (existingIndex >= 0) { rangeFilters.value[existingIndex] = rangeFilter; } else { rangeFilters.value.push(rangeFilter); } }; /** * Удаляет доступный range фильтр */ const removeAvailableRangeFilter = (filterCode: string) => { rangeFilters.value = rangeFilters.value.filter((f) => f.code !== filterCode); }; /** * Очищает все доступные range фильтры */ const clearAvailableRangeFilters = () => { rangeFilters.value = []; }; /** * Получает доступный range фильтр по коду */ const getRangeFilter = (filterCode: string) => { return rangeFilters.value.find((f) => f.code === filterCode); }; return { // Состояние filters, isLoading, error, activeFilters, activeRangeFilters, rangeFilters, // Вычисляемые свойства hasFilters, hasActiveFilters, activeFiltersCount, // Методы управления фильтрами setFilters, addFilter, removeFilter, clearFilters, // Методы управления активными фильтрами applyFilterValue, removeFilterValue, clearActiveFilters, setActiveFilters, isFilterValueActive, getActiveValuesForFilter, // Методы управления активными range фильтрами applyRangeFilter, removeRangeFilter, getActiveRangeFilter, clearRangeFilters, setRangeFilters, // Методы управления доступными range фильтрами setAvailableRangeFilters, addRangeFilter, removeAvailableRangeFilter, clearAvailableRangeFilters, getRangeFilter, }; }