import { useState, useCallback, useEffect, useRef } from "react"; import { apiClient } from "@/lib/api/client"; import { EntitySearchResult, EntitySearchResponse } from "./types"; interface UseEntitySearchProps { tableName: string; searchFields?: string[]; filterCondition?: Record; } export function useEntitySearch({ tableName, searchFields = [], filterCondition = {}, }: UseEntitySearchProps) { const [searchText, setSearchText] = useState(""); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [pagination, setPagination] = useState({ total: 0, page: 1, limit: 20, }); // searchFields와 filterCondition을 ref로 관리하여 useCallback 의존성 문제 해결 const searchFieldsRef = useRef(searchFields); const filterConditionRef = useRef(filterCondition); useEffect(() => { searchFieldsRef.current = searchFields; filterConditionRef.current = filterCondition; }, [searchFields, filterCondition]); const search = useCallback( async (text: string, page: number = 1) => { try { setLoading(true); setError(null); const params = new URLSearchParams({ searchText: text, searchFields: searchFieldsRef.current.join(","), filterCondition: JSON.stringify(filterConditionRef.current), page: page.toString(), limit: pagination.limit.toString(), }); const response = await apiClient.get( `/entity-search/${tableName}?${params.toString()}` ); if (response.data.success) { setResults(response.data.data); if (response.data.pagination) { setPagination(response.data.pagination); } } else { setError(response.data.error || "검색에 실패했습니다"); } } catch (err: any) { console.error("Entity search error:", err); setError(err.response?.data?.message || "검색 중 오류가 발생했습니다"); } finally { setLoading(false); } }, [tableName, pagination.limit] ); // 디바운스된 검색 useEffect(() => { // searchText가 명시적으로 설정되지 않은 경우(null/undefined)만 건너뛰기 if (searchText === null || searchText === undefined) { return; } const timer = setTimeout(() => { // 빈 문자열("")도 검색 (전체 목록 조회) search(searchText.trim(), 1); }, 300); // 300ms 디바운스 return () => clearTimeout(timer); }, [searchText, search]); const clearSearch = useCallback(() => { setSearchText(""); setResults([]); setError(null); }, []); const loadMore = useCallback(() => { if (pagination.page * pagination.limit < pagination.total) { search(searchText, pagination.page + 1); } }, [search, searchText, pagination]); return { searchText, setSearchText, results, loading, error, pagination, search, clearSearch, loadMore, }; }