사용자 검색 기능 구현
This commit is contained in:
@@ -15,20 +15,85 @@ export const useUserManagement = () => {
|
||||
// 검색 필터 상태
|
||||
const [searchFilter, setSearchFilter] = useState<UserSearchFilter>({});
|
||||
|
||||
// 검색어만 디바운싱 (500ms 지연) - searchType은 즉시 반영
|
||||
// 통합 검색어 디바운싱 (500ms 지연)
|
||||
const debouncedSearchValue = useDebounce(searchFilter.searchValue || "", 500);
|
||||
|
||||
// 고급 검색 필드들 디바운싱
|
||||
const debouncedSabun = useDebounce(searchFilter.search_sabun || "", 500);
|
||||
const debouncedCompanyName = useDebounce(searchFilter.search_companyName || "", 500);
|
||||
const debouncedDeptName = useDebounce(searchFilter.search_deptName || "", 500);
|
||||
const debouncedPositionName = useDebounce(searchFilter.search_positionName || "", 500);
|
||||
const debouncedUserId = useDebounce(searchFilter.search_userId || "", 500);
|
||||
const debouncedUserName = useDebounce(searchFilter.search_userName || "", 500);
|
||||
const debouncedTel = useDebounce(searchFilter.search_tel || "", 500);
|
||||
const debouncedEmail = useDebounce(searchFilter.search_email || "", 500);
|
||||
|
||||
// 디바운싱된 검색 필터 (useMemo로 최적화)
|
||||
const debouncedSearchFilter = useMemo(
|
||||
() => ({
|
||||
// 통합 검색
|
||||
searchValue: debouncedSearchValue,
|
||||
|
||||
// 고급 검색
|
||||
search_sabun: debouncedSabun,
|
||||
search_companyName: debouncedCompanyName,
|
||||
search_deptName: debouncedDeptName,
|
||||
search_positionName: debouncedPositionName,
|
||||
search_userId: debouncedUserId,
|
||||
search_userName: debouncedUserName,
|
||||
search_tel: debouncedTel,
|
||||
search_email: debouncedEmail,
|
||||
|
||||
// 하위 호환성
|
||||
searchType: searchFilter.searchType || "all",
|
||||
}),
|
||||
[debouncedSearchValue, searchFilter.searchType],
|
||||
[
|
||||
debouncedSearchValue,
|
||||
debouncedSabun,
|
||||
debouncedCompanyName,
|
||||
debouncedDeptName,
|
||||
debouncedPositionName,
|
||||
debouncedUserId,
|
||||
debouncedUserName,
|
||||
debouncedTel,
|
||||
debouncedEmail,
|
||||
searchFilter.searchType,
|
||||
],
|
||||
);
|
||||
|
||||
// 검색 중인지 확인 (검색어만 체크)
|
||||
const isSearching = (searchFilter.searchValue || "") !== debouncedSearchValue;
|
||||
// 검색 중인지 확인 (모든 검색 필드를 고려)
|
||||
const isSearching = useMemo(() => {
|
||||
return (
|
||||
(searchFilter.searchValue || "") !== debouncedSearchValue ||
|
||||
(searchFilter.search_sabun || "") !== debouncedSabun ||
|
||||
(searchFilter.search_companyName || "") !== debouncedCompanyName ||
|
||||
(searchFilter.search_deptName || "") !== debouncedDeptName ||
|
||||
(searchFilter.search_positionName || "") !== debouncedPositionName ||
|
||||
(searchFilter.search_userId || "") !== debouncedUserId ||
|
||||
(searchFilter.search_userName || "") !== debouncedUserName ||
|
||||
(searchFilter.search_tel || "") !== debouncedTel ||
|
||||
(searchFilter.search_email || "") !== debouncedEmail
|
||||
);
|
||||
}, [
|
||||
searchFilter.searchValue,
|
||||
debouncedSearchValue,
|
||||
searchFilter.search_sabun,
|
||||
debouncedSabun,
|
||||
searchFilter.search_companyName,
|
||||
debouncedCompanyName,
|
||||
searchFilter.search_deptName,
|
||||
debouncedDeptName,
|
||||
searchFilter.search_positionName,
|
||||
debouncedPositionName,
|
||||
searchFilter.search_userId,
|
||||
debouncedUserId,
|
||||
searchFilter.search_userName,
|
||||
debouncedUserName,
|
||||
searchFilter.search_tel,
|
||||
debouncedTel,
|
||||
searchFilter.search_email,
|
||||
debouncedEmail,
|
||||
]);
|
||||
|
||||
// 로딩 및 에러 상태
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@@ -39,52 +104,55 @@ export const useUserManagement = () => {
|
||||
const [pageSize, setPageSize] = useState(20);
|
||||
const [totalItems, setTotalItems] = useState(0);
|
||||
|
||||
// 사용자 목록 로드 (특정 검색 조건으로 호출)
|
||||
// 사용자 목록 로드 (새로운 통합 검색 방식)
|
||||
const loadUsers = useCallback(
|
||||
async (searchValue?: string, searchType?: string) => {
|
||||
async (filter?: UserSearchFilter) => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
// 백엔드 API 호출
|
||||
// 검색 파라미터 구성 (단순 검색 방식)
|
||||
// 검색 파라미터 구성
|
||||
const searchParams: Record<string, string | number | undefined> = {
|
||||
page: currentPage,
|
||||
countPerPage: pageSize,
|
||||
};
|
||||
|
||||
// 검색어가 있고 searchType이 'all'이 아닐 때만 검색 파라미터 추가
|
||||
if (searchValue && searchValue.trim() && searchType && searchType !== "all") {
|
||||
const trimmedValue = searchValue.trim();
|
||||
// 검색 조건 추가
|
||||
if (filter) {
|
||||
// 통합 검색 (우선순위 최고)
|
||||
if (filter.searchValue && filter.searchValue.trim()) {
|
||||
searchParams.search = filter.searchValue.trim();
|
||||
}
|
||||
|
||||
// 각 검색 타입별로 해당하는 백엔드 파라미터 매핑 (백엔드 MyBatis와 정확히 일치)
|
||||
switch (searchType) {
|
||||
case "sabun":
|
||||
searchParams.search_sabun = trimmedValue;
|
||||
break;
|
||||
case "company_name":
|
||||
searchParams.search_companyName = trimmedValue; // MyBatis: search_companyName
|
||||
break;
|
||||
case "dept_name":
|
||||
searchParams.search_deptName = trimmedValue; // MyBatis: search_deptName
|
||||
break;
|
||||
case "position_name":
|
||||
searchParams.search_positionName = trimmedValue; // MyBatis: search_positionName
|
||||
break;
|
||||
case "user_id":
|
||||
searchParams.search_userId = trimmedValue; // MyBatis: search_userId
|
||||
break;
|
||||
case "user_name":
|
||||
searchParams.search_userName = trimmedValue; // MyBatis: search_userName
|
||||
break;
|
||||
case "tel":
|
||||
searchParams.search_tel = trimmedValue; // MyBatis: search_tel
|
||||
break;
|
||||
case "email":
|
||||
searchParams.search_email = trimmedValue; // MyBatis: search_email
|
||||
break;
|
||||
default:
|
||||
searchParams.search_userName = trimmedValue; // 기본값
|
||||
// 고급 검색 (개별 필드별)
|
||||
if (filter.search_sabun && filter.search_sabun.trim()) {
|
||||
searchParams.search_sabun = filter.search_sabun.trim();
|
||||
}
|
||||
if (filter.search_companyName && filter.search_companyName.trim()) {
|
||||
searchParams.search_companyName = filter.search_companyName.trim();
|
||||
}
|
||||
if (filter.search_deptName && filter.search_deptName.trim()) {
|
||||
searchParams.search_deptName = filter.search_deptName.trim();
|
||||
}
|
||||
if (filter.search_positionName && filter.search_positionName.trim()) {
|
||||
searchParams.search_positionName = filter.search_positionName.trim();
|
||||
}
|
||||
if (filter.search_userId && filter.search_userId.trim()) {
|
||||
searchParams.search_userId = filter.search_userId.trim();
|
||||
}
|
||||
if (filter.search_userName && filter.search_userName.trim()) {
|
||||
searchParams.search_userName = filter.search_userName.trim();
|
||||
}
|
||||
if (filter.search_tel && filter.search_tel.trim()) {
|
||||
searchParams.search_tel = filter.search_tel.trim();
|
||||
}
|
||||
if (filter.search_email && filter.search_email.trim()) {
|
||||
searchParams.search_email = filter.search_email.trim();
|
||||
}
|
||||
|
||||
// 하위 호환성: 기존 searchType/searchValue 방식 지원
|
||||
if (!filter.searchValue && filter.searchType && filter.searchType !== "all" && searchParams.searchValue) {
|
||||
// 기존 방식 변환은 일단 제거 (통합 검색과 고급 검색만 지원)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,30 +193,41 @@ export const useUserManagement = () => {
|
||||
loadUsers();
|
||||
}, [loadUsers]);
|
||||
|
||||
// 검색어 변경 시에만 API 호출 (검색어가 있고 'all'이 아닐 때)
|
||||
// 디바운싱된 검색 조건이 변경될 때마다 API 호출
|
||||
useEffect(() => {
|
||||
if (
|
||||
debouncedSearchFilter.searchValue &&
|
||||
debouncedSearchFilter.searchValue.trim() &&
|
||||
debouncedSearchFilter.searchType !== "all"
|
||||
) {
|
||||
loadUsers(debouncedSearchFilter.searchValue, debouncedSearchFilter.searchType);
|
||||
}
|
||||
}, [debouncedSearchFilter.searchValue, loadUsers]);
|
||||
|
||||
// '전체' 선택 시에만 즉시 반영
|
||||
useEffect(() => {
|
||||
if (searchFilter.searchType === "all" && !searchFilter.searchValue) {
|
||||
loadUsers(); // 전체 목록 로드 (검색 조건 없음)
|
||||
}
|
||||
}, [searchFilter.searchType, loadUsers]);
|
||||
loadUsers(debouncedSearchFilter);
|
||||
}, [
|
||||
debouncedSearchFilter.searchValue,
|
||||
debouncedSearchFilter.search_sabun,
|
||||
debouncedSearchFilter.search_companyName,
|
||||
debouncedSearchFilter.search_deptName,
|
||||
debouncedSearchFilter.search_positionName,
|
||||
debouncedSearchFilter.search_userId,
|
||||
debouncedSearchFilter.search_userName,
|
||||
debouncedSearchFilter.search_tel,
|
||||
debouncedSearchFilter.search_email,
|
||||
loadUsers,
|
||||
]);
|
||||
|
||||
// 검색 필터 업데이트
|
||||
const updateSearchFilter = useCallback((newFilter: Partial<UserSearchFilter>) => {
|
||||
setSearchFilter((prev) => ({ ...prev, ...newFilter }));
|
||||
|
||||
// searchType이 변경되거나 searchValue가 변경될 때만 첫 페이지로 이동
|
||||
if (newFilter.searchType !== undefined || newFilter.searchValue !== undefined) {
|
||||
// 검색 조건이 변경될 때마다 첫 페이지로 이동
|
||||
const hasSearchChange = !!(
|
||||
newFilter.searchValue !== undefined ||
|
||||
newFilter.search_sabun !== undefined ||
|
||||
newFilter.search_companyName !== undefined ||
|
||||
newFilter.search_deptName !== undefined ||
|
||||
newFilter.search_positionName !== undefined ||
|
||||
newFilter.search_userId !== undefined ||
|
||||
newFilter.search_userName !== undefined ||
|
||||
newFilter.search_tel !== undefined ||
|
||||
newFilter.search_email !== undefined ||
|
||||
newFilter.searchType !== undefined
|
||||
);
|
||||
|
||||
if (hasSearchChange) {
|
||||
setCurrentPage(1);
|
||||
}
|
||||
}, []);
|
||||
|
||||
Reference in New Issue
Block a user