82 lines
2.1 KiB
TypeScript
82 lines
2.1 KiB
TypeScript
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,
|
|
};
|
|
}
|