244 lines
7.5 KiB
TypeScript
244 lines
7.5 KiB
TypeScript
/**
|
|
* 📄 useSearchModal Hook
|
|
* 검색 모달 훅
|
|
*
|
|
* - 탭 기반 검색 인터페이스 관리 (기본정보, 유지관리 정보, 보고서)
|
|
* - 필터링된 데이터 조회 및 포맷팅
|
|
* - 조회 버튼을 통한 데이터 검색 트리거
|
|
* - 여러 시설 보기 기능
|
|
* - Zustand를 통한 상태 관리 및 로딩 처리
|
|
* - 데이터 매핑 및 코드 변환 (사업 유형 등)
|
|
*
|
|
* 🔗 사용 API
|
|
* - 유지관리 정보 목록 조회: GET /api/v1/bizInfo (sewerage-service)
|
|
*/
|
|
import { getData } from "@/components/lib/api";
|
|
import { formatDisplayData } from "@/components/lib/utils/formatDisplayValue";
|
|
import useStore from "../../../store/useStore";
|
|
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
|
import useSearchModalStore, {
|
|
SEARCH_MODAL_DEFAULT_BASIC_TYPE,
|
|
SEARCH_MODAL_DEFAULT_WORK_TYPE,
|
|
} from "../../../store/useSearchModalStore";
|
|
import useBasicTab from "./useBasicTab";
|
|
import useOperationTab from "./useOperationTab";
|
|
import { postPopupMessageAndClose } from "@/features/windowPopup/lib/popupMessage";
|
|
import { WINDOW_POPUP_MESSAGE_TYPE } from "@/features/windowPopup/model/types";
|
|
|
|
const isPopupWindow = () =>
|
|
typeof window !== "undefined" &&
|
|
!!window.opener &&
|
|
window.location.pathname.startsWith("/popup/");
|
|
|
|
export default function useSearchModal() {
|
|
const {
|
|
activeTab,
|
|
tableData,
|
|
detailTableData,
|
|
setIsSearchModalOpen,
|
|
setShowTable,
|
|
setTableData,
|
|
setCurPage,
|
|
setIsLoading,
|
|
setIsResetPage,
|
|
setIsResetDetailPage,
|
|
setIsResetSelection,
|
|
setIsResetDetailSelection,
|
|
getDateString,
|
|
} = useSearchModalStore();
|
|
const { fetchBasicFilteredData } = useBasicTab();
|
|
const { OPERATION_TABLE_SIZE } = useOperationTab();
|
|
const { BIZ_TY_CD } = useStore();
|
|
|
|
const TABS = [
|
|
{ val: "basic", text: "기본 정보" },
|
|
{ val: "operation", text: "유지관리 정보" },
|
|
{ val: "report", text: "하수도 정비 기본계획 보고서" },
|
|
];
|
|
|
|
// 검색 API 호출 함수
|
|
const fetchFilteredData = async () => {
|
|
const {
|
|
activeTab: currentTab,
|
|
curPage,
|
|
var1,
|
|
var2,
|
|
yearFilter,
|
|
workType,
|
|
todayYear,
|
|
todayMonth,
|
|
todayDate,
|
|
setTableData,
|
|
setDetailTableData,
|
|
setTableCount,
|
|
setDetailTableCount,
|
|
setShowTable,
|
|
setIsLoading,
|
|
setIsResetSelection,
|
|
setIsResetDetailSelection,
|
|
} = useSearchModalStore.getState();
|
|
|
|
setIsLoading(true);
|
|
setIsResetSelection(true);
|
|
setIsResetDetailSelection(true);
|
|
|
|
try {
|
|
if (currentTab === "basic") {
|
|
await fetchBasicFilteredData();
|
|
} else if (currentTab === "operation") {
|
|
const requestDto: Record<string, string> = {
|
|
page: `${curPage - 1}`,
|
|
size: `${OPERATION_TABLE_SIZE}`,
|
|
};
|
|
if (var1) requestDto.bizInfoNm = var1;
|
|
if (var2 !== "0" && var2) requestDto.bizTypeCd = var2;
|
|
|
|
const startDate = getDateString(yearFilter.start, "", "", "19000101");
|
|
const endDate = getDateString(
|
|
yearFilter.end,
|
|
"",
|
|
"",
|
|
`${todayYear}${todayMonth}${todayDate}`,
|
|
);
|
|
requestDto.fromflfmtEndYmd = startDate;
|
|
requestDto.toflfmtEndYmd = endDate;
|
|
requestDto.workTypes = JSON.parse(workType.replace(/'/g, '"'));
|
|
const params = new URLSearchParams(requestDto).toString();
|
|
const res = await getData(`v1/bizInfo?${params}`);
|
|
const totalElements = Number(res.totalElements ?? 0);
|
|
|
|
const mappedContent = (res.content || []).map(
|
|
(item: any, index: number) => {
|
|
const formattedItem = formatDisplayData(item);
|
|
const matched = BIZ_TY_CD.find(
|
|
(code) => code.lwpoCd === item.bizTypeCd,
|
|
);
|
|
return {
|
|
...formattedItem,
|
|
rowNumber:
|
|
totalElements - ((curPage - 1) * OPERATION_TABLE_SIZE + index),
|
|
bizTypeCd: matched ? matched.lwpoCdNm : item.bizTypeCd,
|
|
};
|
|
},
|
|
);
|
|
|
|
setTableData(mappedContent || []);
|
|
setTableCount(totalElements);
|
|
setDetailTableData([]);
|
|
setDetailTableCount(0);
|
|
}
|
|
|
|
setShowTable(true);
|
|
setIsResetSelection(false);
|
|
} catch (err) {
|
|
console.error("API ERROR:", err);
|
|
setTableData([]);
|
|
setIsResetSelection(false);
|
|
} finally {
|
|
setIsLoading(false);
|
|
setIsResetSelection(false);
|
|
}
|
|
};
|
|
|
|
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
|
|
const handleSearch = () => {
|
|
setCurPage(1);
|
|
void fetchFilteredData();
|
|
setIsResetPage(true);
|
|
setIsResetDetailPage(true);
|
|
setIsResetSelection(false);
|
|
setIsResetDetailSelection(false);
|
|
setShowTable(true);
|
|
};
|
|
|
|
/** 현재 탭의 조건·페이지·선택을 기본값으로 복원하고 전체 기본 목록을 즉시 재조회한다. */
|
|
const handleResetSearch = () => {
|
|
const state = useSearchModalStore.getState();
|
|
const resetsBasicType =
|
|
state.activeTab === "basic" &&
|
|
state.basicType !== SEARCH_MODAL_DEFAULT_BASIC_TYPE;
|
|
const resetsWorkType =
|
|
state.activeTab === "operation" &&
|
|
state.workType !== SEARCH_MODAL_DEFAULT_WORK_TYPE;
|
|
state.resetFilters();
|
|
if (state.activeTab === "basic") {
|
|
state.setBasicType(SEARCH_MODAL_DEFAULT_BASIC_TYPE);
|
|
}
|
|
if (state.activeTab === "operation") {
|
|
state.setWorkType(SEARCH_MODAL_DEFAULT_WORK_TYPE);
|
|
}
|
|
state.setCurPage(1);
|
|
state.setDetailCurPage(1);
|
|
state.setIsResetPage(true);
|
|
state.setIsResetDetailPage(true);
|
|
state.setIsResetSelection(true);
|
|
state.setIsResetDetailSelection(true);
|
|
// 구분 변경 시 SearchModal의 자동조회 effect가 실행되므로 중복 요청을 만들지 않는다.
|
|
if (!resetsBasicType && !resetsWorkType) {
|
|
void fetchFilteredData();
|
|
}
|
|
};
|
|
|
|
// 여러 시설 보기
|
|
const viewMultipleFeature = async () => {
|
|
if (activeTab === "basic") {
|
|
if (!(tableData.length === 0)) {
|
|
if (isPopupWindow()) {
|
|
const row = tableData[0];
|
|
postPopupMessageAndClose(
|
|
WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SHOW_MULTIPLE,
|
|
{
|
|
layerNm: row.lyrTypeNm,
|
|
fids: JSON.stringify(tableData.map((item) => item.fid)),
|
|
},
|
|
);
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
|
|
const row = tableData[0];
|
|
const layerNm = row.lyrTypeNm;
|
|
const fids = tableData.map((item) => item.fid);
|
|
const core = GisApp.Module.layer as any;
|
|
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
|
|
setIsLoading(false);
|
|
setIsSearchModalOpen(false);
|
|
}
|
|
} else if (activeTab === "operation") {
|
|
if (!(detailTableData.length === 0)) {
|
|
if (isPopupWindow()) {
|
|
const row = detailTableData[0];
|
|
postPopupMessageAndClose(
|
|
WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SHOW_MULTIPLE,
|
|
{
|
|
layerNm: row.lyrTypeNm,
|
|
fids: JSON.stringify(detailTableData.map((item) => item.fid)),
|
|
},
|
|
);
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
|
|
const row = detailTableData[0];
|
|
const layerNm = row.lyrTypeNm;
|
|
const fids = detailTableData.map((item) => item.fid);
|
|
const core = GisApp.Module.layer as any;
|
|
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids);
|
|
setIsLoading(false);
|
|
setIsSearchModalOpen(false);
|
|
}
|
|
}
|
|
};
|
|
|
|
return {
|
|
TABS,
|
|
getDateString,
|
|
handleSearch,
|
|
handleResetSearch,
|
|
viewMultipleFeature,
|
|
fetchFilteredData,
|
|
};
|
|
}
|