ERP-node/frontend/hooks/useSearchAndFilter.ts

82 lines
2.1 KiB
TypeScript
Raw Permalink Normal View History

import { useState, useMemo } from "react";
export interface SearchAndFilterOptions {
searchFields: string[];
initialSearchTerm?: string;
initialShowActiveOnly?: boolean;
}
export interface SearchAndFilterResult<T> {
// 상태
searchTerm: string;
showActiveOnly: boolean;
filteredItems: T[];
// 액션
setSearchTerm: (term: string) => void;
setShowActiveOnly: (show: boolean) => void;
// 유틸리티
clearSearch: () => void;
toggleActiveFilter: () => void;
}
/**
*
* @param items
* @param options ( , )
*/
export function useSearchAndFilter<T extends { is_active: string }>(
items: T[],
options: SearchAndFilterOptions,
): SearchAndFilterResult<T> {
const { searchFields, initialSearchTerm = "", initialShowActiveOnly = false } = options;
// 검색 및 필터 상태
const [searchTerm, setSearchTerm] = useState(initialSearchTerm);
const [showActiveOnly, setShowActiveOnly] = useState(initialShowActiveOnly);
// 필터링된 아이템 계산
const filteredItems = useMemo(() => {
return items.filter((item) => {
// 검색 조건 확인
const matchesSearch =
searchTerm.trim() === "" ||
searchFields.some((field) => {
const fieldValue = (item as any)[field];
return fieldValue && fieldValue.toString().toLowerCase().includes(searchTerm.toLowerCase());
});
// 활성 상태 조건 확인
const matchesActive = !showActiveOnly || item.is_active === "Y";
return matchesSearch && matchesActive;
});
}, [items, searchTerm, showActiveOnly, searchFields]);
// 검색어 초기화
const clearSearch = () => {
setSearchTerm("");
};
// 활성 필터 토글
const toggleActiveFilter = () => {
setShowActiveOnly((prev) => !prev);
};
return {
// 상태
searchTerm,
showActiveOnly,
filteredItems,
// 액션
setSearchTerm,
setShowActiveOnly,
// 유틸리티
clearSearch,
toggleActiveFilter,
};
}