Files
frontend/apps/wr/components/ui/modal/chkgd/chkgdModal/chkgdModal.tsx
T

329 lines
11 KiB
TypeScript

import { useWrStore } from "@/app/store";
import type { TableUpperProps } from "@/app/store/common/type/header";
import type { splRuseWaterType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
import type { rswtrPolutionsZode } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn/headList";
import { GuideDetailsTable } from "@/components/ui/table/chkgdTable/guideDetailTable/guideDetailTable";
import { ScrollArea, Title } from "@common/business_components/ui";
import { Button } from "@common/components/ui";
import React, { useEffect, useState } from "react";
import type { z } from "zod";
export default function ChkgdModal({ type, obj, setIsModal, readonly }: { type: string; obj: any, setIsModal: (open: boolean) => void, readonly: boolean }) {
const {
rainChkgdn,
rswtChkgdn,
rainChkSttn,
rswtChkSttn,
rainChkGuidUpdate,
rwstPolAndGuideUpdate,
} = useWrStore((state) => state);
const [guidData, setGuidData] = useState<splRuseWaterType[]>();
const [headList, setHeadList] = useState<{
splHeadList: TableUpperProps[];
ruseHeadList: TableUpperProps[];
rswtDetailHeadList: TableUpperProps[];
}>({ splHeadList: [], ruseHeadList: [], rswtDetailHeadList: [] });
const [polutionData, setPolutionData] = useState<Record<string, any[]>>({
"1": [] as z.infer<typeof rswtrPolutionsZode>[],
"2": [] as z.infer<typeof rswtrPolutionsZode>[],
"3": [] as z.infer<typeof rswtrPolutionsZode>[],
"4": [] as z.infer<typeof rswtrPolutionsZode>[],
});
const [upPolutionData, setUpPolutionData] = useState<Record<string, any[]>>({
"1": [] as z.infer<typeof rswtrPolutionsZode>[],
"2": [] as z.infer<typeof rswtrPolutionsZode>[],
"3": [] as z.infer<typeof rswtrPolutionsZode>[],
"4": [] as z.infer<typeof rswtrPolutionsZode>[],
});
const [updateData, setUpdateData] = useState<splRuseWaterType[]>();
const initStats = (): z.infer<typeof rswtrPolutionsZode> => ({
grssClfgUswtr: 0,
combResdch: 0,
trbt: 0,
bod: 0,
smll: 0,
crmty: 0,
tph: 0,
tn: 0,
ph: 0,
clIonQnt: 0,
});
///현황일 경우 input 비활성화 한다.
useEffect(() => {
if (rainChkSttn.isSttn) {
setHeadList({
splHeadList: rainChkSttn.splHeadList,
ruseHeadList: rainChkSttn.ruseHeadList,
rswtDetailHeadList: type === "RNB" ? [] : rswtChkSttn.rswtDetailSttnHeadList,
});
} else {
setHeadList({
splHeadList: rainChkgdn.splHeadList,
ruseHeadList: rainChkgdn.ruseHeadList,
rswtDetailHeadList:
type === "RNB" ? [] : rswtChkgdn.rswtDetailHeadList,
});
}
}, [
rainChkSttn.isSttn,
rainChkgdn.splHeadList,
rainChkSttn.splHeadList,
rswtChkgdn.rswtDetailHeadList,
rswtChkSttn.rswtDetailSttnHeadList
]);
useEffect(() => {
const result = obj.guideDetails?.reduce((acc: any, cur: any) => {
const code = cur.utztnUsgCd;
const month = cur.ym?.slice(4); // "MM"
const ruseMonthKey = `ruse${month}`;
const splMonthKey = `spl${month}`;
const ruseValue = cur.ruseFcltUtztnQnt;
const splValue = cur.splyUswtrUtztnQnt;
// 해당 utztnUsgCd 객체가 없으면 새로 생성
let target = acc.find(
(it: { utztnUsgCd: string }) => it?.utztnUsgCd === code
);
if (!target) {
target = { utztnUsgCd: code, ruseTotal: 0, splTotal: 0 };
acc.push(target);
}
// 월별 값 누적
target[ruseMonthKey] = (target[ruseMonthKey] ?? 0) + ruseValue;
target[splMonthKey] = (target[splMonthKey] ?? 0) + splValue;
// total 누적
target.ruseTotal += ruseValue;
target.splTotal += splValue;
return acc;
}, []);
if (result) {
// '기타' 항목을 배열의 맨 뒤로 정렬합니다.
result.sort((a: splRuseWaterType, b: splRuseWaterType) => {
if (a.utztnUsgCd === "기타") return 1; // a를 b 뒤로 보냅니다.
if (b.utztnUsgCd === "기타") return -1; // b를 a 뒤로 보냅니다.
return 0; // 순서를 유지합니다.
});
}
setGuidData(result as splRuseWaterType[]);
if (obj.rswtrPollutions) {
const resultPolution: Record<string, any[]> = {
"1": [],
"2": [],
"3": [],
"4": [],
};
obj.rswtrPollutions.forEach(
(item: z.infer<typeof rswtrPolutionsZode>) => {
const nodeKey = String(item.node);
resultPolution[nodeKey]?.push(item);
}
);
// 각 노드에 대해 합계/평균 추가
Object.entries(resultPolution).forEach(([nodeKey, items]) => {
const onlyData = items as z.infer<typeof rswtrPolutionsZode>[];
if (onlyData.length === 0) return;
const total = initStats();
onlyData.forEach((item) => {
total.grssClfgUswtr += item.grssClfgUswtr;
total.combResdch += item.combResdch;
total.trbt += item.trbt;
total.bod += item.bod;
total.smll += item.smll;
total.crmty += item.crmty;
total.tph += item.tph;
total.tn += item.tn;
total.ph += item.ph;
total.clIonQnt += item.clIonQnt;
});
const average = {
utztnUsgCd: "평균",
edit: false,
grssClfgUswtr: (total.grssClfgUswtr / onlyData.length).toFixed(1),
combResdch: (total.combResdch / onlyData.length).toFixed(1),
trbt: (total.trbt / onlyData.length).toFixed(1),
bod: (total.bod / onlyData.length).toFixed(1),
smll: (total.smll / onlyData.length).toFixed(1),
crmty: (total.crmty / onlyData.length).toFixed(1),
tph: (total.tph / onlyData.length).toFixed(1),
tn: (total.tn / onlyData.length).toFixed(1),
ph: (total.ph / onlyData.length).toFixed(1),
clIonQnt: (total.clIonQnt / onlyData.length).toFixed(1),
};
if (!resultPolution[nodeKey]) {
resultPolution[nodeKey] = [];
}
// '기타' 항목을 배열의 맨 뒤로 정렬합니다.
resultPolution[nodeKey].sort((a: any, b: any) => {
if (a.utztnUsgCd === "기타") return 1; // a를 b 뒤로 보냅니다.
if (b.utztnUsgCd === "기타") return -1; // b를 a 뒤로 보냅니다.
return 0; // 순서를 유지합니다.
});
resultPolution[nodeKey].push(average);
});
setPolutionData(resultPolution);
}
}, [obj]);
const setChGuidData = (data: splRuseWaterType[]) => {
if (data.length > 0) {
setUpdateData(data);
}
};
const allDataUpdate = () => {
const realGuideDetail = obj.guideDetails;
if (updateData === undefined || updateData.length === 0) return;
realGuideDetail.map((item: any) => {
const findObj = updateData.find(
(ch: any) => ch.utztnUsgCd === item.utztnUsgCd
);
const month = item.ym?.slice(4);
if (findObj) {
const ruseMonthKey = `ruse${month}` as keyof splRuseWaterType;
const splMonthKey = `spl${month}` as keyof splRuseWaterType;
if (
findObj[ruseMonthKey] !== undefined &&
findObj[splMonthKey] !== undefined
) {
item.splyUswtrUtztnQnt = findObj[splMonthKey];
item.ruseFcltUtztnQnt = findObj[ruseMonthKey];
return item;
}
}
});
obj.guideDetails = realGuideDetail;
if (type === "RNB") {
rainChkGuidUpdate(obj);
setIsModal(false)
} else {
const polution = Object.values(upPolutionData)
.flat()
.filter((item) => item.utztnUsgCd !== "평균");
obj.rswtrPollutions = polution;
rwstPolAndGuideUpdate([obj]);
setIsModal(false)
}
};
const getPolutionData = (data: z.infer<typeof rswtrPolutionsZode>[]) => {
const getNode = Number(data[0]?.node);
setUpPolutionData((prevPolutionData) => ({
...prevPolutionData,
[getNode]: data,
}));
};
return (
<>
<div>
<div>
<div className="flex justify-between">
<Title
title={
type === "RNB"
? "빗물이용시설 " + "지도점검 결과"
: "중수도 이용시설 " + "지도점검 결과"
}
></Title>
{!rainChkSttn.isSttn ? (
<Button className="mt-8 mr-7" onClick={allDataUpdate} disabled={!readonly}>
저장
</Button>
) : (
<></>
)}
</div>
<h3 className="text-2xl font-bold text-gray-900 mt-2 ml-6">
{type === "RNB"
? `시설명 : (${obj.bdstNm})` : `시설명 : (${obj.building.bdstNm})`}
</h3>
</div>
<ScrollArea className="h-[60vh]">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
{`연간대체수이용량`}
</h3>
</div>
<GuideDetailsTable
chgRes={guidData || []}
headList={headList.splHeadList}
upheadList={type === "RNB" ? rainChkgdn.rainSplHeadNm : rswtChkgdn.rswtSplHeadNm}
type={""}
setChGuidData={(data) => {
setChGuidData(data);
}}
readonly={readonly}
/>
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
{type === "RNB" ? `연간빗물 이용량` : "연간중수도 이용량"}
</h3>
</div>
<GuideDetailsTable
chgRes={guidData || []}
headList={headList.ruseHeadList}
upheadList={type === "RNB" ? rainChkgdn.rainRuseHeadNm : rswtChkgdn.rswtRuseHeadNm}
type={""}
setChGuidData={(data) => {
setChGuidData(data);
}}
readonly={readonly}
/>
{type !== "RNB" && polutionData !== undefined ? (
<div key={"polutionData"}>
{Object.entries(polutionData).map(([key, value]) => {
const keyNum = Number(key);
return (
<React.Fragment key={`polutionData_fragment_${keyNum}`}>
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
{`연간이용수질 ${keyNum}분기`}
</h3>
</div>
<GuideDetailsTable
chgRes={value}
headList={headList?.rswtDetailHeadList}
upheadList={rswtChkgdn.rswtSplHeadNm}
type={""}
setChGuidData={(data) => {
getPolutionData(data);
}}
readonly={readonly}
/>
</React.Fragment>
);
})}
</div>
) : (
<></>
)}
</ScrollArea>
</div>
</>
);
}