/** * πŸ“„ useBasicTab Hook * 검색 λͺ¨λ‹¬ 기본정보 νƒ­ ν›… * * - ν•„ν„°λ§λœ μ‹œμ„€λ¬Ό 데이터 쑰회 및 ν¬λ§·νŒ… * - ν…Œμ΄λΈ” μ…€ 클릭 μ‹œ 지도 ν”Όμ²˜ 선택 및 쀌 κΈ°λŠ₯ * - μ—‘μ…€ λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯ (ν•œκΈ€ 헀더 지원) * - CQL ν•„ν„° 생성을 ν†΅ν•œ 쿼리 쑰건 μ„€μ • * - Zustandλ₯Ό ν†΅ν•œ μƒνƒœ 관리 및 λ‘œλ”© 처리 * - 데이터 λ§€ν•‘ 및 μ½”λ“œ λ³€ν™˜ (μ‹œλ„/μ‹œκ΅°κ΅¬, μš©λ„ λ“±) * * πŸ”— μ‚¬μš© API * - 관망도 μ‹œμ„€λ¬Ό λͺ©λ‘ 쑰회: GET /api/v1/fclts (sewerage-service) */ import { downloadExcelWithKoreanHeaders } from "@/shared/lib/download-excel"; import { fetchAllPages } from "@/shared/lib/fetch-all-pages"; import { MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_SHAPE, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES, FldngWtlvMapExcelCol, MsSwagePplExcelCol, SwtrmtFcltExcelCol, SwtrmtPrcsZoneExcelCol, MsSwageMhlExcelCol, ExclnSewagePumpExcelCol, stofcbrExcelCol, } from "../components/common/table"; import { getData } from "@/components/lib/api"; import { BASIC_TYPES } from "./basicTab"; import { formatDisplayData } from "@/components/lib/utils/formatDisplayValue"; import useStore from "@/store/useStore"; 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 "@/store/useSearchModalStore"; import { swagePplCqlFilters } from "./swagePpl"; import { swagePrcsFcltCqlFilters } from "./swagePrcsFclt"; import { swagePrcsZoneCqlFilters } from "./swagePrcsZone"; import { fldngWtlvMapCqlFilters } from "./fldngWtlvMap"; import { swageMhlCqlFilters } from "./swageMhl"; import { swagePmstnCqlFilters } from "./swagePmstn"; import { stofcbrCqlFilters } from "./stofcbr"; 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/"); // Excel 열에 ν¬ν•¨λ˜μ§€ μ•ŠλŠ” ν™”λ©΄μš© μœ ν•˜λ°©ν–₯ 보강은 μ œμ™Έν•˜κ³  μ„œλ²„κ°€ 일괄 병합할 수 μžˆλŠ” 크기둜 μˆœνšŒν•œλ‹€. const BASIC_EXCEL_BATCH_SIZE = 2_000; export default function useBasicTab() { 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", }); if (basicType === "tb_ms_swage_ppl") queryParams.set("includeFlowDirectionBasis", "true"); 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: totalCount - ((curPage - 1) * 10 + index), 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); 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 appliedBasicType = appliedQuery.basicType; const queryParams = new URLSearchParams(appliedQuery.query); if (appliedBasicType === "tb_ms_swage_ppl") { queryParams.delete("includeFlowDirectionBasis"); } let headerMapping: { [key: string]: string } = {}; let headerRange: string = "A1:F1"; switch (appliedBasicType) { case "tb_ms_swage_ppl": { // ν•˜μˆ˜κ΄€λ‘œ headerMapping = MsSwagePplExcelCol; headerRange = "A1:Q1"; break; } case "tb_il_swage_prcs_fclt": { // ν•˜μˆ˜μ²˜λ¦¬μ‹œμ„€ headerMapping = SwtrmtFcltExcelCol; headerRange = "A1:J1"; break; } case "tb_ms_swage_prcs_zone": { // ν•˜μˆ˜μ²˜λ¦¬κ΅¬μ—­ headerMapping = SwtrmtPrcsZoneExcelCol; headerRange = "A1:D1"; break; } case "tb_ms_fldng_wtlv_map": { // μΉ¨μˆ˜ν”μ λ„ headerMapping = FldngWtlvMapExcelCol; headerRange = "A1:O1"; break; } case "tb_ms_swage_mhl": { // ν•˜μˆ˜λ§¨ν™€ headerMapping = MsSwageMhlExcelCol; headerRange = "A1:J1"; break; } case "tb_ms_swage_pmstn": { // ν•˜μˆ˜νŽŒν”„μž₯ headerMapping = ExclnSewagePumpExcelCol; headerRange = "A1:J1"; break; } case "tb_ms_stofcbr": { // μš°μˆ˜ν† μ‹€ headerMapping = stofcbrExcelCol; headerRange = "A1:H1"; break; } } const res = await fetchAllPages({ batchSize: BASIC_EXCEL_BATCH_SIZE, fetchPage: (page, size) => { const pageParams = new URLSearchParams(queryParams); pageParams.set("page", String(page)); pageParams.set("size", String(size)); return getData(`v1/fclts?${pageParams.toString()}`); }, getItems: (page) => (Array.isArray(page?.data) ? page.data : []), getTotal: (page) => Number(page?.count ?? 0), }); const mhlUsgCdMap = new Map( MS_SWAGE_MHL_USE_CODES.map((code) => [code.val?.trim(), code.text]), ); const pplUsgCdMap = new Map( MS_SWAGE_PPL_USE_CODES.map((code) => [code.val?.trim(), code.text]), ); const pplMqltCdMap = new Map( MS_SWAGE_PPL_CODES.map((code) => [code.val?.trim(), code.text]), ); const pplShpCdMap = new Map( MS_SWAGE_PPL_SHAPE.map((code) => [code.val?.trim(), code.text]), ); // κ΄€λ‘œ μ‹œμ„€λ¬Όν˜•νƒœμ½”λ“œ const ctpvMap = new Map( ctpv.map((code) => [code.val?.trim(), code.text]), ); const sggMap = new Map( sgg.map((code) => [code.val?.trim(), code.text]), ); let mappedContent = res.items.map((item: any) => { const formattedItem = formatDisplayData(item); let ctpvCd = item?.ctpvCd ?? formattedItem?.ctpvCd ?? ""; let sggCd = item?.sggCd ?? formattedItem?.sggCd ?? ""; 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); } // trim ν•œ 번만 μˆ˜ν–‰ const trimmedUsgCd = item?.usgCd?.trim(); // const trimmedMqltCd = item?.mqltCd?.trim(); switch (appliedBasicType) { case "tb_ms_swage_ppl": { // ν•˜μˆ˜κ΄€λ‘œ return { fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? "-", instMngNo: formattedItem.instMngNo ?? item.instMngNo ?? "-", ctpvNm: ctpvMap.get(ctpvCd) ?? item.ctpvNm ?? "-", sggNm: sggMap.get(sggCd) ?? item.sggNm ?? "-", swtrmt_zone_nm: formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? "-", instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? "-", usgCd: pplUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || "-", pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? "-", prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? "-", tmptDpth: formattedItem.tmptDpth ?? item.tmptDpth ?? "-", tmptMhlMngNo: formattedItem.tmptMhlMngNo ?? item.tmptMhlMngNo ?? "-", scendDpth: formattedItem.scendDpth ?? item.scendDpth ?? "-", scendMhlMngNo: formattedItem.scendMhlMngNo ?? item.scendMhlMngNo ?? "-", vrtcLen: formattedItem.vrtcLen ?? item.vrtcLen ?? "-", wdthLen: formattedItem.wdthLen ?? item.wdthLen ?? "-", fcltyShpCd: pplShpCdMap.get(item?.fcltyShpCd?.trim()) || item.fcltyShpCd || formattedItem.fcltyShpCd || "-", mqltCd: pplMqltCdMap.get(item?.mqltCd?.trim()) || item.mqltCd || formattedItem.mqltCd || "-", }; } case "tb_il_swage_prcs_fclt": { // ν•˜μˆ˜μ²˜λ¦¬μ‹œμ„€ return { swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? "-", fcltCpct: formattedItem.fcltCpct ?? item.fcltCpct ?? "-", rgnExpln: formattedItem.rgnExpln ?? item.rgnExpln ?? "-", oprtngStrtYmd: formattedItem.oprtngStrtYmd ?? item.oprtngStrtYmd ?? "-", laeNm: formattedItem.laeNm ?? item.laeNm ?? "-", sareaNm: formattedItem.sareaNm ?? item.sareaNm ?? "-", rvrNm: formattedItem.rvrNm ?? item.rvrNm ?? "-", dschgWtstNm: formattedItem.dschgWtstNm ?? item.dschgWtstNm ?? "-", swtrmtPpltnCnt: formattedItem.swtrmtPpltnCnt ?? item.swtrmtPpltnCnt ?? "-", rprsMsrcCn: formattedItem.rprsMsrcCn ?? item.rprsMsrcCn ?? "-", }; } case "tb_ms_swage_prcs_zone": { // ν•˜μˆ˜μ²˜λ¦¬κ΅¬μ—­ return { swtrmtZoneNm: formattedItem.swtrmtZoneNm ?? item.swtrmtZoneNm ?? "-", ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? "-", sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? "-", swtrmtFcltNm: formattedItem.swtrmtFcltNm ?? item.swtrmtFcltNm ?? "-", }; } case "tb_ms_fldng_wtlv_map": { // μΉ¨μˆ˜ν”μ λ„ return { fldngYr: formattedItem.fldngYr ?? item.fldngYr ?? "-", fldngDstrNm: formattedItem.fldngDstrNm ?? item.fldngDstrNm ?? "-", ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? "-", sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? "-", bgngYmd: formattedItem.bgngYmd ?? item.bgngYmd ?? "-", fldngBgngHm: formattedItem.fldngBgngHm ?? item.fldngBgngHm ?? "-", endYmd: formattedItem.endYmd ?? item.endYmd ?? "-", fldngEndHm: formattedItem.fldngEndHm ?? item.fldngEndHm ?? "-", fldngHr: formattedItem.fldngHr ?? item.fldngHr ?? "-", fldngDstrctNm: formattedItem.fldngDstrctNm ?? item.fldngDstrctNm ?? "-", fldngCsDtlCd: formattedItem.fldngCsDtlCd ?? item.fldngCsDtlCd ?? "-", avgFldngWtlv: formattedItem.avgFldngWtlv ?? item.avgFldngWtlv ?? "-", fldngArea: formattedItem.fldngArea ?? item.fldngArea ?? "-", exmnYr: formattedItem.exmnYr ?? item.exmnYr ?? "-", damAmt: formattedItem.damAmt ?? item.damAmt ?? "-", }; } case "tb_ms_swage_mhl": { // ν•˜μˆ˜λ§¨ν™€ return { fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? "-", ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? "-", sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? "-", instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? "-", usgCd: mhlUsgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || "-", swageMhlDiamVl: formattedItem.swageMhlDiamVl ?? item.swageMhlDiamVl ?? "-", wdthLen: formattedItem.wdthLen ?? item.wdthLen ?? "-", vrtcLen: formattedItem.vrtcLen ?? item.vrtcLen ?? "-", altdVl: formattedItem.altdVl ?? item.altdVl ?? "-", dpthlVl: formattedItem.dpthlVl ?? item.dpthlVl ?? "-", }; } case "tb_ms_swage_pmstn": { // ν•˜μˆ˜νŽŒν”„μž₯ return { fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? "-", ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? "-", sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? "-", swagePmstnNm: formattedItem.swagePmstnNm ?? item.swagePmstnNm ?? "-", instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? "-", dailyPrcsCpct: formattedItem.dailyPrcsCpct ?? item.dailyPrcsCpct ?? "-", maxImpndCpct: formattedItem.maxImpndCpct ?? item.maxImpndCpct ?? "-", altdVl: formattedItem.altdVl ?? item.altdVl ?? "-", wtlvVl: formattedItem.wtlvVl ?? item.wtlvVl ?? "-", exclnWpmpAbltVl: formattedItem.exclnWpmpAbltVl ?? item.exclnWpmpAbltVl ?? "-", }; } case "tb_ms_stofcbr": { // μš°μˆ˜ν† μ‹€ return { fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? "-", mapshtNo: formattedItem.mapshtNo ?? item.mapshtNo ?? "-", ctpvNm: ctpvMap.get(ctpvCd) ?? formattedItem.ctpvNm ?? "-", sggNm: sggMap.get(sggCd) ?? formattedItem.sggNm ?? "-", instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? "-", worflwWallHgt: formattedItem.worflwWallHgt ?? item.worflwWallHgt ?? "-", swageMhlMngNo: formattedItem.swageMhlMngNo ?? item.swageMhlMngNo ?? "-", drtnAngl: formattedItem.drtnAngl ?? item.drtnAngl ?? "-", }; } } }); // μ„ νƒλœ ν–‰ 데이터λ₯Ό Excel λ‹€μš΄λ‘œλ“œ ν˜•μ‹μœΌλ‘œ λ³€ν™˜ const excelData = mappedContent; // λ°°μ—΄λ‘œ κ°μ‹Έμ„œ 전달 // 파일λͺ… 생성 (λΆ„μ„λ²ˆν˜Έ 기반) const label = BASIC_TYPES.find( (type) => type.val === appliedBasicType, )?.text; const fileName = `${label} 쑰회 κ²°κ³Ό_${todayYear}${todayMonth}${todayDate}`; await downloadExcelWithKoreanHeaders({ data: excelData as unknown as JSON[], fileName: fileName, sheetNameArray: [fileName], headerRange: headerRange, headerMapping: headerMapping, }); setIsLoading(false); } catch (error) { setIsLoading(false); console.error("Excel λ‹€μš΄λ‘œλ“œ 쀑 였λ₯˜ λ°œμƒ:", error); alert("Excel λ‹€μš΄λ‘œλ“œ 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."); } } }; return { fetchBasicFilteredData, handleBasicCellClick, basicExcelDownload }; }