import { numSize } from "@/app/store/common/code/basicCode"; import type { TableUpperProps } from "@/app/store/common/type/header"; import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn"; import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn"; import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui"; export const rainChkTableData = (chkData: rainChkZodType[]) => { // 1. chkgdnSn + utztnUsgCd 기준 누계 정보 만들기 const maketotal = chkData.map((item: rainChkZodType) => { const selectTotal = item.guideDetails.reduce((acc: any, cur: any) => { const code = cur.utztnUsgCd; const fk = cur.chkgdnSn; const key = `${fk}_${code}`; acc[key] = acc[key] || { totalSplyUswtrUtztnQnt: 0, totalRuseFcltUtztnQnt: 0, }; acc[key].totalSplyUswtrUtztnQnt += cur.splyUswtrUtztnQnt; acc[key].totalRuseFcltUtztnQnt += cur.ruseFcltUtztnQnt; return acc; }, {}); return selectTotal; // 모든 키: `${chkgdnSn}_${utztnUsgCd}` 형태 }); // 2. 누계 정보들을 하나의 객체로 합치기 (평탄화) const flatTotalMap = Object.assign({}, ...maketotal); // 3. rainyDetails에 누계 정보 주입 const updatedRainyDetails: any[] = []; chkData.forEach((rd: rainChkZodType) => { rd.rainyDetails.forEach((rainyItem: any) => { const key = `${rainyItem.chkgdnSn}_${rainyItem.utztnUsgCd}`; const totals = flatTotalMap[key] || { totalSplyUswtrUtztnQnt: 0, totalRuseFcltUtztnQnt: 0, }; updatedRainyDetails.push({ ...rd, ...rd.building, ...rainyItem, ...totals, rowspan: rd.rainyDetails?.length, }); }); }); return updatedRainyDetails; }; export const rswtChkTableData = (chkData: rswtChkZodType[]) => { // 1. chkgdnSn + utztnUsgCd 기준 누계 정보 만들기 const makeRswtData: any[] = []; if (chkData && chkData.length > 0) { chkData?.forEach((root) => { root.rswtrDetails.forEach((detail) => { let flatRswtChk = {}; const findGuide = root.guideDetails.find( (guide) => guide.utztnUsgCd === detail.utztnUsgCd ); const findPoluttion = root.rswtrPollutions.find( (polution) => polution.utztnUsgCd === detail.utztnUsgCd ); const operMngCd = root?.reuseBuilding.operMngCd; flatRswtChk = { ...root, ...detail, ...findGuide, ...findPoluttion, ...flatRswtChk, operMngCd: operMngCd, }; makeRswtData.push(flatRswtChk); }); }); } return makeRswtData; }; export const chRowspanTable = ( makeTableData: any[], headList: TableUpperProps[], handleChange: ( rowIndex: number, field: keyof (typeof makeTableData)[0], value: string | number ) => void, toggleSelection: (pk: number, checked: boolean) => void, selectedIds: number[], handleCellClick: (index: number, headId: string) => void ) => { let order = 0 // rowspan된 셀 렌더링 여부 추적용 const renderedMap = new Map>(); return ( <> {/* {makeTableData.map((row, rowIndex) => ( */} {makeTableData && makeTableData.length > 0 ? (makeTableData.map((row, rowIndex) => ( {headList .map((head) => { const key = head.id; const isMerged = head.mergeCell; const value = row[key]; // 병합 대상이면 중복 렌더링 여부 판단 if (isMerged) { const renderedSet = renderedMap.get(key) ?? new Set(); if (renderedSet.has(rowIndex)) { return null; // 이미 렌더링된 셀은 skip } const rowspan = row.rowspan ?? 1; for (let i = 0; i < rowspan; i++) { renderedSet.add(rowIndex + i); } renderedMap.set(key, renderedSet); return ( {key === "checkBox" ? ( toggleSelection(row.chkgdnSn, checked === true) } > ) : key === "order" ? ( ++order ) : ( value )} ); } // 기본 셀 return ( handleCellClick(rowIndex, head.id)} > {head.edit === true ? ( { handleChange(rowIndex, head.id, e.target.value); }} value={value || ""} disabled={!selectedIds.includes(row.chkgdnSn)} maxLength={numSize} //input type number일때 slice 처리 onInput={(e: React.ChangeEvent) => { if (head.type === 'number' && e.target.value.length > numSize) { e.target.value = e.target.value.slice(0, numSize); } }} /> ) : ( (head.id === "totalSplyUswtrUtztnQnt" || head.id === "totalRuseFcltUtztnQnt" || head.id === "splyUswtrUtztnQnt" || head.id === "ruseFcltUtztnQnt") ? ( {value} ) : ( <>{value} ) )} ); })} ))) : ( 조회된 결과가 없습니다. )} ); }; export const headVisibleChange = (headList: TableUpperProps[], isEdit: boolean) => { return headList.forEach((head) => { if (head.edit !== undefined) head.edit = isEdit; if (head.id === 'checkBox') { head.visible = false } }); } const handleChange = ( rowIndex: number, field: any, value: string | number, setInputData: (data: any) => void ) => { if (Number(value) < 0 || !Number(value)) { value = 0; } else { value = Number(value); } setInputData((prevData: any) => prevData?.map((row: any, index: number) => { if (index === rowIndex) { return { ...row, [field]: value, }; } return row; }) ); }; ; export const InputTableBody = ( chgRes: any[] | [], headList: TableUpperProps[], setInputData: (data: any[]) => void ) => { // mergeCell 처리용 const getRowSpan = (data: any[], key: string, rowIndex: number) => { if (rowIndex > 0 && data[rowIndex][key] === data[rowIndex - 1][key]) { return 0; // 이전과 같으면 셀을 그리지 않음 } let span = 1; for (let i = rowIndex + 1; i < data.length; i++) { if (data[i][key] === data[rowIndex][key]) span++; else break; } return span; }; return ( <> {chgRes.map((data, dataIndex) => { // 소계/총합계 행 판별 const isSubTotal = data["용수명"] === "소계"; const isTotal = data["구분"] === 0; const bgClass = isTotal ? "bg-[#d5e1eb] font-bold" : isSubTotal ? "bg-[#e6eef5] font-semibold" : ""; return ( {headList.map((head, headIndex) => { // 총합계 행이면 "구분"에서 colSpan=2로 병합 if ( data["구분"] === 0 && head.id === "구분" ) { return ( 총합계 ); } // 총합계(합계) 행이면 "용수명" 컬럼은 렌더링하지 않음 if ( data["구분"] === 0 && head.id === "용수명" ) { return null; } // mergeCell 처리 if (head.mergeCell) { const rowSpan = getRowSpan(chgRes, head.id, dataIndex); if (rowSpan === 0) return null; return ( {data[head.id as keyof any] ?? ""} ); } // 기본 셀 return head.edit === true && data.edit !== false ? ( handleChange(dataIndex, head.id, e.target.value, setInputData) } value={data[head.id as keyof any] ?? ""} maxLength={numSize} /> ) : (
{data[head.id as keyof any] ?? ""}
); })}
); })} ); };