Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b6e8ceedb | ||
|
|
b4e3d922b1 | ||
|
|
a028b6ae8b | ||
|
|
ad0803f405 | ||
|
|
03675aaa60 | ||
|
|
c0c19c0425 | ||
|
|
214d283366 | ||
|
|
7d95ddf6a5 | ||
|
|
a19c5c269a | ||
|
|
6102e0af6b | ||
|
|
225bae08d3 | ||
|
|
d8b5abb12f | ||
|
|
d9a3da96bb | ||
|
|
87d1f33c05 | ||
|
|
d68c6c151c | ||
|
|
dfb910f270 | ||
|
|
ddf3a5cfa0 | ||
|
|
5976b35c90 | ||
|
|
6b204fce15 | ||
|
|
f731d0f9f0 | ||
|
|
e231d0c4be | ||
|
|
e4328a2ed4 | ||
|
|
069e489d03 | ||
|
|
990dffc11c | ||
|
|
b4140d6457 | ||
|
|
91af5fd27c | ||
|
|
0bb16f9795 | ||
|
|
be7efb2ad0 | ||
|
|
fbd9575df7 | ||
|
|
14608cca4d | ||
|
|
0dab113a3f | ||
|
|
95fc7a22dc | ||
|
|
4c955beff2 | ||
|
|
ae41ea100c | ||
|
|
07e34beca1 | ||
|
|
87d8ddef98 | ||
|
|
8b29d02880 | ||
|
|
ae97a48ba2 | ||
|
|
65d2cbd732 | ||
|
|
db70ba56c6 | ||
|
|
3fa1c526fe | ||
|
|
992893510e | ||
|
|
5fe4bc94da | ||
|
|
c22e07bc16 | ||
|
|
5f302a5711 | ||
|
|
cc749c0c24 | ||
|
|
18ec5c937f | ||
|
|
bd6dfd31fd | ||
|
|
e4f4f70bc9 | ||
|
|
5aaa55d0c9 | ||
|
|
8b1e8ae2eb | ||
|
|
5a3ef19e5d | ||
|
|
01cb48e5b6 | ||
|
|
ea7536bea3 | ||
|
|
2356c10d34 | ||
|
|
8b2dd27a79 | ||
|
|
114293bb00 | ||
|
|
e0171a5a28 | ||
|
|
d7db174c1d | ||
|
|
079542cf74 | ||
|
|
43f210a141 | ||
|
|
5015b8e0d9 | ||
|
|
4d0c0ad48c | ||
|
|
7db61928b1 | ||
|
|
3dae039765 | ||
|
|
35ff13fb38 | ||
|
|
231c0c2940 | ||
|
|
a92f567e5c | ||
|
|
ff9d373fcd | ||
|
|
c111c2c084 | ||
|
|
2d5a08a271 | ||
|
|
9a8abee77c | ||
|
|
4c30c2fa47 | ||
|
|
0cca1c8dbe | ||
|
|
def7b2b01c | ||
|
|
4891725f68 |
@@ -0,0 +1,12 @@
|
||||
NEXT_PUBLIC_SITE_ID = FO
|
||||
NEXT_PUBLIC_PORT = 11300
|
||||
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||
NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
|
||||
@@ -0,0 +1,13 @@
|
||||
NEXT_PUBLIC_SITE_ID = FO
|
||||
NEXT_PUBLIC_PORT = 3000
|
||||
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
|
||||
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
|
||||
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
|
||||
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
|
||||
NEXT_PUBLIC_CLAIM_NAME = Authorization
|
||||
NEXT_PUBLIC_AUTH_USER_ID = token-id
|
||||
NEXT_PUBLIC_ACCESS_TOKEN = access-token
|
||||
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
|
||||
|
||||
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
|
||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성 PC 서버 API
|
||||
@@ -0,0 +1,41 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
#.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
@@ -0,0 +1,12 @@
|
||||
const DEV_PORT_COMMON = "11081";
|
||||
const DEV_PORT_FO = "11082";
|
||||
const DEV_PORT_WR = "11080";
|
||||
|
||||
export const LOCAL_URL_COMMON = `http://192.168.1.129:${DEV_PORT_COMMON}/api/v1`;
|
||||
export const DEV_URL_COMMON = `http://con.mind-one.co.kr:${DEV_PORT_COMMON}/api/v1`;
|
||||
|
||||
export const LOCAL_URL_FO = `http://192.168.1.129:${DEV_PORT_FO}/api/v1`;
|
||||
export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_FO}/api/v1`;
|
||||
|
||||
export const LOCAL_URL_WR = `http://192.168.1.129:${DEV_PORT_WR}/api/v1`;
|
||||
export const DEV_URL_WR = `http://con.mind-one.co.kr:${DEV_PORT_WR}/api/v1`;
|
||||
@@ -0,0 +1 @@
|
||||
export * from './env';
|
||||
@@ -0,0 +1,79 @@
|
||||
import { DEV_URL_COMMON, DEV_URL_FO, DEV_URL_WR } from "./config/env";
|
||||
|
||||
export const getFetch = async (part : string, url: string) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : part === "wr" ? DEV_URL_WR+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl , {
|
||||
method: "GET",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
}
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
const res = await response.json()
|
||||
return res;
|
||||
}
|
||||
|
||||
export const getFetchAreaList = async (url: string) => {
|
||||
const response = await fetch(url , {
|
||||
method: "GET",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
}
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
const res = await response.json()
|
||||
return res;
|
||||
}
|
||||
|
||||
export const postFetch = async (part : string, url: string, params: unknown) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
export const putFetch = async (part : string, url: string, params: unknown) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
export const deleteFetch = async (part : string, url: string, params: unknown) => {
|
||||
let reqUrl = "";
|
||||
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
if(!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
type DataFormProps = {
|
||||
type: string;
|
||||
column: string;
|
||||
item: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export default function DataForm({ type, column, item }: DataFormProps) {
|
||||
if(item) {
|
||||
const value = item[column];
|
||||
switch(type){
|
||||
case 'date':
|
||||
if(value && typeof value === 'string' && value.length >= 8)
|
||||
item[column] = value.substring(0, 4) + "-" + value.substring(4, 6) + "-" + value.substring(6, 8);
|
||||
break;
|
||||
case 'number':
|
||||
if(value && value != '') {
|
||||
item[column] = value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
case 'float1':
|
||||
if(value) {
|
||||
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 10) / 10).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
case 'float2':
|
||||
if(value) {
|
||||
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 100) / 100).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
case 'float3':
|
||||
if(value) {
|
||||
item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1000) / 1000).split('.').map((part, index) =>
|
||||
index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part
|
||||
).join('.')
|
||||
: String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
import { useFoStore } from '@/app/store';
|
||||
import { DatePickerRange, SelectBox } from '@common/business_components/ui';
|
||||
import ListDiv from '@common/business_components/ui/list_div';
|
||||
import { Table, TableCell, TableHead, TableRow } from '@common/components/ui';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
type FacilityTermModalHeaderProps<T extends { msrDt: string }> = {
|
||||
fcltyCd : string;
|
||||
fcltyName: string;
|
||||
tabName: string;
|
||||
searchYear: string;
|
||||
searchList: T[];
|
||||
ref: React.RefObject<ReturnType<T>>;
|
||||
queryClick:(returnType:ReturnType<T>) => void;
|
||||
}
|
||||
|
||||
export type ReturnType<T> = {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
tabName: string;
|
||||
filteredList: T[];
|
||||
}
|
||||
|
||||
export default function FacilityTermModalHeader<T extends { msrDt: string }>({
|
||||
searchList,
|
||||
fcltyName,
|
||||
tabName,
|
||||
searchYear,
|
||||
queryClick,
|
||||
ref
|
||||
}: FacilityTermModalHeaderProps<T & { msrDt: string }>) {
|
||||
const {Common} = useFoStore((state) => state);
|
||||
const { selectFlowPanel } = Common;
|
||||
const [startDate, setStartDate] = useState<Date>(new Date(Number(searchYear), 0, 1));
|
||||
const [endDate, setEndDate] = useState<Date>(new Date(Number(searchYear), 11, 31));
|
||||
const startPickerRef = useRef<HTMLDivElement>(null);
|
||||
const endPickerRef = useRef<HTMLDivElement>(null);
|
||||
const [flowPanel, setFlowPanel] = useState<string>(selectFlowPanel[0]?.val ?? '00');
|
||||
const [copySearchList, setCopySearchList] = useState<T[]>(searchList);
|
||||
const [standSearchList, setStandSearchList] = useState<T[]>(searchList);
|
||||
|
||||
const isDateInRanges = (date: Date) => {
|
||||
const standYear = parseInt(searchYear);
|
||||
const dateRanges:{start:Date, end:Date}[] = [];
|
||||
|
||||
if (tabName.includes("_summer")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 5, 1),
|
||||
end: new Date(standYear, 7, 31)
|
||||
});
|
||||
} else if (tabName.includes("_winter")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 1, 28)
|
||||
});
|
||||
} else {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 11, 31)
|
||||
});
|
||||
}
|
||||
|
||||
return dateRanges.some(range => {
|
||||
const start = new Date(range.start);
|
||||
const end = new Date(range.end);
|
||||
return date >= start && date <= end;
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let startDate = new Date(Number(searchYear), 0, 1);
|
||||
let endDate = new Date(Number(searchYear), 11, 31);
|
||||
|
||||
if(tabName.includes("_summer")) {
|
||||
startDate = new Date(Number(searchYear), 5, 1);
|
||||
endDate = new Date(Number(searchYear), 7, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else if (tabName.includes("_winter")) {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 1, 28);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 11, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
}
|
||||
|
||||
let filteredData: T[] = [];
|
||||
|
||||
if(tabName.includes("_rain")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
|
||||
if(flowPanel === '1') {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay>0 && infoRnDay < 3;
|
||||
} else if(flowPanel === '2'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
|
||||
} else if(flowPanel === '3'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20;
|
||||
} else if(flowPanel === '4'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30;
|
||||
} else if(flowPanel === '5'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40;
|
||||
} else if(flowPanel === '6'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50;
|
||||
} else if(flowPanel === '7'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60;
|
||||
} else if(flowPanel === '8'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60;
|
||||
} else {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (infoRnDay>0 || rainEffectDay ===1);
|
||||
}
|
||||
});
|
||||
} else if(tabName.includes("_chuncheon")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay==0;
|
||||
});
|
||||
} else {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
}
|
||||
|
||||
setCopySearchList(filteredData);
|
||||
setStandSearchList(filteredData);
|
||||
}, [searchList, searchYear, tabName, flowPanel]);
|
||||
|
||||
const handleStartDateSelect = (day: Date | undefined) => {
|
||||
if(day && day > endDate) {
|
||||
alert('종료일은 시작일 이전일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? startDate;
|
||||
setStartDate(selectedDate);
|
||||
const button = startPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = standSearchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const handleEndDateSelect = (day: Date | undefined) => {
|
||||
if(day && day < startDate) {
|
||||
alert('종료일은 시작일 이후일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? endDate;
|
||||
setEndDate(selectedDate);
|
||||
const button = endPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = standSearchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const fncSetFilteredList = useCallback(() => {
|
||||
queryClick({
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
tabName: tabName,
|
||||
filteredList: copySearchList
|
||||
});
|
||||
}, [queryClick, startDate, endDate, tabName, copySearchList]);
|
||||
|
||||
useEffect(() => {
|
||||
fncSetFilteredList();
|
||||
}, [fncSetFilteredList]);
|
||||
|
||||
useEffect(() => {
|
||||
if(ref && ref.current) {
|
||||
const customRef = ref.current;
|
||||
customRef.startDate = startDate;
|
||||
customRef.endDate = endDate;
|
||||
customRef.tabName = tabName;
|
||||
customRef.filteredList = copySearchList;
|
||||
}
|
||||
}, [startDate, endDate, tabName, copySearchList, ref]);
|
||||
|
||||
return (
|
||||
<ListDiv className="!h-[80px]">
|
||||
<div className="!m-[0.5rem] max-h-[40rem] overflow-auto">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="!h-[20px]">
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
{tabName === "tab_term_rain" ? <TableCell className="w-[300px]">{fcltyName}</TableCell> :
|
||||
<TableCell className="w-[380px]">{fcltyName}</TableCell>}
|
||||
{tabName === "tab_term_rain" && (
|
||||
<>
|
||||
<TableHead className="w-[120px]">{'강수구분'}</TableHead>
|
||||
<TableCell className="w-[250px]">
|
||||
<div className="justify-center">
|
||||
<SelectBox
|
||||
selectArray={selectFlowPanel}
|
||||
value={flowPanel}
|
||||
onSelectValue={(val) => setFlowPanel(val.toString())}
|
||||
className="mx-3 w-[150px]"
|
||||
label=""
|
||||
selectClass="w-full p-1 border rounded bg-white"
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</>
|
||||
)}
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<div ref={startPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={startDate}
|
||||
onSelect={(date) => handleStartDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={startDate}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<div ref={endPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={endDate}
|
||||
onSelect={(date) => handleEndDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
import { useFoStore } from '@/app/store';
|
||||
import { SelectBox } from '@common/business_components/ui';
|
||||
import ListDiv from '@common/business_components/ui/list_div';
|
||||
import { DatePicker, Table, TableCell, TableHead, TableRow } from '@common/components/ui';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
type FacilityTermModalHeaderProps<T extends { msrDt: string }> = {
|
||||
fcltyCd : string;
|
||||
fcltyName: string;
|
||||
tabName: string;
|
||||
searchYear: string;
|
||||
searchList: T[];
|
||||
ref: React.RefObject<ReturnType<T>>;
|
||||
queryClick:(returnType:ReturnType<T>) => void;
|
||||
}
|
||||
|
||||
export type ReturnType<T> = {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
tabName: string;
|
||||
filteredList: T[];
|
||||
}
|
||||
|
||||
export default function FacilityTermModalHeaderMonth<T extends { msrDt: string }>({
|
||||
searchList,
|
||||
fcltyName,
|
||||
tabName,
|
||||
searchYear,
|
||||
queryClick,
|
||||
ref
|
||||
}: FacilityTermModalHeaderProps<T & { msrDt: string }>) {
|
||||
const {Common} = useFoStore((state) => state);
|
||||
const { selectFlowPanel } = Common;
|
||||
const [startDate, setStartDate] = useState<Date>(new Date(Number(searchYear), 0, 1));
|
||||
const [endDate, setEndDate] = useState<Date>(new Date(Number(searchYear), 11, 31));
|
||||
const startPickerRef = useRef<HTMLDivElement>(null);
|
||||
const endPickerRef = useRef<HTMLDivElement>(null);
|
||||
const [flowPanel, setFlowPanel] = useState<string>(selectFlowPanel[0]?.val ?? '00');
|
||||
const [copySearchList, setCopySearchList] = useState<T[]>(searchList);
|
||||
|
||||
/* const isDateInRanges = (date: Date) => {
|
||||
const standYear = parseInt(searchYear);
|
||||
const dateRanges = [];
|
||||
|
||||
if (tabName.includes("_summer")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 5, 1),
|
||||
end: new Date(standYear, 7, 31)
|
||||
});
|
||||
} else if (tabName.includes("_winter")) {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 1, 28)
|
||||
});
|
||||
} else {
|
||||
dateRanges.push({
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 11, 31)
|
||||
});
|
||||
}
|
||||
|
||||
return dateRanges.some(range => {
|
||||
const start = new Date(range.start);
|
||||
const end = new Date(range.end);
|
||||
return date >= start && date <= end;
|
||||
});
|
||||
}; */
|
||||
|
||||
useEffect(() => {
|
||||
let startDate = new Date(Number(searchYear), 0, 1);
|
||||
let endDate = new Date(Number(searchYear), 11, 31);
|
||||
|
||||
if(tabName.includes("_summer")) {
|
||||
startDate = new Date(Number(searchYear), 5, 1);
|
||||
endDate = new Date(Number(searchYear), 7, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else if (tabName.includes("_winter")) {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 1, 28);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
} else {
|
||||
startDate = new Date(Number(searchYear), 0, 1);
|
||||
endDate = new Date(Number(searchYear), 11, 31);
|
||||
setStartDate(startDate);
|
||||
setEndDate(endDate);
|
||||
}
|
||||
|
||||
let filteredData: T[] = [];
|
||||
|
||||
if(tabName.includes("_rain")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
|
||||
|
||||
if(flowPanel === '1') {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay>0 && infoRnDay < 3;
|
||||
} else if(flowPanel === '2'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
|
||||
} else if(flowPanel === '3'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20;
|
||||
} else if(flowPanel === '4'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30;
|
||||
} else if(flowPanel === '5'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40;
|
||||
} else if(flowPanel === '6'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50;
|
||||
} else if(flowPanel === '7'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60;
|
||||
} else if(flowPanel === '8'){
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60;
|
||||
} else {
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (infoRnDay>0 || rainEffectDay ===1);
|
||||
}
|
||||
});
|
||||
} else if(tabName.includes("_chuncheon")) {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
|
||||
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay==0;
|
||||
});
|
||||
} else {
|
||||
filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
}
|
||||
|
||||
setCopySearchList(filteredData);
|
||||
}, [searchList, searchYear, tabName, flowPanel]);
|
||||
|
||||
const handleStartDateSelect = (day: Date | undefined) => {
|
||||
if(day && day > endDate) {
|
||||
alert('종료일은 시작일 이전일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? startDate;
|
||||
setStartDate(selectedDate);
|
||||
const button = startPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const handleEndDateSelect = (day: Date | undefined) => {
|
||||
if(day && day < startDate) {
|
||||
alert('종료일은 시작일 이후일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDate = day ?? endDate;
|
||||
setEndDate(selectedDate);
|
||||
const button = endPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
|
||||
const filteredData = searchList.filter((item) => {
|
||||
const itemDate = new Date((item as T & { msrDt: string }).msrDt);
|
||||
const itemDateOnly = new Date(itemDate.getFullYear(), itemDate.getMonth(), itemDate.getDate());
|
||||
const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
|
||||
const endDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
|
||||
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
|
||||
});
|
||||
setCopySearchList(filteredData);
|
||||
};
|
||||
|
||||
const fncSetFilteredList = useCallback(() => {
|
||||
queryClick({
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
tabName: tabName,
|
||||
filteredList: copySearchList
|
||||
});
|
||||
}, [queryClick, startDate, endDate, tabName, copySearchList]);
|
||||
|
||||
useEffect(() => {
|
||||
fncSetFilteredList();
|
||||
}, [fncSetFilteredList]);
|
||||
|
||||
useEffect(() => {
|
||||
if(ref && ref.current) {
|
||||
const customRef = ref.current;
|
||||
customRef.startDate = startDate;
|
||||
customRef.endDate = endDate;
|
||||
customRef.tabName = tabName;
|
||||
customRef.filteredList = copySearchList;
|
||||
}
|
||||
}, [startDate, endDate, tabName, copySearchList, ref]);
|
||||
|
||||
return (
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
{tabName === "tab_term_rain" ? <TableCell className="w-[300px]">{fcltyName}</TableCell> :
|
||||
<TableCell className="w-[380px]">{fcltyName}</TableCell>}
|
||||
{tabName === "tab_term_rain" && (
|
||||
<>
|
||||
<TableHead className="w-[120px]">{'강수구분'}</TableHead>
|
||||
<TableCell className="w-[250px]">
|
||||
<div className="justify-center">
|
||||
<SelectBox
|
||||
selectArray={selectFlowPanel}
|
||||
value={flowPanel}
|
||||
onSelectValue={(val) => setFlowPanel(val.toString())}
|
||||
className="mx-3 w-[150px]"
|
||||
label=""
|
||||
selectClass="w-full p-1 border rounded bg-white"
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</>
|
||||
)}
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<div ref={startPickerRef} className="flex justify-center">
|
||||
<DatePicker
|
||||
mode="single"
|
||||
selected={startDate}
|
||||
onSelect={(date) => handleStartDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
defaultMonth={startDate}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<div ref={endPickerRef} className="flex justify-center">
|
||||
<DatePicker
|
||||
mode="single"
|
||||
selected={endDate}
|
||||
onSelect={(date) => handleEndDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
defaultMonth={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { TableHead, TableRow } from "@common/components/ui";
|
||||
import type { TableUpperProps } from "../../store/dashboard";
|
||||
|
||||
const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProps[], layoutNum: string }) => {
|
||||
return (
|
||||
layoutNum === 'A' ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 'R' ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'유역'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
|
||||
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { HeadMakeColSpan };
|
||||
@@ -0,0 +1,108 @@
|
||||
import { useFoStore } from '@/app/store';
|
||||
import type { facilityListProps } from '@/app/store/processFacility';
|
||||
import { Label } from '@common/components/ui';
|
||||
import React, { useEffect, useState, useRef, useCallback } from 'react'
|
||||
|
||||
type thisProps = {
|
||||
label: string | undefined;
|
||||
setValue : (fcltyCd?: string, fcltyNm?: string, fcltyCpc?: number | '', trtFrfNm?: string | '', efflWqltStndrdNm?: string | '') => void;
|
||||
sidoSigun? : string | undefined;
|
||||
fcltyName? : string | undefined;
|
||||
}
|
||||
|
||||
export default function SearchInputText({label=undefined, setValue=()=>{}, sidoSigun=undefined, fcltyName=undefined} :thisProps) {
|
||||
|
||||
const { ProcessFacilityList, searchProcessFacilitySearching } = useFoStore((state) => state);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [textValue, setTextValue] = useState(fcltyName || '');
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const processFacilityList = ProcessFacilityList?.processFacilityList || [];
|
||||
|
||||
const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setTextValue(value);
|
||||
if (value) {
|
||||
setIsOpen(true);
|
||||
if(sidoSigun) {
|
||||
searchProcessFacilitySearching(1, 4999, 'A', sidoSigun, '0', '0', '0', value);
|
||||
} else {
|
||||
searchProcessFacilitySearching(1, 4999, '0', '0', '0', '0', '0', value);
|
||||
}
|
||||
} else {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}, [searchProcessFacilitySearching, sidoSigun]);
|
||||
|
||||
const onInputFocus = useCallback(() => {
|
||||
setIsOpen(true);
|
||||
if(sidoSigun) {
|
||||
searchProcessFacilitySearching(1, 4999, 'A', sidoSigun, '0', '0', '0');
|
||||
} else {
|
||||
searchProcessFacilitySearching(1, 4999, '0', '0', '0', '0', '0');
|
||||
}
|
||||
}, [searchProcessFacilitySearching, sidoSigun]);
|
||||
|
||||
useEffect(() => {
|
||||
setTextValue(fcltyName || '');
|
||||
}, [fcltyName]);
|
||||
|
||||
const handleSuggestionClick = useCallback((bscFctCd: string, bscFctNm: string, fctCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '') => {
|
||||
console.log('bscFctNm : ', bscFctNm);
|
||||
console.log('bscFctCd : ', bscFctCd);
|
||||
console.log('fctCpc : ', fctCpc);
|
||||
console.log('trtFrfNm : ', trtFrfNm);
|
||||
console.log('efflWqltStndrdNm : ', efflWqltStndrdNm);
|
||||
setTextValue(bscFctNm);
|
||||
setValue(bscFctCd, bscFctNm, fctCpc, trtFrfNm, efflWqltStndrdNm);
|
||||
setIsOpen(false);
|
||||
}, [setValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={'relative'} ref={wrapperRef}>
|
||||
{label && <Label className="w-20 text-xl text-gray-600 justify-self-center">{label}</Label>}
|
||||
<input
|
||||
type="text"
|
||||
value={textValue}
|
||||
onChange={handleInputChange}
|
||||
onFocus={onInputFocus}
|
||||
className="w-[200px] ml-6 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={`${label}을(를) 입력하세요`}
|
||||
/>
|
||||
{isOpen && processFacilityList.length > 0 && (
|
||||
<div className="absolute z-10 w-[300px] px-2 py-1 !mt-5 ml-20 bg-white border border-gray-300 rounded-md shadow-lg h-90 overflow-auto">
|
||||
<div className="max-h-72">
|
||||
{processFacilityList.map((item : facilityListProps, index : number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="w-full text-left pl-1 pr-10 py-2 hover:bg-gray-100 cursor-pointer overflow-auto"
|
||||
onClick={() => handleSuggestionClick(item.bscFctCd, item.bscFctNm, Number(item.fctCpc), item.trtFrfNm, item.efflWqltStndrdNm)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleSuggestionClick(item.bscFctCd, item.bscFctNm, Number(item.fctCpc), item.trtFrfNm, item.efflWqltStndrdNm);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.sido} {item.gugun} <span className="float-right">{item.bscFctNm}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,7 @@
|
||||
@import "../../../packages/common/components/src/base.css";
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: "Noto Sans KR", sans-serif;
|
||||
font-size: 10px;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
"use client"
|
||||
import { BaseLayout } from "@common/components/ui";
|
||||
import "./globals.css";
|
||||
import { StoreProvider } from "./store";
|
||||
|
||||
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<StoreProvider>
|
||||
<BaseLayout>
|
||||
{children}
|
||||
</BaseLayout>
|
||||
</StoreProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link";
|
||||
import { Button } from "@common/components/ui";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="grid grid-cols-12 gap-2">
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/processFacility"}><Button>처리시설 시설정보</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/flowRate"}><Button>시설별 유량현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/dashboard"}><Button>대시보드</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/processArea"}><Button>처리구역정보</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/facilityPrecipitation"}><Button>시설별 강수현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/facilityWaterQlty"}><Button>시설별 수질현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/planSewage"}><Button>계획하수량 산정지표 현황</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/sewageOccur"}><Button>오수발생량 추정</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/underWaterInput"}><Button>지하수 유입량 추정</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/rdi"}><Button>RDII 조회</Button></Link>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Link href={"./pages/map"}><Button>지도보기</Button></Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
"use client"
|
||||
|
||||
import { useFoStore } from '@/app/store';
|
||||
import type { DrainageEquipmentListProps, TableUpperProps } from '@/app/store/dashboard';
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@common/components';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export type DrainageEquipmentProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
export default function DrainageEquipment({searchYear = '', fcltyList = []}: DrainageEquipmentProps) {
|
||||
|
||||
const {
|
||||
Common,
|
||||
DrainageEquipment,
|
||||
searchDrainageEquipment,
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
upHeadListDrainageEquipment,
|
||||
drainageEquipmentList,
|
||||
} = DrainageEquipment;
|
||||
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
// 이전 시설코드 저장
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
|
||||
const tableData = fcltyList;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit && tableData[0]?.bscFctCd && (tableData[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchDrainageEquipment(searchYear, tableData[0].bscFctCd, false);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(tableData[0].bscFctCd);
|
||||
}
|
||||
}, [fcltyList, isInit, searchDrainageEquipment, searchYear, tableData, hasSearched, prevFacilityCode]);
|
||||
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const HeadMakeColSpan = ({ upHeadList }: { upHeadList: TableUpperProps[] }) => {
|
||||
return (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'part1' ? <TableHead rowSpan={3} className='w-60' key={head.id}>구분</TableHead> :
|
||||
head.id === 'part2' ? <TableHead rowSpan={3} className='w-60' key={head.id}>구분</TableHead> :
|
||||
head.id == 'nowSum' ? <TableHead rowSpan={2} colSpan={3} key={head.id} style={{ whiteSpace: 'pre-line' }}>{'현재\n(기준년도)'}</TableHead> :
|
||||
head.id == 'stepOneSum' ? <TableHead rowSpan={1} colSpan={12} key={head.id} style={{ whiteSpace: 'pre-line' }}>{'변경(금회계획)'}</TableHead> :
|
||||
head.id == 'etc' ? <TableHead rowSpan={3} key={head.id}>비고</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'stepOneSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>1단계</TableHead> :
|
||||
head.id === 'stepTwoSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>2단계</TableHead> :
|
||||
head.id === 'stepThreeSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>3단계</TableHead> :
|
||||
head.id === 'stepFourSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>4단계</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const upHeadList = HeadMakeColSpan({upHeadList:upHeadListDrainageEquipment});
|
||||
return (
|
||||
<div className="overflow-x-auto">
|
||||
<Table variant="secondary" className='w-[130%]'>
|
||||
<TableHeader>
|
||||
{upHeadList}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{drainageEquipmentList.map((el: DrainageEquipmentListProps, index) => (
|
||||
<TableRow key={index+"row"}>
|
||||
{upHeadListDrainageEquipment.map((head) => (
|
||||
(head.id==='nowSum')?
|
||||
<TableCell className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{333}</TableCell>
|
||||
:<TableCell className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id as keyof DrainageEquipmentListProps]}</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
"use client"
|
||||
import type { OperationalStatusListProps } from "@/app/store/dashboard";
|
||||
import { CHART_FORM, MainChart, type ChartConfig } from "@common/business_components";
|
||||
import { Button } from "@common/business_components/ui/table/lib/button";
|
||||
import html2canvas from "html2canvas";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
|
||||
type yearProps = {
|
||||
label: string;
|
||||
평균 : number | string | '';
|
||||
최대 : number | string | '';
|
||||
최소 : number | string | '';
|
||||
}
|
||||
|
||||
type summerProps = {
|
||||
전기간 : number | string | '';
|
||||
강우일3mm이상 : number | string | '';
|
||||
비강우시 : number | string | '';
|
||||
}
|
||||
|
||||
type winterProps = {
|
||||
전기간 : number | string | '';
|
||||
청천시최대 : number | string | '';
|
||||
청천시평균 : number | string | '';
|
||||
청천시최소 : number | string | '';
|
||||
}
|
||||
|
||||
type dashBoardChartModalProps = {
|
||||
title : string;
|
||||
item : string;
|
||||
period : string;
|
||||
modalData : OperationalStatusListProps[];
|
||||
waterQlty : string;
|
||||
}
|
||||
|
||||
export default function DashBoardChartModal({item='', period='', title='',modalData=[], waterQlty=''} : dashBoardChartModalProps) {
|
||||
|
||||
const [chartData, setChartData] = useState<yearProps[] | summerProps[] | winterProps[]>([]);
|
||||
const [chartConfig, setChartConfig] = useState<ChartConfig>({});
|
||||
const chartRef = useRef<HTMLDivElement>(null);
|
||||
const chartOption = {
|
||||
chartForm : CHART_FORM.BAR,
|
||||
chartConfig : chartConfig,
|
||||
chartData : chartData,
|
||||
chartTitle : title,
|
||||
chartClassName : "h-[calc(100%-15%)] w-[90%] mt-5",
|
||||
graphSize : 40,
|
||||
yFieldText : item === 'flowRate' ? '유량(㎥/일)' : item === 'waterQlty' ? '수질(mg/L)' : item === 'chongin' ? '수질(mg/L)' : '',
|
||||
showLegend : true
|
||||
}
|
||||
|
||||
const handleDownload = () => {
|
||||
if (!chartRef.current) {
|
||||
return alert('결과 저장에 실패했습니다.');
|
||||
}
|
||||
html2canvas(chartRef.current).then((canvas) => {
|
||||
const link = document.createElement('a');
|
||||
document.body.appendChild(link);
|
||||
link.href = canvas.toDataURL('image/png');
|
||||
link.download = 'result.png';
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if(period === 'year'){
|
||||
const filteredData: yearProps[] = modalData.map((item) => {
|
||||
if(waterQlty.trim().includes('T-N') || waterQlty.trim().includes('T-P')){
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(3) : (item.yearAvg || 0),
|
||||
최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(3) : (item.yearMax || 0),
|
||||
최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(3) : (item.yearMin || 0),
|
||||
}
|
||||
}
|
||||
else{
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(1) : (item.yearAvg || 0),
|
||||
최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(1) : (item.yearMax || 0),
|
||||
최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(1) : (item.yearMin || 0),
|
||||
}
|
||||
}
|
||||
})
|
||||
if (item === 'flowRate') {
|
||||
setChartData(filteredData.slice(0,5));
|
||||
} else if (item === 'waterQlty') {
|
||||
setChartData(filteredData.slice(5,11));
|
||||
} else {
|
||||
setChartData(filteredData.slice(11,13));
|
||||
}
|
||||
}
|
||||
else if (period === 'summer') {
|
||||
const filteredData: summerProps[] = modalData.map((item) => {
|
||||
if(waterQlty.trim().includes('T-N') || waterQlty.trim().includes('T-P')){
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
전기간: typeof item.summerAll === 'string' ? Number(item.summerAll.replace(/,/g, '')).toFixed(3) : (item.summerAll || 0),
|
||||
강우일3mm이상: typeof item.summerThree === 'string' ? Number(item.summerThree.replace(/,/g, '')).toFixed(3) : (item.summerThree || 0),
|
||||
비강우시: typeof item.summerRain === 'string' ? Number(item.summerRain.replace(/,/g, '')).toFixed(3) : (item.summerRain || 0),
|
||||
}
|
||||
}else{
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
전기간: typeof item.summerAll === 'string' ? Number(item.summerAll.replace(/,/g, '')).toFixed(1) : (item.summerAll || 0),
|
||||
강우일3mm이상: typeof item.summerThree === 'string' ? Number(item.summerThree.replace(/,/g, '')).toFixed(1) : (item.summerThree || 0),
|
||||
비강우시: typeof item.summerRain === 'string' ? Number(item.summerRain.replace(/,/g, '')).toFixed(1) : (item.summerRain || 0),
|
||||
}
|
||||
}
|
||||
})
|
||||
if (item === 'flowRate') {
|
||||
setChartData(filteredData.slice(0,5));
|
||||
} else if (item === 'waterQlty') {
|
||||
setChartData(filteredData.slice(5,11));
|
||||
} else {
|
||||
setChartData(filteredData.slice(11,13));
|
||||
}
|
||||
}
|
||||
else if (period === 'winter') {
|
||||
const filteredData: winterProps[] = modalData.map((item) => {
|
||||
return {
|
||||
label: item.waterQlty,
|
||||
전기간: typeof item.winterAll === 'string' ? Number(item.winterAll.replace(/,/g, '')).toFixed(3) : (item.winterAll || 0),
|
||||
청천시최대: typeof item.winterSunnyMax === 'string' ? Number(item.winterSunnyMax.replace(/,/g, '')).toFixed(3) : (item.winterSunnyMax || 0),
|
||||
청천시평균: typeof item.winterSunnyAvg === 'string' ? Number(item.winterSunnyAvg.replace(/,/g, '')).toFixed(3) : (item.winterSunnyAvg || 0),
|
||||
청천시최소: typeof item.winterSunnyMin === 'string' ? Number(item.winterSunnyMin.replace(/,/g, '')).toFixed(3) : (item.winterSunnyMin || 0),
|
||||
}
|
||||
})
|
||||
setChartData(filteredData);
|
||||
|
||||
if (item === 'flowRate') {
|
||||
setChartData(filteredData.slice(0,5));
|
||||
} else if (item === 'waterQlty') {
|
||||
setChartData(filteredData.slice(5,11));
|
||||
} else {
|
||||
setChartData(filteredData.slice(11,13));
|
||||
}
|
||||
} else {
|
||||
setChartData([]);
|
||||
}
|
||||
}, [item, modalData, period, waterQlty]);
|
||||
|
||||
useEffect(() => {
|
||||
const newChartConfig = chartData.reduce((config, element) => {
|
||||
const label = 'label' in element ? element.label : '';
|
||||
if (label) {
|
||||
config[label] = {
|
||||
label: label,
|
||||
color : "hsl(var(--chart-1))"
|
||||
};
|
||||
}
|
||||
return config;
|
||||
}, {} as Record<string, { label: string; color: string; }>) satisfies ChartConfig;
|
||||
setChartConfig(newChartConfig);
|
||||
}, [chartData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-end">
|
||||
<span className="text-[13px] font-bold mt-2 w-[260px] h-[30px] -mb-9">
|
||||
(하절기 : 6/1~8/31 동절기 : 1/1~2/28)
|
||||
</span>
|
||||
<Button className="text-[13px] w-[80px] h-[30px] -mb-9 mr-20" onClick={handleDownload}>캡처</Button>
|
||||
</div>
|
||||
<div ref={chartRef}>
|
||||
<MainChart
|
||||
chartForm={chartOption.chartForm}
|
||||
chartConfig={chartOption.chartConfig}
|
||||
chartData={chartOption.chartData}
|
||||
chartTitle={chartOption.chartTitle}
|
||||
chartClassName={chartOption.chartClassName}
|
||||
graphSize={chartOption.graphSize}
|
||||
yFieldText={chartOption.yFieldText}
|
||||
showLegend={chartOption.showLegend}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/processFacility";
|
||||
import { ContentsDiv, UiModal, UiTable } from "@common/business_components";
|
||||
import { cn, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components";
|
||||
import { useEffect, useState } from "react";
|
||||
import DashBoardChartModal from "./modal/page";
|
||||
|
||||
export type facilityInfoProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const headMakeColSpanPlanFclty = (upHeadList: TableUpperProps[], planYearList: string[]) => {
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={7} style={{ whiteSpace: 'pre-line' }}>{'시설계획\n(금회)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps, index: number) =>
|
||||
(head.upName === 'upChangeRe'?<TableHead key={head.id} style={{ whiteSpace: 'pre-line' }}>{index===0?head.title:head.title+'\n('+planYearList[index-1]+')'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
}
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const headMakeColSpanOperationStatus = (upHeadList: TableUpperProps[], searchYear: string) => {
|
||||
return ( <>
|
||||
<TableRow>
|
||||
<TableHead rowSpan={1} colSpan={16} style={{ whiteSpace: 'pre-line' }}>{searchYear+'년도 운영실태'}</TableHead>
|
||||
</TableRow>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe1'&&head.upSequnce===1?<TableHead key={head.id} rowSpan={2}colSpan={2} style={{ whiteSpace: 'pre-line' }}>{head.title}</TableHead>:
|
||||
!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe2'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'연간 운영실태'}</TableHead>:
|
||||
head.upName === 'upChangeRe3'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'하절기 운영실태\n(6~8월)'}</TableHead>:
|
||||
head.upName === 'upChangeRe4'&&head.upSequnce===1?<TableHead key={head.id} colSpan={4} style={{ whiteSpace: 'pre-line' }}>{'동절기 운영실태\n(1~2월)'}</TableHead>:
|
||||
head.upName === 'upChangeRe5'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'지하수유입량'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe2'||head.upName === 'upChangeRe3'||head.upName === 'upChangeRe4'||head.upName === 'upChangeRe5' ?<TableHead key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
}
|
||||
|
||||
export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: facilityInfoProps & { onFacilityChange: (facility: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }) => void }) {
|
||||
// 입력값 상태 관리
|
||||
const {
|
||||
Common,
|
||||
FcltyMain,
|
||||
PlanFclty,
|
||||
OperationStatus,
|
||||
searchOperationStatus,
|
||||
searchPlanInfo
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const [modalItem, setModalItem] = useState<{item: string, period: string, title: string, waterQlty: string} | null>(null);
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
// Tab1
|
||||
// fclty 관련
|
||||
const {
|
||||
upHeadListFclty,
|
||||
} = FcltyMain;
|
||||
|
||||
// 시설계획 관련
|
||||
const {
|
||||
upHeadListPlanFclty,
|
||||
planFcltyList,
|
||||
planYearList
|
||||
} = PlanFclty;
|
||||
|
||||
// 그리드 관련
|
||||
const {
|
||||
upHeadListOperationStatus,
|
||||
operationalStatusList
|
||||
} = OperationStatus;
|
||||
|
||||
const closeModal = () => {
|
||||
setModalItem(null);
|
||||
};
|
||||
|
||||
// const fcltyListArr = useMemo(() => [fcltyList], [fcltyList]);
|
||||
|
||||
const tableData = fcltyList;
|
||||
|
||||
// key 변환
|
||||
const mappedTableData = tableData.map(item => ({
|
||||
fcltyNm: item.bscFctNm,
|
||||
facilityCapacity: item.fcltyCpc,
|
||||
publicMethod: item.trtFrfNm,
|
||||
location: item.efflWqltStndrdNm,
|
||||
}));
|
||||
|
||||
const fncLoadModal = (item: string, period: string, waterQlty: string) => {
|
||||
// 유량
|
||||
if(item === 'flowRate'){
|
||||
if(period === 'year'){
|
||||
setModalItem({item: 'flowRate', period: 'year', title: '연간 유량', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'summer'){
|
||||
setModalItem({item: 'flowRate', period: 'summer', title: '하절기 유량', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'winter'){
|
||||
setModalItem({item: 'flowRate', period: 'winter', title: '동절기 유량', waterQlty: waterQlty});
|
||||
}
|
||||
}
|
||||
// 수질
|
||||
else if (item == 'waterQlty'){
|
||||
if(period === 'year'){
|
||||
setModalItem({item: 'waterQlty', period: 'year', title: '연간 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'summer'){
|
||||
setModalItem({item: 'waterQlty', period: 'summer', title: '하절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'winter'){
|
||||
setModalItem({item: 'waterQlty', period: 'winter', title: '동절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
}
|
||||
// 총인
|
||||
else {
|
||||
if(period === 'year'){
|
||||
setModalItem({item: 'chongin', period: 'year', title: '총인설비 연간 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'summer'){
|
||||
setModalItem({item: 'chongin', period: 'summer', title: '총인설비 하절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
else if(period === 'winter'){
|
||||
setModalItem({item: 'chongin', period: 'winter', title: '총인설비 동절기 수질', waterQlty: waterQlty});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit && fcltyList[0]?.bscFctCd && (fcltyList[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchOperationStatus(false, searchYear, fcltyList[0].bscFctCd);
|
||||
searchPlanInfo(searchYear, fcltyList[0].bscFctCd);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(fcltyList[0].bscFctCd);
|
||||
planFcltyList.forEach((el: { [key: string]: string | number | boolean }, index) => {
|
||||
if (index === 6) {
|
||||
el['item'] = (Number(searchYear)-2).toString();
|
||||
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
|
||||
} else if (index === 7) {
|
||||
el['item'] = (Number(searchYear)-1).toString();
|
||||
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
|
||||
} else if (index === 8) {
|
||||
el['item'] = (Number(searchYear)-0).toString();
|
||||
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [isInit, searchOperationStatus, searchYear, fcltyList, hasSearched, prevFacilityCode, searchPlanInfo, planFcltyList]);
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
operationalStatusList.map((item: { [key: string]: string | number | boolean },index) => {
|
||||
if(index===8 || index===9 || index===10 || index===11 || index===12 || index===13 || index===14 || index===15){
|
||||
item['yearAvg'] = Number(item['yearAvg']).toFixed(3);
|
||||
item['yearMax'] = item['yearMax']+'%';
|
||||
item['yearMin'] = item['yearMin']+'%';
|
||||
item['summerAll'] = item['summerAll']+'%';
|
||||
item['summerThree'] = item['summerThree']+'%';
|
||||
item['summerRain'] = item['summerRain']+'%';
|
||||
item['winterAll'] = item['winterAll']+'%';
|
||||
item['winterSunnyAvg'] = item['winterSunnyAvg']+'%';
|
||||
item['winterSunnyMax'] = item['winterSunnyMax']+'%';
|
||||
item['winterSunnyMin'] = item['winterSunnyMin']+'%';
|
||||
}
|
||||
|
||||
});
|
||||
}, [operationalStatusList]);
|
||||
|
||||
const upChangeRePlanFclty = headMakeColSpanPlanFclty(upHeadListPlanFclty, planYearList);
|
||||
const upChangeHeadListOperationStatus = headMakeColSpanOperationStatus(upHeadListOperationStatus, searchYear);
|
||||
return (
|
||||
<>
|
||||
<UiTable headName={""} tableData={mappedTableData} headlist={upHeadListFclty} pageSize={0} total={0} cellClick={ undefined } onPageChange={() => { } } />
|
||||
<ContentsDiv>
|
||||
<div className="grid grid-cols-12 gap-1">
|
||||
<div className="col-span-5">
|
||||
<Table variant="secondary">
|
||||
<TableHeader>
|
||||
{upChangeRePlanFclty}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{planFcltyList.map((el: { [key: string]: string | number | boolean },index) => (
|
||||
<TableRow key={index+"row"} >
|
||||
{upHeadListPlanFclty.map((head) => (
|
||||
((index === 6 || index === 7 || index === 8) && (head.id === 'provisionalApproval' || head.id === 'stepTwo'))?
|
||||
<TableCell className="text-right" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:((index === 6 || index === 7 || index === 8) && (head.id === 'now' || head.id === 'stepOne' || head.id === 'stepThree' || head.id === 'stepFour'))?
|
||||
null
|
||||
:((index === 5) && (head.id === 'provisionalApproval' || head.id === 'stepTwo'))?
|
||||
<TableCell colSpan={3} className="text-center border border-[var(--border)] bg-[rgb(234,243,251)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:((index === 5) && (head.id === 'now' || head.id === 'stepOne' || head.id === 'stepThree'|| head.id === 'stepFour'))?
|
||||
null
|
||||
:(index < 5 || index > 5)&& (index!= 4) && (head.id ==='provisionalApproval'||head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour')
|
||||
?<TableCell className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:(head.id === "provisionalApproval" && index === 4)
|
||||
?<TableCell colSpan={6} className="text-right border border-[var(--border)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{(Number(fcltyList[0]?.fcltyCpc)* 0.6).toLocaleString('en-US', { minimumFractionDigits: 1, maximumFractionDigits: 1 })} </TableCell>
|
||||
:((head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') && index === 4)
|
||||
?null
|
||||
:(head.id === 'item' && index != 5)?
|
||||
<TableCell className="text-center text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
:<TableCell className="text-center border border-[var(--border)] bg-[rgb(234,243,251)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="col-span-7 h-[600px] overflow-x-auto">
|
||||
<div className="w-[200%]">
|
||||
<Table variant="secondary">
|
||||
<TableHeader>
|
||||
{upChangeHeadListOperationStatus}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{operationalStatusList.map((el: { [key: string]: string | number | boolean },index) => (
|
||||
<TableRow key={index+"row"} >
|
||||
{upHeadListOperationStatus.map((head) => (
|
||||
(head.id === 'flowRate' && index === 0)?<TableCell rowSpan={5} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'flowRate' && index === 5)?<TableCell rowSpan={6} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'flowRate' && index === 11)?<TableCell rowSpan={2} className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'groundWaterAvg'||head.id === 'groundWaterSummer'||head.id === 'groundWaterWinter')&&(index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 0)?<TableCell rowSpan={2} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 2)?<TableCell rowSpan={3} className={cn("sticky top-0 bg-secondary [&_tr]:border-b", "text-center" )} style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{'RDII추정시\n일강수량(mm)'}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 5)?<TableCell rowSpan={2} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el['rdiRain']}</TableCell>:
|
||||
(head.id === 'rdi'&&index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}></TableCell>:
|
||||
(head.id === 'waterQlty')?<TableCell className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=0 && index<=4))?<TableCell className="bg-yellow-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=5 && index<=10))?<TableCell className="bg-green-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=11 && index<=12))?<TableCell className="bg-blue-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=0 && index<=4))?<TableCell className="bg-yellow-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=5 && index<=10))?<TableCell className="bg-green-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=11 && index<=12))?<TableCell className="bg-blue-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=0 && index<=4))?<TableCell className="bg-yellow-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=5 && index<=10))?<TableCell className="bg-green-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=11 && index<=12))?<TableCell className="bg-blue-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
|
||||
null
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ContentsDiv>
|
||||
{modalItem && (modalItem.item === 'flowRate' || modalItem.item === 'waterQlty' || modalItem.item === 'chongin') && (
|
||||
<UiModal
|
||||
body={<DashBoardChartModal item={modalItem.item} period={modalItem.period} title={modalItem.title} modalData={operationalStatusList} waterQlty={modalItem.waterQlty}></DashBoardChartModal>}
|
||||
bodyClass="sm:max-w-[80%] h-[88%]"
|
||||
open={true}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { lineChartDataProps } from "@/app/store/dashboard";
|
||||
import { CHART_FORM, type ChartConfig, ContentsDiv, MainChart } from "@common/business_components";
|
||||
import { Card, CardContent } from "@common/business_components/ui/chart/lib/card";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type facilityInfoProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
export default function DashBoardChart({searchYear = '', fcltyList = []}: facilityInfoProps) {
|
||||
const {MainGraph
|
||||
,searchMainGraph
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
const [chart_tpTp, setChart_tpTp] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_tntn, setChart_tntn] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_inflBodInflTn, setChart_inflBodInflTn] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
const [chart_inflBodInflTp, setChart_inflBodInflTp] = useState<{
|
||||
chartData1: lineChartDataProps[];
|
||||
chartData2: lineChartDataProps[];
|
||||
}>();
|
||||
|
||||
const {
|
||||
chart_inflowRain,
|
||||
chart_bodRain,
|
||||
chart_inflTp,
|
||||
chart_chongInTp,
|
||||
chart_efflTp,
|
||||
chart_inflTn,
|
||||
chart_efflTn,
|
||||
chart_inflBod,
|
||||
} = MainGraph;
|
||||
|
||||
/**
|
||||
* 차트 Config
|
||||
*/
|
||||
const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#00b50c", "#D4A5A5"];
|
||||
|
||||
//유입하수량-강수량
|
||||
const chartConfig_inflowRain = {
|
||||
barVal0: {
|
||||
label: '강수량',
|
||||
color: colors[2],
|
||||
},
|
||||
lineVal0: {
|
||||
label: '시설용량',
|
||||
color: colors[1],
|
||||
},
|
||||
lineVal1: {
|
||||
label: '유입량',
|
||||
color: colors[4],
|
||||
}
|
||||
} satisfies ChartConfig;
|
||||
//강우량-유입BOD
|
||||
const chartConfig_rainBod = {
|
||||
barVal0: {
|
||||
label: '강수량',
|
||||
color: colors[2],
|
||||
},
|
||||
lineVal0: {
|
||||
label: '유입BOD',
|
||||
color: colors[0],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
//총인유입T-P-방류T-P
|
||||
const chartConfig_tptp = {
|
||||
chartData1: {
|
||||
label: '총인유입T-P',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '방류T-P',
|
||||
color: colors[1],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입T-N-방류T-N
|
||||
const chartConfig_tntn = {
|
||||
chartData1: {
|
||||
label: '유입T-N',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '방류T-N',
|
||||
color: colors[1],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입BOD-유입T-N
|
||||
const chartConfig_inflBodInflTn = {
|
||||
chartData1: {
|
||||
label: '유입BOD',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '유입T-N',
|
||||
color: colors[1],
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
// 유입BOD-유입T-P
|
||||
const chartConfig_inflBodInflTp = {
|
||||
chartData1: {
|
||||
label: '유입BOD',
|
||||
color: colors[0],
|
||||
},
|
||||
chartData2: {
|
||||
label: '유입T-P',
|
||||
color: colors[1],
|
||||
},
|
||||
|
||||
} satisfies ChartConfig;
|
||||
|
||||
useEffect(() => {
|
||||
if (fcltyList.length > 0 && fcltyList[0]?.bscFctCd && (fcltyList[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchMainGraph(searchYear, fcltyList[0].bscFctCd);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(fcltyList[0].bscFctCd);
|
||||
}
|
||||
}, [searchYear, fcltyList, searchMainGraph, hasSearched, chart_inflTp, chart_efflTp, prevFacilityCode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_chongInTp || !chart_efflTp) return;
|
||||
const chartTpTpData = {
|
||||
chartData1: chart_chongInTp,
|
||||
chartData2: chart_efflTp
|
||||
};
|
||||
setChart_tpTp(chartTpTpData);
|
||||
}, [chart_chongInTp, chart_efflTp]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflTn || !chart_efflTn) return;
|
||||
const chartTntnData = {
|
||||
chartData1: chart_inflTn,
|
||||
chartData2: chart_efflTn
|
||||
};
|
||||
setChart_tntn(chartTntnData);
|
||||
}, [chart_inflTn, chart_efflTn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflBod || !chart_inflTn) return;
|
||||
const chartInflBodInflTnData = {
|
||||
chartData1: chart_inflBod,
|
||||
chartData2: chart_inflTn
|
||||
};
|
||||
setChart_inflBodInflTn(chartInflBodInflTnData);
|
||||
}, [chart_inflBod, chart_inflTn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chart_inflBod || !chart_inflTp) return;
|
||||
const chartInflBodInflTpData = {
|
||||
chartData1: chart_inflBod,
|
||||
chartData2: chart_inflTp
|
||||
};
|
||||
setChart_inflBodInflTp(chartInflBodInflTpData);
|
||||
}, [chart_inflBod, chart_inflTp]);
|
||||
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContentsDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_inflowRain} chartData={chart_inflowRain} chartTitle="유입하수량-강수량" yFieldText="유입하수량(m³/일)" yFieldText2="강수량(mm)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig_rainBod} chartData={chart_bodRain} chartTitle="유입BOD-강수량" yFieldText="BOD(mg/L)" yFieldText2="강수량(mm)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tptp} chartData={chart_tpTp} chartTitle="총인유입T-P-방류T-P" yFieldText="T-P(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
{/* 유입T-N-방류T-N */}
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_tntn} chartData={chart_tntn} chartTitle="유입T-N-방류T-N" yFieldText="T-N(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
{/* 유입BOD-유입T-N */}
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTn} chartData={chart_inflBodInflTn} chartTitle="유입BOD-유입T-N" yFieldText="농도(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
{/* 유입BOD-유입T-P */}
|
||||
<ListDiv className="h-[300px]">
|
||||
<Card className="h-full">
|
||||
<CardContent className="h-full">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig_inflBodInflTp} chartData={chart_inflBodInflTp} chartTitle="유입BOD-유입T-P" yFieldText="농도(mg/L)"></MainChart>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
</>
|
||||
);
|
||||
{/* <div>>
|
||||
<MainChart chartForm={CHART_FORM.DN} chartConfig={chartConfig} chartData={chartData} chartTitle="유입하수량-강수량"></MainChart>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<MainChart chartForm={CHART_FORM.LINEBAR} chartConfig={chartConfig} chartData={chart_inflowRain} chartTitle="유입BOD-강수량"></MainChart>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig} chartData={chartData} chartTitle="총인유입T-P-방류T-P"></MainChart>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<MainChart chartForm={CHART_FORM.LINE} chartConfig={chartConfig} chartData={chartData} chartTitle="유입T-N-방류T-N"></MainChart>
|
||||
</div>
|
||||
</div> */}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, downloadMultipleExcel, filePickedBlobArray, MainDiv, SelectBox, UITab, type SelectDataType } from "@common/business_components";
|
||||
import { Button, TabsContent } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
import DashBoardFclty from "../dashboardMain/page";
|
||||
/* import DrainageEquipment from "./drainageEquipment/page"; */
|
||||
import ProcessFacilitySearch from "./facilityInfo/page";
|
||||
import DashBoardChart from "./maingraph/page";
|
||||
import RainManageTab from "./rainManage/page";
|
||||
import DrainageEquipment from "./drainageEquipment/page";
|
||||
|
||||
const tabList = [
|
||||
{ value: 'facilityInfo', label: '시설정보 및 운영현황' },
|
||||
{ value: 'mainGraph', label: '주요그래프' },
|
||||
{ value: 'rainManage', label: '강우일 운영현황' },
|
||||
{ value: 'drainageEquipment', label: '배수설비 정비현황' }
|
||||
];
|
||||
|
||||
export default function DashBoard() {
|
||||
// 입력값 상태 관리
|
||||
const { Common, initializeCommonData,searchMainGraph, searchRainManage, searchOperationStatus, OperationStatus, RainManage, MainGraph, PlanFclty } = useFoStore((state) => state);
|
||||
const [activeTab, setActiveTab] = useState<string>('facilityInfo');
|
||||
|
||||
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
|
||||
const [sidoValue, setSidoValue] = useState<string>('0');
|
||||
const [sigunValue, setSigunValue] = useState<string>('0');
|
||||
const {
|
||||
isInit,
|
||||
selectSearchYear,
|
||||
btnClass,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
planFcltyList
|
||||
} = PlanFclty;
|
||||
|
||||
const {
|
||||
operationalStatusList
|
||||
} = OperationStatus;
|
||||
|
||||
const {
|
||||
excelList
|
||||
} = RainManage;
|
||||
|
||||
const {
|
||||
chart_inflowRain,
|
||||
chart_bodRain,
|
||||
chart_inflTp,
|
||||
chart_chongInTp,
|
||||
chart_efflTp,
|
||||
chart_inflTn,
|
||||
chart_efflTn,
|
||||
} = MainGraph;
|
||||
|
||||
/******************선택된 데이터******************/
|
||||
// 연도
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
|
||||
// 시설명
|
||||
const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
|
||||
bscFctCd: '',
|
||||
bscFctNm: '',
|
||||
fcltyCpc: '',
|
||||
trtFrfNm: '',
|
||||
efflWqltStndrdNm: ''
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
setFcltyList({
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
}
|
||||
}, [isInit, initializeCommonData]);
|
||||
|
||||
const handleFacilityChange = (facility: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }) => {
|
||||
setFcltyList(facility);
|
||||
};
|
||||
|
||||
const onSelectValue = (val: string, type: string) => {
|
||||
switch(type) {
|
||||
case 'sido':
|
||||
setSidoValue(val);
|
||||
initializeSigunData(val);
|
||||
onSelectValue('0', 'sigun');
|
||||
break;
|
||||
case 'sigun':
|
||||
setSigunValue(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 시군구 세팅
|
||||
const initializeSigunData = (sidoCd: string) => {
|
||||
if (sidoCd === '0') {
|
||||
setSigunValue('0');
|
||||
setFilteredSigunData([{ text: "전체", val: '0' }]);
|
||||
} else {
|
||||
const newFilteredData = [
|
||||
{ text: "전체", val: '0' },
|
||||
...selectSigunData.filter((item: SelectDataType) => item.val.substring(0, 2) === sidoCd)
|
||||
];
|
||||
setSigunValue('0');
|
||||
setFilteredSigunData(newFilteredData);
|
||||
}
|
||||
}
|
||||
|
||||
const excelDownload = () => {
|
||||
if (!fcltyList.bscFctCd) return;
|
||||
switch (activeTab) {
|
||||
case 'facilityInfo':
|
||||
searchOperationStatus(false, searchYear, fcltyList.bscFctCd);
|
||||
|
||||
fetch(`/mainDashBoard.xlsx`, {}).then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
// 받은 파일 바인너리 처리
|
||||
const blobRet = await response.arrayBuffer();
|
||||
|
||||
const excelData1 = planFcltyList.map((item) => {
|
||||
return [
|
||||
item.item,
|
||||
item.provisionalApproval,
|
||||
item.now,
|
||||
item.stepOne,
|
||||
item.stepTwo,
|
||||
item.stepThree,
|
||||
item.stepFour,
|
||||
];
|
||||
});
|
||||
|
||||
// operationalStatusList를 2차원 배열로 변환
|
||||
const excelData2 = operationalStatusList.map((item, index) => {
|
||||
const baseData = [
|
||||
item.yearAvg,
|
||||
item.yearMax,
|
||||
item.yearMin,
|
||||
item.summerAll,
|
||||
item.summerThree,
|
||||
item.summerRain,
|
||||
item.winterAll,
|
||||
item.winterSunnyAvg,
|
||||
item.winterSunnyMax,
|
||||
item.winterSunnyMin,
|
||||
item.groundWaterAvg,
|
||||
item.groundWaterSummer,
|
||||
item.groundWaterWinter
|
||||
];
|
||||
|
||||
// index가 0일 때만 rdi와 rdiRain 추가
|
||||
return index === 0 ? [...baseData, item.rdi, item.rdiRain] : baseData;
|
||||
});
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: excelData1,
|
||||
headerNum: 3,
|
||||
headerRange: 'A1:G2',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'A'
|
||||
},
|
||||
{
|
||||
data: excelData2,
|
||||
headerNum: 4,
|
||||
headerRange: 'A1:Q3',
|
||||
sheetName: '운영실태',
|
||||
startCol: 'C'
|
||||
}
|
||||
];
|
||||
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
|
||||
await filePickedBlobArray(blobRet, '시설정보및운영현황황', sheetParameter);
|
||||
});
|
||||
break;
|
||||
|
||||
case 'mainGraph':
|
||||
searchMainGraph(searchYear, fcltyList.bscFctCd);
|
||||
|
||||
const sheetParameter = [
|
||||
{
|
||||
data: [['날짜', '강수량'],...chart_inflowRain.map((item) => [item.label, item.barVal0])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '강수량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입하수량'],...chart_inflowRain.map((item) => [item.label, item.lineVal1])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입하수량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '시설용량'],...chart_inflowRain.map((item) => [item.label, item.lineVal0])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '시설용량'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입BOD'],...chart_bodRain.map((item) => [item.label, item.lineVal0])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입BOD'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입T-P'],...chart_inflTp.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '총인유입T-P'],...chart_chongInTp.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '총인유입T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '방류T-P'],...chart_efflTp.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '방류T-P'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '유입T-N'],...chart_inflTn.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '유입T-N'
|
||||
},
|
||||
{
|
||||
data: [['날짜', '방류T-N'],...chart_efflTn.map((item) => [item.label, item.val])],
|
||||
headerNum: 1,
|
||||
headerRange: 'A1:B1',
|
||||
sheetName: '방류T-N'
|
||||
}
|
||||
];
|
||||
|
||||
downloadMultipleExcel('주요그래프', sheetParameter);
|
||||
break;
|
||||
|
||||
case 'rainManage':
|
||||
searchRainManage(searchYear, fcltyList.bscFctCd, true);
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({ data: excelList as unknown as JSON[], fileName: '강우일 운영현황', sheetNameArray: ['강우일 운영현황'], headerRange: 'A1:T1' });
|
||||
}
|
||||
break;
|
||||
// Add other cases for different tabs as needed
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const initVal = () => {
|
||||
setFcltyList({
|
||||
bscFctCd: '11000SW001R',
|
||||
bscFctNm: '난지',
|
||||
fcltyCpc: 860000,
|
||||
trtFrfNm: '표준활성슬러지법, MLE, A2O',
|
||||
efflWqltStndrdNm: '500톤 이상(Ⅲ지역)'
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<ContentsDiv>
|
||||
<div className="flex card card-border !mt-6">
|
||||
<div className="grid grid-cols-12 gap-5 w-8/12 m-4">
|
||||
<SelectBox className="col-span-2" label={'연도'} selectArray={selectSearchYear} onSelectValue={ (val) => setSearchYear(val.toString()) } value={searchYear} selectClass={undefined}/>
|
||||
<SelectBox className="col-span-3" label={'시도'} selectArray={selectSidoData} onSelectValue={(val) => onSelectValue(val.toString(), 'sido')} value={sidoValue} selectClass={undefined}/>
|
||||
<SelectBox className="col-span-3" label={'시군구'} selectArray={filteredSigunData} onSelectValue={(val) => onSelectValue(val.toString(), 'sigun')} value={sigunValue} selectClass={undefined}/>
|
||||
<div className="col-span-4 flex">
|
||||
<DashBoardFclty onFacilityChange={handleFacilityChange} sidoSigun={sigunValue!='0'?sigunValue:sidoValue!='0'?sidoValue:''} facilityNm={fcltyList.bscFctNm}></DashBoardFclty>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-4/12 mx-5 flex items-center justify-end space-x-2">
|
||||
<Button className={btnClass} onClick={initVal}>
|
||||
초기화
|
||||
</Button>
|
||||
<Button className={btnClass} color="green" onClick={excelDownload}>
|
||||
엑셀다운로드
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<UITab tabList={tabList} defaultValue="facilityInfo" onValueChange={setActiveTab}>
|
||||
<TabsContent value="facilityInfo">
|
||||
<ProcessFacilitySearch searchYear={searchYear} fcltyList={[fcltyList]} onFacilityChange={handleFacilityChange} />
|
||||
</TabsContent>
|
||||
<TabsContent value="mainGraph">
|
||||
<DashBoardChart searchYear={searchYear} fcltyList={[fcltyList]}/>
|
||||
</TabsContent>
|
||||
<TabsContent value="rainManage">
|
||||
<RainManageTab searchYear={searchYear} fcltyList={[fcltyList]}/>
|
||||
</TabsContent>
|
||||
<TabsContent value="drainageEquipment">
|
||||
<DrainageEquipment searchYear={searchYear} fcltyList={[fcltyList]}/>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</ContentsDiv>
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { UiTable } from "@common/business_components/ui/table";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export type facilityInfoProps = {
|
||||
searchYear?: string;
|
||||
fcltyList?: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string, efflWqltStndrdNm: string }[];
|
||||
};
|
||||
|
||||
export default function RainManageTab({searchYear = '', fcltyList = []}: facilityInfoProps) {
|
||||
|
||||
const {
|
||||
Common,
|
||||
searchRainManage,
|
||||
RainManage
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const [hasSearched, setHasSearched] = useState(false);
|
||||
// 이전 시설코드 저장
|
||||
const [prevFacilityCode, setPrevFacilityCode] = useState<string>('');
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
upHeadListRainManage,
|
||||
rainManageList,
|
||||
} = RainManage;
|
||||
|
||||
const tableData = fcltyList;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit && tableData[0]?.bscFctCd && (tableData[0].bscFctCd !== prevFacilityCode || !hasSearched)) {
|
||||
searchRainManage(searchYear, tableData[0].bscFctCd, false);
|
||||
setHasSearched(true);
|
||||
setPrevFacilityCode(tableData[0].bscFctCd);
|
||||
}
|
||||
}, [fcltyList, isInit, searchRainManage, searchYear, tableData, hasSearched, prevFacilityCode]);
|
||||
|
||||
// 연도가 바뀌면 hasSearched를 false로 리셋
|
||||
useEffect(() => {
|
||||
setHasSearched(false);
|
||||
}, [searchYear]);
|
||||
|
||||
return (
|
||||
<UiTable
|
||||
headName=""
|
||||
tableData={rainManageList}
|
||||
headlist={upHeadListRainManage}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
>
|
||||
</UiTable>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchInput from "../../components/common/SearchInput";
|
||||
|
||||
export default function DashBoardFclty({ onFacilityChange, sidoSigun, facilityNm }: { onFacilityChange?: (facility: { bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | '' }) => void, sidoSigun?: string, facilityNm?: string }) {
|
||||
// 입력값 상태 관리
|
||||
const { Common, initializeCommonData } = useFoStore((state) => state);
|
||||
|
||||
const {
|
||||
isInit,
|
||||
} = Common;
|
||||
|
||||
// 시설명
|
||||
const [bscFctNm, setFcltyName] = useState<string>(facilityNm || '난지');
|
||||
const [bscFctCd, setbscFctCd] = useState<string>('11000SW001R');
|
||||
const [fcltyCpc, setFcltyCpc] = useState<number | ''>(860000);
|
||||
const [trtFrfNm, setTrtFrfNm] = useState<string | ''>('표준활성슬러지법, MLE, A2O');
|
||||
const [efflWqltStndrdNm, setEfflWqltStndrdNm] = useState<string | ''>('500톤 이상(Ⅲ지역)');
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
}
|
||||
}, [isInit, initializeCommonData ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (facilityNm) {
|
||||
setFcltyName(facilityNm);
|
||||
}
|
||||
}, [facilityNm]);
|
||||
|
||||
const fncNextPage = (bscFctCd?: string, bscFctNm?: string, fcltyCpc?: number | '', trtFrfNm?: string | '', efflWqltStndrdNm?: string | '') => {
|
||||
setbscFctCd(bscFctCd || '');
|
||||
setFcltyName(bscFctNm || '');
|
||||
setFcltyCpc(fcltyCpc || '');
|
||||
setTrtFrfNm(trtFrfNm || '');
|
||||
setEfflWqltStndrdNm(efflWqltStndrdNm || '');
|
||||
|
||||
if (bscFctCd && onFacilityChange) {
|
||||
onFacilityChange({
|
||||
bscFctCd: bscFctCd || '',
|
||||
bscFctNm: bscFctNm || '',
|
||||
fcltyCpc: fcltyCpc || '',
|
||||
trtFrfNm: trtFrfNm || '',
|
||||
efflWqltStndrdNm: efflWqltStndrdNm || ''
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log('bscFctNm : ', bscFctNm);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchInput label={'시설명'} setValue={fncNextPage} sidoSigun={sidoSigun} fcltyName={bscFctNm}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { PrecipitationPropsDetailProps } from "@/app/store/facilityPrecipitation";
|
||||
import { DatePickerRange, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
type PrecipitationModalProps = {
|
||||
searchYear: string;
|
||||
fcltyName: string;
|
||||
facilityCd: string;
|
||||
detailList: PrecipitationPropsDetailProps[];
|
||||
}
|
||||
|
||||
type DateRange = {
|
||||
start: Date;
|
||||
end: Date;
|
||||
}
|
||||
|
||||
export default function PrecipitationModal(props: PrecipitationModalProps) {
|
||||
const { PrecipitationDetail } = useFoStore((state) => state);
|
||||
const { upHeadListPrecipitationDetail } = PrecipitationDetail;
|
||||
|
||||
// Refs
|
||||
const startPickerRef = useRef<HTMLDivElement>(null);
|
||||
const endPickerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// States
|
||||
const [startDate, setStartDate] = useState<Date | null>(null);
|
||||
const [endDate, setEndDate] = useState<Date | null>(null);
|
||||
const [filteredDetailList, setFilteredDetailList] = useState<PrecipitationPropsDetailProps[]>([]);
|
||||
const [copyDetailList, setCopyDetailList] = useState<PrecipitationPropsDetailProps[]>([]);
|
||||
|
||||
const getDateRanges = (): DateRange[] => {
|
||||
const standYear = parseInt(props.searchYear);
|
||||
return [{
|
||||
start: new Date(standYear, 0, 1),
|
||||
end: new Date(standYear, 11, 31)
|
||||
}];
|
||||
};
|
||||
|
||||
const isDateInRanges = (date: Date): boolean => {
|
||||
return getDateRanges().some(range => {
|
||||
const start = new Date(range.start);
|
||||
const end = new Date(range.end);
|
||||
return date >= start && date <= end;
|
||||
});
|
||||
};
|
||||
|
||||
const filterDataByDateRange = (start: Date | null, end: Date | null): PrecipitationPropsDetailProps[] => {
|
||||
if (!start || !end) return filteredDetailList;
|
||||
return filteredDetailList.filter((item) => {
|
||||
const itemDate = new Date(item.rainDt);
|
||||
return itemDate >= start && itemDate <= end;
|
||||
});
|
||||
};
|
||||
|
||||
const handleStartDateSelect = (date: Date | null) => {
|
||||
if (!date || !endDate) return;
|
||||
|
||||
if (date > endDate) {
|
||||
alert('시작일은 종료일 이후일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const filteredData = filterDataByDateRange(date, endDate);
|
||||
setCopyDetailList(filteredData);
|
||||
setStartDate(date);
|
||||
|
||||
const button = startPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEndDateSelect = (date: Date | null) => {
|
||||
if (!date || !startDate) return;
|
||||
|
||||
if (date < startDate) {
|
||||
alert('종료일은 시작일 이전일 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const filteredData = filterDataByDateRange(startDate, date);
|
||||
setCopyDetailList(filteredData);
|
||||
setEndDate(date);
|
||||
|
||||
const button = endPickerRef.current?.querySelector('button');
|
||||
if (button) {
|
||||
setTimeout(() => button.click(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
const calculateTotals = () => {
|
||||
return copyDetailList.reduce((acc, item) => ({
|
||||
infoRnDay: acc.infoRnDay + Number(item.infoRnDay),
|
||||
rainDay: acc.rainDay + Number(item.rainDay),
|
||||
rainEffectDay: acc.rainEffectDay + Number(item.rainEffectDay)
|
||||
}), { infoRnDay: 0, rainDay: 0, rainEffectDay: 0 });
|
||||
};
|
||||
|
||||
const getTableData = () => {
|
||||
const totals = calculateTotals();
|
||||
return [
|
||||
{
|
||||
bscFctCd: "",
|
||||
rainDt: '합계',
|
||||
...totals
|
||||
},
|
||||
...copyDetailList
|
||||
];
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props.detailList.length > 0) {
|
||||
const filteredList = props.detailList.filter((item) =>
|
||||
props.facilityCd === item.bscFctCd
|
||||
);
|
||||
|
||||
setFilteredDetailList(filteredList);
|
||||
setCopyDetailList(filteredList);
|
||||
|
||||
if (filteredList.length > 0) {
|
||||
const firstDateStr = filteredList[0]?.rainDt;
|
||||
const lastDateStr = filteredList[filteredList.length - 1]?.rainDt;
|
||||
|
||||
if (firstDateStr) {
|
||||
const firstDate = new Date(firstDateStr);
|
||||
if (!isNaN(firstDate.getTime())) {
|
||||
setStartDate(firstDate);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDateStr) {
|
||||
const lastDate = new Date(lastDateStr);
|
||||
if (!isNaN(lastDate.getTime())) {
|
||||
setEndDate(lastDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [props.detailList, props.facilityCd]);
|
||||
|
||||
if (!startDate || !endDate) {
|
||||
return <div>로딩 중...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px] !mt-10">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'년월'}</TableHead>
|
||||
<TableCell className="w-1/3">
|
||||
<div className="flex">
|
||||
<div ref={startPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={startDate}
|
||||
onSelect={(date) => handleStartDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={startDate}
|
||||
/>
|
||||
</div>
|
||||
<span className="mx-3">~</span>
|
||||
<div ref={endPickerRef} className="flex justify-center">
|
||||
<DatePickerRange
|
||||
mode="single"
|
||||
selected={endDate}
|
||||
onSelect={(date) => handleEndDateSelect(date as Date)}
|
||||
className="w-full p-1 border rounded bg-white"
|
||||
disabled={(date) => !isDateInRanges(date)}
|
||||
defaultMonth={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv className="h-[450px] overflow-y-auto">
|
||||
<UiTable
|
||||
headName={"강수현황"}
|
||||
tableData={getTableData()}
|
||||
headlist={upHeadListPrecipitationDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
boldArray={[0]}
|
||||
/>
|
||||
</ListDiv>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import PrecipitationModal from "./modal/page";
|
||||
|
||||
export default function FacilityPrecipitation() {
|
||||
const {Common
|
||||
,FacilityPrecipitation
|
||||
,FacilityPrecipitationSearch
|
||||
,PrecipitationDetail
|
||||
,initializeCommonData
|
||||
,searchFacilityPrecipitationList
|
||||
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = FacilityPrecipitationSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
excelList,
|
||||
facilityPrecipitation,
|
||||
facilityPrecipitationCount
|
||||
} = FacilityPrecipitation;
|
||||
|
||||
const {
|
||||
gridListPrecipitationDetail
|
||||
} = PrecipitationDetail;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const facilityPrecipitationList = FacilityPrecipitation?.facilityPrecipitation || [];
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (facilityPrecipitation[index]) {
|
||||
setFcltyNm(facilityPrecipitation[index].bscFctNm);
|
||||
setFcltyCd(facilityPrecipitation[index].bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '시설별 강수현황',
|
||||
sheetNameArray: ['시설별 강수현황'],
|
||||
headerRange: 'A1:N1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
useEffect(() => {
|
||||
if (facilityPrecipitation.length > 0) {
|
||||
|
||||
}
|
||||
}, [facilityPrecipitation]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
console.log('partValue : ', partValue);
|
||||
console.log('regionValue : ', regionValue);
|
||||
console.log('unitWaterShedValue : ', unitWaterShedValue);
|
||||
console.log('middleRegionValue : ', middleRegionValue);
|
||||
console.log('envPartValue : ', envPartValue);
|
||||
console.log('sidoValue : ', sidoValue);
|
||||
console.log('sigunValue : ', sigunValue);
|
||||
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || operationValue!== '0' || fcltCpct !== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchFacilityPrecipitationList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchFacilityPrecipitationList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchFacilityPrecipitationList, searchYear, fcltCpct]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback((searchReturn: ReturnType) => {
|
||||
searchFacilityPrecipitation(searchReturn, 1, 10000);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFacilityPrecipitation(ref.current, page, 10);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
const mainList = facilityPrecipitationList || [];
|
||||
const total = facilityPrecipitationCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="시설별 강수현황" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 강수현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
<span className="text-2xl font-bold text-gray-500">☞ 강우일은 3mm 이상만 해당 / 강우영향일은 강우일 및 강우일 후 연속 2일간으로 정의</span>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<PrecipitationModal searchYear={searchYear} fcltyName={fcltyNm} facilityCd={fcltyCd} detailList={gridListPrecipitationDetail}></PrecipitationModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[72vw] h-[40vw]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
import { TableHead, TableRow } from "@common/components/ui";
|
||||
|
||||
interface TableUpperProps {
|
||||
id: string;
|
||||
title: string;
|
||||
upName?: string;
|
||||
upSequnce?: number;
|
||||
}
|
||||
|
||||
const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProps[], layoutNum: number }) => {
|
||||
return (
|
||||
layoutNum === 0 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
|
||||
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 1 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
|
||||
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 2 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
|
||||
}else if(head.upName==="upChangeRe2"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
|
||||
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 3 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe2"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 4 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe"&&head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={4} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps, idx: number) => {
|
||||
if (head.upName === 'upChangeRe') {
|
||||
if (idx == 1 || idx == 2 || idx == 3) {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
else {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 5 ? ( // 총인설비 수질현황 헤더
|
||||
<>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if(!head.upName) {
|
||||
return <TableHead className="w-[180px] bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
|
||||
}else if(head.upName==="upChangeRe1" && head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
|
||||
}else if(head.upName==="upChangeRe2" && head.upSequnce===1) {
|
||||
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
): (
|
||||
<>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export { HeadMakeColSpan };
|
||||
@@ -0,0 +1,571 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { FacilityWaterQltyProps, modalExcelType } from "@/app/store/facilityWaterQlty";
|
||||
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 FacilityTermModalHeader from "../../../components/common/FacilityTermModalHeader";
|
||||
import { HeadMakeColSpan } from "../HeadMakeColSpan";
|
||||
|
||||
type ModalProps ={
|
||||
fcltyName: string;
|
||||
facilityCd : string;
|
||||
searchYear : string;
|
||||
}
|
||||
|
||||
const tabList1 = [
|
||||
{ value: 'tab_num1', label: '처리시설 수질현황' },
|
||||
{ value: 'tab_num2', label: '총인설비 수질현황' },
|
||||
];
|
||||
|
||||
const tabList2 = [
|
||||
{ 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: '강우시' }
|
||||
];
|
||||
|
||||
const tabList3 = [
|
||||
{ value: 'tab_term_year_chongin', label: '연간' },
|
||||
{ value: 'tab_term_summer_chongin', label: '하절기' },
|
||||
{ value: 'tab_term_winter_chongin', label: '동절기' }
|
||||
];
|
||||
|
||||
export default function WaterQualityModal({fcltyName='', facilityCd='', searchYear=new Date().getFullYear().toString()} : ModalProps) {
|
||||
// 그리드 관련
|
||||
const {FacilityWaterQltyModal,
|
||||
searchFacilityWaterQltyListHist,
|
||||
Common
|
||||
} = useFoStore((state) => state);
|
||||
const {btnClass} = Common;
|
||||
const {
|
||||
upHeadListModalYear,
|
||||
facilityWaterQltyYearList,
|
||||
upHeadListModalTms,
|
||||
tmsList,
|
||||
msrmtDate,
|
||||
upHeadListModalChongIn,
|
||||
} = FacilityWaterQltyModal;
|
||||
|
||||
const prevExcelListRef = useRef<modalExcelType[] | null>(null);
|
||||
|
||||
// 필터링 된 후 최대, 최소, 평균 값 계산
|
||||
const setFilterAfterData = (filteredData: FacilityWaterQltyProps[]) => {
|
||||
// 쉼표가 포함된 문자열을 숫자로 변환하는 함수
|
||||
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 maxEfflWqltBod = 0;
|
||||
let maxEfflWqltTn = 0;
|
||||
let maxEfflWqltTp = 0;
|
||||
let maxefflWqltCod = 0;
|
||||
let maxEfflWqltSs = 0;
|
||||
|
||||
let maxInflAssctAftWqltBod = 0;
|
||||
let maxInflAssctAftWqltTn = 0;
|
||||
let maxInflAssctBfrWqltTp = 0;
|
||||
let maxInflAssctAftWqltToc = 0;
|
||||
let maxInflAssctAftWqltSs = 0;
|
||||
|
||||
let maxTpInflWqltBod = 0;
|
||||
let maxTpInflWqltTp = 0;
|
||||
let maxInfoRnDay = 0;
|
||||
|
||||
// 초기값 설정
|
||||
let minEfflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltBod) : 0;
|
||||
let minEfflWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTn) : 0;
|
||||
let minEfflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTp) : 0;
|
||||
let minefflWqltCod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltCod) : 0;
|
||||
let minEfflWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltSs) : 0;
|
||||
|
||||
let minInflAssctAftWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltBod) : 0;
|
||||
let minInflAssctAftWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltTn) : 0;
|
||||
let minInflAssctBfrWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTp) : 0;
|
||||
let minInflAssctAftWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltToc) : 0;
|
||||
let minInflAssctAftWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctAftWqltSs) : 0;
|
||||
|
||||
let minTpInflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltBod) : 0;
|
||||
let minTpInflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltTp) : 0;
|
||||
|
||||
let minInfoRnDay = filteredData.length > 0 ? parseNumber(filteredData[0]?.infoRnDay) : 0;
|
||||
|
||||
let avgEfflWqltBod = 0;
|
||||
let avgEfflWqltTn = 0;
|
||||
let avgEfflWqltTp = 0;
|
||||
let avgefflWqltCod = 0;
|
||||
let avgEfflWqltSs = 0;
|
||||
|
||||
let avgInflAssctAftWqltBod = 0;
|
||||
let avgInflAssctAftWqltTn = 0;
|
||||
let avgInflAssctBfrWqltTp = 0;
|
||||
let avgInflAssctAftWqltToc = 0;
|
||||
let avgInflAssctAftWqltSs = 0;
|
||||
|
||||
let avgTpInflWqltBod = 0;
|
||||
let avgTpInflWqltTp = 0;
|
||||
|
||||
let avgInfoRnDay = 0;
|
||||
|
||||
filteredData.forEach((item: FacilityWaterQltyProps) => {
|
||||
const efflWqltBod = parseNumber(item.efflWqltBod);
|
||||
const efflWqltTn = parseNumber(item.efflWqltTn);
|
||||
const efflWqltTp = parseNumber(item.efflWqltTp);
|
||||
const efflWqltCod = parseNumber(item.efflWqltCod);
|
||||
const efflWqltSs = parseNumber(item.efflWqltSs);
|
||||
|
||||
const inflAssctAftWqltBod = parseNumber(item.inflAssctAftWqltBod);
|
||||
const inflAssctAftWqltTn = parseNumber(item.inflAssctAftWqltTn);
|
||||
const inflAssctBfrWqltTp = parseNumber(item.inflAssctBfrWqltTp);
|
||||
const inflAssctAftWqltToc = parseNumber(item.inflAssctAftWqltToc);
|
||||
const inflAssctAftWqltSs = parseNumber(item.inflAssctAftWqltSs);
|
||||
|
||||
|
||||
const tpInflWqltBod = parseNumber(item.tpInflWqltBod);
|
||||
const tpInflWqltTp = parseNumber(item.tpInflWqltTp);
|
||||
|
||||
const infoRnDay = parseNumber(item.infoRnDay);
|
||||
|
||||
maxEfflWqltBod = Math.max(maxEfflWqltBod, efflWqltBod);
|
||||
maxEfflWqltTn = Math.max(maxEfflWqltTn, efflWqltTn);
|
||||
maxEfflWqltTp = Math.max(maxEfflWqltTp, efflWqltTp);
|
||||
maxefflWqltCod = Math.max(maxefflWqltCod, efflWqltCod);
|
||||
maxEfflWqltSs = Math.max(maxEfflWqltSs, efflWqltSs);
|
||||
|
||||
maxInflAssctAftWqltBod = Math.max(maxInflAssctAftWqltBod, inflAssctAftWqltBod);
|
||||
maxInflAssctAftWqltTn = Math.max(maxInflAssctAftWqltTn, inflAssctAftWqltTn);
|
||||
maxInflAssctBfrWqltTp = Math.max(maxInflAssctBfrWqltTp, inflAssctBfrWqltTp);
|
||||
maxInflAssctAftWqltToc = Math.max(maxInflAssctAftWqltToc, inflAssctAftWqltToc);
|
||||
maxInflAssctAftWqltSs = Math.max(maxInflAssctAftWqltSs, inflAssctAftWqltSs);
|
||||
|
||||
maxTpInflWqltBod = Math.max(maxTpInflWqltBod, tpInflWqltBod);
|
||||
maxTpInflWqltTp = Math.max(maxTpInflWqltTp, tpInflWqltTp);
|
||||
|
||||
maxInfoRnDay = Math.max(maxInfoRnDay, infoRnDay);
|
||||
|
||||
minEfflWqltBod = Math.min(minEfflWqltBod, efflWqltBod);
|
||||
minEfflWqltTn = Math.min(minEfflWqltTn, efflWqltTn);
|
||||
minEfflWqltTp = Math.min(minEfflWqltTp, efflWqltTp);
|
||||
minefflWqltCod = Math.min(minefflWqltCod, efflWqltCod);
|
||||
minEfflWqltSs = Math.min(minEfflWqltSs, efflWqltSs);
|
||||
|
||||
minInflAssctAftWqltBod = Math.min(minInflAssctAftWqltBod, inflAssctAftWqltBod);
|
||||
minInflAssctAftWqltTn = Math.min(minInflAssctAftWqltTn, inflAssctAftWqltTn);
|
||||
minInflAssctBfrWqltTp = Math.min(minInflAssctBfrWqltTp, inflAssctBfrWqltTp);
|
||||
minInflAssctAftWqltToc = Math.min(minInflAssctAftWqltToc, inflAssctAftWqltToc);
|
||||
minInflAssctAftWqltSs = Math.min(minInflAssctAftWqltSs, inflAssctAftWqltSs);
|
||||
|
||||
minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod);
|
||||
minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp);
|
||||
|
||||
minInfoRnDay = Math.min(minInfoRnDay, infoRnDay);
|
||||
|
||||
avgEfflWqltBod += efflWqltBod;
|
||||
avgEfflWqltTn += efflWqltTn;
|
||||
avgEfflWqltTp += efflWqltTp;
|
||||
avgefflWqltCod += efflWqltCod;
|
||||
avgEfflWqltSs += efflWqltSs;
|
||||
|
||||
avgInflAssctAftWqltBod += inflAssctAftWqltBod;
|
||||
avgInflAssctAftWqltTn += inflAssctAftWqltTn;
|
||||
avgInflAssctBfrWqltTp += inflAssctBfrWqltTp;
|
||||
avgInflAssctAftWqltToc += inflAssctAftWqltToc;
|
||||
avgInflAssctAftWqltSs += inflAssctAftWqltSs;
|
||||
|
||||
avgTpInflWqltBod += tpInflWqltBod;
|
||||
avgTpInflWqltTp += tpInflWqltTp;
|
||||
|
||||
avgInfoRnDay += infoRnDay;
|
||||
});
|
||||
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
efflWqltBod: filteredData.length==0?'0.0':(Math.round(avgEfflWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltCod: filteredData.length==0?'0.0':(Math.round(avgefflWqltCod / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltSs: filteredData.length==0?'0.0':(Math.round(avgEfflWqltSs / filteredData.length * 10) / 10).toFixed(1),
|
||||
efflWqltTn: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTn / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
efflWqltTp: filteredData.length==0?'0.000':(Math.round(avgEfflWqltTp / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctAftWqltBod: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
inflAssctAftWqltTn: filteredData.length==0?'0.000':(Math.round(avgInflAssctAftWqltTn / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctBfrWqltTp: filteredData.length==0?'0.000':(Math.round(avgInflAssctBfrWqltTp / filteredData.length * 1000) / 1000).toFixed(3),
|
||||
inflAssctAftWqltToc: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltToc / filteredData.length * 10) / 10).toFixed(1),
|
||||
inflAssctAftWqltSs: filteredData.length==0?'0.0':(Math.round(avgInflAssctAftWqltSs / filteredData.length * 10) / 10).toFixed(1),
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
sidoNm: "",
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: filteredData.length==0?'0.0':(Math.round(avgInfoRnDay / filteredData.length * 10) / 10).toFixed(1),
|
||||
tpInflWqltBod: filteredData.length==0?'0.0':(Math.round(avgTpInflWqltBod / filteredData.length * 10) / 10).toFixed(1),
|
||||
tpInflWqltTp: filteredData.length==0?'0.000':(Math.round(avgTpInflWqltTp / filteredData.length * 1000) / 1000).toFixed(3)
|
||||
},
|
||||
{
|
||||
msrDt : '최대',
|
||||
efflWqltBod : Math.round(maxEfflWqltBod * 10) / 10?(Math.round(maxEfflWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltCod : Math.round(maxefflWqltCod * 10) / 10?(Math.round(maxefflWqltCod * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltSs : Math.round(maxEfflWqltSs * 10) / 10?(Math.round(maxEfflWqltSs * 10) / 10).toFixed(1):'0.0',
|
||||
efflWqltTn : Math.round(maxEfflWqltTn * 1000) / 1000?(Math.round(maxEfflWqltTn * 1000) / 1000).toFixed(3):'0.000',
|
||||
efflWqltTp : Math.round(maxEfflWqltTp * 1000) / 1000?(Math.round(maxEfflWqltTp * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctAftWqltBod : Math.round(maxInflAssctAftWqltBod * 10) / 10?(Math.round(maxInflAssctAftWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
inflAssctAftWqltTn : Math.round(maxInflAssctAftWqltTn * 1000) / 1000?(Math.round(maxInflAssctAftWqltTn * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctBfrWqltTp : Math.round(maxInflAssctBfrWqltTp * 1000) / 1000?(Math.round(maxInflAssctBfrWqltTp * 1000) / 1000).toFixed(3):'0.000',
|
||||
inflAssctAftWqltToc : Math.round(maxInflAssctAftWqltToc * 10) / 10?(Math.round(maxInflAssctAftWqltToc * 10) / 10).toFixed(1):'0.0',
|
||||
inflAssctAftWqltSs : Math.round(maxInflAssctAftWqltSs * 10) / 10?(Math.round(maxInflAssctAftWqltSs * 10) / 10).toFixed(1):'0.0',
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
sidoNm: "",
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: 0,
|
||||
tpInflWqltBod: Math.round(maxTpInflWqltBod * 10) / 10?(Math.round(maxTpInflWqltBod * 10) / 10).toFixed(1):'0.0',
|
||||
tpInflWqltTp: Math.round(maxTpInflWqltTp * 1000) / 1000?(Math.round(maxTpInflWqltTp * 1000) / 1000).toFixed(3):'0.000'
|
||||
},
|
||||
{
|
||||
msrDt : '최소',
|
||||
efflWqltBod : Math.round(minEfflWqltBod * 10) / 10?(Math.round(minEfflWqltBod?minEfflWqltBod:0 * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltCod : Math.round(minefflWqltCod * 10) / 10?(Math.round(minefflWqltCod?minefflWqltCod:0 * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltSs : Math.round(minEfflWqltSs * 10) / 10?(Math.round(minEfflWqltSs * 10) / 10).toFixed(1) : '0.0',
|
||||
efflWqltTn : Math.round(minEfflWqltTn * 1000) / 1000?(Math.round(minEfflWqltTn * 1000) / 1000).toFixed(3) : '0.000',
|
||||
efflWqltTp : Math.round(minEfflWqltTp * 1000) / 1000?(Math.round(minEfflWqltTp * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctAftWqltBod : Math.round(minInflAssctAftWqltBod * 10) / 10?(Math.round(minInflAssctAftWqltBod * 10) / 10).toFixed(1) : '0.0',
|
||||
inflAssctAftWqltTn : Math.round(minInflAssctAftWqltTn * 1000) / 1000?(Math.round(minInflAssctAftWqltTn * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctBfrWqltTp : Math.round(minInflAssctBfrWqltTp * 1000) / 1000?(Math.round(minInflAssctBfrWqltTp * 1000) / 1000).toFixed(3) : '0.000',
|
||||
inflAssctAftWqltToc : Math.round(minInflAssctAftWqltToc * 10) / 10?(Math.round(minInflAssctAftWqltToc * 10) / 10).toFixed(1) : '0.0',
|
||||
inflAssctAftWqltSs : Math.round(minInflAssctAftWqltSs * 10) / 10?(Math.round(minInflAssctAftWqltSs * 10) / 10).toFixed(1) : '0.0',
|
||||
bscFctCd: "",
|
||||
bscFctNm: "",
|
||||
lclgvrnmntNm: "",
|
||||
sidoNm: "",
|
||||
sggNm: "",
|
||||
addr: "",
|
||||
fctCpc: 0,
|
||||
infoRnDay: 0,
|
||||
tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10?'0.0':(Math.round(minTpInflWqltBod * 10) / 10).toFixed(1),
|
||||
tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000?'0.000':(Math.round(minTpInflWqltTp * 1000) / 1000).toFixed(3)
|
||||
},
|
||||
...filteredData
|
||||
];
|
||||
return newFilteredData;
|
||||
}
|
||||
|
||||
// 날짜 필터링 관련 상태
|
||||
const [copyYearList, setCopyYearList] = useState<FacilityWaterQltyProps[]>([]);
|
||||
const [chongInWaterQltyYearList, setChongInWaterQltyYearList] = useState<FacilityWaterQltyProps[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
searchFacilityWaterQltyListHist(searchYear, facilityCd);
|
||||
}, [searchYear, facilityCd, searchFacilityWaterQltyListHist]);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredYearData = setFilterAfterData(facilityWaterQltyYearList);
|
||||
setCopyYearList(filteredYearData as FacilityWaterQltyProps[]);
|
||||
setChongInWaterQltyYearList(filteredYearData as FacilityWaterQltyProps[]);
|
||||
}, [facilityWaterQltyYearList]);
|
||||
|
||||
const yesterDay = new Date();
|
||||
yesterDay.setDate(yesterDay.getDate() - 1);
|
||||
const yesterDayStr = yesterDay.toISOString().split('T')[0];
|
||||
|
||||
const ref = useRef<ReturnType<FacilityWaterQltyProps>>({
|
||||
startDate: new Date(),
|
||||
endDate: new Date(),
|
||||
tabName: '',
|
||||
filteredList: [],
|
||||
});
|
||||
|
||||
const filterData = useCallback((returnType: ReturnType<FacilityWaterQltyProps>) => {
|
||||
const filteredData = setFilterAfterData(returnType.filteredList);
|
||||
setCopyYearList(filteredData as FacilityWaterQltyProps[]);
|
||||
}, []);
|
||||
|
||||
const excelDownload = () => {
|
||||
const excelDownList: modalExcelType[] = [];
|
||||
if(copyYearList.length > 0){
|
||||
copyYearList.forEach((item) => {
|
||||
excelDownList.push({
|
||||
날짜: item.msrDt,
|
||||
"유입BOD(mg/L)": item.inflAssctAftWqltBod,
|
||||
"유입TOC(COD)(mg/L)": item.inflAssctAftWqltToc,
|
||||
"유입SS(mg/L)": item.inflAssctAftWqltSs,
|
||||
"유입TN(mg/L)": item.inflAssctAftWqltTn,
|
||||
"유입TP(mg/L)": item.inflAssctBfrWqltTp,
|
||||
"유출BOD(mg/L)": item.efflWqltBod,
|
||||
"유출TOC(COD)(mg/L)": item.efflWqltCod,
|
||||
"유출SS(mg/L)": item.efflWqltSs,
|
||||
"유출TN(mg/L)": item.efflWqltTn,
|
||||
"유출TP(mg/L)": item.efflWqltTp,
|
||||
"강우량(일)": item.infoRnDay?item.infoRnDay.toString():"0.0",
|
||||
});
|
||||
});
|
||||
}
|
||||
if (excelDownList && excelDownList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: searchYear+'년 '+fcltyName + ' 수질현황', sheetNameArray: [fcltyName + ' 수질현황'], headerRange: 'A1:L1' });
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
prevExcelListRef.current = excelDownList;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<UITab tabList={tabList1} defaultValue="tab_num1">
|
||||
<Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}>
|
||||
{"엑셀다운로드"}
|
||||
</Button>
|
||||
{/* 처리시설 수질현황 */}
|
||||
<TabsContent value="tab_num1">
|
||||
<UITab tabList={tabList2} defaultValue="tab_term_year">
|
||||
<TabsContent value="tab_term_year">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName={"tab_term_year"}
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[350px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[310px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">수질 TMS</h3>
|
||||
<h3 className="text-2xl font-medium text-label text-right">({msrmtDate?msrmtDate.substring(0,4)+'-'+msrmtDate.substring(4,6)+'-'+msrmtDate.substring(6,8):yesterDayStr})</h3>
|
||||
</div>
|
||||
<div className="overflow-y-auto h-[250px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={tmsList}
|
||||
headlist={upHeadListModalTms}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalTms} layoutNum={4} />
|
||||
</UiTable>
|
||||
{msrmtDate != yesterDayStr?.replaceAll('-','')?<h3 className="text-2xl text-left text-gray-500">※전날 데이터 결측으로 인해 가장 최근 데이터 표출함</h3> : ''}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_summer">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_summer"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { } }
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_winter">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_winter"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_chuncheon">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_chuncheon"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_rain">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={facilityWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_rain"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalYear} layoutNum={3} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</TabsContent>
|
||||
|
||||
{/* 총인설비 수질현황 */}
|
||||
<TabsContent value="tab_num2">
|
||||
<UITab tabList={tabList3} defaultValue="tab_term_year_chongin">
|
||||
<TabsContent value="tab_term_year_chongin">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={chongInWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_year"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalChongIn}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_summer_chongin">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={chongInWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_summer"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalChongIn}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_winter_chongin">
|
||||
<FacilityTermModalHeader<FacilityWaterQltyProps>
|
||||
searchList={chongInWaterQltyYearList}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_winter"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/>
|
||||
<div className="overflow-y-auto h-[550px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListModalChongIn}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadListModalChongIn} layoutNum={5} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
"use client"
|
||||
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import WaterQualityModal from "./modal/page";
|
||||
import type { FacilityWaterQltyProps } from "@/app/store/facilityWaterQlty";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const { Common
|
||||
, FacilityWaterQltyMain
|
||||
, initializeCommonData
|
||||
, searchFacilityWaterQltyList
|
||||
} = useFoStore((state) => state) || { FacilityWaterQltyList: { facilityWaterQltyList: [], facilityWaterQltyCount: 0 } };
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
mainLabelArray,
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
facilityWaterQltyList,
|
||||
facilityWaterQltyCount,
|
||||
excelList
|
||||
} = FacilityWaterQltyMain;
|
||||
|
||||
const mainList: FacilityWaterQltyProps[] = facilityWaterQltyList || [];
|
||||
|
||||
// 그리드 관련
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
const [modalYear, setModalYear] = useState<string>("");
|
||||
|
||||
const searchFcltyQltyList = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr;
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchFacilityWaterQltyList(pageNo, pageCnt, searchYearValue);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchFacilityWaterQltyList, searchYearValue, fcltCpct]);
|
||||
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYearValue(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
const facility = facilityWaterQltyList[index];
|
||||
if (facility) {
|
||||
setFcltyNm(facility.bscFctNm);
|
||||
setFcltyCd(facility.bscFctCd);
|
||||
setModalYear(searchYearValue);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
}
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFacilityWaterQltyList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '시설별 수질현황',
|
||||
sheetNameArray: ['시설별 수질현황'],
|
||||
headerRange: 'A1:T1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFcltyQltyList(ref.current, 1, 10000);
|
||||
}, [searchFcltyQltyList]);
|
||||
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFcltyQltyList(ref.current, page, 10);
|
||||
}, [searchFcltyQltyList]);
|
||||
|
||||
const total = facilityWaterQltyCount || 1;
|
||||
console.log('total : ', total);
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="시설별 수질현황" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={mainLabelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className="col-span-3" label={mainLabelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={mainLabelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={mainLabelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 수질현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total<10?facilityWaterQltyList.length:total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<WaterQualityModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={modalYear}></WaterQualityModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1200px] h-[920px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
"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";
|
||||
|
||||
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 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);
|
||||
|
||||
let avgtotInflAmnt = 0;
|
||||
let avginflAmnt = 0;
|
||||
let avgsumFlow = 0;
|
||||
let avgreturnAmnt = 0;
|
||||
let avgefflAmnt = 0;
|
||||
let avginfoRnDay = 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);
|
||||
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;
|
||||
});
|
||||
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
totInflAmnt: Math.round(avgtotInflAmnt / filteredData.length * 10) / 10,
|
||||
inflAmnt: Math.round(avginflAmnt / filteredData.length * 10) / 10,
|
||||
sumFlow: Math.round(avgsumFlow / filteredData.length * 10) / 10,
|
||||
returnAmnt: Math.round(avgreturnAmnt / filteredData.length * 10) / 10,
|
||||
efflAmnt: Math.round(avgefflAmnt / filteredData.length * 10) / 10,
|
||||
infoRnDay: avginfoRnDay > 0 ? Math.round(avginfoRnDay / filteredData.length * 10) / 10 : 0,
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
{
|
||||
msrDt: '최대',
|
||||
totInflAmnt: Math.round(maxtotInflAmnt * 10) / 10,
|
||||
inflAmnt: Math.round(maxinflAmnt * 10) / 10,
|
||||
sumFlow: Math.round(maxsumFlow * 10) / 10,
|
||||
returnAmnt: Math.round(maxreturnAmnt * 10) / 10,
|
||||
efflAmnt: Math.round(maxefflAmnt * 10) / 10,
|
||||
infoRnDay: maxinfoRnDay > 0 ? (Math.round(maxinfoRnDay * 10) / 10).toFixed(1) : '0.0',
|
||||
rainEffectDay: 0,
|
||||
},
|
||||
{
|
||||
msrDt: '최소',
|
||||
totInflAmnt: Math.round(mintotInflAmnt * 10) / 10,
|
||||
inflAmnt: Math.round(mininflAmnt * 10) / 10,
|
||||
sumFlow: Math.round(minsumFlow * 10) / 10,
|
||||
returnAmnt: Math.round(minreturnAmnt * 10) / 10,
|
||||
efflAmnt: Math.round(minefflAmnt * 10) / 10,
|
||||
infoRnDay: mininfoRnDay > 0 ? (Math.round(mininfoRnDay * 10) / 10).toFixed(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,
|
||||
"강우량": 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-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</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-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</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-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</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-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable
|
||||
headName="유량현황"
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListFlowRateModalYear}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[370px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</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-auto">
|
||||
<div className="w-[120%]">
|
||||
<UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} className="h-[370px]" boldArray={[0,1,2]}/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import FlowRateModal from "./modal/page";
|
||||
import type { ExcelType } from "@/app/store/flowRate";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const {Common
|
||||
,FlowRateSearch
|
||||
,FlowRateList
|
||||
,initializeCommonData
|
||||
,searchFlowRateList
|
||||
} = useFoStore((state) => state);
|
||||
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectSearchYear,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
flowRateSearchLabelArray
|
||||
} = FlowRateSearch;
|
||||
|
||||
// 그리드 관련
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
flowRateList,
|
||||
flowRateCount,
|
||||
excelList
|
||||
} = FlowRateList;
|
||||
|
||||
// 입력값 상태 관리
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
const prevExcelListRef = useRef<ExcelType[] | null>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
const searchFlowRate = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchFlowRateList(pageNo, pageCnt, searchYearValue, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchFlowRateList(pageNo, pageCnt, searchYearValue);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchFlowRateList, searchYearValue, fcltCpct]);
|
||||
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYearValue(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (flowRateList[index]) {
|
||||
setFcltyNm(flowRateList[index].bscFctNm);
|
||||
setFcltyCd(flowRateList[index].bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
// 페이지 네비게이션션
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFlowRate(ref.current, page, 10);
|
||||
}, [searchFlowRate]);
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 시도 데이터 초기화
|
||||
useEffect(() => {
|
||||
if(!isInit) {
|
||||
initializeCommonData();
|
||||
searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchFlowRateList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({ data: JSON.parse(JSON.stringify(excelList)), fileName: '시설별 유량현황', sheetNameArray: ['시설별 유량현황'], headerRange: 'A1:O1' });
|
||||
} else if (prevExcelListRef.current && prevExcelListRef.current.length > 0) {
|
||||
alert('다운받을 데이터가 없습니다.');
|
||||
}
|
||||
prevExcelListRef.current = excelList;
|
||||
}, [excelList]);
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFlowRate(ref.current, 1, 10000);
|
||||
}, [searchFlowRate]);
|
||||
|
||||
const total = flowRateCount;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="시설별 유량현황" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={flowRateSearchLabelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className="col-span-3" label={flowRateSearchLabelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={flowRateSearchLabelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={flowRateSearchLabelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"시설별 유량현황"} tableData={flowRateList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<FlowRateModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={searchYearValue}></FlowRateModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1050px] h-[700px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open: boolean) => !open && closeModal()}
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
"use client";
|
||||
|
||||
import Gis from "@common/business_components/ui/map/Gis";
|
||||
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
interface FeatureData {
|
||||
fid?: string;
|
||||
ftrIdn?: string;
|
||||
id?: string;
|
||||
getGeometry?: () => { getExtent: () => number[] };
|
||||
setStyle?: () => void;
|
||||
}
|
||||
|
||||
interface MapInstance {
|
||||
getLayers: () => { getArray: () => Array<{ getSource?: () => { getFeatureById?: (id: string) => FeatureData | null } }> };
|
||||
getView: () => { fit: (extent: number[], options: object) => void };
|
||||
}
|
||||
|
||||
const Map = () => {
|
||||
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
|
||||
const gisMaps = useRef<MapInstance | null>(null);
|
||||
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
|
||||
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태
|
||||
const [featureData, setFeatureData] = useState<FeatureData | null>(null); // 선택된 피쳐 데이터
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}/v1/map`
|
||||
const reqUrl = `${API_URL}/lyrStngs/FO_NETWORK`;
|
||||
const response = await fetch(reqUrl, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP 오류! 상태: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json(); // 여기서 json 파싱
|
||||
setTreeData(data); // 데이터 설정
|
||||
} catch (error) {
|
||||
console.error("데이터 불러오기 실패:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// 컴포넌트 마운트 시 1회 실행
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
// SearchModal, GisContent 등에서 호출
|
||||
const onFeatureSelect = (data: FeatureData) => {
|
||||
const map = gisMaps.current;
|
||||
if (!map) {
|
||||
console.warn("지도가 초기화되지 않았습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 항상 같은 select 객체 사용
|
||||
const select = (GisApp.Module.select as unknown) as { resetSelectedFeature: () => void; selectFeature: (feature: FeatureData, selected: boolean) => void } | undefined;
|
||||
if (!select) return;
|
||||
|
||||
// 1. 기존 선택 초기화
|
||||
select.resetSelectedFeature();
|
||||
|
||||
// 2. data가 OpenLayers Feature 인스턴스인지 확인
|
||||
let foundFeature: FeatureData | null = null;
|
||||
if (
|
||||
data &&
|
||||
typeof data.getGeometry === "function" &&
|
||||
typeof data.setStyle === "function"
|
||||
) {
|
||||
// 이미 Feature 인스턴스라면 그대로 사용
|
||||
foundFeature = data;
|
||||
} else {
|
||||
// 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용
|
||||
const featureId = data.fid || data.ftrIdn || data.id;
|
||||
map
|
||||
.getLayers()
|
||||
.getArray()
|
||||
.forEach((layer) => {
|
||||
const source = layer.getSource?.();
|
||||
if (source?.getFeatureById) {
|
||||
const feature = source.getFeatureById(String(featureId).trim());
|
||||
if (feature) foundFeature = feature;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3. 피처 선택
|
||||
if (foundFeature && foundFeature.getGeometry) {
|
||||
const geometry = foundFeature.getGeometry();
|
||||
if (geometry) {
|
||||
const extent = geometry.getExtent();
|
||||
|
||||
map.getView().fit(extent, {
|
||||
duration: 300,
|
||||
padding: [50, 50, 50, 50],
|
||||
maxZoom: 16,
|
||||
constrainResolution: true,
|
||||
nearest: true,
|
||||
});
|
||||
}
|
||||
select.selectFeature(foundFeature, true);
|
||||
} else {
|
||||
console.warn("OpenLayers Feature를 찾을 수 없습니다:", data);
|
||||
}
|
||||
|
||||
setFeatureData(data);
|
||||
setIsOpen(true);
|
||||
setIsSearchModalOpen(false);
|
||||
};
|
||||
|
||||
// onCheckedLayersChange handler
|
||||
const handleCheckedLayersChange = (checkedIds: string[], checkedNodesData: unknown[]) => {
|
||||
// Handle checked layers change if needed
|
||||
console.log('Checked layers changed:', checkedIds, checkedNodesData);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-container">
|
||||
<Gis
|
||||
treeData={treeData}
|
||||
isSearch={false}
|
||||
gisMaps={gisMaps}
|
||||
isMiniMap={true}
|
||||
searchView={null}
|
||||
detailView={null}
|
||||
onFeatureSelect={onFeatureSelect}
|
||||
setIsOpen={setIsOpen}
|
||||
setFeatureData={setFeatureData}
|
||||
featureData={featureData}
|
||||
setIsSearchModalOpen={setIsSearchModalOpen}
|
||||
isOpen={isOpen}
|
||||
isSearchModalOpen={isSearchModalOpen}
|
||||
onCheckedLayersChange={handleCheckedLayersChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Map;
|
||||
@@ -0,0 +1,197 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
export default function PlanSewage() {
|
||||
const {Common
|
||||
,PlanSewage
|
||||
,PlanSewageSearch
|
||||
,initializeCommonData
|
||||
,searchPlanSewageList
|
||||
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = PlanSewageSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
planSewageList,
|
||||
planSewageCount,
|
||||
excelList
|
||||
} = PlanSewage;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1);
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchPlanSewageList(1, 10, searchYear, ref.current.partValue);
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchYear, searchPlanSewageList]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('excelList' , excelList);
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '계획하수량 산정지표 현황',
|
||||
sheetNameArray: ['계획하수량 산정지표 현황'],
|
||||
headerRange: 'A1:M1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchPlanSewage = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchPlanSewageList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchPlanSewageList(pageNo, pageCnt, searchYear, partValue);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchPlanSewageList, searchYear, fcltCpct]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback((searchReturn: ReturnType) => {
|
||||
searchPlanSewage(searchReturn, 1, 10000);
|
||||
}, [searchPlanSewage]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchPlanSewage(ref.current, page, 10);
|
||||
}, [searchPlanSewage]);
|
||||
|
||||
const mainList = planSewageList || [];
|
||||
const total = planSewageCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="계획하수량 산정지표 현황" />
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false}/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={ undefined } headName={"계획하수량 산정지표 현황"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import { TableHead, TableRow } from "@common/components/ui";
|
||||
import type { TableUpperProps } from "../../store/dashboard";
|
||||
|
||||
const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProps[], layoutNum: number }) => {
|
||||
return (
|
||||
layoutNum === 0 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={3} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={2}>{'행정구역'}</TableHead> :
|
||||
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
|
||||
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={19}>{'시설계획'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => (
|
||||
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
|
||||
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
|
||||
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
|
||||
null
|
||||
))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe' || head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : layoutNum === 1 ? (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={3} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={3} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={3}>{'유역'}</TableHead> :
|
||||
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => (
|
||||
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
|
||||
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
|
||||
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
|
||||
null
|
||||
))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe' || head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
|
||||
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
|
||||
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
|
||||
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'환경청'}</TableHead> :
|
||||
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
|
||||
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
|
||||
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
|
||||
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
|
||||
</TableRow>
|
||||
<TableRow className="bg-gray-50">
|
||||
{upHeadList.map((head: TableUpperProps) => {
|
||||
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' ||head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
|
||||
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
|
||||
}
|
||||
})}
|
||||
</TableRow>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { HeadMakeColSpan };
|
||||
@@ -0,0 +1,55 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableHeader, TableRow } from "@common/components/ui";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function ProcessFacilityInfoModal(props: { fcltyName: string; facilityCd : string;}) {
|
||||
// 그리드 관련
|
||||
const {ProcessAreaDetail, initModalData} = useFoStore((state) => state);
|
||||
|
||||
useEffect(() => {
|
||||
initModalData(props.facilityCd);
|
||||
}, [initModalData, props.facilityCd]);
|
||||
|
||||
const {
|
||||
upHeadListFcltyImproveInfo,
|
||||
gridListFcltyImproveInfo,
|
||||
upHeadListProcessPopulation,
|
||||
gridListProcessPopulation,
|
||||
upHeadListProcessAreaPlan,
|
||||
gridListProcessAreaPlan,
|
||||
} = ProcessAreaDetail
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv>
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설코드'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.facilityCd}</TableCell>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<UiTable headName={"시설증설 계획"} tableData={gridListFcltyImproveInfo} headlist={upHeadListFcltyImproveInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
</UiTable>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<UiTable headName={"처리인구 계획"} tableData={gridListProcessPopulation} headlist={upHeadListProcessPopulation} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
</UiTable>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<UiTable headName={"처리구역 계획"} tableData={gridListProcessAreaPlan} headlist={upHeadListProcessAreaPlan} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
</UiTable>
|
||||
</ListDiv>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import ProcessFacilityInfoModal from "./modal/page";
|
||||
|
||||
export default function ProcessArea() {
|
||||
const {Common,
|
||||
ProcessArea,
|
||||
ProcessAreaSearch,
|
||||
initializeCommonData,
|
||||
searchProcessAreaList
|
||||
} = useFoStore((state) => state) || {
|
||||
Common: { isInit: false, selectSidoData: [], selectSigunData: [], selectRegionData: [], selectUnitWaterShedData: [], selectMiddleRegionData: [], selectEnvPartData: [], selectSearchYear: [{ val: "0" }], btnClass: "" },
|
||||
ProcessArea: { processAreaList: [], processAreaCount: 0, excelList: [], upHeadList1: [] },
|
||||
ProcessAreaSearch: { processFacilityLabelArray: [] },
|
||||
initializeCommonData: () => {},
|
||||
searchProcessAreaList: () => {}
|
||||
};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass,
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
processFacilityLabelArray,
|
||||
} = ProcessAreaSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
processAreaList,
|
||||
processAreaCount,
|
||||
excelList
|
||||
} = ProcessArea;
|
||||
|
||||
const mainList: Record<string, unknown>[] = processAreaList || [];
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const searchProcessArea = useCallback(({ sidoText, sigunText}: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
searchProcessAreaList(pageNo, pageCnt, sidoText, sigunText, searchYearValue);
|
||||
}, [searchProcessAreaList, searchYearValue]);
|
||||
|
||||
// 조회
|
||||
const chkVal = useCallback(() => {
|
||||
setResetPage(true);
|
||||
}, []);
|
||||
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
setSearchYearValue(selectSearchYear[0]?.val || "0");
|
||||
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val);
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (processAreaList[index]) {
|
||||
setFcltyNm(processAreaList[index].swtrmtFcltNm);
|
||||
setFcltyCd(processAreaList[index].swtrmtFcltCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val);
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchProcessAreaList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '처리구역정보',
|
||||
sheetNameArray: ['처리구역정보'],
|
||||
headerRange: 'A1:W1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchProcessArea(ref.current, 1, 10000);
|
||||
}, [searchProcessArea]);
|
||||
|
||||
const handlePageChange = useCallback((pageNo: number) => {
|
||||
setResetPage(false);
|
||||
searchProcessArea(ref.current, pageNo, 10);
|
||||
}, [searchProcessArea]);
|
||||
|
||||
const total = processAreaCount;
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="처리구역정보" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[6] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYearValue(val.toString())} value={searchYearValue} selectClass={undefined}/>
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref}
|
||||
isAdmin={true}
|
||||
/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className="w-[180%]">
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"처리구역정보"} tableData={mainList} headlist={upHeadList1} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<ProcessFacilityInfoModal fcltyName={fcltyNm} facilityCd={fcltyCd}></ProcessFacilityInfoModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1200px] h-[900px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open: boolean) => !open && closeModal()}
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/dashboard";
|
||||
import { UITab, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import {
|
||||
TabsContent
|
||||
} from "@common/components";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
|
||||
type ModalType = {
|
||||
fcltyName: string;
|
||||
facilityCd : string;
|
||||
sido : string;
|
||||
gugun : string;
|
||||
daddr : string;
|
||||
fctCpc : number | '';
|
||||
trtFrfNm : string;
|
||||
rnDt : string;
|
||||
cmplDt : string;
|
||||
trstOprEtpNm : string;
|
||||
bscFctClsNm : string;
|
||||
mnstr : string;
|
||||
efflWtrrgn : string;
|
||||
lgbsn : string;
|
||||
efflWqltStndrdNm : string;
|
||||
rgnNm : string;
|
||||
rvbsn : string;
|
||||
}
|
||||
|
||||
// 시설계획 table header 변경
|
||||
const headMakeList = (upHeadList: TableUpperProps[], gridNum:number) => {
|
||||
if(gridNum===1){
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'증설계획(m³/일)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe'?<TableHead className="w-150" key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
} else if(gridNum===2){
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe1'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'계획유입수질(mg/L)'}</TableHead>:
|
||||
head.upName === 'upChangeRe2'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'설계유입수질(mg/L)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe1'||head.upName === 'upChangeRe2'?<TableHead style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
} else if(gridNum===3){
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe1'&& head.upSequnce=== 1?<TableHead key={head.id} colSpan={2} style={{ whiteSpace: 'pre-line' }}>{'사업기간'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
} else if(gridNum===4){
|
||||
return ( <>
|
||||
<TableRow>{
|
||||
upHeadList.map((head: TableUpperProps) =>
|
||||
(!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
|
||||
head.upName === 'upChangeRe1'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'계획유입수질(mg/L)'}</TableHead>:
|
||||
head.upName === 'upChangeRe2'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'설계유입수질(mg/L)'}</TableHead>:
|
||||
head.upName === 'upChangeRe3'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={6} style={{ whiteSpace: 'pre-line' }}>{'계획방류수질(mg/L)'}</TableHead>:null))}
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
{upHeadList.map((head: TableUpperProps) =>
|
||||
(head.upName === 'upChangeRe1'||head.upName === 'upChangeRe2'||head.upName === 'upChangeRe3'?<TableHead style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>:null))}
|
||||
</TableRow>
|
||||
</> )
|
||||
}
|
||||
}
|
||||
|
||||
export default function ProcessFacilityInfoModal(props: ModalType) {
|
||||
// 그리드 관련
|
||||
const {ProcessFacilityDetail} = useFoStore((state) => state);
|
||||
|
||||
const {
|
||||
upHeadListPlanInfo,
|
||||
gridListPlanInfo,
|
||||
upHeadListFcltyAreaInfo,
|
||||
gridListFcltyAreaInfo,
|
||||
|
||||
upHeadListFcltyHistInfo,
|
||||
gridListFcltyHistInfo,
|
||||
upHeadListFcltyWaterQltyInfo,
|
||||
gridListFcltyWaterQltyInfo,
|
||||
|
||||
upHeadListLegalWaterQlty,
|
||||
gridListLegalWaterQlty,
|
||||
} = ProcessFacilityDetail;
|
||||
|
||||
gridListFcltyAreaInfo.map((item) => {
|
||||
item.efflWtrrgn = props.efflWtrrgn;
|
||||
item.lgbsn = props.lgbsn;
|
||||
item.efflWqltStndrdNm = props.efflWqltStndrdNm;
|
||||
item.rgnNm = props.rgnNm;
|
||||
item.rvbsn = props.rvbsn;
|
||||
})
|
||||
|
||||
const tabList = [
|
||||
{ value: 'common_info', label: '기본정보' },
|
||||
{ value: 'history_info', label: '이력정보' },
|
||||
];
|
||||
const fctCpc = props.fctCpc ? props.fctCpc.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : '';
|
||||
const upHeadListPlanInfoChange = headMakeList(upHeadListPlanInfo, 2);
|
||||
const upHeadListFcltyHistInfoChange = headMakeList(upHeadListFcltyHistInfo, 3);
|
||||
const upHeadListFcltyWaterQltyInfoChange = headMakeList(upHeadListFcltyWaterQltyInfo, 4);
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설코드'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.facilityCd}</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto">
|
||||
<div className="!h-[600px]">
|
||||
<ListDiv className="">
|
||||
<UITab tabList={tabList} defaultValue="common_info">
|
||||
<TabsContent value="common_info">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">시설 기본정보</h3>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설구분'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.bscFctClsNm}</TableCell>
|
||||
<TableHead className="w-1/6">{'시설용량(m³/일)'}</TableHead>
|
||||
<TableCell className="w-1/6">{fctCpc}</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시도'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.sido}</TableCell>
|
||||
<TableHead className="w-1/6">{'시군구'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.gugun}</TableCell>
|
||||
<TableHead className="w-1/6">{'가동개시일'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.rnDt}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'주소'}</TableHead>
|
||||
<TableCell className="w-1/6" colSpan={3}>{props.daddr}</TableCell>
|
||||
<TableHead className="w-1/6">{'준공일'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.cmplDt}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'공법'}</TableHead>
|
||||
<TableCell className="w-1/6" colSpan={3}>{props.trtFrfNm}</TableCell>
|
||||
<TableHead className="w-1/6">{'관리대행업자'}</TableHead>
|
||||
<TableCell className="w-1/6">{props.trstOprEtpNm}</TableCell>
|
||||
</TableRow>
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
<UiTable headName={"시설 계획정보"} tableData={gridListPlanInfo} headlist={upHeadListPlanInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListPlanInfoChange}
|
||||
</UiTable>
|
||||
<UiTable headName={"시설 법적방류수질"} tableData={gridListLegalWaterQlty} headlist={upHeadListLegalWaterQlty} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}} />
|
||||
<UiTable headName={"시설 수역 및 구역정보"} tableData={gridListFcltyAreaInfo} headlist={upHeadListFcltyAreaInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="history_info">
|
||||
<ListDiv>
|
||||
<div className="h-[270px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<div className="h-[130%]">
|
||||
<UiTable headName={"시설 이력관리"} tableData={gridListFcltyHistInfo} headlist={upHeadListFcltyHistInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListFcltyHistInfoChange}
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv>
|
||||
<div className="h-[270px] w-full overflow-y-auto overflow-x-hidden">
|
||||
<div className="h-[130%]">
|
||||
<UiTable headName={"시설 수질정보"} tableData={gridListFcltyWaterQltyInfo} headlist={upHeadListFcltyWaterQltyInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}>
|
||||
{upHeadListFcltyWaterQltyInfoChange}
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</ListDiv>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
"use client"
|
||||
import { HeadMakeColSpan } from "@/app/components/common/HeadMakeColSpan";
|
||||
import { useFoStore } from "@/app/store";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import ProcessFacilityInfoModal from "./modal/page";
|
||||
|
||||
export default function ProcessFacilitySearch() {
|
||||
const {Common
|
||||
,ProcessFacility
|
||||
,ProcessFacilityList
|
||||
,initializeCommonData
|
||||
//시설데이터 조회
|
||||
,searchProcessFacility
|
||||
//시설데이터 이력정보 조회
|
||||
,searchProcessFacilityHist
|
||||
//시설데이터 수질정보 조회
|
||||
,searchProcessFacilityWaterQlty
|
||||
} = useFoStore((state) => state) || { ProcessFacilityList: { processFacilityList: [], processFacilityCount: 0 }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectFacilityPartData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
btnClass,
|
||||
} = Common;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if(!isInit) {
|
||||
initializeCommonData();
|
||||
searchProcessFacility(1, 10, 'A', '0', '0', '0', '0');
|
||||
}
|
||||
}, [isInit
|
||||
,initializeCommonData
|
||||
,searchProcessFacility
|
||||
]);
|
||||
|
||||
const {
|
||||
processFacilityLabelArray,
|
||||
} = ProcessFacility;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
excelList
|
||||
} = ProcessFacilityList;
|
||||
|
||||
const processFacilityList = ProcessFacilityList?.processFacilityList || [];
|
||||
|
||||
// 그리드 관련
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
const [facilityPartValue, setFacilityPartValue] = useState<string>("0");
|
||||
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
|
||||
const [partValue, setPartValue] = useState<string>("A");
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
const [upHeadList, setUpheadList] = useState(upHeadList1);
|
||||
|
||||
/**
|
||||
* 모달 상태 변수
|
||||
* selectedRow : 클릭한 행의 index
|
||||
* modalFcltyNm : 시설명
|
||||
* modalFcltyCd : 시설코드
|
||||
* modalSido : 시도
|
||||
* modalGugun : 시군구
|
||||
* modalLaeNm : 주소
|
||||
* modalFctCpc : 시설용량
|
||||
* modalTrtFrfNm : 공법
|
||||
* modalRnDt : 가동개시일
|
||||
* modalCmplDt : 준공일
|
||||
* modalTrstOprEtpNm : 관리대행업자
|
||||
* modalBscFctClsNm : 시설구분
|
||||
*/
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [modalFcltyNm, setModalFcltyNm] = useState<string>("");
|
||||
const [modalFcltyCd, setModalFcltyCd] = useState<string>("");
|
||||
const [modalSido, setModalSido] = useState<string>("");
|
||||
const [modalGugun, setModalGugun] = useState<string>("");
|
||||
const [modalAddr, setModalAddr] = useState<string>("");
|
||||
const [modalFctCpc, setModalFctCpc] = useState<number | ''>("");
|
||||
const [modalTrtFrfNm, setModalTrtFrfNm] = useState<string>("");
|
||||
const [modalRnDt, setModalRnDt] = useState<string>("");
|
||||
const [modalCmplDt, setModalCmplDt] = useState<string>("");
|
||||
const [modalTrstOprEtpNm, setModalTrstOprEtpNm] = useState<string>("");
|
||||
const [modalBscFctClsNm, setModalBscFctClsNm] = useState<string>("");
|
||||
const [modalMnstr, setModalMnstr] = useState<string>("");
|
||||
const [modalEfflWtrrgn, setModalEfflWtrrgn] = useState<string>("");
|
||||
const [modalLgbsn, setModalLgbsn] = useState<string>("");
|
||||
const [modalEfflWqltStndrdNm, setModalEfflWqltStndrdNm] = useState<string>("");
|
||||
const [modalRgnNm, setModalRgnNm] = useState<string>("");
|
||||
const [modalRvbsn, setModalRvbsn] = useState<string>("");
|
||||
const [isSearch, setIsSearch] = useState<boolean>(false);
|
||||
|
||||
// 표 레이아웃 상태
|
||||
const chkVal = useCallback((result:ReturnType) => {
|
||||
setPartValue(result.partValue);
|
||||
setResetPage(true);
|
||||
setIsSearch(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
switch (partValue) {
|
||||
case 'A':
|
||||
setWidthSize("w-[130%]");
|
||||
setUpheadList(upHeadList1);
|
||||
break;
|
||||
case 'R':
|
||||
setWidthSize("w-[140%]");
|
||||
setUpheadList(upHeadList2);
|
||||
break;
|
||||
case 'G':
|
||||
setWidthSize("w-[150%]");
|
||||
setUpheadList(upHeadList3);
|
||||
break;
|
||||
}
|
||||
}, [partValue, upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({ data: excelList as unknown as JSON[], fileName: '처리시설 시설정보', sheetNameArray: ['처리시설 시설정보'], headerRange: 'A1:P1' });
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
const searchFcltyList = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=10) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
searchProcessFacility(pageNo, pageCnt, partStr, nameCd || '0', fcltCpct, operationValue, facilityPartValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
if(isSearch) {
|
||||
setIsSearch(false);
|
||||
}
|
||||
}, [facilityPartValue, fcltCpct, fcltyName, isSearch, operationValue, searchProcessFacility])
|
||||
|
||||
const changePage = useCallback((page: number) => {
|
||||
searchFcltyList(ref.current, page);
|
||||
},[searchFcltyList])
|
||||
|
||||
const resetVal = () => {
|
||||
// SelectBox 초기화 - 각 selectArray의 첫 번째 옵션 값 사용
|
||||
searchProcessFacility(1, 10, 'A', '0', '0', '0', '0', '');
|
||||
setFcltCpct("0");
|
||||
setOperationValue("0");
|
||||
setFacilityPartValue("0");
|
||||
setPartValue('A');
|
||||
setUpheadList(upHeadList1);
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
|
||||
// ref를 사용하여 input 값 초기화
|
||||
if (inputRef.current) {
|
||||
inputRef.current.value = "";
|
||||
}
|
||||
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
const facility = processFacilityList[index];
|
||||
if (facility) {
|
||||
setModalFcltyNm(facility.bscFctNm);
|
||||
setModalFcltyCd(facility.bscFctCd);
|
||||
setModalSido(facility.sido);
|
||||
setModalGugun(facility.gugun);
|
||||
setModalAddr(facility.daddr);
|
||||
setModalFctCpc(Number(facility.fctCpc));
|
||||
setModalTrtFrfNm(facility.trtFrfNm);
|
||||
setModalRnDt(facility.rnDt);
|
||||
setModalCmplDt(facility.cmplDt);
|
||||
setModalTrstOprEtpNm(facility.trstOprEtpNm);
|
||||
setModalBscFctClsNm(facility.bscFctClsNm);
|
||||
setModalMnstr(facility.mnstr);
|
||||
setModalEfflWtrrgn(facility.efflWtrrgn);
|
||||
setModalLgbsn(facility.lgbsn);
|
||||
setModalEfflWqltStndrdNm(facility.efflWqltStndrdNm);
|
||||
setModalRgnNm(facility.rgnNm);
|
||||
setModalRvbsn(facility.rvbsn);
|
||||
|
||||
searchProcessFacilityHist(facility.bscFctCd);
|
||||
searchProcessFacilityWaterQlty(facility.bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
}
|
||||
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFcltyList(ref.current, 1, 10000);
|
||||
}, [searchFcltyList]);
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
}
|
||||
|
||||
const total = ProcessFacilityList?.processFacilityCount || 1;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="처리시설 시설정보" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[3] as string} selectArray={selectUpdownData} onSelectValue={val => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className="col-span-3" label={processFacilityLabelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[5] as string} selectArray={selectOperationData} onSelectValue={val => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={processFacilityLabelArray[6] as string} selectArray={selectFacilityPartData} onSelectValue={val => setFacilityPartValue(val.toString())} value={facilityPartValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable
|
||||
cellClick={(index: number | undefined) => index !== undefined && cellClick(index)}
|
||||
headName={"처리시설 시설정보"}
|
||||
tableData={processFacilityList}
|
||||
headlist={upHeadList}
|
||||
pageSize={10}
|
||||
total={total}
|
||||
resetPageNo={resetPage}
|
||||
onPageChange={changePage}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={upHeadList} layoutNum={partValue}/>
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<span className="text-2xl text-gray-500">※계획유입수질 및 설계유입수질은 해당 BOD를 나타냄</span>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<ProcessFacilityInfoModal fcltyName={modalFcltyNm} facilityCd={modalFcltyCd} sido={modalSido} gugun={modalGugun} daddr={modalAddr} fctCpc={modalFctCpc} trtFrfNm={modalTrtFrfNm} rnDt={modalRnDt} cmplDt={modalCmplDt} trstOprEtpNm={modalTrstOprEtpNm} bscFctClsNm={modalBscFctClsNm} mnstr={modalMnstr} efflWtrrgn={modalEfflWtrrgn} lgbsn={modalLgbsn} efflWqltStndrdNm={modalEfflWqltStndrdNm} rgnNm={modalRgnNm} rvbsn={modalRvbsn}></ProcessFacilityInfoModal>}
|
||||
bodyClass="sm:max-w-[70vw] sm:max-h-[95vh]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
export default function Rdi() {
|
||||
const {Common
|
||||
,initializeCommonData
|
||||
,Rdi
|
||||
,RdiSearch
|
||||
,searchRdiList
|
||||
} = useFoStore((state) => state) || { processAreaList: { processAreaList: [] }};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = RdiSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
rdiList,
|
||||
rdiCount,
|
||||
excelList,
|
||||
} = Rdi;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchRdiList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchRdiList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchRdiList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: 'RDII추정',
|
||||
sheetNameArray: ['RDII추정'],
|
||||
headerRange: 'A1:O1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchRdi = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchRdiList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchRdiList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [operationValue, fcltyName, searchRdiList, searchYear, fcltCpct]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchRdi(ref.current, 1, 10000);
|
||||
}, [searchRdi]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchRdi(ref.current, page, 10);
|
||||
}, [searchRdi]);
|
||||
|
||||
const mainList: Record<string, string | number | boolean>[] = rdiList || [];
|
||||
const total = rdiCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="RDII추정" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput ref={searchInputRef} className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref} isAdmin={false} />
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={ undefined } headName={"RDII추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
<span className="text-2xl text-gray-500">※주) 처리장 유입부에서 측정된 유량 및 수질조사 자료를 기준으로 산정된 결과임</span>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { SewageOccurDetailProps } from "@/app/store/sewageOccur";
|
||||
import { DateMonthPicker, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function SewageOccurModal(props: { fcltyName: string; facilityCd : string; searchYear : string}) {
|
||||
// 그리드 관련
|
||||
const {SewageOccurDetail} = useFoStore((state) => state);
|
||||
|
||||
// searchYear 유효성 검사 및 기본값 설정
|
||||
const validSearchYear = props.searchYear && /^\d{4}$/.test(props.searchYear) ? props.searchYear : new Date().getFullYear().toString();
|
||||
|
||||
const [startYearMonth, setStartYearMonth] = useState(validSearchYear+'01');
|
||||
const [endYearMonth, setEndYearMonth] = useState(validSearchYear+'12');
|
||||
const [detailList, setDetailList] = useState<SewageOccurDetailProps[]>([]);
|
||||
const {
|
||||
upHeadListSewageOccurDetail,
|
||||
gridListSewageOccurDetail
|
||||
} = SewageOccurDetail;
|
||||
|
||||
useEffect(() => {
|
||||
setDetailList(gridListSewageOccurDetail);
|
||||
}, [gridListSewageOccurDetail]);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredList = gridListSewageOccurDetail.filter(item => item.msrDt.replace(/-/g, '') >= startYearMonth && item.msrDt.replace(/-/g, '') <= endYearMonth);
|
||||
let maxWaterUsage = 0;
|
||||
let maxSwageChangePercent = 0;
|
||||
let maxEstimationSewage = 0;
|
||||
|
||||
let minWaterUsage = filteredList[0]?.waterUsage || 0;
|
||||
let minSwageChangePercent = filteredList[0]?.swageChangePercent || 0;
|
||||
let minEstimationSewage = filteredList[0]?.estimationSewage || 0;
|
||||
|
||||
let totalWaterUsage = 0;
|
||||
let totalSwageChangePercent = 0;
|
||||
let totalEstimationSewage = 0;
|
||||
|
||||
let avgWaterUsage = 0;
|
||||
let avgSwageChangePercent = 0;
|
||||
let avgEstimationSewage = 0;
|
||||
|
||||
filteredList.forEach(item => {
|
||||
if (item.waterUsage > maxWaterUsage) {
|
||||
maxWaterUsage = item.waterUsage;
|
||||
}
|
||||
if (item.swageChangePercent > maxSwageChangePercent) {
|
||||
maxSwageChangePercent = item.swageChangePercent;
|
||||
}
|
||||
if (item.estimationSewage > maxEstimationSewage) {
|
||||
maxEstimationSewage = item.estimationSewage;
|
||||
}
|
||||
|
||||
if (item.waterUsage < minWaterUsage) {
|
||||
minWaterUsage = item.waterUsage;
|
||||
}
|
||||
if (item.swageChangePercent < minSwageChangePercent) {
|
||||
minSwageChangePercent = item.swageChangePercent;
|
||||
}
|
||||
if (item.estimationSewage < minEstimationSewage) {
|
||||
minEstimationSewage = item.estimationSewage;
|
||||
}
|
||||
|
||||
totalWaterUsage += item.waterUsage;
|
||||
totalSwageChangePercent += item.swageChangePercent;
|
||||
totalEstimationSewage += item.estimationSewage;
|
||||
});
|
||||
|
||||
avgWaterUsage = totalWaterUsage?totalWaterUsage / filteredList.length:0;
|
||||
avgSwageChangePercent = totalSwageChangePercent?totalSwageChangePercent / filteredList.length:0;
|
||||
avgEstimationSewage = totalEstimationSewage?totalEstimationSewage / filteredList.length:0;
|
||||
|
||||
const newData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
waterUsage: Math.round(avgWaterUsage * 100) / 100,
|
||||
swageChangePercent: Math.round(avgSwageChangePercent * 100) / 100,
|
||||
estimationSewage: Math.round(avgEstimationSewage * 100) / 100
|
||||
},
|
||||
{
|
||||
msrDt: '최대',
|
||||
waterUsage: maxWaterUsage,
|
||||
swageChangePercent: maxSwageChangePercent,
|
||||
estimationSewage: maxEstimationSewage
|
||||
},
|
||||
{
|
||||
msrDt: '최소',
|
||||
waterUsage: minWaterUsage,
|
||||
swageChangePercent: minSwageChangePercent,
|
||||
estimationSewage: minEstimationSewage
|
||||
},
|
||||
...filteredList
|
||||
]
|
||||
setDetailList(newData);
|
||||
|
||||
|
||||
}, [startYearMonth, endYearMonth, gridListSewageOccurDetail]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListDiv className="!h-[80px] !mt-10">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow className="">
|
||||
<TableHead className="w-1/6">{'시설명'}</TableHead>
|
||||
<TableCell className="w-1/3">{props.fcltyName}</TableCell>
|
||||
<TableHead className="w-1/6">{'년월'}</TableHead>
|
||||
<TableCell className="w-1/3">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYearMonth || (() => {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
return `${year}${month}`;
|
||||
})(),
|
||||
onChange: (value: string) => {
|
||||
if (value && /^\d{6}$/.test(value)) {
|
||||
setStartYearMonth(value);
|
||||
}
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={1900}
|
||||
/>~
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYearMonth || (() => {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
return `${year}${month}`;
|
||||
})(),
|
||||
onChange: (value: string) => {
|
||||
if (value && /^\d{6}$/.test(value)) {
|
||||
setEndYearMonth(value);
|
||||
}
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={1900}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<ListDiv className="!h-[570px] overflow-y-auto">
|
||||
<div className="h-[120%]">
|
||||
<UiTable headName={"오수발생량 추정"} tableData={detailList} headlist={upHeadListSewageOccurDetail} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} boldArray={[0, 1, 2]}>
|
||||
</UiTable>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import SewageOccurModal from "./modal/page";
|
||||
import type { SewageOccurProps } from "@/app/store/sewageOccur";
|
||||
|
||||
export default function PlanSewage() {
|
||||
const {Common
|
||||
,SewageOccur
|
||||
,SewageOccurSearch
|
||||
,initializeCommonData
|
||||
,searchSewageOccurList
|
||||
} = useFoStore((state) => state) || {
|
||||
Common: { isInit: false, selectUpdownData: [], selectOperationData: [], selectSidoData: [], selectSigunData: [], selectRegionData: [], selectUnitWaterShedData: [], selectMiddleRegionData: [], selectEnvPartData: [], selectSearchYear: [{ val: "0" }], btnClass: "" },
|
||||
SewageOccur: { sewageOccurList: [], sewageOccurCount: 0, excelList: [], upHeadList1: [], upHeadList2: [], upHeadList3: [] },
|
||||
SewageOccurSearch: { labelArray: [] },
|
||||
initializeCommonData: () => {},
|
||||
searchSewageOccurList: () => {}
|
||||
};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = SewageOccurSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
sewageOccurList,
|
||||
sewageOccurCount,
|
||||
excelList
|
||||
} = SewageOccur;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const sewageOccur = SewageOccur?.sewageOccurList || [];
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
const [fcltyCd, setFcltyCd] = useState<string>("");
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (sewageOccur[index]) {
|
||||
setFcltyNm(sewageOccur[index].bscFctNm);
|
||||
setFcltyCd(sewageOccur[index].bscFctCd);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchSewageOccurList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '오수발생량 추정',
|
||||
sheetNameArray: ['오수발생량 추정'],
|
||||
headerRange: 'A1:O1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchSewageOccurList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchSewageOccurList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [fcltCpct, operationValue, fcltyName, searchSewageOccurList, searchYear]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFacilityPrecipitation(ref.current, 1, 10000);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFacilityPrecipitation(ref.current, page, 10);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
const mainList: SewageOccurProps[] = sewageOccurList || [];
|
||||
const total = sewageOccurCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="오수발생량 추정" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref}
|
||||
isAdmin={false}
|
||||
/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"오수발생량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<SewageOccurModal fcltyName={fcltyNm} facilityCd={fcltyCd} searchYear={searchYear}></SewageOccurModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { UnderWaterInputModalProps } from "@/app/store/underWaterInput";
|
||||
import { DateMonthPicker, UITab, UiTable } from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Table, TableCell, TableHead, TableRow, TabsContent } from "@common/components/ui";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type ModalProps ={
|
||||
fcltyName: string;
|
||||
searchYear : string;
|
||||
}
|
||||
|
||||
const tabList1 = [
|
||||
{ value: 'tab_term_year', label: '연간' },
|
||||
{ value: 'tab_term_summer', label: '하절기' },
|
||||
{ value: 'tab_term_winter', label: '동절기' },
|
||||
];
|
||||
|
||||
export default function UnderWaterInputModal({fcltyName='', searchYear=new Date().getFullYear().toString()} : ModalProps) {
|
||||
// 그리드 관련
|
||||
const {UnderWaterDetail} = useFoStore((state) => state);
|
||||
|
||||
const [startYmDate, setStartYmDate] = useState<string>(searchYear+'01');
|
||||
const [endYmDate, setEndYmDate] = useState<string>(searchYear+'12');
|
||||
const [tabTerm, setTabTerm] = useState<string>('tab_term_year');
|
||||
|
||||
// 이전 값들을 저장하기 위한 상태
|
||||
const [prevStartYmDate, setPrevStartYmDate] = useState<string>(searchYear+'01');
|
||||
const [prevEndYmDate, setPrevEndYmDate] = useState<string>(searchYear+'12');
|
||||
|
||||
const {
|
||||
upHeadListUnderWaterDetail,
|
||||
gridListUnderWaterDetail,
|
||||
} = UnderWaterDetail;
|
||||
|
||||
// 필터링 된 후 최대, 최소, 평균 값 계산
|
||||
const setFilterAfterData = (filteredData: UnderWaterInputModalProps[]) => {
|
||||
let maxRealSewageInput = Number(filteredData[0]?.realSewageInput ?? 0);
|
||||
let maxSewageOccur = Number(filteredData[0]?.sewageOccur ?? 0);
|
||||
let maxUnderWaterInput = Number(filteredData[0]?.underWaterInput ?? 0);
|
||||
|
||||
let minRealSewageInput = Number(filteredData[0]?.realSewageInput ?? 0);
|
||||
let minSewageOccur = Number(filteredData[0]?.sewageOccur ?? 0);
|
||||
let minUnderWaterInput = Number(filteredData[0]?.underWaterInput ?? 0);
|
||||
|
||||
let avgRealSewageInput = 0;
|
||||
let avgSewageOccur = 0;
|
||||
let avgUnderWaterInput = 0;
|
||||
|
||||
filteredData.forEach((item: UnderWaterInputModalProps) => {
|
||||
maxRealSewageInput = Math.max(Number(maxRealSewageInput), Number(item.realSewageInput));
|
||||
maxSewageOccur = Math.max(Number(maxSewageOccur), Number(item.sewageOccur));
|
||||
maxUnderWaterInput = Math.max(Number(maxUnderWaterInput), Number(item.underWaterInput));
|
||||
|
||||
minRealSewageInput = Math.min(Number(minRealSewageInput) || 0, Number(item.realSewageInput));
|
||||
minSewageOccur = Math.min(Number(minSewageOccur) || 0, Number(item.sewageOccur));
|
||||
minUnderWaterInput = Math.min(Number(minUnderWaterInput) || 0, Number(item.underWaterInput));
|
||||
|
||||
avgRealSewageInput += Number(item.realSewageInput ?? 0);
|
||||
avgSewageOccur += Number(item.sewageOccur ?? 0);
|
||||
avgUnderWaterInput += Number(item.underWaterInput ?? 0);
|
||||
})
|
||||
|
||||
const newFilteredData = [
|
||||
{
|
||||
msrDt: '평균',
|
||||
realSewageInput: filteredData.length==0?0:Math.round(Number(avgRealSewageInput) / filteredData.length * 10) / 10,
|
||||
sewageOccur: filteredData.length==0?0:Math.round(Number(avgSewageOccur) / filteredData.length * 1000) / 1000 ,
|
||||
underWaterInput: filteredData.length==0?0:Math.round(Number(avgUnderWaterInput) / filteredData.length * 1000) / 1000,
|
||||
},
|
||||
{
|
||||
msrDt : '최대',
|
||||
realSewageInput : Math.round(maxRealSewageInput * 10) / 10,
|
||||
sewageOccur : Math.round(maxSewageOccur * 1000) / 1000 ,
|
||||
underWaterInput : Math.round(maxUnderWaterInput * 1000) / 1000,
|
||||
},
|
||||
{
|
||||
msrDt : '최소',
|
||||
realSewageInput : Math.round(minRealSewageInput * 10) / 10,
|
||||
sewageOccur : Math.round(minSewageOccur * 1000) / 1000 ,
|
||||
underWaterInput : Math.round(minUnderWaterInput * 1000) / 1000,
|
||||
},
|
||||
...filteredData
|
||||
];
|
||||
return newFilteredData;
|
||||
}
|
||||
|
||||
// 날짜 필터링 관련 상태
|
||||
const [copyYearList, setCopyYearList] = useState<UnderWaterInputModalProps[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const filteredYearData = setFilterAfterData(gridListUnderWaterDetail);
|
||||
setCopyYearList(filteredYearData as UnderWaterInputModalProps[]);
|
||||
}, [gridListUnderWaterDetail]);
|
||||
|
||||
useEffect(() => {
|
||||
switch (tabTerm) {
|
||||
case 'tab_term_summer':
|
||||
setStartYmDate(searchYear+'06');
|
||||
setEndYmDate(searchYear+'08');
|
||||
setPrevStartYmDate(searchYear+'06');
|
||||
setPrevEndYmDate(searchYear+'08');
|
||||
break;
|
||||
case 'tab_term_winter':
|
||||
setStartYmDate(searchYear+'01');
|
||||
setEndYmDate(searchYear+'02');
|
||||
setPrevStartYmDate(searchYear+'01');
|
||||
setPrevEndYmDate(searchYear+'02');
|
||||
break;
|
||||
default:
|
||||
setStartYmDate(searchYear+'01');
|
||||
setEndYmDate(searchYear+'12');
|
||||
setPrevStartYmDate(searchYear+'01');
|
||||
setPrevEndYmDate(searchYear+'12');
|
||||
}
|
||||
}, [searchYear, tabTerm]);
|
||||
|
||||
useEffect(() => {
|
||||
if(endYmDate < startYmDate) {
|
||||
alert('종료일이 시작일보다 작습니다.')
|
||||
// 이전 값으로 되돌리기
|
||||
setStartYmDate(prevStartYmDate);
|
||||
setEndYmDate(prevEndYmDate);
|
||||
return;
|
||||
}
|
||||
|
||||
// 유효한 경우 현재 값을 이전 값으로 저장
|
||||
setPrevStartYmDate(startYmDate);
|
||||
setPrevEndYmDate(endYmDate);
|
||||
|
||||
const filteredData = gridListUnderWaterDetail.filter((item: UnderWaterInputModalProps) => {
|
||||
// msrDt가 "2024-01" 형태이므로 "202401" 형태로 변환
|
||||
const itemDate = item.msrDt.replace('-', '');
|
||||
return itemDate >= startYmDate && itemDate <= endYmDate;
|
||||
});
|
||||
const filteredYearData = setFilterAfterData(filteredData);
|
||||
setCopyYearList(filteredYearData as UnderWaterInputModalProps[]);
|
||||
}, [startYmDate, endYmDate, gridListUnderWaterDetail, prevStartYmDate, prevEndYmDate]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<UITab tabList={tabList1} defaultValue="tab_term_year" onValueChange={(val) => {setTabTerm(val)}}>
|
||||
<TabsContent value="tab_term_year">
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
<TableCell className="w-[300px]">{fcltyName}</TableCell>
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYmDate,
|
||||
onChange: (value: string) => {
|
||||
setStartYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYmDate,
|
||||
onChange: (value: string) => {
|
||||
setEndYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListUnderWaterDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[200px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_summer">
|
||||
{/* <FacilityTermModalHeader<UnderWaterInputModalProps>
|
||||
searchList={gridListUnderWaterDetail}
|
||||
fcltyCd={facilityCd}
|
||||
fcltyName={fcltyName}
|
||||
tabName="tab_term_summer"
|
||||
searchYear={searchYear}
|
||||
ref={ref}
|
||||
queryClick={filterData}
|
||||
/> */}
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
<TableCell className="w-[300px]">{fcltyName}</TableCell>
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYmDate,
|
||||
onChange: (value: string) => {
|
||||
setStartYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYmDate,
|
||||
onChange: (value: string) => {
|
||||
setEndYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListUnderWaterDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { } }
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tab_term_winter">
|
||||
<ListDiv className="!h-[100px]">
|
||||
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow>
|
||||
<TableHead className="w-[120px]">{'시설명'}</TableHead>
|
||||
<TableCell className="w-[300px]">{fcltyName}</TableCell>
|
||||
<TableHead className="w-[120px]">{'년/월'}</TableHead>
|
||||
<TableCell className="">
|
||||
<div className="flex">
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: startYmDate,
|
||||
onChange: (value: string) => {
|
||||
setStartYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
<h3 className="justify-center px-5">~</h3>
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
value: endYmDate,
|
||||
onChange: (value: string) => {
|
||||
setEndYmDate(value);
|
||||
}
|
||||
}}
|
||||
selectClass="ml-5 w-[100px]"
|
||||
startYear={Number(searchYear)} // 시작 연도 설정
|
||||
/>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</thead>
|
||||
</Table>
|
||||
</div>
|
||||
</ListDiv>
|
||||
<div className="overflow-y-auto h-[500px]">
|
||||
<UiTable
|
||||
headName={undefined}
|
||||
tableData={copyYearList}
|
||||
headlist={upHeadListUnderWaterDetail}
|
||||
pageSize={0}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => {}}
|
||||
className="h-[500px]"
|
||||
boldArray={[0,1,2]}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</UITab>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
"use client"
|
||||
import { useFoStore } from "@/app/store";
|
||||
import type { TableUpperProps } from "@/app/store/common";
|
||||
import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, SelectBox, Title, UiModal, UiTable, type ReturnType } from "@common/business_components";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import UnderWaterInputModal from "./modal/page";
|
||||
import type { UnderWaterProps } from "@/app/store/underWaterInput";
|
||||
|
||||
export default function UnderWaterInput() {
|
||||
const {Common
|
||||
,UnderWater
|
||||
,UnderWaterSearch
|
||||
,initializeCommonData
|
||||
,searchUnderWaterList
|
||||
} = useFoStore((state) => state) || {
|
||||
Common: { isInit: false, selectUpdownData: [], selectOperationData: [], selectSidoData: [], selectSigunData: [], selectRegionData: [], selectUnitWaterShedData: [], selectMiddleRegionData: [], selectEnvPartData: [], selectSearchYear: [{ val: "0" }], btnClass: "" },
|
||||
UnderWater: { underWaterList: [], underWaterCount: 0, excelList: [], upHeadList1: [], upHeadList2: [], upHeadList3: [] },
|
||||
UnderWaterSearch: { labelArray: [] },
|
||||
initializeCommonData: () => {},
|
||||
searchUnderWaterList: () => {}
|
||||
};
|
||||
|
||||
const {
|
||||
isInit,
|
||||
selectUpdownData,
|
||||
selectOperationData,
|
||||
selectSidoData,
|
||||
selectSigunData,
|
||||
selectRegionData,
|
||||
selectUnitWaterShedData,
|
||||
selectMiddleRegionData,
|
||||
selectEnvPartData,
|
||||
selectSearchYear,
|
||||
btnClass
|
||||
} = Common;
|
||||
|
||||
const {
|
||||
labelArray,
|
||||
} = UnderWaterSearch;
|
||||
|
||||
const {
|
||||
upHeadList1,
|
||||
upHeadList2,
|
||||
upHeadList3,
|
||||
underWaterList,
|
||||
underWaterCount,
|
||||
excelList,
|
||||
} = UnderWater;
|
||||
|
||||
const ref = useRef<ReturnType>({
|
||||
partValue: '',
|
||||
sidoValue: '',
|
||||
sigunValue: '',
|
||||
regionValue: '',
|
||||
unitWaterShedValue: '',
|
||||
middleRegionValue: '',
|
||||
envPartValue: '',
|
||||
sidoText: '',
|
||||
sigunText: ''
|
||||
});
|
||||
|
||||
const underWater = UnderWater?.underWaterList || [];
|
||||
|
||||
// 모달 상태 추가
|
||||
const [selectedRow, setSelectedRow] = useState<number | null>(null);
|
||||
const [fcltyNm, setFcltyNm] = useState<string>("");
|
||||
|
||||
// 그리드 관련
|
||||
const searchInputRef = useRef<HTMLDivElement & HTMLInputElement>(null);
|
||||
|
||||
// 초기화 변수
|
||||
const [resetPage, setResetPage] = useState<boolean>(false);
|
||||
// 표 너비
|
||||
const [widthSize, setWidthSize] = useState<string>("w-[120%]");
|
||||
// 구분별 그리드 헤더
|
||||
const [upheadList, setUpheadList] = useState<TableUpperProps[]>(upHeadList1);
|
||||
// 용량별
|
||||
const [fcltCpct, setFcltCpct] = useState<string>("0");
|
||||
// 시설명
|
||||
const [fcltyName, setFcltyName] = useState<string>("");
|
||||
// 시설상태
|
||||
const [operationValue, setOperationValue] = useState<string>("0");
|
||||
// 조회기간
|
||||
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
|
||||
|
||||
/**
|
||||
* 페이지 함수
|
||||
*/
|
||||
// 초기화
|
||||
const resetVal = () => {
|
||||
setWidthSize("w-[120%]");
|
||||
setUpheadList(upHeadList1)
|
||||
// 상태값 설정
|
||||
setFcltCpct(selectUpdownData[0]?.val || "0");
|
||||
setOperationValue(selectOperationData[0]?.val || "0");
|
||||
setSearchYear(selectSearchYear[0]?.val || "0");
|
||||
// SearchInputSelect 초기화
|
||||
setFcltyName("");
|
||||
if (searchInputRef.current) {
|
||||
const input = searchInputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.value = "";
|
||||
}
|
||||
}
|
||||
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
|
||||
// 모달 닫기
|
||||
const closeModal = () => {
|
||||
setSelectedRow(null);
|
||||
};
|
||||
|
||||
// 셀 클릭 시 모달 표시
|
||||
const cellClick = (index: number) => {
|
||||
if (underWater[index]) {
|
||||
setFcltyNm(underWater[index].bscFctNm);
|
||||
setSelectedRow(index); // 클릭한 행의 index 저장
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* useEffect
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!isInit) {
|
||||
initializeCommonData();
|
||||
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
|
||||
}
|
||||
}, [isInit, initializeCommonData, searchUnderWaterList, selectSearchYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (excelList && excelList.length > 0) {
|
||||
downloadExcel({
|
||||
data: excelList as unknown as JSON[],
|
||||
fileName: '지하수유입량 추정',
|
||||
sheetNameArray: ['지하수유입량 추정'],
|
||||
headerRange: 'A1:V1'
|
||||
});
|
||||
}
|
||||
}, [excelList]);
|
||||
|
||||
/**
|
||||
* 콜백함수
|
||||
*/
|
||||
// 조회
|
||||
const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => {
|
||||
let nameCd, partStr
|
||||
switch (partValue) {
|
||||
case 'R':
|
||||
if (regionValue !== '0') {
|
||||
if(unitWaterShedValue==='0') nameCd = regionValue;
|
||||
else if (middleRegionValue==='0') nameCd = unitWaterShedValue;
|
||||
else nameCd = middleRegionValue;
|
||||
}
|
||||
partStr = partValue
|
||||
break;
|
||||
default:
|
||||
if(sidoValue !== '0') nameCd = sidoValue;
|
||||
if(sigunValue !== '0') nameCd = sigunValue;
|
||||
partStr = envPartValue !== '0' ? envPartValue:partValue;
|
||||
break;
|
||||
}
|
||||
if (partStr.length > 1 || fcltCpct !== '0' || operationValue!== '0' ||nameCd ||(fcltyName.trim() !== "" && fcltyName.trim() !== null)) {
|
||||
searchUnderWaterList(pageNo, pageCnt, searchYear, partStr, nameCd || '0', fcltCpct, operationValue, fcltyName.trim() !== "" || fcltyName.trim() !== null ? fcltyName : undefined);
|
||||
} else {
|
||||
searchUnderWaterList(pageNo, pageCnt, searchYear);
|
||||
}
|
||||
}, [fcltCpct, operationValue, fcltyName, searchUnderWaterList, searchYear]);
|
||||
|
||||
const chkVal = useCallback((returntype:ReturnType) => {
|
||||
setWidthSize(returntype.partValue=='A' ?"w-[120%]":"w-[130%]")
|
||||
setUpheadList(returntype.partValue == 'R' ? upHeadList2 : returntype.partValue == 'G'?upHeadList3:upHeadList1);
|
||||
setResetPage(true);
|
||||
}, [upHeadList1, upHeadList2, upHeadList3]);
|
||||
|
||||
// 엑셀다운로드
|
||||
const excelDownload = useCallback(() => {
|
||||
searchFacilityPrecipitation(ref.current, 1, 10000);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
// 페이지 변경
|
||||
const handlePageChange = useCallback((page: number) => {
|
||||
setResetPage(false);
|
||||
searchFacilityPrecipitation(ref.current, page, 10);
|
||||
}, [searchFacilityPrecipitation]);
|
||||
|
||||
const mainList: UnderWaterProps[] = underWaterList || [];
|
||||
const total = underWaterCount || 0;
|
||||
|
||||
return (
|
||||
<MainDiv>
|
||||
<Title title="지하수유입량 추정" />
|
||||
<ContentsDiv>
|
||||
<SearchBaseForm
|
||||
leftChildren={<>
|
||||
<SelectBox className="col-span-3" label={labelArray[3] as string} selectArray={selectUpdownData} onSelectValue={(val) => setFcltCpct(val.toString())} value={fcltCpct} selectClass={undefined} />
|
||||
<SearchInput className={"col-span-3"} label={labelArray[4] as string} textValue={fcltyName} setText={setFcltyName} />
|
||||
<SelectBox className="col-span-3" label={labelArray[5] as string} selectArray={selectSearchYear} onSelectValue={(val) => setSearchYear(val.toString())} value={searchYear} selectClass={undefined} />
|
||||
<SelectBox className="col-span-3" label={labelArray[6] as string} selectArray={selectOperationData} onSelectValue={(val) => setOperationValue(val.toString())} value={operationValue} selectClass={undefined} />
|
||||
</>}
|
||||
rightChildren={undefined}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
selectRegionData={selectRegionData}
|
||||
selectUnitWaterShedData={selectUnitWaterShedData}
|
||||
selectMiddleRegionData={selectMiddleRegionData}
|
||||
selectEnvPartData={selectEnvPartData}
|
||||
btnClass={btnClass}
|
||||
queryClick={chkVal}
|
||||
excelClick={excelDownload}
|
||||
initClick={resetVal}
|
||||
ref={ref}
|
||||
isAdmin={false}
|
||||
/>
|
||||
<ListDiv>
|
||||
<div className="h-full w-full overflow-x-scroll">
|
||||
<div className={widthSize}>
|
||||
<UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"지하수유입량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} />
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-2xl text-gray-500">※지하수 유입량 = 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)</span>
|
||||
</ListDiv>
|
||||
</ContentsDiv>
|
||||
{selectedRow !== null && (
|
||||
<UiModal
|
||||
body={<UnderWaterInputModal fcltyName={fcltyNm} searchYear={searchYear}></UnderWaterInputModal>}
|
||||
bodyClass="sm:max-w-[90vw] w-[1000px] h-[770px]"
|
||||
open={selectedRow !== null}
|
||||
onOpenChange={(open) => !open && closeModal()}
|
||||
noHeaderYn="Y"
|
||||
noFooterYn="Y"
|
||||
/>
|
||||
)}
|
||||
</MainDiv>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
/**====================================
|
||||
* 보편적으로 쓰는 store 공간
|
||||
====================================**/
|
||||
|
||||
import { getFetch } from "@/app/components/api";
|
||||
|
||||
/**
|
||||
* STORE - TYPE
|
||||
*/
|
||||
|
||||
// selectBox
|
||||
export type SelectDataType = {
|
||||
text: string;
|
||||
val: string;
|
||||
}
|
||||
// grid header
|
||||
export type TableUpperProps = {
|
||||
id: string;
|
||||
title: string;
|
||||
upName?: string;
|
||||
upSequnce?: number;
|
||||
}
|
||||
|
||||
// 시도 데이터
|
||||
export type sidoDataType = {
|
||||
adstDstrCd: number,
|
||||
sido: string,
|
||||
}
|
||||
|
||||
// 시군구 데이터
|
||||
export type sigunDataType = {
|
||||
adstDstrCd: number,
|
||||
gugun: string
|
||||
}
|
||||
|
||||
// 권역 데이터
|
||||
export type regionDataType = {
|
||||
rvbsnCd: string,
|
||||
rvbsn: string,
|
||||
}
|
||||
|
||||
// 단위유역 데이터
|
||||
export type unitWaterShedDataType = {
|
||||
rvbsnCd: string,
|
||||
lgbsn: string,
|
||||
}
|
||||
|
||||
// 중권역 데이터
|
||||
export type middleRegionDataType = {
|
||||
rvbsnCd: string,
|
||||
mdmbsn: string,
|
||||
}
|
||||
|
||||
// 환경청 데이터
|
||||
export type envPartDataType = {
|
||||
lclgvrnmntCd: string,
|
||||
lclgvrnmntNm: string,
|
||||
adstDliStrCd: string,
|
||||
adstDstrCd: string,
|
||||
}
|
||||
|
||||
export type envPartSelectDataType = SelectDataType & {
|
||||
adstDliStrCd: string,
|
||||
}
|
||||
|
||||
/**
|
||||
* STORE - DATA
|
||||
*/
|
||||
|
||||
// 시도 데이터
|
||||
let selectSidoData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 시군구 데이터
|
||||
let selectSigunData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 권역 데이터
|
||||
const selectRegionData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 단위유역 데이터
|
||||
const selectUnitWaterShedData: SelectDataType[] = [
|
||||
];
|
||||
|
||||
// 환경청 데이터
|
||||
let selectEnvPartData: envPartSelectDataType[] = [
|
||||
{ text: "전체", val: '0', adstDliStrCd: '' }
|
||||
];
|
||||
|
||||
// 환경청 내 시도 데이터
|
||||
const selectEnvPartSidoData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 환경청 내 시군구 데이터
|
||||
const selectEnvPartSigunData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
// 구분 데이터
|
||||
// const selectPartData:SelectDataType[] = [
|
||||
// { text: "행정별", val: '0' },
|
||||
// { text: "유역별", val: '01' },
|
||||
// { text: "환경청별", val: '02' },
|
||||
// ];
|
||||
|
||||
// 상향 하향 데이터
|
||||
const selectUpdownData:SelectDataType[] = [
|
||||
{ text: "전체", val: '0' },
|
||||
{ text: "500이하", val: '400' },
|
||||
{ text: "500이상", val: '500' },
|
||||
];
|
||||
|
||||
// 운영 상태 데이터
|
||||
const selectOperationData:SelectDataType[] = [
|
||||
{ text: "전체", val: '0' },
|
||||
{ text: "가동중", val: '1' },
|
||||
{ text: "재가동", val: '2' },
|
||||
{ text: "가동중지", val: '3' },
|
||||
{ text: "시설폐쇄", val: '4' },
|
||||
];
|
||||
|
||||
// 시설 구분 데이터
|
||||
const selectFacilityPartData:SelectDataType[] = [
|
||||
{ text: "전체", val: '0' },
|
||||
{ text: "공공하수처리시설", val: 'SW' },
|
||||
{ text: "오수처리장", val: 'SS' },
|
||||
{ text: "개인하수처리시설", val: 'PB' },
|
||||
{ text: "분뇨처리장", val: 'NS' },
|
||||
{ text: "폐수처리장", val: 'LW' },
|
||||
{ text: "침출수처리장", val: 'LC' },
|
||||
{ text: "기타기초시설", val: 'ET' },
|
||||
];
|
||||
|
||||
// 년도 데이터
|
||||
const getYearData = () => {
|
||||
const year = new Date().getFullYear();
|
||||
const year1 = year - 1;
|
||||
const year2 = year - 2;
|
||||
const year3 = year - 3;
|
||||
const year4 = year - 4;
|
||||
const year5 = year - 5;
|
||||
return [
|
||||
{ text: year1 + "년", val: year1.toString() },
|
||||
{ text: year2 + "년", val: year2.toString() },
|
||||
{ text: year3 + "년", val: year3.toString() },
|
||||
{ text: year4 + "년", val: year4.toString() },
|
||||
{ text: year5 + "년", val: year5.toString() },
|
||||
]
|
||||
}
|
||||
|
||||
const selectSearchYear:SelectDataType[] = getYearData();
|
||||
|
||||
// 유량 기간 구분
|
||||
const selectFlowTerm : SelectDataType[] = [
|
||||
{ text: "연간", val: '0' },
|
||||
{ text: "하절기", val: '01' },
|
||||
{ text: "동절기", val: '02' },
|
||||
{ text: "청천시", val: '03' },
|
||||
{ text: "강우시", val: '04' },
|
||||
];
|
||||
|
||||
// 유량 기간 구분
|
||||
const selectFlowPanel : SelectDataType[] = [
|
||||
{ text: "전체", val: '0'},
|
||||
{ text: "3~10mm미만", val: '2'},
|
||||
{ text: "10~20mm미만", val: '3'},
|
||||
{ text: "20~30mm미만", val: '4'},
|
||||
{ text: "30~40mm미만", val: '5'},
|
||||
{ text: "40~50mm미만", val: '6'},
|
||||
{ text: "50~60mm미만", val: '7'},
|
||||
{ text: "60mm이상", val: '8'},
|
||||
];
|
||||
|
||||
// 중권역 데이터
|
||||
const selectMiddleRegionData: SelectDataType[] = [
|
||||
{ text: "전체", val: '0' }
|
||||
];
|
||||
|
||||
/**
|
||||
* STORE - API
|
||||
*/
|
||||
|
||||
// 시도 API 호출 함수 추가
|
||||
const fetchSidoData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/city');
|
||||
const data = res.data;
|
||||
selectSidoData = [
|
||||
{ text: "전체", val: '0'},
|
||||
...data.map((item: sidoDataType) => ({
|
||||
text: item.sido || '',
|
||||
val: String(item.adstDstrCd) || ''
|
||||
}))
|
||||
];
|
||||
return selectSidoData;
|
||||
} catch (error) {
|
||||
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectSidoData;
|
||||
}
|
||||
};
|
||||
|
||||
// 시군구 API 호출 함수 추가
|
||||
const fetchSigunData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/sgg');
|
||||
const data = res.data;
|
||||
selectSigunData = [
|
||||
{ text: "전체", val: '0' },
|
||||
...data
|
||||
.map((item: sigunDataType) => ({
|
||||
text: item.gugun || '',
|
||||
val: String(item.adstDstrCd) || ''
|
||||
}))
|
||||
];
|
||||
return selectSigunData;
|
||||
} catch (error) {
|
||||
console.error('시군구 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectSigunData;
|
||||
}
|
||||
};
|
||||
|
||||
// 권역 API 호출 함수 추가
|
||||
const fetchRegionData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/sarea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0'},
|
||||
...data.map((item: regionDataType) => ({
|
||||
text: item.rvbsn || '',
|
||||
val: String(item.rvbsnCd) || ''
|
||||
}))
|
||||
];
|
||||
} catch (error) {
|
||||
console.error('권역 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectRegionData;
|
||||
}
|
||||
};
|
||||
|
||||
// 중권역 API 호출 함수 추가
|
||||
const fetchMiddleRegionData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/midArea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0' },
|
||||
...data
|
||||
.map((item: middleRegionDataType) => ({
|
||||
text: item.mdmbsn || '',
|
||||
val: String(item.rvbsnCd) || ''
|
||||
}))
|
||||
];
|
||||
} catch (error) {
|
||||
console.error('중권역 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectMiddleRegionData;
|
||||
}
|
||||
};
|
||||
|
||||
// 단위유역 API 호출 함수 추가
|
||||
const fetchUnitWaterShedData = async (): Promise<SelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/largeArea');
|
||||
const data = res.data;
|
||||
return [
|
||||
{ text: "전체", val: '0' },
|
||||
...data
|
||||
.map((item: unitWaterShedDataType) => ({
|
||||
text: item.lgbsn || '',
|
||||
val: String(item.rvbsnCd) || ''
|
||||
}))
|
||||
];
|
||||
} catch (error) {
|
||||
console.error('단위유역 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectUnitWaterShedData;
|
||||
}
|
||||
};
|
||||
|
||||
// 환경청 데이터
|
||||
const fetchEnvPartData = async (): Promise<envPartSelectDataType[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/addr/govArea');
|
||||
const data = res.data;
|
||||
selectEnvPartData = [
|
||||
{ text: "전체", val: '0', adstDliStrCd: '' },
|
||||
...data
|
||||
.map((item: envPartDataType) => ({
|
||||
text: item.lclgvrnmntNm || '',
|
||||
val: String(item.lclgvrnmntCd) || '',
|
||||
adstDliStrCd: item.adstDliStrCd || ''
|
||||
}))
|
||||
];
|
||||
return selectEnvPartData;
|
||||
} catch (error) {
|
||||
console.error('환경청 데이터를 가져오는데 실패했습니다:', error);
|
||||
return selectEnvPartData;
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type CommonAction = {
|
||||
initializeCommonData: () => Promise<void>;
|
||||
}
|
||||
|
||||
export type CommonType = {
|
||||
Common: {
|
||||
isInit: boolean;
|
||||
selectSidoData: SelectDataType[];
|
||||
selectSigunData: SelectDataType[];
|
||||
selectUpdownData: SelectDataType[];
|
||||
selectOperationData: SelectDataType[];
|
||||
selectFacilityPartData: SelectDataType[];
|
||||
selectSearchYear: SelectDataType[];
|
||||
selectUnitWaterShedData: SelectDataType[];
|
||||
selectRegionData: SelectDataType[];
|
||||
selectMiddleRegionData: SelectDataType[];
|
||||
selectEnvPartSidoData: SelectDataType[];
|
||||
selectEnvPartSigunData: SelectDataType[];
|
||||
selectFlowTerm: SelectDataType[];
|
||||
selectFlowPanel: SelectDataType[];
|
||||
selectEnvPartData: envPartSelectDataType[];
|
||||
btnClass: string;
|
||||
}
|
||||
}
|
||||
|
||||
export const commonState:CommonType = {
|
||||
Common: {
|
||||
isInit: false,
|
||||
selectSidoData: selectSidoData,
|
||||
selectSigunData: selectSigunData,
|
||||
selectUpdownData: selectUpdownData,
|
||||
selectOperationData: selectOperationData,
|
||||
selectFacilityPartData: selectFacilityPartData,
|
||||
selectSearchYear: selectSearchYear,
|
||||
selectRegionData: selectRegionData,
|
||||
selectUnitWaterShedData: selectUnitWaterShedData,
|
||||
selectMiddleRegionData: selectMiddleRegionData,
|
||||
selectEnvPartSidoData : selectEnvPartSidoData,
|
||||
selectEnvPartSigunData : selectEnvPartSigunData,
|
||||
selectFlowTerm: selectFlowTerm,
|
||||
selectFlowPanel: selectFlowPanel,
|
||||
selectEnvPartData : selectEnvPartData,
|
||||
btnClass: "p-4 m-2 text-white rounded-sm text-lg font-medium"
|
||||
}
|
||||
}
|
||||
|
||||
export const CommonReducer:(set:(fn: (state: CommonType) => CommonType) => void)=>CommonAction=(set: (fn: (state: CommonType) => CommonType) => void) => {
|
||||
return {
|
||||
// 시도 변경 이벤트
|
||||
initializeCommonData: async () => {
|
||||
const promiseSet = await Promise.all([fetchSidoData(), fetchSigunData(), fetchRegionData(), fetchUnitWaterShedData(), fetchMiddleRegionData(), fetchEnvPartData()]);
|
||||
const [sidoData, sggData, regionData, unitData, midData, envData] = promiseSet;
|
||||
set((state: CommonType) => ({
|
||||
Common: {
|
||||
...state.Common,
|
||||
selectSidoData: sidoData,
|
||||
selectSigunData: sggData,
|
||||
selectRegionData: regionData,
|
||||
selectMiddleRegionData: midData,
|
||||
selectUnitWaterShedData: unitData,
|
||||
selectEnvPartData: envData
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export type CommonStore = CommonType & CommonAction;
|
||||
@@ -0,0 +1,307 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
type FacilityPrecipitationProps = {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
bscFctNm : string,
|
||||
addr : string,
|
||||
fctCpc : number,
|
||||
stnKo : string,
|
||||
infoRnDay : number,
|
||||
rainEffectDay : number,
|
||||
totalYearRain : number,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
rgnNm : string,
|
||||
}
|
||||
|
||||
/*
|
||||
* (2) 강수현황 팝업
|
||||
*/
|
||||
// 강수현황
|
||||
export type PrecipitationPropsDetailProps = {
|
||||
bscFctCd : string,
|
||||
rainDt : string,
|
||||
infoRnDay : number,
|
||||
rainEffectDay : number,
|
||||
rainDay : number
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
관측소정보 : string,
|
||||
강우일 : number,
|
||||
강우영향일 : number,
|
||||
연간총강수량 : number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '시설상태', '조회기간', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "행정구역", row: 0, colSpan: 2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row: 1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row: 1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row: 1} ,
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row: 1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row: 1},
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row: 0, rowSpan: 2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3} ,
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row: 1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row: 1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row: 1},
|
||||
{ id: "rgnNm", title: "환경청", row: 0, rowSpan: 2},
|
||||
{ id: "B", title: "행정구역", upName:"upChangeRe2", row: 0, colSpan: 2},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row: 1},
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row: 1},
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "addr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row: 0, rowSpan: 2},
|
||||
{ id: "stnKo", title: "관측소 정보", row: 0, rowSpan: 2},
|
||||
{ id: "infoRnDay", title: "강우일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "rainEffectDay", title: "강우영향일\n(일)", row: 0, rowSpan: 2},
|
||||
{ id: "totalYearRain", title: "연간 총 총강수량\n(mm)", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
const facilityPrecipitation:FacilityPrecipitationProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* 강수현황 상세팝업
|
||||
*/
|
||||
// 강수현황 (헤더)
|
||||
const upHeadListPrecipitationDetail:TableUpperProps[] = [
|
||||
{ id: "rainDt", title: "날짜"},
|
||||
{ id: "infoRnDay", title: "강수량(mm/일)"},
|
||||
{ id: "rainDay", title: "강우일(일)"},
|
||||
{ id: "rainEffectDay", title: "강우영향일(일)"}
|
||||
]
|
||||
// 강수현황 (리스트)
|
||||
const gridListPrecipitationDetail:PrecipitationPropsDetailProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - api
|
||||
====================================*/
|
||||
|
||||
const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const tailStr = '/'+pageNo + '/' + pageSize + '/' + searchYear + (part?'/' + part:'' ) + (nameCd?'/' + nameCd:'' ) + (fcltCpct?'/' + fcltCpct:'' ) + (operationValue?'/' + operationValue:'' ) + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') ;
|
||||
console.log('tailStr', tailStr);
|
||||
const url = '/fclt/rain' + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
const tmpData:PrecipitationPropsDetailProps[] = [];
|
||||
if(res!= null && res.data.length > 0){
|
||||
for(let idx=0; idx<res.data.length; idx++){
|
||||
for(let idx2=0; idx2<res.data[idx].rainyDayObjList.length; idx2++){
|
||||
const bscFctCd = res.data[idx].rainyDayObjList[idx2].bscFctCd;
|
||||
const rainDt = res.data[idx].rainyDayObjList[idx2].rainDt;
|
||||
const infoRnDay = res.data[idx].rainyDayObjList[idx2].infoRnDay;
|
||||
const rainDay = res.data[idx].rainyDayObjList[idx2].infoRnDay>=3?1:0;
|
||||
let rainEffectDay = 0;
|
||||
if(idx2 < res.data[idx].rainyDayObjList.length-2){
|
||||
if(rainDay==1){
|
||||
rainEffectDay = 1;
|
||||
} else {
|
||||
if(idx2 >= 2){
|
||||
if(res.data[idx].rainyDayObjList[idx2-1].infoRnDay>=3 || res.data[idx].rainyDayObjList[idx2-2].infoRnDay>=3){
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(idx2 < res.data[idx].rainyDayObjList.length-1){
|
||||
if(rainDay==1 || res.data[idx].rainyDayObjList[idx2+1].infoRnDay>=3){
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
} else {
|
||||
rainEffectDay = rainDay;
|
||||
}
|
||||
|
||||
tmpData.push({
|
||||
bscFctCd : bscFctCd,
|
||||
rainDt : rainDt,
|
||||
infoRnDay : infoRnDay,
|
||||
rainDay : rainDay,
|
||||
rainEffectDay : rainEffectDay
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
res.data.map((item: FacilityPrecipitationProps) => {
|
||||
const filteredList = tmpData.filter((gridItem) => {
|
||||
return gridItem.bscFctCd === item.bscFctCd;
|
||||
});
|
||||
|
||||
item.rainEffectDay = filteredList.reduce((acc, curr) => acc + curr.rainEffectDay, 0);
|
||||
item.totalYearRain = filteredList.reduce((acc, curr) => acc + curr.infoRnDay, 0);
|
||||
item.infoRnDay = filteredList.reduce((acc, curr) => acc + curr.rainDay, 0);
|
||||
})
|
||||
}
|
||||
return { data: res.data, count: res.count, detailData: tmpData };
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type FacilityPrecipitationActions = {
|
||||
searchFacilityPrecipitationList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : FacilityPrecipitationProps)=> {
|
||||
DataForm({ type: 'number', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'totalYearRain', item: item as unknown as Record<string, unknown>});
|
||||
};
|
||||
|
||||
export type FacilityPrecipitationType = {
|
||||
FacilityPrecipitationSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
FacilityPrecipitation : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
facilityPrecipitation: FacilityPrecipitationProps[];
|
||||
excelList: ExcelType[];
|
||||
facilityPrecipitationCount: number;
|
||||
},
|
||||
|
||||
PrecipitationDetail : {
|
||||
isInit : boolean;
|
||||
upHeadListPrecipitationDetail : TableUpperProps[];
|
||||
gridListPrecipitationDetail : PrecipitationPropsDetailProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export const facilityPrecipitationInitState: FacilityPrecipitationType = {
|
||||
FacilityPrecipitationSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
FacilityPrecipitation : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
facilityPrecipitation : facilityPrecipitation,
|
||||
excelList : [],
|
||||
facilityPrecipitationCount : 0
|
||||
},
|
||||
|
||||
PrecipitationDetail : {
|
||||
isInit : false,
|
||||
upHeadListPrecipitationDetail : upHeadListPrecipitationDetail,
|
||||
gridListPrecipitationDetail : gridListPrecipitationDetail
|
||||
}
|
||||
}
|
||||
|
||||
export type FacilityPrecipitationStore = FacilityPrecipitationType & FacilityPrecipitationActions;
|
||||
|
||||
export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitationType) => FacilityPrecipitationType) => void)=>FacilityPrecipitationActions=(set: (fn: (state: FacilityPrecipitationType) => FacilityPrecipitationType) => void) => {
|
||||
return {
|
||||
searchFacilityPrecipitationList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchFacilityPrecipitationList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
if(pageSize>5000){
|
||||
data.forEach((item: FacilityPrecipitationProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : 0;
|
||||
item.totalYearRain = item.totalYearRain ? parseFloat(item.totalYearRain.toString().replace(/,/g, '')) : 0;
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sido,
|
||||
시군구: item.gugun,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.addr,
|
||||
시설용량: item.fctCpc,
|
||||
관측소정보: item.stnKo,
|
||||
강우일: item.infoRnDay,
|
||||
강우영향일: item.rainEffectDay,
|
||||
연간총강수량: item.totalYearRain,
|
||||
})
|
||||
})
|
||||
}else{
|
||||
data.forEach((item: FacilityPrecipitationProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : 0;
|
||||
item.totalYearRain = item.totalYearRain ? parseFloat(item.totalYearRain.toString().replace(/,/g, '')) : 0;
|
||||
})
|
||||
}
|
||||
set((state:FacilityPrecipitationType) => ({
|
||||
...state,
|
||||
FacilityPrecipitation: pageSize<5000?{
|
||||
...state.FacilityPrecipitation,
|
||||
facilityPrecipitation: res.data,
|
||||
facilityPrecipitationCount: res.count,
|
||||
}:{
|
||||
...state.FacilityPrecipitation,
|
||||
excelList: excelDownList,
|
||||
},
|
||||
PrecipitationDetail:{
|
||||
...state.PrecipitationDetail,
|
||||
gridListPrecipitationDetail: res.detailData
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,659 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
export type { TableUpperProps };
|
||||
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
*
|
||||
* tn, tp는 소수점 3자리까지, 나머지는 소수점 1자리까지
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설수질리스트 타입
|
||||
export interface FacilityWaterQltyProps {
|
||||
bscFctCd: string,
|
||||
bscFctNm: string,
|
||||
msrDt: string
|
||||
sidoNm: string,
|
||||
sggNm: string,
|
||||
addr: string,
|
||||
fctCpc: number,
|
||||
inflAssctAftWqltBod: string | '',
|
||||
inflAssctAftWqltToc: string | '',
|
||||
inflAssctAftWqltSs: string | '',
|
||||
inflAssctAftWqltTn: string | '',
|
||||
inflAssctAftWqltTp: string | '',
|
||||
inflAssctBfrWqltTp: string | '',
|
||||
efflWqltBod: string | '',
|
||||
efflWqltCod: string | '',
|
||||
efflWqltSs: string | '',
|
||||
efflWqltTn: string | '',
|
||||
efflWqltTp: string | '',
|
||||
rgnNm:string|'',
|
||||
rvbsn:string|'',
|
||||
lgbsn:string|'',
|
||||
mdmbsn:string|'',
|
||||
inflAmnt: number | '',
|
||||
lclgvrnmntNm: string,
|
||||
infoRnDay: number | '',
|
||||
rainEffectDay: number | '',
|
||||
tpInflWqltTmprtr: number | '',
|
||||
tpInflWqltPh: string | '',
|
||||
tpInflWqltBod: string | '',
|
||||
tpInflWqltCod: string | '',
|
||||
tpInflWqltSs: string | '',
|
||||
tpInflWqltTn: string | '',
|
||||
tpInflWqltTp: string | '',
|
||||
tpInflWqltEclgyTox: string | '',
|
||||
tpInflWqltClfgrpcnt: string | '',
|
||||
}
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
용량: number,
|
||||
유입BOD: string | '',
|
||||
유입TOC: string | '',
|
||||
유입SS: string | '',
|
||||
유입TN: string | '',
|
||||
유입TP: string | '',
|
||||
유출BOD: string | '',
|
||||
유출TOC: string | '',
|
||||
유출SS: string | '',
|
||||
유출TN: string | '',
|
||||
유출TP: string | '',
|
||||
}
|
||||
|
||||
/**
|
||||
* (2) 모달페이지
|
||||
*/
|
||||
// 시설수질리스트 타입
|
||||
export type FacilityWaterQltyTmsProps = {
|
||||
part: string,
|
||||
toc: number,
|
||||
ss: number,
|
||||
tn: number,
|
||||
tp: number,
|
||||
}
|
||||
|
||||
// API 응답 데이터 타입
|
||||
export interface WaterQualityHistoryResponse {
|
||||
data: {
|
||||
wqltObjs: FacilityWaterQltyProps[];
|
||||
};
|
||||
}
|
||||
|
||||
export type modalExcelType = {
|
||||
날짜: string;
|
||||
"유입BOD(mg/L)": string;
|
||||
"유입TOC(COD)(mg/L)": string;
|
||||
"유입SS(mg/L)": string;
|
||||
"유입TN(mg/L)": string;
|
||||
"유입TP(mg/L)": string;
|
||||
"유출BOD(mg/L)": string;
|
||||
"유출TOC(COD)(mg/L)": string;
|
||||
"유출SS(mg/L)": string;
|
||||
"유출TN(mg/L)": string;
|
||||
"유출TP(mg/L)": string;
|
||||
"강우량(일)": string;
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 메인 라벨 배열
|
||||
const mainLabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 시설수질리스트 헤더(행정별)
|
||||
const upHeadList1: TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", rowSpan: 2, row:0 },
|
||||
{ id: "C", title: "행정명", colSpan: 2, row: 0 },
|
||||
{ id: "sidoNm", title: "시도", row: 1 },
|
||||
{ id: "sggNm", title: "시군구", row: 1 },
|
||||
{ id: "bscFctNm", title: "시설명", rowSpan: 2, row: 0 },
|
||||
{ id: "addr", title: "주소", rowSpan: 2, row: 0 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align: "right", rowSpan: 2, row: 0 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1 },
|
||||
{ id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row: 1 },
|
||||
{ id: "efflWqltCod", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row: 1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 4, align: "right", row: 1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row: 1 },
|
||||
];
|
||||
|
||||
// 시설수질리스트 헤더(권역별)
|
||||
const upHeadList2: TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0 },
|
||||
{ id: "rvbsn", title: "권역", upName: "upChangeRe1", upSequnce: 1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName: "upChangeRe1", upSequnce: 2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName: "upChangeRe1", upSequnce: 3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "addr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "efflWqltCod", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
];
|
||||
|
||||
// 시설수질리스트 헤더(환경청별)
|
||||
const upHeadList3: TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "유역", colSpan: 3, row: 0 },
|
||||
{ id: "rvbsn", title: "권역", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "D", title: "행정명", colSpan: 2, row: 0 },
|
||||
{ id: "sidoNm", title: "시도", upName: "upChangeRe2", row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName: "upChangeRe2", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "addr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/L)", align: "right", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유입", colSpan: 5, row: 0 },
|
||||
{ id: "B", title: "방류", colSpan: 5, row: 0 },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "inflAssctAftWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe4", upSequnce: 1, align: "right", row:1 },
|
||||
{ id: "efflWqltCod", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe4", upSequnce: 2, align: "right", row:1 },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe4", upSequnce: 3, align: "right", row:1 },
|
||||
];
|
||||
|
||||
/**
|
||||
* (2) 모달페이지
|
||||
*/
|
||||
// 처리시설 수질현황 헤더(모달-연간)
|
||||
const upHeadListModalYear: TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜" },
|
||||
{ id: "inflAssctAftWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" },
|
||||
{ id: "inflAssctAftWqltToc", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "inflAssctAftWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" },
|
||||
{ id: "inflAssctAftWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "inflAssctBfrWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" },
|
||||
{ id: "efflWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe2", upSequnce: 1, align: "right" },
|
||||
{ id: "efflWqltCod", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
{ id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" },
|
||||
{ id: "infoRnDay", title: "강우량", align: "right" },
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 헤더(모달-수질TMS)
|
||||
const upHeadListModalTms: TableUpperProps[] = [
|
||||
{ id: "part", title: "구분" },
|
||||
{ id: "toc", title: "TOC(mg/L)", upName: "upChangeRe", upSequnce: 1, align: "right" },
|
||||
{ id: "ss", title: "SS(mg/L)", upName: "upChangeRe", upSequnce: 2, align: "right" },
|
||||
{ id: "tn", title: "T-N(mg/L)", upName: "upChangeRe", upSequnce: 3, align: "right" },
|
||||
{ id: "tp", title: "T-P(mg/L)", upName: "upChangeRe", upSequnce: 4, align: "right" },
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 데이터(모달-연간)
|
||||
const facilityWaterQltyYearList: FacilityWaterQltyProps[] = [
|
||||
];
|
||||
|
||||
// 처리시설 수질현황 데이터(모달-수질TMS)
|
||||
const facilityWaterQltyTmsList: FacilityWaterQltyTmsProps[] = [
|
||||
];
|
||||
|
||||
// 총인설비 수질현황 헤더 데이터
|
||||
const upHeadListModalChongIn: TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜" },
|
||||
{ id: "tpInflWqltBod", title: "BOD(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" },
|
||||
{ id: "tpInflWqltTp", title: "T-P(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
|
||||
{ id: "efflWqltBod", title: "BOD(mg/L)", upName: "upChangeRe2", upSequnce: 1, align: "right" },
|
||||
{ id: "efflWqltTp", title: "T-P(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
|
||||
];
|
||||
|
||||
/**====================================
|
||||
* Store - api (데이터 호출)
|
||||
====================================*/
|
||||
// 메인페이지
|
||||
// 시설정보 수질 리스트 데이터 호출
|
||||
const fetchFacilityWaterQltyList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string|undefined, nameCd?: string|undefined, fcltCpct?: string|undefined, operationValue?: string|undefined, fcltyNm?: string | undefined): Promise<{ data: FacilityWaterQltyProps[], count: number }> => {
|
||||
try {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/qlty/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질현황 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [], count: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
// 시설정보 수질 리스트 데이터 호출(모달-수질TMS)
|
||||
const fetchFacilityWaterQltyTmsList = async (facilityCd: string|undefined) => {
|
||||
try {
|
||||
const res = await getFetch('wr', '/il/getTms/' + facilityCd);
|
||||
return { data: res.data, count: res.count };
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질현황 TMS 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [], count: 0 };
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 수질 리스트 데이터 호출(모달-이력)
|
||||
const fetchFacilityWaterQltyListHist = async (searchYear: string|undefined, facilityCd: string|undefined): Promise<WaterQualityHistoryResponse | null> => {
|
||||
try {//
|
||||
const res = await getFetch('fo', '/fclt/qlty/hist/' + searchYear + '/' + facilityCd);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질현황 이력 데이터를 가져오는데 실패했습니다:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - export
|
||||
====================================*/
|
||||
export type FacilityWaterQltyType = {
|
||||
FacilityWaterQltyMain: {
|
||||
facilityWaterQltyList: FacilityWaterQltyProps[];
|
||||
excelList: ExcelType[];
|
||||
facilityWaterQltyCount: number;
|
||||
isInit: boolean;
|
||||
mainLabelArray: string[];
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
},
|
||||
|
||||
FacilityWaterQltyModal: {
|
||||
// 처리시설 수질현황
|
||||
upHeadListModalYear: TableUpperProps[];
|
||||
facilityWaterQltyYearList: FacilityWaterQltyProps[];
|
||||
upHeadListModalTms: TableUpperProps[];
|
||||
facilityWaterQltyTmsList: FacilityWaterQltyTmsProps[];
|
||||
|
||||
// 수질tms
|
||||
tmsList: FacilityWaterQltyTmsProps[];
|
||||
msrmtDate: string;
|
||||
|
||||
// 총인시설 수질현황
|
||||
upHeadListModalChongIn: TableUpperProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export const facilityWaterQltyInitState: FacilityWaterQltyType = {
|
||||
FacilityWaterQltyMain: {
|
||||
facilityWaterQltyCount: 0,
|
||||
facilityWaterQltyList: [],
|
||||
excelList: [],
|
||||
isInit: false,
|
||||
mainLabelArray: mainLabelArray,
|
||||
upHeadList1: upHeadList1,
|
||||
upHeadList2: upHeadList2,
|
||||
upHeadList3: upHeadList3,
|
||||
},
|
||||
|
||||
FacilityWaterQltyModal: {
|
||||
// 처리시설 수질현황
|
||||
upHeadListModalYear: upHeadListModalYear,
|
||||
facilityWaterQltyYearList: facilityWaterQltyYearList,
|
||||
upHeadListModalTms: upHeadListModalTms,
|
||||
facilityWaterQltyTmsList: facilityWaterQltyTmsList,
|
||||
|
||||
// 수질tms
|
||||
tmsList: [],
|
||||
msrmtDate: '',
|
||||
|
||||
// 총인시설 수질현황
|
||||
upHeadListModalChongIn: upHeadListModalChongIn,
|
||||
}
|
||||
}
|
||||
|
||||
export type FacilityWaterQltyActions = {
|
||||
/**
|
||||
* 시설정보 수질현황 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
* @param searchYear : 검색 년도
|
||||
* @param part : 구분
|
||||
* @param nameCd : 시설명
|
||||
* @param fcltCpct : 시설용량
|
||||
* @param operationValue : 운영상태코드
|
||||
* @param fcltyNm : 시설명
|
||||
*/
|
||||
searchFacilityWaterQltyList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => Promise<void>;
|
||||
|
||||
/**
|
||||
* 시설정보 수질현황 이력 데이터 호출
|
||||
* @param searchYear : 검색 년도
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchFacilityWaterQltyListHist: (searchYear: string, facilityCd: string) => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param item : 시설수질리스트 타입
|
||||
* @returns : 없음
|
||||
* @description : 시설수질리스트 타입의 데이터를 표현 방식으로 바꿔주는 함수
|
||||
* - msrDt : YYYY-MM-DD 형식으로 변환
|
||||
* - inflAssctAftWqltBod : 소수점 1자리까지 표현
|
||||
* - inflAssctAftWqltTn : 소수점 1자리까지 표현
|
||||
* - inflAssctBfrWqltTp : 소수점 1자리까지 표현
|
||||
* - efflWqltBod : 소수점 2자리까지 표현
|
||||
* - efflWqltTn : 소수점 2자리까지 표현
|
||||
* - efflWqltTp : 소수점 2자리까지 표현
|
||||
* @author : 박진우
|
||||
* @date : 2025-04-24
|
||||
*/
|
||||
const dataFormSetting = (item: FacilityWaterQltyProps) => {
|
||||
DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> });
|
||||
}
|
||||
|
||||
export type FacilityWaterQltyStore = FacilityWaterQltyType & FacilityWaterQltyActions;
|
||||
|
||||
export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType) => FacilityWaterQltyType) => void): FacilityWaterQltyActions => {
|
||||
return {
|
||||
// 메인페이지
|
||||
/**
|
||||
* 시설정보 수질현황 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
* @param searchYear : 검색 년도
|
||||
* @param part : 구분
|
||||
* @param nameCd : 시설명
|
||||
* @param fcltCpct : 시설용량
|
||||
* @param operationValue : 운영상태코드
|
||||
* @param fcltyNm : 시설명
|
||||
*/
|
||||
searchFacilityWaterQltyList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchFacilityWaterQltyList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const rtnData = res.data.map(item => {
|
||||
dataFormSetting(item)
|
||||
if(item.inflAssctAftWqltTn) {
|
||||
item.inflAssctAftWqltTn = Number(Math.round(Number(item.inflAssctAftWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTn){
|
||||
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctAftWqltTp){
|
||||
item.inflAssctAftWqltTp = Number(Math.round(Number(item.inflAssctAftWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTp){
|
||||
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltBod){
|
||||
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltBod){
|
||||
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltSs){
|
||||
item.inflAssctAftWqltSs = Number(Math.round(Number(item.inflAssctAftWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltSs){
|
||||
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
const excelDownList: ExcelType[] = [];
|
||||
if(pageSize>5000){
|
||||
res.data.forEach(item => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.addr,
|
||||
용량: item.fctCpc,
|
||||
유입BOD: item.inflAssctAftWqltBod,
|
||||
유입TOC: item.inflAssctAftWqltToc,
|
||||
유입SS: item.inflAssctAftWqltSs,
|
||||
유입TN: item.inflAssctAftWqltTn,
|
||||
유입TP: item.inflAssctAftWqltTp,
|
||||
유출BOD: item.efflWqltBod,
|
||||
유출TOC: item.efflWqltCod,
|
||||
유출SS: item.efflWqltSs,
|
||||
유출TN: item.efflWqltTn,
|
||||
유출TP: item.efflWqltTp,
|
||||
});
|
||||
});
|
||||
}else{
|
||||
res.data.forEach((item: FacilityWaterQltyProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
});
|
||||
}
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
...state,
|
||||
FacilityWaterQltyMain: pageSize<5000?{
|
||||
...state.FacilityWaterQltyMain,
|
||||
facilityWaterQltyList: rtnData,
|
||||
facilityWaterQltyCount: res.count,
|
||||
}:{
|
||||
...state.FacilityWaterQltyMain,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
|
||||
searchFacilityWaterQltyListHist: async (searchYear: string, facilityCd: string) => {
|
||||
const res = await fetchFacilityWaterQltyListHist(searchYear, facilityCd);
|
||||
const res1 = await fetchFacilityWaterQltyTmsList(facilityCd);
|
||||
|
||||
let rtnMsrmtDate = '';
|
||||
const rtnTmsList: FacilityWaterQltyTmsProps[] = [];
|
||||
if(res1.data){
|
||||
rtnTmsList.push({
|
||||
part: '평균',
|
||||
toc: res1.data.tocAvgVl,
|
||||
ss: res1.data.ssAvgVl,
|
||||
tn: res1.data.tnAvgVl,
|
||||
tp: res1.data.tpAvgVl,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최대',
|
||||
toc: res1.data.tocMaxVl,
|
||||
ss: res1.data.ssMaxVl,
|
||||
tn: res1.data.tnMaxVl,
|
||||
tp: res1.data.tpMaxVl,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최소',
|
||||
toc: res1.data.tocMinVl,
|
||||
ss: res1.data.ssMinVl,
|
||||
tn: res1.data.tnMinVl,
|
||||
tp: res1.data.tpMinVl,
|
||||
});
|
||||
|
||||
rtnMsrmtDate = res1.data.msrmtDate;
|
||||
}else{
|
||||
rtnTmsList.push({
|
||||
part: '평균',
|
||||
toc: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최대',
|
||||
toc: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
});
|
||||
|
||||
rtnTmsList.push({
|
||||
part: '최소',
|
||||
toc: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
});
|
||||
|
||||
rtnMsrmtDate = '';
|
||||
}
|
||||
|
||||
if(Array.isArray(res) || !res || !('data' in res) || !res.data || !res.data.wqltObjs || res.data.wqltObjs.length === 0) {
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
...state,
|
||||
FacilityWaterQltyModal: {
|
||||
...state.FacilityWaterQltyModal,
|
||||
facilityWaterQltyYearList: [],
|
||||
tmsList : rtnTmsList,
|
||||
msrmtDate : rtnMsrmtDate
|
||||
}
|
||||
}))
|
||||
return;
|
||||
}
|
||||
|
||||
const tmpData:FacilityWaterQltyProps[] = [];
|
||||
|
||||
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
|
||||
for(let idx = 0; idx < res.data.wqltObjs.length; idx++) {
|
||||
const item = res.data.wqltObjs[idx];
|
||||
if (!item) continue;
|
||||
|
||||
const rainDay = Number(item.infoRnDay) >= 3 ? 1 : 0;
|
||||
let rainEffectDay = 0;
|
||||
|
||||
if(idx < res.data.wqltObjs.length - 2) {
|
||||
if(rainDay == 1) {
|
||||
rainEffectDay = 1;
|
||||
} else {
|
||||
if(idx >= 2) {
|
||||
const prevItem1 = res.data.wqltObjs[idx-1];
|
||||
const prevItem2 = res.data.wqltObjs[idx-2];
|
||||
if((prevItem1 && Number(prevItem1.infoRnDay) >= 3) || (prevItem2 && Number(prevItem2.infoRnDay) >= 3)) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(idx < res.data.wqltObjs.length - 1) {
|
||||
const nextItem = res.data.wqltObjs[idx+1];
|
||||
if(rainDay == 1 || (nextItem && Number(nextItem.infoRnDay) >= 3)) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
} else {
|
||||
rainEffectDay = rainDay;
|
||||
}
|
||||
|
||||
tmpData.push({
|
||||
...item,
|
||||
rainEffectDay: rainEffectDay,
|
||||
} as FacilityWaterQltyProps);
|
||||
}
|
||||
|
||||
const rtnData = tmpData.map((item: FacilityWaterQltyProps) => {
|
||||
dataFormSetting(item)
|
||||
if(item.inflAssctAftWqltTn) {
|
||||
item.inflAssctAftWqltTn = Number(Math.round(Number(item.inflAssctAftWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTn){
|
||||
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctBfrWqltTp){
|
||||
item.inflAssctBfrWqltTp = Number(Math.round(Number(item.inflAssctBfrWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.efflWqltTp){
|
||||
item.efflWqltTp = Number(Math.round(Number(item.efflWqltTp) * 1000)/1000).toFixed(3);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltBod){
|
||||
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltBod){
|
||||
item.efflWqltBod = Number(Math.round(Number(item.efflWqltBod) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltSs){
|
||||
item.inflAssctAftWqltSs = Number(Math.round(Number(item.inflAssctAftWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltSs){
|
||||
item.efflWqltSs = Number(Math.round(Number(item.efflWqltSs) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.inflAssctAftWqltToc){
|
||||
item.inflAssctAftWqltToc = Number(Math.round(Number(item.inflAssctAftWqltToc) * 10)/10).toFixed(1);
|
||||
}
|
||||
if(item.efflWqltCod){
|
||||
item.efflWqltCod = Number(Math.round(Number(item.efflWqltCod) * 10)/10).toFixed(1);
|
||||
}
|
||||
|
||||
if(item.tpInflWqltBod){
|
||||
item.tpInflWqltBod = item.tpInflWqltBod?Number(Math.round(Number(item.tpInflWqltBod) * 10)/10).toFixed(1):Number(item.tpInflWqltBod)===0?'0.0':'';
|
||||
}else{
|
||||
item.tpInflWqltBod = '';
|
||||
}
|
||||
|
||||
if(item.tpInflWqltTp){
|
||||
item.tpInflWqltTp = item.tpInflWqltTp?Number(Math.round(Number(item.tpInflWqltTp) * 1000)/1000).toFixed(3): Number(item.tpInflWqltTp)===0?'0.000':'';
|
||||
}else{
|
||||
item.tpInflWqltTp = '';
|
||||
}
|
||||
return item;
|
||||
})
|
||||
set((state: FacilityWaterQltyType) => ({
|
||||
...state,
|
||||
FacilityWaterQltyModal: {
|
||||
...state.FacilityWaterQltyModal,
|
||||
facilityWaterQltyYearList: rtnData,
|
||||
tmsList : rtnTmsList,
|
||||
msrmtDate : rtnMsrmtDate
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
const FlowRateSearchLabelArray:string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
export type flowRateListProps = {
|
||||
bscFctCd : string,
|
||||
sidoNm : string,
|
||||
sggNm : string,
|
||||
bscFctNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
lclgvrnmntNm : string,
|
||||
totInflAmnt : number | '',
|
||||
inflAmnt : number | '',
|
||||
sumFlow : number | '',
|
||||
returnAmnt : number | '',
|
||||
efflAmnt : number | '',
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
infoRnDay : number | '',
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
용량: number,
|
||||
총유입량: number | '',
|
||||
하수유입량: number | '',
|
||||
연계처리량: number | '',
|
||||
총인반류수량: number | '',
|
||||
방류량: number | '',
|
||||
환경청:string|'',
|
||||
}
|
||||
|
||||
export type modalExcelType = {
|
||||
날짜: string,
|
||||
"총유입량(m³/일)": number | '',
|
||||
"하수유입량(m³/일)": number | '',
|
||||
"연계처리량(m³/일)": number | '',
|
||||
"총인반류수량(m³/일)": number | '',
|
||||
"방류량(m³/일)": number | '',
|
||||
"강우량": number | string | '',
|
||||
}
|
||||
/**
|
||||
* (2) 모달
|
||||
*/
|
||||
export interface FlowRateModalInterface {
|
||||
msrDt : string,
|
||||
totInflAmnt : number | '',
|
||||
inflAmnt : number | '',
|
||||
sumFlow : number | '',
|
||||
returnAmnt : number | '',
|
||||
efflAmnt : number | '',
|
||||
infoRnDay : number | string | '',
|
||||
rainEffectDay : number | string | '' ,
|
||||
}
|
||||
export type FlowRateModalProps = {
|
||||
msrDt : string,
|
||||
totInflAmnt : number,
|
||||
inflAmnt : number,
|
||||
sumFlow : number,
|
||||
returnAmnt : number,
|
||||
efflAmnt : number,
|
||||
infoRnDay : number | string | '',
|
||||
rainEffectDay : number | string | '',
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 리스트 (행정별)
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2},
|
||||
{ id: "A", title: "행정명", row: 0 ,colSpan: 2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe", row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
// 리스트 (권역별)
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2},
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3},
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2},
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2},
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2}
|
||||
];
|
||||
|
||||
// 리스트 (환경청별별)
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row: 0, colSpan: 3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정명", row: 0 ,colSpan: 2 },
|
||||
{ id: "ctpvNm", title: "시도", upName:"upChangeRe2", row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe2", row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2 },
|
||||
{ id: "daddr", title: "주소", row: 0, rowSpan: 2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "totInflAmnt", title: "총 유입입량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "inflAmnt", title: "하수유입량\n(m³/일)", align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "sumFlow", title: '연계처리량\n(m³/일)', align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align:"right", row: 0, rowSpan: 2 },
|
||||
{ id: "efflAmnt", title: '방류량\n(m³/일)', align:"right", row: 0, rowSpan: 2 }
|
||||
];
|
||||
|
||||
const flowRateList:flowRateListProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* (2) 모달
|
||||
*/
|
||||
|
||||
const upHeadListFlowRateModal:TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜"},
|
||||
{ id: "totInflAmnt", title: "총 유입량(m³/일)", align:"right"},
|
||||
{ id: "inflAmnt", title: "하수유입량(m³/일)", align:"right"},
|
||||
{ id: "sumFlow", title: "연계처리량(m³/일)", align:"right"},
|
||||
{ id: "returnAmnt", title: "총인 반류수량(m³/일)", align:"right"},
|
||||
{ id: "efflAmnt", title: "방류량(m³/일)", align:"right"},
|
||||
{ id: "infoRnDay", title: "강우량", align:"right"}
|
||||
]
|
||||
|
||||
const modalFlowRateListYear:FlowRateModalProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - API
|
||||
====================================*/
|
||||
const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
try {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
console.log(url);
|
||||
return { data: res.data, count: res.count }
|
||||
} catch (error) {
|
||||
console.error('시설정보 유량현황 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [], count: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
const fetchFlowRateModalList = async (bscFctCd: string, searchYear: string) => {
|
||||
try {
|
||||
const url = '/fclt/flow/' + bscFctCd + '/' + searchYear;
|
||||
const res = await getFetch('fo', url);
|
||||
|
||||
// msrDt 오름차순으로 정렬
|
||||
const sortedData = res.data.sort((a: FlowRateModalInterface, b: FlowRateModalInterface) => {
|
||||
return new Date(a.msrDt).getTime() - new Date(b.msrDt).getTime();
|
||||
});
|
||||
|
||||
return { data: sortedData }
|
||||
} catch (error) {
|
||||
console.error('시설정보 유량현황 모달 데이터를 가져오는데 실패했습니다:', error);
|
||||
return { data: [] }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
|
||||
export type FlowRateSearchActions = {
|
||||
searchFlowRateList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
|
||||
searchFlowRateModalList : (bscFctCd: string, searchYear: string) => void;
|
||||
}
|
||||
|
||||
export type FlowRateSearchType = {
|
||||
FlowRateSearch: {
|
||||
isInit: boolean;
|
||||
flowRateSearchLabelArray:string[];
|
||||
},
|
||||
|
||||
FlowRateList : {
|
||||
isInit : boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
flowRateList:flowRateListProps[];
|
||||
flowRateCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
|
||||
FlowRateModal : {
|
||||
isInit : boolean;
|
||||
modalFlowRateListYear : FlowRateModalProps[];
|
||||
upHeadListFlowRateModalYear : TableUpperProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export type FlowRateSearchStore = FlowRateSearchType & FlowRateSearchActions;
|
||||
|
||||
const dataFormSetting=(item : flowRateListProps | FlowRateModalProps)=> {
|
||||
DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'totInflAmnt', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'inflAmnt', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'sumFlow', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'efflWqltBod', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'returnAmnt', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'efflAmnt', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
export const flowRateSearchInitState:FlowRateSearchType = {
|
||||
FlowRateSearch: {
|
||||
isInit: false,
|
||||
flowRateSearchLabelArray: FlowRateSearchLabelArray,
|
||||
},
|
||||
FlowRateList : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
flowRateList : flowRateList,
|
||||
flowRateCount : 0,
|
||||
excelList: []
|
||||
},
|
||||
FlowRateModal : {
|
||||
isInit : false,
|
||||
upHeadListFlowRateModalYear : upHeadListFlowRateModal,
|
||||
modalFlowRateListYear : modalFlowRateListYear,
|
||||
}
|
||||
}
|
||||
|
||||
export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => FlowRateSearchType) => void)=>FlowRateSearchActions=(set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => {
|
||||
return {
|
||||
searchFlowRateList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
const rtnData = data.map((item: flowRateListProps) => {
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0)
|
||||
dataFormSetting(item);
|
||||
return item;
|
||||
});
|
||||
|
||||
if(pageSize>5000){
|
||||
rtnData.forEach((item: flowRateListProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
용량: item.fctCpc,
|
||||
총유입량: item.totInflAmnt,
|
||||
하수유입량: item.inflAmnt,
|
||||
연계처리량: item.sumFlow,
|
||||
총인반류수량: item.returnAmnt,
|
||||
방류량: item.efflAmnt,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
console.log('excelDownList' , excelDownList);
|
||||
set((state: FlowRateSearchType) => ({
|
||||
...state,
|
||||
FlowRateList: pageSize<5000?{
|
||||
...state.FlowRateList,
|
||||
flowRateList: rtnData,
|
||||
flowRateCount: res.count,
|
||||
}:{
|
||||
...state.FlowRateList,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
searchFlowRateModalList: async (bscFctCd: string, searchYear: string) => {
|
||||
const res = await fetchFlowRateModalList(bscFctCd, searchYear);
|
||||
const data = res.data;
|
||||
|
||||
const tmpData:FlowRateModalProps[] = [];
|
||||
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
|
||||
for(let idx = 0; idx < data.length; idx++) {
|
||||
const item = data[idx];
|
||||
const rainDay = Number(item.infoRnDay) >= 3 ? 1 : 0;
|
||||
let rainEffectDay = 0;
|
||||
|
||||
if(idx < data.length - 2) {
|
||||
if(rainDay == 1) {
|
||||
rainEffectDay = 1;
|
||||
} else {
|
||||
if(idx >= 2) {
|
||||
if(Number(data[idx-1].infoRnDay) >= 3 || Number(data[idx-2].infoRnDay) >= 3) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(idx < data.length - 1) {
|
||||
if(rainDay == 1 || Number(data[idx+1].infoRnDay) >= 3) {
|
||||
rainEffectDay = 1;
|
||||
}
|
||||
} else {
|
||||
rainEffectDay = rainDay;
|
||||
}
|
||||
|
||||
tmpData.push({
|
||||
...item,
|
||||
rainEffectDay: rainEffectDay,
|
||||
});
|
||||
}
|
||||
|
||||
const rtnData = tmpData.map((item: FlowRateModalProps) => {
|
||||
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0)
|
||||
dataFormSetting(item);
|
||||
return item;
|
||||
});
|
||||
|
||||
set((state: FlowRateSearchType) => ({
|
||||
...state,
|
||||
FlowRateModal: {
|
||||
...state.FlowRateModal,
|
||||
modalFlowRateListYear: rtnData || [],
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
'use client'
|
||||
|
||||
import { type ReactNode, createContext, useContext, useRef } from 'react'
|
||||
import { useStore } from 'zustand'
|
||||
import { type FoStore, StoreZus } from './store'
|
||||
|
||||
|
||||
export type StoreApi = ReturnType<typeof StoreZus>
|
||||
|
||||
export const StoreContext = createContext<StoreApi | undefined>(
|
||||
undefined,
|
||||
)
|
||||
|
||||
export interface StoreProviderProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const StoreProvider = ({
|
||||
children,
|
||||
}: StoreProviderProps) => {
|
||||
const storeRef = useRef<StoreApi>()
|
||||
|
||||
if (!storeRef.current) {
|
||||
const store = StoreZus()
|
||||
storeRef.current = store
|
||||
}
|
||||
|
||||
return (
|
||||
<StoreContext.Provider value={storeRef.current}>
|
||||
{children}
|
||||
</StoreContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useFoStore = <T,>(
|
||||
selector: (store: FoStore) => T,
|
||||
): T => {
|
||||
const storeContext = useContext(StoreContext)
|
||||
|
||||
if (!storeContext) {
|
||||
throw new Error(`useStore must be used within StoreProvider`)
|
||||
}
|
||||
|
||||
return useStore(storeContext, selector)
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
type PlanSewageProps = {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
bscFctNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
spareCapacity : number,
|
||||
variableLoadPercent : number,
|
||||
classifiedSewerPercent : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
sprtProcZoneAr : number,
|
||||
procZoneSm : number,
|
||||
avgInflAmnt : number,
|
||||
avgInflAmntSunny : number,
|
||||
maxInflAmntSunny : number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "행정구역", upSequnce:1, row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1},
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1},
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정구역", upName:"upChangeRe", upSequnce:1, row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' },
|
||||
{ id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' },
|
||||
];
|
||||
|
||||
const planSewageList:PlanSewageProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - api
|
||||
====================================*/
|
||||
const fetchPlanSewageList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + (nameCd || '0') + '/' + (fcltCpct || '0') + '/' + (operationValue || '0') +'/0'+ (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/prcsFclt/info/plan/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
console.log(url);
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type ExcelType = {
|
||||
시설코드: string;
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string;
|
||||
시군구: string;
|
||||
시설이름: string;
|
||||
주소: string;
|
||||
시설용량: number;
|
||||
여유용량: number;
|
||||
변동부하율 : number;
|
||||
분류식화율 : number;
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : PlanSewageProps)=> {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'spareCapacity', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'variableLoadPercent', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'classifiedSewerPercent', item: item as unknown as Record<string, unknown>});
|
||||
};
|
||||
|
||||
export type PlanSewageActions = {
|
||||
searchPlanSewageList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
export type PlanSewageType = {
|
||||
PlanSewageSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
PlanSewage : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
planSewageList: PlanSewageProps[];
|
||||
planSewageCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
}
|
||||
|
||||
export const planSewageInitState: PlanSewageType = {
|
||||
PlanSewageSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
PlanSewage : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
planSewageList : planSewageList,
|
||||
planSewageCount : 0,
|
||||
excelList : []
|
||||
},
|
||||
}
|
||||
|
||||
export type PlanSewageStore = PlanSewageType & PlanSewageActions;
|
||||
|
||||
export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageType) => void)=>PlanSewageActions=(set: (fn: (state: PlanSewageType) => PlanSewageType) => void) => {
|
||||
return {
|
||||
searchPlanSewageList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchPlanSewageList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const excelDownList: ExcelType[] = [];
|
||||
console.log('res' , res.data);
|
||||
/**
|
||||
* 결과데이터 계산
|
||||
* (1) 여유용량 = 시설용량 - 건기시 평균유량
|
||||
* (2) 변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년)
|
||||
* (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100
|
||||
*/
|
||||
const resultData = res.data.map((item:PlanSewageProps) => {
|
||||
item.spareCapacity = Number(item.fctCpc) - Number(item.avgInflAmntSunny);
|
||||
item.variableLoadPercent = item.maxInflAmntSunny && item.maxInflAmntSunny!==0 ? Number(item.maxInflAmntSunny) / Number(item.avgInflAmntSunny) : 0;
|
||||
item.classifiedSewerPercent = item.sprtProcZoneAr && item.sprtProcZoneAr!==0 ? Number(item.sprtProcZoneAr) / Number(item.procZoneSm) * 100 : 0;
|
||||
return item;
|
||||
});
|
||||
|
||||
resultData.forEach((item:PlanSewageProps) => {
|
||||
dataFormSetting(item)
|
||||
})
|
||||
|
||||
if(pageSize>5000){
|
||||
resultData.forEach((item:PlanSewageProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.lgbsn,
|
||||
단위유역: item.rvbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시설이름: item.bscFctNm,
|
||||
시도: item.sido,
|
||||
시군구: item.gugun,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
여유용량: item.spareCapacity,
|
||||
변동부하율: item.variableLoadPercent,
|
||||
분류식화율: item.classifiedSewerPercent,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
set((state:PlanSewageType) => ({
|
||||
...state,
|
||||
PlanSewage: pageSize<5000?{
|
||||
...state.PlanSewage,
|
||||
planSewageList: resultData,
|
||||
planSewageCount: res.count,
|
||||
}:{
|
||||
...state.PlanSewage,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,507 @@
|
||||
import { getFetchAreaList, postFetch } from "@/app/components/api";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 처리구역 리스트
|
||||
export type ProcessAreaProps = {
|
||||
swtrmtFcltCd : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
swtrmtFcltNm : string,
|
||||
location : string,
|
||||
fctCpc : number | '',
|
||||
ruse : boolean,
|
||||
yrDt4 : string,
|
||||
yr : string,
|
||||
yrDc1 : string,
|
||||
yrDc2 : string,
|
||||
yrDc3 : string,
|
||||
yrDc4 : string,
|
||||
/**
|
||||
* 증설계획
|
||||
*/
|
||||
// 기승인(당초4단계), 현재, 변경1~4
|
||||
planSwageQntSumDt4 : number | '',
|
||||
planSwageQntSum : number | '',
|
||||
planSwageQntSumDc1 : number | '',
|
||||
planSwageQntSumDc2 : number | '',
|
||||
planSwageQntSumDc3 : number | '',
|
||||
planSwageQntSumDc4 : number | '',
|
||||
/**
|
||||
* 처리인구
|
||||
*/
|
||||
// 기승인(당초4단계), 변경1~4
|
||||
swtrmtPpltnCntDt4 : number | '',
|
||||
swtrmtPpltnCnt : number | '',
|
||||
swtrmtPpltnCntDc1 : number | '',
|
||||
swtrmtPpltnCntDc2 : number | '',
|
||||
swtrmtPpltnCntDc3 : number | '',
|
||||
swtrmtPpltnCntDc4 : number | '',
|
||||
/**
|
||||
* 처리구역면적
|
||||
*/
|
||||
// 기승인(당초4단계), 변경1~4
|
||||
swtrmtZoneAreaDt4 : number | '',
|
||||
swtrmtZoneArea : number | '',
|
||||
swtrmtZoneAreaDc1 : number | '',
|
||||
swtrmtZoneAreaDc2 : number | '',
|
||||
swtrmtZoneAreaDc3 : number | '',
|
||||
swtrmtZoneAreaDc4 : number | '',
|
||||
// 처리구역
|
||||
trtDstr : string | '',
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number | '',
|
||||
증설계획기존: number | '',
|
||||
증설계획현재: number | '',
|
||||
증설계획1단계: number | '',
|
||||
증설계획2단계: number | '',
|
||||
증설계획3단계: number | '',
|
||||
증설계획4단계: number | '',
|
||||
처리인구기존: number | '',
|
||||
처리인구현재: number | '',
|
||||
처리인구1단계: number | '',
|
||||
처리인구2단계: number | '',
|
||||
처리인구3단계: number | '',
|
||||
처리인구4단계: number | '',
|
||||
처리구역기존: number | '',
|
||||
처리구역현재: number | '',
|
||||
처리구역1단계: number | '',
|
||||
처리구역2단계: number | '',
|
||||
처리구역3단계: number | '',
|
||||
처리구역4단계: number | '',
|
||||
처리구역: string | ''
|
||||
}
|
||||
|
||||
// (2) 처리구역 팝업
|
||||
// 시설증설 계획
|
||||
export type FcltyImproveInfoProps = {
|
||||
planSwageQntSumDt4 : number | '',
|
||||
planSwageQntSum : number | '',
|
||||
planSwageQntSumDc1 : number | '',
|
||||
planSwageQntSumDc2 : number | '',
|
||||
planSwageQntSumDc3 : number | '',
|
||||
planSwageQntSumDc4 : number | '',
|
||||
}
|
||||
|
||||
// 처리인구 계획
|
||||
export type ProcessPopulationProps = {
|
||||
swtrmtPpltnCntDt4 : number | '',
|
||||
swtrmtPpltnCnt : number | '',
|
||||
swtrmtPpltnCntDc1 : number | '',
|
||||
swtrmtPpltnCntDc2 : number | '',
|
||||
swtrmtPpltnCntDc3 : number | '',
|
||||
swtrmtPpltnCntDc4 : number | '',
|
||||
}
|
||||
// 처리구역 계획
|
||||
export type ProcessAreaPlanProps = {
|
||||
swtrmtZoneAreaDt4 : number | '',
|
||||
swtrmtZoneArea : number | '',
|
||||
swtrmtZoneAreaDc1 : number | '',
|
||||
swtrmtZoneAreaDc2 : number | '',
|
||||
swtrmtZoneAreaDc3 : number | '',
|
||||
swtrmtZoneAreaDc4 : number | '',
|
||||
trtDstr : string,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '시설상태', '연도별', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더(행정별)
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "swtrmtFcltCd", title: "시설코드", rowSpan:3, row:0},
|
||||
{ id: "A", title: "행정구역", colSpan:2, rowSpan:2, row:0},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", row:2 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe", row:2 },
|
||||
{ id: "swtrmtFcltNm", title: "시설명", rowSpan:3, row:0},
|
||||
{ id: "location", title: "주소", rowSpan:3, row:0, },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", rowSpan:3, row:0},
|
||||
{ id: "B", title: "시설계획", colSpan:19, row:0},
|
||||
{ id: "C", title: "증설계획(m³/일)", colSpan:6, row:1},
|
||||
{ id: "planSwageQntSumDt4", title: "기승인\n4단계", row:2},
|
||||
{ id: "planSwageQntSum", title: "현재", row:2},
|
||||
{ id: "planSwageQntSumDc1", title: "1단계", row:2},
|
||||
{ id: "planSwageQntSumDc2", title: "2단계", row:2},
|
||||
{ id: "planSwageQntSumDc3", title: "3단계", row:2},
|
||||
{ id: "planSwageQntSumDc4", title: "4단계", row:2},
|
||||
{ id: "D", title: "처리인구(인)", colSpan:6, row:1},
|
||||
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계", row:2},
|
||||
{ id: "swtrmtPpltnCnt", title: "현재", row:2},
|
||||
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:2},
|
||||
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:2},
|
||||
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:2},
|
||||
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:2},
|
||||
{ id: "E", title: "처리구역(km²)", colSpan:7, row:1},
|
||||
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계", row:2},
|
||||
{ id: "swtrmtZoneArea", title: "현재", row:2},
|
||||
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:2},
|
||||
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:2},
|
||||
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:2},
|
||||
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:2},
|
||||
{ id: "trtDstr", title: "처리구역", row:2}
|
||||
];
|
||||
|
||||
const processAreaList:ProcessAreaProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* 처리구역정보 상세팝업
|
||||
*/
|
||||
// 시설증설 계획 (헤더)
|
||||
const upHeadListFcltyImproveInfo:TableUpperProps[] = [
|
||||
{ id: "planSwageQntSumDt4", title: "기승인\n4단계(m³/일)", rowSpan:2, row:0},
|
||||
{ id: "A", title: "증설계획(m³/일)", colSpan:5, row:0},
|
||||
{ id: "planSwageQntSum", title: "현재", row:1},
|
||||
{ id: "planSwageQntSumDc1", title: "1단계", row:1},
|
||||
{ id: "planSwageQntSumDc2", title: "2단계", row:1},
|
||||
{ id: "planSwageQntSumDc3", title: "3단계", row:1},
|
||||
{ id: "planSwageQntSumDc4", title: "4단계", row:1},
|
||||
];
|
||||
|
||||
// 시설증설 계획 (리스트)
|
||||
const gridListFcltyImproveInfo:FcltyImproveInfoProps[] = [
|
||||
];
|
||||
|
||||
// 처리인구 계획 (헤더)
|
||||
const upHeadListProcessPopulation:TableUpperProps[] = [
|
||||
{ id: "swtrmtPpltnCntDt4", title: "기승인\n4단계(인)", rowSpan:2, row:0},
|
||||
{ id: "A", title: "처리인구(인)", colSpan:5, row:0},
|
||||
{ id: "swtrmtPpltnCnt", title: "현재", row:1},
|
||||
{ id: "swtrmtPpltnCntDc1", title: "1단계", row:1},
|
||||
{ id: "swtrmtPpltnCntDc2", title: "2단계", row:1},
|
||||
{ id: "swtrmtPpltnCntDc3", title: "3단계", row:1},
|
||||
{ id: "swtrmtPpltnCntDc4", title: "4단계", row:1},
|
||||
];
|
||||
|
||||
// 처리인구 계획 (리스트)
|
||||
const gridListProcessPopulation:ProcessPopulationProps[] = [
|
||||
];
|
||||
|
||||
// 처리구역 계획 (헤더)
|
||||
const upHeadListProcessAreaPlan:TableUpperProps[] = [
|
||||
{ id: "swtrmtZoneAreaDt4", title: "기승인\n4단계(km²)", rowSpan:2, row:0},
|
||||
{ id: "A", title: "처리면적(km²)", colSpan:6, row:0},
|
||||
{ id: "swtrmtZoneArea", title: "현재", row:1},
|
||||
{ id: "swtrmtZoneAreaDc1", title: "1단계", row:1},
|
||||
{ id: "swtrmtZoneAreaDc2", title: "2단계", row:1},
|
||||
{ id: "swtrmtZoneAreaDc3", title: "3단계", row:1},
|
||||
{ id: "swtrmtZoneAreaDc4", title: "4단계", row:1},
|
||||
{ id: "trtDstr", title: "처리구역", row:1}
|
||||
];
|
||||
|
||||
// 시설증설 계획 (리스트)
|
||||
const gridListProcessAreaPlan:ProcessAreaPlanProps[] = [
|
||||
];
|
||||
|
||||
/**====================================
|
||||
* Store - API
|
||||
=====================================*/
|
||||
// 시설 상세 정보 조회 API
|
||||
const fetchFacilityDetailInfo = async (swtrmtFcltCd: string) => {
|
||||
try {
|
||||
const tailUrl = '/1/5/A/0/0/0/SW';
|
||||
const res = await postFetch('fo', '/prcsFclt/ruseInfo'+tailUrl, [swtrmtFcltCd]);
|
||||
return { data:res.data, count:res.count };
|
||||
} catch (error) {
|
||||
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : string | undefined, sggNm : string | undefined, targetYear : string | undefined ): Promise<{data:ProcessAreaProps[], count:number}> => {
|
||||
try {
|
||||
targetYear = targetYear ? targetYear : "2024";
|
||||
const baseUrl = 'https://apigateway.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy';
|
||||
const queryParams = new URLSearchParams();
|
||||
|
||||
if (ctpvNm && ctpvNm !== '전체') queryParams.append('ctpvNm', ctpvNm);
|
||||
if (sggNm && sggNm !== '전체') queryParams.append('sggNm', sggNm);
|
||||
if (targetYear) queryParams.append('targetYear',targetYear);
|
||||
|
||||
const queryString = queryParams.toString();
|
||||
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||
const res = await getFetchAreaList(url);
|
||||
|
||||
if(res && res.length > 0){
|
||||
const enrichedData = await Promise.all(
|
||||
res.map(async (item: ProcessAreaProps) => {
|
||||
upHeadList1.forEach((head:TableUpperProps) => {
|
||||
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + item.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + item.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + item.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + item.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + item.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + item.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
const res = await fetchFacilityDetailInfo(item.swtrmtFcltCd);
|
||||
const detailInfo = res.data.filter((item:ProcessAreaProps) => item.ruse === true);
|
||||
return {
|
||||
...item,
|
||||
sido: detailInfo.length > 0 ? detailInfo[0].sido||'' : '',
|
||||
sigungo: detailInfo.length > 0 ? detailInfo[0].gugun||'' : '',
|
||||
location: detailInfo.length > 0 ? detailInfo[0].addr||'' : '',
|
||||
fctCpc: detailInfo.length > 0 ? detailInfo[0].fctCpc||'' : 0,
|
||||
trtDstr: detailInfo.length > 0 ? detailInfo[0].trtDstr||'' : '',
|
||||
};
|
||||
})
|
||||
);
|
||||
const startIndex = (pageNo - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const paginatedData = enrichedData.slice(startIndex, endIndex);
|
||||
return {data: paginatedData, count: enrichedData.length};
|
||||
}else{
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('시설계획정보를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
=====================================*/
|
||||
export type ProcessAreaActions = {
|
||||
searchProcessAreaList : (pageNo: number, pageSize: number, ctpvNm?:string, sggNm?:string, targetYear?:string) => void;
|
||||
initModalData : (swtrmtFcltCd:string) => void;
|
||||
}
|
||||
|
||||
export type ProcessAreaType = {
|
||||
ProcessAreaSearch: {
|
||||
isInit: boolean;
|
||||
processFacilityLabelArray:string[];
|
||||
},
|
||||
|
||||
ProcessArea : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
processAreaList: ProcessAreaProps[];
|
||||
processAreaCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
|
||||
ProcessAreaDetail : {
|
||||
isInit: boolean;
|
||||
upHeadListFcltyImproveInfo: TableUpperProps[];
|
||||
gridListFcltyImproveInfo: FcltyImproveInfoProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
upHeadListProcessPopulation: TableUpperProps[];
|
||||
gridListProcessPopulation: ProcessPopulationProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
upHeadListProcessAreaPlan: TableUpperProps[];
|
||||
gridListProcessAreaPlan: ProcessAreaPlanProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
},
|
||||
}
|
||||
|
||||
export const processAreaInitState: ProcessAreaType = {
|
||||
ProcessAreaSearch: {
|
||||
isInit: false,
|
||||
processFacilityLabelArray: ProcessFacilityLabelArray,
|
||||
},
|
||||
|
||||
ProcessArea : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
processAreaList : processAreaList,
|
||||
processAreaCount : 0,
|
||||
excelList : []
|
||||
},
|
||||
|
||||
ProcessAreaDetail : {
|
||||
isInit : false,
|
||||
upHeadListFcltyImproveInfo : upHeadListFcltyImproveInfo,
|
||||
gridListFcltyImproveInfo : gridListFcltyImproveInfo,
|
||||
upHeadListProcessPopulation : upHeadListProcessPopulation,
|
||||
gridListProcessPopulation : gridListProcessPopulation,
|
||||
upHeadListProcessAreaPlan : upHeadListProcessAreaPlan,
|
||||
gridListProcessAreaPlan : gridListProcessAreaPlan,
|
||||
},
|
||||
}
|
||||
|
||||
// 상태 설정 함수 타입 정의
|
||||
type SetStateFunction = (state: ProcessAreaType | ((state: ProcessAreaType) => ProcessAreaType)) => void;
|
||||
|
||||
export type ProcessAreaStore = ProcessAreaType & ProcessAreaActions;
|
||||
|
||||
export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set: SetStateFunction) => {
|
||||
return {
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessAreaList: async ( pageNo:number, pageSize:number, ctpvNm?:string, sggNm?:string, targetYear?:string) => {
|
||||
const res = await fetchProcessAreaList(pageNo, pageSize, ctpvNm, sggNm, targetYear);
|
||||
res.data.forEach((item:ProcessAreaProps) => {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
|
||||
})
|
||||
const excelDownList: ExcelType[] = [];
|
||||
if(pageSize>5000){
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
excelDownList.push({
|
||||
시설코드: item.swtrmtFcltCd,
|
||||
시설명: item.swtrmtFcltNm,
|
||||
주소: item.location,
|
||||
시설용량: item.fctCpc,
|
||||
증설계획기존: item.planSwageQntSumDt4,
|
||||
증설계획현재: item.planSwageQntSum,
|
||||
증설계획1단계: item.planSwageQntSumDc1,
|
||||
증설계획2단계: item.planSwageQntSumDc2,
|
||||
증설계획3단계: item.planSwageQntSumDc3,
|
||||
증설계획4단계: item.planSwageQntSumDc4,
|
||||
처리인구기존: item.swtrmtPpltnCntDt4,
|
||||
처리인구현재: item.swtrmtPpltnCnt,
|
||||
처리인구1단계: item.swtrmtPpltnCntDc1,
|
||||
처리인구2단계: item.swtrmtPpltnCntDc2,
|
||||
처리인구3단계: item.swtrmtPpltnCntDc3,
|
||||
처리인구4단계: item.swtrmtPpltnCntDc4,
|
||||
처리구역기존: item.swtrmtZoneAreaDt4,
|
||||
처리구역현재: item.swtrmtZoneArea,
|
||||
처리구역1단계: item.swtrmtZoneAreaDc1,
|
||||
처리구역2단계: item.swtrmtZoneAreaDc2,
|
||||
처리구역3단계: item.swtrmtZoneAreaDc3,
|
||||
처리구역4단계: item.swtrmtZoneAreaDc4,
|
||||
처리구역: item.trtDstr
|
||||
});
|
||||
});
|
||||
}else{
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
})
|
||||
}
|
||||
set((state:ProcessAreaType) => ({
|
||||
...state,
|
||||
ProcessArea: pageSize<5000?{
|
||||
...state.ProcessArea,
|
||||
processAreaList: res.data,
|
||||
processAreaCount: res.count,
|
||||
}:{
|
||||
...state.ProcessArea,
|
||||
excelList: excelDownList,
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
initModalData: async (swtrmtFcltCd:string) => {
|
||||
set((state: ProcessAreaType) => {
|
||||
const rtnData = state.ProcessArea.processAreaList.find((item: ProcessAreaProps) => item.swtrmtFcltCd === swtrmtFcltCd);
|
||||
if (rtnData) {
|
||||
upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => {
|
||||
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + rtnData.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
|
||||
upHeadListProcessAreaPlan.forEach((head:TableUpperProps) => {
|
||||
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + rtnData.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
|
||||
upHeadListProcessPopulation.forEach((head:TableUpperProps) => {
|
||||
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
|
||||
head.title = '현재\n(' + rtnData.yr + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
|
||||
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
|
||||
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
|
||||
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
|
||||
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
|
||||
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
|
||||
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
|
||||
}
|
||||
});
|
||||
|
||||
// 시설증설 계획 데이터 생성
|
||||
const fcltyImproveInfo: FcltyImproveInfoProps = {
|
||||
planSwageQntSumDt4: rtnData.planSwageQntSumDt4,
|
||||
planSwageQntSum: rtnData.planSwageQntSum,
|
||||
planSwageQntSumDc1: rtnData.planSwageQntSumDc1,
|
||||
planSwageQntSumDc2: rtnData.planSwageQntSumDc2,
|
||||
planSwageQntSumDc3: rtnData.planSwageQntSumDc3,
|
||||
planSwageQntSumDc4: rtnData.planSwageQntSumDc4
|
||||
};
|
||||
|
||||
// 처리인구 계획 데이터 생성
|
||||
const processPopulation: ProcessPopulationProps = {
|
||||
swtrmtPpltnCntDt4: rtnData.swtrmtPpltnCntDt4,
|
||||
swtrmtPpltnCnt: rtnData.swtrmtPpltnCnt,
|
||||
swtrmtPpltnCntDc1: rtnData.swtrmtPpltnCntDc1,
|
||||
swtrmtPpltnCntDc2: rtnData.swtrmtPpltnCntDc2,
|
||||
swtrmtPpltnCntDc3: rtnData.swtrmtPpltnCntDc3,
|
||||
swtrmtPpltnCntDc4: rtnData.swtrmtPpltnCntDc4
|
||||
};
|
||||
|
||||
// 처리구역 계획 데이터 생성
|
||||
const processAreaPlan: ProcessAreaPlanProps = {
|
||||
swtrmtZoneAreaDt4: rtnData.swtrmtZoneAreaDt4,
|
||||
swtrmtZoneArea: rtnData.swtrmtZoneArea,
|
||||
swtrmtZoneAreaDc1: rtnData.swtrmtZoneAreaDc1,
|
||||
swtrmtZoneAreaDc2: rtnData.swtrmtZoneAreaDc2,
|
||||
swtrmtZoneAreaDc3: rtnData.swtrmtZoneAreaDc3,
|
||||
swtrmtZoneAreaDc4: rtnData.swtrmtZoneAreaDc4,
|
||||
trtDstr: rtnData.trtDstr
|
||||
};
|
||||
|
||||
return {
|
||||
...state,
|
||||
ProcessAreaDetail: {
|
||||
...state.ProcessAreaDetail,
|
||||
gridListFcltyImproveInfo: [fcltyImproveInfo],
|
||||
gridListProcessPopulation: [processPopulation],
|
||||
gridListProcessAreaPlan: [processAreaPlan]
|
||||
}
|
||||
};
|
||||
}
|
||||
return state;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,832 @@
|
||||
import { getFetch } from "@/app/components/api";
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
export type { TableUpperProps };
|
||||
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 처리시설 리스트
|
||||
export type facilityListProps = {
|
||||
bscFctCd : string,
|
||||
bscFctNm : string,
|
||||
bscFctClsNm : string,
|
||||
sido : string,
|
||||
gugun : string,
|
||||
daddr : string,
|
||||
fctCpc : number | string | '',
|
||||
plInflWqltBod : number | string | '',
|
||||
dsInflWqltBod : number | string | '',
|
||||
trtFrfNm : string,
|
||||
rnDt : string,
|
||||
cmplDt : string,
|
||||
trstOprEtpNm : string,
|
||||
rvbsn : string,
|
||||
mdmbsn : string,
|
||||
lgbsn : string,
|
||||
rgnNm : string,
|
||||
mnstr : string,
|
||||
efflWtrrgn : string,
|
||||
efflWqltStndrdNm : string
|
||||
}
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설이름: string,
|
||||
주소: string,
|
||||
시설용량: number | '',
|
||||
계획유입수질: number | '',
|
||||
설계유입수질: number | '',
|
||||
공법: string,
|
||||
가동개시일: string,
|
||||
준공일: string,
|
||||
관리대행업자: string,
|
||||
}
|
||||
|
||||
// (2) 처리시설 팝업
|
||||
// 시설 기본정보
|
||||
export type BasicInfoProps = {
|
||||
bscFctNm : string,
|
||||
fctCpc : number | '',
|
||||
sido : string,
|
||||
gugun : string,
|
||||
startDay : string,
|
||||
addr : string,
|
||||
cmplDt : string,
|
||||
trtFrfNm : string,
|
||||
trstOprEtpNm : string,
|
||||
}
|
||||
|
||||
// 시설 계획정보
|
||||
export type PlanInfoProps = {
|
||||
plInflWqltBod? : string,
|
||||
plInflWqltToc? : string,
|
||||
plInflWqltCod? : string,
|
||||
plInflWqltSs? : string,
|
||||
plInflWqltTn? : string,
|
||||
plInflWqltTp? : string,
|
||||
dsInflWqltBod? : string,
|
||||
dsInflWqltToc? : string,
|
||||
dsInflWqltCod? : string,
|
||||
dsInflWqltSs? : string,
|
||||
dsInflWqltTn? : string,
|
||||
dsInflWqltTp? : string,
|
||||
sitArea? : string | number,
|
||||
trtDstrArea? : string | number,
|
||||
swrTrtPopl? : string | number
|
||||
}
|
||||
|
||||
// 시설 계획정보
|
||||
export type LegalWaterQltyProps = {
|
||||
totClfgrpcnt : number,
|
||||
bod : number,
|
||||
cod : number,
|
||||
ss : number,
|
||||
tn : number,
|
||||
tp : number
|
||||
}
|
||||
|
||||
// 시설 수역 및 구역정보
|
||||
export type fcltyAreaInfoProps = {
|
||||
rvbsn : string,
|
||||
efflWtrrgn : string,
|
||||
lgbsn : string,
|
||||
efflWqltStndrdNm : string,
|
||||
rgnNm : string,
|
||||
}
|
||||
|
||||
// 시설 이력관리
|
||||
export type fcltyHistInfoProps = {
|
||||
extnsSeqno : string,
|
||||
extnsNm : string,
|
||||
bzStrtYrMnth : string,
|
||||
bzEdYrMnth : string,
|
||||
eqpPrmsDt : string,
|
||||
cmplDt : string,
|
||||
trlrnCmplDt : string,
|
||||
rnDt : string,
|
||||
sitArea : number,
|
||||
trtDstrArea : number,
|
||||
swrTrtPopl : number
|
||||
}
|
||||
|
||||
// 시설 수질정보
|
||||
export type fcltyWaterQltyInfoProps = {
|
||||
extnsSeqno : string,
|
||||
plInflWqltBod : string,
|
||||
plInflWqltToc : string,
|
||||
plInflWqltCod : string,
|
||||
plInflWqltSs : string,
|
||||
plInflWqltTn : string,
|
||||
plInflWqltTp : string,
|
||||
dsInflWqltBod : string,
|
||||
dsInflWqltToc : string,
|
||||
dsInflWqltCod : string,
|
||||
dsInflWqltSs : string,
|
||||
dsInflWqltTn : string,
|
||||
dsInflWqltTp : string,
|
||||
plEfflWqltBod : string,
|
||||
plEfflWqltToc : string,
|
||||
plEfflWqltCod : string,
|
||||
plEfflWqltSs : string,
|
||||
plEfflWqltTn : string,
|
||||
plEfflWqltTp : string,
|
||||
bod : number,
|
||||
cod : number,
|
||||
ss : number,
|
||||
tn : number,
|
||||
tp : number,
|
||||
totClfgrpcnt : number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const ProcessFacilityLabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '시설상태', '시설구분', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드"},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe",upSequnce:2 },
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:"right"},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:"right"},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
];
|
||||
|
||||
// 처리시설 리스트 (유역)
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드"},
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3},
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
];
|
||||
|
||||
// 처리시설 리스트 (환경청청)
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드"},
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1},
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2},
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3},
|
||||
{ id: "rgnNm", title: "환경청"},
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1 },
|
||||
{ id: "gugun", title: "시군구", upName:"upChangeRe2",upSequnce:2 },
|
||||
{ id: "bscFctNm", title: "시설명"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align: 'right'},
|
||||
{ id: "plInflWqltBod", title: "계획유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "dsInflWqltBod", title: "설계유입수질\n(mg/L)", align:'right'},
|
||||
{ id: "trtFrfNm", title: '공법'},
|
||||
{ id: "rnDt", title: '가동개시일'},
|
||||
{ id: "cmplDt", title: '준공일' },
|
||||
{ id: "trstOprEtpNm", title: '관리대행업자'}
|
||||
];
|
||||
|
||||
const processFacilityList:facilityListProps[] = [
|
||||
]
|
||||
|
||||
/**
|
||||
* 처리시설 상세팝업
|
||||
*/
|
||||
// 시설 기본정보 (헤더)
|
||||
const upHeadListBasicInfo:TableUpperProps[] = [
|
||||
{ id: "bscFctNm", title: "시설명" },
|
||||
{ id: "fctCpc", title: "시설용량n(m³/일)", align: 'right'},
|
||||
{ id: "sido", title: "시도"},
|
||||
{ id: "gugun", title: "시군구"},
|
||||
{ id: "rnDt", title: "가동개시일"},
|
||||
{ id: "daddr", title: "주소"},
|
||||
{ id: "cmplDt", title: "준공일"},
|
||||
{ id: "trtFrfNm", title: "공법"},
|
||||
{ id: "trstOprEtpNm", title: "관리대행업자"},
|
||||
];
|
||||
|
||||
// 시설 기본정보 (리스트)
|
||||
const gridListBasicInfo:BasicInfoProps[] = [
|
||||
{
|
||||
bscFctNm : "난지",
|
||||
fctCpc : 860000,
|
||||
sido : "서울특별시",
|
||||
gugun : "",
|
||||
startDay : "1987-06-30",
|
||||
addr : "경기도 고양시 덕양구 대덕로 426 (현천동)",
|
||||
cmplDt : "2013-04-30",
|
||||
trtFrfNm : "MLE, A2O",
|
||||
trstOprEtpNm : "자체",
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 법적방류수질 (헤더)
|
||||
const upHeadListLegalWaterQlty:TableUpperProps[] = [
|
||||
{ id: "bod", title: "BOD(mg/L)", align: 'right'},
|
||||
{ id: "cod", title: "TOC(COD)(mg/L)", align: 'right'},
|
||||
{ id: "ss", title: "SS(mg/L)", align: 'right'},
|
||||
{ id: "tn", title: "T-N(mg/L)", align: 'right'},
|
||||
{ id: "tp", title: "T-P(mg/L) ", align: 'right'},
|
||||
{ id: "totClfgrpcnt", title: "대장균군(개/100ml)"},
|
||||
]
|
||||
|
||||
// 시설 법적방류수질 (리스트)
|
||||
let gridListLegalWaterQlty:LegalWaterQltyProps[] = [
|
||||
]
|
||||
|
||||
// 시설 계획정보 (헤더)
|
||||
const upHeadListPlanInfo:TableUpperProps[] = [
|
||||
{ id: "plInflWqltBod", title: "BOD", upName:"upChangeRe1", upSequnce:1, align: 'right' },
|
||||
{ id: "plInflWqltToc", title: "TOC", upName:"upChangeRe1", upSequnce:2, align: 'right' },
|
||||
{ id: "plInflWqltCod", title: "COD", upName:"upChangeRe1", upSequnce:3, align: 'right' },
|
||||
{ id: "plInflWqltSs", title: "SS", upName:"upChangeRe1", upSequnce:4, align: 'right' },
|
||||
{ id: "plInflWqltTn", title: "T-N", upName:"upChangeRe1", upSequnce:5, align: 'right' },
|
||||
{ id: "plInflWqltTp", title: "T-P", upName:"upChangeRe1", upSequnce:6, align: 'right' },
|
||||
{ id: "dsInflWqltBod", title: "BOD", upName:"upChangeRe2", upSequnce:1, align: 'right' },
|
||||
{ id: "dsInflWqltToc", title: "TOC", upName:"upChangeRe2", upSequnce:2, align: 'right' },
|
||||
{ id: "dsInflWqltCod", title: "COD", upName:"upChangeRe2", upSequnce:3, align: 'right' },
|
||||
{ id: "dsInflWqltSs", title: "SS", upName:"upChangeRe2", upSequnce:4, align: 'right' },
|
||||
{ id: "dsInflWqltTn", title: "T-N", upName:"upChangeRe2", upSequnce:5, align: 'right' },
|
||||
{ id: "dsInflWqltTp", title: "T-P", upName:"upChangeRe2", upSequnce:6, align: 'right' },
|
||||
{ id: "sitArea", title: "부지면적\n(m²)", align: 'right'},
|
||||
{ id: "trtDstrArea", title: "처리구역면적\n(ha)", align: 'right'},
|
||||
{ id: "swrTrtPopl", title: "하수처리인구\n(인)", align: 'right'},
|
||||
];
|
||||
|
||||
// 시설 계획정보 (리스트)
|
||||
const gridListPlanInfo:PlanInfoProps[] = [
|
||||
{
|
||||
plInflWqltBod : "179.0",
|
||||
plInflWqltToc : "90.0",
|
||||
plInflWqltCod : "0.0",
|
||||
plInflWqltSs : "132.0",
|
||||
plInflWqltTn : "38.000",
|
||||
plInflWqltTp : "4.300",
|
||||
dsInflWqltBod : "178.0",
|
||||
dsInflWqltToc : "91.0",
|
||||
dsInflWqltCod : "0.0",
|
||||
dsInflWqltSs : "131.0",
|
||||
dsInflWqltTn : "40.200",
|
||||
dsInflWqltTp : "4.500",
|
||||
sitArea : "928,574",
|
||||
trtDstrArea : "7,994.0",
|
||||
swrTrtPopl : "1,573,277",
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 수역 및 구역정보 (헤더)
|
||||
const upHeadListFcltyAreaInfo:TableUpperProps[] = [
|
||||
{ id: "rvbsn", title: "하천명" },
|
||||
{ id: "efflWtrrgn", title: "방류수역"},
|
||||
{ id: "lgbsn", title: "단위유역"},
|
||||
{ id: "efflWqltStndrdNm", title: "지역구분"},
|
||||
{ id: "rgnNm", title: "관할 유역(지방) 환경청"}
|
||||
];
|
||||
|
||||
// 시설 수역 및 구역정보 (리스트)
|
||||
const gridListFcltyAreaInfo:fcltyAreaInfoProps[] = [
|
||||
{
|
||||
rvbsn : "한강",
|
||||
efflWtrrgn : "한강수계",
|
||||
lgbsn : "한강본류",
|
||||
efflWqltStndrdNm : "500톤 이상\n(Ⅲ지역)",
|
||||
rgnNm : "한강유역환경청"
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 이력관리 (헤더)
|
||||
const upHeadListFcltyHistInfo:TableUpperProps[] = [
|
||||
{ id: "extnsSeqno", title: "차수", align: 'center' },
|
||||
{ id: "extnsNm", title: "구분"},
|
||||
{ id: "bzStrtYrMnth", title: "사업기간", upName:"upChangeRe1", upSequnce:1},
|
||||
{ id: "bzEdYrMnth", title: "사업기간", upName:"upChangeRe1", upSequnce:2},
|
||||
{ id: "eqpPrmsDt", title: "설치인가일"},
|
||||
{ id: "cmplDt", title: "준공일"},
|
||||
{ id: "trlrnCmplDt", title: "시운전완료일"},
|
||||
{ id: "rnDt", title: "가동개시일"},
|
||||
];
|
||||
|
||||
// 시설 이력관리 (리스트)
|
||||
const gridListFcltyHistInfo:fcltyHistInfoProps[] = [
|
||||
{
|
||||
extnsSeqno : "최초",
|
||||
extnsNm : "최초",
|
||||
bzStrtYrMnth : "1984.12.01",
|
||||
bzEdYrMnth : "1987.06.01",
|
||||
eqpPrmsDt : "1985.09.13",
|
||||
cmplDt : "1987.06.30",
|
||||
trlrnCmplDt : "1987.06.30",
|
||||
rnDt : "1987.06.30",
|
||||
sitArea : 0,
|
||||
trtDstrArea : 0,
|
||||
swrTrtPopl : 0,
|
||||
}
|
||||
];
|
||||
|
||||
// 시설 수질정보 (헤더)
|
||||
const upHeadListFcltyWaterQltyInfo:TableUpperProps[] = [
|
||||
{ id: "extnsSeqno", title: "차수" },
|
||||
{ id: "plInflWqltBod", title: "BOD", upName:"upChangeRe1", upSequnce:1, align: 'right' },
|
||||
{ id: "plInflWqltToc", title: "TOC", upName:"upChangeRe1", upSequnce:2, align: 'right' },
|
||||
{ id: "plInflWqltCod", title: "COD", upName:"upChangeRe1", upSequnce:3, align: 'right' },
|
||||
{ id: "plInflWqltSs", title: "SS", upName:"upChangeRe1", upSequnce:4, align: 'right' },
|
||||
{ id: "plInflWqltTn", title: "T-N", upName:"upChangeRe1", upSequnce:5, align: 'right' },
|
||||
{ id: "plInflWqltTp", title: "T-P", upName:"upChangeRe1", upSequnce:6, align: 'right' },
|
||||
{ id: "dsInflWqltBod", title: "BOD", upName:"upChangeRe2", upSequnce:1, align: 'right' },
|
||||
{ id: "dsInflWqltToc", title: "TOC", upName:"upChangeRe2", upSequnce:2, align: 'right' },
|
||||
{ id: "dsInflWqltCod", title: "COD", upName:"upChangeRe2", upSequnce:3, align: 'right' },
|
||||
{ id: "dsInflWqltSs", title: "SS", upName:"upChangeRe2", upSequnce:4, align: 'right' },
|
||||
{ id: "dsInflWqltTn", title: "T-N", upName:"upChangeRe2", upSequnce:5, align: 'right' },
|
||||
{ id: "dsInflWqltTp", title: "T-P", upName:"upChangeRe2", upSequnce:6, align: 'right' },
|
||||
{ id: "plEfflWqltBod", title: "BOD", upName:"upChangeRe3", upSequnce:1, align: 'right' },
|
||||
{ id: "plEfflWqltToc", title: "TOC", upName:"upChangeRe3", upSequnce:2, align: 'right' },
|
||||
{ id: "plEfflWqltCod", title: "COD", upName:"upChangeRe3", upSequnce:3, align: 'right' },
|
||||
{ id: "plEfflWqltSs", title: "SS", upName:"upChangeRe3", upSequnce:4, align: 'right' },
|
||||
{ id: "plEfflWqltTn", title: "T-N", upName:"upChangeRe3", upSequnce:5, align: 'right' },
|
||||
{ id: "plEfflWqltTp", title: "T-P", upName:"upChangeRe3", upSequnce:6, align: 'right' },
|
||||
];
|
||||
|
||||
// 시설 수질정보 (리스트)
|
||||
const gridListFcltyWaterQltyInfo:fcltyWaterQltyInfoProps[] = [
|
||||
{
|
||||
extnsSeqno: "최초",
|
||||
plInflWqltBod: "111.0",
|
||||
plInflWqltToc: "(0.0)",
|
||||
plInflWqltCod: "(0.0)",
|
||||
plInflWqltSs: "122.0",
|
||||
plInflWqltTn: "0.000",
|
||||
plInflWqltTp: "0.000",
|
||||
dsInflWqltBod: "111.0",
|
||||
dsInflWqltToc: "(0.0)",
|
||||
dsInflWqltCod: "(0.0)",
|
||||
dsInflWqltSs: "122.0",
|
||||
dsInflWqltTn: "0.000",
|
||||
dsInflWqltTp: "0.000",
|
||||
plEfflWqltBod: "20.0",
|
||||
plEfflWqltCod: "(0.0)",
|
||||
plEfflWqltToc: "(0.0)",
|
||||
plEfflWqltSs: "12.0",
|
||||
plEfflWqltTn: "0.000",
|
||||
plEfflWqltTp: "0.000",
|
||||
bod: 0,
|
||||
cod: 0,
|
||||
ss: 0,
|
||||
tn: 0,
|
||||
tp: 0,
|
||||
totClfgrpcnt: 0
|
||||
}
|
||||
];
|
||||
|
||||
/**====================================
|
||||
* Store - api (데이터 호출)
|
||||
====================================*/
|
||||
|
||||
// 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
const fetchFacilityList = async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string ): Promise<{data:facilityListProps[], count:number}> => {
|
||||
try {
|
||||
const tailStr = partValue ? '/'+ (partValue==='G' ? 'A' : partValue) + '/' + nameCd + '/' + fcltCpct + '/' + oprtngSttsCd + '/' + facilityPartValue + (facilityName && facilityName !== '' ? '/' + facilityName : '') : '';
|
||||
const url = '/prcsFclt/info/history/'+pageNo+'/'+pageSize+tailStr;
|
||||
//const res = await getFetch('fo', '/prcsFclt/info/'+pageNo+'/'+pageSize+tailUrl);
|
||||
const res = await getFetch('fo', url);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 리스트 데이터 호출 (대시보드용)
|
||||
const fetchFacilityListSearching = async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string ): Promise<{data:facilityListProps[], count:number}> => {
|
||||
try {
|
||||
const tailStr = partValue ? '/'+ (partValue==='G' ? 'A' : partValue) + '/' + nameCd + '/' + fcltCpct + '/' + oprtngSttsCd + '/' + facilityPartValue + (facilityName && facilityName !== '' ? '/' + facilityName : '') : '';
|
||||
const url = '/prcsFclt/searching/'+pageNo+'/'+pageSize+tailStr;
|
||||
//const res = await getFetch('fo', '/prcsFclt/info/'+pageNo+'/'+pageSize+tailUrl);
|
||||
const res = await getFetch('fo', url);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.error('시설정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return {data: [], count: 0};
|
||||
}
|
||||
};
|
||||
|
||||
// 모달
|
||||
// 시설정보 이력정보 데이터 호출
|
||||
const fetchFacilityHistInfo = async (facilityCd:string ): Promise<fcltyHistInfoProps[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/prcsFclt/hist/'+facilityCd);
|
||||
const data = res.data;
|
||||
DataForm({ type: 'date', column: 'trlrnCmplDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'date', column: 'eqpPrmsDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'date', column: 'cmplDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'date', column: 'rnDt', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'number', column: 'sitArea', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'number', column: 'trtDstrArea', item: data as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'number', column: 'swrTrtPopl', item: data as unknown as Record<string, unknown> });
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('시설정보 이력정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// 시설정보 수질정보 데이터 호출
|
||||
const fetchFacilityWaterQltyInfo = async (facilityCd:string ): Promise<fcltyWaterQltyInfoProps[]> => {
|
||||
try {
|
||||
const res = await getFetch('fo', '/prcsFclt/info/history/'+facilityCd);
|
||||
const data = res.data;
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('시설정보 수질정보 데이터를 가져오는데 실패했습니다:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type ProcessFacilityActions = {
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
* @param partValue : 구분값(행정명, 대유역, 환경청)
|
||||
* @param nameCd : 행정코드(시도명, 시군구명, 단위유역)
|
||||
* @param fcltCpct : 시설용량
|
||||
* @param oprtngSttsCd : 운영 상태 코드
|
||||
* @param facilityName : 시설명
|
||||
*/
|
||||
searchProcessFacility : (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => void;
|
||||
|
||||
/**
|
||||
* 시설정보 이력정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityHist : (facilityCd:string) => void;
|
||||
|
||||
/**
|
||||
* 시설정보 수질정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityWaterQlty : (facilityCd:string) => void;
|
||||
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출 (대시보드용)
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessFacilitySearching : (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => void;
|
||||
}
|
||||
|
||||
export type ProcessFacilityType = {
|
||||
ProcessFacility: {
|
||||
isInit: boolean;
|
||||
processFacilityLabelArray:string[];
|
||||
},
|
||||
|
||||
ProcessFacilityList : {
|
||||
isInit: boolean;
|
||||
upHeadList1:TableUpperProps[];
|
||||
upHeadList2:TableUpperProps[];
|
||||
upHeadList3:TableUpperProps[];
|
||||
processFacilityList:facilityListProps[];
|
||||
processFacilityCount:number;
|
||||
excelList : ExcelType[];
|
||||
},
|
||||
|
||||
ProcessFacilityDetail : {
|
||||
isInit : boolean;
|
||||
upHeadListBasicInfo : TableUpperProps[];
|
||||
gridListBasicInfo : BasicInfoProps[];
|
||||
upHeadListPlanInfo : TableUpperProps[];
|
||||
gridListPlanInfo : PlanInfoProps[];
|
||||
upHeadListFcltyAreaInfo : TableUpperProps[];
|
||||
gridListFcltyAreaInfo : fcltyAreaInfoProps[];
|
||||
|
||||
upHeadListFcltyHistInfo : TableUpperProps[];
|
||||
gridListFcltyHistInfo : fcltyHistInfoProps[];
|
||||
upHeadListFcltyWaterQltyInfo : TableUpperProps[];
|
||||
gridListFcltyWaterQltyInfo : fcltyWaterQltyInfoProps[];
|
||||
|
||||
upHeadListLegalWaterQlty : TableUpperProps[];
|
||||
gridListLegalWaterQlty : LegalWaterQltyProps[];
|
||||
},
|
||||
}
|
||||
|
||||
export const processFacilityInitState:ProcessFacilityType = {
|
||||
ProcessFacility: {
|
||||
isInit: false,
|
||||
processFacilityLabelArray: ProcessFacilityLabelArray,
|
||||
},
|
||||
|
||||
ProcessFacilityList : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
processFacilityList : processFacilityList,
|
||||
processFacilityCount:1,
|
||||
excelList : []
|
||||
},
|
||||
|
||||
ProcessFacilityDetail : {
|
||||
isInit : false,
|
||||
upHeadListBasicInfo : upHeadListBasicInfo,
|
||||
gridListBasicInfo : gridListBasicInfo,
|
||||
upHeadListPlanInfo : upHeadListPlanInfo,
|
||||
gridListPlanInfo : gridListPlanInfo,
|
||||
upHeadListFcltyAreaInfo : upHeadListFcltyAreaInfo,
|
||||
gridListFcltyAreaInfo : gridListFcltyAreaInfo,
|
||||
|
||||
upHeadListFcltyHistInfo : upHeadListFcltyHistInfo,
|
||||
gridListFcltyHistInfo : gridListFcltyHistInfo,
|
||||
upHeadListFcltyWaterQltyInfo : upHeadListFcltyWaterQltyInfo,
|
||||
gridListFcltyWaterQltyInfo : gridListFcltyWaterQltyInfo,
|
||||
|
||||
upHeadListLegalWaterQlty : upHeadListLegalWaterQlty,
|
||||
gridListLegalWaterQlty : gridListLegalWaterQlty,
|
||||
}
|
||||
}
|
||||
|
||||
// 상태 설정 함수 타입 정의
|
||||
type SetStateFunction = (state: ProcessFacilityType | ((state: ProcessFacilityType) => ProcessFacilityType)) => void;
|
||||
|
||||
export type ProcessFacilityStore = ProcessFacilityType & ProcessFacilityActions;
|
||||
|
||||
export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActions=(set: SetStateFunction) => {
|
||||
return{
|
||||
// 메인페이지
|
||||
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessFacility: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => {
|
||||
const res = await fetchFacilityList(pageNo, pageSize, partValue, nameCd, fcltCpct, oprtngSttsCd, facilityPartValue, facilityName);
|
||||
res.data.forEach((item:facilityListProps) => {
|
||||
DataForm({ type: 'date', column: 'cmplDt', item:item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'date', column: 'rnDt', item:item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
|
||||
})
|
||||
|
||||
res.data.forEach(item => {
|
||||
item.plInflWqltBod = item.plInflWqltBod ? Number(item.plInflWqltBod).toFixed(1) : '';
|
||||
item.dsInflWqltBod = item.dsInflWqltBod ? Number(item.dsInflWqltBod).toFixed(1) : '';
|
||||
})
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
if(pageSize>5000){
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sido,
|
||||
시군구: item.gugun,
|
||||
시설이름: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc ? Number(item.fctCpc) : '',
|
||||
계획유입수질: item.plInflWqltBod ? Number(item.plInflWqltBod) : '',
|
||||
설계유입수질: item.dsInflWqltBod ? Number(item.dsInflWqltBod) : '',
|
||||
공법: item.trtFrfNm,
|
||||
가동개시일: item.rnDt,
|
||||
준공일: item.cmplDt,
|
||||
관리대행업자: item.mnstr,
|
||||
})
|
||||
})
|
||||
}else{
|
||||
res.data.forEach(item => {
|
||||
item.fctCpc = item.fctCpc ? parseFloat(item.fctCpc.toString().replace(/,/g, '')) : '';
|
||||
})
|
||||
}
|
||||
set((state:ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityList: pageSize<5000?{
|
||||
...state.ProcessFacilityList,
|
||||
processFacilityList: res.data,
|
||||
processFacilityCount: res.count,
|
||||
}:{
|
||||
...state.ProcessFacilityList,
|
||||
excelList: excelDownList,
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* 시설정보 리스트 데이터 호출
|
||||
* @param pageNo : 페이지 번호
|
||||
* @param pageSize : 페이지 크기
|
||||
*/
|
||||
searchProcessFacilitySearching: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => {
|
||||
const res = await fetchFacilityListSearching(pageNo, pageSize, partValue, nameCd, fcltCpct, oprtngSttsCd, facilityPartValue, facilityName);
|
||||
/* res.data.forEach((item:facilityListProps) => {
|
||||
DataForm({ type: 'date', column: 'cmplDt', item:item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'date', column: 'rnDt', item:item as unknown as Record<string, unknown>});
|
||||
})
|
||||
|
||||
res.data.forEach(item => {
|
||||
item.plInflWqltBod = item.plInflWqltBod ? Number(item.plInflWqltBod).toFixed(1) : '';
|
||||
item.dsInflWqltBod = item.dsInflWqltBod ? Number(item.dsInflWqltBod).toFixed(1) : '';
|
||||
}) */
|
||||
console.log(res.data);
|
||||
set((state:ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityList: {
|
||||
...state.ProcessFacilityList,
|
||||
processFacilityList: res.data,
|
||||
processFacilityCount: res.count,
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
|
||||
// 모달 이력정보
|
||||
/**
|
||||
* 시설정보 이력정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityHist: async (facilityCd:string) => {
|
||||
const promiseSet = await Promise.all([fetchFacilityHistInfo(facilityCd)]);
|
||||
const [facilityHistInfo] = promiseSet;
|
||||
// extnsSeqno를 기준으로 오름차순 정렬
|
||||
const sortedHistInfo = [...facilityHistInfo].sort((a, b) => {
|
||||
// 숫자로 변환하여 비교
|
||||
const numA = Number(a.extnsSeqno);
|
||||
const numB = Number(b.extnsSeqno);
|
||||
if (!isNaN(numA) && !isNaN(numB)) {
|
||||
return numA - numB;
|
||||
}
|
||||
// 숫자 변환이 실패하면 문자열로 비교
|
||||
return String(a.extnsSeqno).localeCompare(String(b.extnsSeqno));
|
||||
});
|
||||
|
||||
sortedHistInfo.forEach(item => {
|
||||
if(item.extnsSeqno == '0'){
|
||||
item.extnsSeqno = '최초';
|
||||
item.extnsNm = '신설';
|
||||
}
|
||||
});
|
||||
|
||||
// yyyy-MM-dd로 변환
|
||||
sortedHistInfo.forEach(item => {
|
||||
item.eqpPrmsDt = item.eqpPrmsDt ? item.eqpPrmsDt.substring(0,4) + '-' + item.eqpPrmsDt.substring(4,6) + '-' + item.eqpPrmsDt.substring(6,8) : '';
|
||||
item.trlrnCmplDt = item.trlrnCmplDt ? item.trlrnCmplDt.substring(0,4) + '-' + item.trlrnCmplDt.substring(4,6) + '-' + item.trlrnCmplDt.substring(6,8) : '';
|
||||
item.cmplDt = item.cmplDt ? item.cmplDt.substring(0,4) + '-' + item.cmplDt.substring(4,6) + '-' + item.cmplDt.substring(6,8) : '';
|
||||
item.rnDt = item.rnDt ? item.rnDt.substring(0,4) + '-' + item.rnDt.substring(4,6) + '-' + item.rnDt.substring(6,8) : '';
|
||||
});
|
||||
|
||||
// 마지막 이력 데이터의 값을 gridListPlanInfo에 업데이트
|
||||
if (sortedHistInfo.length > 0) {
|
||||
const lastHistInfo = sortedHistInfo[sortedHistInfo.length - 1];
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyHistInfo: sortedHistInfo,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
swrTrtPopl: lastHistInfo?.swrTrtPopl ?? state.ProcessFacilityDetail.gridListPlanInfo[0]?.swrTrtPopl,
|
||||
trtDstrArea: lastHistInfo?.trtDstrArea ?? state.ProcessFacilityDetail.gridListPlanInfo[0]?.trtDstrArea,
|
||||
sitArea: lastHistInfo?.sitArea ?? state.ProcessFacilityDetail.gridListPlanInfo[0]?.sitArea
|
||||
}]
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyHistInfo: sortedHistInfo,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
swrTrtPopl: '',
|
||||
trtDstrArea: '',
|
||||
sitArea: ''
|
||||
}]
|
||||
}
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
// 모달 수질정보
|
||||
/**
|
||||
* 시설정보 수질정보 데이터 호출
|
||||
* @param facilityCd : 시설코드
|
||||
*/
|
||||
searchProcessFacilityWaterQlty: async (facilityCd:string) => {
|
||||
const promiseSet = await Promise.all([fetchFacilityWaterQltyInfo(facilityCd)]);
|
||||
const [facilityWaterQltyInfo] = promiseSet;
|
||||
// extnsSeqno를 기준으로 오름차순 정렬
|
||||
const sortedWaterQltyInfo = [...facilityWaterQltyInfo].sort((a, b) => {
|
||||
// 숫자로 변환하여 비교
|
||||
const numA = Number(a.extnsSeqno);
|
||||
const numB = Number(b.extnsSeqno);
|
||||
if (!isNaN(numA) && !isNaN(numB)) {
|
||||
return numA - numB;
|
||||
}
|
||||
// 숫자 변환이 실패하면 문자열로 비교
|
||||
return String(a.extnsSeqno).localeCompare(String(b.extnsSeqno));
|
||||
});
|
||||
|
||||
sortedWaterQltyInfo.forEach(item => {
|
||||
if(item.extnsSeqno == '0'){
|
||||
item.extnsSeqno = '최초';
|
||||
}
|
||||
});
|
||||
|
||||
// 법적수질정보 초기화 및 push
|
||||
gridListLegalWaterQlty = [];
|
||||
|
||||
gridListLegalWaterQlty.push({
|
||||
bod: facilityWaterQltyInfo[0]?.bod ?? 0,
|
||||
cod: Number(facilityWaterQltyInfo[0]?.cod ?? 0),
|
||||
ss: Number(facilityWaterQltyInfo[0]?.ss ?? 0),
|
||||
tn: Number(facilityWaterQltyInfo[0]?.tn ?? 0),
|
||||
tp: Number(facilityWaterQltyInfo[0]?.tp ?? 0),
|
||||
totClfgrpcnt : Number(facilityWaterQltyInfo[0]?.totClfgrpcnt ?? 0),
|
||||
});
|
||||
|
||||
// 마지막 수질 데이터의 값을 gridListPlanInfo에 업데이트
|
||||
if (sortedWaterQltyInfo.length > 0) {
|
||||
const lastWaterQltyInfo = sortedWaterQltyInfo[sortedWaterQltyInfo.length - 1];
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyWaterQltyInfo: sortedWaterQltyInfo,
|
||||
gridListLegalWaterQlty: gridListLegalWaterQlty,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
dsInflWqltBod: lastWaterQltyInfo?.dsInflWqltBod === 'NULL' || lastWaterQltyInfo?.dsInflWqltBod === undefined ? '' : lastWaterQltyInfo.dsInflWqltBod,
|
||||
dsInflWqltToc: lastWaterQltyInfo?.dsInflWqltToc === 'NULL' || lastWaterQltyInfo?.dsInflWqltToc === undefined ? '' : lastWaterQltyInfo.dsInflWqltToc,
|
||||
dsInflWqltCod: lastWaterQltyInfo?.dsInflWqltCod === 'NULL' || lastWaterQltyInfo?.dsInflWqltCod === undefined ? '' : lastWaterQltyInfo.dsInflWqltCod,
|
||||
dsInflWqltSs: lastWaterQltyInfo?.dsInflWqltSs === 'NULL' || lastWaterQltyInfo?.dsInflWqltSs === undefined ? '' : lastWaterQltyInfo.dsInflWqltSs,
|
||||
dsInflWqltTn: lastWaterQltyInfo?.dsInflWqltTn === 'NULL' || lastWaterQltyInfo?.dsInflWqltTn === undefined ? '' : lastWaterQltyInfo.dsInflWqltTn,
|
||||
dsInflWqltTp: lastWaterQltyInfo?.dsInflWqltTp === 'NULL' || lastWaterQltyInfo?.dsInflWqltTp === undefined ? '' : lastWaterQltyInfo.dsInflWqltTp,
|
||||
plInflWqltBod: lastWaterQltyInfo?.plInflWqltBod === 'NULL' || lastWaterQltyInfo?.plInflWqltBod === undefined ? '' : lastWaterQltyInfo.plInflWqltBod,
|
||||
plInflWqltToc: lastWaterQltyInfo?.plInflWqltToc === 'NULL' || lastWaterQltyInfo?.plInflWqltToc === undefined ? '' : lastWaterQltyInfo.plInflWqltToc,
|
||||
plInflWqltCod: lastWaterQltyInfo?.plInflWqltCod === 'NULL' || lastWaterQltyInfo?.plInflWqltCod === undefined ? '' : lastWaterQltyInfo.plInflWqltCod,
|
||||
plInflWqltSs: lastWaterQltyInfo?.plInflWqltSs === 'NULL' || lastWaterQltyInfo?.plInflWqltSs === undefined ? '' : lastWaterQltyInfo.plInflWqltSs,
|
||||
plInflWqltTn: lastWaterQltyInfo?.plInflWqltTn === 'NULL' || lastWaterQltyInfo?.plInflWqltTn === undefined ? '' : lastWaterQltyInfo.plInflWqltTn,
|
||||
plInflWqltTp: lastWaterQltyInfo?.plInflWqltTp === 'NULL' || lastWaterQltyInfo?.plInflWqltTp === undefined ? '' : lastWaterQltyInfo.plInflWqltTp
|
||||
}]
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
set((state: ProcessFacilityType) => ({
|
||||
...state,
|
||||
ProcessFacilityDetail: {
|
||||
...state.ProcessFacilityDetail,
|
||||
gridListFcltyWaterQltyInfo: sortedWaterQltyInfo,
|
||||
gridListLegalWaterQlty: gridListLegalWaterQlty,
|
||||
gridListPlanInfo: [{
|
||||
...state.ProcessFacilityDetail.gridListPlanInfo[0],
|
||||
dsInflWqltBod: '',
|
||||
dsInflWqltToc: '',
|
||||
dsInflWqltCod: '',
|
||||
dsInflWqltSs: '',
|
||||
dsInflWqltTn: '',
|
||||
dsInflWqltTp: '',
|
||||
plEfflWqltBod: '',
|
||||
plEfflWqltToc: '',
|
||||
plEfflWqltCod: '',
|
||||
plEfflWqltSs: '',
|
||||
plEfflWqltTn: '',
|
||||
plEfflWqltTp: ''
|
||||
}]
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
export type TableUpperProps = {
|
||||
id: string;
|
||||
title: string;
|
||||
upName?: string;
|
||||
upSequnce?: number;
|
||||
}
|
||||
type PublicReuseFacility = {
|
||||
sido: string,
|
||||
sigungo: string,
|
||||
facilityName: string,
|
||||
location: string,
|
||||
locationgubun: string,
|
||||
facilityCapacity: string,
|
||||
yn?: string,
|
||||
authoDay?: string,
|
||||
area?: string,
|
||||
reuse?: string,
|
||||
register?: string
|
||||
}
|
||||
const upHeadList:TableUpperProps[] = [
|
||||
{ id: "sido", title: "시도"},
|
||||
{ id: "sigungo", title: "시군구"},
|
||||
{ id: "facilityName", title: "시설명"},
|
||||
{ id: "location", title: "위치"},
|
||||
{ id: "locationgubun", title: "지역구분"},
|
||||
{ id: "facilityCapacity", title: "시설용량"},
|
||||
{ id: "yn", title: '여부', upName:'upChangeRe' , upSequnce:1 },
|
||||
{ id: "authoDay", title: '허가일',upName:'upChangeRe', upSequnce:2 },
|
||||
{ id: "area", title: '면적' ,upName:'upChangeRe',upSequnce:3 }];
|
||||
|
||||
const publicReuseFacilityUper:PublicReuseFacility[] = [
|
||||
{
|
||||
sido: "서울",
|
||||
sigungo: "강남구",
|
||||
facilityName: "난지",
|
||||
location: "경기도 고양시 덕양구 대차로 4가",
|
||||
locationgubun: "500",
|
||||
facilityCapacity: "800,000",
|
||||
reuse: "Y",
|
||||
register: "Y"
|
||||
},
|
||||
{
|
||||
sido: "서울",
|
||||
sigungo: "강남구",
|
||||
facilityName: "난지",
|
||||
location: "경기도 고양시 덕양구 대차로 4가",
|
||||
locationgubun: "500",
|
||||
facilityCapacity: "800,000",
|
||||
reuse: "Y",
|
||||
register: "Y"
|
||||
},
|
||||
{
|
||||
sido: "서울",
|
||||
sigungo: "강남구",
|
||||
facilityName: "난지",
|
||||
location: "경기도 고양시 덕양구 대차로 4가",
|
||||
locationgubun: "500",
|
||||
facilityCapacity: "800,000",
|
||||
yn: "Y",
|
||||
authoDay: "2012",
|
||||
area:"123"
|
||||
},
|
||||
]
|
||||
|
||||
export type tableState = {
|
||||
isInit: boolean;
|
||||
upHeadList: TableUpperProps[];
|
||||
publicReuseFacilityUper: PublicReuseFacility[];
|
||||
}
|
||||
type tableActions = {
|
||||
decrementList: () => void
|
||||
}
|
||||
|
||||
export type tableType = tableState & tableActions;
|
||||
|
||||
export const tableStateExport:tableState= {
|
||||
isInit:false,
|
||||
upHeadList: upHeadList,
|
||||
publicReuseFacilityUper: publicReuseFacilityUper,
|
||||
}
|
||||
|
||||
// 상태 설정 함수 타입 정의
|
||||
type SetStateFunction = (state: tableState | ((state: tableState) => tableState)) => void;
|
||||
|
||||
export const tableActionsExport:(set:SetStateFunction)=>tableActions=(set: SetStateFunction) => {
|
||||
|
||||
return {
|
||||
decrementList:()=>set(
|
||||
(state:tableState) => {
|
||||
return {
|
||||
...state,
|
||||
publicReuseFacilityUper:
|
||||
state.publicReuseFacilityUper.slice(0, state.publicReuseFacilityUper.length - 1)
|
||||
}}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
export type RdiProps = {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
sigungo : string,
|
||||
bscFctNm : string,
|
||||
lclgvrnmntNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
summerMinBodValue : number,
|
||||
inflAmnt : number,
|
||||
winterAvgBodLowRainfall : number,
|
||||
rdiiValue : number,
|
||||
infoRnDay : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
}
|
||||
|
||||
export interface RdiInterface {
|
||||
bscFctCd : string,
|
||||
sido : string,
|
||||
sigungo : string,
|
||||
bscFctNm : string,
|
||||
lclgvrnmntNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
summerMinBodValue : number,
|
||||
inflAmnt : number,
|
||||
winterAvgBodLowRainfall : number,
|
||||
rdiiValue : number,
|
||||
infoRnDay : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
}
|
||||
|
||||
// 모달
|
||||
export interface RdiInputModalProps {
|
||||
msrDt : string,
|
||||
realSewageInput : number | '',
|
||||
sewageOccur : number | '',
|
||||
underWaterInput : number | '',
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
하절기강우일최저유입BOD: number | '',
|
||||
하절기최저유입BOD유입유량: number | '',
|
||||
동절기청천시유입BOD: number | '',
|
||||
RDII추정 : number | '',
|
||||
RDII추정시일강수량 : number | '',
|
||||
}
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "3mm 이상 강우일 중 최저 유입BOD\n(mg/L)", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량\n(m³/일)", row:1 },
|
||||
{ id: "C", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량\n(mm)", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1 },
|
||||
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sido", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "sigungo", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 },
|
||||
{ id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 },
|
||||
{ id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1 },
|
||||
{ id: "D", title: "동절기 운영현황(1~2월)", row:0 },
|
||||
{ id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1 },
|
||||
{ id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2 },
|
||||
{ id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const rdiList:RdiProps[] = [
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - API
|
||||
====================================*/
|
||||
|
||||
const fetchRdiList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
try{
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/rdii/list/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
console.log(url);
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
}catch(error){
|
||||
console.log(error);
|
||||
return { data: rdiList, count: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type RdiActions = {
|
||||
searchRdiList: (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
export type RdiType = {
|
||||
RdiSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
Rdi : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
rdiList: RdiProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
rdiCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
}
|
||||
|
||||
export const rdiInitState: RdiType = {
|
||||
RdiSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
Rdi : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
rdiList : rdiList,
|
||||
rdiCount : 2,
|
||||
excelList : []
|
||||
}
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : RdiProps)=> {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'summerMinBodValue', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float1', column: 'winterAvgBodLowRainfall', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'rdiiValue', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'infoRnDay', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
// Add type definitions for state setter function
|
||||
type SetStateFunction = (state: RdiType | ((state: RdiType) => RdiType)) => void;
|
||||
|
||||
export type RdiStore = RdiType & RdiActions;
|
||||
|
||||
export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunction) => {
|
||||
console.log("tableActionsExport");
|
||||
return {
|
||||
searchRdiList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchRdiList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const excelDownList: ExcelType[] = [];
|
||||
|
||||
const rtnData = data.map((item: RdiProps) => {
|
||||
return {
|
||||
...item,
|
||||
sido: item.lclgvrnmntNm.split(' ')[0]?.toString() || '',
|
||||
sigungo: item.lclgvrnmntNm.split(' ')[1]?.toString() || '',
|
||||
inflAmnt: item.inflAmnt?item.inflAmnt.toFixed(1) : ''
|
||||
}
|
||||
})
|
||||
|
||||
rtnData.forEach((item: RdiProps) => {
|
||||
dataFormSetting(item)
|
||||
})
|
||||
|
||||
if(pageSize>5000){
|
||||
rtnData.forEach((item: RdiProps) => {
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시설명: item.bscFctNm,
|
||||
시도: item.sido,
|
||||
시군구: item.sigungo,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
하절기강우일최저유입BOD: item.summerMinBodValue,
|
||||
하절기최저유입BOD유입유량: item.inflAmnt,
|
||||
동절기청천시유입BOD: item.winterAvgBodLowRainfall,
|
||||
RDII추정 : item.rdiiValue,
|
||||
RDII추정시일강수량 : item.infoRnDay,
|
||||
});
|
||||
});
|
||||
}
|
||||
set((state: RdiType) => ({
|
||||
...state,
|
||||
Rdi: pageSize<5000?{
|
||||
...state.Rdi,
|
||||
rdiList: rtnData,
|
||||
rdiCount: res.count,
|
||||
}:{
|
||||
...state.Rdi,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
export type SewageOccurProps = {
|
||||
bscFctCd : string,
|
||||
sidoNm : string,
|
||||
sggNm : string,
|
||||
lclgvrnmntNm : string,
|
||||
bscFctNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
waterUsage : number,
|
||||
swageChangePercent : number,
|
||||
estimationSewage : number,
|
||||
sewageInputYear : number,
|
||||
sewageInputChungchun : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
msrDt : string,
|
||||
}
|
||||
|
||||
export type SewageOccurDetailProps = {
|
||||
msrDt : string,
|
||||
waterUsage : number,
|
||||
swageChangePercent : number,
|
||||
estimationSewage : number,
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
물사용량: number | '',
|
||||
오수전환율: number | '',
|
||||
오수발생량추정: number | '',
|
||||
연간하수유입량: number | '',
|
||||
청천시하수유입량: number | '',
|
||||
}
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "swageChangePercent", title: "오수전환율\n(%)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "swageChangePercent", title: "오수전환율", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "waterUsage", title: "물사용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "swageChangePercent", title: "오수전환율", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "estimationSewage", title: "오수발생량 추정\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputYear", title: "연간 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "sewageInputChungchun", title: "청천시 하수유입량\n(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const upHeadListSewageOccurDetail:TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "년월" },
|
||||
{ id: "waterUsage", title: "물사용량(m³/일)" },
|
||||
{ id: "swageChangePercent", title: "오수전환율" },
|
||||
{ id: "estimationSewage", title: "오수발생량 추정(m³/일)", row:0, rowSpan:2 },
|
||||
];
|
||||
|
||||
const sewageOccurList:SewageOccurProps[] = [
|
||||
]
|
||||
|
||||
const tempSewageOccurList:SewageOccurDetailProps[] = [
|
||||
{
|
||||
msrDt: '2024-01',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 60,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-02',
|
||||
waterUsage: 106,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-03',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-04',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-05',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 10,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-06',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-07',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 580,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-08',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-09',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-10',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-11',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2024-12',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-01',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-02',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-03',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-04',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-05',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-06',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-07',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-08',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 0.8,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-09',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-10',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-11',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
{
|
||||
msrDt: '2025-12',
|
||||
waterUsage: 100,
|
||||
swageChangePercent: 80,
|
||||
estimationSewage: 80,
|
||||
},
|
||||
]
|
||||
|
||||
/**====================================
|
||||
* Store - API
|
||||
====================================*/
|
||||
|
||||
const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
// 20250701임시시
|
||||
console.log("partCd", partCd);
|
||||
console.log("nameCd", nameCd);
|
||||
console.log("fcltCpct", fcltCpct);
|
||||
console.log("operationValue", operationValue);
|
||||
console.log("fcltyNm", fcltyNm);
|
||||
console.log("searchYear", searchYear);
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
console.log("res", res.data);
|
||||
return { data: res.data, count: res.count }
|
||||
|
||||
/*
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/qlty/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count } */
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type SewageOccurActions = {
|
||||
searchSewageOccurList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
export type SewageOccurType = {
|
||||
SewageOccurSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
SewageOccur : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
sewageOccurList: SewageOccurProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
sewageOccurCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
|
||||
SewageOccurDetail : {
|
||||
isInit: boolean;
|
||||
upHeadListSewageOccurDetail: TableUpperProps[];
|
||||
gridListSewageOccurDetail: SewageOccurDetailProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export const sewageOccurInitState: SewageOccurType = {
|
||||
SewageOccurSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
SewageOccur : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
sewageOccurList : sewageOccurList,
|
||||
sewageOccurCount : 2,
|
||||
excelList : []
|
||||
},
|
||||
|
||||
SewageOccurDetail : {
|
||||
isInit: false,
|
||||
upHeadListSewageOccurDetail: upHeadListSewageOccurDetail,
|
||||
gridListSewageOccurDetail: tempSewageOccurList,
|
||||
}
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : SewageOccurProps)=> {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'waterUsage', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'estimationSewage', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'sewageInputYear', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'sewageInputChungchun', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
export type SewageOccurStore = SewageOccurType & SewageOccurActions;
|
||||
|
||||
// Add type definitions for API responses
|
||||
type FlowDataItem = {
|
||||
inflAmnt: string | number;
|
||||
infoRnDay: string | number;
|
||||
bscFctCd: string;
|
||||
msrDt: string;
|
||||
}
|
||||
|
||||
type FlowResponse = {
|
||||
data: FlowDataItem[];
|
||||
count: number;
|
||||
}
|
||||
|
||||
type SetStateFunction = (state: SewageOccurType | ((state: SewageOccurType) => SewageOccurType)) => void;
|
||||
|
||||
export const sewageOccurReducer:(set:SetStateFunction)=>SewageOccurActions=(set: SetStateFunction) => {
|
||||
return {
|
||||
searchSewageOccurList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchSewageOccurList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
|
||||
// Promise.all을 사용하여 모든 비동기 작업이 완료될 때까지 기다림
|
||||
const calData = await Promise.all(data.map(async (item: SewageOccurProps) => {
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
item.waterUsage = item.fctCpc * 0.6;
|
||||
item.swageChangePercent = 80;
|
||||
item.estimationSewage = item.waterUsage * (item.swageChangePercent/100);
|
||||
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const url2 = '/fclt/flow/' + bscFctCd + '/' + searchYear;
|
||||
const res2 = await getFetch('fo', url2) as FlowResponse;
|
||||
const sumFlow = res2.data.reduce((acc: number, curr: FlowDataItem) => Number(acc) + Number(curr.inflAmnt), 0);
|
||||
|
||||
let sumChungcunDay = 0;
|
||||
let chungcunSumFlow = 0;
|
||||
|
||||
res2.data.forEach((item: FlowDataItem) => {
|
||||
if(Number(item.infoRnDay) ===0){
|
||||
chungcunSumFlow += Number(item.inflAmnt);
|
||||
sumChungcunDay += 1;
|
||||
}else{
|
||||
console.log(item.bscFctCd +' day : ' +' '+item.msrDt);
|
||||
}
|
||||
});
|
||||
|
||||
item.sewageInputYear = sumFlow/res2.count;
|
||||
item.sewageInputChungchun = chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay);
|
||||
return item;
|
||||
}));
|
||||
|
||||
console.log('calData : ', calData);
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
if(pageSize>5000){
|
||||
calData.forEach(item => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
/* item.ctpvNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
시설명: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
물사용량: item.waterUsage,
|
||||
오수전환율: item.swageChangePercent,
|
||||
오수발생량추정: item.estimationSewage,
|
||||
연간하수유입량: item.sewageInputYear,
|
||||
청천시하수유입량: item.sewageInputChungchun,
|
||||
});
|
||||
});
|
||||
}else{
|
||||
calData.forEach((item: SewageOccurProps) => {
|
||||
dataFormSetting(item)
|
||||
/* item.sidoNmNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
|
||||
});
|
||||
}
|
||||
set((state: SewageOccurType) => ({
|
||||
...state,
|
||||
SewageOccur: pageSize<5000?{
|
||||
...state.SewageOccur,
|
||||
sewageOccurList: calData,
|
||||
sewageOccurCount: res.count,
|
||||
}:{
|
||||
...state.SewageOccur,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { createStore } from 'zustand/vanilla';
|
||||
import { CommonReducer, commonState, type CommonStore, type CommonType } from './common';
|
||||
import { dashBoardReducer, dashBoardInitState, type DashBoardStore, type DashBoardType } from './dashboard';
|
||||
import {
|
||||
facilityPrecipitationInitState,
|
||||
facilityPrecipitationReducer,
|
||||
type FacilityPrecipitationStore, type FacilityPrecipitationType
|
||||
} from './facilityPrecipitation';
|
||||
import { planSewageInitState, planSewageReducer, type PlanSewageStore, type PlanSewageType } from './planSewage';
|
||||
import { flowRateSearchInitState, flowRateSearchReducer, type FlowRateSearchStore, type FlowRateSearchType } from './flowRate';
|
||||
import {
|
||||
processAreaInitState,
|
||||
processAreaReducer,
|
||||
type ProcessAreaStore, type ProcessAreaType
|
||||
} from './processArea';
|
||||
import {
|
||||
processFacilityInitState,
|
||||
processFacilityReducer,
|
||||
type ProcessFacilityStore, type ProcessFacilityType
|
||||
} from './processFacility';
|
||||
import {
|
||||
facilityWaterQltyInitState,
|
||||
facilityWaterQltyReducer,
|
||||
type FacilityWaterQltyStore, type FacilityWaterQltyType
|
||||
} from './facilityWaterQlty';
|
||||
import {
|
||||
sewageOccurInitState,
|
||||
sewageOccurReducer,
|
||||
type SewageOccurStore, type SewageOccurType
|
||||
} from './sewageOccur';
|
||||
import {
|
||||
underWaterInitState,
|
||||
underWaterReducer,
|
||||
type UnderWaterStore, type UnderWaterType
|
||||
} from './underWaterInput';
|
||||
import {
|
||||
rdiInitState,
|
||||
rdiReducer,
|
||||
type RdiStore, type RdiType
|
||||
} from './rdi';
|
||||
import { tableActionsExport, tableStateExport, type tableState, type tableType } from './publicReuseFaciltyInsert/index';
|
||||
export type FoStore = CommonStore & tableType & DashBoardStore & ProcessFacilityStore & ProcessAreaStore & FlowRateSearchStore & FacilityPrecipitationStore & FacilityWaterQltyStore & PlanSewageStore & SewageOccurStore & UnderWaterStore & RdiStore;
|
||||
export type FoState = CommonType & tableState & ProcessFacilityType & ProcessAreaType & FacilityPrecipitationType & FlowRateSearchType & DashBoardType & FacilityWaterQltyType & PlanSewageType & SewageOccurType & UnderWaterType & RdiType;
|
||||
|
||||
export const StoreZus =
|
||||
(initState: FoState = { ...commonState,
|
||||
...tableStateExport
|
||||
, ...processFacilityInitState
|
||||
, ...processAreaInitState
|
||||
, ...facilityPrecipitationInitState
|
||||
, ...dashBoardInitState
|
||||
, ...flowRateSearchInitState
|
||||
, ...facilityWaterQltyInitState
|
||||
, ...planSewageInitState
|
||||
, ...sewageOccurInitState
|
||||
, ...underWaterInitState
|
||||
, ...rdiInitState
|
||||
}
|
||||
) => {
|
||||
return createStore<FoStore>()((set) => {
|
||||
return {
|
||||
...initState,
|
||||
...CommonReducer(set),
|
||||
...tableActionsExport(set),
|
||||
...dashBoardReducer(set),
|
||||
...processFacilityReducer(set),
|
||||
...processAreaReducer(set),
|
||||
...facilityPrecipitationReducer(set),
|
||||
...flowRateSearchReducer(set),
|
||||
...facilityWaterQltyReducer(set),
|
||||
...planSewageReducer(set),
|
||||
...sewageOccurReducer(set),
|
||||
...underWaterReducer(set),
|
||||
...rdiReducer(set),
|
||||
}
|
||||
})
|
||||
}
|
||||
//store 등록하는 부분
|
||||
@@ -0,0 +1,397 @@
|
||||
import DataForm from "@/app/components/common/DataForm";
|
||||
import type { TableUpperProps } from "../dashboard";
|
||||
import { getFetch } from "@/app/components/api";
|
||||
export type { TableUpperProps };
|
||||
/**====================================
|
||||
* Store - 타입
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 시설별 강수현황
|
||||
export type UnderWaterProps = {
|
||||
bscFctCd : string,
|
||||
lclgvrnmntNm : string,
|
||||
sidoNm : string,
|
||||
sggNm : string,
|
||||
bscFctNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
underWaterInputYear : number,
|
||||
underWaterInputSummer : number,
|
||||
underWaterInputWinter : number,
|
||||
infoRnDay : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
}
|
||||
export interface UnderWaterInterface {
|
||||
bscFctCd : string,
|
||||
sidoNm : string,
|
||||
sggNm : string,
|
||||
bscFctNm : string,
|
||||
daddr : string,
|
||||
fctCpc : number,
|
||||
underWaterInputYear : number,
|
||||
underWaterInputSummer : number,
|
||||
underWaterInputWinter : number,
|
||||
infoRnDay : number,
|
||||
rgnNm : string,
|
||||
rvbsn : string,
|
||||
lgbsn : string,
|
||||
mdmbsn : string,
|
||||
}
|
||||
|
||||
// 모달
|
||||
export interface UnderWaterInputModalProps {
|
||||
msrDt : string,
|
||||
realSewageInput : number | '',
|
||||
sewageOccur : number | '',
|
||||
underWaterInput : number | '',
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - data
|
||||
====================================*/
|
||||
|
||||
/**
|
||||
* (1) 메인페이지
|
||||
*/
|
||||
// 검색단
|
||||
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
|
||||
|
||||
export interface ExcelType {
|
||||
시설코드: string,
|
||||
권역:string|'',
|
||||
단위유역:string|'',
|
||||
중권역:string|'',
|
||||
환경청:string|'',
|
||||
시도: string,
|
||||
시군구: string,
|
||||
시설명: string,
|
||||
주소: string,
|
||||
시설용량: number,
|
||||
연간지하수유입량: number | '',
|
||||
하절기지하수유입량: number | '',
|
||||
동절기지하수유입량: number | '',
|
||||
}
|
||||
|
||||
// 리스트 헤더
|
||||
const upHeadList1:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 },
|
||||
];
|
||||
|
||||
const upHeadList2:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 },
|
||||
];
|
||||
|
||||
const upHeadList3:TableUpperProps[] = [
|
||||
{ id: "bscFctCd", title: "시설코드", row:0, rowSpan:2 },
|
||||
{ id: "A", title: "유역", row:0, colSpan:3 },
|
||||
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
|
||||
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
|
||||
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
|
||||
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
|
||||
{ id: "B", title: "행정구역", row:0, colSpan:2 },
|
||||
{ id: "sidoNm", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
|
||||
{ id: "sggNm", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
|
||||
{ id: "bscFctNm", title: "시설명", row:0, rowSpan:2 },
|
||||
{ id: "daddr", title: "주소", row:0, rowSpan:2 },
|
||||
{ id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 },
|
||||
{ id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 },
|
||||
{ id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 },
|
||||
{ id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 },
|
||||
];
|
||||
|
||||
// 모달
|
||||
const upHeadListUnderWaterDetail:TableUpperProps[] = [
|
||||
{ id: "msrDt", title: "날짜" },
|
||||
{ id: "realSewageInput", title: "실제 하수유입량\n(m³/일)" },
|
||||
{ id: "sewageOccur", title: "오수발생량\n(m³/일)" },
|
||||
{ id: "underWaterInput", title: "지하수 유입량\n(m³/일)" },
|
||||
];
|
||||
|
||||
const underWaterList:UnderWaterProps[] = [
|
||||
]
|
||||
|
||||
const underWaterDetailList:UnderWaterInputModalProps[] = [
|
||||
{
|
||||
msrDt : "2024-01",
|
||||
realSewageInput : 178007,
|
||||
sewageOccur : 10.5,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-02",
|
||||
realSewageInput : 123007,
|
||||
sewageOccur : 10.7,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-03",
|
||||
realSewageInput : 213007,
|
||||
sewageOccur : 10.1,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-04",
|
||||
realSewageInput : 83007,
|
||||
sewageOccur : 9.57,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-05",
|
||||
realSewageInput : 15007,
|
||||
sewageOccur : 3.57,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-06",
|
||||
realSewageInput : 123007,
|
||||
sewageOccur : '',
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-07",
|
||||
realSewageInput : 101007,
|
||||
sewageOccur : 1,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-08",
|
||||
realSewageInput : 103807,
|
||||
sewageOccur : 10.57,
|
||||
underWaterInput : '',
|
||||
},
|
||||
{
|
||||
msrDt : "2024-09",
|
||||
realSewageInput : 9007,
|
||||
sewageOccur : 10.57,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-10",
|
||||
realSewageInput : 163007,
|
||||
sewageOccur : 10.57,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-11",
|
||||
realSewageInput : 123007,
|
||||
sewageOccur : 10.57,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
{
|
||||
msrDt : "2024-12",
|
||||
realSewageInput : 1007,
|
||||
sewageOccur : 10.57,
|
||||
underWaterInput : 80.6,
|
||||
},
|
||||
]
|
||||
/**====================================
|
||||
* Store - API
|
||||
====================================*/
|
||||
|
||||
// API response types
|
||||
interface FlowDataItem {
|
||||
inflAmnt: number;
|
||||
infoRnDay: number;
|
||||
msrDt: string;
|
||||
}
|
||||
|
||||
interface ApiResponse {
|
||||
data: FlowDataItem[];
|
||||
count: number;
|
||||
}
|
||||
|
||||
const fetchUnderWaterList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count }
|
||||
/*
|
||||
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
|
||||
const url = '/fclt/qlty/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
|
||||
const res = await getFetch('fo', url);
|
||||
return { data: res.data, count: res.count } */
|
||||
|
||||
//return { data: underWaterList, count: 2 };
|
||||
}
|
||||
|
||||
/**====================================
|
||||
* Store - expaort
|
||||
====================================*/
|
||||
export type UnderWaterActions = {
|
||||
searchUnderWaterList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
|
||||
}
|
||||
|
||||
export type UnderWaterType = {
|
||||
UnderWaterSearch: {
|
||||
isInit: boolean;
|
||||
labelArray:string[];
|
||||
},
|
||||
|
||||
UnderWater : {
|
||||
isInit: boolean;
|
||||
upHeadList1: TableUpperProps[];
|
||||
upHeadList2: TableUpperProps[];
|
||||
upHeadList3: TableUpperProps[];
|
||||
underWaterList: UnderWaterProps[]; // Changed from facilityAreaProps to ProcessAreaProps
|
||||
underWaterCount: number;
|
||||
excelList: ExcelType[];
|
||||
},
|
||||
|
||||
UnderWaterDetail : {
|
||||
isInit: boolean;
|
||||
upHeadListUnderWaterDetail: TableUpperProps[];
|
||||
gridListUnderWaterDetail: UnderWaterInputModalProps[];
|
||||
}
|
||||
}
|
||||
|
||||
export const underWaterInitState: UnderWaterType = {
|
||||
UnderWaterSearch: {
|
||||
isInit: false,
|
||||
labelArray: LabelArray,
|
||||
},
|
||||
|
||||
UnderWater : {
|
||||
isInit : false,
|
||||
upHeadList1 : upHeadList1,
|
||||
upHeadList2 : upHeadList2,
|
||||
upHeadList3 : upHeadList3,
|
||||
underWaterList : underWaterList,
|
||||
underWaterCount : 4,
|
||||
excelList : []
|
||||
},
|
||||
|
||||
UnderWaterDetail : {
|
||||
isInit: false,
|
||||
upHeadListUnderWaterDetail: upHeadListUnderWaterDetail,
|
||||
gridListUnderWaterDetail: underWaterDetailList,
|
||||
}
|
||||
}
|
||||
|
||||
const dataFormSetting=(item : UnderWaterProps)=> {
|
||||
DataForm({ type: 'float1', column: 'fctCpc', item: item as unknown as Record<string, unknown> });
|
||||
DataForm({ type: 'float1', column: 'underWaterInputYear', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'underWaterInputSummer', item: item as unknown as Record<string, unknown>});
|
||||
DataForm({ type: 'float2', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown>});
|
||||
}
|
||||
|
||||
export type UnderWaterStore = UnderWaterType & UnderWaterActions;
|
||||
|
||||
export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterType) => void)=>UnderWaterActions=(set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => {
|
||||
return {
|
||||
searchUnderWaterList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
|
||||
const res = await fetchUnderWaterList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
|
||||
const data = res.data;
|
||||
const calData = await Promise.all(data.map(async (item: UnderWaterProps) => {
|
||||
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
|
||||
const bscFctCd = item.bscFctCd;
|
||||
const url2 = '/fclt/flow/' + bscFctCd + '/' + searchYear;
|
||||
const res2 = await getFetch('fo', url2) as ApiResponse;
|
||||
|
||||
let sumChungcunDay = 0;
|
||||
let chungcunSumFlow = 0;
|
||||
|
||||
let sumSummerChungcunDay = 0;
|
||||
let sumSummerChungcunFlow = 0;
|
||||
|
||||
let sumWinterChungcunDay = 0;
|
||||
let sumWinterChungcunFlow = 0;
|
||||
|
||||
res2.data.forEach((flowItem: FlowDataItem) => {
|
||||
// 청천시
|
||||
if(Number(flowItem.infoRnDay) ===0){
|
||||
sumChungcunDay += 1;
|
||||
chungcunSumFlow += Number(flowItem.inflAmnt);
|
||||
|
||||
if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
|
||||
sumSummerChungcunDay += 1;
|
||||
sumSummerChungcunFlow += Number(flowItem.inflAmnt);
|
||||
}else if(flowItem.msrDt.includes('01') || flowItem.msrDt.includes('02')){
|
||||
sumWinterChungcunDay += 1;
|
||||
sumWinterChungcunFlow += Number(flowItem.inflAmnt);
|
||||
}
|
||||
}
|
||||
});
|
||||
item.underWaterInputYear = Number(chungcunSumFlow==0?0:Math.round((chungcunSumFlow / sumChungcunDay) * 10) / 10) - Number(item.fctCpc * 0.6 * 0.8);
|
||||
item.underWaterInputSummer = Number(sumSummerChungcunFlow==0?0:Math.round((sumSummerChungcunFlow / sumSummerChungcunDay) * 10) / 10) - Number(item.fctCpc * 0.6 * 0.8);
|
||||
item.underWaterInputWinter = Number(sumWinterChungcunFlow==0?0:Math.round((sumWinterChungcunFlow / sumWinterChungcunDay) * 10) / 10) - Number(item.fctCpc * 0.6 * 0.8);
|
||||
|
||||
return item;
|
||||
}));
|
||||
|
||||
const excelDownList: ExcelType[] = [];
|
||||
if(pageSize>5000){
|
||||
calData.forEach(item => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
/* item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
|
||||
excelDownList.push({
|
||||
시설코드: item.bscFctCd,
|
||||
권역: item.rvbsn,
|
||||
단위유역: item.lgbsn,
|
||||
중권역: item.mdmbsn,
|
||||
환경청: item.rgnNm,
|
||||
시도: item.sidoNm,
|
||||
시군구: item.sggNm,
|
||||
시설명: item.bscFctNm,
|
||||
주소: item.daddr,
|
||||
시설용량: item.fctCpc,
|
||||
연간지하수유입량: item.underWaterInputYear,
|
||||
하절기지하수유입량: item.underWaterInputSummer,
|
||||
동절기지하수유입량: item.underWaterInputWinter,
|
||||
|
||||
});
|
||||
});
|
||||
}else{
|
||||
data.forEach((item: UnderWaterProps) => {
|
||||
dataFormSetting(item)
|
||||
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
|
||||
/* item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
|
||||
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
|
||||
});
|
||||
}
|
||||
set((state: UnderWaterType) => ({
|
||||
...state,
|
||||
UnderWater: pageSize<5000?{
|
||||
...state.UnderWater,
|
||||
underWaterList: calData,
|
||||
underWaterCount: res.count,
|
||||
}:{
|
||||
...state.UnderWater,
|
||||
excelList: excelDownList,
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": true,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "app/globals.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
});
|
||||
|
||||
const eslintConfig = [
|
||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||
];
|
||||
|
||||
export default eslintConfig;
|
||||
@@ -0,0 +1,115 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id";
|
||||
const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization";
|
||||
const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || "";
|
||||
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
|
||||
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
|
||||
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
console.log("Middleware 진입:", req.nextUrl.pathname);
|
||||
const pathname = req.nextUrl.pathname;
|
||||
const searchParams = req.nextUrl.searchParams;
|
||||
|
||||
if (pathname.startsWith("/server")) {
|
||||
const queryParams = searchParams.toString();
|
||||
const newUrl = `${SERVER_API_URL}${pathname.replace("/server", "")}${
|
||||
queryParams ? `?${queryParams}` : ""
|
||||
}`;
|
||||
console.log(`[Middleware] Rewriting from '/server' path to: ${newUrl}`);
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/geoserver")) {
|
||||
let queryParams = searchParams.toString();
|
||||
const typename = searchParams.get("TYPENAME");
|
||||
|
||||
let newUrl = `${GEOSERVER_URL}${pathname.replace("/geoserver", "")}${queryParams ? `?${queryParams}` : ""}`;
|
||||
|
||||
if (
|
||||
typename == "hasudo:tb_il_swage_prcs_fclt" //하수처리시설
|
||||
|| typename == "hasudo:tb_ms_swage_prcs_zone" //하수처리구역
|
||||
|| typename == "hasudo:tb_ms_sbmrg_dngr_map" //침수위험지도
|
||||
|| typename == "hasudo:tb_ms_flood_dngr_map" //도시침수지도
|
||||
) {
|
||||
newUrl = `${GEOSERVER_URL}${pathname.replace("/geoserver", "")}${queryParams ? `?${queryParams}` : ""}`;
|
||||
}
|
||||
else if (
|
||||
typename == "hasudo:tb_ms_swage_ppl" //관로
|
||||
|| typename == "hasudo:tb_ms_swage_mhl" //맨홀
|
||||
|| typename == "hasudo:tb_ms_swage_pmstn" //펌프장
|
||||
|| typename == "hasudo:tb_ms_stofcbr" //우수토실
|
||||
) {
|
||||
newUrl = `${LX_GEOSERVER_URL}${pathname.replace("/geoserver", "")}${queryParams ? `?${queryParams}` : ""}`;
|
||||
}
|
||||
else if (
|
||||
typename == "hasudo:om_dt_untrt_swg_rain" //중점우수토실
|
||||
|| typename == "hasudo:om_wqlt_station" //관측소
|
||||
|| typename == "hasudo:tb_wr_bdst_ruse_fclt" //재이용시설
|
||||
|| typename == "hasudo:tb_wr_rnwtr_utztn_fclt" //빗물이용시설
|
||||
|| typename == "hasudo:tb_wr_rswtr_fclt" //중수도시설
|
||||
|| typename == "hasudo:tb_wr_htdfl_fclt" //온배수시설
|
||||
|| typename == "hasudo:tb_wr_ruse_fclt_dmd_co" //수요처
|
||||
|| typename == "hasudo:tb_wr_tmpr_dmd_co" //잠재수요처
|
||||
){
|
||||
const url = req.nextUrl.clone();
|
||||
url.searchParams.set('TYPENAME', typename.replace("hasudo:",""));
|
||||
queryParams = url.searchParams.toString();
|
||||
newUrl = `${SEWERAGE_API_URL}/v1/map/geometry${queryParams ? `?${queryParams}` : ""}`;
|
||||
}
|
||||
|
||||
console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`);
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/sewerage-service/api/v1/map/geometry")) {
|
||||
const queryParams = searchParams.toString();
|
||||
const newUrl = `${SEWERAGE_API_URL}${pathname.replace("/sewerage-service/api", "")}${
|
||||
queryParams ? `?${queryParams}` : ""
|
||||
}`;
|
||||
console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`);
|
||||
return NextResponse.rewrite(new URL(newUrl));
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/attach-service") || pathname.startsWith("/cms-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const token = req.cookies.get(CLAIM_NAME)?.value;
|
||||
const userId = req.cookies.get(AUTH_USER_ID)?.value;
|
||||
const newUrl = `${SERVER_API_URL}${pathname}`;
|
||||
|
||||
if (token) requestHeaders.set(CLAIM_NAME, token);
|
||||
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
|
||||
|
||||
console.log(
|
||||
`[Middleware] Rewriting from '/attach-service' path to: ${newUrl}`,
|
||||
);
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/user-service")) {
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const newUrl = `${SERVER_API_URL}${pathname}`;
|
||||
|
||||
console.log(
|
||||
`[Middleware] Rewriting from '/user-service' path to: ${newUrl}`,
|
||||
);
|
||||
return NextResponse.rewrite(new URL(newUrl), {
|
||||
headers: requestHeaders,
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
"/server/:path*",
|
||||
"/geoserver/:path*",
|
||||
"/attach-service/:path*",
|
||||
"/user-service/:path*",
|
||||
"/cms-service/:path*",
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const subDomain =
|
||||
process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13001";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
output: "standalone",
|
||||
async rewrites() {
|
||||
return {
|
||||
beforeFiles: [
|
||||
{
|
||||
source: "/_next/static/:path*",
|
||||
destination: `${subDomain}/_next/static/:path*`,
|
||||
has: [
|
||||
{
|
||||
type: "header",
|
||||
key: "referer",
|
||||
value: "(.*)/pst(.*)",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
afterFiles: [
|
||||
{
|
||||
source: "/pst/:path*",
|
||||
destination: `${subDomain}/pst/:path*`,
|
||||
},
|
||||
],
|
||||
fallback: [],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "fo",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@common/business_components": "workspace:*",
|
||||
"@common/components": "workspace:*",
|
||||
"@tailwindcss/vite": "^4.0.10",
|
||||
"html2canvas": "^1.4.1",
|
||||
"next": "15.1.7",
|
||||
"select": "^1.1.2",
|
||||
"webpack": "^5.98.0",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "15.1.7",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5.6.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1 @@
|
||||
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 391 B |
@@ -0,0 +1 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 961 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 970 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1016 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 468 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 757 B |
|
After Width: | Height: | Size: 785 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 791 B |
|
After Width: | Height: | Size: 782 B |
|
After Width: | Height: | Size: 782 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 217 B |
|
After Width: | Height: | Size: 217 B |
|
After Width: | Height: | Size: 217 B |
|
After Width: | Height: | Size: 217 B |
|
After Width: | Height: | Size: 217 B |