Files
frontend/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx
T
2025-09-18 14:02:00 +09:00

326 lines
13 KiB
TypeScript

/**
* 처리시설 연간 운영현황 - 유량현황(모달))
*
* - 선택한 시설의 유량 정보를 하루 단위로 표로 출력해주는 모달
*/
"use client"
import FacilityTermModalHeader from "@/app/components/common/FacilityTermModalHeader";
import { useFoStore } from "@/app/store";
import type { FlowRateModalInterface, modalExcelType } from "@/app/store/flowRate";
import { downloadExcel, UITab, UiTable } from "@common/business_components/ui";
import { Button, TabsContent } from "@common/components/ui";
import { useCallback, useEffect, useRef, useState } from "react";
import type { ReturnType } from "../../../../components/common/FacilityTermModalHeader";
import { roundUp } from "@/app/store/common";
import { roundNumber } from "@/app/components/common/DataForm";
import UnderComment from "@/app/components/common/UnderComment";
const tabList = [
{ value: 'tab_term_year', label: '연간' },
{ value: 'tab_term_summer', label: '하절기' },
{ value: 'tab_term_winter', label: '동절기' },
{ value: 'tab_term_chuncheon', label: '청천시' },
{ value: 'tab_term_rain', label: '강우시' }
];
export default function FlowRateModal(props: { fcltyName: string; facilityCd: string; searchYear: string }) {
// 그리드 관련
const { Common, FlowRateModal, searchFlowRateModalList } = useFoStore((state) => state);
const { btnClass } = Common;
const [copyYearList, setCopyYearList] = useState<FlowRateModalInterface[]>([]);
const [isLoading, setIsLoading] = useState(true);
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
const {
modalFlowRateListYear,
upHeadListFlowRateModalYear,
} = FlowRateModal;
const ref = useRef<ReturnType<FlowRateModalInterface>>({
startDate: new Date(),
endDate: new Date(),
tabName: '',
filteredList: [],
});
const filterData = useCallback((returnType: ReturnType<FlowRateModalInterface>) => {
if (!returnType.filteredList) return;
// 타입을 FlowRateModalInterface[]로 강제 변환하여 타입 오류 해결
const filteredData = setFilterAfterData(returnType.filteredList as FlowRateModalInterface[]);
setCopyYearList(filteredData);
}, []);
// 필터링 된 후 최대, 최소, 평균 값 계산
const setFilterAfterData = (filteredData: FlowRateModalInterface[]) => {
if (!filteredData || filteredData.length === 0) return [];
// 쉼표가 포함된 문자열을 숫자로 변환하는 함수
const parseNumber = (value: string | number | null | undefined): number => {
if (value === null || value === undefined || value === '') return 0;
if (typeof value === 'number') return value;
return Number(value.replace(/,/g, ''));
};
let maxtotInflAmnt = 0;
let maxinflAmnt = 0;
let maxsumFlow = 0;
let maxreturnAmnt = 0;
let maxefflAmnt = 0;
let maxinfoRnDay = 0;
let maxNoProcessInflAmnt = 0;
// 초기값 설정
let mintotInflAmnt = parseNumber(filteredData[0]?.totInflAmnt);
let mininflAmnt = parseNumber(filteredData[0]?.inflAmnt);
let minsumFlow = parseNumber(filteredData[0]?.sumFlow);
let minreturnAmnt = parseNumber(filteredData[0]?.returnAmnt);
let minefflAmnt = parseNumber(filteredData[0]?.efflAmnt);
let mininfoRnDay = parseNumber(filteredData[0]?.infoRnDay && filteredData[0]?.infoRnDay.toString().trim() !== 'x' ? filteredData[0]?.infoRnDay.toString().trim() : 0);
let minNoProcessInflAmnt = 99999999;
let avgtotInflAmnt = 0;
let avginflAmnt = 0;
let avgsumFlow = 0;
let avgreturnAmnt = 0;
let avgefflAmnt = 0;
let avginfoRnDay = 0;
let avgNoProcessInflAmnt = 0;
let noProcessInflAmntCnt = 0;
filteredData.forEach((item: FlowRateModalInterface) => {
const totInflAmnt = parseNumber(item.totInflAmnt);
const inflAmnt = parseNumber(item.inflAmnt);
const sumFlow = parseNumber(item.sumFlow);
const returnAmnt = parseNumber(item.returnAmnt);
const efflAmnt = parseNumber(item.efflAmnt);
const infoRnDay = parseNumber(item.infoRnDay && item.infoRnDay.toString().trim() !== 'x' ? item.infoRnDay.toString().trim() : 0);
maxtotInflAmnt = Math.max(maxtotInflAmnt, totInflAmnt);
maxinflAmnt = Math.max(maxinflAmnt, inflAmnt);
maxsumFlow = Math.max(maxsumFlow, sumFlow);
maxreturnAmnt = Math.max(maxreturnAmnt, returnAmnt);
maxefflAmnt = Math.max(maxefflAmnt, efflAmnt);
maxinfoRnDay = Math.max(maxinfoRnDay, infoRnDay);
mintotInflAmnt = Math.min(mintotInflAmnt, totInflAmnt);
mininflAmnt = Math.min(mininflAmnt, inflAmnt);
minsumFlow = Math.min(minsumFlow, sumFlow);
minreturnAmnt = Math.min(minreturnAmnt, returnAmnt);
minefflAmnt = Math.min(minefflAmnt, efflAmnt);
mininfoRnDay = Math.min(mininfoRnDay, infoRnDay);
avgtotInflAmnt += totInflAmnt;
avginflAmnt += inflAmnt;
avgsumFlow += sumFlow;
avgreturnAmnt += returnAmnt;
avgefflAmnt += efflAmnt;
avginfoRnDay += infoRnDay;
if(item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined){
const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',',''));
avgNoProcessInflAmnt += noProcessInflAmnt;
maxNoProcessInflAmnt = Math.max(maxNoProcessInflAmnt, noProcessInflAmnt);
minNoProcessInflAmnt = Math.min(minNoProcessInflAmnt, noProcessInflAmnt);
noProcessInflAmntCnt +=1;
}
});
const newFilteredData = [
{
msrDt: '평균',
totInflAmnt: avgtotInflAmnt && avgtotInflAmnt!=0 ? roundUp((avgtotInflAmnt / filteredData.length), 0) : 0,
inflAmnt: avginflAmnt && avginflAmnt!=0 ? roundUp((avginflAmnt / filteredData.length), 0) : 0,
sumFlow: avgsumFlow && avgsumFlow!=0 ? roundUp((avgsumFlow / filteredData.length), 0) : 0,
returnAmnt: avgreturnAmnt && avgreturnAmnt!=0 ? roundUp((avgreturnAmnt / filteredData.length), 0) : 0,
efflAmnt: avgefflAmnt && avgefflAmnt!=0 ? roundUp((avgefflAmnt / filteredData.length), 0) : 0,
noProcessInflAmnt : roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0),
infoRnDay: avginfoRnDay > 0 ? roundUp((avginfoRnDay / filteredData.length), 1) : '0.0',
rainEffectDay: 0,
},
{
msrDt: '최대',
totInflAmnt: roundUp(maxtotInflAmnt, 0),
inflAmnt: roundUp(maxinflAmnt, 0),
sumFlow: roundUp(maxsumFlow, 0),
returnAmnt: roundUp(maxreturnAmnt, 0),
efflAmnt: roundUp(maxefflAmnt, 0),
noProcessInflAmnt : roundNumber(maxNoProcessInflAmnt, 0),
infoRnDay: maxinfoRnDay > 0 ? roundUp(maxinfoRnDay, 1) : '0.0',
rainEffectDay: 0,
},
{
msrDt: '최소',
totInflAmnt: roundUp(mintotInflAmnt, 0),
inflAmnt: roundUp(mininflAmnt, 0),
sumFlow: roundUp(minsumFlow, 0),
returnAmnt: roundUp(minreturnAmnt, 0),
efflAmnt: roundUp(minefflAmnt, 0),
noProcessInflAmnt : roundNumber(minNoProcessInflAmnt, 0),
infoRnDay: mininfoRnDay > 0 ? roundUp(mininfoRnDay, 1) : '0.0',
rainEffectDay: 0,
},
...filteredData
];
return newFilteredData;
}
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
await searchFlowRateModalList(props.facilityCd, props.searchYear);
} finally {
setIsLoading(false);
}
};
fetchData();
}, [props.facilityCd, props.searchYear, searchFlowRateModalList]);
if (isLoading) {
return <div>로딩 중...</div>;
}
const excelDownload = () => {
const excelDownList: modalExcelType[] = [];
if(copyYearList.length > 0){
copyYearList.forEach((item) => {
excelDownList.push({
"날짜": item.msrDt,
"총유입량(m³/일)": item.totInflAmnt,
"하수유입량(m³/일)": item.inflAmnt,
"연계처리량(m³/일)": item.sumFlow,
"총인반류수량(m³/일)": item.returnAmnt,
"방류량(m³/일)": item.efflAmnt,
/* "강우량(mm/일)": item.infoRnDay, */
});
});
}
if (excelDownList && excelDownList.length > 0) {
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 유량현황', sheetNameArray: [props.fcltyName + ' 유량현황'], headerRange: 'A1:G1' });
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
alert('다운받을 데이터가 없습니다.');
}
prevExcelListRef.current = excelDownList;
}
return (
<>
<UITab tabList={tabList} defaultValue="tab_term_year">
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
{"엑셀다운로드"}
</Button>
<TabsContent value="tab_term_year">
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
fcltyName={props.fcltyName}
tabName={"tab_term_year"}
searchYear={props.searchYear}
ref={ref}
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
</TabsContent>
<TabsContent value="tab_term_summer">
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
fcltyName={props.fcltyName}
tabName={"tab_term_summer"}
searchYear={props.searchYear}
ref={ref}
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
</TabsContent>
<TabsContent value="tab_term_winter">
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
fcltyName={props.fcltyName}
tabName={"tab_term_winter"}
searchYear={props.searchYear}
ref={ref}
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
</TabsContent>
<TabsContent value="tab_term_chuncheon">
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
fcltyName={props.fcltyName}
tabName={"tab_term_chuncheon"}
searchYear={props.searchYear}
ref={ref}
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable
headName="유량현황"
tableData={copyYearList}
headlist={upHeadListFlowRateModalYear}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => {}}
className="h-[370px]"
boldArray={[0,1,2]}
/>
</div>
</TabsContent>
<TabsContent value="tab_term_rain">
<FacilityTermModalHeader<FlowRateModalInterface>
searchList={modalFlowRateListYear}
fcltyCd={props.facilityCd}
fcltyName={props.fcltyName}
tabName={"tab_term_rain"}
searchYear={props.searchYear}
ref={ref}
queryClick={filterData}
/>
<div className="h-[370px] overflow-y-auto overflow-x-hidden">
<UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} className="h-[370px]" boldArray={[0,1,2]}/>
</div>
<UnderComment commentArray={["강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날"]} />
</TabsContent>
</UITab>
</>
);
}