import { mapSearchNavigationOptions } from "@/features/map-search/lib/map-navigation"; /** * πŸ“„ useBasicTab Hook * 검색 λͺ¨λ‹¬ 기본정보 νƒ­ ν›… * * - ν•„ν„°λ§λœ μ‹œμ„€λ¬Ό 데이터 쑰회 및 ν¬λ§·νŒ… * - ν…Œμ΄λΈ” μ…€ 클릭 μ‹œ 지도 ν”Όμ²˜ 선택 및 쀌 κΈ°λŠ₯ * - μ—‘μ…€ λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯ (ν•œκΈ€ 헀더 지원) * - CQL ν•„ν„° 생성을 ν†΅ν•œ 쿼리 쑰건 μ„€μ • * - Zustandλ₯Ό ν†΅ν•œ μƒνƒœ 관리 및 λ‘œλ”© 처리 * - 데이터 λ§€ν•‘ 및 μ½”λ“œ λ³€ν™˜ (μ‹œλ„/μ‹œκ΅°κ΅¬, μš©λ„ λ“±) * * πŸ”— μ‚¬μš© API * - 관망도 μ‹œμ„€λ¬Ό λͺ©λ‘ 쑰회: GET /api/v1/fclts (sewerage-service) */ import { requestGridExcel } from "@/shared/api/grid-export"; import { useFacilityCodeCatalog } from "@/entities/facility/lib/use-facility-code-catalog"; import { getData } from "@/shared/api/sewerage-api"; import { BASIC_TYPES } from "./basic-tab"; import { formatDisplayData } from "@/components/lib/utils/format-display-value"; import useStore from "@/entities/reference-data/model/reference-data-store"; import GisApp from "@common/business_components/ui/map/lib/gis.core"; import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { useAlertStore } from "@/shared/lib"; import useSearchModalStore from "@/features/map-search/model/search-store"; import { swagePplCqlFilters } from "./swage-ppl"; import { swagePrcsFcltCqlFilters } from "./swage-prcs-fclt"; import { swagePrcsZoneCqlFilters } from "./swage-prcs-zone"; import { fldngWtlvMapCqlFilters } from "./fldng-wtlv-map"; import { swageMhlCqlFilters } from "./swage-mhl"; import { swagePmstnCqlFilters } from "./swage-pmstn"; import { stofcbrCqlFilters } from "./stofcbr"; import { postPopupMessageAndClose } from "@/features/window-popup/lib/popup-message"; import { WINDOW_POPUP_MESSAGE_TYPE } from "@/features/window-popup/model/types"; const isPopupWindow = () => typeof window !== "undefined" && !!window.opener && window.location.pathname.startsWith("/popup/"); export default function useBasicTab() { const { MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_SHAPE, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES } = useFacilityCodeCatalog(); const alert = useAlertStore((state) => state.setMessage); const { confirm } = useConfirm(); const { basicType, tableData, curPage, todayYear, todayMonth, todayDate, setIsSearchModalOpen, setTableData, setTableCount, setIsLoading, setAppliedBasicQuery, } = useSearchModalStore(); const { ctpv, sgg } = useStore(); const fetchBasicFilteredData = async () => { // μ΄ˆκΈ°ν™” 직후에도 이전 λ Œλ”μ˜ 쑰건을 μ‚¬μš©ν•˜μ§€ μ•Šλ„λ‘ μ΅œμ‹  μŠ€ν† μ–΄ 값을 μ½λŠ”λ‹€. const { basicType, curPage } = useSearchModalStore.getState(); let cqlFilters: string[] = []; const queryParams = new URLSearchParams({ lyrTypeNm: basicType, page: `${curPage - 1}`, size: "10", }); // ν˜„μž¬ μ„œλ²„μ˜ μœ ν•˜λ°©ν–₯ 배치 보강 μ˜΅μ…˜μ€ μ‹€νŒ¨ μ‹œ λͺ©λ‘ 전체λ₯Ό 500으둜 μ€‘λ‹¨ν•œλ‹€. // 상세 μœ ν•˜λ°©ν–₯ μ‘°νšŒμ™€ 뢄리해 κΈ°λ³Έ 정보검색 λͺ©λ‘μ„ μš°μ„  정상 μ œκ³΅ν•œλ‹€. if (basicType === "tb_ms_swage_ppl") cqlFilters = swagePplCqlFilters(); // ν•˜μˆ˜κ΄€λ‘œ else if (basicType === "tb_il_swage_prcs_fclt") cqlFilters = swagePrcsFcltCqlFilters(); // ν•˜μˆ˜μ²˜λ¦¬μ‹œμ„€ else if (basicType === "tb_ms_swage_prcs_zone") cqlFilters = swagePrcsZoneCqlFilters(); // ν•˜μˆ˜μ²˜λ¦¬κ΅¬μ—­ else if (basicType === "tb_ms_fldng_wtlv_map") cqlFilters = fldngWtlvMapCqlFilters(); // μΉ¨μˆ˜ν”μ λ„ else if (basicType === "tb_ms_swage_mhl") cqlFilters = swageMhlCqlFilters(); // ν•˜μˆ˜λ§¨ν™€ else if (basicType === "tb_ms_swage_pmstn") cqlFilters = swagePmstnCqlFilters(); // ν•˜μˆ˜νŽŒν”„μž₯ else if (basicType === "tb_ms_stofcbr") cqlFilters = stofcbrCqlFilters(); // μš°μˆ˜ν† μ‹€ if (cqlFilters.length > 0) queryParams.append("cqlFiter", cqlFilters.join(" and ")); const res = await getData(`v1/fclts?${queryParams.toString()}`); const totalCount = Number(res.count ?? 0); // 🎯 각 μ•„μ΄ν…œμ„ κ°œλ³„μ μœΌλ‘œ ν¬λ§·νŒ…ν•˜λ©΄μ„œ 일련번호 μΆ”κ°€ const dataWithRowNumber = (res.data || []).map( (item: any, index: number) => { // 🎯 λ¨Όμ € 각 μ•„μ΄ν…œμ„ ν¬λ§·νŒ… const formattedItem = formatDisplayData(item); let ctpvCd = item?.ctpvNm ?? formattedItem?.ctpvNm ?? ""; let sggCd = item?.sggNm ?? formattedItem?.sggNm ?? ""; if (!ctpvCd || !sggCd) { const code = String( item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? item?.stdgCd ?? formattedItem?.stdgCd ?? "", )?.trim(); if (!ctpvCd && code) ctpvCd = code.slice(0, 2); if (!sggCd && code) sggCd = code.slice(0, 5); } const matchedMqltCode = basicType === "tb_ms_swage_ppl" ? MS_SWAGE_PPL_CODES.find( (code) => code.val === item?.mqltCd?.trim(), ) // ν•˜μˆ˜κ΄€λ‘œ 재질 : basicType === "tb_ms_swage_mhl" ? MS_SWAGE_MHL_CODES.find( (code) => code.val === item?.mqltCd?.trim(), ) // 맨홀 재질 : undefined; const matchedMhlUsgCode = MS_SWAGE_MHL_USE_CODES.find( (code) => code.val === item?.usgCd, ); // 맨홀 μš©λ„ const matchedPplShpCode = MS_SWAGE_PPL_SHAPE.find( (code) => code.val === item?.fcltyShpCd, ); // ν•˜μˆ˜κ΄€λ‘œ μ‹œμ„€λ¬Όν˜•νƒœμ½”λ“œ const ctpvNm = ctpv.find((code) => code.val.trim() === ctpvCd)?.text || item?.ctpvNm; const sggNm = sgg.find((code) => code.val.trim() === sggCd)?.text || item?.sggNm; const usgCdObj = MS_SWAGE_PPL_USE_CODES.find( (code) => code.val === item?.usgCd?.trim(), ); // μΆ”κ°€ 처리 및 일련번호 μΆ”κ°€ return { ...formattedItem, rowNumber: (curPage - 1) * 10 + index + 1, scsYn: item.scsYn === null || item.scsYn === undefined ? "N" : item?.scsYn, // scsYn이 null이면 'N'으둜 λ³€κ²½ mqltCd: matchedMqltCode ? matchedMqltCode.text : item?.mqltCd, usgCd: matchedMhlUsgCode ? matchedMhlUsgCode.text : usgCdObj ? usgCdObj.text : item?.usgCd, ctpvNm: ctpvNm ?? "-", sggNm: sggNm ?? "-", swtrmt_zone_nm: item.swtrmtZoneNm || item.swtrmt_zone_nm || "-", fcltyShpCd: matchedPplShpCode ? matchedPplShpCode.text : item?.fcltyShpCd, }; }, ); setTableData(dataWithRowNumber); setTableCount(totalCount); queryParams.delete("page"); queryParams.delete("size"); setAppliedBasicQuery({ basicType, query: queryParams.toString(), }); }; // 기본정보 ν…Œμ΄λΈ” cellClick ν•Έλ“€λŸ¬ const handleBasicCellClick = async ( index?: number | undefined, headId?: String, ) => { if (typeof index === "number") { const row = tableData[index]; if (isPopupWindow()) { postPopupMessageAndClose( WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SELECT_FEATURE, { layerNm: row.lyrTypeNm, fid: String(row.fid), }, ); return; } setIsLoading(true); const layerNm = row.lyrTypeNm; const fid = row.fid; const core = GisApp.Module.layer as any; await core.showSearchResultsFromGeoJSON(layerNm, fid, mapSearchNavigationOptions((GisApp.Module.core as any).map)); setIsLoading(false); setIsSearchModalOpen(false); // SearchModal λ‹«κΈ° } }; // 기본정보 Excel λ‹€μš΄λ‘œλ“œ ν•Έλ“€λŸ¬ const basicExcelDownload = async () => { if (tableData.length === 0) { alert("λ‹€μš΄λ‘œλ“œ ν•  Excel 파일이 μ—†μŠ΅λ‹ˆλ‹€.\n쑰회 ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."); return; } if ( !(await confirm( "파일 λ‹€μš΄λ‘œλ“œμ—λŠ” 2λΆ„ λ‚΄μ™Έμ˜ μ‹œκ°„μ΄ μ†Œμš”λ  수 μžˆμŠ΅λ‹ˆλ‹€.\n파일 λ‹€μš΄λ‘œλ“œλ₯Ό μ§„ν–‰ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?", )) ) return; await onDownload(); async function onDownload() { setIsLoading(true); try { const appliedQuery = useSearchModalStore.getState().appliedBasicQuery; if (!appliedQuery) throw new Error("ν™”λ©΄ μ‘°νšŒμ‘°κ±΄μ„ 확인할 수 μ—†μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‘°νšŒν•΄μ£Όμ„Έμš”."); const params = new URLSearchParams(appliedQuery.query); // ν˜„μž¬ νŽ˜μ΄μ§€λ‚˜ λͺ©λ‘ 배열을 보내지 μ•Šκ³  전체 쑰건과 ν‘œμ‹œλͺ…λ§Œ μ„œλ²„ μž‘μ—…μœΌλ‘œ μ „λ‹¬ν•œλ‹€. const label = BASIC_TYPES.find((type) => type.val === appliedQuery.basicType)?.text ?? "μ‹œμ„€"; await requestGridExcel("v1/facilityExports", { lyrTypeNm: appliedQuery.basicType, cqlFilter: params.get("cqlFiter") ?? "", sort: params.get("sort"), ctpvNames: Object.fromEntries(ctpv.map((item) => [String(item.val).trim(), item.text])), sggNames: Object.fromEntries(sgg.map((item) => [String(item.val).trim(), item.text])), }, `${label} 쑰회 κ²°κ³Ό_${todayYear}${todayMonth}${todayDate}.xlsx`); setIsLoading(false); } catch (error) { setIsLoading(false); console.error("Excel λ‹€μš΄λ‘œλ“œ 쀑 였λ₯˜ λ°œμƒ:", error); alert("Excel λ‹€μš΄λ‘œλ“œ 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."); } } }; return { fetchBasicFilteredData, handleBasicCellClick, basicExcelDownload }; }