326 lines
13 KiB
TypeScript
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>
|
|
</>
|
|
);
|
|
} |