Files
frontend/apps/wr/components/lib/func/TableData.tsx
T
truthwing 05daa4200d 엑셀 상단 색상 넣는 부분 추가.
엑셀 선택시 모달 띄우는 부분 모듈화.
2025-04-30 15:57:59 +09:00

139 lines
4.6 KiB
TypeScript

import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui";
export const rightTableData = (rainChk: rainChkZodType[]) => {
// 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기
const maketotal = rainChk.map((item: rainChkZodType) => {
const selectTotal = item.guideDetails.reduce((acc: any, cur: any) => {
const code = cur.utztnUsgCd;
const fk = cur.chkgdnFk;
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; // 모든 키: `${chkgdnFk}_${utztnUsgCd}` 형태
});
console.log("maketotal", maketotal);
// 2. 누계 정보들을 하나의 객체로 합치기 (평탄화)
const flatTotalMap = Object.assign({}, ...maketotal);
// 3. rainyDetails에 누계 정보 주입
const updatedRainyDetails: any[] = [];
rainChk.forEach((rd: rainChkZodType) => {
rd.rainyDetails.forEach((rainyItem: any) => {
const key = `${rainyItem.chkgdnFk}_${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 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
) => {
console.log('chRowspanTable', makeTableData);
// rowspan된 셀 렌더링 여부 추적용
const renderedMap = new Map<string, Set<number>>();
return (
<>
{makeTableData.map((row, rowIndex) => (
<TableRow key={rowIndex}>
{headList.map((head) => {
const key = head.id;
const isMerged = head.rowSpan;
const value = row[key];
// 병합 대상이면 중복 렌더링 여부 판단
if (isMerged) {
const renderedSet = renderedMap.get(key) ?? new Set<number>();
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 (
<TableCell
key={key}
rowSpan={rowspan}
className="align-middle text-center whitespace-nowrap"
>
{key === "order" ? (
<Checkbox
checked={selectedIds.includes(row.chkgdnPk)}
onCheckedChange={(checked) =>
toggleSelection(row.chkgdnPk, checked === true)
}
></Checkbox>
) : (
value
)}
</TableCell>
);
}
// 기본 셀
return (
<TableCell
key={key}
className="text-center whitespace-nowrap"
onClick={() => handleCellClick(rowIndex, head.id)}
>
{key === "totalSplyUswtrUtztnQnt" ||
key === "totalRuseFcltUtztnQnt" ||
key === "utztnUsgCd" ? (
`${value}`
) : (
<Input
className={`${head.type === "number" ? "text-right" : "text-center"} text-3xl`}
type={head.type}
onChange={(e) => {
handleChange(rowIndex, head.id, e.target.value);
}}
value={value}
/>
)}
</TableCell>
);
})}
</TableRow>
))}
</>
);
};