187 lines
5.9 KiB
TypeScript
187 lines
5.9 KiB
TypeScript
import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
|
|
import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn";
|
|
import type { TableUpperProps } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
|
|
import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui";
|
|
|
|
export const rainChkTableData = (chkData: rainChkZodType[]) => {
|
|
// 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기
|
|
const maketotal = chkData.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}` 형태
|
|
});
|
|
|
|
// 2. 누계 정보들을 하나의 객체로 합치기 (평탄화)
|
|
const flatTotalMap = Object.assign({}, ...maketotal);
|
|
|
|
// 3. rainyDetails에 누계 정보 주입
|
|
|
|
const updatedRainyDetails: any[] = [];
|
|
chkData.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 rswtChkTableData = (chkData: rswtChkZodType[]) => {
|
|
// 1. chkgdnFk + utztnUsgCd 기준 누계 정보 만들기
|
|
const makeRswtData: any[] = [];
|
|
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<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 === "checkBox" ? (
|
|
<Checkbox
|
|
checked={selectedIds.includes(row.chkgdnPk)}
|
|
onCheckedChange={(checked) =>
|
|
toggleSelection(row.chkgdnPk, checked === true)
|
|
}
|
|
></Checkbox>
|
|
) : key === "order" ? (
|
|
++order
|
|
) : (
|
|
value
|
|
)}
|
|
</TableCell>
|
|
);
|
|
}
|
|
|
|
// 기본 셀
|
|
return (
|
|
<TableCell
|
|
key={key}
|
|
className="text-center whitespace-nowrap"
|
|
onClick={() => handleCellClick(rowIndex, head.id)}
|
|
>
|
|
{head.edit === true ? (
|
|
<Input
|
|
className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`}
|
|
type={head.type}
|
|
onChange={(e) => {
|
|
handleChange(rowIndex, head.id, e.target.value);
|
|
}}
|
|
value={value}
|
|
/>
|
|
) : (
|
|
(head.id === "totalSplyUswtrUtztnQnt" || head.id === "totalRuseFcltUtztnQnt" || head.id === "splyUswtrUtztnQnt" || head.id === "ruseFcltUtztnQnt") ? (
|
|
<span className="underline text-blue-600 cursor-pointer">
|
|
{value}
|
|
</span>
|
|
) : (
|
|
<>{value}</>
|
|
)
|
|
)}
|
|
</TableCell>
|
|
);
|
|
|
|
})}
|
|
</TableRow>
|
|
))}
|
|
</>
|
|
);
|
|
};
|
|
|
|
|
|
|
|
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
|
|
}
|
|
|
|
});
|
|
} |