import { downloadExcelWithKoreanHeaders } from '@common/business_components/ui'; import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES } from '../components/common/table'; import { getData } from "@/components/lib/api"; import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; import GisApp from "@common/business_components/ui/map/lib/gis.core"; import { confirmToast } from '@/components/ui/toast' import { toast } from "react-hot-toast"; import useSearchModalStore from '@/store/useSearchModalStore'; import useStore from '@/store/useStore'; export default function useOperationTab() { const OPERATION_TABLE_SIZE = 5; const { workType, tableData, detailTableData, curPage, detailCurPage, detailBizId, var1, var2, yearFilter, todayYear, todayMonth, todayDate, setIsSearchModalOpen, setTableData, setDetailTableData, setTableCount, setDetailTableCount, setDetailCurPage, setIsLoading, setIsDetailLoading, setIsResetDetailPage, setIsResetDetailSelection, setDetailBizId, getDateString } = useSearchModalStore(); const { BIZ_TY_CD } = useStore(); const WORK_TYPES = [ // 운영정보 '구분' 선택 목록 { val: "['200', '201', '204']", text: "보수 및 갱신" }, { val: "['100']", text: "점검 및 진단" }, { val: "['203']", text: "청소 및 준설" }, ]; const OPERATION_TABLE_HEADLIST = [ // 운영정보 - 사업 현황 { id: 'rowNumber', title: '일련번호' }, { id: "bizInfoNm", title: "사업명" }, { id: "flfmtBgngYmd", title: "수행시작일자" }, { id: "flfmtEndYmd", title: "수행종료일자" }, { id: "flfmtYr", title: "수행년도" }, { id: "bizTypeCd", title: "사업유형" }, { id: "bizAmt", title: "사업금액" }, ]; const MAINTENANACE_TABLE_HEADLIST = [ // 운영정보 - 보수 및 갱신 결과표 { id: 'rowNumber', title: '일련번호' }, { id: "fcltMngNo", title: "관리번호" }, { id: "swtrmt_zone_nm", title: "처리구역" }, { id: "usgCd", title: "용도" }, // { id: "lgalDrblyr", title: "내용연수" }, // { id: "acqsPrmpc", title: "취득금액" }, { id: "mqltCd", title: "재질" }, { id: "pdmtVl", title: "관경(mm)" }, { id: "prlgVl", title: "연장(m)" }, { id: "instlYmd", title: "설치일자" }, // { id: "instlYmd", title: "사업구분" }, ]; const CLEANING_TABLE_HEADLIST = [ // 운영정보 - 청소 및 준설 결과표 { id: 'rowNumber', title: '일련번호' }, { id: "fcltMngNo", title: "관리번호" }, { id: "swtrmt_zone_nm", title: "처리구역" }, { id: "usgCd", title: "용도" }, // { id: "lgalDrblyr", title: "내용연수" }, // { id: "acqsPrmpc", title: "취득금액" }, { id: "mqltCd", title: "재질" }, { id: "pdmtVl", title: "관경(mm)" }, { id: "prlgVl", title: "연장(m)" }, { id: "instlYmd", title: "설치일자" }, ]; const INSPECTION_TABLE_HEADLIST = [ // 운영정보 - 점검 및 진단 결과표 { id: 'rowNumber', title: '일련번호' }, { id: "fcltMngNo", title: "관리번호" }, { id: "swtrmt_zone_nm", title: "처리구역" }, { id: "usgCd", title: "용도" }, // { id: "riskEval", title: "위험평가" }, // { id: "acqsPrmpc", title: "취득금액" }, // { id: "lgalDrblyr", title: "내용연수" }, // { id: "remLife", title: "잔존수명" }, { id: "mqltCd", title: "재질" }, { id: "pdmtVl", title: "관경(mm)" }, { id: "prlgVl", title: "연장(m)" }, { id: "instlYmd", title: "설치일자" }, { id: "strc_stts_grd", title: "구조적 상태등급" }, { id: "oper_stts_grd", title: "운영적 상태등급" }, ]; const fetchOperationFilteredData = async () => { const RequestDTO: Record = { 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; // JSON.parse 사용으로 문자열 -> 배열 변환 RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"')); const params = new URLSearchParams(RequestDTO).toString(); const res = await getData(`v1/bizInfo?${params}`); 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: (curPage - 1) * OPERATION_TABLE_SIZE + index + 1, // 1부터 시작하는 일련번호 추가 bizTypeCd: matched ? matched.lwpoCdNm : item.bizTypeCd, }; }); setTableData(mappedContent || []); setTableCount(res.totalElements || 0); setDetailTableData([]); setDetailTableCount(0); }; // 운영정보 테이블 cellClick 핸들러 const handleOperationCellClick = async (index?: number | undefined, headId?: String) => { setIsResetDetailPage(true); // 페이지를 1로 초기화 setIsResetDetailSelection(true); // 선택 초기화 setIsResetDetailPage(true); // 디테일 페이지를 초기화 if (typeof index === "number") { setIsDetailLoading(true); setDetailBizId(tableData[index].bizId); setDetailCurPage(1); // 상세 페이지 초기화 try { const RequestDTO: Record = { page: `${detailCurPage - 1}`, size: `${OPERATION_TABLE_SIZE}`, bizId: tableData[index % OPERATION_TABLE_SIZE].bizId, }; RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"')); const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`); const mappedData = (res.data || []).map((item: any, detailIndex: number) => { const formattedItem = formatDisplayData(item); const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim()); const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim()); return { ...formattedItem, rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1, usgCd: usgCdObj ? usgCdObj.text : item.usgCd, mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd, swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-', }; }); setDetailTableData(mappedData); setDetailTableCount(res.count || 0); } catch (error) { console.error('운영정보 cellClick 에러:', error); } finally { setIsDetailLoading(false); setIsResetDetailPage(false); setIsResetDetailSelection(false); } } }; // 운영정보 디테일 테이블 cellClick 핸들러 const handleOperationResultCellClick = async (index?: number | undefined, headId?: String) => { if (typeof index === "number") { setIsLoading(true); const row = detailTableData[index]; 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 닫기 } }; // 운영정보 디테일 테이블 페이지네이션 핸들러 const handleOperationPageNation = async (index?: number | undefined) => { if (typeof index === "number") { setIsDetailLoading(true); try { const RequestDTO: Record = { page: `${detailCurPage - 1}`, size: `${OPERATION_TABLE_SIZE}`, bizId: String(detailBizId), }; const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`); const mappedData = (res.data || []).map((item: any, detailIndex: number) => { const formattedItem = formatDisplayData(item); const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim()); const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item?.mqltCd?.trim()); return { ...formattedItem, rowNumber: (detailCurPage - 1) * OPERATION_TABLE_SIZE + detailIndex + 1, usgCd: usgCdObj ? usgCdObj.text : item.usgCd, mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd, swtrmt_zone_nm: item.swtrmt_zone_nm ? item.swtrmt_zone_nm : '-', }; }); setDetailTableData(mappedData); setDetailTableCount(res.count || 0); } catch (error) { console.error('운영정보 페이지네이션 에러:', error); } finally { setIsDetailLoading(false); } } }; // 운영정보 Excel 다운로드 핸들러 추가 const operationExcelDownload = async () => { if (tableData.length === 0) { alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요."); return; } toast.dismiss("global-confirm-toast"); confirmToast( "파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?", onAnalysis ?? (() => { }), "text-xl font-medium text-gray-800" ); async function onAnalysis() { setIsLoading(true); try { const RequestDTO: Record = { size: '10000', }; 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; // JSON.parse 사용으로 문자열 -> 배열 변환 RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"')); const params = new URLSearchParams(RequestDTO).toString(); const res = await getData(`v1/bizInfo?${params}`); // 헤더 매핑 정의 const headerMapping: { [key: string]: string } = { 'bizInfoNm': '사업명', 'flfmtBgngYmd': '수행시작일자', 'flfmtEndYmd': '수행종료일자', 'flfmtYr': '수행년도', 'bizTypeCd': '사업유형', 'bizAmt': '사업금액(원)', }; const bizTyCdMap = new Map(BIZ_TY_CD.map(code => [code.lwpoCd, code.lwpoCdNm])); const mappedContent = (res.content || []).map((item: any) => { const formattedItem = formatDisplayData(item); return { bizInfoNm: formattedItem.bizInfoNm ?? item.bizInfoNm ?? '', flfmtBgngYmd: formattedItem.flfmtBgngYmd ?? item.flfmtBgngYmd ?? '', flfmtEndYmd: formattedItem.flfmtEndYmd ?? item.flfmtEndYmd ?? '', flfmtYr: formattedItem.flfmtYr ?? item.flfmtYr ?? '', bizTypeCd: bizTyCdMap.get(item.bizTypeCd) || item.bizTypeCd || formattedItem.bizTypeCd || '', bizAmt: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.bizAmt ?? item.bizAmt), }; }); // 선택된 행 데이터를 Excel 다운로드 형식으로 변환 const excelData = mappedContent; // 배열로 감싸서 전달 // 파일명 생성 (분석번호 기반) const label = WORK_TYPES.find((type) => type.val === workType)?.text const fileName = `${label} 사업 현황_${todayYear}${todayMonth}${todayDate}`; await downloadExcelWithKoreanHeaders({ data: excelData as JSON[], fileName: fileName, sheetNameArray: [fileName], headerRange: "A1:F1", headerMapping: headerMapping }); setIsLoading(false); } catch (error) { setIsLoading(false); console.error("Excel 다운로드 중 오류 발생:", error); alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요."); } } }; // 운영정보 결과표 Excel 다운로드 핸들러 추가 const operationResultExcelDownload = async () => { if (detailTableData.length === 0) { alert("다운로드 할 Excel 파일이 없습니다.\n조회 후 다시 시도해주세요."); return; } toast.dismiss("global-confirm-toast"); confirmToast( "파일 다운로드에는 2분 내외의 시간이 소요될 수 있습니다.\n파일 다운로드를 진행하시겠습니까?", onAnalysis ?? (() => { }), "text-xl font-medium text-gray-800" ); async function onAnalysis() { setIsLoading(true); try { const RequestDTO: Record = { size: '100', bizId: String(detailBizId), }; const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`); console.log('res', res); // 헤더 매핑 정의 const headerMapping: { [key: string]: string } = { 'fcltMngNo': '관리번호', 'swtrmt_zone_nm': '처리구역', 'usgCd': '용도', 'mqltCd': '재질', 'pdmtVl': '관경(mm)', 'prlgVl': '연장(m)', 'instlYmd': '설치일자', 'strc_stts_grd': '구조적 상태등급', 'oper_stts_grd': '운영적 상태등급', }; const usgCdMap = new Map(MS_SWAGE_PPL_USE_CODES.map(code => [code.val, code.text])); const mqltCdMap = new Map(MS_SWAGE_PPL_CODES.map(code => [code.val, code.text])); // 🎯 단일 반복문으로 최적화 - 각 아이템마다 필요한 필드만 직접 매핑 const mappedData = (res.data || []).map((item: any) => { const formattedItem = formatDisplayData(item); // trim 한 번만 수행 const trimmedUsgCd = item?.usgCd?.trim(); const trimmedMqltCd = item?.mqltCd?.trim(); // zone 값 한 번만 계산 const zone = item.swtrmtZoneNm ?? formattedItem.swtrmt_zone_nm ?? item.swtrmt_zone_nm ?? ''; // 직접 매핑 - 반복문 없이 한 번에 객체 생성 return { fcltMngNo: formattedItem.fcltMngNo ?? item.fcltMngNo ?? '', swtrmt_zone_nm: (zone === null || zone === '') ? '-' : zone, usgCd: usgCdMap.get(trimmedUsgCd) || item.usgCd || formattedItem.usgCd || '', mqltCd: mqltCdMap.get(trimmedMqltCd) || item.mqltCd || formattedItem.mqltCd || '', pdmtVl: formattedItem.pdmtVl ?? item.pdmtVl ?? '', prlgVl: formattedItem.prlgVl ?? item.prlgVl ?? '', instlYmd: formattedItem.instlYmd ?? item.instlYmd ?? '', strc_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.strc_stts_grd ?? item.strc_stts_grd), oper_stts_grd: ((v) => (v === 0 || v === '0') ? '0' : (v ?? ''))(formattedItem.oper_stts_grd ?? item.oper_stts_grd), }; }); // 선택된 행 데이터를 Excel 다운로드 형식으로 변환 const excelData = mappedData; // 배열로 감싸서 전달 // 파일명 생성 (분석번호 기반) const label = WORK_TYPES.find((type) => type.val === workType)?.text const fileName = `${label} 결과표_${todayYear}${todayMonth}${todayDate}`; await downloadExcelWithKoreanHeaders({ data: excelData as JSON[], fileName: fileName, sheetNameArray: [fileName], headerRange: "A1:I1", headerMapping: headerMapping }); setIsLoading(false); } catch (error) { setIsLoading(false); console.error("Excel 다운로드 중 오류 발생:", error); alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요."); } } }; return { WORK_TYPES, OPERATION_TABLE_HEADLIST, MAINTENANACE_TABLE_HEADLIST, CLEANING_TABLE_HEADLIST, INSPECTION_TABLE_HEADLIST, OPERATION_TABLE_SIZE, fetchOperationFilteredData, handleOperationCellClick, handleOperationResultCellClick, handleOperationPageNation, operationExcelDownload, operationResultExcelDownload }; };