Compare commits

...
Author SHA1 Message Date
jyha00 9bdf01e7f3 모달창 사이즈 조정 2025-08-01 16:16:50 +09:00
jyha00 cb83b7f92b 하수재이용시설 현황 엑셀 데이터 없을 시 toast 추가 2025-08-01 15:50:44 +09:00
jyha00 59e3dbbe97 중수도 신규등록 텍스트 수정 2025-08-01 14:59:36 +09:00
leedj312 75bafd5a34 Merge commit '6808430c9ae74890d0f0e84f20a0ffe5409de157' into iipbs/wr/dev 2025-08-01 09:28:04 +09:00
leedj312 8ac807a550 Merge commit '8eea3c75aa82327ae5d670640afc242933766332' into iipbs/wr/dev 2025-08-01 09:26:12 +09:00
leedj312 9d2511c6ea Merge commit 'cb0f3160230da1d5a70e0e527e62bfe0af0d6d04' into iipbs/wr/dev 2025-08-01 09:25:05 +09:00
leedj312 8eea3c75aa 수요매칭 검토 이상 이하 수정 2025-07-31 20:16:38 +09:00
jyha00 cb0f316023 수요처관리 비밀번호 초기화 추가 수정 2025-07-31 20:11:10 +09:00
jyha00 d23f928ddb 수요처관리 비밀번호 초기화 추가 2025-07-31 19:53:17 +09:00
JIeunhuh fb9dacd60c 팝업 크기 적용 2025-07-31 17:58:33 +09:00
JIeunhuh 1952bd5c2c Merge commit 'fd55d2e3cfa04fcea4ac767a7709f1b3920668cf' into iipbs/wr/gismng 2025-07-31 17:27:25 +09:00
JIeunhuh 765ca59e35 팝업별 컴포넌트 분리 및 시설 선택시 해당 api만 호출하도록 변경 2025-07-31 17:00:08 +09:00
swcho 6808430c9a feat: UITable 컴포넌트의 index props를 통해 외부에서 내부 select idx를 제어할 수 있도록 변경 2025-07-31 16:09:36 +09:00
leedj312 fd55d2e3cf Merge commit '3a3eae84aea917edab09e0f82faaba0749921ea7' 2025-07-31 14:54:41 +09:00
leedj312 3a3eae84ae Merge commit '0c16b9d14df0f523bbdd6908536b40f9e88e6d56' into iipbs/wr/dev 2025-07-31 14:51:14 +09:00
leedj312 a24d9f42d6 Merge commit 'e5f2cb2182f407a78d25edc05f81e5cc6f49deaf' into iipbs/wr/dev 2025-07-31 14:43:08 +09:00
Your Name 96ef328fbf Merge branch 'iipbs/fo/dev' 2025-07-31 14:39:23 +09:00
JIeunhuh 7ee7a0fc69 컴포넌ㅌ트 분리중 .. 2025-07-31 14:38:14 +09:00
Your Name 4c66dacdb0 원복 2025-07-31 14:31:59 +09:00
yschoi 024a69b1fd Merge remote-tracking branch 'origin/iipbs/fo/dev' 2025-07-31 13:53:15 +09:00
Your Name 8a2bbfe220 원앤올 API URL 재수정 2025-07-31 13:52:52 +09:00
yschoi d954675824 Merge remote-tracking branch 'origin/iipbs/dm/dev' 2025-07-31 13:50:43 +09:00
Your Name 5712bcedaa 원앤올 DB바라보게 수정 2025-07-31 13:38:27 +09:00
yschoi deaf428ed9 Merge remote-tracking branch 'origin/iipbs/wr/dev' 2025-07-31 13:29:41 +09:00
leedj312 0c16b9d14d 중수도 지도점검 엑셀등록 오류 메시지 추가 2025-07-31 13:28:21 +09:00
yschoi 41686670a4 Merge remote-tracking branch 'origin/iipbs/fo/dev' 2025-07-31 13:23:08 +09:00
yschoi 82019c86bf Merge remote-tracking branch 'origin/iipbs/sn/dev' 2025-07-31 13:18:46 +09:00
yschoi 637929ea26 지도 코드 정리 2025-07-31 13:15:22 +09:00
JIeunhuh 80156bd349 팝업 현황 수정사항 변경 (시설물 클릭 시 api 모두 조회 되는 부분 작업 중) 2025-07-31 10:02:21 +09:00
swcho 2e7b06d970 feat: 중점우수토실 페이징 처리 (테이블 동기화 추가 작업 필요) 2025-07-30 21:37:40 +09:00
swcho c23fe68675 refactor: 시도, 시군구 호출 주석 추가 2025-07-30 21:35:16 +09:00
swcho b5c7f09bc9 feat: 시도, 시군구 zustand Store로 메인 화면에서 호출 후 SearchModal.tsx에서 사용 2025-07-30 20:55:57 +09:00
swcho 4cfa032be2 feat: 오수전환율 초깃값 0.8로 수정 2025-07-30 20:31:13 +09:00
swcho 83b63901ff Merge branch 'iipbs/sn/dev' 2025-07-30 17:51:53 +09:00
swcho 96624140e0 Merge branch 'iipbs/sn/ii' into iipbs/sn/dev 2025-07-30 17:48:28 +09:00
swcho 6c6b5e662c feat: 하수처리시설에 시도, 시군구 검색 조건 추가 2025-07-30 17:47:16 +09:00
swcho bbfd7fd201 fix: 연월 포맷 수정 (년월일 -> -로 구분) 2025-07-30 17:00:15 +09:00
swcho 340814439a fix, remove:
- featureClickEventPopup.tsx 경로 수정
- 이전 시도, 시군구 리스트 삭제
2025-07-30 16:44:11 +09:00
swcho 5cc86d81f1 refactor: featureClickEventPopup.tsx 경로 변경 (popupComponent 내부로) 2025-07-30 16:35:11 +09:00
swcho a05b0e1cfe feat, remove:
- GeoServer API 호출 함수 구현
- 하드코딩 시도, 시군구 테이블 삭제
2025-07-30 16:33:31 +09:00
swcho c89c588487 fix: 시도, 시군구 하드코딩 -> 알에스원 API로 변경 (이후 Store로 변경 필요) 2025-07-30 16:25:09 +09:00
Your Name df18a79528 물사용량 오류 및 null 관련오류 수정 2025-07-30 16:00:22 +09:00
swcho 18b8a6edab fix: searchModal.tsx 테이블 헤더 줄 바꿈 수정 2025-07-30 15:42:47 +09:00
swcho fcfaa23dc3 fix: 검색 창 위 아래 간격 수정 2025-07-30 15:35:45 +09:00
yschoi 5382328f94 Merge remote-tracking branch 'origin/iipbs/fo/dev' 2025-07-30 13:54:39 +09:00
Your Name 3bd22d83b7 계획정보 API 호출 공통화 및 수정 2025-07-30 11:23:16 +09:00
rsone001 5405af7ff3 연계 api 미들웨어 적용용 2025-07-30 10:09:34 +09:00
Your Name 0abc7eaaac 배수설비 정비현황 조회삭제 2025-07-30 09:49:26 +09:00
yschoi 0805fbcc26 Merge remote-tracking branch 'origin/iipbs/dm/dev' 2025-07-30 09:45:42 +09:00
swcho 2f553a0dff fix: searchModal.tsx 테이블 헤더리스트 줄 바꿈 적용 2025-07-30 09:44:09 +09:00
Your Name c713b55480 물사용량은 계획정보 없어도 대시보드에 추출되도록 수정 2025-07-30 09:34:54 +09:00
swcho 6dd48a3054 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2025-07-29 20:57:37 +09:00
swcho afa129f20b Merge branch 'main' into iipbs/sn/dev 2025-07-29 20:55:53 +09:00
swcho 6dae81eb05 fix, refactor:
- 기본검색 하수관로의 Input 컴포넌트 변수 중복 에러 수정
- 운영정보 검색 테이블 개수 5개로 수정
2025-07-29 20:51:12 +09:00
jyha00 e5f2cb2182 물재이용사례관리 페이지 수정 2025-07-29 20:40:05 +09:00
swcho 0fe84dba22 feat: Input 컴포넌트의 Enter 키 입력시 조회, 검색 기능 event 구현 2025-07-29 20:32:30 +09:00
swcho b2e0780654 feat: 하수관로 상세페이지 '상류관로 보기' 버튼 오른쪽 정렬 2025-07-29 20:20:29 +09:00
swcho 81d589acb0 fix : 조건창에 텍스트와 입력창 간격 등 일정하게 처리 2025-07-29 20:15:21 +09:00
leedj312 3ba11b5508 빗물 엑셀 등록 항목 오류 점검 2025-07-29 20:11:51 +09:00
Your Name eafe131df1 계획정보 못불러 올 경우 progressbar 없어지게 수정 2025-07-29 18:11:39 +09:00
swcho 97b0a2e5bf fix, feat:
- I/I 분석 화면 CSS 수정 (간격 통일
- I/I 분석 화면 Enter 클릭 이벤트 추가
2025-07-29 16:09:49 +09:00
leedj312 65f74987f8 Merge commit 'aaed8fe971d0ccf31cb0b07f96bb51af4c125a1f' into iipbs/wr/dev 2025-07-29 15:52:08 +09:00
leedj312 aaed8fe971 재이용 시설 실적 등록 목록 테이블 수정 2025-07-29 15:51:18 +09:00
chanii8 c222e809b6 [apps/cs] feat: 접속자 통계 > 접속 로그 상세 테이블 작업 2025-07-29 15:44:47 +09:00
yschoi cba305ab9b Merge branch 'iipbs/wr/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/wr/dev 2025-07-29 15:17:51 +09:00
yschoi 913256cac4 원복 2025-07-29 15:16:45 +09:00
mind-one003 e1fc6f210f 삼항연산자 수정 2025-07-29 01:43:54 -04:00
Your Name 1bec6a3787 결함수정, 날짜2024초기화, 총인설비 tp 키값수정정 2025-07-29 14:29:37 +09:00
chanii8 3ed203c597 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs_cs 2025-07-29 13:23:59 +09:00
chanii8 12f7fe53ad [apps/cs] feat: 접속자통계 데이터 바인딩 2025-07-29 13:23:48 +09:00
leedj312 75d14782f4 Merge commit 'c30de7f40d6b810cc19d5cd23a581d012116899f' into iipbs/wr/dev 2025-07-29 11:33:05 +09:00
chanii8 387362d42b [apps/cs] feat: 게시글 내 목록 버튼 기능 수정 2025-07-29 11:28:48 +09:00
chanii8 4e04676a57 [apps/cs] chore: 대시보드 페이지 데이터 표기 수정 2025-07-29 11:28:01 +09:00
jyha00 c30de7f40d 재이용실적 현황 엑셀 다운로드 수정, 초기화 버튼 수정 2025-07-29 11:10:22 +09:00
leedj312 ca96e55c07 Merge commit '64698fb97e39f5b35b0fd05012f94833dead1522' into iipbs/wr/dev 2025-07-29 10:47:41 +09:00
jyha00 64698fb97e 재이용실적 현황 페이지네이션 오류 수정 2025-07-29 10:33:34 +09:00
leedj312 662a461cfa 하수재이용 현황 페이지 네이션 오류 수정 2025-07-28 18:26:43 +09:00
swcho 2c5ed5f6cf Merge branch 'iipbs/sn/dev' 2025-07-28 17:58:05 +09:00
swcho 484d90e84f fix: 사업 구분 3개로 바꾸기2 2025-07-28 17:51:01 +09:00
swcho f550a62f99 refactor: searchModal.tsx 코드 정리 2025-07-28 17:32:25 +09:00
swcho 9759a5250a fix: 사업 구분 3개로 바꾸기 2025-07-28 17:03:36 +09:00
swcho 890e2af79b fix: 상세 정보 페이지 컬럼 너비 통일 2025-07-28 16:09:22 +09:00
swcho 895adeef0a fix:
- 하수관로 상세정보 컬럼 수정
- 운영정보 검색 일련번호 에러 수정
2025-07-28 15:36:54 +09:00
yschoi 2a15138014 Merge remote-tracking branch 'origin/main' into iipbs/wr/dev 2025-07-28 12:41:08 +09:00
Your Name a2b2d94581 gis.layer merge 2025-07-28 11:21:16 +09:00
Your Name 1083be517d Merge branch 'iipbs/common/main' into iipbs/fo/dev 2025-07-28 11:13:09 +09:00
Your Name dad8b9925e monthpicker enableMonth string[] 파라미터 추가
(선택가능한 월 배열 추가하면됨 ex.['4월', '5월'])
2025-07-28 11:12:27 +09:00
Your Name aeb4f5f8ca 지하수유입량 하절기는 6,7,8월 / 동절기는 1월 2월만 선택가능하도록 파라미터 추가 2025-07-28 11:07:54 +09:00
swcho fc54f6253c Merge branch 'iipbs/common/main' into iipbs/sn/ii 2025-07-28 10:52:20 +09:00
swcho 07c7947da1 fix: gis.layer.js 하수펌프장 CQL 필터 적용 안되는 에러 수정 2025-07-28 10:51:37 +09:00
swcho af035aa649 Merge branch 'iipbs/common/main' into iipbs/sn/ii 2025-07-28 10:35:19 +09:00
swcho 35e1203168 fix: monthPicker.tsx 현재 월에 hover 효과가 지속되는 코드 주석 처리 2025-07-28 10:34:35 +09:00
leedj312 97727908fa 수요처 nullish 처리 2025-07-28 10:32:58 +09:00
swcho 81a3e6324e fix: 침입수, RDII 분석결과 상수사용기간 시작 년도 당해 년도 1월부터로 수정 2025-07-28 09:06:56 +09:00
Your Name dfabee3e08 초기화 돌아가는 문제해결, 대시보드 calData 수정, 처리구역정보 null 오류 수정 2025-07-27 23:50:24 +09:00
mind-one005 16ebb8eb3a Merge branch 'iipbs/sn/dev' 2025-07-27 21:59:04 +09:00
mind-one005 f8c902a138 기본계획 component 분리 2025-07-27 21:55:24 +09:00
Your Name be5ffb60f6 결함수정 - 강우영향일 계산 수정, 2025-07-27 18:40:35 +09:00
mind-one005 01c01dedbb Merge branch 'iipbs/common/main' 2025-07-27 17:16:48 +09:00
mind-one005 007a39ebfa Merge branch 'iipbs/common/main' into iipbs/sn/dev 2025-07-27 17:14:21 +09:00
mind-one005 bec3132417 SelectBox labelClass props 추가 2025-07-27 17:13:43 +09:00
mind-one005 8c2bdc65eb 침입수,RDII 그래프 수정 2025-07-27 17:09:25 +09:00
Your Name befb3f1c84 빌드에러 수정 2025-07-27 14:56:32 +09:00
Your Name 87ee8c827d Merge branch 'iipbs/common/main' into iipbs/fo/dev 2025-07-27 14:44:17 +09:00
Your Name e7a46ac3a2 년월 캘린더 년 readonly 옵션추가 (not necessary) 2025-07-27 14:43:42 +09:00
Your Name bd7debbe3e 오수발생량 추정, 지하수유입량 추정 년월 중 년 disabled 2025-07-27 14:42:30 +09:00
Your Name 1850ab2aa8 대시보드 물사용량평균 수정, 초기화오류 수정, 수질 변수 다시수정 2025-07-27 14:34:32 +09:00
Your Name c976b5d6ee 빌드에러 수정, 대시보드 물사용량 추출완료, 초기화 전체 2023년 2025-07-26 22:55:23 +09:00
Your Name ad7a633bc9 빌드에러 수정 안쓰는변수제거거 2025-07-26 20:59:20 +09:00
Your Name b91298f3d9 강우영향일 관련 문구 추가 2025-07-26 20:57:52 +09:00
Your Name 1207754092 강우영향일 기준 강우일 운영현황 나오도록 수정 2025-07-26 20:45:09 +09:00
Your Name 2fc4f9512f 결함수정중 2025-07-26 19:57:09 +09:00
Your Name 55de8cc31e 결함문제 해결 진행중 2025-07-26 19:24:32 +09:00
mind-one002 f18eaa8f01 메인 머지 이슈로 수정. 2025-07-26 16:46:59 +09:00
mind-one002 04bc7d3a3a Merge commit '0ad7d6a2c4c8d7585d6a5b053444dd6c2b35b710' into iipbs/fo/dev 2025-07-26 16:43:28 +09:00
130 changed files with 4575 additions and 3871 deletions
+27 -1
View File
@@ -11,6 +11,8 @@ import {
const serverApiUrl =
process.env.NEXT_PUBLIC_SERVER_API_URL ?? "http://localhost:3000";
const linkBackendApiHost = process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST ?? "http://localhost:8080";
export function middleware(req: NextRequest) {
const pathname = req.nextUrl.pathname;
const searchParams = req.nextUrl.searchParams;
@@ -52,6 +54,30 @@ export function middleware(req: NextRequest) {
});
}
if (pathname.startsWith("/api/link")) {
const requestHeaders = new Headers(req.headers);
const token = req.cookies.get(CLAIM_NAME)?.value;
const userId = req.cookies.get(AUTH_USER_ID)?.value;
// /api/link 경로를 제거하고 백엔드 API 경로로 변환
const apiPath = pathname.replace("/api/link", "");
const queryParams = searchParams.toString();
const newUrl = `${linkBackendApiHost}${apiPath}${
queryParams ? `?${queryParams}` : ""
}`;
if (token) requestHeaders.set(CLAIM_NAME, token);
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
logMessages.push(` Link API Rewritten URL: ${newUrl}`);
logMessages.push("\n--------------------------------\n");
console.log(logMessages.join("\n"));
return NextResponse.rewrite(new URL(newUrl), {
headers: requestHeaders,
});
}
if (pathname === "/") {
return NextResponse.redirect(new URL("/dashboard", req.url));
}
@@ -62,5 +88,5 @@ export function middleware(req: NextRequest) {
}
export const config = {
matcher: ["/server/:path*", "/attach-service/:path*", "/"],
matcher: ["/server/:path*", "/attach-service/:path*", "/api/link/:path*", "/"],
};
+23 -23
View File
@@ -20,7 +20,7 @@ import {
export class LinkApiService implements LinkService {
public async getLinkList(params: LinkSearchParam): Promise<LinkList> {
const response = await axios.get<LinkList>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkList`,
`/api/link/getLinkList`,
{ params }
);
return response.data;
@@ -28,41 +28,41 @@ export class LinkApiService implements LinkService {
public async getLinkInfo(linkSn: string): Promise<LinkInfo> {
const response = await axios.get<LinkInfo>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkInfo/${linkSn}`,
`/api/link/getLinkInfo/${linkSn}`,
);
return response.data;
}
public async linkQuickStart(linkSn: string): Promise<string> {
const response = await axios.patch<string>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/linkQuickStart/${linkSn}`,
`/api/link/linkQuickStart/${linkSn}`,
);
return response.data;
}
public async updateLinkInfo(data: LinkFormData): Promise<void> {
await axios.put<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkInfo`,
'/api/link/updateLinkInfo',
data,
);
}
public async insertLinkInfo(data: LinkFormData): Promise<void> {
await axios.post<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkInfo`,
'/api/link/insertLinkInfo',
data,
);
}
public async deleteLink(linkSn: string): Promise<void> {
await axios.delete<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/deleteLink/${linkSn}`,
`/api/link/deleteLink/${linkSn}`,
);
}
public async getLinkLogList(params: LinkSearchParam): Promise<LinkLogList> {
const response = await axios.get<LinkLogList>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/selectLinkLoglist`,
'/api/link/selectLinkLoglist',
{ params }
);
return response.data;
@@ -70,7 +70,7 @@ export class LinkApiService implements LinkService {
public async getLinkStatsList(params: LinkSearchParam): Promise<LinkStatsList> {
const response = await axios.get<LinkStatsList>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/selectLinkStats`,
'/api/link/selectLinkStats',
{ params }
);
return response.data;
@@ -78,14 +78,14 @@ export class LinkApiService implements LinkService {
public async getLinkVrblList(linkSn: string): Promise<LinkVrblList> {
const response = await axios.get<LinkVrblList>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkVrblList/${linkSn}`,
`/api/link/getLinkVrblList/${linkSn}`,
);
return response.data;
}
public async insertLinkVrbl(data: LinkVrblFormData): Promise<number> {
const response = await axios.post<number>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkVrbl`,
'/api/link/insertLinkVrbl',
data,
);
@@ -94,7 +94,7 @@ export class LinkApiService implements LinkService {
public async deleteLinkVrbl(data: string[]): Promise<void> {
await axios.delete<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/deleteLinkVrbl`,
'/api/link/deleteLinkVrbl',
{
data
}
@@ -103,35 +103,35 @@ export class LinkApiService implements LinkService {
public async getLinkVrblInfo(linkVrblSn: string): Promise<LinkVrbl> {
const response = await axios.get<LinkVrbl>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkVrblInfo/${linkVrblSn}`,
`/api/link/getLinkVrblInfo/${linkVrblSn}`,
);
return response.data;
}
public async updateLinkVrblInfo(data: LinkVrblFormData): Promise<void> {
await axios.put<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkVrblInfo`,
'/api/link/updateLinkVrblInfo',
data,
);
}
public async getLinkTableInfo(linkSn: string): Promise<LinkTable> {
const response = await axios.get<LinkTable>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkTableInfo/${linkSn}`,
`/api/link/getLinkTableInfo/${linkSn}`,
);
return response.data;
}
public async getLinkTableColList(linkSn: string): Promise<LinkTableColumnsList> {
const response = await axios.get<LinkTableColumnsList>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkTableColList/${linkSn}`,
`/api/link/getLinkTableColList/${linkSn}`,
);
return response.data;
}
public async getLinkTableColInfo(params: { colSn: string; tblSn:string; }): Promise<LinkTableColumns> {
const response = await axios.get<LinkTableColumns>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkTableColInfo`,
'/api/link/getLinkTableColInfo',
{ params }
);
return response.data;
@@ -139,14 +139,14 @@ export class LinkApiService implements LinkService {
public async insertLinkTableCol(data: LinkTableColData): Promise<void> {
await axios.post<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkTableCol`,
'/api/link/insertLinkTableCol',
data
);
}
public async deleteLinkTableCol(data: string[]): Promise<void> {
await axios.delete<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/deleteLinkTableCol`,
'/api/link/deleteLinkTableCol',
{
data
},
@@ -155,35 +155,35 @@ export class LinkApiService implements LinkService {
public async updateLinkTableCol(data: LinkTableColData): Promise<void> {
axios.put<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkTableCol`,
'/api/link/updateLinkTableCol',
data,
);
}
public async insertLinkTableInfo(data: LinkTableFormData): Promise<void> {
await axios.post<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/insertLinkTableInfo`,
'/api/link/insertLinkTableInfo',
data
);
}
public async updateLinkTableInfo(data: LinkTableFormData): Promise<void> {
await axios.put<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkTableInfo`,
'/api/link/updateLinkTableInfo',
data
);
}
public async countLinkTblNm(tblNm: string): Promise<{count: number, tbl_sn: string}> {
const response = await axios.get<{count: number, tbl_sn: string}>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/countLinkTblNm/${tblNm}`,
`/api/link/countLinkTblNm/${tblNm}`,
);
return response.data;
}
public async updateLinkResultCode(linkSn: string): Promise<void> {
await axios.patch<void>(
`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/updateLinkResultCode/${linkSn}`,
`/api/link/updateLinkResultCode/${linkSn}`,
);
}
}
@@ -118,7 +118,7 @@ function DashboardPage() {
금일 신규 가입자
{data?.memberTodayCnt
? data.memberTodayCnt.toLocaleString()
: "-"}
: "0"}
명
</p>
</div>
@@ -141,7 +141,7 @@ function DashboardPage() {
</div>
<p className="mt-1 text-2xl opacity-80">
금일 +
{data?.pstTodayCnt ? data.pstTodayCnt.toLocaleString() : "-"}{" "}
{data?.pstTodayCnt ? data.pstTodayCnt.toLocaleString() : "0"}
등록
</p>
</div>
@@ -168,7 +168,7 @@ function DashboardPage() {
전일 대비 +
{data?.accessBefDayPer
? data.accessBefDayPer.toLocaleString()
: "-"}
: "0"}
%
</p>
</div>
@@ -70,7 +70,7 @@ function LinkParamsPage() {
// Link 목록 쿼리
const query = useQuery({
queryKey: [`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkList`, linkSearchParam],
queryKey: ['api/link/getLinkList', linkSearchParam],
queryFn: () => LinkApi.getLinkList({
...linkSearchParam,
page: pagination.pageIndex,
@@ -142,9 +142,10 @@ function LinkParamsPage() {
const { mutateAsync: deleteLinkVrbl } = useMutation({
mutationFn: async (data: string[]) => await LinkApi.deleteLinkVrbl(data),
onSuccess: async () => {
await queryClient.invalidateQueries({
await queryClient.refetchQueries({
queryKey: ['linkVrblList', selectedLink.linkSn]
});
setSelectedVrblIds([]);
alert('삭제되었습니다.');
}
@@ -67,7 +67,7 @@ function LinkTablePage() {
};
const query = useQuery({
queryKey: [`${process.env.NEXT_PUBLIC_LINK_BACKEND_API_HOST}/getLinkList`, linkSearchParam],
queryKey: ['/api/link/getLinkList', linkSearchParam],
queryFn: () => LinkApi.getLinkList({
...linkSearchParam,
page: pagination.pageIndex,
@@ -0,0 +1,33 @@
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import {
type ConnectionLogParams,
type ConnectionLogList,
type ConnectionStatisticsParams,
type ConnectionStatistics,
type ConnectionLogService,
} from "../model/connection-log-interface";
class ConnectionLogApiService implements ConnectionLogService {
async getConnectionLog(
params: ConnectionLogParams,
): Promise<ConnectionLogList> {
const response = await client.get<ConnectionLogList>(
`${ENDPOINT.CMS_SERVICE.CONNECTION_LOG}`,
{ params },
);
return response.data;
}
async getConnectionStatistics(
params: ConnectionStatisticsParams,
): Promise<ConnectionStatistics> {
const response = await client.get<ConnectionStatistics>(
`${ENDPOINT.CMS_SERVICE.CONNECTION_LOG}/stat`,
{ params },
);
return response.data;
}
}
export const ConnectionLogApi = new ConnectionLogApiService();
@@ -1 +0,0 @@
export { UserStatisticsApi } from "./user-statistics-service";
@@ -1,138 +0,0 @@
import {
type AccessLog,
type AccessLogParams,
type AccessLogService,
type PageableList,
} from "../model/user-statistics-interface";
// 목 데이터
const mockAccessLogs: AccessLog[] = [
{
no: 1,
accessTime: "2024-01-15 14:30:25",
accessIp: "192.168.1.100",
accessRegion: "서울특별시",
urlPath: "/index",
browser: "Chrome",
site: "SITE1",
accessType: "메인",
},
{
no: 2,
accessTime: "2024-01-15 14:28:15",
accessIp: "203.241.50.123",
accessRegion: "부산광역시",
urlPath: "/board/list",
browser: "Edge",
site: "SITE2",
accessType: "게시판",
},
{
no: 3,
accessTime: "2024-01-15 14:25:42",
accessIp: "175.223.45.67",
accessRegion: "대구광역시",
urlPath: "/statistics",
browser: "Safari",
site: "SITE1",
accessType: "통계",
},
{
no: 4,
accessTime: "2024-01-15 14:22:18",
accessIp: "211.252.87.45",
accessRegion: "인천광역시",
urlPath: "/contents/view",
browser: "Firefox",
site: "SITE3",
accessType: "컨텐츠",
},
{
no: 5,
accessTime: "2024-01-15 14:20:33",
accessIp: "121.254.12.89",
accessRegion: "광주광역시",
urlPath: "/search",
browser: "Chrome",
site: "SITE1",
accessType: "검색",
},
];
// 목 API 서비스
class UserStatisticsApiImpl implements AccessLogService {
async getAccessLogList(
params: AccessLogParams,
): Promise<PageableList<AccessLog>> {
// 실제 API 호출 대신 목 데이터 반환
const { page = 0, size = 10 } = params;
// 필터링 로직 (실제로는 서버에서 처리)
let filteredLogs = [...mockAccessLogs];
if (params.urlPath) {
filteredLogs = filteredLogs.filter((log) =>
log.urlPath.toLowerCase().includes(params.urlPath!.toLowerCase()),
);
}
if (params.accessIp) {
filteredLogs = filteredLogs.filter((log) =>
log.accessIp.includes(params.accessIp!),
);
}
if (params.accessRegion) {
filteredLogs = filteredLogs.filter((log) =>
log.accessRegion.includes(params.accessRegion!),
);
}
if (params.browser) {
filteredLogs = filteredLogs.filter(
(log) => log.browser.toLowerCase() === params.browser!.toLowerCase(),
);
}
if (params.siteId) {
filteredLogs = filteredLogs.filter((log) => log.site === params.siteId);
}
// 페이지네이션
const start = page * size;
const end = start + size;
const paginatedLogs = filteredLogs.slice(start, end);
// 목 응답 생성
return {
content: paginatedLogs,
pageable: {
pageNumber: page,
pageSize: size,
sort: {
empty: true,
sorted: false,
unsorted: true,
},
offset: page * size,
paged: true,
unpaged: false,
},
last: (page + 1) * size >= filteredLogs.length,
totalPages: Math.ceil(filteredLogs.length / size),
totalElements: filteredLogs.length,
size,
number: page,
sort: {
empty: true,
sorted: false,
unsorted: true,
},
first: page === 0,
numberOfElements: paginatedLogs.length,
empty: paginatedLogs.length === 0,
};
}
}
export const UserStatisticsApi = new UserStatisticsApiImpl();
@@ -1,148 +1,103 @@
import { type ChartData, type ChartOptions } from "chart.js";
// 일별 접속 현황 차트 데이터
export const monthlyStatisticsData = {
labels: [
"1일",
"2일",
"3일",
"4일",
"5일",
"6일",
"7일",
"8일",
"9일",
"10일",
"11일",
"12일",
"13일",
"14일",
"15일",
],
datasets: [
{
type: "bar" as const,
label: "페이지뷰",
data: [
850, 1000, 750, 750, 700, 750, 780, 800, 850, 900, 1200, 1700, 2300,
2100, 2600,
],
backgroundColor: "rgba(54, 162, 235, 0.8)",
order: 2,
},
{
type: "line" as const,
label: "신규 접속자",
data: [
700, 600, 500, 550, 500, 550, 500, 550, 600, 850, 1200, 1500, 1700,
2300, 2200,
],
borderColor: "rgba(255, 99, 132, 0.8)",
borderWidth: 2,
tension: 0.4,
pointRadius: 3,
order: 0,
},
{
type: "line" as const,
label: "총 접속자",
data: [
200, 300, 400, 500, 600, 500, 550, 500, 400, 500, 350, 800, 900, 1200,
1300,
],
borderColor: "rgba(75, 192, 192, 0.8)",
borderWidth: 2,
tension: 0.4,
pointRadius: 3,
order: 1,
},
],
};
export const monthlyStatisticsOptions: ChartOptions<"bar"> = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: "top" as const,
},
tooltip: {
mode: "index" as const,
intersect: false,
},
},
};
// 사이트별 접속자 차트 데이터
export const siteVisitorsData: ChartData<"bar"> = {
labels: ["SITE1", "SITE2", "SITE3", "SITE4", "SITE5"],
datasets: [
{
label: "사이트별 접속자",
data: [2500, 2000, 1500, 1200, 800],
backgroundColor: [
"rgba(54, 162, 235, 0.8)",
"rgba(153, 102, 255, 0.8)",
"rgba(255, 99, 132, 0.8)",
"rgba(255, 159, 64, 0.8)",
"rgba(255, 205, 86, 0.8)",
],
borderWidth: 1,
},
],
};
export const siteVisitorsOptions: ChartOptions<"bar"> = {
responsive: true,
maintainAspectRatio: false,
indexAxis: "y" as const,
plugins: {
legend: {
display: false,
},
},
};
// 브라우저별 접속자 차트 데이터
export const browserStatisticsData: ChartData<"doughnut"> = {
labels: ["Chrome", "Edge", "Safari", "Firefox", "Internet Explorer"],
datasets: [
{
data: [45, 25, 15, 10, 5],
backgroundColor: [
"rgba(54, 162, 235, 0.8)",
"rgba(153, 102, 255, 0.8)",
"rgba(255, 99, 132, 0.8)",
"rgba(255, 159, 64, 0.8)",
"rgba(255, 205, 86, 0.8)",
],
borderColor: [
"rgba(54, 162, 235, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 99, 132, 1)",
"rgba(255, 159, 64, 1)",
"rgba(255, 205, 86, 1)",
],
borderWidth: 1,
},
],
};
export const browserStatisticsOptions: ChartOptions<"doughnut"> = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: "bottom" as const,
},
},
};
import type { ChartData, ChartOptions } from "chart.js";
import { getCssVariableValue } from "@common/components";
import type { ConnectionStatistics } from "./connection-log-interface";
export const chartData = {
monthlyStatisticsData,
monthlyStatisticsOptions,
siteVisitorsData,
siteVisitorsOptions,
browserStatisticsData,
browserStatisticsOptions,
day: (
data: ConnectionStatistics,
): {
data: ChartData<"line">;
options: ChartOptions<"line">;
} => {
return {
data: {
labels: data.dayList.map((item) => item.dayYmd),
datasets: [
{
type: "line",
label: "접속자 수",
data: data.dayList.map((item) => item.accessCnt),
borderColor: getCssVariableValue("--chart-1"),
},
],
},
options: {
maintainAspectRatio: false,
scales: {
y: {
ticks: {
precision: 0,
},
},
},
},
};
},
site: (
data: ConnectionStatistics,
): {
data: ChartData<"bar">;
options: ChartOptions<"bar">;
} => {
return {
data: {
labels: data.siteList.map((item) => item.siteNm),
datasets: [
{
type: "bar",
label: "사이트별 접속자",
data: data.siteList.map((item) => item.accessCnt),
backgroundColor: data.siteList.map((_, index) =>
getCssVariableValue(`--chart-${(index % 5) + 1}`),
),
},
],
},
options: {
maintainAspectRatio: false,
indexAxis: "y",
scales: {
x: {
ticks: {
precision: 0,
},
},
},
plugins: {
legend: {
display: false,
},
},
},
};
},
browser: (
data: ConnectionStatistics,
): {
data: ChartData<"doughnut">;
options: ChartOptions<"doughnut">;
} => {
return {
data: {
labels: data.browserList.map((item) => item.wbsrKndNm),
datasets: [
{
type: "doughnut",
data: data.browserList.map((item) => item.accessCnt),
backgroundColor: data.browserList.map((_, index) =>
getCssVariableValue(`--chart-${(index % 5) + 1}`),
),
},
],
},
options: {
maintainAspectRatio: false,
plugins: {
legend: {
position: "bottom",
},
},
},
};
},
};
@@ -0,0 +1,72 @@
import type { PageableList, PageableParams } from "@/shared/model";
export interface ConnectionLogParams extends PageableParams {
keywordType?: string;
keyword?: string;
siteId?: string;
cntnIp?: string;
cntnRgn?: string;
wbsrKnd?: string;
urlPath?: string;
cntnDtStart?: string;
cntnDtEnd?: string;
}
export interface ConnectionLog {
cntnSn: number;
cntnDt: string;
cntnId: string;
cntnIp: string;
cntnRgn: string;
wbsrKnd: string;
menuCd: number;
siteId: string;
urlPath: string;
siteNm: string;
menuNm: string;
wbsrKndNm: string;
}
export interface ConnectionStatisticsParams {
keywordType?: string;
keyword?: string;
siteId?: string;
cntnIp?: string;
cntnRgn?: string;
wbsrKnd?: string;
urlPath?: string;
cntnDtStart?: string;
cntnDtEnd?: string;
}
interface DayConnectionStatistics {
dayYmd: string;
accessCnt: number;
}
interface SiteConnectionStatistics {
siteId: string;
siteNm: string;
accessCnt: number;
}
interface BrowserConnectionStatistics {
wbsrKnd: string;
wbsrKndNm: string;
accessCnt: number;
}
export interface ConnectionStatistics {
dayList: DayConnectionStatistics[];
siteList: SiteConnectionStatistics[];
browserList: BrowserConnectionStatistics[];
}
export type ConnectionLogList = PageableList<ConnectionLog>;
export interface ConnectionLogService {
getConnectionLog(params: ConnectionLogParams): Promise<ConnectionLogList>;
getConnectionStatistics(
params: ConnectionStatisticsParams,
): Promise<ConnectionStatistics>;
}
@@ -1,39 +1,46 @@
import { createColumnHelper } from "@tanstack/react-table";
import { type AccessLog } from "./user-statistics-interface";
import type { ColumnDef } from "@tanstack/react-table";
import type { ConnectionLog } from "./connection-log-interface";
import dayjs from "dayjs";
const columnHelper = createColumnHelper<AccessLog>();
export const columns = [
columnHelper.accessor("no", {
export const columns: ColumnDef<ConnectionLog>[] = [
{
header: "No",
cell: (info) => info.getValue(),
}),
columnHelper.accessor("accessTime", {
cell: ({ row, table }) => {
const totalRows = table.getRowCount();
const currentPage = table.getState().pagination.pageIndex;
const pageSize = table.getState().pagination.pageSize;
return totalRows - (currentPage * pageSize + row.index);
},
},
{
accessorKey: "cntnDt",
header: "접속일시",
cell: (info) => info.getValue(),
}),
columnHelper.accessor("accessIp", {
cell: ({ row }) => {
return dayjs(row.original.cntnDt).format("YYYY-MM-DD HH:mm:ss");
},
},
{
accessorKey: "cntnIp",
header: "접속IP",
cell: (info) => info.getValue(),
}),
columnHelper.accessor("accessRegion", {
},
{
accessorKey: "cntnRgn",
header: "접속지역",
cell: (info) => info.getValue(),
}),
columnHelper.accessor("urlPath", {
},
{
accessorKey: "urlPath",
header: "URL경로",
cell: (info) => info.getValue(),
}),
columnHelper.accessor("browser", {
},
{
accessorKey: "wbsrKndNm",
header: "브라우저",
cell: (info) => info.getValue(),
}),
columnHelper.accessor("site", {
},
{
accessorKey: "siteNm",
header: "사이트",
cell: (info) => info.getValue(),
}),
columnHelper.accessor("accessType", {
},
{
accessorKey: "menuNm",
header: "메뉴명",
cell: (info) => info.getValue(),
}),
},
];
@@ -1,56 +0,0 @@
export interface AccessLog {
no: number;
accessTime: string;
accessIp: string;
accessRegion: string;
urlPath: string;
browser: string;
site: string;
accessType: string;
}
export interface AccessLogParams {
page?: number;
size?: number;
urlPath?: string;
accessIp?: string;
accessRegion?: string;
browser?: string;
accessDateStart?: string;
accessDateEnd?: string;
siteId?: string;
sort?: string;
}
export interface AccessLogService {
getAccessLogList(params: AccessLogParams): Promise<PageableList<AccessLog>>;
}
export interface PageableList<T> {
content: T[];
pageable: {
pageNumber: number;
pageSize: number;
sort: {
empty: boolean;
sorted: boolean;
unsorted: boolean;
};
offset: number;
paged: boolean;
unpaged: boolean;
};
last: boolean;
totalPages: number;
totalElements: number;
size: number;
number: number;
sort: {
empty: boolean;
sorted: boolean;
unsorted: boolean;
};
first: boolean;
numberOfElements: number;
empty: boolean;
}
@@ -15,9 +15,8 @@ import {
Filler,
Legend,
Tooltip,
type ChartData,
} from "chart.js";
import { Bar, Doughnut } from "react-chartjs-2";
import { Bar, Doughnut, Line } from "react-chartjs-2";
import {
Button,
Input,
@@ -30,11 +29,13 @@ import {
} from "@common/components";
import { SiteSelect } from "@/entities/site";
import { useDataTable } from "@/shared/lib";
import { ENDPOINT } from "@/shared/config";
import { NoData } from "@/shared/ui/no-data";
import { InputDateRangePicker } from "@/shared/ui/input-date-range-picker";
import { UserStatisticsApi } from "../api";
import { ConnectionLogApi } from "../api/connection-log-service";
import { chartData } from "../model/chart-data";
import { columns } from "../model/table-columns";
import { type AccessLogParams } from "../model/user-statistics-interface";
import type { ConnectionStatisticsParams } from "../model/connection-log-interface";
ChartJS.register(
CategoryScale,
@@ -65,25 +66,31 @@ function UserStatisticsPage() {
});
const [keywordType, setKeywordType] = useState("");
const [keyword, setKeyword] = useState("");
const [siteId, setSiteId] = useState("");
const [presetDateRange, setPresetDateRange] = useState("1W");
const [dateRange, setDateRange] = useState<DateRange>(defaultDateRange);
const [searchParams, setSearchParams] = useState<AccessLogParams>({
urlPath: "",
accessIp: "",
accessRegion: "",
browser: "",
accessDateStart: dayjs().subtract(7, "day").format("YYYY-MM-DD"),
accessDateEnd: dayjs().format("YYYY-MM-DD"),
sort: "accessTime,desc",
const [searchParams, setSearchParams] = useState<ConnectionStatisticsParams>({
keywordType: "",
keyword: "",
siteId: "",
cntnDtStart: dayjs(defaultDateRange.from).format("YYYY-MM-DD"),
cntnDtEnd: dayjs(defaultDateRange.to).format("YYYY-MM-DD"),
});
const query = useQuery({
queryKey: ["user-statistics", searchParams, pagination],
queryKey: [ENDPOINT.CMS_SERVICE.CONNECTION_LOG, searchParams],
queryFn: () =>
UserStatisticsApi.getAccessLogList({
ConnectionLogApi.getConnectionLog({
...searchParams,
}),
placeholderData: keepPreviousData,
});
const { data: connectionStatisticsData } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.CONNECTION_LOG, searchParams],
queryFn: () =>
ConnectionLogApi.getConnectionStatistics({
...searchParams,
page: pagination.pageIndex,
size: pagination.pageSize,
}),
placeholderData: keepPreviousData,
});
@@ -139,54 +146,30 @@ function UserStatisticsPage() {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setPagination({
...pagination,
pageIndex: 0,
});
// 검색 조건에 따라 검색 파라미터 설정
const params: AccessLogParams = {
sort: "accessTime,desc",
accessDateStart: dateRange.from
const params: ConnectionStatisticsParams = {
keywordType,
keyword,
siteId,
cntnDtStart: dateRange.from
? dayjs(dateRange.from).format("YYYY-MM-DD")
: "",
accessDateEnd: dateRange.to
? dayjs(dateRange.to).format("YYYY-MM-DD")
: "",
cntnDtEnd: dateRange.to ? dayjs(dateRange.to).format("YYYY-MM-DD") : "",
};
// 검색어 타입에 따라 파라미터 설정
switch (keywordType) {
case "urlPath":
params.urlPath = keyword;
break;
case "ip":
params.accessIp = keyword;
break;
case "region":
params.accessRegion = keyword;
break;
case "browser":
params.browser = keyword;
break;
}
setSearchParams(params);
};
const handleReset = () => {
setKeywordType("");
setKeyword("");
setSiteId("");
setDateRange(defaultDateRange);
setPresetDateRange("1W");
setSearchParams({
urlPath: "",
accessIp: "",
accessRegion: "",
browser: "",
accessDateStart: dayjs().subtract(7, "day").format("YYYY-MM-DD"),
accessDateEnd: dayjs().format("YYYY-MM-DD"),
sort: "accessTime,desc",
keywordType: "",
keyword: "",
siteId: "",
cntnDtStart: dayjs(defaultDateRange.from).format("YYYY-MM-DD"),
cntnDtEnd: dayjs(defaultDateRange.to).format("YYYY-MM-DD"),
});
};
@@ -210,7 +193,11 @@ function UserStatisticsPage() {
setDateRange={handleDateRangeChange}
/>
<Label className="ml-4 mr-2 text-label">사이트</Label>
<SiteSelect enabledAllSite className="w-[16rem]" />
<SiteSelect
className="w-[16rem]"
value={siteId}
onValueChange={(value) => setSiteId(value)}
/>
<Label className="ml-4 mr-2 text-label">검색</Label>
<Select
value={keywordType}
@@ -221,9 +208,9 @@ function UserStatisticsPage() {
</SelectTrigger>
<SelectContent>
<SelectItem value="urlPath">URL경로</SelectItem>
<SelectItem value="ip">접속IP</SelectItem>
<SelectItem value="region">접속지역</SelectItem>
<SelectItem value="browser">브라우저</SelectItem>
<SelectItem value="cntnIp">접속IP</SelectItem>
<SelectItem value="cntnRgn">접속지역</SelectItem>
<SelectItem value="wbsrKnd">브라우저</SelectItem>
</SelectContent>
</Select>
<Input
@@ -245,45 +232,44 @@ function UserStatisticsPage() {
</form>
</div>
{/* 차트 영역 */}
<div className="grid grid-cols-2">
{/* 일별 접속 현황 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-xl font-medium">일별 접속 현황</h3>
<h3 className="text-2xl font-medium">일별 접속 현황</h3>
</div>
<div className="h-96 p-4">
<Bar
data={chartData.monthlyStatisticsData as ChartData<"bar">}
options={chartData.monthlyStatisticsOptions}
/>
{connectionStatisticsData?.dayList?.length ? (
<Line {...chartData.day(connectionStatisticsData)} />
) : (
<NoData />
)}
</div>
</div>
<div className="grid grid-cols-2">
{/* 사이트별 접속자 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-xl font-medium">사이트별 접속자</h3>
<h3 className="text-2xl font-medium">사이트별 접속자</h3>
</div>
<div className="h-96 p-4">
<Bar
data={chartData.siteVisitorsData}
options={chartData.siteVisitorsOptions}
/>
{connectionStatisticsData?.siteList?.length ? (
<Bar {...chartData.site(connectionStatisticsData)} />
) : (
<NoData />
)}
</div>
</div>
{/* 브라우저별 접속자 */}
<div className="card card-border">
<div className="card-header">
<h3 className="text-xl font-medium">브라우저별 접속자</h3>
<h3 className="text-2xl font-medium">브라우저별 접속자</h3>
</div>
<div className="h-96 p-4">
<Doughnut
data={chartData.browserStatisticsData}
options={chartData.browserStatisticsOptions}
/>
{connectionStatisticsData?.browserList?.length ? (
<Doughnut {...chartData.browser(connectionStatisticsData)} />
) : (
<NoData />
)}
</div>
</div>
</div>
+1
View File
@@ -55,6 +55,7 @@ export const ENDPOINT = {
MANAGER_IP: "/cms-service/api/v1/mgrip",
APILOG: "/cms-service/api/v1/api-logs",
SITE_AUTHORITY: "/cms-service/api/v1/site-authrt",
CONNECTION_LOG: "/cms-service/api/v1/cntnlog",
},
BOARD_SERVICE: {
BBS: "/board-service/api/v1/bbs",
+2 -1
View File
@@ -25,6 +25,7 @@ function PostAction({ children, handleDelete }: PostActionProps) {
const { prompt } = useSelectPrompt(selectData);
const bbsInfo = useMenuStore((state) => state.bbsInfo);
const userInfo = useUserStore((state) => state.userInfo);
const postPageLink = `/bbs/${bbsInfo?.bbsTypeCd.toLowerCase()}/${bbsInfo?.bbsId}`;
const onDelete = async () => {
const { resolved, value } = await prompt("삭제 사유를 입력해주세요.");
@@ -64,7 +65,7 @@ function PostAction({ children, handleDelete }: PostActionProps) {
size="lg"
color="white"
type="button"
onClick={() => router.back()}
onClick={() => router.push(postPageLink)}
>
목록
</Button>
+12 -10
View File
@@ -62,10 +62,9 @@ const Map = () => {
Object.keys(item).length > 0 &&
!prev.some((f) => f.pbnstRuseFcltId === item.pbnstRuseFcltId)
);
console.log(newItems)
console.log(newItems);
return [...prev, ...newItems];
});
} catch (error) {
console.error("데이터 불러오기 실패:", error);
}
@@ -232,14 +231,6 @@ const Map = () => {
return (
<>
<SearchBar
setHasuPk={(hasuPk: any) => {
if (hasuPk) {
setSelectDataPk(hasuPk);
}
}}
onApply={onApply}
/>
<div className="bg-container">
<Gis
treeData={treeData}
@@ -257,6 +248,17 @@ const Map = () => {
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={onCheckedLayersChange}
imgVisble={false}
searchBar={(props: any) => (
<SearchBar
setHasuPk={(hasuPk: any) => {
if (hasuPk) {
setSelectDataPk(hasuPk);
}
}}
onApply={onApply}
{...props}
/>
)}
/>
</div>
<SelectedFcltList
@@ -16,7 +16,6 @@ export class LoginApiService implements LoginService {
public async login(payload: ILogin): Promise<void> {
try {
console.log(' ENDPOINT.USER_SERVICE.LOGIN ', ENDPOINT.USER_SERVICE.LOGIN)
const response = await fetch( PROXY_HOST+ ENDPOINT.USER_SERVICE.LOGIN, {
method: "POST",
body: JSON.stringify({
+1
View File
@@ -2,6 +2,7 @@ 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://con.mind-one.co.kr:11082/api/v1
#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
+2 -1
View File
@@ -1,7 +1,8 @@
NEXT_PUBLIC_SITE_ID = FO
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
+1
View File
@@ -15,6 +15,7 @@ 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://con.mind-one.co.kr:11082/api/v1
#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
@@ -97,10 +97,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
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'){
if(flowPanel === '2'){
const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10;
} else if(flowPanel === '3'){
@@ -122,8 +119,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
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);
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (rainEffectDay ===1);
}
});
} else if(tabName.includes("_chuncheon")) {
@@ -132,8 +128,8 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
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;
const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay;
return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && rainEffectDay==0;
});
} else {
filteredData = searchList.filter((item) => {
@@ -144,7 +140,6 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
return itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly;
});
}
setCopySearchList(filteredData);
setStandSearchList(filteredData);
}, [searchList, searchYear, tabName, flowPanel]);
@@ -15,7 +15,6 @@ export default function DrainageEquipment({searchYear = '', fcltyList = []}: Dra
const {
Common,
DrainageEquipment,
searchDrainageEquipment,
} = useFoStore((state) => state);
const {
@@ -35,11 +34,10 @@ export default function DrainageEquipment({searchYear = '', fcltyList = []}: Dra
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]);
}, [fcltyList, isInit, searchYear, tableData, hasSearched, prevFacilityCode]);
// 연도가 바뀌면 hasSearched를 false로 리셋
useEffect(() => {
@@ -5,6 +5,7 @@ import { ContentsDiv, UiModal, UiTable } from "@common/business_components";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@common/components";
import { useEffect, useState } from "react";
import DashBoardChartModal from "./modal/page";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export type facilityInfoProps = {
searchYear?: string;
@@ -56,7 +57,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
PlanFclty,
OperationStatus,
searchOperationStatus,
searchPlanInfo
searchPlanInfo,
} = useFoStore((state) => state);
const [modalItem, setModalItem] = useState<{item: string, period: string, title: string, waterQlty: string} | null>(null);
@@ -77,13 +78,18 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
const {
upHeadListPlanFclty,
planFcltyList,
planYearList
planYearList,
waterUsage1,
waterUsage2,
waterUsage3,
isLoadingPlanFclty
} = PlanFclty;
// 그리드 관련
const {
upHeadListOperationStatus,
operationalStatusList
operationalStatusList,
isLoadingOperationStatus
} = OperationStatus;
const closeModal = () => {
@@ -147,20 +153,27 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
searchPlanInfo(searchYear, fcltyList[0].bscFctCd);
setHasSearched(true);
setPrevFacilityCode(fcltyList[0].bscFctCd);
}
}, [isInit, searchOperationStatus, searchYear, fcltyList, hasSearched, prevFacilityCode, searchPlanInfo]);
// waterUsage 값들이 로드된 후에 테이블 데이터 업데이트
useEffect(() => {
if (waterUsage1 !== '' && waterUsage2 !== '' && waterUsage3 !== '') {
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;
el['provisionalApproval'] = waterUsage3;
} else if (index === 7) {
el['item'] = (Number(searchYear)-1).toString();
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
el['provisionalApproval'] = waterUsage2;
} else if (index === 8) {
el['item'] = (Number(searchYear)-0).toString();
el['provisionalApproval'] = Number(fcltyList[0]?.fcltyCpc)* 0.6;
el['provisionalApproval'] = waterUsage1;
}
});
console.log('planFcltyList :', planFcltyList);
}
}, [isInit, searchOperationStatus, searchYear, fcltyList, hasSearched, prevFacilityCode, searchPlanInfo, planFcltyList]);
}, [waterUsage1, waterUsage2, waterUsage3, searchYear, planFcltyList]);
// 연도가 바뀌면 hasSearched를 false로 리셋
useEffect(() => {
setHasSearched(false);
@@ -190,6 +203,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
<>
<UiTable headName={""} tableData={mappedTableData} headlist={upHeadListFclty} pageSize={0} total={0} cellClick={ undefined } onPageChange={() => { } } />
<ContentsDiv>
<LoadingOverlay isLoading={isLoadingPlanFclty} />
<div className="grid grid-cols-12 gap-1">
<div className="col-span-5">
<Table variant="secondary">
@@ -211,8 +225,8 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
:(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)
?<TableCell colSpan={6} className="text-right border border-[var(--border)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{Math.round((Number(waterUsage1)+Number(waterUsage2)+Number(waterUsage3))/3 * 100)/100}</TableCell>
:((head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') )
?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>
@@ -225,39 +239,40 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
</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={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'rdi'&&index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}></TableCell>:
(head.id === 'rdiRain'&&index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el['rdiRain']}</TableCell>:
(head.id === 'rdiRain'&&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>
<LoadingOverlay isLoading={isLoadingOperationStatus} />
<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={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'rdi'&&index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
(head.id === 'rdiRain'&&index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el['rdiRain']}</TableCell>:
(head.id === 'rdiRain'&&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>
@@ -5,6 +5,7 @@ import { CHART_FORM, type ChartConfig, ContentsDiv, MainChart } from "@common/bu
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";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
type facilityInfoProps = {
searchYear?: string;
@@ -44,6 +45,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
chart_inflTn,
chart_efflTn,
chart_inflBod,
isLoadingMainGraph,
} = MainGraph;
/**
@@ -179,6 +181,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
return (
<>
<ContentsDiv>
<LoadingOverlay isLoading={isLoadingMainGraph} />
<ListDiv className="h-[300px]">
<Card className="h-full">
<CardContent className="h-full">
+5 -3
View File
@@ -57,8 +57,7 @@ export default function DashBoard() {
/******************선택된 데이터******************/
// 연도
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
const [searchYear, setSearchYear] = useState<string>('2023');
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || '0');
// 시설명
const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({
bscFctCd: '26260PB001R',
@@ -280,8 +279,11 @@ export default function DashBoard() {
trtFrfNm: '표준활성슬러지법, MLE, MBR',
efflWqltStndrdNm: '500톤 이상(Ⅳ지역)'
});
setSearchYear('2023');
setSearchYear(selectSearchYear[0]?.val || '0');
searchFcltyList.bscFctNm = '수영';
setSidoValue('0');
setSigunValue('0');
}
const searchVal = () => {
@@ -45,6 +45,7 @@ export default function RainManageTab({searchYear = '', fcltyList = []}: facilit
}, [searchYear]);
return (
<div>
<UiTable
headName=""
tableData={rainManageList}
@@ -55,5 +56,7 @@ export default function RainManageTab({searchYear = '', fcltyList = []}: facilit
onPageChange={() => {}}
>
</UiTable>
<span className="text-2xl font-bold text-gray-500">☞ 일수에 강우영향일 포함됨</span>
</div>
)
}
@@ -5,6 +5,7 @@ import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, Selec
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import PrecipitationModal from "./modal/page";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function FacilityPrecipitation() {
const {Common
@@ -39,7 +40,8 @@ export default function FacilityPrecipitation() {
upHeadList3,
excelList,
facilityPrecipitation,
facilityPrecipitationCount
facilityPrecipitationCount,
isLoading,
} = FacilityPrecipitation;
const {
@@ -81,8 +83,7 @@ export default function FacilityPrecipitation() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
/**
* 페이지 함수
@@ -126,9 +127,9 @@ export default function FacilityPrecipitation() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchFacilityPrecipitationList(1, 10, searchYear || "0");
searchFacilityPrecipitationList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchFacilityPrecipitationList, searchYear]);
}, [isInit, initializeCommonData, searchFacilityPrecipitationList]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -227,6 +228,7 @@ export default function FacilityPrecipitation() {
initClick={resetVal}
ref={ref} isAdmin={false} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
@@ -66,11 +66,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let maxefflWqltToc = 0;
let maxEfflWqltSs = 0;
let maxInflAssctAftWqltBod = 0;
let maxInflAssctAftWqltTn = 0;
let maxinflAssctBfrWqltBod = 0;
let maxinflAssctBfrWqltTn = 0;
let maxInflAssctBfrWqltTp = 0;
let maxInflAssctAftWqltToc = 0;
let maxInflAssctAftWqltSs = 0;
let maxinflAssctBfrWqltToc = 0;
let maxinflAssctBfrWqltSs = 0;
let maxTpInflWqltBod = 0;
let maxTpInflWqltTp = 0;
@@ -83,11 +83,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let minefflWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltToc) : 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 mininflAssctBfrWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltBod) : 0;
let mininflAssctBfrWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltTn) : 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 mininflAssctBfrWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltToc) : 0;
let mininflAssctBfrWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltSs) : 0;
let minTpInflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltBod) : 0;
let minTpInflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltTp) : 0;
@@ -100,11 +100,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
let avgefflWqltToc = 0;
let avgEfflWqltSs = 0;
let avgInflAssctAftWqltBod = 0;
let avgInflAssctAftWqltTn = 0;
let avginflAssctBfrWqltBod = 0;
let avginflAssctBfrWqltTn = 0;
let avgInflAssctBfrWqltTp = 0;
let avgInflAssctAftWqltToc = 0;
let avgInflAssctAftWqltSs = 0;
let avginflAssctBfrWqltToc = 0;
let avginflAssctBfrWqltSs = 0;
let avgTpInflWqltBod = 0;
let avgTpInflWqltTp = 0;
@@ -118,11 +118,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
const efflWqltToc = parseNumber(item.efflWqltToc);
const efflWqltSs = parseNumber(item.efflWqltSs);
const inflAssctAftWqltBod = parseNumber(item.inflAssctAftWqltBod);
const inflAssctAftWqltTn = parseNumber(item.inflAssctAftWqltTn);
const inflAssctBfrWqltBod = parseNumber(item.inflAssctBfrWqltBod);
const inflAssctBfrWqltTn = parseNumber(item.inflAssctBfrWqltTn);
const inflAssctBfrWqltTp = parseNumber(item.inflAssctBfrWqltTp);
const inflAssctAftWqltToc = parseNumber(item.inflAssctAftWqltToc);
const inflAssctAftWqltSs = parseNumber(item.inflAssctAftWqltSs);
const inflAssctBfrWqltToc = parseNumber(item.inflAssctBfrWqltToc);
const inflAssctBfrWqltSs = parseNumber(item.inflAssctBfrWqltSs);
const tpInflWqltBod = parseNumber(item.tpInflWqltBod);
@@ -136,11 +136,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
maxefflWqltToc = Math.max(maxefflWqltToc, efflWqltToc);
maxEfflWqltSs = Math.max(maxEfflWqltSs, efflWqltSs);
maxInflAssctAftWqltBod = Math.max(maxInflAssctAftWqltBod, inflAssctAftWqltBod);
maxInflAssctAftWqltTn = Math.max(maxInflAssctAftWqltTn, inflAssctAftWqltTn);
maxinflAssctBfrWqltBod = Math.max(maxinflAssctBfrWqltBod, inflAssctBfrWqltBod);
maxinflAssctBfrWqltTn = Math.max(maxinflAssctBfrWqltTn, inflAssctBfrWqltTn);
maxInflAssctBfrWqltTp = Math.max(maxInflAssctBfrWqltTp, inflAssctBfrWqltTp);
maxInflAssctAftWqltToc = Math.max(maxInflAssctAftWqltToc, inflAssctAftWqltToc);
maxInflAssctAftWqltSs = Math.max(maxInflAssctAftWqltSs, inflAssctAftWqltSs);
maxinflAssctBfrWqltToc = Math.max(maxinflAssctBfrWqltToc, inflAssctBfrWqltToc);
maxinflAssctBfrWqltSs = Math.max(maxinflAssctBfrWqltSs, inflAssctBfrWqltSs);
maxTpInflWqltBod = Math.max(maxTpInflWqltBod, tpInflWqltBod);
maxTpInflWqltTp = Math.max(maxTpInflWqltTp, tpInflWqltTp);
@@ -153,11 +153,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
minefflWqltToc = Math.min(minefflWqltToc, efflWqltToc);
minEfflWqltSs = Math.min(minEfflWqltSs, efflWqltSs);
minInflAssctAftWqltBod = Math.min(minInflAssctAftWqltBod, inflAssctAftWqltBod);
minInflAssctAftWqltTn = Math.min(minInflAssctAftWqltTn, inflAssctAftWqltTn);
mininflAssctBfrWqltBod = Math.min(mininflAssctBfrWqltBod, inflAssctBfrWqltBod);
mininflAssctBfrWqltTn = Math.min(mininflAssctBfrWqltTn, inflAssctBfrWqltTn);
minInflAssctBfrWqltTp = Math.min(minInflAssctBfrWqltTp, inflAssctBfrWqltTp);
minInflAssctAftWqltToc = Math.min(minInflAssctAftWqltToc, inflAssctAftWqltToc);
minInflAssctAftWqltSs = Math.min(minInflAssctAftWqltSs, inflAssctAftWqltSs);
mininflAssctBfrWqltToc = Math.min(mininflAssctBfrWqltToc, inflAssctBfrWqltToc);
mininflAssctBfrWqltSs = Math.min(mininflAssctBfrWqltSs, inflAssctBfrWqltSs);
minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod);
minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp);
@@ -170,11 +170,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
avgefflWqltToc += efflWqltToc;
avgEfflWqltSs += efflWqltSs;
avgInflAssctAftWqltBod += inflAssctAftWqltBod;
avgInflAssctAftWqltTn += inflAssctAftWqltTn;
avginflAssctBfrWqltBod += inflAssctBfrWqltBod;
avginflAssctBfrWqltTn += inflAssctBfrWqltTn;
avgInflAssctBfrWqltTp += inflAssctBfrWqltTp;
avgInflAssctAftWqltToc += inflAssctAftWqltToc;
avgInflAssctAftWqltSs += inflAssctAftWqltSs;
avginflAssctBfrWqltToc += inflAssctBfrWqltToc;
avginflAssctBfrWqltSs += inflAssctBfrWqltSs;
avgTpInflWqltBod += tpInflWqltBod;
avgTpInflWqltTp += tpInflWqltTp;
@@ -190,11 +190,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
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),
inflAssctBfrWqltBod: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltBod / filteredData.length * 10) / 10).toFixed(1),
inflAssctBfrWqltTn: filteredData.length==0?'0.000':(Math.round(avginflAssctBfrWqltTn / 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),
inflAssctBfrWqltToc: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltToc / filteredData.length * 10) / 10).toFixed(1),
inflAssctBfrWqltSs: filteredData.length==0?'0.0':(Math.round(avginflAssctBfrWqltSs / filteredData.length * 10) / 10).toFixed(1),
bscFctCd: "",
bscFctNm: "",
lclgvrnmntNm: "",
@@ -213,11 +213,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
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',
inflAssctBfrWqltBod : Math.round(maxinflAssctBfrWqltBod * 10) / 10?(Math.round(maxinflAssctBfrWqltBod * 10) / 10).toFixed(1):'0.0',
inflAssctBfrWqltTn : Math.round(maxinflAssctBfrWqltTn * 1000) / 1000?(Math.round(maxinflAssctBfrWqltTn * 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',
inflAssctBfrWqltToc : Math.round(maxinflAssctBfrWqltToc * 10) / 10?(Math.round(maxinflAssctBfrWqltToc * 10) / 10).toFixed(1):'0.0',
inflAssctBfrWqltSs : Math.round(maxinflAssctBfrWqltSs * 10) / 10?(Math.round(maxinflAssctBfrWqltSs * 10) / 10).toFixed(1):'0.0',
bscFctCd: "",
bscFctNm: "",
lclgvrnmntNm: "",
@@ -236,11 +236,11 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
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',
inflAssctBfrWqltBod : Math.round(mininflAssctBfrWqltBod * 10) / 10?(Math.round(mininflAssctBfrWqltBod * 10) / 10).toFixed(1) : '0.0',
inflAssctBfrWqltTn : Math.round(mininflAssctBfrWqltTn * 1000) / 1000?(Math.round(mininflAssctBfrWqltTn * 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',
inflAssctBfrWqltToc : Math.round(mininflAssctBfrWqltToc * 10) / 10?(Math.round(mininflAssctBfrWqltToc * 10) / 10).toFixed(1) : '0.0',
inflAssctBfrWqltSs : Math.round(mininflAssctBfrWqltSs * 10) / 10?(Math.round(mininflAssctBfrWqltSs * 10) / 10).toFixed(1) : '0.0',
bscFctCd: "",
bscFctNm: "",
lclgvrnmntNm: "",
@@ -293,10 +293,10 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe
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,
"유입BOD(mg/L)": item.inflAssctBfrWqltBod,
"유입TOC(COD)(mg/L)": item.inflAssctBfrWqltToc,
"유입SS(mg/L)": item.inflAssctBfrWqltSs,
"유입TN(mg/L)": item.inflAssctBfrWqltTn,
"유입TP(mg/L)": item.inflAssctBfrWqltTp,
"유출BOD(mg/L)": item.efflWqltBod,
"유출TOC(COD)(mg/L)": item.efflWqltToc,
+6 -4
View File
@@ -7,6 +7,7 @@ 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";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function ProcessFacilitySearch() {
const { Common
@@ -36,7 +37,8 @@ export default function ProcessFacilitySearch() {
upHeadList3,
facilityWaterQltyList,
facilityWaterQltyCount,
excelList
excelList,
isLoading,
} = FacilityWaterQltyMain;
const mainList: FacilityWaterQltyProps[] = facilityWaterQltyList || [];
@@ -48,8 +50,7 @@ export default function ProcessFacilitySearch() {
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 [searchYearValue, setSearchYearValue] = useState<string>("2023");
const [searchYearValue, setSearchYearValue] = useState<string>(selectSearchYear[0]?.val || "0");
const [fcltCpct, setFcltCpct] = useState<string>("0");
// 모달 상태 추가
@@ -133,7 +134,7 @@ export default function ProcessFacilitySearch() {
initializeCommonData();
searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchFacilityWaterQltyList, selectSearchYear]);
}, [isInit, initializeCommonData, searchFacilityWaterQltyList]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -187,6 +188,7 @@ export default function ProcessFacilitySearch() {
initClick={resetVal}
ref={ref} isAdmin={false} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
@@ -52,7 +52,6 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
return Number(value.replace(/,/g, ''));
};
console.log('filteredData : ', filteredData);
let maxtotInflAmnt = 0;
let maxinflAmnt = 0;
let maxsumFlow = 0;
+8 -7
View File
@@ -6,6 +6,7 @@ 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";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function ProcessFacilitySearch() {
const {Common
@@ -42,15 +43,15 @@ export default function ProcessFacilitySearch() {
upHeadList3,
flowRateList,
flowRateCount,
excelList
excelList,
isLoading,
} = 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 [searchYearValue, setSearchYearValue] = useState<string>("2023");
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);
@@ -89,9 +90,9 @@ export default function ProcessFacilitySearch() {
setWidthSize("w-[120%]");
setUpheadList(upHeadList1)
// 상태값 설정
setSearchYearValue(selectSearchYear[0]?.val || "0");
setFcltCpct(selectUpdownData[0]?.val || "0");
setOperationValue(selectOperationData[0]?.val || "0");
setSearchYearValue(selectSearchYear[0]?.val || "0");
// SearchInputSelect 초기화
setFcltyName("");
if (searchInputRef.current) {
@@ -126,11 +127,10 @@ export default function ProcessFacilitySearch() {
// 시도 데이터 초기화
useEffect(() => {
if(!isInit) {
console.log('searchYearValue', searchYearValue, isInit);
initializeCommonData();
searchFlowRateList(1, 10, searchYearValue || "0");
searchFlowRateList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchFlowRateList, searchYearValue]);
}, [isInit, initializeCommonData, searchFlowRateList]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -189,6 +189,7 @@ export default function ProcessFacilitySearch() {
initClick={resetVal}
ref={ref} isAdmin={false} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
+21 -7
View File
@@ -13,7 +13,11 @@ interface FeatureData {
}
interface MapInstance {
getLayers: () => { getArray: () => Array<{ getSource?: () => { getFeatureById?: (id: string) => FeatureData | null } }> };
getLayers: () => {
getArray: () => Array<{
getSource?: () => { getFeatureById?: (id: string) => FeatureData | null };
}>;
};
getView: () => { fit: (extent: number[], options: object) => void };
}
@@ -26,20 +30,20 @@ const Map = () => {
const fetchData = async () => {
try {
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}/v1/map`
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 파싱
const data = await response.json(); // 여기서 json 파싱
setTreeData(data); // 데이터 설정
} catch (error) {
console.error("데이터 불러오기 실패:", error);
@@ -60,7 +64,12 @@ const Map = () => {
}
// 항상 같은 select 객체 사용
const select = (GisApp.Module.select as unknown) as { resetSelectedFeature: () => void; selectFeature: (feature: FeatureData, selected: boolean) => void } | undefined;
const select = GisApp.Module.select as unknown as
| {
resetSelectedFeature: () => void;
selectFeature: (feature: FeatureData, selected: boolean) => void;
}
| undefined;
if (!select) return;
// 1. 기존 선택 초기화
@@ -115,9 +124,12 @@ const Map = () => {
};
// onCheckedLayersChange handler
const handleCheckedLayersChange = (checkedIds: string[], checkedNodesData: unknown[]) => {
const handleCheckedLayersChange = (
checkedIds: string[],
checkedNodesData: unknown[]
) => {
// Handle checked layers change if needed
console.log('Checked layers changed:', checkedIds, checkedNodesData);
console.log("Checked layers changed:", checkedIds, checkedNodesData);
};
return (
@@ -137,6 +149,8 @@ const Map = () => {
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
imgVisble={false}
searchBar={undefined}
/>
</div>
);
+8 -5
View File
@@ -4,6 +4,7 @@ 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";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function PlanSewage() {
const {Common
@@ -37,7 +38,8 @@ export default function PlanSewage() {
upHeadList3,
planSewageList,
planSewageCount,
excelList
excelList,
isLoading,
} = PlanSewage;
const ref = useRef<ReturnType>({
@@ -70,8 +72,7 @@ export default function PlanSewage() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
/**
* 페이지 함수
@@ -92,6 +93,7 @@ export default function PlanSewage() {
input.value = "";
}
}
searchPlanSewageList(1, 10, selectSearchYear[0]?.val || "0", ref.current.partValue);
}
/**
@@ -100,9 +102,9 @@ export default function PlanSewage() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchPlanSewageList(1, 10, searchYear, ref.current.partValue);
searchPlanSewageList(1, 10, selectSearchYear[0]?.val || "0", ref.current.partValue);
}
}, [isInit, initializeCommonData, searchYear, searchPlanSewageList]);
}, [isInit, initializeCommonData, searchPlanSewageList]);
useEffect(() => {
console.log('excelList' , excelList);
@@ -187,6 +189,7 @@ export default function PlanSewage() {
initClick={resetVal}
ref={ref} isAdmin={false}/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
+7 -4
View File
@@ -4,6 +4,7 @@ import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SelectBox, Title,
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import ProcessFacilityInfoModal from "./modal/page";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function ProcessArea() {
const {Common,
@@ -39,7 +40,8 @@ export default function ProcessArea() {
upHeadList1,
processAreaList,
processAreaCount,
excelList
excelList,
isLoading,
} = ProcessArea;
const mainList: Record<string, unknown>[] = processAreaList || [];
@@ -84,7 +86,7 @@ export default function ProcessArea() {
}
}
setSearchYearValue(selectSearchYear[0]?.val || "0");
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val);
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val || "0");
}
// 셀 클릭 시 모달 표시
@@ -104,9 +106,9 @@ export default function ProcessArea() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val);
searchProcessAreaList(1, 10, '', '', selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchProcessAreaList, selectSearchYear]);
}, [isInit, initializeCommonData, searchProcessAreaList]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -152,6 +154,7 @@ export default function ProcessArea() {
isAdmin={true}
/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
+4 -1
View File
@@ -5,6 +5,7 @@ import { ContentsDiv, downloadExcel, MainDiv, SearchBaseForm, SearchInput, Selec
import ListDiv from "@common/business_components/ui/list_div";
import { useCallback, useEffect, useRef, useState } from "react";
import ProcessFacilityInfoModal from "./modal/page";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function ProcessFacilitySearch() {
const {Common
@@ -63,7 +64,8 @@ export default function ProcessFacilitySearch() {
upHeadList1,
upHeadList2,
upHeadList3,
excelList
excelList,
isLoading,
} = ProcessFacilityList;
const processFacilityList = ProcessFacilityList?.processFacilityList || [];
@@ -262,6 +264,7 @@ export default function ProcessFacilitySearch() {
initClick={resetVal}
ref={ref} isAdmin={false} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<div className="h-full w-full overflow-x-scroll">
<div className={widthSize}>
<UiTable
+8 -2
View File
@@ -4,6 +4,7 @@ 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";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function Rdi() {
const {Common
@@ -38,6 +39,7 @@ export default function Rdi() {
rdiList,
rdiCount,
excelList,
isLoading,
} = Rdi;
const ref = useRef<ReturnType>({
@@ -70,6 +72,10 @@ export default function Rdi() {
// 조회기간
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
useEffect(() => {
console.log(isLoading);
}, [isLoading]);
/**
* 페이지 함수
*/
@@ -91,7 +97,6 @@ export default function Rdi() {
}
}
searchRdiList(1, 10, selectSearchYear[0]?.val || "0");
}
/**
@@ -102,7 +107,7 @@ export default function Rdi() {
initializeCommonData();
searchRdiList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchRdiList, selectSearchYear]);
}, [isInit, initializeCommonData, searchRdiList]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -187,6 +192,7 @@ export default function Rdi() {
initClick={resetVal}
ref={ref} isAdmin={false} />
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
@@ -30,6 +30,11 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd
setDetailList(gridListSewageOccurDetail);
}, [gridListSewageOccurDetail]);
useEffect(() => {
searchSewageOccurDetailList(props.facilityCd, validSearchYear, startYearMonth, endYearMonth);
}, [startYearMonth, endYearMonth]);
return (
<>
<ListDiv className="!h-[80px] !mt-10">
@@ -57,6 +62,7 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd
}}
selectClass="ml-5 w-[100px]"
startYear={1900}
yearReadOnly={true}
/>~
<DateMonthPicker
field={{
@@ -74,6 +80,7 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd
}}
selectClass="ml-5 w-[100px]"
startYear={1900}
yearReadOnly={true}
/>
</TableCell>
</TableRow>
+8 -5
View File
@@ -6,6 +6,7 @@ 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";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function PlanSewage() {
const {Common
@@ -46,7 +47,8 @@ export default function PlanSewage() {
upHeadList3,
sewageOccurList,
sewageOccurCount,
excelList
excelList,
isLoading,
} = SewageOccur;
const ref = useRef<ReturnType>({
@@ -84,8 +86,7 @@ export default function PlanSewage() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
// const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
/**
* 페이지 함수
@@ -106,6 +107,7 @@ export default function PlanSewage() {
input.value = "";
}
}
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
}
// 모달 닫기
@@ -128,9 +130,9 @@ export default function PlanSewage() {
useEffect(() => {
if (!isInit) {
initializeCommonData();
searchSewageOccurList(1, 10, searchYear || "0");
searchSewageOccurList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchSewageOccurList, searchYear]);
}, [isInit, initializeCommonData, searchSewageOccurList]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -217,6 +219,7 @@ export default function PlanSewage() {
isAdmin={false}
/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
@@ -116,7 +116,6 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
}
}, [searchYear, tabTerm]);
useEffect(()=>{
console.log(fcltyName, searchYear);
unserWaterModal(fcltyName, searchYear);
}, [])
useEffect(() => {
@@ -164,6 +163,7 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
}}
selectClass="ml-5 w-[100px]"
startYear={Number(searchYear)} // 시작 연도 설정
yearReadOnly={true}
/>
<h3 className="justify-center px-5">~</h3>
<DateMonthPicker
@@ -175,6 +175,7 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
}}
selectClass="ml-5 w-[100px]"
startYear={Number(searchYear)} // 시작 연도 설정
yearReadOnly={true}
/>
</div>
</TableCell>
@@ -227,6 +228,8 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
}}
selectClass="ml-5 w-[100px]"
startYear={Number(searchYear)} // 시작 연도 설정
yearReadOnly={true}
enableMonth={['6월', '7월', '8월']}
/>
<h3 className="justify-center px-5">~</h3>
<DateMonthPicker
@@ -238,6 +241,8 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
}}
selectClass="ml-5 w-[100px]"
startYear={Number(searchYear)} // 시작 연도 설정
yearReadOnly={true}
enableMonth={['6월', '7월', '8월']}
/>
</div>
</TableCell>
@@ -281,6 +286,8 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
}}
selectClass="ml-5 w-[100px]"
startYear={Number(searchYear)} // 시작 연도 설정
yearReadOnly={true}
enableMonth={['1월', '2월']}
/>
<h3 className="justify-center px-5">~</h3>
<DateMonthPicker
@@ -292,6 +299,8 @@ export default function UnderWaterInputModal({fcltyName='', searchYear=new Date(
}}
selectClass="ml-5 w-[100px]"
startYear={Number(searchYear)} // 시작 연도 설정
yearReadOnly={true}
enableMonth={['1월', '2월']}
/>
</div>
</TableCell>
+5 -3
View File
@@ -6,6 +6,7 @@ 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/types";
import LoadingOverlay from "@common/business_components/ui/loadingBar";
export default function UnderWaterInput() {
const {Common
@@ -46,6 +47,7 @@ export default function UnderWaterInput() {
underWaterList,
underWaterCount,
excelList,
isLoading,
} = UnderWater;
const ref = useRef<ReturnType>({
@@ -82,8 +84,7 @@ export default function UnderWaterInput() {
// 시설상태
const [operationValue, setOperationValue] = useState<string>("0");
// 조회기간
//const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
const [searchYear, setSearchYear] = useState<string>("2023");
const [searchYear, setSearchYear] = useState<string>(selectSearchYear[0]?.val || "0");
/**
* 페이지 함수
@@ -128,7 +129,7 @@ export default function UnderWaterInput() {
initializeCommonData();
searchUnderWaterList(1, 10, selectSearchYear[0]?.val || "0");
}
}, [isInit, initializeCommonData, searchUnderWaterList, selectSearchYear]);
}, [isInit, initializeCommonData, searchUnderWaterList]);
useEffect(() => {
if (excelList && excelList.length > 0) {
@@ -215,6 +216,7 @@ export default function UnderWaterInput() {
isAdmin={false}
/>
<ListDiv>
<LoadingOverlay isLoading={isLoading} />
<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} />
+23 -1
View File
@@ -2,7 +2,7 @@
* 보편적으로 쓰는 store 공간
====================================**/
import { getFetch } from "@/app/components/api";
import { getFetch, getFetchAreaList } from "@/app/components/api";
/**
* STORE - TYPE
@@ -205,6 +205,28 @@ const selectMiddleRegionData: SelectDataType[] = [
* STORE - API
*/
// 처리시설 계획정보 호출 (알에스원)
export const planInfoUrl = 'https://apigateway.apps.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy';
export const fetchPlanInfo = async (targetYear : string | undefined, ctpvNm : string | undefined, sggNm : string | undefined, fcltyCd : string | undefined) => {
try {
const baseUrl = planInfoUrl;
const queryParams = new URLSearchParams();
if (ctpvNm && ctpvNm !== '전체') queryParams.append('ctpvNm', ctpvNm);
if (sggNm && sggNm !== '전체') queryParams.append('sggNm', sggNm);
if (targetYear) queryParams.append('targetYear',targetYear);
if (fcltyCd) queryParams.append('swtrmtFcltCd', fcltyCd);
const queryString = queryParams.toString();
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
const res = await getFetchAreaList(url);
return res;
} catch (error) {
console.error('처리시설 계획정보를 가져오는데 실패했습니다:', error);
return [];
}
}
// 시도 API 호출 함수 추가
const fetchSidoData = async (): Promise<SelectDataType[]> => {
try {
+392 -283
View File
@@ -2,9 +2,11 @@
* Store - 타입
*/
import { getFetch, getFetchAreaList } from "@/app/components/api";
import { getFetch } from "@/app/components/api";
import DataForm from "@/app/components/common/DataForm";
import { fetchPlanInfo } from "../common";
import type { FacilityWaterQltyProps } from "../facilityWaterQlty";
import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput";
// selectBox
export type SelectDataType = {
@@ -111,13 +113,13 @@ export interface RainManageListProps {
sggNm?: string,
addr?: string,
fctCpc?: number,
inflAssctAftWqltBod: number | '',
inflAssctAftWqltToc: number | '',
inflAssctAftWqltSs: number | '',
inflAssctAftWqltTn: number | '',
inflAssctAftWqltTp: number | '',
inflAssctBfrWqltBod: number | '',
inflAssctBfrWqltToc: number | '',
inflAssctBfrWqltSs: number | '',
inflAssctBfrWqltTn: number | '',
inflAssctBfrWqltTp: number | '',
efflWqltBod: number | '',
efflWqltCod: number | '',
efflWqltToc: number | '',
efflWqltSs: number | '',
efflWqltTn: number | '',
efflWqltTp: number | '',
@@ -143,6 +145,7 @@ export interface RainManageListProps {
dsInflWqltTn: number | '',
dsInflWqltTp: number | '',
extnsSeqno?: number | '',
rainEffectDay?: number | '',
}
export interface RainManageExcelType {
@@ -364,14 +367,14 @@ const upHeadListRainManage : TableUpperProps[] = [
{ id: "dsInflWqltTn", title: "T-N", row:1 },
{ id: "dsInflWqltTp", title: "T-P", row:1 },
{ id: "C", title: "유입수질(㎎/L)", row:0, colSpan:5 },
{ id: "inflAssctAftWqltBod", title: "BOD", row:1 },
{ id: "inflAssctAftWqltToc", title: "TOC\n(COD)", row:1 },
{ id: "inflAssctAftWqltSs", title: "SS", row:1 },
{ id: "inflAssctAftWqltTn", title: "T-N", row:1 },
{ id: "inflAssctAftWqltTp", title: "T-P", row:1 },
{ id: "inflAssctBfrWqltBod", title: "BOD", row:1 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)", row:1 },
{ id: "inflAssctBfrWqltSs", title: "SS", row:1 },
{ id: "inflAssctBfrWqltTn", title: "T-N", row:1 },
{ id: "inflAssctBfrWqltTp", title: "T-P", row:1 },
{ id: "D", title: "방류수질(㎎/L)", row:0, colSpan:5 },
{ id: "efflWqltBod", title: "BOD", row:1 },
{ id: "efflWqltCod", title: "TOC\n(COD)", row:1 },
{ id: "efflWqltToc", title: "TOC\n(COD)", row:1 },
{ id: "efflWqltSs", title: "SS", row:1 },
{ id: "efflWqltTn", title: "T-N", row:1 },
{ id: "efflWqltTp", title: "T-P", row:1 },
@@ -687,20 +690,20 @@ const drainageEquipmentList : DrainageEquipmentListProps[] = [
* Store - api (데이터 호출)
====================================*/
/* 시설정보 및 운영현황 - 계획 */
const fetchFacilityPlan = async (targetYear : string | undefined, fcltyCd : string | undefined) => {
const fetchFacilityPlan = async (targetYear : string | undefined, fcltyCd : string | undefined, set : (fn: (state: DashBoardType) => DashBoardType) => void) => {
try {
targetYear = targetYear ? targetYear : "2023";
const baseUrl = 'https://apigateway.rsonesoft.com/dc-service/api/v1/nowDmgMtncGnsvy';
const queryParams = new URLSearchParams();
if (fcltyCd) queryParams.append('swtrmtFcltCd', fcltyCd);
//if (targetYear) queryParams.append('targetYear',targetYear);
const queryString = queryParams.toString();
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
const res = await getFetchAreaList(url);
return res
const res = await fetchPlanInfo(undefined, undefined, undefined, fcltyCd);
return res;
} catch (error) {
console.error('시설계획정보를 가져오는데 실패했습니다:', error);
set((state) => ({
...state,
PlanFclty : {
...state.PlanFclty,
isLoadingPlanFclty : false,
isLoadingOperationStatus : false
}
}));
return {data: [], count: 0};
}
};
@@ -729,20 +732,6 @@ const fetchMainGraph = async (searchYear: string|undefined, fcltyCd: string|unde
}
}
// 배수설비 정비현황
const fetchDrainageEquipment = async (searchYear: string|undefined, fcltyCd: string|undefined) => {
try{
/* const url = '/fclt/qlty/hist/' + (searchYear?searchYear:'2024') + '/' + (fcltyCd?fcltyCd:'11680PB001R');
const res = await getFetch('fo', url);
return { data: res.data, count: res.count } */
console.log(searchYear, fcltyCd);
return { data : drainageEquipmentList, count : drainageEquipmentList.length }
} catch (error) {
console.error('배수설비 정비현황 데이터를 가져오는데 실패했습니다:', error);
return { data: [], count: 0 };
}
}
/**====================================
* Store - action
====================================*/
@@ -756,8 +745,6 @@ export type DashBoardActions = {
searchMainGraph(searchYear: string, fcltyCd: string): Promise<void>;
/**강우일 운영현황 */
searchRainManage(searchYear: string, fcltyCd: string, isExcel: boolean): Promise<void>;
/**배수설비 정비현황 */
searchDrainageEquipment(searchYear: string, fcltyCd: string, isExcel: boolean): Promise<void>;
}
export type DashBoardType = {
@@ -777,12 +764,17 @@ export type DashBoardType = {
planYearList : string[];
upHeadListPlanFclty : TableUpperProps[];
planFcltyList : planFcltyListProps[];
waterUsage1 : number | '',
waterUsage2 : number | '',
waterUsage3 : number | '',
isLoadingPlanFclty : boolean;
},
OperationStatus : {
isInit : boolean;
upHeadListOperationStatus : TableUpperProps[];
operationalStatusList : OperationalStatusListProps[];
isLoadingOperationStatus : boolean;
}
MainGraph : {
@@ -796,6 +788,7 @@ export type DashBoardType = {
chart_efflTn : lineChartDataProps[];
chart_inflBod : lineChartDataProps[];
chart_efflBod : lineChartDataProps[];
isLoadingMainGraph : boolean;
},
RainManage : {
@@ -803,6 +796,7 @@ export type DashBoardType = {
upHeadListRainManage : TableUpperProps[];
rainManageList : RainManageListProps[];
excelList : RainManageExcelType[];
isLoadingRainManage : boolean;
},
DrainageEquipment : {
@@ -831,13 +825,18 @@ export const dashBoardInitState:DashBoardType = {
isInit : true,
planYearList : planYearList,
upHeadListPlanFclty : upHeadListPlanFclty,
planFcltyList : planFcltyList
planFcltyList : planFcltyList,
waterUsage1 : 0,
waterUsage2 : 0,
waterUsage3 : 0,
isLoadingPlanFclty : false,
},
OperationStatus : {
isInit : false,
upHeadListOperationStatus : upHeadListOperationStatus,
operationalStatusList : operationalStatusList
operationalStatusList : operationalStatusList,
isLoadingOperationStatus : false,
},
MainGraph : {
@@ -850,14 +849,16 @@ export const dashBoardInitState:DashBoardType = {
chart_inflTn : chart_inflTn,
chart_efflTn : chart_efflTn,
chart_inflBod : chart_inflBod,
chart_efflBod : chart_efflBod
chart_efflBod : chart_efflBod,
isLoadingMainGraph : false,
},
RainManage : {
isInit : false,
upHeadListRainManage : upHeadListRainManage,
rainManageList : rainManageList,
excelList : []
excelList : [],
isLoadingRainManage : false,
},
DrainageEquipment : {
@@ -926,18 +927,106 @@ const changeValue=(operationalStatus, data, keyTxt = 'INFL_AMNT')=>{
const calcValue = (operationalStatus, data, keyTxt='INFL_ASSCT_BFR_WQLT_TP') => {
// 연간
operationalStatus.yearAvg = data.yearData ? Number(Math.round(data.yearData['AVG_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.yearMax = data.yearData ? Number(Math.round(data.yearData.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.yearMin = data.yearData ? Number(Math.round(data.yearData.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.yearAvg = data.yearData && data.yearData['AVG_'+keyTxt] ? Number(Math.round(data.yearData['AVG_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.yearMax = data.yearData && data.yearData['MAX_'+keyTxt] ? Number(Math.round(data.yearData['MAX_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.yearMin = data.yearData && data.yearData['MIN_'+keyTxt] ? Number(Math.round(data.yearData['MIN_'+keyTxt] * 1000) / 1000).toFixed(3).toString() : '';
// 여름
operationalStatus.summerAll = data.summer ? Number(Math.round(data.summer.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.summerThree = data.summerRainy ? Number(Math.round(data.summerRainy.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.summerRain = data.summerSunny ? Number(Math.round(data.summerSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.summerAll = data.summer && data.summer['AVG_'+keyTxt] ? Number(Math.round(data.summer['AVG_'+keyTxt] * 0.8 * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.summerThree = data.summerRainy && data.summerRainy['AVG_'+keyTxt] ? Number(Math.round(data.summerRainy['AVG_'+keyTxt] * 0.82 * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.summerRain = data.summerSunny && data.summerSunny['AVG_'+keyTxt] ? Number(Math.round(data.summerSunny['AVG_'+keyTxt] * 0.74 * 1000) / 1000).toFixed(3).toString() : '';
// 겨울
operationalStatus.winterAll = data.winter ? Number(Math.round(data.winter.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.winterSunnyMin = data.winterSunny ? Number(Math.round(data.winterSunny.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.winterSunnyAvg = data.winterSunny ? Number(Math.round(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.winterSunnyMax = data.winterSunny ? Number(Math.round(data.winterSunny.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.winterAll = data.winter && data.winter['AVG_'+keyTxt] ? Number(Math.round(data.winter['AVG_'+keyTxt] * 1.16*1000) / 1000).toFixed(3).toString() : '';
operationalStatus.winterSunnyMin = data.winterSunny && data.winterSunny['MIN_'+keyTxt] ? Number(Math.round(data.winterSunny['MIN_'+keyTxt] * 1.2 * 1000) / 1000).toFixed(3).toString() : '';
operationalStatus.winterSunnyAvg = data.winterSunny && data.winterSunny['AVG_'+keyTxt] ? Number(Math.round(data.winterSunny['AVG_'+keyTxt] * 1.25 *1000) / 1000).toFixed(3).toString() : '';
operationalStatus.winterSunnyMax = data.winterSunny && data.winterSunny['MAX_'+keyTxt] ? Number(Math.round(data.winterSunny['MAX_'+keyTxt] * 1.3 *1000) / 1000).toFixed(3).toString() : '';
}
type RtnFlowType = {
inflAmnt: string | number;
infoRnDay: string | number;
bscFctCd: string;
msrDt: string;
}
type RtnFlowResponse = {
data: RtnFlowType[];
count: number;
}
const searchWaterUsage = async (searchYear: string, fcltyCd: string) => {
const waterUsage = [0, 0, 0];
for (let i = 0; i < 3; i++) {
try {
const res = await getFetch('fo', '/fclt/flow/' + fcltyCd + '/' + (Number(searchYear)-i)) as RtnFlowResponse;
let totWaterUsage = 0;
if (res && res.data && Array.isArray(res.data)) {
res.data.forEach((item: RtnFlowType) => {
totWaterUsage += Number(item.inflAmnt);
});
if (res.count > 0) {
const avg = totWaterUsage / res.count;
waterUsage[i] = parseFloat((avg * 0.65).toFixed(2));
}
}
} catch (error) {
console.error(`Error fetching water usage for year ${Number(searchYear)-i}:`, error);
waterUsage[i] = 0;
}
}
return waterUsage;
}
// 강우영향일 계산 및 강우량 덮어씌우기
export const calRainEffectDayRainManage = (data: RainManageListProps[]) => {
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
for(let idx = 0; idx < data.length; idx++) {
const item = data[idx];
if(item){
if(item.infoRnDay && Number(item.infoRnDay) >= 3) {
item.rainEffectDay = 1;
} else {
item.rainEffectDay = 0;
}
}
}
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
for(let idx = 0; idx < data.length; idx++) {
if(data[idx]) {
// 하루 전이 강우영향일(3 이상)인 경우
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
data[idx]!.rainEffectDay = 1;
}
// 이틀 전이 강우영향일(3 이상)인 경우
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
data[idx]!.rainEffectDay = 1;
}
}
}
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
}
}
let rtnData : RainManageListProps[] = [];
rtnData = data.filter((item: RainManageListProps) => item.rainEffectDay === 1);
return rtnData;
}
export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) => void)=>DashBoardActions=(set: (fn: (state: DashBoardType) => DashBoardType) => void) => {
@@ -954,7 +1043,28 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
/** 시설정보 및 운영현황 - 계획정보 */
searchPlanInfo : async (targetYear: string, fcltyCd: string) => {
const res = await fetchFacilityPlan(targetYear, fcltyCd);
set((state: DashBoardType) => ({
...state,
PlanFclty: {
...state.PlanFclty,
isLoadingPlanFclty: true,
},
}));
let waterUsage = [0, 0, 0];
waterUsage = await searchWaterUsage(targetYear, fcltyCd);
set((state: DashBoardType) => ({
...state,
PlanFclty : {
...state.PlanFclty,
waterUsage1 : waterUsage[0] || 0,
waterUsage2 : waterUsage[1] || 0,
waterUsage3 : waterUsage[2] || 0,
},
}));
const res = await fetchFacilityPlan(targetYear, fcltyCd, set);
let minDiff=9999999;
let minIndex;
res.forEach((el:any, idx) => {
@@ -1004,21 +1114,31 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
// 임시시
dataFormSettingPlan(el);
console.log('planFcltyList', planFcltyList);
console.log('rtnPlanData', rtnPlanData);
set((state: DashBoardType) => ({
...state,
PlanFclty: {
...state.PlanFclty,
planFcltyList: planFcltyList,
isLoadingPlanFclty: false,
},
}));
});
set((state: DashBoardType) => ({
...state,
PlanFclty : {
...state.PlanFclty,
planFcltyList : planFcltyList
}
}));
},
/** 시설정보 및 운영현황 - 운영실태 */
searchOperationStatus: async (isExcel: boolean, searchYear: string, fcltyCd: string) => {
set((state: DashBoardType) => ({
...state,
OperationStatus: {
...state.OperationStatus,
isLoadingOperationStatus: true,
},
}));
const res = await fetchOperationStatus(searchYear, fcltyCd);
const data = res.data;
if(data && operationalStatusList){
// 유량 - 유입
if (operationalStatusList?.[0]) {
@@ -1050,10 +1170,56 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
operationalStatusList[0].winterSunnyMin = data.winterSunny === null ? '' : (data.winterSunny.MIN_INFL_AMNT ? data.winterSunny.MIN_INFL_AMNT : 0) + (data.winterSunny.MIN_SUM_FLOW ? data.winterSunny.MIN_SUM_FLOW : 0) + (data.winterSunny.MIN_TP_INFL_WQLT_TP ? data.winterSunny.MIN_TP_INFL_WQLT_TP : 0);
operationalStatusList[0].winterSunnyAvg = data.winterSunny === null ? '' : (data.winterSunny.AVG_INFL_AMNT ? data.winterSunny.AVG_INFL_AMNT : 0) + (data.winterSunny.AVG_SUM_FLOW ? data.winterSunny.AVG_SUM_FLOW : 0) + (data.winterSunny.AVG_TP_INFL_WQLT_TP ? data.winterSunny.AVG_TP_INFL_WQLT_TP : 0);
operationalStatusList[0].winterSunnyMax = data.winterSunny === null ? '' : (data.winterSunny.MAX_INFL_AMNT ? data.winterSunny.MAX_INFL_AMNT : 0) + (data.winterSunny.MAX_SUM_FLOW ? data.winterSunny.MAX_SUM_FLOW : 0) + (data.winterSunny.MAX_TP_INFL_WQLT_TP ? data.winterSunny.MAX_TP_INFL_WQLT_TP : 0);
// 지하수
operationalStatusList[0].groundWaterAvg = data.yearData.AVG_INFL_AMNT === null ? '' : Number(data.yearData.AVG_INFL_AMNT) - (Number(data.yearData.AVG_INFL_AMNT)*0.65*0.8);
operationalStatusList[0].groundWaterSummer = data.summer.AVG_INFL_AMNT === null ? '' : Number(data.summer.AVG_INFL_AMNT) - (Number(data.summer.AVG_INFL_AMNT)*0.65*0.8);
operationalStatusList[0].groundWaterWinter = data.winter.AVG_INFL_AMNT === null ? '' : Number(data.winter.AVG_INFL_AMNT) - (Number(data.winter.AVG_INFL_AMNT)*0.65*0.8);
// 연계처리수,지하수유입량
const bscFctCd = fcltyCd;
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse;
const calData = calRainEffectDay(res2.data, 'SUNNY');
let chungcunSumFlow = 0;
let sumSummerChungcunDay = 0;
let sumSummerChungcunFlow = 0;
let sumWinterChungcunDay = 0;
let sumWinterChungcunFlow = 0;
/* let yearSumFlow = 0;
let summerSumFlow = 0;
let winterSumFlow = 0; */
calData.forEach((flowItem: FlowDataItem) => {
chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
//yearSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
sumSummerChungcunDay += 1;
sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
//summerSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
}else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){
sumWinterChungcunDay += 1;
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
// winterSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0;
}
});
// 연계처리수
/* const avgYearSumFlow = yearSumFlow / calData.length;
const avgSummerSumFlow = summerSumFlow / calData.length;
const avgWinterSumFlow = winterSumFlow / calData.length; */
// 지하수유입량
const usage = chungcunSumFlow / calData.length;
const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay;
const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay;
operationalStatusList[0].groundWaterAvg = Math.round((usage-(usage*0.65*0.8)) * 100) / 100;
operationalStatusList[0].groundWaterSummer = Math.round((summerUsage-(summerUsage*0.65*0.8)) * 100) / 100;
operationalStatusList[0].groundWaterWinter = Math.round((winterUsage-(winterUsage*0.65*0.8)) * 100) / 100;
//operationalStatusList[0].groundWaterAvg = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8);
//operationalStatusList[0].groundWaterSummer = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8);
//operationalStatusList[0].groundWaterWinter = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8);
// 오염물질
// RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
@@ -1063,16 +1229,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0;
operationalStatusList[0].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatusList[0].rdiRain = summerLowRain;
dataFormSetting(operationalStatusList[0]);
}
if(operationalStatusList[0] && operationalStatusList[7]){
console.log(Number(operationalStatusList[0].groundWaterAvg)+' '+Number(data.yearData.AVG_INFL_AMNT));
console.log(Number(operationalStatusList[0].groundWaterSummer)+' '+Number(data.summer.AVG_INFL_AMNT));
console.log(Number(operationalStatusList[0].groundWaterWinter)+' '+Number(data.winter.AVG_INFL_AMNT));
operationalStatusList[7].groundWaterAvg = Number(operationalStatusList[0].groundWaterAvg) / Number(data.yearData.AVG_INFL_AMNT) * 100;
operationalStatusList[7].groundWaterSummer = Number(operationalStatusList[0].groundWaterSummer) / Number(data.summer.AVG_INFL_AMNT) * 100;
operationalStatusList[7].groundWaterWinter = Number(operationalStatusList[0].groundWaterWinter) / Number(data.winter.AVG_INFL_AMNT) * 100;
operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : data.yearData && data.yearData.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterAvg) / (data.yearData && data.yearData.AVG_INFL_AMNT ? Number(data.yearData.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].groundWaterSummer = operationalStatusList[0].groundWaterSummer === null ? '' : data.summer && data.summer.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterSummer) / (data.summer && data.summer.AVG_INFL_AMNT ? Number(data.summer.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].groundWaterWinter = operationalStatusList[0].groundWaterWinter === null ? '' : data.winter && data.winter.AVG_INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].groundWaterWinter) / (data.winter && data.winter.AVG_INFL_AMNT ? Number(data.winter.AVG_INFL_AMNT) : 0) * 100) * 10) / 10+'%';
operationalStatusList[7].rdi = operationalStatusList[0].rdi === null ? '' : data.summerBod && data.summerBod.INFL_AMNT === 0 ? '' : Math.round((Number(operationalStatusList[0].rdi) / (data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0) * 100) * 10) / 10+'%';
/* operationalStatusList[7].groundWaterAvg = operationalStatusList[0].groundWaterAvg === null ? '' : Number(Number(operationalStatusList[0].groundWaterAvg) / Number(data.yearData.AVG_INFL_AMNT)) * 100;
operationalStatusList[7].groundWaterSummer = operationalStatusList[0].groundWaterSummer === null ? '' : Number(Number(operationalStatusList[0].groundWaterSummer) / Number(data.summer.AVG_INFL_AMNT)) * 100;
operationalStatusList[7].groundWaterWinter = operationalStatusList[0].groundWaterWinter === null ? '' : Number(Number(operationalStatusList[0].groundWaterWinter) / Number(data.winter.AVG_INFL_AMNT)) * 100;*/
@@ -1080,7 +1243,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
}
for(let i=1; i<operationalStatusList.length; i++){
const txtArray = ['1', 'INFL_AMNT', 'SUM_FLOW', 'RETURN_AMNT', 'EFFL_AMNT', 'INFL_ASSCT_BFR_WQLT_BOD', 'EFFL_WQLT_BOD', 'INFL_ASSCT_BFR_WQLT_TN', 'EFFL_WQLT_TN', 'INFL_ASSCT_BFR_WQLT_TP', 'EFFL_WQLT_TP', 'INFL_ASSCT_BFR_WQLT_TP', 'EFFL_WQLT_TP'];
const txtArray = ['1', 'INFL_AMNT', 'SUM_FLOW', 'RETURN_AMNT', 'EFFL_AMNT', 'INFL_ASSCT_BFR_WQLT_BOD', 'EFFL_WQLT_BOD', 'INFL_ASSCT_BFR_WQLT_TN', 'EFFL_WQLT_TN', 'INFL_ASSCT_BFR_WQLT_TP', 'EFFL_WQLT_TP', 'TP_INFL_WQLT_TP', 'EFFL_WQLT_TP'];
if(operationalStatusList[i]){
if(i < 7){
changeValue(operationalStatusList[i], data, txtArray[i]);
@@ -1106,8 +1269,8 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
시군구: item.sggNm,
주소: item.addr,
용량: item.fctCpc,
유입BOD: item.inflAssctAftWqltBod,
유입TN: item.inflAssctAftWqltTn,
유입BOD: item.inflAssctBfrWqltBod,
유입TN: item.inflAssctBfrWqltTn,
유입TP: item.inflAssctBfrWqltTp,
유출BOD: item.efflWqltBod,
유출TN: item.efflWqltTn,
@@ -1127,12 +1290,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
OperationStatus: {
...state.OperationStatus,
operationalStatusList: operationalStatusList,
operationalStatusCount: res.count
}
operationalStatusCount: res.count,
isLoadingOperationStatus : false,
},
}))
},
searchMainGraph: async (searchYear: string, fcltyCd: string) => {
set((state: DashBoardType) => ({
...state,
MainGraph: {
...state.MainGraph,
isLoadingMainGraph: true,
},
}));
const res = await fetchMainGraph(searchYear, fcltyCd);
if(res == null || res.data == null || res.data.length === 0) {
set((state: DashBoardType) => ({
@@ -1148,6 +1319,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
chart_efflTn: [],
chart_inflBod: [],
chart_efflBod: [],
isLoadingMainGraph : false,
}
}));
return;
@@ -1163,7 +1335,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const chart_bodRain = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({
label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8),
barVal0: item.infoRnDay ?? 0,
lineVal0: item.inflAssctAftWqltBod ?? 0,
lineVal0: item.inflAssctBfrWqltBod ?? 0,
}));
const chart_inflTp = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({
@@ -1183,7 +1355,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const chart_inflTn = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({
label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8),
val : item.inflAssctAftWqltTn ?? 0
val : item.inflAssctBfrWqltTn ?? 0
}));
const chart_efflTn = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({
@@ -1193,7 +1365,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const chart_inflBod = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({
label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8),
val : item.inflAssctAftWqltBod ?? 0
val : item.inflAssctBfrWqltBod ?? 0
}));
const chart_efflBod = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({
@@ -1213,12 +1385,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
chart_inflTn: chart_inflTn,
chart_efflTn: chart_efflTn,
chart_inflBod: chart_inflBod,
chart_efflBod: chart_efflBod
}
chart_efflBod: chart_efflBod,
isLoadingMainGraph : false,
},
}))
},
searchRainManage: async (searchYear: string, fcltyCd: string, isExcel : boolean) => {
set((state: DashBoardType) => ({
...state,
RainManage: {
...state.RainManage,
isLoadingRainManage: true,
},
}));
const res = await fetchMainGraph(searchYear, fcltyCd);
if(res == null || res.data.wqltObjs == null || res.data.wqltObjs.length === 0) {
set((state: DashBoardType) => ({
@@ -1226,6 +1406,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
RainManage: {
...state.RainManage,
rainManageList: [],
isLoadingRainManage : false,
}
}));
return;
@@ -1243,75 +1424,51 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const dsInflWqltSs: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltTn: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const dsInflWqltTp: number[] = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltBod = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTocCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltToc = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltSs = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTn = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctAftWqltTp = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltBod = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltTocCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltToc = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltSs = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltTn = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const inflAssctBfrWqltTp = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltBodCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltBod = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltCodCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltCod = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTocCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltToc = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltSsCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltSs = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTnCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTn = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTpCnt = [0, 0, 0, 0, 0, 0, 0, 0];
const efflWqltTp = [0, 0, 0, 0, 0, 0, 0, 0];
// 청천시 중 강우영향일인 날짜는 이전의 강우량을 대입해 리스트 수정
const rainEffectList = calRainEffectDayRainManage(res.data.wqltObjs);
// Process the data and create rain management list
res.data.wqltObjs.forEach((item: RainManageListProps) => {
// 강우일
/*if(Number(item.infoRnDay) < 3){
rainDate[1] = Number(rainDate[1] || 0) + 1;
inflAmtCnt[1] = Number(inflAmtCnt[1] || 0) + 1;
inflAmnt[1] = Number(inflAmnt[1] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[1] = 0;
inflAssctAftWqltBodCnt[1] = Number(inflAssctAftWqltBodCnt[1] || 0) + 1;
inflAssctAftWqltBod[1] = Number(inflAssctAftWqltBod[1] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[1] = Number(inflAssctAftWqltTocCnt[1] || 0) + 1;
inflAssctAftWqltToc[1] = Number(inflAssctAftWqltToc[1] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[1] = Number(inflAssctAftWqltSsCnt[1] || 0) + 1;
inflAssctAftWqltSs[1] = Number(inflAssctAftWqltSs[1] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[1] = Number(inflAssctAftWqltTnCnt[1] || 0) + 1;
inflAssctAftWqltTn[1] = Number(inflAssctAftWqltTn[1] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[1] = Number(inflAssctAftWqltTpCnt[1] || 0) + 1;
inflAssctAftWqltTp[1] = Number(inflAssctAftWqltTp[1] || 0) + Number(item.inflAssctAftWqltTp || 0);
efflWqltBodCnt[1] = Number(efflWqltBodCnt[1] || 0) + 1;
efflWqltBod[1] = Number(efflWqltBod[1] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[1] = Number(efflWqltCodCnt[1] || 0) + 1;
efflWqltCod[1] = Number(efflWqltCod[1] || 0) + Number(item.efflWqltCod || 0);
efflWqltSsCnt[1] = Number(efflWqltSsCnt[1] || 0) + 1;
efflWqltSs[1] = Number(efflWqltSs[1] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[1] = Number(efflWqltTnCnt[1] || 0) + 1;
efflWqltTn[1] = Number(efflWqltTn[1] || 0) + Number(item.efflWqltTn || 0);
efflWqltTpCnt[1] = Number(efflWqltTpCnt[1] || 0) + 1;
efflWqltTp[1] = Number(efflWqltTp[1] || 0) + Number(item.efflWqltTp || 0);
}*/
rainEffectList.forEach((item: RainManageListProps) => {
if(Number(item.infoRnDay) >= 3 && Number(item.infoRnDay) < 10){
rainDate[1] = Number(rainDate[1] || 0) + 1;
inflAmtCnt[1] = Number(inflAmtCnt[1] || 0) + 1;
inflAmnt[1] = Number(inflAmnt[1] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[1] = 0;
inflAssctAftWqltBodCnt[1] = Number(inflAssctAftWqltBodCnt[1] || 0) + 1;
inflAssctAftWqltBod[1] = Number(inflAssctAftWqltBod[1] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[1] = Number(inflAssctAftWqltTocCnt[1] || 0) + 1;
inflAssctAftWqltToc[1] = Number(inflAssctAftWqltToc[1] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[1] = Number(inflAssctAftWqltSsCnt[1] || 0) + 1;
inflAssctAftWqltSs[1] = Number(inflAssctAftWqltSs[1] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[1] = Number(inflAssctAftWqltTnCnt[1] || 0) + 1;
inflAssctAftWqltTn[1] = Number(inflAssctAftWqltTn[1] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[1] = Number(inflAssctAftWqltTpCnt[1] || 0) + 1;
inflAssctAftWqltTp[1] = Number(inflAssctAftWqltTp[1] || 0) + Number(item.inflAssctAftWqltTp || 0);
inflAssctBfrWqltBodCnt[1] = Number(inflAssctBfrWqltBodCnt[1] || 0) + 1;
inflAssctBfrWqltBod[1] = Number(inflAssctBfrWqltBod[1] || 0) + Number(item.inflAssctBfrWqltBod || 0);
inflAssctBfrWqltTocCnt[1] = Number(inflAssctBfrWqltTocCnt[1] || 0) + 1;
inflAssctBfrWqltToc[1] = Number(inflAssctBfrWqltToc[1] || 0) + Number(item.inflAssctBfrWqltToc || 0);
inflAssctBfrWqltSsCnt[1] = Number(inflAssctBfrWqltSsCnt[1] || 0) + 1;
inflAssctBfrWqltSs[1] = Number(inflAssctBfrWqltSs[1] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[1] = Number(inflAssctBfrWqltTnCnt[1] || 0) + 1;
inflAssctBfrWqltTn[1] = Number(inflAssctBfrWqltTn[1] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[1] = Number(inflAssctBfrWqltTpCnt[1] || 0) + 1;
inflAssctBfrWqltTp[1] = Number(inflAssctBfrWqltTp[1] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[1] = Number(efflWqltBodCnt[1] || 0) + 1;
efflWqltBod[1] = Number(efflWqltBod[1] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[1] = Number(efflWqltCodCnt[1] || 0) + 1;
efflWqltCod[1] = Number(efflWqltCod[1] || 0) + Number(item.efflWqltCod || 0);
efflWqltTocCnt[1] = Number(efflWqltTocCnt[1] || 0) + 1;
efflWqltToc[1] = Number(efflWqltToc[1] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[1] = Number(efflWqltSsCnt[1] || 0) + 1;
efflWqltSs[1] = Number(efflWqltSs[1] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[1] = Number(efflWqltTnCnt[1] || 0) + 1;
@@ -1323,20 +1480,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmtCnt[2] = Number(inflAmtCnt[2] || 0) + 1;
inflAmnt[2] = Number(inflAmnt[2] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[2] = 0;
inflAssctAftWqltBodCnt[2] = Number(inflAssctAftWqltBodCnt[2] || 0) + 1;
inflAssctAftWqltBod[2] = Number(inflAssctAftWqltBod[2] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[2] = Number(inflAssctAftWqltTocCnt[2] || 0) + 1;
inflAssctAftWqltToc[2] = Number(inflAssctAftWqltToc[2] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[2] = Number(inflAssctAftWqltSsCnt[2] || 0) + 1;
inflAssctAftWqltSs[2] = Number(inflAssctAftWqltSs[2] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[2] = Number(inflAssctAftWqltTnCnt[2] || 0) + 1;
inflAssctAftWqltTn[2] = Number(inflAssctAftWqltTn[2] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[2] = Number(inflAssctAftWqltTpCnt[2] || 0) + 1;
inflAssctAftWqltTp[2] = Number(inflAssctAftWqltTp[2] || 0) + Number(item.inflAssctAftWqltTp || 0);
inflAssctBfrWqltBodCnt[2] = Number(inflAssctBfrWqltBodCnt[2] || 0) + 1;
inflAssctBfrWqltBod[2] = Number(inflAssctBfrWqltBod[2] || 0) + Number(item.inflAssctBfrWqltBod || 0);
inflAssctBfrWqltTocCnt[2] = Number(inflAssctBfrWqltTocCnt[2] || 0) + 1;
inflAssctBfrWqltToc[2] = Number(inflAssctBfrWqltToc[2] || 0) + Number(item.inflAssctBfrWqltToc || 0);
inflAssctBfrWqltSsCnt[2] = Number(inflAssctBfrWqltSsCnt[2] || 0) + 1;
inflAssctBfrWqltSs[2] = Number(inflAssctBfrWqltSs[2] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[2] = Number(inflAssctBfrWqltTnCnt[2] || 0) + 1;
inflAssctBfrWqltTn[2] = Number(inflAssctBfrWqltTn[2] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[2] = Number(inflAssctBfrWqltTpCnt[2] || 0) + 1;
inflAssctBfrWqltTp[2] = Number(inflAssctBfrWqltTp[2] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[2] = Number(efflWqltBodCnt[2] || 0) + 1;
efflWqltBod[2] = Number(efflWqltBod[2] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[2] = Number(efflWqltCodCnt[2] || 0) + 1;
efflWqltCod[2] = Number(efflWqltCod[2] || 0) + Number(item.efflWqltCod || 0);
efflWqltTocCnt[2] = Number(efflWqltTocCnt[2] || 0) + 1;
efflWqltToc[2] = Number(efflWqltToc[2] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[2] = Number(efflWqltSsCnt[2] || 0) + 1;
efflWqltSs[2] = Number(efflWqltSs[2] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[2] = Number(efflWqltTnCnt[2] || 0) + 1;
@@ -1348,20 +1505,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmtCnt[3] = Number(inflAmtCnt[3] || 0) + 1;
inflAmnt[3] = Number(inflAmnt[3] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[3] = 0;
inflAssctAftWqltBodCnt[3] = Number(inflAssctAftWqltBodCnt[3] || 0) + 1;
inflAssctAftWqltBod[3] = Number(inflAssctAftWqltBod[3] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[3] = Number(inflAssctAftWqltTocCnt[3] || 0) + 1;
inflAssctAftWqltToc[3] = Number(inflAssctAftWqltToc[3] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[3] = Number(inflAssctAftWqltSsCnt[3] || 0) + 1;
inflAssctAftWqltSs[3] = Number(inflAssctAftWqltSs[3] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[3] = Number(inflAssctAftWqltTnCnt[3] || 0) + 1;
inflAssctAftWqltTn[3] = Number(inflAssctAftWqltTn[3] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[3] = Number(inflAssctAftWqltTpCnt[3] || 0) + 1;
inflAssctAftWqltTp[3] = Number(inflAssctAftWqltTp[3] || 0) + Number(item.inflAssctAftWqltTp || 0);
inflAssctBfrWqltBodCnt[3] = Number(inflAssctBfrWqltBodCnt[3] || 0) + 1;
inflAssctBfrWqltBod[3] = Number(inflAssctBfrWqltBod[3] || 0) + Number(item.inflAssctBfrWqltBod || 0);
inflAssctBfrWqltTocCnt[3] = Number(inflAssctBfrWqltTocCnt[3] || 0) + 1;
inflAssctBfrWqltToc[3] = Number(inflAssctBfrWqltToc[3] || 0) + Number(item.inflAssctBfrWqltToc || 0);
inflAssctBfrWqltSsCnt[3] = Number(inflAssctBfrWqltSsCnt[3] || 0) + 1;
inflAssctBfrWqltSs[3] = Number(inflAssctBfrWqltSs[3] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[3] = Number(inflAssctBfrWqltTnCnt[3] || 0) + 1;
inflAssctBfrWqltTn[3] = Number(inflAssctBfrWqltTn[3] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[3] = Number(inflAssctBfrWqltTpCnt[3] || 0) + 1;
inflAssctBfrWqltTp[3] = Number(inflAssctBfrWqltTp[3] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[3] = Number(efflWqltBodCnt[3] || 0) + 1;
efflWqltBod[3] = Number(efflWqltBod[3] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[3] = Number(efflWqltCodCnt[3] || 0) + 1;
efflWqltCod[3] = Number(efflWqltCod[3] || 0) + Number(item.efflWqltCod || 0);
efflWqltTocCnt[3] = Number(efflWqltTocCnt[3] || 0) + 1;
efflWqltToc[3] = Number(efflWqltToc[3] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[3] = Number(efflWqltSsCnt[3] || 0) + 1;
efflWqltSs[3] = Number(efflWqltSs[3] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[3] = Number(efflWqltTnCnt[3] || 0) + 1;
@@ -1373,20 +1530,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmtCnt[4] = Number(inflAmtCnt[4] || 0) + 1;
inflAmnt[4] = Number(inflAmnt[4] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[4] = item.inflAmnt&&Number(item.inflAmnt) !== 0 ? Number(Math.round(Number(item.inflAmnt) / Number(item.fctCpc) * 10) / 10) : 0;
inflAssctAftWqltBodCnt[4] = Number(inflAssctAftWqltBodCnt[4] || 0) + 1;
inflAssctAftWqltBod[4] = Number(inflAssctAftWqltBod[4] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[4] = Number(inflAssctAftWqltTocCnt[4] || 0) + 1;
inflAssctAftWqltToc[4] = Number(inflAssctAftWqltToc[4] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[4] = Number(inflAssctAftWqltSsCnt[4] || 0) + 1;
inflAssctAftWqltSs[4] = Number(inflAssctAftWqltSs[4] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[4] = Number(inflAssctAftWqltTnCnt[4] || 0) + 1;
inflAssctAftWqltTn[4] = Number(inflAssctAftWqltTn[5] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[4] = Number(inflAssctAftWqltTpCnt[4] || 0) + 1;
inflAssctAftWqltTp[4] = Number(inflAssctAftWqltTp[4] || 0) + Number(item.inflAssctAftWqltTp || 0);
inflAssctBfrWqltBodCnt[4] = Number(inflAssctBfrWqltBodCnt[4] || 0) + 1;
inflAssctBfrWqltBod[4] = Number(inflAssctBfrWqltBod[4] || 0) + Number(item.inflAssctBfrWqltBod || 0);
inflAssctBfrWqltTocCnt[4] = Number(inflAssctBfrWqltTocCnt[4] || 0) + 1;
inflAssctBfrWqltToc[4] = Number(inflAssctBfrWqltToc[4] || 0) + Number(item.inflAssctBfrWqltToc || 0);
inflAssctBfrWqltSsCnt[4] = Number(inflAssctBfrWqltSsCnt[4] || 0) + 1;
inflAssctBfrWqltSs[4] = Number(inflAssctBfrWqltSs[4] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[4] = Number(inflAssctBfrWqltTnCnt[4] || 0) + 1;
inflAssctBfrWqltTn[4] = Number(inflAssctBfrWqltTn[5] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[4] = Number(inflAssctBfrWqltTpCnt[4] || 0) + 1;
inflAssctBfrWqltTp[4] = Number(inflAssctBfrWqltTp[4] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[4] = Number(efflWqltBodCnt[4] || 0) + 1;
efflWqltBod[4] = Number(efflWqltBod[4] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[4] = Number(efflWqltCodCnt[4] || 0) + 1;
efflWqltCod[4] = Number(efflWqltCod[4] || 0) + Number(item.efflWqltCod || 0);
efflWqltTocCnt[4] = Number(efflWqltTocCnt[4] || 0) + 1;
efflWqltToc[4] = Number(efflWqltToc[4] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[4] = Number(efflWqltSsCnt[4] || 0) + 1;
efflWqltSs[4] = Number(efflWqltSs[4] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[4] = Number(efflWqltTnCnt[5] || 0) + 1;
@@ -1398,20 +1555,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmtCnt[5] = Number(inflAmtCnt[5] || 0) + 1;
inflAmnt[5] = Number(inflAmnt[5] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[5] = 0;
inflAssctAftWqltBodCnt[5] = Number(inflAssctAftWqltBodCnt[5] || 0) + 1;
inflAssctAftWqltBod[5] = Number(inflAssctAftWqltBod[5] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[5] = Number(inflAssctAftWqltTocCnt[5] || 0) + 1;
inflAssctAftWqltToc[5] = Number(inflAssctAftWqltToc[5] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[5] = Number(inflAssctAftWqltSsCnt[5] || 0) + 1;
inflAssctAftWqltSs[5] = Number(inflAssctAftWqltSs[5] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[5] = Number(inflAssctAftWqltTnCnt[5] || 0) + 1;
inflAssctAftWqltTn[5] = Number(inflAssctAftWqltTn[5] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[5] = Number(inflAssctAftWqltTpCnt[5] || 0) + 1;
inflAssctAftWqltTp[5] = Number(inflAssctAftWqltTp[5] || 0) + Number(item.inflAssctAftWqltTp || 0);
inflAssctBfrWqltBodCnt[5] = Number(inflAssctBfrWqltBodCnt[5] || 0) + 1;
inflAssctBfrWqltBod[5] = Number(inflAssctBfrWqltBod[5] || 0) + Number(item.inflAssctBfrWqltBod || 0);
inflAssctBfrWqltTocCnt[5] = Number(inflAssctBfrWqltTocCnt[5] || 0) + 1;
inflAssctBfrWqltToc[5] = Number(inflAssctBfrWqltToc[5] || 0) + Number(item.inflAssctBfrWqltToc || 0);
inflAssctBfrWqltSsCnt[5] = Number(inflAssctBfrWqltSsCnt[5] || 0) + 1;
inflAssctBfrWqltSs[5] = Number(inflAssctBfrWqltSs[5] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[5] = Number(inflAssctBfrWqltTnCnt[5] || 0) + 1;
inflAssctBfrWqltTn[5] = Number(inflAssctBfrWqltTn[5] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[5] = Number(inflAssctBfrWqltTpCnt[5] || 0) + 1;
inflAssctBfrWqltTp[5] = Number(inflAssctBfrWqltTp[5] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[5] = Number(efflWqltBodCnt[5] || 0) + 1;
efflWqltBod[5] = Number(efflWqltBod[5] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[5] = Number(efflWqltCodCnt[5] || 0) + 1;
efflWqltCod[5] = Number(efflWqltCod[5] || 0) + Number(item.efflWqltCod || 0);
efflWqltTocCnt[5] = Number(efflWqltTocCnt[5] || 0) + 1;
efflWqltToc[5] = Number(efflWqltToc[5] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[5] = Number(efflWqltSsCnt[5] || 0) + 1;
efflWqltSs[5] = Number(efflWqltSs[5] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[5] = Number(efflWqltTnCnt[5] || 0) + 1;
@@ -1423,20 +1580,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmtCnt[6] = Number(inflAmtCnt[6] || 0) + 1;
inflAmnt[6] = Number(inflAmnt[6] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[6] = 0;
inflAssctAftWqltBodCnt[6] = Number(inflAssctAftWqltBodCnt[6] || 0) + 1;
inflAssctAftWqltBod[6] = Number(inflAssctAftWqltBod[6] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[6] = Number(inflAssctAftWqltTocCnt[6] || 0) + 1;
inflAssctAftWqltToc[6] = Number(inflAssctAftWqltToc[6] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[6] = Number(inflAssctAftWqltSsCnt[6] || 0) + 1;
inflAssctAftWqltSs[6] = Number(inflAssctAftWqltSs[6] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[6] = Number(inflAssctAftWqltTnCnt[6] || 0) + 1;
inflAssctAftWqltTn[6] = Number(inflAssctAftWqltTn[6] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[6] = Number(inflAssctAftWqltTpCnt[6] || 0) + 1;
inflAssctAftWqltTp[6] = Number(inflAssctAftWqltTp[6] || 0) + Number(item.inflAssctAftWqltTp || 0);
inflAssctBfrWqltBodCnt[6] = Number(inflAssctBfrWqltBodCnt[6] || 0) + 1;
inflAssctBfrWqltBod[6] = Number(inflAssctBfrWqltBod[6] || 0) + Number(item.inflAssctBfrWqltBod || 0);
inflAssctBfrWqltTocCnt[6] = Number(inflAssctBfrWqltTocCnt[6] || 0) + 1;
inflAssctBfrWqltToc[6] = Number(inflAssctBfrWqltToc[6] || 0) + Number(item.inflAssctBfrWqltToc || 0);
inflAssctBfrWqltSsCnt[6] = Number(inflAssctBfrWqltSsCnt[6] || 0) + 1;
inflAssctBfrWqltSs[6] = Number(inflAssctBfrWqltSs[6] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[6] = Number(inflAssctBfrWqltTnCnt[6] || 0) + 1;
inflAssctBfrWqltTn[6] = Number(inflAssctBfrWqltTn[6] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[6] = Number(inflAssctBfrWqltTpCnt[6] || 0) + 1;
inflAssctBfrWqltTp[6] = Number(inflAssctBfrWqltTp[6] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[6] = Number(efflWqltBodCnt[6] || 0) + 1;
efflWqltBod[6] = Number(efflWqltBod[6] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[6] = Number(efflWqltCodCnt[6] || 0) + 1;
efflWqltCod[6] = Number(efflWqltCod[6] || 0) + Number(item.efflWqltCod || 0);
efflWqltTocCnt[6] = Number(efflWqltTocCnt[6] || 0) + 1;
efflWqltToc[6] = Number(efflWqltToc[6] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[6] = Number(efflWqltSsCnt[6] || 0) + 1;
efflWqltSs[6] = Number(efflWqltSs[6] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[6] = Number(efflWqltTnCnt[6] || 0) + 1;
@@ -1448,20 +1605,20 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmtCnt[7] = Number(inflAmtCnt[7] || 0) + 1;
inflAmnt[7] = Number(inflAmnt[7] || 0) + Number(item.inflAmnt || 0);
fcltyCpct[7] = 0;
inflAssctAftWqltBodCnt[7] = Number(inflAssctAftWqltBodCnt[7] || 0) + 1;
inflAssctAftWqltBod[7] = Number(inflAssctAftWqltBod[7] || 0) + Number(item.inflAssctAftWqltBod || 0);
inflAssctAftWqltTocCnt[7] = Number(inflAssctAftWqltTocCnt[7] || 0) + 1;
inflAssctAftWqltToc[7] = Number(inflAssctAftWqltToc[7] || 0) + Number(item.inflAssctAftWqltToc || 0);
inflAssctAftWqltSsCnt[7] = Number(inflAssctAftWqltSsCnt[7] || 0) + 1;
inflAssctAftWqltSs[7] = Number(inflAssctAftWqltSs[7] || 0) + Number(item.inflAssctAftWqltSs || 0);
inflAssctAftWqltTnCnt[7] = Number(inflAssctAftWqltTnCnt[7] || 0) + 1;
inflAssctAftWqltTn[7] = Number(inflAssctAftWqltTn[7] || 0) + Number(item.inflAssctAftWqltTn || 0);
inflAssctAftWqltTpCnt[7] = Number(inflAssctAftWqltTpCnt[7] || 0) + 1;
inflAssctAftWqltTp[7] = Number(inflAssctAftWqltTp[7] || 0) + Number(item.inflAssctAftWqltTp || 0);
inflAssctBfrWqltBodCnt[7] = Number(inflAssctBfrWqltBodCnt[7] || 0) + 1;
inflAssctBfrWqltBod[7] = Number(inflAssctBfrWqltBod[7] || 0) + Number(item.inflAssctBfrWqltBod || 0);
inflAssctBfrWqltTocCnt[7] = Number(inflAssctBfrWqltTocCnt[7] || 0) + 1;
inflAssctBfrWqltToc[7] = Number(inflAssctBfrWqltToc[7] || 0) + Number(item.inflAssctBfrWqltToc || 0);
inflAssctBfrWqltSsCnt[7] = Number(inflAssctBfrWqltSsCnt[7] || 0) + 1;
inflAssctBfrWqltSs[7] = Number(inflAssctBfrWqltSs[7] || 0) + Number(item.inflAssctBfrWqltSs || 0);
inflAssctBfrWqltTnCnt[7] = Number(inflAssctBfrWqltTnCnt[7] || 0) + 1;
inflAssctBfrWqltTn[7] = Number(inflAssctBfrWqltTn[7] || 0) + Number(item.inflAssctBfrWqltTn || 0);
inflAssctBfrWqltTpCnt[7] = Number(inflAssctBfrWqltTpCnt[7] || 0) + 1;
inflAssctBfrWqltTp[7] = Number(inflAssctBfrWqltTp[7] || 0) + Number(item.inflAssctBfrWqltTp || 0);
efflWqltBodCnt[7] = Number(efflWqltBodCnt[7] || 0) + 1;
efflWqltBod[7] = Number(efflWqltBod[7] || 0) + Number(item.efflWqltBod || 0);
efflWqltCodCnt[7] = Number(efflWqltCodCnt[7] || 0) + 1;
efflWqltCod[7] = Number(efflWqltCod[7] || 0) + Number(item.efflWqltCod || 0);
efflWqltTocCnt[7] = Number(efflWqltTocCnt[7] || 0) + 1;
efflWqltToc[7] = Number(efflWqltToc[7] || 0) + Number(item.efflWqltToc || 0);
efflWqltSsCnt[7] = Number(efflWqltSsCnt[7] || 0) + 1;
efflWqltSs[7] = Number(efflWqltSs[7] || 0) + Number(item.efflWqltSs || 0);
efflWqltTnCnt[7] = Number(efflWqltTnCnt[7] || 0) + 1;
@@ -1539,13 +1696,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
for(let idx=0; idx<inflAmnt.length; idx++){
inflAmnt[idx] = calculateAverage(Number(inflAmnt[idx]), Number(inflAmtCnt[idx]));
inflAssctAftWqltBod[idx] = calculateAverage(Number(inflAssctAftWqltBod[idx]), Number(inflAssctAftWqltBodCnt[idx]));
inflAssctAftWqltToc[idx] = calculateAverage(Number(inflAssctAftWqltToc[idx]), Number(inflAssctAftWqltTocCnt[idx]));
inflAssctAftWqltSs[idx] = calculateAverage(Number(inflAssctAftWqltSs[idx]), Number(inflAssctAftWqltSsCnt[idx]));
inflAssctAftWqltTn[idx] = calculateAverage(Number(inflAssctAftWqltTn[idx]), Number(inflAssctAftWqltTnCnt[idx]));
inflAssctAftWqltTp[idx] = calculateAverage(Number(inflAssctAftWqltTp[idx]), Number(inflAssctAftWqltTpCnt[idx]));
inflAssctBfrWqltBod[idx] = calculateAverage(Number(inflAssctBfrWqltBod[idx]), Number(inflAssctBfrWqltBodCnt[idx]));
inflAssctBfrWqltToc[idx] = calculateAverage(Number(inflAssctBfrWqltToc[idx]), Number(inflAssctBfrWqltTocCnt[idx]));
inflAssctBfrWqltSs[idx] = calculateAverage(Number(inflAssctBfrWqltSs[idx]), Number(inflAssctBfrWqltSsCnt[idx]));
inflAssctBfrWqltTn[idx] = calculateAverage(Number(inflAssctBfrWqltTn[idx]), Number(inflAssctBfrWqltTnCnt[idx]));
inflAssctBfrWqltTp[idx] = calculateAverage(Number(inflAssctBfrWqltTp[idx]), Number(inflAssctBfrWqltTpCnt[idx]));
efflWqltBod[idx] = calculateAverage(Number(efflWqltBod[idx]), Number(efflWqltBodCnt[idx]));
efflWqltCod[idx] = calculateAverage(Number(efflWqltCod[idx]), Number(efflWqltCodCnt[idx]));
efflWqltToc[idx] = calculateAverage(Number(efflWqltToc[idx]), Number(efflWqltTocCnt[idx]));
efflWqltSs[idx] = calculateAverage(Number(efflWqltSs[idx]), Number(efflWqltSsCnt[idx]));
efflWqltTn[idx] = calculateAverage(Number(efflWqltTn[idx]), Number(efflWqltTnCnt[idx]));
efflWqltTp[idx] = calculateAverage(Number(efflWqltTp[idx]), Number(efflWqltTpCnt[idx]));
@@ -1558,13 +1715,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
inflAmnt[0] = calculateAverage(calculateTotal(inflAmnt), dataIsCount);
fcltyCpct[0] = calculateTotal(fcltyCpct);
inflAssctAftWqltBod[0] = Number((calculateTotal(inflAssctAftWqltBod)/7).toFixed(1));
inflAssctAftWqltToc[0] = Number((calculateTotal(inflAssctAftWqltToc)/7).toFixed(1));
inflAssctAftWqltSs[0] = Number((calculateTotal(inflAssctAftWqltSs)/7).toFixed(1));
inflAssctAftWqltTn[0] = Number((calculateTotal(inflAssctAftWqltTn)/7).toFixed(3));
inflAssctAftWqltTp[0] = Number((calculateTotal(inflAssctAftWqltTp)/7).toFixed(3));
inflAssctBfrWqltBod[0] = Number((calculateTotal(inflAssctBfrWqltBod)/7).toFixed(1));
inflAssctBfrWqltToc[0] = Number((calculateTotal(inflAssctBfrWqltToc)/7).toFixed(1));
inflAssctBfrWqltSs[0] = Number((calculateTotal(inflAssctBfrWqltSs)/7).toFixed(1));
inflAssctBfrWqltTn[0] = Number((calculateTotal(inflAssctBfrWqltTn)/7).toFixed(3));
inflAssctBfrWqltTp[0] = Number((calculateTotal(inflAssctBfrWqltTp)/7).toFixed(3));
efflWqltBod[0] = Number((calculateTotal(efflWqltBod)/7).toFixed(1));
efflWqltCod[0] = Number((calculateTotal(efflWqltCod)/7).toFixed(1));
efflWqltToc[0] = Number((calculateTotal(efflWqltToc)/7).toFixed(1));
efflWqltSs[0] = Number((calculateTotal(efflWqltSs as number[])/7).toFixed(1));
efflWqltTn[0] = Number((calculateTotal(efflWqltTn as number[])/7).toFixed(3));
efflWqltTp[0] = Number((calculateTotal(efflWqltTp as number[])/7).toFixed(3));
@@ -1581,13 +1738,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
dsInflWqltSs: dsInflWqltSs[index] ? Number(dsInflWqltSs[index].toFixed(1)) : '',
dsInflWqltTn: dsInflWqltTn[index] ? dsInflWqltTn[index].toFixed(3) : '',
dsInflWqltTp: dsInflWqltTp[index] ? dsInflWqltTp[index].toFixed(3) : '',
inflAssctAftWqltBod: inflAssctAftWqltBod[index] ? Number(inflAssctAftWqltBod[index].toFixed(1)) : '',
inflAssctAftWqltToc: inflAssctAftWqltToc[index] ? Number(inflAssctAftWqltToc[index].toFixed(1)) : '',
inflAssctAftWqltSs: inflAssctAftWqltSs[index] ? Number(inflAssctAftWqltSs[index].toFixed(1)) : '',
inflAssctAftWqltTn: inflAssctAftWqltTn[index] ? inflAssctAftWqltTn[index].toFixed(3) : '',
inflAssctAftWqltTp: inflAssctAftWqltTp[index] ? inflAssctAftWqltTp[index].toFixed(3) : '',
inflAssctBfrWqltBod: inflAssctBfrWqltBod[index] ? Number(inflAssctBfrWqltBod[index].toFixed(1)) : '',
inflAssctBfrWqltToc: inflAssctBfrWqltToc[index] ? Number(inflAssctBfrWqltToc[index].toFixed(1)) : '',
inflAssctBfrWqltSs: inflAssctBfrWqltSs[index] ? Number(inflAssctBfrWqltSs[index].toFixed(1)) : '',
inflAssctBfrWqltTn: inflAssctBfrWqltTn[index] ? inflAssctBfrWqltTn[index].toFixed(3) : '',
inflAssctBfrWqltTp: inflAssctBfrWqltTp[index] ? inflAssctBfrWqltTp[index].toFixed(3) : '',
efflWqltBod: efflWqltBod[index] ? Number(efflWqltBod[index].toFixed(1)) : '',
efflWqltCod: efflWqltCod[index] ? Number(efflWqltCod[index].toFixed(1)) : '',
efflWqltToc: efflWqltToc[index] ? Number(efflWqltToc[index].toFixed(1)) : '',
efflWqltSs: efflWqltSs[index] ? Number(efflWqltSs[index].toFixed(1)) : '',
efflWqltTn: efflWqltTn[index] ? efflWqltTn[index].toFixed(3) : '',
efflWqltTp: efflWqltTp[index] ? efflWqltTp[index].toFixed(3) : ''
@@ -1607,13 +1764,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
설계유입수질SS: item.dsInflWqltSs ? Number(Number(item.dsInflWqltSs).toFixed(1)) : '',
설계유입수질TN: item.dsInflWqltTn ? Number(item.dsInflWqltTn).toFixed(3) : '',
설계유입수질TP: item.dsInflWqltTp ? Number(item.dsInflWqltTp).toFixed(3) : '',
유입수질BOD: item.inflAssctAftWqltBod ? Number(Number(item.inflAssctAftWqltBod).toFixed(1)) : '',
유입수질TOC: item.inflAssctAftWqltToc ? Number(Number(item.inflAssctAftWqltToc).toFixed(1)) : '',
유입수질SS: item.inflAssctAftWqltSs ? Number(Number(item.inflAssctAftWqltSs).toFixed(1)) : '',
유입수질TN: item.inflAssctAftWqltTn ? Number(item.inflAssctAftWqltTn).toFixed(3) : '',
유입수질TP: item.inflAssctAftWqltTp ? Number(item.inflAssctAftWqltTp).toFixed(3) : '',
유입수질BOD: item.inflAssctBfrWqltBod ? Number(Number(item.inflAssctBfrWqltBod).toFixed(1)) : '',
유입수질TOC: item.inflAssctBfrWqltToc ? Number(Number(item.inflAssctBfrWqltToc).toFixed(1)) : '',
유입수질SS: item.inflAssctBfrWqltSs ? Number(Number(item.inflAssctBfrWqltSs).toFixed(1)) : '',
유입수질TN: item.inflAssctBfrWqltTn ? Number(item.inflAssctBfrWqltTn).toFixed(3) : '',
유입수질TP: item.inflAssctBfrWqltTp ? Number(item.inflAssctBfrWqltTp).toFixed(3) : '',
방류수질BOD: item.efflWqltBod ? Number(Number(item.efflWqltBod).toFixed(1)) : '',
방류수질TOC: item.efflWqltCod ? Number(Number(item.efflWqltCod).toFixed(1)) : '',
방류수질TOC: item.efflWqltToc ? Number(Number(item.efflWqltToc).toFixed(1)) : '',
방류수질SS: item.efflWqltSs ? Number(Number(item.efflWqltSs).toFixed(1)) : '',
방류수질TN: item.efflWqltTn ? Number(item.efflWqltTn).toFixed(3) : '',
방류수질TP: item.efflWqltTp ? Number(item.efflWqltTp).toFixed(3) : '',
@@ -1627,61 +1784,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
...state.RainManage,
rainManageList: filteredData as RainManageListProps[],
excelList: excelList,
isLoadingRainManage : false,
} : {
...state.RainManage,
rainManageList: filteredData as RainManageListProps[],
isLoadingRainManage : false,
}
}));
},
searchDrainageEquipment: async (searchYear: string, fcltyCd: string, isExcel : boolean) => {
await fetchDrainageEquipment(searchYear, fcltyCd);
/* if(res == null || res.data.wqltObjs == null || res.data.wqltObjs.length === 0) {
set((state: DashBoardType) => ({
...state.RainManage,
rainManageList: [],
}));
return;
} */
/* if(isExcel){
res.data.wqltObjs.forEach((item) => {
excelList.push({
강우량: item.rainItem,
강우조건비율: item.rainRate || 0,
일수: item.rainDay || 0,
유입유량: item.inflAmnt || 0,
시설용량대비: item.fctCpc || 0,
설계유입수질BOD: item.dsInflWqltBod || 0,
설계유입수질TOC: item.dsInflWqltCod || 0,
설계유입수질SS: item.dsInflWqltSs || 0,
설계유입수질TN: item.dsInflWqltTn || 0,
설계유입수질TP: item.dsInflWqltTp || 0,
유입수질BOD: item.inflAssctAftWqltBod || 0,
유입수질COD: item.inflAssctAftWqltToc || 0,
유입수질SS: item.inflAssctAftWqltSs || 0,
유입수질TN: item.inflAssctAftWqltTn || 0,
유입수질TP: item.inflAssctAftWqltTp || 0,
방류수질BOD: item.efflWqltBod || 0,
방류수질COD: item.efflWqltCod || 0,
방류수질SS: item.efflWqltSs || 0,
방류수질TN: item.efflWqltTn || 0,
방류수질TP: item.efflWqltTp || 0,
});
});
} */
set((state: DashBoardType) => ({
...state,
DrainageEquipment: isExcel ? {
...state.DrainageEquipment,
drainageEquipmentList: drainageEquipmentList,
drainageEquipmentExcelList: [],
} : {
...state.DrainageEquipment,
drainageEquipmentList: drainageEquipmentList,
}
}));
}
}
}
@@ -217,6 +217,7 @@ export type FacilityPrecipitationType = {
facilityPrecipitation: FacilityPrecipitationProps[];
excelList: ExcelType[];
facilityPrecipitationCount: number;
isLoading: boolean;
},
PrecipitationDetail : {
@@ -239,7 +240,8 @@ export const facilityPrecipitationInitState: FacilityPrecipitationType = {
upHeadList3 : upHeadList3,
facilityPrecipitation : facilityPrecipitation,
excelList : [],
facilityPrecipitationCount : 0
facilityPrecipitationCount : 0,
isLoading : true,
},
PrecipitationDetail : {
@@ -254,6 +256,14 @@ export type FacilityPrecipitationStore = FacilityPrecipitationType & FacilityPre
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) => {
set((state: FacilityPrecipitationType) => ({
...state,
FacilityPrecipitation: {
...state.FacilityPrecipitation,
isLoading: true,
},
}));
const res = await fetchFacilityPrecipitationList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
const data = res.data;
const excelDownList: ExcelType[] = [];
@@ -293,13 +303,15 @@ export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitatio
...state.FacilityPrecipitation,
facilityPrecipitation: res.data,
facilityPrecipitationCount: res.count,
isLoading : false,
}:{
...state.FacilityPrecipitation,
excelList: excelDownList,
isLoading : false,
},
PrecipitationDetail:{
...state.PrecipitationDetail,
gridListPrecipitationDetail: res.detailData
gridListPrecipitationDetail: res.detailData,
}
}))
}
+106 -84
View File
@@ -21,12 +21,16 @@ export interface FacilityWaterQltyProps {
sggNm: string,
addr: string,
fctCpc: number,
inflAssctBfrWqltBod: string | '',
inflAssctAftWqltBod: string | '',
inflAssctBfrWqltToc: string | '',
inflAssctAftWqltToc: string | '',
inflAssctBfrWqltSs: string | '',
inflAssctAftWqltSs: string | '',
inflAssctBfrWqltTn: string | '',
inflAssctAftWqltTn: string | '',
inflAssctAftWqltTp: string | '',
inflAssctBfrWqltTp: string | '',
inflAssctAftWqltTp: string | '',
efflWqltBod: string | '',
efflWqltToc: string | '',
efflWqltSs: string | '',
@@ -127,11 +131,11 @@ const upHeadList1: TableUpperProps[] = [
{ 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: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row: 1 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row: 1 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row: 1 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 4, align: "right", row: 1 },
{ id: "inflAssctBfrWqltTp", 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: "efflWqltToc", 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 },
@@ -151,11 +155,11 @@ const upHeadList2: TableUpperProps[] = [
{ 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: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
{ id: "inflAssctBfrWqltTp", 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: "efflWqltToc", 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 },
@@ -179,11 +183,11 @@ const upHeadList3: TableUpperProps[] = [
{ 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: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe3", upSequnce: 1, align: "right", row:1 },
{ id: "inflAssctBfrWqltToc", title: "TOC\n(COD)\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe3", upSequnce: 3, align: "right", row:1 },
{ id: "inflAssctBfrWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe3", upSequnce: 2, align: "right", row:1 },
{ id: "inflAssctBfrWqltTp", 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: "efflWqltToc", 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 },
@@ -197,10 +201,10 @@ const upHeadList3: TableUpperProps[] = [
// 처리시설 수질현황 헤더(모달-연간)
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: "inflAssctBfrWqltBod", title: "BOD\n(mg/L)", upName: "upChangeRe1", upSequnce: 1, align: "right" },
{ id: "inflAssctBfrWqltToc", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe1", upSequnce: 2, align: "right" },
{ id: "inflAssctBfrWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe1", upSequnce: 3, align: "right" },
{ id: "inflAssctBfrWqltTn", 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: "efflWqltToc", title: "TOC(COD)\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" },
@@ -288,6 +292,7 @@ export type FacilityWaterQltyType = {
upHeadList1: TableUpperProps[];
upHeadList2: TableUpperProps[];
upHeadList3: TableUpperProps[];
isLoading: boolean;
},
FacilityWaterQltyModal: {
@@ -311,6 +316,7 @@ export const facilityWaterQltyInitState: FacilityWaterQltyType = {
facilityWaterQltyCount: 0,
facilityWaterQltyList: [],
excelList: [],
isLoading: true,
isInit: false,
mainLabelArray: mainLabelArray,
upHeadList1: upHeadList1,
@@ -361,8 +367,8 @@ export type FacilityWaterQltyActions = {
* @returns : 없음
* @description : 시설수질리스트 타입의 데이터를 표현 방식으로 바꿔주는 함수
* - msrDt : YYYY-MM-DD 형식으로 변환
* - inflAssctAftWqltBod : 소수점 1자리까지 표현
* - inflAssctAftWqltTn : 소수점 1자리까지 표현
* - inflAssctBfrWqltBod : 소수점 1자리까지 표현
* - inflAssctBfrWqltTn : 소수점 1자리까지 표현
* - inflAssctBfrWqltTp : 소수점 1자리까지 표현
* - efflWqltBod : 소수점 2자리까지 표현
* - efflWqltTn : 소수점 2자리까지 표현
@@ -391,41 +397,48 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
* @param fcltyNm : 시설명
*/
searchFacilityWaterQltyList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
set((state: FacilityWaterQltyType) => ({
...state,
FacilityWaterQltyMain: {
...state.FacilityWaterQltyMain,
isLoading: true,
},
}));
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.inflAssctBfrWqltTn) {
item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 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.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.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
}
if(item.inflAssctAftWqltBod){
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
if(item.inflAssctBfrWqltBod){
item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 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.inflAssctBfrWqltSs){
item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 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.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
@@ -450,11 +463,11 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
시설이름: item.bscFctNm,
주소: item.addr,
용량: item.fctCpc,
유입BOD: item.inflAssctAftWqltBod,
유입TOC: item.inflAssctAftWqltToc,
유입SS: item.inflAssctAftWqltSs,
유입TN: item.inflAssctAftWqltTn,
유입TP: item.inflAssctAftWqltTp,
유입BOD: item.inflAssctBfrWqltBod,
유입TOC: item.inflAssctBfrWqltToc,
유입SS: item.inflAssctBfrWqltSs,
유입TN: item.inflAssctBfrWqltTn,
유입TP: item.inflAssctBfrWqltTp,
유출BOD: item.efflWqltBod,
유출TOC: item.efflWqltToc,
유출SS: item.efflWqltSs,
@@ -476,10 +489,12 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
...state.FacilityWaterQltyMain,
facilityWaterQltyList: rtnData,
facilityWaterQltyCount: res.count,
isLoading : false,
}:{
...state.FacilityWaterQltyMain,
excelList: excelDownList,
}
isLoading : false,
},
}))
},
@@ -556,47 +571,54 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
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 data = res.data.wqltObjs;
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
for(let idx = 0; idx < data.length; idx++) {
const item = data[idx];
if(item){
if(item.infoRnDay && Number(item.infoRnDay) > 3) {
item.rainEffectDay = 1;
} else {
item.rainEffectDay = 0;
}
}
}
const rtnData = tmpData.map((item: FacilityWaterQltyProps) => {
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
for(let idx = 0; idx < data.length; idx++) {
if(data[idx]) {
// 하루 전이 강우영향일(3 이상)인 경우
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) {
data[idx]!.rainEffectDay = 1;
}
// 이틀 전이 강우영향일(3 이상)인 경우
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) {
data[idx]!.rainEffectDay = 1;
}
}
}
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) > 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) > 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
}
}
const rtnData = data.map((item: FacilityWaterQltyProps) => {
dataFormSetting(item)
if(item.inflAssctAftWqltTn) {
item.inflAssctAftWqltTn = Number(Math.round(Number(item.inflAssctAftWqltTn) * 1000)/1000).toFixed(3);
if(item.inflAssctBfrWqltTn) {
item.inflAssctBfrWqltTn = Number(Math.round(Number(item.inflAssctBfrWqltTn) * 1000)/1000).toFixed(3);
}
if(item.efflWqltTn){
item.efflWqltTn = Number(Math.round(Number(item.efflWqltTn) * 1000)/1000).toFixed(3);
@@ -607,26 +629,26 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType
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.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
}
if(item.inflAssctAftWqltBod){
item.inflAssctAftWqltBod = Number(Math.round(Number(item.inflAssctAftWqltBod) * 10)/10).toFixed(1);
if(item.inflAssctBfrWqltBod){
item.inflAssctBfrWqltBod = Number(Math.round(Number(item.inflAssctBfrWqltBod) * 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.inflAssctBfrWqltSs){
item.inflAssctBfrWqltSs = Number(Math.round(Number(item.inflAssctBfrWqltSs) * 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.inflAssctBfrWqltToc){
item.inflAssctBfrWqltToc = Number(Math.round(Number(item.inflAssctBfrWqltToc) * 10)/10).toFixed(1);
}
if(item.efflWqltToc){
item.efflWqltToc = Number(Math.round(Number(item.efflWqltToc) * 10)/10).toFixed(1);
+48 -35
View File
@@ -170,7 +170,6 @@ const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: s
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);
@@ -220,6 +219,7 @@ export type FlowRateSearchType = {
flowRateList:flowRateListProps[];
flowRateCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
FlowRateModal : {
@@ -253,7 +253,8 @@ export const flowRateSearchInitState:FlowRateSearchType = {
upHeadList3 : upHeadList3,
flowRateList : flowRateList,
flowRateCount : 0,
excelList: []
excelList: [],
isLoading: true,
},
FlowRateModal : {
isInit : false,
@@ -265,6 +266,13 @@ export const flowRateSearchInitState:FlowRateSearchType = {
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) => {
set((state: FlowRateSearchType) => ({
...state,
FlowRateList: {
...state.FlowRateList,
isLoading: true,
},
}));
const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
const data = res.data;
const excelDownList: ExcelType[] = [];
@@ -303,54 +311,59 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow
...state.FlowRateList,
flowRateList: rtnData,
flowRateCount: res.count,
isLoading : false,
}:{
...state.FlowRateList,
excelList: excelDownList,
}
isLoading : false,
},
}))
},
searchFlowRateModalList: async (bscFctCd: string, searchYear: string) => {
const res = await fetchFlowRateModalList(bscFctCd, searchYear);
const data = res.data;
const tmpData:FlowRateModalProps[] = [];
data.forEach((item: FlowRateModalProps) => {
if(item.infoRnDay && item.infoRnDay.toString().trim() === 'x') {
item.infoRnDay = '';
}
});
// facilityPrecipitation의 rainEffectDay 계산 로직을 적용
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
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;
if(item){
if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) {
item.rainEffectDay = 1;
} else {
if(idx >= 2) {
if(Number(data[idx-1].infoRnDay) >= 3 || Number(data[idx-2].infoRnDay) >= 3) {
rainEffectDay = 1;
}
}
item.rainEffectDay = 0;
}
} 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) => {
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
for(let idx = 0; idx < data.length; idx++) {
if(data[idx]) {
// 하루 전이 강우영향일(3 이상)인 경우
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.rainEffectDay = 1;
}
// 이틀 전이 강우영향일(3 이상)인 경우
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.rainEffectDay = 1;
}
}
}
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
}
}
const rtnData = data.map((item: FlowRateModalProps) => {
item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0)
dataFormSetting(item);
return item;
+36 -4
View File
@@ -1,6 +1,7 @@
import DataForm from "@/app/components/common/DataForm";
import type { TableUpperProps } from "../dashboard";
import { getFetch } from "@/app/components/api";
import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput";
export type { TableUpperProps };
/**====================================
* Store - 타입
@@ -145,6 +146,7 @@ export type PlanSewageType = {
planSewageList: PlanSewageProps[];
planSewageCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
}
@@ -161,7 +163,8 @@ export const planSewageInitState: PlanSewageType = {
upHeadList3 : upHeadList3,
planSewageList : planSewageList,
planSewageCount : 0,
excelList : []
excelList : [],
isLoading : true,
},
}
@@ -170,16 +173,43 @@ 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) => {
set((state: PlanSewageType) => ({
...state,
PlanSewage: {
...state.PlanSewage,
isLoading: true,
},
}));
const res = await fetchPlanSewageList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
const excelDownList: ExcelType[] = [];
console.log('res' , res.data);
const data = res.data
const processedData = await Promise.all(data.map(async (item:PlanSewageProps) => {
const res2 = await getFetch('fo', '/fclt/flow/' + item.bscFctCd + '/' + searchYear) as ApiResponse;
const calData = calRainEffectDay(res2.data, 'SUNNY');
let sumInflAmntSunny = 0;
let avgInflAmntSunny = 0;
calData.forEach((flowItem:FlowDataItem) => {
sumInflAmntSunny += Number(flowItem.inflAmnt);
})
avgInflAmntSunny = sumInflAmntSunny / calData.length;
item.avgInflAmntSunny = avgInflAmntSunny;
if(item.bscFctCd === '11200PB001R'){
console.log('avgInflAmntSunny : ',item.avgInflAmntSunny);
console.log('calData : ',calData);
}
return item;
}));
/**
* 결과데이터 계산
* (1) 여유용량 = 시설용량 - 건기시 평균유량
* (2) 변동부하율 = 건기시 일최대 유량/일평균유량(기준 최근 3개년)
* (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100
*/
const resultData = res.data.map((item:PlanSewageProps) => {
const resultData = processedData.map((item:PlanSewageProps) => {
console.log('item.fctCpc : ',item.fctCpc);
console.log('item.avgInflAmntSunny : ',item.avgInflAmntSunny);
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;
@@ -216,10 +246,12 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy
...state.PlanSewage,
planSewageList: resultData,
planSewageCount: res.count,
isLoading : false,
}:{
...state.PlanSewage,
excelList: excelDownList,
}
isLoading : false,
},
}))
}
}
+66 -45
View File
@@ -1,6 +1,7 @@
import { getFetchAreaList, postFetch } from "@/app/components/api";
import type { TableUpperProps } from "../dashboard";
import { postFetch } from "@/app/components/api";
import DataForm from "@/app/components/common/DataForm";
import { fetchPlanInfo } from "../common";
import type { TableUpperProps } from "../dashboard";
export type { TableUpperProps };
/**====================================
* Store - 타입
@@ -227,25 +228,14 @@ const fetchFacilityDetailInfo = async (swtrmtFcltCd: string) => {
};
// 시설정보 리스트 데이터 호출(구분 선택 후 시설명 있을 경우)
const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : string | undefined, sggNm : string | undefined, targetYear : string | undefined ): Promise<{data:ProcessAreaProps[], count:number}> => {
const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm : string | undefined, sggNm : string | undefined, targetYear : string | undefined, set : (fn: (state: ProcessAreaType) => ProcessAreaType) => void): 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);
const res = await fetchPlanInfo(targetYear, ctpvNm, sggNm, undefined);
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') {
/* 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 + '년)';
@@ -257,6 +247,19 @@ const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm :
head.title = '4단계\n(' + item.yrDc4 + '년)';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계(' + item.yrDt4 + '년)';
} */
if (head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계';
}
});
const res = await fetchFacilityDetailInfo(item.swtrmtFcltCd);
@@ -280,6 +283,13 @@ const fetchProcessAreaList = async (pageNo : number, pageSize : number, ctpvNm :
}
} catch (error) {
console.error('시설계획정보를 가져오는데 실패했습니다:', error);
set((state) => ({
...state,
ProcessArea : {
...state.ProcessArea,
isLoading : false
}
}));
return {data: [], count: 0};
}
};
@@ -304,6 +314,7 @@ export type ProcessAreaType = {
processAreaList: ProcessAreaProps[];
processAreaCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
ProcessAreaDetail : {
@@ -328,7 +339,8 @@ export const processAreaInitState: ProcessAreaType = {
upHeadList1 : upHeadList1,
processAreaList : processAreaList,
processAreaCount : 0,
excelList : []
excelList : [],
isLoading : true,
},
ProcessAreaDetail : {
@@ -355,7 +367,14 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set:
* @param pageSize : 페이지 크기
*/
searchProcessAreaList: async ( pageNo:number, pageSize:number, ctpvNm?:string, sggNm?:string, targetYear?:string) => {
const res = await fetchProcessAreaList(pageNo, pageSize, ctpvNm, sggNm, targetYear);
set((state: ProcessAreaType) => ({
...state,
ProcessArea: {
...state.ProcessArea,
isLoading: true,
},
}));
const res = await fetchProcessAreaList(pageNo, pageSize, ctpvNm, sggNm, targetYear, set);
res.data.forEach((item:ProcessAreaProps) => {
DataForm({ type: 'float1', column: 'fctCpc', item:item as unknown as Record<string, unknown>});
})
@@ -400,9 +419,11 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set:
...state.ProcessArea,
processAreaList: res.data,
processAreaCount: res.count,
isLoading : false,
}:{
...state.ProcessArea,
excelList: excelDownList,
isLoading : false,
},
}))
},
@@ -411,51 +432,51 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set:
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 + '년)';
}
});
upHeadListFcltyImproveInfo.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = rtnData.yr? '현재\n(' + rtnData.yr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = rtnData.yrDc1? '1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = rtnData.yrDc2? '2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = rtnData.yrDc3? '3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = rtnData.yrDc4? '4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = rtnData.yrDt4? '기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계';
}
});
upHeadListProcessAreaPlan.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재\n(' + rtnData.yr + '년)';
head.title = rtnData.yr? '현재\n(' + rtnData.yr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
head.title = rtnData.yrDc1?'1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
head.title = rtnData.yrDc2?'2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
head.title = rtnData.yrDc3? '3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
head.title = rtnData.yrDc4?'4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
head.title = rtnData.yrDt4?'기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계';
}
});
upHeadListProcessPopulation.forEach((head:TableUpperProps) => {
if(head.id === 'planSwageQntSum' || head.id === 'swtrmtPpltnCnt' || head.id === 'swtrmtZoneArea') {
head.title = '현재\n(' + rtnData.yr + '년)';
head.title = rtnData.yr?'현재\n(' + rtnData.yr + '년)':head.title = '현재';
} else if(head.id === 'planSwageQntSumDc1' || head.id === 'swtrmtPpltnCntDc1' || head.id === 'swtrmtZoneAreaDc1') {
head.title = '1단계\n(' + rtnData.yrDc1 + '년)';
head.title = rtnData.yrDc1?'1단계\n(' + rtnData.yrDc1 + '년)':head.title = '1단계';
} else if(head.id === 'planSwageQntSumDc2' || head.id === 'swtrmtPpltnCntDc2' || head.id === 'swtrmtZoneAreaDc2') {
head.title = '2단계\n(' + rtnData.yrDc2 + '년)';
head.title = rtnData.yrDc2?'2단계\n(' + rtnData.yrDc2 + '년)':head.title = '2단계';
} else if(head.id === 'planSwageQntSumDc3' || head.id === 'swtrmtPpltnCntDc3' || head.id === 'swtrmtZoneAreaDc3') {
head.title = '3단계\n(' + rtnData.yrDc3 + '년)';
head.title = rtnData.yrDc3?'3단계\n(' + rtnData.yrDc3 + '년)':head.title = '3단계';
} else if(head.id === 'planSwageQntSumDc4' || head.id === 'swtrmtPpltnCntDc4' || head.id === 'swtrmtZoneAreaDc4') {
head.title = '4단계\n(' + rtnData.yrDc4 + '년)';
head.title = rtnData.yrDc4?'4단계\n(' + rtnData.yrDc4 + '년)':head.title = '4단계';
} else if(head.id === 'planSwageQntSumDt4' || head.id === 'swtrmtPpltnCntDt4' || head.id === 'swtrmtZoneAreaDt4') {
head.title = '기승인\n4단계(' + rtnData.yrDt4 + '년)';
head.title = rtnData.yrDt4?'기승인\n4단계(' + rtnData.yrDt4 + '년)':head.title = '기승인\n4단계';
}
});
+20 -1
View File
@@ -517,6 +517,7 @@ export type ProcessFacilityType = {
processFacilityList:facilityListProps[];
processFacilityCount:number;
excelList : ExcelType[];
isLoading: boolean;
},
ProcessFacilityDetail : {
@@ -551,7 +552,8 @@ export const processFacilityInitState:ProcessFacilityType = {
upHeadList3 : upHeadList3,
processFacilityList : processFacilityList,
processFacilityCount:1,
excelList : []
excelList : [],
isLoading : true,
},
ProcessFacilityDetail : {
@@ -588,6 +590,13 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
* @param pageSize : 페이지 크기
*/
searchProcessFacility: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => {
set((state: ProcessFacilityType) => ({
...state,
ProcessFacilityList: {
...state.ProcessFacilityList,
isLoading: true,
},
}));
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>});
@@ -635,9 +644,11 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
...state.ProcessFacilityList,
processFacilityList: res.data,
processFacilityCount: res.count,
isLoading: false,
}:{
...state.ProcessFacilityList,
excelList: excelDownList,
isLoading: false,
},
}))
},
@@ -648,6 +659,13 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
* @param pageSize : 페이지 크기
*/
searchProcessFacilitySearching: async (pageNo:number, pageSize:number, partValue?:string, nameCd?:string, fcltCpct?:string, oprtngSttsCd?:string, facilityPartValue?:string, facilityName?:string) => {
set((state: ProcessFacilityType) => ({
...state,
ProcessFacilityList: {
...state.ProcessFacilityList,
isLoading: true,
},
}));
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>});
@@ -665,6 +683,7 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio
...state.ProcessFacilityList,
processFacilityList: res.data,
processFacilityCount: res.count,
isLoading: false,
},
}))
},
+14 -2
View File
@@ -183,6 +183,7 @@ export type RdiType = {
rdiList: RdiProps[]; // Changed from facilityAreaProps to ProcessAreaProps
rdiCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
}
@@ -199,7 +200,8 @@ export const rdiInitState: RdiType = {
upHeadList3 : upHeadList3,
rdiList : rdiList,
rdiCount : 2,
excelList : []
excelList : [],
isLoading : true,
}
}
@@ -220,6 +222,14 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
console.log("tableActionsExport");
return {
searchRdiList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
set((state: RdiType) => ({
...state,
Rdi: {
...state.Rdi,
isLoading: true,
},
}));
const res = await fetchRdiList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm);
const data = res.data;
const excelDownList: ExcelType[] = [];
@@ -264,10 +274,12 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio
...state.Rdi,
rdiList: rtnData,
rdiCount: res.count,
isLoading : false,
}:{
...state.Rdi,
excelList: excelDownList,
}
isLoading : false,
},
}))
},
}
+88 -13
View File
@@ -126,7 +126,6 @@ const tempSewageOccurList:modalTableType[] = []
const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
// 20250701임시시
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);
@@ -145,7 +144,7 @@ const fetchSewageOccurList = async (pageNo: number, pageSize: number, searchYear
====================================*/
export type SewageOccurActions = {
searchSewageOccurList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
searchSewageOccurDetailList: (bscFctCd: string, searchYear: string) => void;
searchSewageOccurDetailList: (bscFctCd: string, searchYear: string, startYearMonth?: string, endYearMonth?: string) => void;
}
export type SewageOccurType = {
@@ -162,6 +161,7 @@ export type SewageOccurType = {
sewageOccurList: SewageOccurProps[]; // Changed from facilityAreaProps to ProcessAreaProps
sewageOccurCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
SewageOccurDetail : {
@@ -184,7 +184,8 @@ export const sewageOccurInitState: SewageOccurType = {
upHeadList3 : upHeadList3,
sewageOccurList : sewageOccurList,
sewageOccurCount : 2,
excelList : []
excelList : [],
isLoading : true,
},
SewageOccurDetail : {
@@ -197,14 +198,15 @@ export const sewageOccurInitState: SewageOccurType = {
export type SewageOccurStore = SewageOccurType & SewageOccurActions;
// Add type definitions for API responses
type FlowDataItem = {
export type FlowDataItem = {
inflAmnt: string | number;
infoRnDay: string | number;
bscFctCd: string;
msrDt: string;
rainEffectDay?: number;
}
type FlowResponse = {
export type FlowResponse = {
data: FlowDataItem[];
count: number;
}
@@ -212,28 +214,84 @@ type FlowResponse = {
export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
return {
searchSewageOccurList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
set((state: SewageOccurType) => ({
...state,
SewageOccur: {
...state.SewageOccur,
isLoading: true,
},
}));
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.swageChangePercent = 80;
const bscFctCd = item.bscFctCd;
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse;
let sumChungcunDay = 0;
let chungcunSumFlow = 0;
let totWaterUsage = 0;
if(bscFctCd === '11200PB001R'){
console.log('res2.data : ',res2.data);
}
// 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일)
for(let idx = 0; idx < res2.data.length; idx++) {
const item = res2.data[idx];
if(item){
if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) {
item.rainEffectDay = 1;
} else {
item.rainEffectDay = 0;
}
}
}
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
for(let idx = 0; idx < res2.data.length; idx++) {
if(res2.data[idx]) {
// 하루 전이 강우영향일(3 이상)인 경우
if(idx > 0 && res2.data[idx-1]?.infoRnDay && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
res2.data[idx]!.rainEffectDay = 1;
}
// 이틀 전이 강우영향일(3 이상)인 경우
if(idx > 1 && res2.data[idx-2]?.infoRnDay && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
res2.data[idx]!.rainEffectDay = 1;
}
}
}
for(let idx = 0; idx < res2.data.length; idx++) {
if(res2.data[idx] && res2.data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(res2.data[idx-1]?.infoRnDay && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
res2.data[idx]!.infoRnDay = res2.data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(res2.data[idx-2]?.infoRnDay && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
res2.data[idx]!.infoRnDay = res2.data[idx-2]!.infoRnDay;
}
}
}
}
if(bscFctCd === '11200PB001R'){
console.log('calData : ',res2.data);
}
res2.data.forEach((item: FlowDataItem) => {
if(Number(item.infoRnDay) ===0){
if(Number(item.rainEffectDay) === 0){
chungcunSumFlow += Number(item.inflAmnt);
sumChungcunDay += 1;
}
totWaterUsage += Number(item.inflAmnt);
});
const avg = totWaterUsage /res2.count;
@@ -250,17 +308,34 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
...state.SewageOccur,
sewageOccurList: calData,
sewageOccurCount: res.count,
isLoading : false,
}:{
...state.SewageOccur,
excelList: [],
}
isLoading : false,
},
}))
},
searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string) => {
searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string, startYearMonth?: string, endYearMonth?: string) => {
const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
const monthData: SewageOccurDetailProps[] = [];
let tot = 0, cnt= 0
let tot = 0, cnt= 0;
console.log('startYearMonth : ', startYearMonth, 'endYearMonth : ', endYearMonth);
if(startYearMonth) {
res.data = res.data.filter((item: FlowDataItem) => {
const month = item.msrDt?.substring(0, 6);
return month >= startYearMonth;
});
}
if(endYearMonth) {
res.data = res.data.filter((item: FlowDataItem) => {
const month = item.msrDt?.substring(0, 6);
return month <= endYearMonth;
});
}
res.data.forEach((item: FlowDataItem) => {
const month = item.msrDt?.substring(4, 6);
const monthIdx = month ? Number(month) - 1 : -1;
@@ -284,7 +359,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => {
monthData.forEach((item, index) => {
item.usege = item.sum/item.cnt *0.65
tableData.push({
msrDt: item.yr+'-'+(index+1>10?String(index+1):'0'+(index+1)),
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
waterUsage: Math.round(item.usege*100) /100,
swageChangePercent: (Math.round((item.usege/item.usege*0.8) * 100) / 100) * 100,
estimationSewage: Math.round(item.usege*0.8 * 100) / 100
+1 -1
View File
@@ -59,7 +59,7 @@ export const StoreZus =
}
) => {
return createStore<FoStore>()((set) => {
LoginApi.login({userId: "admin1gmail", password: "test1234!"})
LoginApi.login({userId: "CLEANWATER", password: "gktneh12!@"})
return {
...initState,
...CommonReducer(set),
+114 -30
View File
@@ -2,8 +2,15 @@ import DataForm from "@/app/components/common/DataForm";
import type { TableUpperProps } from "../dashboard";
import { getFetch } from "@/app/components/api";
import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps } from "./types";
import type { SewageOccurDetailProps } from "../sewageOccur";
export type { TableUpperProps };
// SewageOccurDetailProps 타입을 여기에 정의
export type SewageOccurDetailProps = {
cnt : number,
sum : number,
yr:string,
usege:number
}
/**====================================
* Store - 타입
====================================*/
@@ -75,7 +82,7 @@ const upHeadList3:TableUpperProps[] = [
// 모달
const upHeadListUnderWaterDetail:TableUpperProps[] = [
{ id: "msrDt", title: "날짜" },
{ id: "realSewageInput", title: "실제 하수유입량\n(m³/일)" },
{ id: "realSewageInput", title: "청천시 실제 하수유입량\n(m³/일)" },
{ id: "sewageOccur", title: "오수발생량\n(m³/일)" },
{ id: "underWaterInput", title: "지하수 유입량\n(m³/일)" },
];
@@ -162,13 +169,15 @@ const underWaterDetailList:UnderWaterInputModalProps[] = [
====================================*/
// API response types
interface FlowDataItem {
inflAmnt: number;
export interface FlowDataItem {
inflAmnt: number | string;
infoRnDay: number;
msrDt: string;
rainEffectDay? : number;
sumFlow? : number | string | '';
}
interface ApiResponse {
export interface ApiResponse {
data: FlowDataItem[];
count: number;
}
@@ -209,6 +218,7 @@ export type UnderWaterType = {
underWaterList: UnderWaterProps[]; // Changed from facilityAreaProps to ProcessAreaProps
underWaterCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
UnderWaterDetail : {
@@ -231,7 +241,8 @@ export const underWaterInitState: UnderWaterType = {
upHeadList3 : upHeadList3,
underWaterList : underWaterList,
underWaterCount : 4,
excelList : []
excelList : [],
isLoading : true,
},
UnderWaterDetail : {
@@ -250,9 +261,70 @@ const dataFormSetting=(item : UnderWaterProps)=> {
export type UnderWaterStore = UnderWaterType & UnderWaterActions;
export const calRainEffectDay = (data: FlowDataItem[], weather: string) => {
// 강우영향일 계산 (강우량이 3 이상이면 무조건 강우영향일)
for(let idx = 0; idx < data.length; idx++) {
const item = data[idx];
if(item){
if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) {
item.rainEffectDay = 1;
} else {
item.rainEffectDay = 0;
}
}
}
// 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정
for(let idx = 0; idx < data.length; idx++) {
if(data[idx]) {
// 하루 전이 강우영향일(3 이상)인 경우
if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.rainEffectDay = 1;
}
// 이틀 전이 강우영향일(3 이상)인 경우
if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.rainEffectDay = 1;
}
}
}
for(let idx = 0; idx < data.length; idx++) {
if(data[idx] && data[idx]?.rainEffectDay === 1) {
if(idx > 1){
if(data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-1]!.infoRnDay;
}
}
if(idx > 2){
if(data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) {
data[idx]!.infoRnDay = data[idx-2]!.infoRnDay;
}
}
}
}
let rtnData : FlowDataItem[] = [];
if (weather === 'ALL') {
rtnData = data;
} else if (weather === 'SUNNY') {
rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 0);
} else {
rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 1);
}
return rtnData;
}
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) => {
set((state: UnderWaterType) => ({
...state,
UnderWater: {
...state.UnderWater,
isLoading: true,
},
}));
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) => {
@@ -262,8 +334,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
const bscFctCd = item.bscFctCd;
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse;
let sumChungcunDay = 0;
const calData = calRainEffectDay(res2.data, 'SUNNY');
let chungcunSumFlow = 0;
let sumSummerChungcunDay = 0;
@@ -272,24 +343,25 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
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);
}
calData.forEach((flowItem: FlowDataItem) => {
chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
sumSummerChungcunDay += 1;
sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
}else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){
sumWinterChungcunDay += 1;
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
}
});
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);
const usage = chungcunSumFlow / calData.length;
const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay;
const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay;
item.underWaterInputYear = Math.round((usage-(usage*0.65*0.8)) * 100) / 100;
item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*0.8)) * 100) / 100;
item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*0.8)) * 100) / 100;
return item;
}));
@@ -332,17 +404,30 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
...state.UnderWater,
underWaterList: calData,
underWaterCount: res.count,
isLoading : false,
}:{
...state.UnderWater,
excelList: excelDownList,
}
isLoading : false,
excelList: excelDownList
},
}))
},
unserWaterModal:async (bscFctCd, searchYear)=>{
console.log('searchYear : ', searchYear);
const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
const monthData: SewageOccurDetailProps[] = [];
let tot = 0, cnt= 0
res.data.forEach((item: FlowDataItem) => {
const calData = calRainEffectDay(res.data, 'SUNNY');
let tot = 0, cnt= 0;
let tmpTot = 0;
calData.forEach((item: FlowDataItem) => {
tmpTot += Number(item.inflAmnt);
})
console.log('tmpTot : ', tmpTot/calData.length);
calData.forEach((item: FlowDataItem) => {
const month = item.msrDt?.substring(4, 6);
const monthIdx = month ? Number(month) - 1 : -1;
if (monthIdx >= 0) {
@@ -364,7 +449,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
monthData.forEach((item, index) => {
item.usege = item.sum/item.cnt
tableData.push({
msrDt: item.yr+'-'+(index+1>10?String(index+1):'0'+(index+1)),
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
realSewageInput:Math.round(item.usege*100) /100,
sewageOccur:Math.round(item.usege*0.65*0.8 * 100) / 100,
underWaterInput:Math.round((item.usege-(item.usege*0.65*0.8)) * 100) / 100,
@@ -379,7 +464,6 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy
});
avgWaterUsage = tot/cnt
const newData= [
{
msrDt: '평균',
@@ -17,8 +17,6 @@ export class LoginApiService implements LoginService {
public async login(payload: ILogin): Promise<void> {
try {
console.log(' ENDPOINT.USER_SERVICE.LOGIN ', ENDPOINT.USER_SERVICE.LOGIN)
console.log(payload.userId+' '+payload.password)
const response = await fetch( PROXY_HOST+ ENDPOINT.USER_SERVICE.LOGIN, {
method: "POST",
body: JSON.stringify({
@@ -28,20 +28,20 @@ export const MsSwagePplCol = [
// { id: 'lyrTypeNm', title: '레이어타입명' },
]
export const MsSwagePplCol2 = [
{ id: 'rowNumber', title: '일련번호' },
{ id: 'fcltMngNo', title: '시설 관리번호' },
{ id: 'instMngNo', title: '기관 관리번호' },
{ id: 'rowNumber', title: '일련\n번호' },
{ id: 'fcltMngNo', title: '시설\n관리번호' },
{ id: 'instMngNo', title: '기관\n관리번호' },
{ id: 'instlYmd', title: '설치일자' },
// { id: 'mapshtNo', title: '도엽번호' },
{ id: 'pdmt', title: '관경(mm)' },
{ id: 'prlg', title: '연장(m)' },
{ id: 'avgGrdn', title: '평균구배(m/m)' },
{ id: 'tmptDpth', title: '시점깊이(m)' },
{ id: 'tmptMhlMngNo', title: '시점맨홀 관리번호' },
{ id: 'scendDpth', title: '종점깊이(m)' },
{ id: 'scendMhlMngNo', title: '종점맨홀 관리번호' },
{ id: 'vrtcLen', title: '세로길이(m)' },
{ id: 'wdthLen', title: '가로길이(m)' },
{ id: 'pdmt', title: '관경\n(mm)' },
{ id: 'prlg', title: '연장\n(m)' },
{ id: 'avgGrdn', title: '평균구배\n(m/m)' },
{ id: 'tmptDpth', title: '시점깊이\n(m)' },
{ id: 'tmptMhlMngNo', title: '시점맨홀\n관리번호' },
{ id: 'scendDpth', title: '종점깊이\n(m)' },
{ id: 'scendMhlMngNo', title: '종점맨홀\n관리번호' },
{ id: 'vrtcLen', title: '세로길이\n(m)' },
{ id: 'wdthLen', title: '가로길이\n(m)' },
// { id: 'fcltyShpCd', title: '시설물형태코드' },
// { id: 'fid', title: 'FID' },
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
@@ -287,19 +287,19 @@ export const SwtrmtFcltCol = [
{ id: 'ycrd', title: 'Y좌표' },
// { id: 'oprtngSttsCd', title: '가동상태코드' },
{ id: 'rprs_msrc_cn', title: '대표공법내용' },
{ id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량(mg/L)' },
{ id: 'stty_crtr_toc', title: '법정기준TOC((mg/L))' },
{ id: 'stty_crtr_ss', title: '법정기준SS(mg/L)' },
{ id: 'stty_crtr_tn', title: '법정기준총질소(mg/L)' },
{ id: 'stty_crtr_tph', title: '법정기준총인(mg/L)' },
{ id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수(군수/100mL)' },
// { id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량(mg/L)' },
// { id: 'stty_crtr_toc', title: '법정기준TOC((mg/L))' },
// { id: 'stty_crtr_ss', title: '법정기준SS(mg/L)' },
// { id: 'stty_crtr_tn', title: '법정기준총질소(mg/L)' },
// { id: 'stty_crtr_tph', title: '법정기준총인(mg/L)' },
// { id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수(군수/100mL)' },
{ id: 'bsn_nm', title: '유역명' },
// { id: 'obsrvnSptCd', title: '관측지점코드' },
];
export const SwtrmtFcltCol2 = [
{ id: 'rowNumber', title: '일련번호' },
{ id: 'swtrmtFcltNm', title: '하수처리시설명' },
{ id: 'fcltCpct', title: '시설용량(㎥/d)' },
{ id: 'rowNumber', title: '일련\n번호' },
{ id: 'swtrmtFcltNm', title: '하수처리\n시설명' },
{ id: 'fcltCpct', title: '시설\n용량\n(㎥/d)' },
{ id: 'rgnExpln', title: '지역설명' },
// { id: 'cmcnYmd', title: '준공일자' },
{ id: 'oprtngStrtYmd', title: '가동개시일자' },
@@ -311,7 +311,7 @@ export const SwtrmtFcltCol2 = [
// { id: 'sggNm', title: '시군구명' },
// { id: 'sareaCd', title: '권역코드' },
{ id: 'sareaNm', title: '권역명' },
{ id: 'lrgeSareaNm', title: '대권역명' },
// { id: 'lrgeSareaNm', title: '대권역명' },
{ id: 'rvrNm', title: '하천명' },
// { id: 'addr', title: '주소' },
// { id: 'dtlAddr', title: '상세주소' },
@@ -320,19 +320,19 @@ export const SwtrmtFcltCol2 = [
{ id: 'dschgWtstNm', title: '방류수계명' },
// { id: 'pllnArea', title: '부지면적(m²)' },
// { id: 'mngRprtvBzentyNm', title: '관리대행업체명' },
{ id: 'swtrmtPpltnCnt', title: '하수처리인구수(인)' },
{ id: 'swtrmtPpltnCnt', title: '하수\n처리\n인구수\n(인)' },
// { id: 'prcsZoneAreaSum', title: '처리구역면적합계(m²)' },
// { id: 'xcrd', title: 'X좌표' },
// { id: 'ycrd', title: 'Y좌표' },
// { id: 'oprtngSttsCd', title: '가동상태코드' },
{ id: 'rprsMsrcCn', title: '대표공법내용' },
{ id: 'rprsMsrcCn', title: '대표\n공법\n내용' },
// { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량(mg/L)' },
// { id: 'sttyCrtrToc', title: '법정기준TOC(mg/L)' },
// { id: 'sttyCrtrSs', title: '법정기준SS(mg/L)' },
// { id: 'sttyCrtrTn', title: '법정기준총질소(mg/L)' },
// { id: 'sttyCrtrTph', title: '법정기준총인(mg/L)' },
// { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수(군수/100mL)' },
{ id: 'bsnNm', title: '유역명' },
// { id: 'bsnNm', title: '유역명' },
// { id: 'obsrvnSptCd', title: '관측지점코드' },
];
@@ -353,9 +353,9 @@ export const SwtrmtPrcsZoneCol2 = [
{ id: 'swtrmtZoneNm', title: '하수처리구역명' },
// { id: 'swtrmt_fclt_cd', title: '하수처리시설코드' },
// { id: 'ctpv_cd', title: '시도코드' },
{ id: 'ctpvNm', title: '시도명' },
{ id: 'ctpvNm', title: '시도' },
// { id: 'sgg_cd', title: '시군구코드' },
{ id: 'sggNm', title: '시군구명' },
{ id: 'sggNm', title: '시군구' },
{ id: 'swtrmtFcltNm', title: '하수처리시설명' },
];
@@ -12,20 +12,114 @@ const inputColumn = [
{ id: "swtrmtZoneCd", title: "처리구역", type: "input" },
];
const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: {
featureData: any,
isMainSsc?: boolean,
rainMeasureData?: any,
chmbrXcnts?: string,
chmbrYdnts?: string,
onSaveClick?: () => void
}) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [isDataLoaded, setIsDataLoaded] = useState(false);
const [formData, setFormData] = useState<any>({});
const [mntrngsData, setMntrngsData] = useState<any[]>([]); // 수량/수질 측정 정보
const [rainMeasureData, setRainMeasureData] = useState<any>({}); // 강우, 측정 정보
const [mntrngsData, setMntrngsData] = useState<any[]>([]); // 수량/수질측정 정보
const [totalCount, setTotalCount] = useState<number>(0);
const [totalDetailCount, setTotalDetailCount] = useState<number>(0);
const [selectedRowIndex, setSelectedRowIndex] = useState<number>(-1);
const [curPage, setCurPage] = useState<number>(1);
const [curDetailPage, setCurDetailPage] = useState<number>(1);
const [isResetPage, setIsResetPage] = useState<boolean>(false);
const [isResetDetailPage, setIsResetDetailPage] = useState<boolean>(false);
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
const [curIdx, setCurIdx] = useState<number>(0);
// console.log('featureData data received:', featureData); // 추가 데이터 확인용
// console.log('rainMeasureData received:', rainMeasureData); // 추가 데이터 확인용
// 강우, 측정 정보 API 호출 함수
const fetchRainMeasureData = async (chmbrXcnts: string, chmbrYdnts: string) => {
if (!chmbrXcnts || !chmbrYdnts) {
console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { chmbrXcnts, chmbrYdnts });
return [];
}
try {
const queryParams = new URLSearchParams({
chmbrXcnts: chmbrXcnts,
chmbrYdnts: chmbrYdnts,
page: `${curPage - 1}`,
size: '3',
});
console.log('queryParams', queryParams.toString());
console.log(`추가 데이터 API 호출 시작: v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
const result = await getData(`v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
console.log('추가 데이터 API 호출 성공:', result);
const processedDataArray: any[] = result.content.map((data: any) => {
// 🎯 formatDisplayData로 기본 포맷팅 적용
const formattedItem = formatDisplayData(data);
// 🎯 추가 데이터 조합
return {
...formattedItem,
flwmtrCombined: `${data.flwmtrMesureTpEtc || '-'} / ${data.flwmtrKnd || '-'}`,
};
});
setRainMeasureData(processedDataArray);
setTotalCount(result?.totalElements || 0);
} catch (error) {
console.error('추가 데이터 로딩 실패:', error);
return [];
}
};
// 수량/수질측정 정보 API 호출 함수
const fetchMntrngsData = async (adstDstrCd: string, manageNo: string) => {
if (!adstDstrCd || !manageNo) {
console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { adstDstrCd, manageNo });
return [];
}
try {
const queryParams = new URLSearchParams({
page: `${curDetailPage - 1}`,
size: '3',
});
console.log(`SSC 추가 데이터 API 호출 시작: v1/onsemiro/swgRain?${queryParams.toString()}`);
const result = await getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`);
console.log('SSC 추가 데이터 API 호출 성공:', result);
// 각 아이템 전처리
const processedDataArray = result.content.map((data: any) => {
// 기본 포맷팅 적용
const formattedItem = formatDisplayData(data);
return {
...formattedItem,
};
});
console.log('processedDataArray', processedDataArray);
setMntrngsData(processedDataArray);
setTotalDetailCount(result?.totalElements || 0);
} catch (error) {
console.error('추가 데이터 로딩 실패:', error);
return [];
}
};
// 🎯 추가 데이터는 별도 useEffect로 비동기 로딩
useEffect(() => {
// 강우/측정 정보 데이터 호출
if (isMainSsc && chmbrXcnts && chmbrYdnts) {
fetchRainMeasureData(chmbrXcnts, chmbrYdnts)
}
}, [chmbrXcnts, chmbrYdnts]);
const openModal = () => {
setIsModalOpen(true);
@@ -46,6 +140,19 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
}
}, [featureData]);
// featureData가 변경될 때 formData 초기화
useEffect(() => {
// showTable이 true일 때만 fetch (최초 렌더 방지)
setIsResetPage(false);
setIsResetDetailPage(true);
if (chmbrXcnts && chmbrYdnts) fetchRainMeasureData(chmbrXcnts, chmbrYdnts);
}, [curPage]);
// 페이지 변경 시마다 데이터 fetch
useEffect(() => {
if (chmbrXcnts && chmbrYdnts) fetchMntrngsData(chmbrXcnts, chmbrYdnts);
}, [curDetailPage]);
// 폼 데이터가 변경될 때 호출될 핸들러
const handleFormDataChange = (newFormData: any) => {
setFormData(newFormData);
@@ -62,91 +169,39 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
// 테이블 셀 클릭 핸들러 추가
const handleCellClick = async (index: number | undefined, headId: string) => {
if (index !== undefined && rainMeasureData) {
const data = await fetchMntrngsData(rainMeasureData[index].adstDstrCd, rainMeasureData[index].manageNo);
setMntrngsData(data);
await fetchMntrngsData(rainMeasureData[index].adstDstrCd, rainMeasureData[index].manageNo);
setSelectedRowIndex(index);
}
};
// 🎯 추가 데이터 API 호출 함수 (독립적으로 실행)
const fetchMntrngsData = useCallback(async (adstDstrCd: string, manageNo: string) => {
if (!adstDstrCd || !manageNo) {
console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { adstDstrCd, manageNo });
return [];
}
try {
const queryParams = new URLSearchParams({
pageable: `{}`,
});
console.log(`SSC 추가 데이터 API 호출 시작: v1/onsemiro/swgRain?${queryParams.toString()}`);
const result = await getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`);
console.log('SSC 추가 데이터 API 호출 성공:', result);
// 🎯 result가 페이지네이션 객체인 경우 content 배열 추출
let dataArray: any[] = [];
if (result && typeof result === 'object' && 'content' in result && Array.isArray(result.content)) {
dataArray = result.content;
} else if (Array.isArray(result)) {
dataArray = result;
} else {
console.warn('예상치 못한 API 응답 형식:', result);
return [];
}
// 🎯 각 아이템을 전처리하여 반환
const processedDataArray = dataArray.map((data: any) => {
// 🎯 formatDisplayData로 기본 포맷팅 적용
const formattedItem = formatDisplayData(data);
// 🎯 추가 데이터 조합
return {
...formattedItem,
};
});
console.log('processedDataArray', processedDataArray);
return processedDataArray;
} catch (error) {
console.error('추가 데이터 로딩 실패:', error);
return [];
}
}, []);
const renderModalBody = () => (
<div className='grid grid-cols-1 gap-4 p-4'>
{/* 강우정보 테이블 */}
<UiTable
headName='강우정보'
tableData={Array.isArray(rainMeasureData) ? rainMeasureData : []}
tableData={rainMeasureData}
headlist={untrtSwgRainCol3}
pageSize={10}
total={Array.isArray(rainMeasureData) ? rainMeasureData.length : 0}
pageSize={3}
total={0}
cellClick={handleCellClick}
onPageChange={function (page: number): void {
console.log('Rain data page change:', page);
}}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
index={curIdx}
/>
{/* 측정정보 테이블 */}
<UiTable
headName='측정정보'
tableData={Array.isArray(rainMeasureData) ? rainMeasureData : []}
tableData={rainMeasureData}
headlist={untrtSwgRainCol4}
pageSize={10}
total={Array.isArray(rainMeasureData) ? rainMeasureData.length : 0}
pageSize={3}
total={totalCount}
cellClick={handleCellClick}
// onPageChange={setCurPage}
onPageChange={function (page: number): void {
console.log('Rain data page change:', page);
}}
resetPageNo={false}
// index={curPage}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
index={curIdx}
>
{/* 커스텀 헤더 */}
<TableRow>
@@ -168,14 +223,12 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
{/* 수량/수질측정 정보 테이블 */}
<UiTable
headName='수량/수질측정 정보'
tableData={Array.isArray(mntrngsData) ? mntrngsData : []}
tableData={mntrngsData}
headlist={untrtSwgRainCol5}
pageSize={10}
total={Array.isArray(mntrngsData) ? mntrngsData.length : 0}
pageSize={3}
total={totalDetailCount}
cellClick={undefined}
onPageChange={function (page: number): void {
console.log('Quality data page change:', page);
}}
onPageChange={setCurDetailPage}
/>
</div>
)
@@ -162,7 +162,7 @@ const InfilChart = ({ pplMngNo }: ModalOpenProp) => {
<span className="text-2xl text-red-600 font-bold">● 침입수량 산정결과</span>
<div className="flex items-center mt-2">
<span className="ml-5 text-black text-xl">침입수량 : </span>
<span className="w-[35px] inline-block text-right text-black text-xl font-bold">{inftwtQty}</span>
<span className="w-[45px] inline-block text-right text-black text-xl font-bold">{inftwtQty}</span>
<span className="ml-2 text-black text-xl">m³/d</span>
</div>
</div>
@@ -170,7 +170,7 @@ const InfilChart = ({ pplMngNo }: ModalOpenProp) => {
{/* 차트 */}
<div className="h-[90%] bg-white text-3xl">
<MainChart chartConfig={chartConfig} chartForm={chartForm} chartData={chartData} chartTitle={'침입수량 그래프'}
yFieldText2="시간" yFieldText="유량(m³/h)"/>
yFieldText2="" yFieldText="유량(m³/h)"/>
</div>
</div>
{popupOpen && (
@@ -161,17 +161,17 @@ const RdiiChart = ({ pplMngNo }: ModalOpenProp) => {
<span className="text-2xl text-red-600 font-bold">● 강우유입수량 분석결과</span>
<div className="flex items-center mt-2">
<span className="w-[95px] inline-block text-right text-black text-xl">평균RDII : </span>
<span className="w-[30px] inline-block text-right text-black text-xl font-bold"> {rdiiQty}</span>
<span className="w-[45px] inline-block text-right text-black text-xl font-bold"> {rdiiQty}</span>
<span className="ml-2 text-black"> m³/d</span>
</div>
<div className="flex items-center mt-2">
<span className="w-[95px] inline-block text-right text-black text-xl">적용강우량 : </span>
<span className="w-[30px] inline-block text-right text-black text-xl font-bold"> {rainTotal}</span>
<span className="w-[45px] inline-block text-right text-black text-xl font-bold"> {rainTotal}</span>
<span className="ml-2 text-black"> mm</span>
</div>
<div className="flex items-center mt-2">
<span className="w-[95px] inline-block text-right text-black text-xl">강우량대비RDII : </span>
<span className="w-[30px] inline-block text-right text-black text-xl font-bold"> {totalVolume}</span>
<span className="w-[45px] inline-block text-right text-black text-xl font-bold"> {totalVolume}</span>
<span className="ml-2 text-black"> m³/mm</span>
</div>
</div>
@@ -5,13 +5,13 @@ import { VerticalTable } from "@/components/ui/verticalTable";
import { useGisContext } from "@common/business_components/ui/map/Gis";
import { Button } from "@common/components/ui";
import { useEffect, useRef, useState, useCallback, useMemo } from "react";
import { getLayerContentComponent } from "./components/common";
import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table";
import InfilChart from './components/popupComponent/chart/infilChart';
import RdiiChart from './components/popupComponent/chart/rdiiChart';
import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore";
import { getLayerContentComponent } from "../common";
import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "../common/table";
import InfilChart from './chart/infilChart';
import RdiiChart from './chart/rdiiChart';
import { useInfilChartModalStore, useRdiiChartModalStore } from "./chartModalStore";
import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue';
import { codeMapper } from "./components/common/codeMapper";
import { codeMapper } from "../common/codeMapper";
import { searchUpperPpls } from '@common/business_components/ui/map/Gis';
import LoadingOverlay from '@/components/ui/LoadingBar';
@@ -33,9 +33,10 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
// 🎯 InfilChart 및 RdiiChart 관련 상태 추가
const { setIsOpen: setIsModalInfil } = useInfilChartModalStore();
const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore();
const [curPage, setCurPage] = useState(1); // 현재 페이지 상태
const [isClicked, setIsClicked] = useState(true); // 클릭 여부 상태
const [isLoading, setIsLoading] = useState(false); // 로딩 상태
const [chmbrXcnts, setChmbrXcnts] = useState(); // 로딩 상태
const [chmbrYdnts, setChmbrYdnts] = useState(); // 로딩 상태
// 🎯 관로관리번호 추출
const pplMngNo = featureData?.values_?.fclt_mng_no || "";
@@ -263,18 +264,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
data: { ...processedFormattedData }
}));
// 강우/측정 정보 데이터 호출
if (tableData?.chmbr_xcnts && tableData?.chmbr_ydnts) {
fetchRainMeasureData(tableData.chmbr_xcnts, tableData.chmbr_ydnts)
.then(response => {
console.log('additionalResponse', response);
setRainMeasureData(response || []);
})
.catch(error => {
console.error('추가 데이터 로딩 실패:', error);
setRainMeasureData([]);
});
}
setChmbrXcnts(data.chmbr_xcnts);
setChmbrYdnts(data.chmbr_ydnts);
break;
default:
break;
@@ -317,76 +309,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
fetchData();
}, [featureId, processedData]);
// 🎯 추가 데이터 API 호출 함수
const fetchRainMeasureData = useCallback(async (chmbrXcnts: string, chmbrYdnts: string) => {
if (!chmbrXcnts || !chmbrYdnts) {
console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { chmbrXcnts, chmbrYdnts });
return [];
}
try {
const queryParams = new URLSearchParams({
chmbrXcnts: chmbrXcnts,
chmbrYdnts: chmbrYdnts,
pageable: `{}`,
});
console.log(`추가 데이터 API 호출 시작: v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
const result = await getData(`v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
console.log('추가 데이터 API 호출 성공:', result);
// 🎯 result가 페이지네이션 객체인 경우 content 배열 추출
let dataArray: any[] = [];
if (result && typeof result === 'object' && 'content' in result && Array.isArray(result.content)) {
dataArray = result.content;
} else if (Array.isArray(result)) {
dataArray = result;
} else {
console.warn('예상치 못한 API 응답 형식:', result);
return [];
}
// 🎯 각 아이템을 전처리하여 반환
const processedDataArray = dataArray.map((data: any) => {
// 🎯 formatDisplayData로 기본 포맷팅 적용
const formattedItem = formatDisplayData(data);
// 🎯 추가 데이터 조합
return {
...formattedItem,
flwmtrCombined: `${data.flwmtrMesureTpEtc || '-'} / ${data.flwmtrKnd || '-'}`,
};
});
return processedDataArray;
} catch (error) {
console.error('추가 데이터 로딩 실패:', error);
return [];
}
}, []);
// 🎯 추가 데이터는 별도 useEffect로 비동기 로딩
useEffect(() => {
if (layerNm === '중점우수토실' && featureData?.values_) {
const data = featureData.values_;
if (data?.chmbr_xcnts && data?.chmbr_ydnts) {
// 🎯 추가 데이터를 비동기로 로딩 (UI 블로킹 없음)
fetchRainMeasureData(data.chmbr_xcnts, data.chmbr_ydnts)
.then(response => {
console.log('추가 데이터 로딩 완료:', response);
setRainMeasureData(response || []);
})
.catch(error => {
console.error('추가 데이터 최종 로딩 실패:', error);
setRainMeasureData([]);
});
}
}
}, [layerNm, featureData?.values_, fetchRainMeasureData]);
// 저장 시 모달 띄우기
const handleSaveClick = () => {
setIsModalOpen(true); // 모달 열기
@@ -482,45 +404,47 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
</>
)} 정보 <br />관리번호 : {layerSpecificNm}
</h3>
<div className="flex items-center space-x-3">
{/* 🎯 하수관로일 때만 Infil/RDII 버튼 표시 */}
{layerNm === '하수관로' && (
<>
<Button onClick={() => setIsModalInfil(true)}
className="py-1 text-xl text-blue-600 border border-blue-600 rounded hover:bg-gray-700"
color="white"
size="sm"
>
침입수분석
</Button>
<Button onClick={() => setIsModalRdii(true)}
className="py-1 text-xl text-gray-600 border border-gray-600 rounded hover:bg-gray-700"
color="white"
size="sm"
>
RDII분석
</Button>
</>
)}
{layerNm === '하수맨홀' && (
<>
<Button onClick={() => {
</div>
<div className="flex items-center space-x-3">
{/* 🎯 하수관로일 때만 Infil/RDII 버튼 표시 */}
{layerNm === '하수관로' && (
<>
<Button onClick={() => setIsModalInfil(true)}
className="py-1 text-xl text-blue-600 border border-blue-600 rounded hover:bg-gray-700"
color="white"
size="sm"
>
침입수분석
</Button>
<Button onClick={() => setIsModalRdii(true)}
className="py-1 text-xl text-gray-600 border border-gray-600 rounded hover:bg-gray-700 mr-4"
color="white"
size="sm"
>
RDII분석
</Button>
</>
)}
{layerNm === '하수맨홀' && (
<>
<Button
color="white"
className="px-2 py-1 text-xl text-gray-600 border border-gray-600 rounded hover:bg-gray-700 mr-4"
onClick={() => {
setIsLoading(true);
searchUpperPpls(layerSpecificNm).finally(() => setIsLoading(false));
}}
className="px-2 py-1 text-xl text-gray-600 border border-gray-600 rounded hover:bg-gray-700"
color="white"
>
상류관로 보기
</Button>
</>
)}
</div>
>
상류관로 보기
</Button>
</>
)}
</div>
<Button
onClick={onClose}
// className="text-white hover:text-gray-300 focus:outline-none"
className="absolute top-8 right-4 text-white hover:text-gray-300 focus:outline-none"
className="flex items-center space-x-4 text-white hover:text-gray-300 focus:outline-none"
// className="absolute top-8 right-4 text-white hover:text-gray-300 focus:outline-none"
size="xs"
>
✕
@@ -553,8 +477,10 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
featureData={fetchData}
isMainSsc={isMainSsc}
isDrtwSewagePump={isDrtwSewagePump}
rainMeasureData={rainMeasureData}
// rainMeasureData={rainMeasureData}
onSaveClick={handleSaveClick}
chmbrXcnts={chmbrXcnts}
chmbrYdnts={chmbrYdnts}
/>
}
</div>
+11 -1
View File
@@ -5,7 +5,9 @@ import { getData } from "../../components/lib/api";
import { useCallback, useEffect, useRef, useState } from "react";
import GisApp from "@common/business_components/ui/map/lib/gis.core";
import SearchModal from "./searchModal/searchModal";
import FeatureClickEventPopup from "./featureClickEventPopup";
import FeatureClickEventPopup from "./components/popupComponent/featureClickEventPopup";
import useStore from "../../store/useStore";
import { SearchBar } from "./searchBar/searchBar";
// 타입 정의 추가
export type LyrStngProps = {
@@ -38,6 +40,13 @@ const Map = () => {
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태
const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터
const { fetchCtpvData, fetchSggData } = useStore();
// 시도, 시군구 호출
useEffect(() => {
fetchCtpvData();
fetchSggData();
}, [fetchCtpvData, fetchSggData]);
const fetchData = async () => {
try {
@@ -130,6 +139,7 @@ const Map = () => {
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={undefined}
searchBar={SearchBar}
/>
</div>
);
@@ -0,0 +1,83 @@
"use client";
import {
SearchDiv,
SearchFormLeft,
SelectBox,
type SelectDataType,
} from "@common/business_components/ui";
import { useCallback, useEffect, useState } from "react";
export function SearchBar() {
const [sidoValue, setSidoValue] = useState<string>("");
const [sigunValue, setSigunValue] = useState<string>("");
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([
{ text: "시도 선택", val: "0" },
]);
const initializeSigunData = useCallback((sidoCd: string) => {
if (sidoCd === "0") {
setSigunValue("0");
setFilteredSigunData([{ text: "시도 선택", val: "0" }]);
} else {
const newFilteredData = [
{ text: "데이터", val: "0" },
// ...Common.selectSigunData.filter(
// (item: SelectDataType) => item.val.substring(0, 2) === sidoCd,
// ),
];
setSigunValue("0");
setFilteredSigunData(newFilteredData);
}
}, []);
const onSelectValue = useCallback(
(val: string, type: string) => {
switch (type) {
case "ctpvCd":
initializeSigunData(val);
setSidoValue(val);
break;
case "sggCd":
setSigunValue(val);
}
},
[initializeSigunData],
);
return (
<>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<div className="card card-border flex">
<div className="col-span-10 flex flex-row">
<SelectBox
className="mr-10 w-[200px]"
selectClass="rounded-lg bg-white"
label="시도"
selectArray={/* Common.selectSidoData || */ []}
onSelectValue={(val) => onSelectValue(val.toString(), "ctpvCd")}
value={sidoValue || /* Common.selectSidoData[0]?.val || */ ""}
/>
<SelectBox
className="mr-10 w-[200px]"
selectClass="rounded-lg bg-white"
label="시군구"
selectArray={filteredSigunData || []}
onSelectValue={(val) => onSelectValue(val.toString(), "sggCd")}
value={sigunValue}
/>
<SelectBox
className="mr-3 w-[250px]"
selectClass="rounded-lg bg-white"
labelClass="w-[200px]"
label="하수처리시설명"
selectArray={filteredSigunData || []}
onSelectValue={(val) => onSelectValue(val.toString(), "sggCd")}
value={sigunValue}
/>
</div>
</div>
</div>
</div>
</>
);
}
@@ -39,7 +39,9 @@ interface BasicTabProps {
// setTableCount?: (count: number) => void;
setBasicType: (type: string) => void;
setCity: (city: number) => void;
setCtpvName: (name: string) => void;
setSgg: (sgg: number) => void;
setSggName: (name: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
setStart1: (value: string) => void;
setStart2: (value: string) => void;
@@ -68,7 +70,9 @@ const BasicTab: React.FC<BasicTabProps> = ({
// setTableCount,
setBasicType,
setCity,
setCtpvName,
setSgg,
setSggName,
setYearFilter,
setStart1,
setStart2,
@@ -78,14 +82,15 @@ const BasicTab: React.FC<BasicTabProps> = ({
setVar2,
}) => {
return (
<div className="relative border rounded-lg p-6 w-full h-[10vh]">
<div className="relative border rounded-lg p-5 w-full h-[10vh]">
{/* 구분 */}
<div className="mb-3 flex items-center justify-between gap-4">
<div className="flex items-center">
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">구분</Label>
<SelectBox
className="w-[150px] mr-3"
selectClass="rounded-lg bg-white"
label="구분"
label=""
selectArray={BASIC_TYPES}
onSelectValue={(value: string | number) =>
setBasicType(String(value))
@@ -101,12 +106,16 @@ const BasicTab: React.FC<BasicTabProps> = ({
var1={var1}
var2={var2}
start1={start1}
start2={start2}
end1={end1}
end2={end2}
yearFilter={yearFilter}
setVar1={setVar1}
setVar2={setVar2}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
@@ -119,12 +128,18 @@ const BasicTab: React.FC<BasicTabProps> = ({
start2={start2}
end1={end1}
end2={end2}
city={city}
sgg={sgg}
yearFilter={yearFilter}
setVar1={setVar1}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setCity={setCity}
setCtpvName={setCtpvName}
setSgg={setSgg}
setSggName={setSggName}
setYearFilter={setYearFilter}
handleSearch={handleSearch}
/>
@@ -12,11 +12,9 @@ import React from 'react';
// { val: "inspection", text: "점검 및 진단" },
// ];
export const WORK_TYPES = [
{ val: "200", text: "보수 및 갱신(개대체)" },
{ val: "201", text: "보수 및 갱신(유지보수)" },
{ val: "204", text: "보수 및 갱신(단순보수)" },
{ val: "100", text: "점검 및 진단" },
{ val: "203", text: "청소 및 준설" },
{ val: "['200', '201', '204']", text: "보수 및 갱신" },
{ val: "['100']", text: "점검 및 진단" },
{ val: "['203']", text: "청소 및 준설" },
];
// const BIZ_SE_CD = useBizByFcltStore(state => state.BIZ_SE_CD);
export const BIZ_SE_CD = [
@@ -113,12 +111,13 @@ const OperationTab: React.FC<OperationTabProps> = ({
setYearFilter,
}) => {
return (
<div className="relative flex flex-col border rounded-lg p-6 w-full h-[10vh]">
<div className="relative flex flex-col border rounded-lg p-5 w-full h-[10vh]">
<div className="flex items-center mb-3">
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">업무구분</Label>
<SelectBox
className="w-80 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="업무구분"
label=""
selectArray={WORK_TYPES.map((w) => ({
val: w.val,
text: w.text,
@@ -129,12 +128,18 @@ const OperationTab: React.FC<OperationTabProps> = ({
/>
</div>
<div className="flex items-center mb-6">
<Label className="mr-2 w-auto text-xl text-gray-600">사업명</Label>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">사업명</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center mr-4"
className="w-[100px] !text-xl placeholder:text-center mr-8"
placeholder="입력"
value={var1}
onChange={(e) => { setVar1(e.target.value); }}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<YearRangeSelectBox
start={yearFilter.start}
@@ -143,10 +148,11 @@ const OperationTab: React.FC<OperationTabProps> = ({
startLabel="수행기간"
endLabel=""
/>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">사업 유형</Label>
<SelectBox
className="ml-8 w-60 mr-8"
className="w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="사업 유형"
label=""
selectArray={BIZ_TY_CD_SELECT_ARRAY}
value={var2}
onSelectValue={(val) => {
@@ -1,14 +1,15 @@
'use client';
import React, { useEffect, useState } from 'react';
import { Button, Label } from '@common/components';
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SelectBox } from '@common/business_components/ui';
import { Button, Input } from '@common/components';
import React from 'react';
//import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi';
import { SelectBox, UiTable } from '@common/business_components/ui';
import LoadingOverlay from '@/components/ui/LoadingBar';
import { addFileName, flattenFolders, getFileDownload, useCityCd, useDcTree, useSggCd, reportGubuns } from './searchModalReportApi';
import { type SelectDataType } from '../commonStore';
import { useCityCd, useSggCd } from '../components/searchModalReportApi';
// import { useBizByFcltStore } from "../../../store/StoreProvider";
// // 하수도정비 기본계획 보고서
// 하수도정비 기본계획 보고서
export const reportTableHeadlist = [
{ id: "no", title: "NO" },
{ id: "sido", title: "시도" },
@@ -23,79 +24,176 @@ export const reportTableHeadlist = [
interface BasicTabProps {
open?: boolean;
gubun: string;
sidos: SelectDataType[];
ctpvCd: string | number;
sigungu: string;
filteredSiguns: SelectDataType[];
yearFilter: { start: string; end: string; };
handleSearch: () => void;
handleCtpvCdChange: (val: string | number) => void;
// onOpenChange?: (open: boolean) => void;
// onFeatureSelect?: (row: any) => void;
// setTableData?: (data: any[]) => void;
// setTableCount?: (count: number) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
setGubun: (gubun: string) => void;
setSigungu: (sigungu: string) => void;
}
const ReportTab: React.FC<BasicTabProps> = ({
open,
gubun,
sidos,
ctpvCd,
sigungu,
filteredSiguns = [{ val: '0', text: '전체', sido: '0' }],
yearFilter,
handleSearch,
handleCtpvCdChange,
// onOpenChange,
// onFeatureSelect,
// setTableData,
// setTableCount,
setYearFilter,
setGubun,
setSigungu,
}) => {
const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
const [isLoading, setIsLoading] = useState(false);
const [isResetPage, setIsResetPage] = useState<boolean>(false);
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
const [showTable, setShowTable] = useState(false);
const [tableData, setTableData] = useState<any[]>([]);
const [tableCount, setTableCount] = useState(0);
const [curPage, setCurPage] = useState(1);
const [yearFilter, setYearFilter] = useState({ start: "", end: "" });
const [ctpvCd, setCtpvCd] = useState('0'); // 하수정비기본계획 report
const [sigungu, setSigungu] = useState('0'); // 하수정비기본계획 report
const [filteredSiguns, setFilteredSiguns] = useState<SelectDataType[]>([{ val: '0', text: '전체', sido: '0' }]);
const [gubun, setGubun] = useState(""); // 하수정비기본계획 report
const [reportGubun, setReportGubun] = useState("0"); // 하수정비기본계획 report
// 하수정비기본계획 report
const sidos = useCityCd();
const siguns = useSggCd();
const reportOriginData = useDcTree(""); //:Folder[]
const dynamicHeadlist: { id: string, title: string }[] = reportTableHeadlist;
useEffect(() => {
// filterParams 초기화
setCtpvCd('0');
setSigungu('0');
setReportGubun('0');
setYearFilter({ start: "", end: "" });
setShowTable(false);
setTableData([]);
setTableCount(0);
setCurPage(1); // 페이지를 1로 초기화
setIsResetPage(true); // 페이지를 초기화
setIsResetSelection(true); // 선택 초기화
}, [open]);
// 페이지 변경 시마다 데이터 fetch
useEffect(() => {
// showTable이 true일 때만 fetch (최초 렌더 방지)
setIsResetPage(false);
setIsResetSelection(true); // 선택 초기화
if (showTable) fetchFilteredData();
}, [curPage]);
const handleCtpvCdChange = (val: string | number) => { // 하수도정비기본계획.시도
const sidoOption = sidos.find((n) => n.val === val);
setCtpvCd(String(val));
if (val !== '0') {
const filterSiguns = siguns.filter(item => item.sido === sidoOption?.text);
filterSiguns.unshift({ val: '0', text: '전체', sido: '0' });
setFilteredSiguns(filterSiguns);
}
setSigungu("0");
setGubun("");
setYearFilter({ start: "", end: "", });
}
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
const handleSearch = () => {
setCurPage(1); // 페이지를 1로 초기화
fetchFilteredData();
setIsResetPage(true); // 페이지를 초기화
setIsResetSelection(false); // 선택 초기화
setShowTable(true);
};
// 하수도정비기본계획 테이블 cellClick 핸들러
const handleReportCellClick = (index: number | undefined ) => {
console.log(index);
if (typeof index === "number" && tableData[index]) {
const reportData = tableData[index];
const fileName = reportData.fileName;
const filePath = reportData.filePath;
if (reportData.fileSn !== "") {
getFileDownload(reportData.fileSn, fileName, filePath);
}
}
};
// 검색 API 호출 함수
const fetchFilteredData = async () => {
setIsLoading(true); // 로딩 시작
setIsResetSelection(true); // 선택 초기화
try {
//const reportOriginData = await getDcTree('경기도');
const reportData = flattenFolders(reportOriginData);
let filterReportData = reportData;
if (ctpvCd !== "0") { // 시도검색
const sidoOption = sidos.find((n) => n.val === ctpvCd);
filterReportData = filterReportData.filter(item => item.sido === sidoOption?.text);
}
if (sigungu !== "0") { // 시군구검색
const sigunguOption = filteredSiguns.find((n) => n.val === sigungu);
filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.text);
}
if (reportGubun !== "0") { // 보고서구분검색
const reportGubunOption = reportGubuns.find((n) => n.val === reportGubun);
filterReportData = filterReportData.filter(item => item.reportGubun === reportGubunOption?.text);
}
if (yearFilter.start != "" && yearFilter.end == "") //승인년도검색
filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" : null);
if (yearFilter.start == "" && yearFilter.end != "")
filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear <= yearFilter.end + "년" : null);
if (yearFilter.start != "" && yearFilter.end != "") {
filterReportData = filterReportData.filter(item => {
return (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" && item.approvalYear <= yearFilter.end + "년" : null;
});
}
if (gubun !== "") { // 구분검색
filterReportData = filterReportData.filter(item => (item.plantZoneGugun) ? String(item.plantZoneGugun).includes(String(gubun)) : null);
}
console.log('report count:', filterReportData.length);
setTableCount(filterReportData.length || 0);
filterReportData = filterReportData.slice((curPage - 1) * 10, curPage * 10); // paging
filterReportData = filterReportData?.map((item, index) => ({ ...item, no: (curPage - 1) * 10 + index + 1 }));
//const fileList = await getDcFile("CLS20250530000041");
addFileName(filterReportData).then(data => {
filterReportData = data;
setTableData(filterReportData || []);
});
setTableData(filterReportData || []);
setShowTable(true);
} catch (err) {
console.error('API ERROR:', err);
setTableData([]);
} finally {
setIsLoading(false); // 로딩 종료
}
};
return (
<div className="relative flex flex-col border rounded-lg p-6 w-full h-[10vh]">
<>
<div className="relative flex flex-col border rounded-lg p-5 w-full h-[10vh]">
<div className="flex items-center mb-3">
<SelectBox
className="w-[150px] mr-8"
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시도</Label>
<SelectBox className="w-60 mr-8"
selectClass="rounded-lg bg-white"
label="시도"
selectArray={sidos}
value={ctpvCd}
onSelectValue={handleCtpvCdChange}
label="" selectArray={sidos}
value={ctpvCd} onSelectValue={handleCtpvCdChange}
selectContentClass="z-[101]"
/>
<SelectBox
className="w-48"
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시군구</Label>
<SelectBox className="w-48"
selectClass="w-48 rounded-lg bg-white truncate"
label="시군구"
selectArray={filteredSiguns}
value={sigungu}
onSelectValue={val => setSigungu(String(val))}
label="" selectArray={filteredSiguns}
value={sigungu} onSelectValue={val => setSigungu(String(val))}
selectContentClass="z-[101]"
/>
</div>
<div className="flex items-center mb-6">
<label className="inline-block w-auto whitespace-nowrap text-xl text-gray-600 mr-2">구분</label>
<Input
className='!text-xl w-[100px] placeholder:text-center mr-8'
placeholder="입력"
value={gubun}
onChange={(e) => { setGubun(e.target.value); }}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">보고서 구분</Label>
<SelectBox className="w-44 mr-8"
selectClass="rounded-lg bg-white"
label="" selectArray={[...reportGubuns]}
value={reportGubun} onSelectValue={val => setReportGubun(String(val))}
selectContentClass="z-[101]" labelClass='whitespace-nowrap text-xl text-gray-600 pr-2'
/>
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
{/* 승인년도 필터 */}
<YearRangeSelectBox start={yearFilter.start} end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="승인년도"
endLabel=""
startLabel="승인년도" endLabel=""
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
@@ -103,6 +201,28 @@ const ReportTab: React.FC<BasicTabProps> = ({
</div>
</div>
</div>
<div className="h-[79vh] w-full overflow-hidden rounded-lg border">
{/* 테이블2 영역 (가로/세로 스크롤 가능) */}
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={(() => {
return (<>조회 결과 ({tableCount.toLocaleString('ko-KR')})건</>);
})()
}
tableData={tableData}
headlist={dynamicHeadlist}
pageSize={10}
total={tableCount}
cellClick={handleReportCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
/>
</div>
</div>
</>
);
};
@@ -3,11 +3,8 @@ import { UiModal, UITab, UiTable } from '@common/business_components/ui';
import axios from 'axios';
import React, { useEffect, useMemo, useState } from 'react';
import { ExclnSewagePumpCol2, MsSwageMhlCol2, MsSwagePplCol2, stofcbrCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2 } from '../components/common/table';
//import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi';
import { type SelectDataType } from '../commonStore';
import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES, MS_SWAGE_MHL_CODES } from '../components/common/table';
import { addFileName, flattenFolders, getFileDownload, useCityCd, useDcTree, useSggCd } from '../components/searchModalReportApi';
// import { useBizByFcltStore } from "../../../store/StoreProvider";
import { getData } from "@/components/lib/api";
import BasicTab, { BASIC_TYPES } from './basicTab';
import OperationTab, { BIZ_TY_CD, operationCleaningTableHeadlist, operationInspectionTableHeadlist, operationMaintenanceTableHeadlist, operationTableHeadlist, WORK_TYPES } from './operationTab';
@@ -66,11 +63,14 @@ const SearchModal: React.FC<SearchModalProps> = ({
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
const [isResetDetailSelection, setIsResetDetailSelection] = useState<boolean>(false);
const [detailBizId, setDetailBizId] = useState(0);
const [city, setCity] = useState(0);
const [sgg, setSgg] = useState(0);
const [ctpvCd, setCtpvCd] = useState('0');
const [sigungu, setSigungu] = useState('0');
const [gubun, setGubun] = useState(""); // 하수정비기본계획 report
const [city, setCity] = useState<number>(0);
const [ctpvName, setCtpvName] = useState<string>('');
const [sgg, setSgg] = useState<number>(0);
const [sggName, setSggName] = useState<string>('');
const [ctpvCd, setCtpvCd] = useState('0'); // 하수정비기본계획 report
const [sigungu, setSigungu] = useState('0'); // 하수정비기본계획 report
const [gubun, setGubun] = useState(""); // 하수정비기본계획 report
const [reportGubun, setReportGubun] = useState("0"); // 하수정비기본계획 report
const [start1, setStart1] = useState("");
const [start2, setStart2] = useState("");
const [end1, setEnd1] = useState("");
@@ -83,9 +83,6 @@ const SearchModal: React.FC<SearchModalProps> = ({
const [yearFilter, setYearFilter] = useState({ start: "", end: "" });
const [filteredSiguns, setFilteredSiguns] = useState<SelectDataType[]>([{ val: '0', text: '전체', sido: '0' }]);
const sidos = useCityCd();
const siguns = useSggCd();
const reportOriginData = useDcTree(""); //:Folder[]
// 오늘 날짜 구하기
const today = new Date();
@@ -105,18 +102,15 @@ const SearchModal: React.FC<SearchModalProps> = ({
return [];
}
if (activeTab === 'operation') return operationTableHeadlist;
if (activeTab === 'report') return reportTableHeadlist;
return [];
}, [activeTab, basicType, workType]);
const dynamicHeadlist2: { id: string, title: string }[] = useMemo(() => {
if (activeTab === 'operation') {
if (workType === '200') return operationMaintenanceTableHeadlist;
if (workType === '201') return operationMaintenanceTableHeadlist;
if (workType === '204') return operationMaintenanceTableHeadlist;
if (workType === '100') return operationCleaningTableHeadlist;
if (workType === '203') return operationInspectionTableHeadlist;
if (workType === WORK_TYPES[0]?.val) return operationMaintenanceTableHeadlist;
if (workType === WORK_TYPES[1]?.val) return operationCleaningTableHeadlist;
if (workType === WORK_TYPES[2]?.val) return operationInspectionTableHeadlist;
}
return [];
@@ -134,8 +128,6 @@ const SearchModal: React.FC<SearchModalProps> = ({
setVar4("");
setCity(0);
setSgg(0);
setCtpvCd('0');
setSigungu('0');
setYearFilter({
start: "",
end: "",
@@ -187,7 +179,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
setIsLoading(true); // 로딩 시작
setIsResetSelection(true); // 선택 초기화
setIsResetDetailSelection(true); // 선택 초기화
try {
let cqlFilters: string[] = [];
if (activeTab === 'basic') {
@@ -255,8 +247,8 @@ const SearchModal: React.FC<SearchModalProps> = ({
RequestDTO.fromflfmtEndYmd = startDate;
RequestDTO.toflfmtEndYmd = endDate;
RequestDTO.bizSeCd = workType;
// JSON.parse 사용으로 문자열 -> 배열 변환
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
const params = new URLSearchParams(RequestDTO).toString();
@@ -271,7 +263,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
const matched = BIZ_TY_CD.find(code => code.lwpoCd === item.bizTyCd);
return {
...formattedItem,
rowNumber: (curPage - 1) * 4 + index + 1, // 1부터 시작하는 일련번호 추가
rowNumber: (curPage - 1) * 5 + index + 1, // 1부터 시작하는 일련번호 추가
bizTyCd: matched ? matched.lwpoCdNm : item.bizTyCd,
};
});
@@ -280,41 +272,6 @@ const SearchModal: React.FC<SearchModalProps> = ({
setTableCount(res.totalElements || 0);
setDetailTableData([]);
setDetailTableCount(0);
} else if (activeTab === 'report') {
//const reportOriginData = await getDcTree('경기도');
const reportData = flattenFolders(reportOriginData);
let filterReportData = reportData;
if (ctpvCd !== "0") { // 시도검색
const sidoOption = sidos.find((n) => n.val === ctpvCd);
filterReportData = filterReportData.filter(item => item.sido === sidoOption?.text);
}
if (sigungu !== "0") { // 시군구검색
const sigunguOption = filteredSiguns.find((n) => n.val === sigungu);
filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.text);
}
if (yearFilter.start != "" && yearFilter.end == "") //승인년도검색
filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" : null);
if (yearFilter.start == "" && yearFilter.end != "")
filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear <= yearFilter.end + "년" : null);
if (yearFilter.start != "" && yearFilter.end != "") {
filterReportData = filterReportData.filter(item => {
return (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" && item.approvalYear <= yearFilter.end + "년" : null;
});
}
if (gubun !== "") { // 구분검색
filterReportData = filterReportData.filter(item => (item.plantZoneGugun) ? String(item.plantZoneGugun).includes(String(gubun)) : null);
}
console.log('report count:', filterReportData.length);
setTableCount(filterReportData.length || 0);
filterReportData = filterReportData.slice((curPage - 1) * 10, curPage * 10); // paging
filterReportData = filterReportData?.map((item, index) => ({ ...item, no: (curPage - 1) * 10 + index + 1 }));
//const fileList = await getDcFile("CLS20250530000041");
addFileName(filterReportData).then(data => {
filterReportData = data;
setTableData(filterReportData || []);
});
setTableData(filterReportData || []);
}
setShowTable(true);
@@ -386,13 +343,17 @@ const SearchModal: React.FC<SearchModalProps> = ({
cqlFilters.push(`fclt_cpct BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`fclt_cpct >= ${start1}`);
else if (end1) cqlFilters.push(`fclt_cpct <= ${end1}`);
// 처리구역 면적
if (start2 && end2)
cqlFilters.push(`prcsZoneAreaSum BETWEEN ${start2} AND ${end2}`);
else if (start2) cqlFilters.push(`prcsZoneAreaSum >= ${start2}`);
else if (end2) cqlFilters.push(`prcsZoneAreaSum <= ${end2}`);
// 하수처리시설명
if (var1) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var1}%'`);
// 시도
if (ctpvName) cqlFilters.push(`ctpv_nm ILIKE '%${ctpvName}%'`);
if (sggName) cqlFilters.push(`sgg_nm ILIKE '%${sggName}%'`);
// // 처리구역 면적
// if (start2 && end2)
// cqlFilters.push(`prcsZoneAreaSum BETWEEN ${start2} AND ${end2}`);
// else if (start2) cqlFilters.push(`prcsZoneAreaSum >= ${start2}`);
// else if (end2) cqlFilters.push(`prcsZoneAreaSum <= ${end2}`);
// // 하수처리시설명
// if (var1) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var1}%'`);
return cqlFilters;
};
// 하수처리구역용 CQL 필터 생성
@@ -488,12 +449,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
const handleSearch = () => {
setCurPage(1); // 페이지를 1로 초기화
// setDetailCurPage(1); // 페이지를 1로 초기화
// setIsResetPage(false); // 페이지를 초기화
// setIsResetDetailPage(true); // 디테일 페이지를 초기화
// setIsResetSelection(true); // 선택 초기화
// setIsResetDetailSelection(true); // 선택 초기화
setCurPage(1); // 페이지를 1로 초기화
fetchFilteredData();
setIsResetPage(true); // 페이지를 초기화
setIsResetDetailPage(true); // 디테일 페이지를 초기화
@@ -526,8 +482,11 @@ const SearchModal: React.FC<SearchModalProps> = ({
bizId: tableData[index % 5].bizId,
};
RequestDTO.workTypes = JSON.parse(workType.replace(/'/g, '"'));
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
console.log('운영정보 cellClick 데이터:', res);
console.log('운영정보 cellClick.data:', res.data);
console.log('운영정보 length:', res.data.length);
const mappedData = (res.data || []).map((item: any, detailIndex: number) => {
@@ -537,12 +496,14 @@ const SearchModal: React.FC<SearchModalProps> = ({
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim());
return {
...formattedItem,
rowNumber: (detailCurPage - 1) * 4 + detailIndex + 1,
rowNumber: (detailCurPage - 1) * 5 + detailIndex + 1,
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
};
});
console.log('운영정보 cellClick mappedData:', mappedData);
setDetailTableData(mappedData);
setDetailTableCount(res.count || 0);
} catch (error) {
@@ -573,7 +534,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim());
return {
...formattedItem,
rowNumber: (detailCurPage - 1) * 4 + detailIndex + 1,
rowNumber: (detailCurPage - 1) * 5 + detailIndex + 1,
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
};
@@ -588,31 +549,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
}
}
};
// 하수도정비기본계획 테이블 cellClick 핸들러
const handleReportCellClick = (index: number | undefined, headId?: String) => {
console.log(index);
if (typeof index === "number" && tableData[index]) {
const reportData = tableData[index];
const fileName = reportData.fileName;
const filePath = reportData.filePath;
if (reportData.fileSn !== "") {
getFileDownload(reportData.fileSn, fileName, filePath);
}
}
};
const handleCtpvCdChange = (val: string | number) => { // 하수도정비기본계획.시도
const sidoOption = sidos.find((n) => n.val === val);
setCtpvCd(String(val));
if (val !== '0') {
const filterSiguns = siguns.filter(item => item.sido === sidoOption?.text);
filterSiguns.unshift({ val: '0', text: '전체', sido: '0' });
setFilteredSiguns(filterSiguns);
}
setSigungu("0");
setGubun("");
setYearFilter({ start: "", end: "", });
}
const renderBody = () => (
<>
@@ -626,74 +563,64 @@ const SearchModal: React.FC<SearchModalProps> = ({
onValueChange={(value: string) => setActiveTab(value)}
>
</UITab>
{/* 각각의 탭 영역 */}
{/* 기본정보 탭 */}
{activeTab === 'basic' && (
<BasicTab
open={open}
basicType={basicType}
city={city}
sgg={sgg}
start1={start1}
start2={start2}
end1={end1}
end2={end2}
var1={var1}
var2={var2}
yearFilter={yearFilter}
handleSearch={handleSearch}
setBasicType={setBasicType}
setCity={setCity}
setSgg={setSgg}
setYearFilter={setYearFilter}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setVar1={setVar1}
setVar2={setVar2}
/>
)}
{/* 운영정보 탭 */}
{activeTab === 'operation' && (
<OperationTab
open={open}
workType={workType}
var1={var1}
var2={var2}
yearFilter={yearFilter}
handleSearch={handleSearch}
setWorkType={setWorkType}
setVar1={setVar1}
setVar2={setVar2}
setYearFilter={setYearFilter}
/>
)}
{/* 하수도정비기본계획보고서 탭 */}
{activeTab === 'report' && (
<ReportTab
open={open}
gubun={gubun}
sidos={sidos}
ctpvCd={ctpvCd}
sigungu={sigungu}
filteredSiguns={filteredSiguns}
yearFilter={yearFilter}
handleSearch={handleSearch}
handleCtpvCdChange={handleCtpvCdChange}
setYearFilter={setYearFilter}
setGubun={setGubun}
setSigungu={setSigungu}
/>
)}
{/* </UITab2> */}
{/* 각각의 탭 영역 */}
{/* 기본정보 탭 */}
{activeTab === 'basic' && (
<BasicTab
open={open}
basicType={basicType}
city={city}
sgg={sgg}
start1={start1}
start2={start2}
end1={end1}
end2={end2}
var1={var1}
var2={var2}
yearFilter={yearFilter}
handleSearch={handleSearch}
setBasicType={setBasicType}
setCity={setCity}
setCtpvName={setCtpvName}
setSgg={setSgg}
setSggName={setSggName}
setYearFilter={setYearFilter}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setVar1={setVar1}
setVar2={setVar2}
/>
)}
{/* 운영정보 탭 */}
{activeTab === 'operation' && (
<OperationTab
open={open}
workType={workType}
var1={var1}
var2={var2}
yearFilter={yearFilter}
handleSearch={handleSearch}
setWorkType={setWorkType}
setVar1={setVar1}
setVar2={setVar2}
setYearFilter={setYearFilter}
/>
)}
{/* 하수도정비기본계획보고서 탭 */}
{activeTab === 'report' && (
<ReportTab
open={open}
/>
)}
{/* </UITab2> */}
{/* 📋 결과 리스트 */}
{/* 기본정보 탭, 하수도정비기본계획보고서 탭 */}
{(activeTab === 'basic' || activeTab === 'report') && (
{/* 하수도정비기본계획보고서 탭 */}
{activeTab === 'basic' && (
<div className="h-[79vh] w-full overflow-hidden rounded-lg border">
{/* 테이블2 영역 (가로/세로 스크롤 가능) */}
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
@@ -706,7 +633,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
headlist={dynamicHeadlist}
pageSize={10}
total={tableCount}
cellClick={activeTab === 'report' ? handleReportCellClick : handleBasicCellClick}
cellClick={handleBasicCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
@@ -740,6 +667,7 @@ const SearchModal: React.FC<SearchModalProps> = ({
</div>
<div className="h-[39vh] w-full overflow-hidden rounded-lg border">
{/* 테이블2 영역 */}
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isDetailLoading} />
<UiTable
@@ -31,6 +31,14 @@ const isYear = (value: string): boolean => {
return /^[0-9]{4}년$/.test(value);
};
export const reportGubuns = [{val: '0', text: '전체'}, {val: '1', text: '보고서'}
, {val: '2', text: '요약보고서'} , {val: '3', text: '부록'}, {val: '4', text: '기타'}];
/**
* Flatten a hierarchical folder structure into a flat array.
* @param data - The hierarchical folder data to flatten.
* @returns An array of flattened folders with their paths and levels.
*/
export function flattenFolders(data: Folder[]): FlattenedFolder[] {
const result: FlattenedFolder[] = [];
const exceptNodeNm = ["부분","통합","전체"];
@@ -72,15 +80,10 @@ export function flattenFolders(data: Folder[]): FlattenedFolder[] {
}
data.forEach((root) => traverse(root, {}, 0));
console.log(result.slice(0, 10));
return result;
}
export const getDcTree = async (clsfSystmNm:string) => {
//const cityName = encodeURIComponent(clsfSystmNm);
const queryString = 'clsfSystmNm='+clsfSystmNm;
console.log("getDcTree queryString:", queryString);
//const result = await getDcData(`/api/v1/dc/clsf${queryString ? `?${queryString}` : ''}`);
const result = await getDcData("/api/v1/dc/clsf?clsfSystmNm=" + clsfSystmNm);
return result;
};
@@ -110,13 +113,8 @@ export const addFileName = async (data:FlattenedFolder[]) => {
data.map(async (item) => {
const filenameArr:ReportDataFile[] = await getDcFile(String(item.clsfSystmSn));
const f = filenameArr[0];
//console.log("clsfSystmSn:", item.clsfSystmSn, "f:", f);
const result = {...item, fileName:f?.fileTitle, regDate:f?.regDt, fileSn:f?.fileSn, filePath:f?.filePath};
// if (f !== undefined && f.fileSn !== "") {
// const fprcs = await getDcFileprcs(f?.fileSn);
// if (fprcs.length>0)
// result.filePath = fprcs[0].filePath;
// }
return result;
})
);
@@ -124,7 +122,6 @@ export const addFileName = async (data:FlattenedFolder[]) => {
}
export const getDcFileprcs = async (fileSn:string) => {
const queryString = 'fileSn='+fileSn;
console.log("getDcTree queryString:", queryString);
const result = await getDcData(`/api/v1/dc/fileprcs${queryString ? `?${queryString}` : ''}`);
return result;
};
@@ -151,9 +148,6 @@ export const fileDownload = (data:Blob, fileName:string) => { // Blob데이터
window.URL.revokeObjectURL(url);
}
export const getFileDownload = async (fileSn:string, fileName:string, filePath:string) => {
//const fileprcsData = await getDcFileprcs(fileSn); // filePath 조회
//if (fileprcsData?.length === 0 ) { alert("filePath 조회 오류"); }
//if (fileprcsData[0].filePath === "") alert("filePath 정보 없으므로 다운로드 불가");
if (filePath === "") alert("filePath 정보 없으므로 다운로드 불가:filesn"+ fileSn);
const blobData = await getDcFileDownload(filePath); // 실제 다운로드 API
fileDownload(blobData, fileName);
@@ -165,12 +159,13 @@ export const getCityCd = async (): Promise<SelectDataType[]> => {
if (!response.ok) throw new Error(`시도 데이터 오류: ${response.status}`);
const res = await response.json();
const city = res.data;
const cityCd = city.map((item: any) => ({
let citys:SelectDataType[] = city.map((item: {adstDstrCd:string, sido:string}) => ({
val: item.adstDstrCd,
text: item.sido,
}));
cityCd.unshift({ val: '0', text: '전체' });
return cityCd;
citys = citys.sort((a:SelectDataType, b:SelectDataType) => a.text.localeCompare(b.text));
citys.unshift({ val: '0', text: '전체' });
return citys;
} catch (error) {
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
return [{ val: '0', text: '전체', sido: '0' }];
@@ -186,9 +181,9 @@ export const useSggCd = () => {
if (result) {
setData(result);
}
console.log("useSggCd호출");
};
fetch();
console.log("useSggCd호출");
}, []);
return data;
};
@@ -200,7 +195,7 @@ export const getSggCd = async (): Promise<SelectDataType[]> => {
if (!response.ok) throw new Error(`시군구 데이터 오류: ${response.status}`);
const res = await response.json();
const sgg = res.data;
const sggCd = sgg.map((item: any) => ({
const sggCd = sgg.map((item: {adstDstrCd:string, sido:string, gugun:string}) => ({
val: item.adstDstrCd,
sido: item.sido,
text: item.gugun,
@@ -222,9 +217,9 @@ export const useCityCd = () => {
if (result) {
setData(result);
}
console.log("useCityCd호출");
};
fetch();
console.log("useCityCd호출");
}, []);
return data;
};
@@ -31,12 +31,6 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
handleSearch,
}) => {
const handleEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleSearch();
}
};
return (
<div className="mb-3">
<div className="mb-2 flex items-center">
@@ -55,10 +49,11 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
endLabel=""
/>
{/* 용도 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">용도</Label>
<SelectBox
className="ml-8 w-60 mr-8"
className="w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="용도"
label=""
selectArray={MS_SWAGE_MHL_USE_CODES}
value={var1}
onSelectValue={(val) => {
@@ -67,7 +62,7 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
selectContentClass="z-[101]"
/>
{/* 하수맨홀 구경 */}
<Label className="mr-2 w-auto text-xl text-gray-600">구경(mm)</Label>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">구경(mm)</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
@@ -77,7 +72,12 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
@@ -89,7 +89,12 @@ const SwageMhl: React.FC<SwageMhlProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
@@ -32,12 +32,6 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
handleSearch,
}) => {
const handleEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleSearch();
}
};
return (
<div className="mb-3">
<div className="flex items-center mb-2">
@@ -50,7 +44,7 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
endLabel=""
/>
{/* 일일처리용량 - 오수맨홀 */}
<Label className="ml-8 mr-2 w-auto text-xl text-gray-600">일일처리용량(㎥)</Label>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">일일처리용량(㎥)</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
@@ -60,7 +54,12 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
@@ -72,12 +71,15 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
{/* 양수능력 - 우수맨홀 */}
<Label className="mr-2 w-auto text-xl text-gray-600">
양수능력(m²/d)
</Label>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">양수능력(m²/d)</Label>
<Input
className="w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
@@ -87,7 +89,12 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setStart2(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
@@ -99,7 +106,12 @@ const SwagePmstn: React.FC<SwagePmstnProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd2(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
@@ -10,12 +10,16 @@ interface SwagePplProps {
var1: string;
var2: string;
start1: string;
start2: string;
end1: string;
end2: string;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setVar2: (value: string) => void;
setStart1: (value: string) => void;
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
@@ -24,22 +28,20 @@ const SwagePpl: React.FC<SwagePplProps> = ({
var1,
var2,
start1,
start2,
end1,
end2,
yearFilter,
setVar1,
setVar2,
setStart1,
setStart2,
setEnd1,
setEnd2,
setYearFilter,
handleSearch,
}) => {
const handleEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleSearch();
}
};
return (
<div className="mb-6">
<div className="mb-2 flex items-center">
@@ -58,10 +60,11 @@ const SwagePpl: React.FC<SwagePplProps> = ({
endLabel=""
/>
{/* 용도 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">용도</Label>
<SelectBox
className="ml-8 w-60 mr-8"
className="w-40 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="용도"
label=""
selectArray={MS_SWAGE_PPL_USE_CODES}
value={var1}
onSelectValue={(val) => {
@@ -70,10 +73,11 @@ const SwagePpl: React.FC<SwagePplProps> = ({
selectContentClass="z-[101]"
/>
{/* 재질 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">재질</Label>
<SelectBox
className="w-60 mr-8"
selectClass="rounded-lg bg-white text-xl"
label="재질"
label=""
selectArray={MS_SWAGE_PPL_CODES}
value={var2}
onSelectValue={(val) => {
@@ -82,32 +86,7 @@ const SwagePpl: React.FC<SwagePplProps> = ({
selectContentClass="z-[101]"
/>
{/* 관경 */}
<Label className="mr-2 w-auto text-xl text-gray-600">관경(mm)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={var1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setVar1(val);
}}
onKeyDown={handleEnterKey}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={end1}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
onKeyDown={handleEnterKey}
/>
{/* 연장 */}
<Label className="mr-2 w-auto text-xl text-gray-600">연장(m)</Label>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">관경(mm)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
@@ -117,7 +96,12 @@ const SwagePpl: React.FC<SwagePplProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
@@ -129,7 +113,47 @@ const SwagePpl: React.FC<SwagePplProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
{/* 연장 */}
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">연장(m)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={start2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart2(val);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={end2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd2(val);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
@@ -1,8 +1,10 @@
// 하수처리시설
import React from 'react';
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { Button, Input, Label } from '@common/components';
import React from 'react';
import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox';
interface SwagePrcsFcltProps {
var1: string;
@@ -10,42 +12,53 @@ interface SwagePrcsFcltProps {
start2: string;
end1: string;
end2: string;
city: number;
sgg: number;
yearFilter: { start: string; end: string };
setVar1: (value: string) => void;
setStart1: (value: string) => void;
setStart2: (value: string) => void;
setEnd1: (value: string) => void;
setEnd2: (value: string) => void;
setCity: (value: number) => void;
setCtpvName: (name: string) => void;
setSgg: (value: number) => void;
setSggName: (name: string) => void;
setYearFilter: (filter: { start: string; end: string }) => void;
handleSearch: () => void;
}
const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
var1,
start1,
start2,
end1,
end2,
city,
sgg,
yearFilter,
setVar1,
setStart1,
setStart2,
setEnd1,
setEnd2,
setCity,
setCtpvName,
setSgg,
setSggName,
setYearFilter,
handleSearch,
}) => {
const handleEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleSearch();
}
};
return (
<div className="mb-3">
{/* 가동개시일자 */}
<div className="mb-2 flex items-center">
<SidoSigunguSelectBox
sido={city}
sigungu={sgg}
onSidoChange={(sidoId) => {
setCity(sidoId);
setSgg(0);
}}
onSigunguChange={setSgg}
setCtpvName={setCtpvName}
setSggName={setSggName}
/>
{/* 가동개시일자 */}
<Label className="mr-2 w-auto text-xl text-gray-600">가동개시일자</Label>
<YearRangeSelectBox
start={yearFilter.start}
@@ -61,7 +74,7 @@ const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
endLabel=""
/>
{/* 시설용량 */}
<Label className="ml-8 mr-2 w-auto text-xl text-gray-600">시설용량(㎥/d)</Label>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시설용량(㎥/d)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
@@ -71,7 +84,12 @@ const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setStart1(val);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
@@ -83,43 +101,12 @@ const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd1(val);
}}
onKeyDown={handleEnterKey}
/>
{/* 처리구역 면적 */}
<Label className="mr-2 w-auto text-xl text-gray-600">처리구역 면적(m²)</Label>
<Input
className="w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={start2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setStart2(val);
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
onKeyDown={handleEnterKey}
/>
<span className="mx-2 text-xl font-semibold">~</span>
<Input
className="mr-8 w-[60px] !text-xl placeholder:text-center"
placeholder="입력"
value={end2}
onChange={(e) => {
// 숫자만 입력 허용
const val = e.target.value.replace(/[^0-9]/g, "");
setEnd2(val);
}}
onKeyDown={handleEnterKey}
/>
{/* 하수처리시설명 */}
<Label className="mr-2 w-auto text-xl text-gray-600">하수처리시설명</Label>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={var1}
onChange={(e) => {
setVar1(e.target.value);
}}
onKeyDown={handleEnterKey}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
@@ -28,12 +28,6 @@ const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
handleSearch,
}) => {
const handleEnterKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleSearch();
}
};
return (
<div className="mb-3">
<div className="mb-2 flex items-center">
@@ -46,17 +40,7 @@ const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
}}
onSigunguChange={setSgg}
/>
<Label className="mr-2 w-auto text-xl text-gray-600">하수처리구역명</Label>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={var1}
onChange={(e) => {
setVar1(e.target.value);
}}
onKeyDown={handleEnterKey}
/>
<Label className="mr-2 w-auto text-xl text-gray-600">하수처리시설명</Label>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리시설명</Label>
<Input
className='!text-xl w-[120px] placeholder:text-center mr-8'
placeholder="입력"
@@ -64,7 +48,27 @@ const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
onChange={(e) => {
setVar2(e.target.value);
}}
onKeyDown={handleEnterKey}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리구역명</Label>
<Input
className="mr-8 w-[100px] !text-xl placeholder:text-center"
placeholder="입력"
value={var1}
onChange={(e) => {
setVar1(e.target.value);
}}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
@@ -218,23 +218,24 @@ const BaseLayout = ({
<div className="flex items-center w-full">
{showDatePicker && ( // showDatePicker 값에 따라 DatePicker 렌더링
<>
<Label className="mr-4 w-20 text-xl text-gray-600 whitespace-nowrap">상수사용기간</Label>
<Label className="ml-2 mr-4 w-20 text-xl font-medium text-gray-600 whitespace-nowrap">상수사용기간</Label>
<DateMonthPicker
field={{
value: aplcnYmFrom || (() => { // aplcnYm이 없으면 현재 연월을 기본값으로 설정
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
return `${year}${month}`;
// const month = String(now.getMonth() + 1).padStart(2, '0');
// return `${year}${month}`;
return `${year}01`;
})(), // yyyyMM 형식
onChange: (value: string) => {
setAplcnYmFrom?.(value); // string 값을 직접 전달
}
}}
selectClass="ml-5 w-[100px]"
selectClass="ml-8 w-[100px]"
startYear={1900} // 시작 연도 설정
/>
<span className="font-semibold text-xl mx-2">~</span>
<span className="font-semibold text-xl mx-4">~</span>
<DateMonthPicker
field={{
value: aplcnYmTo || (() => { // aplcnYm이 없으면 현재 연월을 기본값으로 설정
@@ -247,7 +248,7 @@ const BaseLayout = ({
setAplcnYmTo?.(value); // string 값을 직접 전달
}
}}
selectClass="w-[100px]"
selectClass="w-[100px] mr-8"
startYear={1900} // 시작 연도 설정
/>
</>
@@ -258,21 +259,40 @@ const BaseLayout = ({
setRtnEnvPartSidoValue={(val) => setCtpvCd?.(val)}
setRtnEnvPartSigunValue={setSigungu} // 선택된 시군구 값을 받을 콜백 함수 전달
>
<SelectBox label={"하수처리장"} value={selectedSwageTreatmentPlant} selectArray={treatmentFacilityOptions} className="col-span-3" selectClass="ml-5 rounded-lg bg-white truncate" onSelectValue={(val) => onSwageTreatmentPlantChange?.(val)} selectContentClass="z-[101]" />
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-4">하수처리장</Label>
<SelectBox
label={''}
value={selectedSwageTreatmentPlant}
selectArray={treatmentFacilityOptions}
className="w-[160px]"
selectClass="rounded-lg bg-white truncate"
onSelectValue={(val) => onSwageTreatmentPlantChange?.(val)}
selectContentClass="z-[101]"
/>
{/* <SelectBox label={"하수처리구역"} value={selectedSwageProcessingZone} selectArray={processingZoneOptions} className="col-span-3" selectClass="rounded-lg bg-white truncate" onSelectValue={(val) => onSwageProcessingZoneChange?.(val)} selectContentClass="z-[101]" /> */}
</GovSidoSigunguSearchForm>
{selectBox?.searchChk ? <SearchFormRight><Button size="sm" onClick={() => selectBox.onSearchClick?.()}>조회</Button></SearchFormRight> : null}
{selectBox?.searchChk && (
<div className='flex flex-1 justify-end mr-6'>
<Button size="sm" onClick={() => selectBox.onSearchClick?.()}>조회</Button>
</div>
)}
</div>
</ListDiv>
<ListDiv>
<div className="card-header">
<h3 className="text-2xl font-medium">{titleName.firstCardTitle}</h3>
<div>
{graphBtn ? <Button className="px-4 py-2 !mr-[1.2rem] bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={isChckFile}>파일 다운로드</Button> : null}
{graphBtn && (
<Button className="px-4 py-2 !mr-[1.2rem] bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={isChckFile}>파일 다운로드</Button>
)}
{/* 그래프 있을 시 */}
{graphBtn ? <Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm" onClick={isDeleteFile}>삭제</Button> : null}
{graphBtn && (
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm" onClick={isDeleteFile}>삭제</Button>
)}
{/* 분석 버튼 */}
{analysisBtn ? <Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm" onClick={onAnalysis}>{analysisBtn}</Button> : null}
{analysisBtn && (
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm" onClick={onAnalysis}>{analysisBtn}</Button>
)}
</div>
</div>
<Form {...form}>
@@ -284,19 +304,23 @@ const BaseLayout = ({
</form>
</Form>
</ListDiv>
{
children?.[1] != null ? <ListDiv>
<div className="card-header flex items-center justify-between">
{children?.[1] != null && (
<ListDiv>
<div className="card-header flex items-center">
<h3 className="text-2xl font-medium">{titleName?.secondCardTitle}</h3>
<div>
{graphBtn ? <Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm">파일 다운로드</Button> : null}
<div className='flex flex-1 justify-end mr-8'>
{graphBtn && (
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm">파일 다운로드</Button>
)}
{/* 그래프 있을 시 */}
{graphBtn ? <Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm">삭제</Button> : null}
{graphBtn && (
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm">삭제</Button>
)}
</div>
</div>
<div className="card !m-[1.2rem]">{children?.[1]}</div>
</ListDiv> : null
}
</ListDiv>
)}
</Form>
)
}
@@ -47,7 +47,7 @@ interface ApiSelectOption {
}
const IrSetting = () => {
const [input1, setInput1] = useState('');
const [input1, setInput1] = useState('0.8'); // 오수전환율 초기값
const [input2, setInput2] = useState('');
const [select1, setSelect1] = useState('0'); // 환경청코드
const [select2, setSelect2] = useState('0'); // 시도코드
@@ -387,10 +387,7 @@ const IrSetting = () => {
accept={".xls, .xlsx, .xlsm, .xltx"}
fileIdx={2} />
</FormSection>
<FormSection
name='inputdate'
form={form}
titleNm='▷ 상수사용량 적용월'>
<FormSection name='inputdate' form={form} titleNm='▷ 상수사용량 적용월'>
{/* 연월 선택 라이브러리로 수정 필요 */}
<DateMonthPicker
field={{
@@ -399,14 +396,11 @@ const IrSetting = () => {
setSelectedDate(value);
}
}}
selectClass="ml-5 w-[150px]"
selectClass="ml-5 w-[225px]"
startYear={1900} // 시작 연도 설정
/>
</FormSection>
<FormSection
name='rtkSource'
form={form}
titleNm='▷ 오수전환율'>
<FormSection name='rtkSource' form={form} titleNm='▷ 오수전환율'>
<Input
value={input1}
onChange={(e) => {
@@ -430,18 +424,23 @@ const IrSetting = () => {
setInput1(newValue);
}}
className="ml-5 h-[3.2rem] text-center text-xl w-[150px]"
className="ml-5 h-[3.2rem] text-center text-xl w-[225px]"
placeholder="예: 0.75"
/>
</FormSection>
<FormSection
name='analysis information'
form={form}
titleNm='▷ 분석 정보'>
<FormSection name='analysis information' form={form} titleNm='▷ 분석 정보'>
<Input
value={input2}
onChange={(e) => setInput2(e.target.value)}
className="ml-5 h-[3.2rem] text-center text-xl w-[150px]" />
className="ml-5 h-[3.2rem] text-center text-xl w-[225px]"
placeholder='세부 분석정보 입력'
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleAnalysisClick();
}
}}
/>
</FormSection>
<ListDiv>
<div className="card !m-[1.2rem]">
@@ -61,8 +61,8 @@ const defaultFormValues: FormSchemaType = {
sggCd: "",
swageTmplntCd: "",
swtrmtZoneCd: "",
rtkSource: "출처",
rdiiArea: "123", // 문자열로 기본값 설정
rtkSource: "",
rdiiArea: "", // 문자열로 기본값 설정
unitFactors: [
{ response: "Short-Term", R: "0.040", T: "0.5", K: "1" }, // 문자열로 기본값 설정
{ response: "Medium-Term", R: "0.005", T: "1", K: "2" },
@@ -78,7 +78,7 @@ const defaultFormValues: FormSchemaType = {
aplcnYm: "",
rate: "0.8", // 문자열로 기본값 설정
// rainFile: undefined,
analysisInfo: "test 분석정보",
analysisInfo: "",
date: (() => { // 현재 연월을 yyyyMM 형식으로 설정
const now = new Date();
const year = now.getFullYear();
@@ -501,7 +501,7 @@ export default function RTKForm() {
form.setValue("rate", newValue, { shouldValidate: true }); // form의 rate 필드에 설정
}}
className="h-12 text-center text-xl w-[225px] ml-5"
placeholder="예: 0.75"
placeholder="0 ~ 1 사이의 값 입력"
/>
</FormSection>
<FormSection name='date' form={form} titleNm='○ 상수사용량 적용월'>
@@ -512,17 +512,24 @@ export default function RTKForm() {
form.setValue("date", value, { shouldValidate: true }); // form의 date 필드에 직접 설정
}
}}
selectClass="ml-5 w-[200px]"
selectClass="ml-5 w-[225px]"
startYear={1900} // 시작 연도 설정
/>
</FormSection>
<FormSection name='rate' form={form} titleNm='○ 분석 정보'>
<Input {...form.register("analysisInfo")} className="h-12 text-center text-xl w-[225px] ml-5" />
<Input
{...form.register("analysisInfo")}
className="h-12 text-center text-xl w-[225px] ml-5"
placeholder='세부 분석정보 입력'
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleAnalysisClick();
}
}}
/>
</FormSection>
</div>
{/* <div className="flex justify-end mt-1">
<Button size="sm" type="submit" onClick={handleAnalysisClick}>RDII분석 실행</Button>
</div> */}
</div>
]}
</BaseLayout >
@@ -22,8 +22,9 @@ const formSchema = z.object({
aplcnYmFrom: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
return `${year}${month}`;
// const month = String(now.getMonth() + 1).padStart(2, '0');
// return `${year}${month}`;
return `${year}01`; // 기본값을 1월로 설정
}), // 분석기간 시작연월
aplcnYmTo: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경
const now = new Date();
@@ -66,8 +67,9 @@ const Result = () => {
aplcnYmFrom: (() => { // 현재 연월을 yyyyMM 형식으로 설정
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
return `${year}${month}`;
// const month = String(now.getMonth() + 1).padStart(2, '0');
// return `${year}${month}`;
return `${year}01`;
})(),
aplcnYmTo: (() => { // 현재 연월을 yyyyMM 형식으로 설정
const now = new Date();
@@ -22,8 +22,9 @@ const formSchema = z.object({
aplcnYmFrom: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
return `${year}${month}`;
// const month = String(now.getMonth() + 1).padStart(2, '0');
// return `${year}${month}`;
return `${year}01`;
}), // 분석기간 시작연월
aplcnYmTo: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경
const now = new Date();
@@ -62,8 +63,9 @@ const Result = () => {
aplcnYmFrom: (() => { // 현재 연월을 yyyyMM 형식으로 설정
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
return `${year}${month}`;
// const month = String(now.getMonth() + 1).padStart(2, '0');
// return `${year}${month}`;
return `${year}01`;
})(),
aplcnYmTo: (() => { // 현재 연월을 yyyyMM 형식으로 설정
const now = new Date();
@@ -160,6 +160,12 @@ const Page = () => {
className='w-[100px]'
value={usr}
onChange={(e) => setUsr(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
</div>
<div className='flex items-center'>
@@ -168,6 +174,12 @@ const Page = () => {
className='w-[100px]'
value={pjNm}
onChange={(e) => setpjNm(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
</div>
</div>
@@ -114,8 +114,8 @@ const Page = () => {
atflId: id,
dcrpPplMtncBizNm: fileNm
})
if (data) {
alert('파일이 등록되었습니다.');
if (data) {
alert('파일이 등록되었습니다.');
setIsModalOpen(false);
handleSearch();
}
@@ -154,6 +154,12 @@ const Page = () => {
className='w-[100px] !text-2xl'
value={usr}
onChange={(e) => setUsr(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
</div>
<div className='flex items-center'>
@@ -162,6 +168,12 @@ const Page = () => {
className='w-[100px] !text-2xl'
value={pjNm}
onChange={(e) => { setpjNm(e.target.value) }}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키 기본 동작 방지
handleSearch();
}
}}
/>
</div>
</div>
+14 -3
View File
@@ -85,9 +85,8 @@ export const deleteData = async (url: string, data?: object): Promise<any> => {
return res;
};
// RSONE DC API 호출
// DC API 호출
export const getDcData = async (url: string, data?: object): Promise<any> => {
console.log(url);
const res = await fetch('/dc-service' + url, {
method: "GET",
});
@@ -98,7 +97,7 @@ export const getDcData = async (url: string, data?: object): Promise<any> => {
throw new Error('Failed to fetch data');
};
// RSONE DC API 호출
// CMS API 호출
export const getCmsData = async (url: string, data?: object): Promise<any> => {
console.log(url);
const res = await fetch('/cms-service' + url, {
@@ -111,6 +110,18 @@ export const getCmsData = async (url: string, data?: object): Promise<any> => {
throw new Error('Failed to fetch data');
};
// GeoServer API 호출
export const getGeoData = async (url: string, data?: object): Promise<any> => {
const res = await fetch('/geoserver' + url, {
method: "GET",
});
if (res.ok) {
const data = await res.json();
return data;
}
throw new Error('Failed to fetch data');
};
export function getCookie(name: string) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match && match[2]) {
+5 -3
View File
@@ -103,8 +103,10 @@ export const formatDateString = (dateStr: string): string => {
}
const year = cleanStr.substring(0, 4);
const month = parseInt(cleanStr.substring(4, 6)); // parseInt로 앞의 0 제거
const day = parseInt(cleanStr.substring(6, 8)); // parseInt로 앞의 0 제거
const month = cleanStr.substring(4, 6); // parseInt로 앞의 0 제거
// const month = parseInt(cleanStr.substring(4, 6)); // parseInt로 앞의 0 제거
// const day = parseInt(cleanStr.substring(6, 8)); // parseInt로 앞의 0 제거
const day = cleanStr.substring(6, 8); // parseInt로 앞의 0 제거
return `${year}년 ${month}월 ${day}일`;
return `${year}-${month}-${day}`;
};
@@ -21,7 +21,7 @@ export const formatDisplayData = (data: { [key: string]: any }): { [key: string]
if (/^\d{6}$/.test(dateStr)) {
const year = dateStr.substring(0, 4);
const month = parseInt(dateStr.substring(4, 6));
formattedData[fieldId] = `${year}년 ${month}월`;
formattedData[fieldId] = `${year}-${month}`;
} else {
formattedData[fieldId] = String(value);
}
@@ -45,9 +45,10 @@ export const formatDisplayData = (data: { [key: string]: any }): { [key: string]
// 🎯 undefined 체크 후 parseInt 적용
if (year && month && day && hour && minute) {
const formattedMonth = parseInt(month);
const formattedDay = parseInt(day);
formattedData[fieldId] = `${year}년 ${formattedMonth}월 ${formattedDay}일 ${hour}시 ${minute}분 ${second}초`;
// const formattedMonth = parseInt(month);
// const formattedDay = parseInt(day);
// formattedData[fieldId] = `${year}-${formattedMonth}-${formattedDay} ${hour}:${minute}:${second}`;
formattedData[fieldId] = `${year}-${month}-${day} ${hour}:${minute}:${second}`;
} else {
formattedData[fieldId] = String(value);
}
@@ -1,5 +1,7 @@
import React, { useMemo } from "react";
import React, { useState, useMemo, useEffect } from "react";
import { SelectBox } from '@common/business_components/ui'
import { Label } from '@common/components';
import useStore from '../../store/useStore';
interface Option {
id: number;
@@ -10,150 +12,72 @@ interface SidoSigunguSelectBoxProps {
sido: number;
sigungu: number;
onSidoChange: (id: number) => void;
setCtpvName?: (name: string) => void;
onSigunguChange: (id: number) => void;
setSggName?: (name: string) => void;
className?: string;
}
const sidoList: { id: number, name: string }[] = [
{ id: 0, name: '전체' },
{ id: 26, name: '부산광역시' },
{ id: 28, name: '인천광역시' },
{ id: 30, name: '대전광역시' },
{ id: 41, name: '경기도' },
{ id: 42, name: '강원도' },
{ id: 44, name: '충청남도' },
{ id: 45, name: '전라북도' },
{ id: 46, name: '전라남도' },
{ id: 47, name: '경상북도' },
{ id: 48, name: '경상남도' },
];
const sigunguMap: Record<number, { id: number; name: string }[]> = {
26: [
{ id: 0, name: '전체' },
// ...부산산광역시의 시군구 추가
],
28: [
{ id: 0, name: '전체' },
// ...인천광역시의 시군구 추가
],
30: [
{ id: 0, name: '전체' },
// ...대전광역시의 시군구 추가
],
41: [
{ id: 0, name: '전체' },
{ id: 41820, name: '가평군' },
{ id: 41550, name: '안성시' },
{ id: 41830, name: '양평군' },
{ id: 41670, name: '여주시' },
{ id: 41500, name: '이천시' },
{ id: 41430, name: '의왕시' },
{ id: 41150, name: '의정부시' },
{ id: 41480, name: '파주시' },
{ id: 41650, name: '포천시' },
// ...경기도의 시군구 추가
],
42: [
{ id: 0, name: '전체' },
{ id: 42170, name: '동해시' },
{ id: 42110, name: '춘천시' },
{ id: 42720, name: '홍천군' },
// ...강원도의 시군구 추가
],
44: [
{ id: 0, name: '전체' },
{ id: 44770, name: '서천군' },
// ...충청남도의 시군구 추가
],
45: [
{ id: 0, name: '전체' },
{ id: 45130, name: '군산시' },
{ id: 45190, name: '남원시' },
{ id: 45730, name: '무주군' },
{ id: 45800, name: '부안군' },
{ id: 45770, name: '순창군' },
{ id: 45140, name: '익산시' },
{ id: 45750, name: '임실군' },
{ id: 45710, name: '완주군' },
{ id: 45110, name: '전주시' },
// ...전라북도의 시군구 추가
],
46: [
{ id: 0, name: '전체' },
{ id: 46810, name: "강진군" },
{ id: 46770, name: "고흥군" },
{ id: 46720, name: "곡성군" },
{ id: 46730, name: "구례군" },
{ id: 46230, name: "광양시" },
{ id: 46170, name: "나주시" },
{ id: 46110, name: "목포시" },
{ id: 46840, name: "무안군" },
{ id: 46150, name: "순천시" },
{ id: 46910, name: "신안군" },
{ id: 46130, name: "여수시" },
{ id: 46890, name: "완도군" },
// ...전라남도의 시군구 추가
],
47: [
{ id: 0, name: '전체' },
{ id: 47130, name: "경주시" },
{ id: 47830, name: "고령군" },
{ id: 47190, name: "구미시" },
{ id: 47720, name: "군위군" },
{ id: 47150, name: "김천시" },
{ id: 47280, name: "문경시" },
{ id: 47920, name: "봉화군" },
{ id: 47250, name: "상주시" },
{ id: 47770, name: "영덕군" },
{ id: 47760, name: "영양군" },
{ id: 47210, name: "영주시" },
{ id: 47900, name: "예천군" },
{ id: 47930, name: "울진군" },
{ id: 47730, name: "의성군" },
{ id: 47750, name: "청송군" },
{ id: 47850, name: "칠곡군" },
{ id: 47110, name: "포항시" },
// ...경상북도의 시군구 추가
],
48: [
{ id: 0, name: '전체' },
{ id: 48310, name: "거제시" },
{ id: 48250, name: "김해시" },
{ id: 48270, name: "밀양시" },
{ id: 48220, name: "통영시" },
// ...경상남도의 시군구 추가
],
// ...나머지 시도별 시군구 추가
};
export function SidoSigunguSelectBox({
sido,
sigungu,
onSidoChange,
setCtpvName,
onSigunguChange,
setSggName,
className = "",
}: SidoSigunguSelectBoxProps) {
// 선택된 시도에 따라 시군구 리스트를 가져옴
const sigunguList = useMemo(() => sigunguMap[sido] || [{ id: 0, name: '전체' }], [sido]);
const { ctpv, sgg} = useStore();
useEffect(() => {
(async () => {
onSidoChange(0);
onSigunguChange(0);
if (setCtpvName && setSggName) {
setCtpvName("");
setSggName("");
}
})();
}, []);
return (
<div className={`flex items-center justify-center ${className} mr-8`}>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시도</Label>
<SelectBox
className="w-[150px] mr-8"
className="w-60 mr-8"
selectClass="rounded-lg bg-white"
label="시도"
selectArray={sidoList.map(opt => ({ val: opt.id, text: opt.name }))}
label=""
selectArray={
[{ val: 0, text: '전체' },
...ctpv.map(opt => ({ val: opt.id, text: opt.name }))
]
}
value={sido}
onSelectValue={val => onSidoChange(Number(val))}
onSelectValue={val => {
onSidoChange(Number(val));
if (setCtpvName) setCtpvName(ctpv.find(opt => Number(opt.id) === Number(val))?.name || "");
}}
selectContentClass="z-[101]"
/>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시군구</Label>
<SelectBox
className="w-48"
selectClass="w-48 rounded-lg bg-white truncate"
label="시군구"
selectArray={sigunguList.map(opt => ({ val: opt.id, text: opt.name }))}
label=""
selectArray={
[{ val: 0, text: '전체' },
...sgg
.filter(opt => String(opt.id).slice(0, 2) === String(sido))
.map(opt => ({ val: opt.id, text: opt.name }))
]
}
value={sigungu}
onSelectValue={val => onSigunguChange(Number(val))}
onSelectValue={val => {
onSigunguChange(Number(val))
if (setSggName) setSggName(sgg.find(opt => Number(opt.id) === Number(val))?.name || "");
}}
selectContentClass="z-[101]"
/>
</div>
@@ -88,9 +88,9 @@ export function YearRangeSelectBox({
};
return (
<div className={`flex items-center ${className}`}>
<div className={`flex items-center mr-8 ${className}`}>
<SelectBox
className="flex-1 mr-3"
className="flex-1"
selectClass={selectClass}
label={startLabel}
selectArray={getStartYearArray()}
@@ -100,7 +100,7 @@ export function YearRangeSelectBox({
/>
<span className="font-semibold text-xl mx-2">~</span>
<SelectBox
className="flex-1 ml-1"
className="flex-1"
selectClass={selectClass}
label={endLabel}
selectArray={getEndYearArray()}
+1 -1
View File
@@ -103,7 +103,7 @@ const FileUploadForm = ({
}}
customPreview={
showPreview ? (
<div className="file-uploader-preview">
<div className="file-uploader-preview text-center">
{files && files.length > 0
? fileName
: "파일을 선택하세요."}
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react';
import { SelectBox } from '@common/business_components/ui/select';
import { Label } from '@radix-ui/react-label';
export type comCodeState = {
code: {
@@ -24,9 +25,9 @@ export type comCodeState = {
};
type SelectDataType = {
text: string;
val: string;
sido?: string; // 시도 코드 (선택 사항)
text: string;
val: string;
sido?: string; // 시도 코드 (선택 사항)
}
type EnvPartSelectDataType = SelectDataType & {
@@ -73,9 +74,9 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
const [allSigunOptions, setAllSigunOptions] = useState<SelectDataType[]>([]);
// 조회된 조건에 맞는 환경청 시도 시군 (SelectBox에 실제 사용될 데이터)
const [filteredEnvPartData, setFilteredEnvPartData] = useState<EnvPartSelectDataType[]>([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]);
const [filteredEnvPartSidoData, setFilteredEnvPartSidoData] = useState<EnvPartSelectDataType[]>([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]);
const [filteredEnvPartSigunData, setFilteredEnvPartSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0', sido: '0' }]);
const [filteredEnvPartData, setFilteredEnvPartData] = useState<EnvPartSelectDataType[]>([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]);
const [filteredEnvPartSidoData, setFilteredEnvPartSidoData] = useState<EnvPartSelectDataType[]>([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }]);
const [filteredEnvPartSigunData, setFilteredEnvPartSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0', sido: '0' }]);
// 시군구 데이터
const getSggCd = async (): Promise<SelectDataType[]> => {
@@ -93,7 +94,7 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
return sggCd;
} catch (error) {
console.error('시군구 데이터를 가져오는데 실패했습니다:', error);
return [{ val: '0', text: '전체', sido: '0' }];
return [{ val: '0', text: '전체', sido: '0' }];
}
};
@@ -112,7 +113,7 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
return cityCd;
} catch (error) {
console.error('시도 데이터를 가져오는데 실패했습니다:', error);
return [{ val: '0', text: '전체', sido: '0' }];
return [{ val: '0', text: '전체', sido: '0' }];
}
};
@@ -135,7 +136,7 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
return lclgvrnmntCd;
} catch (error) {
console.error('환경청 데이터를 가져오는데 실패했습니다:', error);
return [{ val: '0', text: '전체', adstDliStrCd: '', sido: '0' }];
return [{ val: '0', text: '전체', adstDliStrCd: '', sido: '0' }];
}
};
@@ -188,8 +189,8 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
const relevantSigunSidos = Array.from(
new Set(
allSigunOptions
.filter(sigungu => cityCodesInEnvPart.includes(sigungu.val))
.map(sigungu => sigungu.sido)
.filter(sigungu => cityCodesInEnvPart.includes(sigungu.val))
.map(sigungu => sigungu.sido)
)
);
console.log('relevantSigunTexts:', relevantSigunSidos);
@@ -210,8 +211,8 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
// relevantSidos와 relevantSigunsForSidoDerivation은 초기 빈 배열 상태를 유지합니다.
setFilteredEnvPartSidoData([
{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' },
...relevantSidos.map((item: SelectDataType) => ({ text: item.text, val: item.val, adstDliStrCd: '', sido: '0' }))
{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' },
...relevantSidos.map((item: SelectDataType) => ({ text: item.text, val: item.val, adstDliStrCd: '', sido: '0' }))
]);
setFilteredEnvPartSigunDataSelected(relevantSigunsForSidoDerivation);
@@ -246,14 +247,14 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
setEnvPartSigunValue('0'); // 시군구 "전체"로 초기화
// 부모에게도 초기화된 값 전달 (text 포함)
if (setRtnEnvPartSidoValue) {
const sidoDefault = filteredEnvPartSidoData.find(item => item.val === '0') || { val: '0', text: '전체' };
// setRtnEnvPartSidoValue(sidoDefault.val); // 이전 방식: 값만 전달
// TODO: 만약 시도 값도 객체로 전달해야 한다면 아래와 같이 수정
// setRtnEnvPartSidoValue({ val: sidoDefault.val, text: sidoDefault.text });
const sidoDefault = filteredEnvPartSidoData.find(item => item.val === '0') || { val: '0', text: '전체' };
// setRtnEnvPartSidoValue(sidoDefault.val); // 이전 방식: 값만 전달
// TODO: 만약 시도 값도 객체로 전달해야 한다면 아래와 같이 수정
// setRtnEnvPartSidoValue({ val: sidoDefault.val, text: sidoDefault.text });
}
if (setRtnEnvPartSigunValue) {
const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' };
setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text });
const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' };
setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text });
}
break;
case 'envPartSido': // 환경청별 - 시도 선택
@@ -262,8 +263,8 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
initializeCityDataByEnvPartSigun(val);
setEnvPartSigunValue('0'); // 시군구 "전체"로 초기화
if (setRtnEnvPartSigunValue) {
const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' };
setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text });
const sigunDefault = filteredEnvPartSigunData.find(item => item.val === '0') || { val: '0', text: '전체' };
setRtnEnvPartSigunValue({ val: sigunDefault.val, text: sigunDefault.text });
}
break;
case 'envPartSigun': // 환경청별 - 시군구 선택
@@ -286,11 +287,11 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
setEnvPartSigunValue('0');
// 필터링된 목록들도 초기 "전체" 또는 전체 목록으로 리셋
setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]);
setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]);
setFilteredEnvPartData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allEnvPartOptions]);
setFilteredEnvPartSidoData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allSidoOptions.map(s => ({ ...s, adstDliStrCd: '' }))]);
setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]);
setFilteredEnvPartData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allEnvPartOptions]);
setFilteredEnvPartSidoData([{ text: "전체", val: '0', adstDliStrCd: '', sido: '0' }, ...allSidoOptions.map(s => ({ ...s, adstDliStrCd: '' }))]);
setFilteredEnvPartSigunData([{ text: "전체", val: '0', sido: '0' }, ...allSigunOptions]);
setFilteredEnvPartSigunDataSelected(allSigunOptions);
@@ -316,11 +317,35 @@ function GovSidoSigunguSearchForm({ isShowPart = false, children, selectSidoData
return (
isShowPart ? (
<div className="grid grid-cols-12 gap-5 w-11/12 m-4">
<div className="flex items-center my-4">
<>
<SelectBox className="col-span-2" label={'환경청'} selectArray={filteredEnvPartData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPart')} value={envPartValue} selectClass={'rounded-lg bg-white truncate'} />
<SelectBox className="col-span-2" label={'시도'} selectArray={filteredEnvPartSidoData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSido')} value={envPartSidoValue} selectClass={'rounded-lg bg-white truncate'} />
<SelectBox className="col-span-2" label={'시군구'} selectArray={filteredEnvPartSigunData} onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSigun')} value={envPartSigunValue} selectClass={'rounded-lg bg-white truncate'} />
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap ml-2 mr-4">환경청</Label>
<SelectBox
className="w-[160px] mr-8"
label={''}
selectArray={filteredEnvPartData}
onSelectValue={(val) => onSelectValue(val.toString(), 'envPart')}
value={envPartValue}
selectClass={'rounded-lg bg-white truncate'}
/>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-4">시도</Label>
<SelectBox
className="w-[160px] mr-8"
label={''}
selectArray={filteredEnvPartSidoData}
onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSido')}
value={envPartSidoValue}
selectClass={'rounded-lg bg-white truncate'}
/>
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-4">시군구</Label>
<SelectBox
className="w-[160px] mr-8"
label={''}
selectArray={filteredEnvPartSigunData}
onSelectValue={(val) => onSelectValue(val.toString(), 'envPartSigun')}
value={envPartSigunValue}
selectClass={'rounded-lg bg-white truncate'}
/>
</>
{children}
</div>
+2 -2
View File
@@ -121,7 +121,7 @@ export function VerticalTable({
{headlist?.map((head) => (
<TableRow key={head.id}>
{/* 컬럼 제목 */}
<TableCell className="font-bold bg-blue-100 text-xs">
<TableCell className={`font-bold bg-blue-100 text-xs w-[120px] whitespace-nowrap`}>
{head.title}
</TableCell>
{/* 데이터 값 또는 입력 필드 */}
@@ -168,7 +168,7 @@ export function VerticalTable({
{headlist2?.map((head) => (
<TableRow key={head.id}>
{/* 컬럼 제목 */}
<TableCell className="font-bold bg-blue-100 text-xs w-fit whitespace-nowrap">
<TableCell className={`font-bold bg-blue-100 text-xs w-[120px] whitespace-nowrap`}>
{head.title}
</TableCell>
{/* 데이터 값 또는 입력 필드 */}
+41
View File
@@ -0,0 +1,41 @@
import { useMemo } from "react";
import { create } from "zustand";
import { getGeoData } from "@/components/lib/api";
import { get } from "http";
interface Option { id: number, name: string }
interface SnStoreState {
ctpv: Option[];
sgg: Option[];
fetchCtpvData: () => Promise<void>;
fetchSggData: () => Promise<void>;
}
const useStore = create<SnStoreState>((set) => ({
// Define your store state and actions here
ctpv: [],
sgg: [],
fetchCtpvData: async () => {
const ctpvData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_ctpv&outputFormat=application%2Fjson');
const ctpvList: Option[] = ctpvData.features
.map((feature: any) => ({
id: feature.properties.mctpv_cd.trim(),
name: feature.properties.mctpv_korn_nm
}))
.sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko'));
set({ ctpv: ctpvList });
},
fetchSggData: async () => {
const sggData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_sgg&outputFormat=application%2Fjson');
const sggList: Option[] = sggData.features
.map((feature: any) => ({
id: feature.properties.sgg_cd,
name: feature.properties.sgg_korn_nm
}))
.sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko'));
set({ sgg: sggList });
}
}));
export default useStore;
@@ -0,0 +1,89 @@
import { useWrStore } from "@/app/store";
import type { pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import { tableData } from "@/components/lib/func/commom";
import { Title, UiTable } from "@common/business_components/ui";
import { useEffect, useState } from "react";
interface Props {
seletectedLayerNm: string;
viewMode: 'list' | 'detail' | 'nothing';
onFeatureSelect: (feature: any) => void;
onClose: () => void;
isRuseReg: { data: any | undefined };
}
const HasuFacility = ({ seletectedLayerNm, viewMode, onClose, onFeatureSelect, isRuseReg }: Props) => {
const {
code,
pbnst,
pubHasuInit,
} = useWrStore((state) => state);
const { pubFacHeadList, pbnstHasuRes, pbnstHasuResCount } = pbnst;
const [hasuTable, setHasuTable] = useState<pubHasuType[]>();
const [hasuPage, setHasuPage] = useState<number>(1);
useEffect(() => {
if (code.sggCd.length && pbnstHasuRes.length > 0) {
setHasuTable(tableData(pbnstHasuRes, { code }));
}
}, [code, pbnstHasuRes]);
useEffect(() => {
if (seletectedLayerNm !== '하수처리시설' || viewMode != 'list') return;
if (!pbnst.isInit) {
pubHasuInit("1", "0");
}
}, [pbnst.isInit, pubHasuInit]);
useEffect(() => {
if (seletectedLayerNm !== '하수처리시설' || viewMode != 'list') return;
pubHasuInit(String(hasuPage), "0");
}, [hasuPage, pubHasuInit]);
const hasuCellClick = (index: number | undefined) => {
if (index !== undefined && pbnstHasuRes !== undefined) {
onFeatureSelect(pbnstHasuRes[index]);
onClose();
}
};
return (viewMode == 'list' ? (
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center mb-4">
<Title title="하수처리시설 현황" />
</div>
{/* 높이 조정 */}
<UiTable
tableData={hasuTable || []}
headlist={pubFacHeadList}
pageSize={11}
total={pbnstHasuResCount || 0}
headName={""}
cellClick={hasuCellClick}
onPageChange={setHasuPage}
/>
</div>
) :
(
<div style={{ overflowX: 'hidden' }}>
<div className="flex justify-between items-center mb-4">
<Title title="하수처리시설 상세정보" />
</div>
{/* 높이 조정 */}
<UiTable
tableData={isRuseReg?.data || []}
headlist={pubFacHeadList.slice(0, 4)}
pageSize={1}
total={0}
headName={"위치정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
<UiTable
tableData={isRuseReg?.data || []}
headlist={pubFacHeadList.slice(4)}
pageSize={1}
total={0}
headName={"기본정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
</div>
)
)
}
export default HasuFacility;
@@ -0,0 +1,83 @@
import { useWrStore } from '@/app/store';
import type { customHtdflBdst } from '@/app/store/ruseFcltMng/fcltReg/htdflReg';
import { tableData } from '@/components/lib/func/commom';
import SttnDetailModal from '@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal';
import { Title, UiTable } from '@common/business_components/ui';
import { HeadMakeColSpan } from '@common/business_components/ui/table/HeadMakeColSpan';
import React, { useEffect, useState } from 'react'
interface Props {
seletectedLayerNm: string;
viewMode: 'list' | 'detail' | 'nothing';
onFeatureSelect: (feature: any) => void;
onClose: () => void;
htdflDetailModal: { isOpen: boolean; data: customHtdflBdst | undefined };
}
const HtdflFacility = ({ seletectedLayerNm, viewMode, onFeatureSelect, onClose, htdflDetailModal }: Props) => {
const { code, htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore((state) => state);
const { htdflSttnRes, htdflSttnResCount } = htdflSttn;
const [htdflTable, setHtdflTable] = useState<customHtdflBdst[]>();
const [htdflPage, setHtdflPage] = useState(1)
// 온배수시설 cellClick 이벤트 (상세정보)
const htdflCellClick = (index: number | undefined) => {
if (index !== undefined && htdflTable !== undefined) {
onFeatureSelect(htdflTable[index]);
onClose();
}
};
useEffect(() => {
if (seletectedLayerNm !== '온배수시설' || viewMode != 'list') return;
if (!htdflSttn.isInit) {
initHtdfl(false, 1, "20", "0", '', code.cityCd, code.sggCd);
}
}, [code.cityCd, code.sggCd, htdflSttn.isInit, initHtdfl]);
useEffect(() => {
if (seletectedLayerNm !== '온배수시설' || viewMode != 'list') return;
const data = tableData(htdflSttnRes, { code });
const chData = data
.map((item: any) => ({
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0].htdflObj,
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
}))
.filter((item: any) => item.htdflObj !== undefined);
setHtdflTable(chData);
}, [code, htdflSttnRes, htdflSttn.htdflSttHeadList]);
useEffect(() => {
if (seletectedLayerNm !== '온배수시설' || viewMode != 'list') return;
htdflSttnSearch(true, htdflPage, "20", '', '', code.cityCd, code.sggCd);
}, [code.cityCd, code.sggCd, htdflPage, htdflSttnSearch]);
return (
viewMode == 'detail' ? (
<SttnDetailModal type={"HTB"} formObj={htdflDetailModal.data as customHtdflBdst} />
) : (
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center">
<Title title="온배수시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={excelClick}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={htdflTable || []}
headlist={htdflSttn.htdflSttHeadList}
pageSize={20}
total={htdflSttnResCount || 0}
cellClick={(index: number | undefined) => {
htdflCellClick(index ?? undefined);
}}
onPageChange={setHtdflPage}
>
<HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} />
</UiTable>
</div>
)
)
}
export default HtdflFacility
@@ -0,0 +1,105 @@
import { useWrStore } from "@/app/store";
import type { customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { tableData } from "@/components/lib/func/commom";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
import { Title, UiTable } from "@common/business_components/ui";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { useEffect, useState } from "react";
interface Props {
seletectedLayerNm: string;
viewMode: 'list' | 'detail' | 'nothing';
onFeatureSelect: (feature: any) => void;
onClose: () => void;
rainDetailModal: { isOpen: boolean; data: customRainBdst | undefined };
}
const RainFacility = ({seletectedLayerNm,viewMode,onFeatureSelect,onClose,rainDetailModal}:Props) => {
// 빗물재이용시설 변수
const { code, rainSttn, rainSttnSearch, rainSttnInit } = useWrStore(
(state) => state
);
const { rainSttnRes, rainSttnResCount } = rainSttn;
const [rainTable, setRainTable] = useState<customRainBdst[]>();
const [rainPage, setRainPage] = useState(1)
// 빗물재이용시설 cellClick 이벤트 (상세정보)
const rainCellClick = (index: number | undefined, headId: string) => {
if (
index !== undefined &&
rainTable !== undefined &&
headId !== 'chBuildingYn') {
onFeatureSelect(rainTable[index]);
onClose();
}
}
useEffect(() => {
if (seletectedLayerNm !== '빗물이용시설' || viewMode != 'list') return;
console.log('빗물이용시설 초기값 호출', viewMode)
if (!rainSttn.isInit) {
rainSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd);
}
}, [code.cityCd, code.sggCd, rainSttn.isInit, rainSttnInit]);
useEffect(() => {
const data = tableData(rainSttnRes, { code });
const chData = data
.map((item: any) => {
return {
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0].rainyObj,
dtfcltCpct: item.reuseBuilding[0].rainyObj.dtfcltCpct === -1
? "확인불가"
: item.reuseBuilding[0].rainyObj.dtfcltCpct,
instlCst: item.reuseBuilding[0].instlCst === -1
? "확인불가"
: item.reuseBuilding[0].instlCst,
instlCstSprtAmt: item.reuseBuilding[0].instlCstSprtAmt === -1
? "확인불가"
: item.reuseBuilding[0].instlCstSprtAmt,
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
pntfColArea: item.reuseBuilding[0].rainyObj.pntfColArea === -1
? "확인불가"
: item.reuseBuilding[0].rainyObj.pntfColArea,
filtrTrtmfctCpct: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct === -1
? "확인불가"
: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct,
archArea: Math.floor(item.archArea) === -1 ? "확인불가" : item.archArea,
};
})
.filter((item: any) => item.rainyObj !== undefined);
setRainTable(chData);
}, [code, rainSttnRes, rainSttn.rainSttHeadList]);
useEffect(() => {
if (seletectedLayerNm !== '빗물이용시설' || viewMode != 'list') return;
rainSttnSearch(false, rainPage, "20", '', '', code.cityCd, code.sggCd);
}, [code.cityCd, code.sggCd, rainPage, rainSttnSearch]);
return (viewMode == 'detail' ?
(<SttnDetailModal type={"RNB"} formObj={rainDetailModal.data as customRainBdst} />)
: (
<>
<div className="flex justify-between items-center">
<Title title="빗물이용시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={excelClick}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={rainTable || []}
headlist={rainSttn.rainSttHeadList}
pageSize={20}
total={rainSttnResCount}
cellClick={(index: number | undefined, headId: string) => {
rainCellClick(index ?? undefined, headId);
}}
onPageChange={setRainPage}
>
<HeadMakeColSpan upHeadList={rainSttn.rainSttNodeList} />
</UiTable>
</>
))
}
export default RainFacility;
@@ -0,0 +1,146 @@
import { useWrStore } from "@/app/store";
import type { customPbnst } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type";
import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal";
import { Title, UITab, UiTable } from "@common/business_components/ui";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { useState, useEffect, useCallback } from "react";
interface Props {
seletectedLayerNm: string;
viewMode: 'list' | 'detail' | 'nothing';
setFcltPk: (pk: string) => void;
onFeatureSelect: (feature: any) => void;
onClose: () => void;
actTabData: { id: string; name: string; data: any } | undefined;
tabData: { id: string; name: string; data: any }[];
}
const ResueFacility = ({ viewMode, seletectedLayerNm, tabData, actTabData, setFcltPk, onFeatureSelect, onClose}: Props) => {
const [activeTab, setActiveTab] = useState<string>(''); // 현재 활성화된 탭
// 하수재이용시설 변수
const {
pbnstSttn,
pbnstSttnSearch,
pbnSttnInit,
getFlcts
} = useWrStore((state) => state);
const { fclts, pbnstSttnResCount } = pbnstSttn
const [bdstTable, setBdstTable] = useState<WaterReuseFacility[]>()
// 재이용시설 cellClick 이벤트 (상세정보)
const pbnstCellClick = (index: number | undefined) => {
if (
index !== undefined &&
pbnstSttn.pbnstSttnRes &&
pbnstSttn.pbnstSttnRes[index]
) {
setFcltPk(pbnstSttn.pbnstSttnRes[index].pbnstRuseFcltId);
onFeatureSelect(pbnstSttn.pbnstSttnRes[index]);
onClose()
}
};
// 재이용 현황 초기값
useEffect(() => {
if (seletectedLayerNm !== '하수재이용시설' || viewMode !='list') return;
if (!pbnstSttn.isInit) {
getFlcts()
}
}, [seletectedLayerNm, pbnstSttn.isInit]);
useEffect(() => {
if (seletectedLayerNm !== '하수재이용시설' || viewMode !='list') return;
pbnSttnInit("1", "20", {
partValue: "A",
sidoValue: '0',
sigunValue: "0",
regionValue: "",
unitWaterShedValue: "",
middleRegionValue: "",
envPartValue: "",
sidoText: "",
sigunText: ""
}, String(new Date().getFullYear()), pbnstSttn.fclts);
}, [fclts, pbnSttnInit, pbnstSttn.fclts, seletectedLayerNm])
useEffect(() => {
setBdstTable(pbnstSttn.pbnstSttnRes);
}, [seletectedLayerNm, pbnstSttn.pbnstSttnRes]);
// 재이용시설 조회
// 재이용시설 페이징처리 관련 함수
const onPageChangeHandler = useCallback((page: number) => {
if (seletectedLayerNm !== '하수재이용시설' || viewMode !='list') return;
pbnstSttnSearch(
false,
String(page),
String(20),
{
partValue: "A",
sidoValue: "0",
sigunValue: "0",
regionValue: "",
unitWaterShedValue: "",
middleRegionValue: "",
envPartValue: "",
sidoText: "",
sigunText: "",
},
"",
String(new Date().getFullYear()), fclts
);
}, [fclts, pbnstSttnSearch]);
// FIXME: 윤선화차장님 요구사항으로 엑셀 다운로드 삭제.
// const excelClick = useCallback(() => {
// // if (codeData) pbnstSttnSearch(1, "10000", codeData);
// excelDownload(
// [[]],
// "하수재이용시설 현황",
// "sample_pbnstSttn.xlsx",
// "A1:U2"
// );
// }, [pbnstSttnSearch]);
return (
viewMode == 'detail' ?
// 재이용시설 상세
<>
<div className="flex justify-between items-center mb-4">
<Title title="하수재이용시설 상세정보" />
</div>
<div className="flex justify-between items-center mb-8">
<UITab
defaultValue={activeTab}
tabList={tabData.map((tab) => ({
value: tab.id,
label: tab.name,
onClick: () => setActiveTab(tab.id),
}))}
/>
</div>
<PbnstSttnModal
data={actTabData?.data[0] || ({} as customPbnst)}
titleVisible={false}
/>
</> :
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center">
<Title title="하수재이용시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={excelClick}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={bdstTable || []}
headlist={pbnstSttn.pbnstSttHeadList}
pageSize={20}
total={pbnstSttnResCount || 0}
cellClick={(index: number | undefined) => {
pbnstCellClick(index);
}}
onPageChange={onPageChangeHandler}
>
<HeadMakeColSpan upHeadList={pbnstSttn.pbnstSttNodeList} />
</UiTable>
</div>
)
}
export default ResueFacility;
@@ -0,0 +1,103 @@
import { useWrStore } from '@/app/store';
import { tableData, formatPhoneNumber } from '@/components/lib/func/commom';
import { Title, UiTable } from '@common/business_components/ui';
import type { DemandCompType } from '@common/business_components/ui/sdmInsertForm/form';
import moment from 'moment';
import React, { useEffect, useState } from 'react'
interface Props {
seletectedLayerNm: string;
viewMode: 'list' | 'detail' | 'nothing';
onFeatureSelect: (feature: any) => void;
onClose: () => void;
isDmdModal: { data: any | undefined };
}
const ReuseMngFacility = ({seletectedLayerNm, viewMode, onFeatureSelect, onClose, isDmdModal}:Props) => {
const { code,
coSttn,
coSttnInit,
coSttnSearch,
} = useWrStore((state) => state);
const [mngTable, setMngTable] = useState<DemandCompType[]>();
const [mngPage, setMngPage] = useState(1);
const { coSttnRes, coSttnResCount, coSttHeadList } = coSttn;
useEffect(() => {
if (seletectedLayerNm !== '수요처' || viewMode != 'list') return;
if (!coSttn.isInit) {
coSttnInit("1", "20", "0");
}
}, [coSttn.isInit, coSttnInit]);
const coMngCellClick = (index: number | undefined) => {
if (index !== undefined && mngTable !== undefined) {
onFeatureSelect(mngTable[index]);
onClose();
}
};
useEffect(() => {
if (seletectedLayerNm !== '수요처' || viewMode!='list') return;
if (coSttnRes) {
if (coSttnRes?.length > 0 && code.cityCd.length > 0) {
const data = tableData(coSttnRes, { code });
const chData = data.map((item: any) => ({
...item,
telno: formatPhoneNumber(item.telno || undefined),
regDt: moment(item.regDt).format("YYYY-MM-DD"),
dmdInfoId: `${item.dmdInfoId.slice(0, 3)}-${item.dmdInfoId.slice(3, 5)}-${item.dmdInfoId.slice(5, 10)}-${item.dmdInfoId.slice(10)}`
}));
// .filter((item: any) => item !== undefined);
setMngTable(chData);
}
}
}, [coSttnRes, code]);
useEffect(() => {
if (seletectedLayerNm !== '수요처' || viewMode!='list') return;
coSttnSearch(String(mngPage), "20", String(0));
}, [coSttnSearch, mngPage]);
return (
viewMode == 'detail'
? (
<div style={{ overflowX: 'hidden' }}>
<div className="flex justify-between items-center mb-4">
<Title title="수요처 상세정보" />
</div>
{/* 높이 조정 */}
<UiTable
tableData={isDmdModal?.data || []}
headlist={coSttHeadList.slice(0, 3)}
pageSize={1}
total={0}
headName={"위치정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
<UiTable
tableData={isDmdModal?.data || []}
headlist={coSttHeadList.slice(3)}
pageSize={1}
total={0}
headName={"기본정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
</div>
) : (<div>
<div className="flex justify-between items-center">
<Title title="수요처 현황" />
</div>
<UiTable
headName={[]}
tableData={mngTable || []}
headlist={coSttHeadList}
pageSize={20}
total={coSttnResCount + 10 || 0}
cellClick={(index: number | undefined) => {
coMngCellClick(index);
// setUpdateData(coSttnRes[index as number]);
}}
onPageChange={(page) => {
setMngPage(page);
}}
></UiTable></div>)
)
}
export default ReuseMngFacility
@@ -0,0 +1,107 @@
import { useWrStore } from "@/app/store";
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import { tableData } from "@/components/lib/func/commom";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
import { Title, UiTable } from "@common/business_components/ui";
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import { useEffect, useState } from "react";
interface Props {
seletectedLayerNm: string;
viewMode: 'list' | 'detail' | 'nothing';
onFeatureSelect: (feature: any) => void;
onClose: () => void;
rswtrDetailModal: { isOpen: boolean; data: customRswtBdst | undefined };
}
const RswtFacility = ({ seletectedLayerNm, viewMode, onFeatureSelect, onClose, rswtrDetailModal }: Props) => {
const { code, rswtSttn, rswtSttnSearch, rswtSttnInit } = useWrStore(
(state) => state
);
const { rswtSttnRes, rswtSttnResCount } = rswtSttn;
const [rswtrTable, setRswtrTable] = useState<customRswtBdst[]>()
const [rswtrPage, setRswtrPage] = useState(1);
// 중수도시설 cellClick 이벤트 (상세정보)
const rswtCellClick = (index: number | undefined, headId: string) => {
if (headId !== 'chBuildingYn' && index !== undefined && rswtrTable !== undefined) {
// setRswtrDetailModal({ isOpen: true, data: rswtrTable[index] });
// setViewMode('detail')
onFeatureSelect(rswtrTable[index]);
onClose();
}
}
useEffect(() => {
if (seletectedLayerNm !== '중수도시설' || viewMode != 'list') return;
if (!rswtSttn.isInit) {
rswtSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd);
}
}, [code.cityCd, code.sggCd, rswtSttn.isInit, rswtSttnInit]);
useEffect(() => {
if (seletectedLayerNm !== '중수도시설' || viewMode != 'list') return;
const data = tableData(rswtSttnRes, { code });
const chData = data
.map((item: customRswtBdst) => {
return {
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0]?.rswtrObj,
chBuildingYn: item?.chgBuilding[0]?.bdstChgNm !== null && item?.chgBuilding.length > 0 ? 'Y' : 'N',
instlCst: item.reuseBuilding[0]?.instlCst === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCst,
instlCstSprtAmt: item.reuseBuilding[0]?.instlCstSprtAmt === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCstSprtAmt,
archArea: item?.archArea.split('.')[0] !== '-1' ? item?.archArea.split('.')[0] : '확인불가'
}
})
.filter(
(item: customRswtBdst) =>
item.reuseBuilding[0]?.rswtrObj !== undefined
);
setRswtrTable(chData);
}, [code, rswtSttnRes]);
// FIXME: 윤선화 차장님 요구사항으로 엑셀 다운로드 삭제.
// const rswtSttnExcelDownload = useCallback(() => {
// if (rswtSttn.excelList.length > 0) {
// if (rswtSttn.excelList.length === 0) return;
// excelDownload(
// rswtSttn.excelList,
// "중수도시설 현황",
// "sample_rswtSttn.xlsx",
// "A1:W3",
// );
// }
// }, [rswtSttn.excelList])
useEffect(() => {
if (seletectedLayerNm !== '중수도시설' || viewMode != 'list') return;
rswtSttnSearch(false, rswtrPage, "20", '', '', code.cityCd, code.sggCd);
}, [code.cityCd, code.sggCd, rswtSttnSearch, rswtrPage]);
return (
viewMode == 'detail' ?
// 중수도시설 상세
(
<SttnDetailModal type={"RST"} formObj={rswtrDetailModal.data as customRswtBdst} />
) : (
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center">
<Title title="중수도시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={rswtSttnExcelDownload}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={rswtrTable || []}
headlist={rswtSttn.rswtSttHeadList}
pageSize={20}
total={rswtSttnResCount}
cellClick={(index: number | undefined, headId: string) => {
rswtCellClick(index, headId);
}}
onPageChange={setRswtrPage}
>
<HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} />
</UiTable>
</div>
))
}
export default RswtFacility;
@@ -0,0 +1,183 @@
"use client"
import NewWindowPortal from '@/app/map/components/newWindowPortal';
import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg";
import type { pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import type { customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import { useGisContext } from "@common/business_components/ui/map/Gis";
import type { DemandCompType } from '@common/business_components/ui/sdmInsertForm/form';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import ResueFacility from './layerPopup/reuseFacility';
import { detainSttn, fetchHasuDetail, fetchpbnstDetail } from '../util';
import HasuFacility from './layerPopup/hasuFacility';
import RainFacility from './layerPopup/rainFacility';
import RswtFacility from './layerPopup/rswtFacility';
import HtdflFacility from './layerPopup/htdflFacility';
import ReuseMngFacility from './layerPopup/reuseMngFacility';
interface NewWindowPopupProps {
featureData: any;
seletectedLayerNm?: string
onFeatureSelect: (data: any) => void;
onClose: () => void;
}
const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
featureData,
seletectedLayerNm,
onFeatureSelect,
onClose
}) => {
const { gisMap } = useGisContext() as unknown as { checkedLayerIds: React.MutableRefObject<number[]>; treeData: { lyrSn: number }[] | null; gisCore: any; gisMap: any; };
const [tabData, setTabData] = useState<{ id: string; name: string; data: any }[]>([]);
const [activeTab, setActiveTab] = useState<string>('0');
const [viewMode, setViewMode] = useState<'list' | 'detail' | 'nothing'>('list');
const [fcltPk, setFcltPk] = useState<string>('');
// onClose 함수를 useCallback으로 메모이제이션
const memoizedOnClose = useCallback(() => {
onClose();
}, [onClose]);
// 빗물재이용시설 변수
const [rainDetailModal, setRainDetailModal] = useState<{ isOpen: boolean, data: customRainBdst | undefined }>({ data: undefined, isOpen: false });
const [rainList, setRainList] = useState<customRainBdst[]>([]);
// 중수도시설 변수
const [rswtrDetailModal, setRswtrDetailModal] = useState<{ isOpen: boolean, data: customRswtBdst | undefined }>({ data: undefined, isOpen: false });
const [rswtrList, setRswtrList] = useState<customRswtBdst[]>([]);
// 온배수시설 변수
const [htdflDetailModal, setHtdflDetailModal] = useState<{ isOpen: boolean, data: customHtdflBdst | undefined }>({ data: undefined, isOpen: false });
const [htdflList, setHtdflList] = useState<customHtdflBdst[]>([]);
// 하수처리시설 변수
const [hasuList, setHasuList] = useState<pubHasuType[]>([]);
const [isRuseReg, setIsRuseReg] = useState<{
data: any | undefined;
}>({ data: undefined });
// 수요처관리 변수
const [isDmdModal, setIsDmdModal] = useState<{
isMoal: boolean;
data: any | undefined;
}>({ isMoal: false, data: undefined });
const [mngList, setMngList] = useState<DemandCompType[]>([]);
///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 ///////////////////////////////////////////////
const getSelectedLayers = () => {
console.trace('호출확인', 1)
let result = null;
const layers = gisMap ? gisMap.getLayers().getArray().filter((l: any) => l.getVisible()) : []; // gisMap이 null인지 확인 후 레이어 가져오기
let featureLayer: { get: (key: string) => any } = { get: () => null };
layers.forEach((layer: any) => {
const source = layer.getSource();
if (source && source.hasFeature && featureData
&& typeof featureData.getId === 'function' && source.hasFeature(featureData)) {
featureLayer = layer; // 피처가 속한 레이어 찾기)
}
});
result = featureLayer.get('lyrNm');
return result;
};
// 상세 목록 데이터 상태 처리
useEffect(() => {
if (hasuList.length > 0) setIsRuseReg({ data: [hasuList[0]] });
}, [hasuList])
useEffect(() => {
if (rainList.length > 0) setRainDetailModal({ isOpen: true, data: rainList[0] });
}, [rainList])
useEffect(() => {
if (rswtrList.length > 0) setRswtrDetailModal({ isOpen: true, data: rswtrList[0] });
}, [rswtrList])
useEffect(() => {
if (htdflList.length > 0) setHtdflDetailModal({ isOpen: true, data: htdflList[0] });
}, [htdflList])
useEffect(() => {
if (mngList.length > 0) setIsDmdModal({ isMoal: true, data: [mngList[0]] });
}, [mngList])
const lastCalledIdRef = useRef<string | null>(null);
const [layerId, setLayerId] = useState<string | null>();
useEffect(() => {
const layers = getSelectedLayers();
setLayerId(layers);
}, []); // 최초 렌더링 시 호출
// 피쳐 데이터가 변경될 때마다 호출
useEffect(() => {
if (!featureData || typeof featureData.getProperties !== "function" || featureData.getProperties() == '') return;
const selectedProps = featureData.getProperties();
const currentId = featureData.getId?.() || selectedProps?.id || selectedProps?.fid;
// 유효하지 않은 ID는 아예 무시
if (!currentId || typeof currentId !== 'string') return;
// 이전과 동일하면 무시
if (!currentId || currentId === lastCalledIdRef.current) return;
lastCalledIdRef.current = currentId // 새로운 피처일 때만 API 호출
const layerId = getSelectedLayers?.();
if (!layerId || typeof layerId !== 'string') return;
const featureCd =
layerId === '하수재이용시설' ? selectedProps?.swtrmt_fclt_cd :
['빗물이용시설', '중수도시설', '온배수시설', '수요처'].includes(layerId) ? selectedProps?.bdst_nm :
layerId === '하수처리시설' ? selectedProps?.swtrmt_fclt_nm :
null;
if (!featureCd || featureCd === fcltPk) return;
if (layerId === '하수재이용시설') {
fetchpbnstDetail(featureCd, setTabData);
} else if (layerId === '하수처리시설') {
fetchHasuDetail(featureCd, selectedProps?.swtrmt_fclt_cd).then((data) => { setHasuList(data) })
} else {
detainSttn(featureCd, layerId).then((res) => {
if (layerId === '빗물이용시설') setRainList(res);
else if (layerId === '중수도시설') setRswtrList(res);
else if (layerId === '온배수시설') { setHtdflList(res); setHtdflDetailModal({ isOpen: true, data: res[0] }); }
else if (layerId === '수요처') setMngList(res);
});
}
setFcltPk(featureCd);
setActiveTab(featureCd);
setViewMode("detail");
}, [featureData]);
///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 ///////////////////////////////////////////////
// 체크된 레이어에 따른 조건부 컴포넌트 렌더링 함수
const renderConditionalContent = () => {
const actTabData = tabData.find((tab) => tab.id === activeTab);
if (layerId === null || layerId === undefined) {
setLayerId(seletectedLayerNm || '');
}
switch (layerId) {
case '하수재이용시설':
return (<ResueFacility viewMode={viewMode} seletectedLayerNm={layerId} tabData={tabData} actTabData={actTabData} setFcltPk={setFcltPk} onFeatureSelect={onFeatureSelect} onClose={onClose} />)
case '하수처리시설':
return (<HasuFacility seletectedLayerNm={layerId} viewMode={viewMode} onFeatureSelect={onFeatureSelect} onClose={onClose} isRuseReg={isRuseReg} />)
case '빗물이용시설':
return (<RainFacility seletectedLayerNm={layerId} viewMode={viewMode} onFeatureSelect={onFeatureSelect} onClose={onClose} rainDetailModal={rainDetailModal} />)
case '중수도시설':
return (<RswtFacility seletectedLayerNm={layerId} viewMode={viewMode} onFeatureSelect={onFeatureSelect} onClose={onClose} rswtrDetailModal={rswtrDetailModal} />)
case '온배수시설':
return (<HtdflFacility seletectedLayerNm={layerId} viewMode={viewMode} onFeatureSelect={onFeatureSelect} onClose={onClose} htdflDetailModal={htdflDetailModal} />)
case '수요처':
return(<ReuseMngFacility seletectedLayerNm={layerId} viewMode={viewMode} onFeatureSelect={onFeatureSelect} onClose={onClose} isDmdModal={isDmdModal} />)
default:
break;
}
return null; // 조건에 맞는 콘텐츠가 없을 경우
};
return (
viewMode == 'nothing' ? <></> :
<NewWindowPortal
onClose={memoizedOnClose}
title="시설 상세 정보"
scrollbars='yes'
viewMode={viewMode}
resizable='no'>
{/* 체크된 레이어에 따른 조건부 렌더링 */}
{renderConditionalContent()}
</NewWindowPortal>
);
};
export default NewWindowPopup;
@@ -31,9 +31,10 @@ interface NewWindowPortalProps {
height?: number;
resizable?: string;
scrollbars?: string;
viewMode?: 'list' | 'detail' | 'nothing';
}
const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, title = "", width = 900, height = 800, resizable = "yes", scrollbars = "yes" }) => {
const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, title = "", resizable = "yes", scrollbars = "yes", viewMode }) => {
const [container, setContainer] = useState<HTMLElement | null>(null);
const newWindowRef = useRef<Window | null>(null);
const onCloseRef = useRef(onClose);
@@ -46,7 +47,15 @@ const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, ti
const handleUnload = useCallback(() => {
onCloseRef.current();
}, []);
useEffect(() => {
if (newWindowRef.current) {
if (viewMode == 'detail') {
newWindowRef.current.resizeTo(1100, 700);
} else {
newWindowRef.current.resizeTo(screen.availWidth, screen.availHeight);
}
}
}, [viewMode]);
useEffect(() => {
// 이미 창이 열려있으면 새로 열지 않음
if (newWindowRef.current && !newWindowRef.current.closed) return;
@@ -57,11 +66,11 @@ const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, ti
const screenHeight = window.innerHeight ?? document.documentElement.clientHeight;
// 중앙 위치 계산
const left = screenLeft + (screenWidth - width) / 2;
const top = screenTop + (screenHeight - height) / 2;
const left = screenLeft + (screenWidth - window.screen.width) / 2;
const top = screenTop + (screenHeight - window.screen.height) / 2;
// 1. 새 창을 열고 참조를 저장합니다.
const popupOptions = `width=${width},height=${height},left=${left}, top=${top}, resizable=${resizable},scrollbars=${scrollbars}`;
const popupOptions = `width=${window.screen.width},height=${window.screen.height},left=${left}, top=${top}, resizable=${resizable},scrollbars=${scrollbars}`;
newWindowRef.current = window.open('', title, popupOptions);
if (newWindowRef.current) {
+26 -29
View File
@@ -3,7 +3,7 @@
import Gis from "@common/business_components/ui/map/Gis";
import { useEffect, useRef, useState, useCallback } from "react";
import { mapService } from "../service";
import NewWindowPopup from "../newWindowPopup";
import NewWindowPopup from "../components/newWindowPopup";
import GisApp from "@common/business_components/ui/map/lib/gis.core";
const Map = () => {
@@ -11,7 +11,7 @@ const Map = () => {
const gisMaps = useRef<any | null>(null);
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
const [isSearchModalOpen, setIsSearchModalOpen] = useState(true); // SearchModal 열림 상태
const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터
const [featureData, setFeatureData] = useState<any>(null); // 선택된 피쳐 데이터
const [checkedLayers, setCheckedLayers] = useState<string[]>([]);
const [checkedLayersData, setCheckedLayersData] = useState<any[]>([]);
@@ -63,25 +63,25 @@ const Map = () => {
let foundFeature: any = null;
let featureId = data.fid;
const layerName = data.layerNm;
if (layerName === "tb_wr_bdst_ruse_fclt") {
console.log("선택된 레이어 이름:", data, layerName);
if (layerName === "하수재이용시설") {
// 재이용시설
featureId = `${layerName}.${data.searchPk}`;
} else if ( //빗물이용시설, 중수도시설
layerName === "tb_wr_rnwtr_utztn_fclt" ||
layerName == "tb_wr_rswtr_fclt"
layerName === "빗물이용시설" ||
layerName == "중수도시설"
) {
featureId = `${layerName}.${data.bdstInfoSn}`;
} else if (layerName === "tb_il_swage_prcs_fclt") { //하수처리시설
} else if (layerName === "하수처리시설") { //하수처리시설
featureId = `${layerName}.${data.bscFctCd}`;
} else if (layerName === "tb_wr_htdfl_fclt") { //온배수시설
} else if (layerName === "온배수시설") { //온배수시설
featureId = `${layerName}.${data.bdstRuseFcltSn}`;
} else if (layerName == "tb_wr_ruse_fclt_dmd_co") { //수요처
} else if (layerName == "수요처") { //수요처
featureId = `${layerName}.${data.dmdInfoId.replaceAll("-", "")}`;
} else {
console.warn("해당 레이어에 대한 featureId 매핑 없음", layerName);
featureId = `${layerName}.${data.fid || data.id || data.ftrIdn}`;
}
map
.getLayers()
.getArray()
@@ -111,7 +111,9 @@ const Map = () => {
} else {
console.warn("OpenLayers Feature를 찾을 수 없습니다:", data);
}
const currentId = data?.fid || data?.id || data?.ftrIdn;
const lastId = featureData?.fid || featureData?.id || featureData?.ftrIdn;
if (featureData && currentId === lastId) return; // 이전과 같으면 무시
setFeatureData(data);
setIsOpen(true);
setIsSearchModalOpen(false);
@@ -127,7 +129,18 @@ const Map = () => {
// />
// );
// };
const renderDetailView = useCallback(
(props: any) => (
<NewWindowPopup
key={featureData?.fid || featureData?.id || featureData?.ftrIdn}
onClose={handlePopupClose}
checkedLayers={checkedLayers}
checkedLayersData={checkedLayersData}
{...props}
/>
),
[checkedLayers, checkedLayersData] // 필요 시 의존성 넣기
);
return (
<div className="bg-container">
<Gis
@@ -136,24 +149,7 @@ const Map = () => {
gisMaps={gisMaps}
isMiniMap={false}
searchView={undefined}
// searchView={(props: any) => (
// <MapSearchBar
// searchType="공급처 후보지 조회"
// showApplyButton={false}
// checkedLayers={checkedLayers}
// checkedLayersData={checkedLayersData}
// {...props}
// />
// )
// }
detailView={(props: any) => (
<NewWindowPopup
onClose={handlePopupClose} // 메모이제이션된 함수 사용
checkedLayers={checkedLayers}
checkedLayersData={checkedLayersData}
{...props}
/>
)}
detailView={renderDetailView}
onFeatureSelect={onFeatureSelect}
setIsOpen={setIsOpen}
setFeatureData={setFeatureData}
@@ -163,6 +159,7 @@ const Map = () => {
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
imgVisble={true}
searchBar={undefined}
/>
</div>
);
-795
View File
@@ -1,795 +0,0 @@
"use client"
import NewWindowPortal from '@/app/map/newWindowPortal';
import { useWrStore } from "@/app/store";
import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg";
import type { customPbnst, pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
import type { customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg";
import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type";
import { fetchType, getFetch, postFectch } from "@/components/lib/api";
import { formatPhoneNumber, tableData } from "@/components/lib/func/commom";
import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal";
import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal";
import { Title, UITab, UiTable } from '@common/business_components';
import { useGisContext } from "@common/business_components/ui/map/Gis";
import type { DemandCompType } from '@common/business_components/ui/sdmInsertForm/form';
import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan";
import moment from 'moment';
import React, { useCallback, useEffect, useState } from 'react';
interface NewWindowPopupProps {
featureData: any;
seletectedLayerNm?: string
viewMode?: 'list' | 'detail' | 'nothing'
onFeatureSelect: (data: any) => void;
onClose: () => void;
}
const NewWindowPopup: React.FC<NewWindowPopupProps> = ({
featureData,
seletectedLayerNm,
onFeatureSelect,
onClose
}) => {
const { gisMap } = useGisContext() as unknown as { checkedLayerIds: React.MutableRefObject<number[]>; treeData: { lyrSn: number }[] | null; gisCore: any; gisMap: any; };
const [tabData, setTabData] = useState<{ id: string; name: string; data: any }[]>([]);
const [activeTab, setActiveTab] = useState<string>('0');
const [viewMode, setViewMode] = useState<'list' | 'detail' | 'nothing'>('list');
const [fcltPk, setFcltPk] = useState<string>('');
// onClose 함수를 useCallback으로 메모이제이션
const memoizedOnClose = useCallback(() => {
onClose();
}, [onClose]);
// 하수재이용시설 변수
const {
code,
pbnstSttn,
pbnstSttnSearch,
pbnSttnInit,
getFlcts
} = useWrStore((state) => state);
const { fclts, pbnstSttnResCount } = pbnstSttn
const [bdstTable, setBdstTable] = useState<WaterReuseFacility[]>()
// 빗물재이용시설 변수
const { rainSttn, rainSttnSearch, rainSttnInit } = useWrStore(
(state) => state
);
const { rainSttnRes, rainSttnResCount } = rainSttn;
const [rainTable, setRainTable] = useState<customRainBdst[]>();
const [rainPage, setRainPage] = useState(1)
const [rainDetailModal, setRainDetailModal] = useState<{ isOpen: boolean, data: customRainBdst | undefined }>({ data: undefined, isOpen: false });
const [rainList, setRainList] = useState<customRainBdst[]>(rainSttnRes || []);
// 중수도시설 변수
const { rswtSttn, rswtSttnSearch, rswtSttnInit } = useWrStore(
(state) => state
);
const { rswtSttnRes, rswtSttnResCount } = rswtSttn;
const [rswtrTable, setRswtrTable] = useState<customRswtBdst[]>();
const [rswtrDetailModal, setRswtrDetailModal] = useState<{ isOpen: boolean, data: customRswtBdst | undefined }>({ data: undefined, isOpen: false });
const [rswtrPage, setRswtrPage] = useState(1);
const [rswtrList, setRswtrList] = useState<customRswtBdst[]>(rswtSttnRes || []);
// 온배수시설 변수
const { htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore((state) => state);
const { htdflSttnRes, htdflSttnResCount } = htdflSttn;
const [htdflTable, setHtdflTable] = useState<customHtdflBdst[]>();
const [htdflDetailModal, setHtdflDetailModal] = useState<{ isOpen: boolean, data: customHtdflBdst | undefined }>({ data: undefined, isOpen: false });
const [htdflPage, setHtdflPage] = useState(1)
const [htdflList, setHtdflList] = useState<customHtdflBdst[]>(htdflSttnRes || []);
//하수처리시설 변수
const {
pbnst,
pubHasuInit,
} = useWrStore((state) => state);
const { pubFacHeadList, pbnstHasuRes } = pbnst;
const [hasuList, setHasuList] = useState<pubHasuType[]>(pbnstHasuRes || []);
const [isRuseReg, setIsRuseReg] = useState<{
data: any | undefined;
}>({ data: undefined });
const [hasuTable, setHasuTable] = useState<pubHasuType[]>();
const [hasuPage, setHasuPage] = useState<number>(1);
// 수요처관리 변수
const {
coSttn,
coSttnInit,
coSttnSearch,
// getDemandCompList,
// regDemandCompany,
// updateDemandCompany,
// coSttnTxtSearch,
// demandCompList,
} = useWrStore((state) => state);
const [mngTable, setMngTable] = useState<DemandCompType[]>();
const [mngPage, setMngPage] = useState(1);
const { coSttnRes, coSttnResCount, coSttHeadList } = coSttn;
const [isDmdModal, setIsDmdModal] = useState<{
isMoal: boolean;
data: any | undefined;
}>({ isMoal: false, data: undefined});
const [mngList, setMngList] = useState<DemandCompType[]>(coSttnRes || []);
///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 ///////////////////////////////////////////////
const getSelectedLayers = () => {
let result = null;
const layers = gisMap ? gisMap.getLayers().getArray().filter((l: any) => l.getVisible()) : []; // gisMap이 null인지 확인 후 레이어 가져오기
let featureLayer: { get: (key: string) => any } = { get: () => null };
layers.forEach((layer: any) => {
const source = layer.getSource();
if (source && source.hasFeature && featureData
&& typeof featureData.getId === 'function' && source.hasFeature(featureData)) {
featureLayer = layer; // 피처가 속한 레이어 찾기)
}
});
result = featureLayer.get('lyrNm');
return result;
};
const fetchpbnstDetail = async (featureCd: string) => {
try {
const response = await getFetch("wr", `/reuseFc/pubFc/${featureCd}`);
// 중복 데이터 추가 방지
setTabDataFunc(response, featureCd);
} catch (error) {
console.error("Error fetching data:", error);
}
};
const fetchHasuDetail = async (featureCd: string, data: string) => {
try {
const rainRes = await postFectch(`/prcsFclt/ruseInfo/1/10/A/0/0/1/SW/${featureCd}`, [data], fetchType.COMMON)
setHasuList(
rainRes.data.map((item: any) => {
return {
...item,
fctCpc: Number(item.fctCpc) || 0,
ruse: item.ruse === false ? "N" : "Y",
};
})
)
} catch (error) {
console.error("Error fetching data:", error);
}
};
const detainSttn = async (featureCd: string, layerNm: string) => {
if (layerNm == 'tb_wr_rnwtr_utztn_fclt') { //빗물이용시설
const res = await getFetch(fetchType.WR, `/reuseFc/rainyInfoList/1/20/0/${featureCd}`)
setRainList(res)
}
else if (layerNm == 'tb_wr_rswtr_fclt') { //중수도 시설
const res = await getFetch(fetchType.WR, `/reuseFc/waterreuseFc/1/20/0/${featureCd}`)
setRswtrList(res)
}
else if(layerNm =='tb_wr_ruse_fclt_dmd_co'){ //수요처
const res = await getFetch(fetchType.WR, `/reuseFc/request/1/20/0/${featureCd}`)
setMngList(res)
}
else {
const res = await getFetch(fetchType.WR, `/drain/facilityList/1/20/0/${featureCd}`)
setHtdflList(res)
setHtdflDetailModal({ isOpen: true, data: htdflSttnRes[0] });
}
}
// 상세 목록 데이터 상태 처리
useEffect(() => {
if (hasuList.length > 0) setIsRuseReg({ data: [hasuList[0]] });
}, [hasuList])
useEffect(() => {
if (rainList.length > 0) setRainDetailModal({ isOpen: true, data: rainList[0] });
}, [rainList])
useEffect(() => {
if (rswtrList.length > 0) setRswtrDetailModal({ isOpen: true, data: rswtrList[0] });
}, [rswtrList])
useEffect(() => {
if (htdflList.length > 0) setHtdflDetailModal({ isOpen: true, data: htdflList[0] });
}, [htdflList])
useEffect(() => {
if(mngList.length > 0) setIsDmdModal({ isMoal: true, data: [mngList[0]] });
},[mngList])
const layerId = getSelectedLayers();
if (featureData && typeof featureData.getProperties === "function") {
const selectedVal = featureData.getProperties();
let featureCd = layerId == '하수재이용시설' ? selectedVal?.swtrmt_fclt_cd : layerId == '빗물이용시설' || layerId == '중수도시설' || layerId == '온배수시설' || layerId == '수요처' ? selectedVal?.bdst_nm : layerId == '하수처리시설' ? selectedVal?.swtrmt_fclt_nm : null;
if (featureCd && featureCd !== fcltPk) {
if (layerId == '하수재이용시설') {
featureCd = selectedVal?.swtrmt_fclt_cd;
setFcltPk(featureCd); // 현재 호출된 featureCd 저장
setActiveTab(featureCd)
fetchpbnstDetail(featureCd); // 상세정보
}
else if (layerId == '하수처리시설') {
featureCd = selectedVal?.swtrmt_fclt_nm;
setFcltPk(featureCd); // 현재 호출된 featureCd 저장
fetchHasuDetail(featureCd, selectedVal?.swtrmt_fclt_cd);
}
else {
featureCd = selectedVal?.bdst_nm;
setFcltPk(featureCd)
if (layerId) {
detainSttn(featureCd, layerId);
}
}
setViewMode("detail")
}
} else if (layerId === null && seletectedLayerNm) { setViewMode("list") }
///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 ///////////////////////////////////////////////
///////////////////////////////////////////// 하수재이용시설 //////////////////////////////////////////////////
// 재이용시설 cellClick 이벤트 (상세정보)
const pbnstCellClick = (index: number | undefined) => {
if (
index !== undefined &&
pbnstSttn.pbnstSttnRes &&
pbnstSttn.pbnstSttnRes[index]
) {
setFcltPk(pbnstSttn.pbnstSttnRes[index].pbnstRuseFcltId);
onFeatureSelect(pbnstSttn.pbnstSttnRes[index]);
onClose()
}
};
// 재이용 현황 초기값
useEffect(() => {
if (!pbnstSttn.isInit) {
getFlcts()
}
}, [seletectedLayerNm, pbnstSttn.isInit, getFlcts]);
useEffect(() => {
pbnSttnInit("1", "15", {
partValue: "A",
sidoValue: '0',
sigunValue: "0",
regionValue: "",
unitWaterShedValue: "",
middleRegionValue: "",
envPartValue: "",
sidoText: "",
sigunText: ""
}, String(new Date().getFullYear()), pbnstSttn.fclts);
}, [fclts, pbnSttnInit, pbnstSttn.fclts])
useEffect(() => {
setBdstTable(pbnstSttn.pbnstSttnRes);
}, [seletectedLayerNm, pbnstSttn.pbnstSttnRes]);
// 재이용시설 상세정보
const setTabDataFunc = (res: any, pk: string) => {
setTabData((prev) => {
if (prev.some((tab) => tab.id === pk)) {
return prev; // 이미 존재하는 탭이면 추가하지 않음
}
return [...prev, { id: pk, name: `재이용시설 ${prev.length + 1}`, data: res }];
});
}
// 재이용시설 조회
// 재이용시설 페이징처리 관련 함수
const onPageChangeHandler = useCallback((page: number) => {
pbnstSttnSearch(
false,
String(page),
String(13),
{
partValue: "A",
sidoValue: "0",
sigunValue: "0",
regionValue: "",
unitWaterShedValue: "",
middleRegionValue: "",
envPartValue: "",
sidoText: "",
sigunText: "",
},
"",
String(new Date().getFullYear()), fclts
);
}, [fclts, pbnstSttnSearch]);
// FIXME: 윤선화차장님 요구사항으로 엑셀 다운로드 삭제.
// const excelClick = useCallback(() => {
// // if (codeData) pbnstSttnSearch(1, "10000", codeData);
// excelDownload(
// [[]],
// "하수재이용시설 현황",
// "sample_pbnstSttn.xlsx",
// "A1:U2"
// );
// }, [pbnstSttnSearch]);
///////////////////////////////////////////// 하수재이용시설 //////////////////////////////////////////////////
///////////////////////////////////////////// 빗물 재이용 //////////////////////////////////////////////////
// 빗물재이용시설 cellClick 이벤트 (상세정보)
const rainCellClick = (index: number | undefined, headId: string) => {
if (
index !== undefined &&
rainTable !== undefined &&
headId !== 'chBuildingYn') {
// setRainDetailModal({ isOpen: true, data: rainTable[index] })
// setViewMode('detail')
onFeatureSelect(rainTable[index]);
onClose();
}
}
useEffect(() => {
if (!rainSttn.isInit) {
rainSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd);
}
}, [code.cityCd, code.sggCd, rainSttn.isInit, rainSttnInit]);
useEffect(() => {
const data = tableData(rainSttnRes, { code });
const chData = data
.map((item: any) => {
return {
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0].rainyObj,
dtfcltCpct: item.reuseBuilding[0].rainyObj.dtfcltCpct === -1
? "확인불가"
: item.reuseBuilding[0].rainyObj.dtfcltCpct,
instlCst: item.reuseBuilding[0].instlCst === -1
? "확인불가"
: item.reuseBuilding[0].instlCst,
instlCstSprtAmt: item.reuseBuilding[0].instlCstSprtAmt === -1
? "확인불가"
: item.reuseBuilding[0].instlCstSprtAmt,
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
pntfColArea: item.reuseBuilding[0].rainyObj.pntfColArea === -1
? "확인불가"
: item.reuseBuilding[0].rainyObj.pntfColArea,
filtrTrtmfctCpct: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct === -1
? "확인불가"
: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct,
archArea: Math.floor(item.archArea) === -1 ? "확인불가" : item.archArea,
};
})
.filter((item: any) => item.rainyObj !== undefined);
setRainTable(chData);
}, [code, rainSttnRes, rainSttn.rainSttHeadList]);
useEffect(() => {
rainSttnSearch(false, rainPage, "20", '', '', code.cityCd, code.sggCd);
}, [code.cityCd, code.sggCd, rainPage, rainSttnSearch]);
///////////////////////////////////////////// 빗물 재이용 //////////////////////////////////////////////////
///////////////////////////////////////////// 중수도 시설 //////////////////////////////////////////////////
// 중수도시설 cellClick 이벤트 (상세정보)
const rswtCellClick = (index: number | undefined, headId: string) => {
if (headId !== 'chBuildingYn' && index !== undefined && rswtrTable !== undefined) {
// setRswtrDetailModal({ isOpen: true, data: rswtrTable[index] });
// setViewMode('detail')
onFeatureSelect(rswtrTable[index]);
onClose();
}
}
useEffect(() => {
if (!rswtSttn.isInit) {
rswtSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd);
}
}, [code.cityCd, code.sggCd, rswtSttn.isInit, rswtSttnInit]);
useEffect(() => {
const data = tableData(rswtSttnRes, { code });
const chData = data
.map((item: customRswtBdst) => {
return {
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0]?.rswtrObj,
chBuildingYn: item?.chgBuilding[0]?.bdstChgNm !== null && item?.chgBuilding.length > 0 ? 'Y' : 'N',
instlCst: item.reuseBuilding[0]?.instlCst === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCst,
instlCstSprtAmt: item.reuseBuilding[0]?.instlCstSprtAmt === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCstSprtAmt,
archArea: item?.archArea.split('.')[0] !== '-1' ? item?.archArea.split('.')[0] : '확인불가'
}
})
.filter(
(item: customRswtBdst) =>
item.reuseBuilding[0]?.rswtrObj !== undefined
);
setRswtrTable(chData);
}, [code, rswtSttnRes]);
// FIXME: 윤선화 차장님 요구사항으로 엑셀 다운로드 삭제.
// const rswtSttnExcelDownload = useCallback(() => {
// if (rswtSttn.excelList.length > 0) {
// if (rswtSttn.excelList.length === 0) return;
// excelDownload(
// rswtSttn.excelList,
// "중수도시설 현황",
// "sample_rswtSttn.xlsx",
// "A1:W3",
// );
// }
// }, [rswtSttn.excelList])
useEffect(() => {
rswtSttnSearch(false, rswtrPage, "20", '', '', code.cityCd, code.sggCd);
}, [code.cityCd, code.sggCd, rswtSttnSearch, rswtrPage]);
///////////////////////////////////////////// 중수도 시설 //////////////////////////////////////////////////
///////////////////////////////////////////// 온배수 시설 //////////////////////////////////////////////////
// 온배수시설 cellClick 이벤트 (상세정보)
const htdflCellClick = (index: number | undefined) => {
if (index !== undefined && htdflTable !== undefined) {
onFeatureSelect(htdflTable[index]);
onClose();
}
};
useEffect(() => {
if (!htdflSttn.isInit) {
initHtdfl(false, 1, "20", "0", '', code.cityCd, code.sggCd);
}
}, [code.cityCd, code.sggCd, htdflSttn.isInit, initHtdfl]);
useEffect(() => {
const data = tableData(htdflSttnRes, { code });
const chData = data
.map((item: any) => ({
...item,
...item.reuseBuilding[0],
...item.reuseBuilding[0].htdflObj,
chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N",
}))
.filter((item: any) => item.htdflObj !== undefined);
setHtdflTable(chData);
}, [code, htdflSttnRes, htdflSttn.htdflSttHeadList]);
useEffect(() => {
htdflSttnSearch(true, htdflPage, "20", '', '', code.cityCd, code.sggCd);
}, [code.cityCd, code.sggCd, htdflPage, htdflSttnSearch]);
///////////////////////////////////////////// 온배수 시설 //////////////////////////////////////////////////
///////////////////////////////////////////// 하수처리 시설 //////////////////////////////////////////////////
useEffect(() => {
if (code.sggCd.length && pbnstHasuRes.length > 0) {
setHasuTable(tableData(pbnstHasuRes, { code }));
}
}, [code, pbnstHasuRes]);
useEffect(() => {
if (!pbnst.isInit) {
pubHasuInit("1", "0");
}
}, [pbnst.isInit, pubHasuInit]);
useEffect(() => {
pubHasuInit(String(hasuPage), "0");
}, [hasuPage, pubHasuInit]);
const hasuCellClick = (index: number | undefined) => {
if (index !== undefined && pbnstHasuRes !== undefined) {
onFeatureSelect(pbnstHasuRes[index]);
onClose();
}
};
///////////////////////////////////////////// 하수처리 시설 //////////////////////////////////////////////////
///////////////////////////////////////////// 수요처 관리 //////////////////////////////////////////////////
useEffect(() => {
if (!coSttn.isInit) {
coSttnInit("1", "13", "0");
}
}, [coSttn.isInit, coSttnInit]);
const coMngCellClick = (index: number | undefined) => {
if (index !== undefined && mngTable !== undefined) {
onFeatureSelect(mngTable[index]);
onClose();
}
};
useEffect(() => {
if (coSttnRes) {
if (coSttnRes?.length > 0 && code.cityCd.length > 0) {
const data = tableData(coSttnRes, { code });
const chData = data.map((item: any) => ({
...item,
telno: formatPhoneNumber(item.telno || undefined),
regDt: moment(item.regDt).format("YYYY-MM-DD"),
dmdInfoId: `${item.dmdInfoId.slice(0, 3)}-${item.dmdInfoId.slice(3, 5)}-${item.dmdInfoId.slice(5, 10)}-${item.dmdInfoId.slice(10)}`
}));
// .filter((item: any) => item !== undefined);
setMngTable(chData);
}
}
}, [coSttnRes, code]);
useEffect(() => {
coSttnSearch(String(mngPage), "13", String(0));
}, [coSttnSearch, mngPage]);
///////////////////////////////////////////// 수요처 관리 //////////////////////////////////////////////////
// 체크된 레이어에 따른 조건부 컴포넌트 렌더링 함수
const renderConditionalContent = () => {
const actTabData = tabData.find((tab) => tab.id === activeTab);
let layerId: string | undefined | null = getSelectedLayers();
if (layerId === null || layerId === undefined) {
layerId = seletectedLayerNm || '';
}
//하수처리시설
const isPrcsFclt = layerId == 'tb_il_swage_prcs_fclt'
// 재이용시설
const isPbnst = layerId == 'tb_wr_bdst_ruse_fclt';
// 빗물이용시설
const isRain = layerId == 'tb_wr_rnwtr_utztn_fclt';
// 중수도시설
const isRswt = layerId == 'tb_wr_rswtr_fclt';
// 온배수시설
const isHtdfl = layerId == 'tb_wr_htdfl_fclt';
// 수요처관리
const isReuseMng = layerId == 'tb_wr_ruse_fclt_dmd_co';
if (isPrcsFclt) {
if (viewMode == 'list') {
return (
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center mb-4">
<Title title="하수처리시설 현황" />
</div>
{/* 높이 조정 */}
<UiTable
tableData={hasuTable || []}
headlist={pubFacHeadList}
pageSize={10}
total={5000}
headName={""}
cellClick={hasuCellClick}
onPageChange={setHasuPage}
/>
</div>
)
} else {
return (
<div style={{ overflowX: 'hidden' }}>
<div className="flex justify-between items-center mb-4">
<Title title="하수처리시설 상세정보" />
</div>
{/* 높이 조정 */}
<UiTable
tableData={isRuseReg?.data || []}
headlist={pubFacHeadList.slice(0, 4)}
pageSize={1}
total={0}
headName={"위치정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
<UiTable
tableData={isRuseReg?.data || []}
headlist={pubFacHeadList.slice(4)}
pageSize={1}
total={0}
headName={"기본정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
</div>
)
}
}
if (isPbnst) {
if (viewMode == 'detail') {
// 재이용시설 상세
return (
<>
<div className="flex justify-between items-center mb-4">
<Title title="하수재이용시설 상세정보" />
</div>
<div className="flex justify-between items-center mb-8">
<UITab
defaultValue={activeTab}
tabList={tabData.map((tab) => ({
value: tab.id,
label: tab.name,
onClick: () => setActiveTab(tab.id),
}))}
/>
</div>
<PbnstSttnModal
data={actTabData?.data[0] || ({} as customPbnst)}
titleVisible={false}
/>
</>
);
} else {
// 재이용시설 목록
return (
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center">
<Title title="하수재이용시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={excelClick}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={bdstTable || []}
headlist={pbnstSttn.pbnstSttHeadList}
pageSize={20}
total={pbnstSttnResCount || 0}
cellClick={(index: number | undefined) => {
pbnstCellClick(index);
}}
onPageChange={onPageChangeHandler}
>
<HeadMakeColSpan upHeadList={pbnstSttn.pbnstSttNodeList} />
</UiTable>
</div>
);
}
}
if (isRain) {
if (viewMode == 'detail') {
// 빗물이용시설 상세
return (
<SttnDetailModal type={"RNB"} formObj={rainDetailModal.data as customRainBdst} />
);
} else {
// 빗물이용시설 목록
return (
<>
<div className="flex justify-between items-center">
<Title title="빗물이용시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={excelClick}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={rainTable || []}
headlist={rainSttn.rainSttHeadList}
pageSize={20}
total={rainSttnResCount}
cellClick={(index: number | undefined, headId: string) => {
rainCellClick(index ?? undefined, headId);
}}
onPageChange={setRainPage}
>
<HeadMakeColSpan upHeadList={rainSttn.rainSttNodeList} />
</UiTable>
</>
);
}
}
if (isRswt) {
if (viewMode == 'detail') {
// 중수도시설 상세
return (
<SttnDetailModal type={"RST"} formObj={rswtrDetailModal.data as customRswtBdst} />
);
} else {
// 중수도시설 목록
return (
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center">
<Title title="중수도시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={rswtSttnExcelDownload}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={rswtrTable || []}
headlist={rswtSttn.rswtSttHeadList}
pageSize={20}
total={rswtSttnResCount}
cellClick={(index: number | undefined, headId: string) => {
rswtCellClick(index, headId);
}}
onPageChange={setRswtrPage}
>
<HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} />
</UiTable>
</div>
);
}
}
if (isHtdfl) {
if (viewMode == 'detail') {
// 온배수시설 상세
return (
<SttnDetailModal type={"HTB"} formObj={htdflDetailModal.data as customHtdflBdst} />
);
} else {
// 온배수시설 목록
return (
<div style={{ overflowY: 'auto' }}>
<div className="flex justify-between items-center">
<Title title="온배수시설 현황" />
{/* <div className="flex gap-2 mt-8">
<Button className={btnClass} color="primary" onClick={excelClick}>
엑셀다운로드
</Button>
</div> */}
</div>
<UiTable
headName={[]}
tableData={htdflTable || []}
headlist={htdflSttn.htdflSttHeadList}
pageSize={20}
total={htdflSttnResCount || 0}
cellClick={(index: number | undefined) => {
htdflCellClick(index ?? undefined);
}}
onPageChange={setHtdflPage}
>
<HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} />
</UiTable>
</div>
);
}
}
if (isReuseMng) {
if (viewMode == 'detail') {
return (
<div style={{ overflowX: 'hidden' }}>
<div className="flex justify-between items-center mb-4">
<Title title="수요처 상세정보" />
</div>
{/* 높이 조정 */}
<UiTable
tableData={isDmdModal?.data || []}
headlist={coSttHeadList.slice(0, 3)}
pageSize={1}
total={0}
headName={"위치정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
<UiTable
tableData={isDmdModal?.data || []}
headlist={coSttHeadList.slice(3)}
pageSize={1}
total={0}
headName={"기본정보"}
cellClick={() => { }}
onPageChange={() => { }}
/>
</div>
)
} else if(viewMode == 'list') {
return ( <div>
<div className="flex justify-between items-center">
<Title title="수요처 현황" />
</div>
<UiTable
headName={[]}
tableData={mngTable || []}
headlist={coSttHeadList}
pageSize={20}
total={coSttnResCount + 10 || 0}
cellClick={(index: number | undefined) => {
coMngCellClick(index);
// setUpdateData(coSttnRes[index as number]);
}}
onPageChange={(page) => {
setMngPage(page);
}}
></UiTable></div>)
}
}
return null; // 조건에 맞는 콘텐츠가 없을 경우
};
return (
viewMode == 'nothing' ? <></> :
<NewWindowPortal
onClose={memoizedOnClose}
title="시설 상세 정보"
width={viewMode == 'list' ? window.screen.availWidth : 1100}
height={viewMode == 'list' ? window.screen.availHeight : layerId == '하수처리시설' && viewMode == 'detail' ? 450 : 900}
scrollbars='yes'
resizable='no'>
{/* 체크된 레이어에 따른 조건부 렌더링 */}
{renderConditionalContent()}
</NewWindowPortal>
);
};
export default NewWindowPopup;
+2 -11
View File
@@ -3,7 +3,7 @@
import Gis from "@common/business_components/ui/map/Gis";
import { useEffect, useRef, useState, useCallback } from "react";
import { mapService } from "../service";
import NewWindowPopup from "../newWindowPopup";
import NewWindowPopup from "../components/newWindowPopup";
import GisApp from "@common/business_components/ui/map/lib/gis.core";
const Map = () => {
@@ -123,16 +123,6 @@ const Map = () => {
gisMaps={gisMaps}
isMiniMap={false}
searchView={undefined}
// searchView={(props: any) => (
// <MapSearchBar
// searchType="공급처 후보지 조회"
// showApplyButton={false}
// checkedLayers={checkedLayers}
// checkedLayersData={checkedLayersData}
// {...props}
// />
// )
// }
detailView={(props: any) =>(
<NewWindowPopup
onClose={handlePopupClose} // 메모이제이션된 함수 사용
@@ -150,6 +140,7 @@ const Map = () => {
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
imgVisble={true}
searchBar={undefined}
/>
</div>
);
+58
View File
@@ -0,0 +1,58 @@
import { getFetch, postFectch, fetchType } from "@/components/lib/api";
const fetchpbnstDetail = async (featureCd: string, setTabData: any) => {
try {
const response = await getFetch("wr", `/reuseFc/pubFc/${featureCd}`);
// 중복 데이터 추가 방지
setTabDataFunc(response, featureCd, setTabData);
} catch (error) {
console.error("Error fetching data:", error);
}
};
const fetchHasuDetail = async (featureCd: string, data: string) => {
try {
const rainRes = await postFectch(`/prcsFclt/ruseInfo/1/20/A/0/0/1/SW/${featureCd}`, [data], fetchType.COMMON)
// setHasuList
const filteredData = rainRes.data.map((item: any) => {
return {
...item,
fctCpc: Number(item.fctCpc) || 0,
ruse: item.ruse === false ? "N" : "Y",
};
})
return filteredData
} catch (error) {
console.error("Error fetching data:", error);
}
};
// 재이용시설 상세정보
const setTabDataFunc = (res: any, pk: string, setTabData: any) => {
setTabData((prev) => {
if (prev.some((tab) => tab.id === pk)) {
return prev; // 이미 존재하는 탭이면 추가하지 않음
}
return [...prev, { id: pk, name: `재이용시설 ${prev.length + 1}`, data: res }];
});
}
const detainSttn = async (featureCd: string, layerNm: string) => {
if (layerNm == '빗물이용시설') { //빗물이용시설
const res = await getFetch(fetchType.WR, `/reuseFc/rainyInfoList/1/20/0/${featureCd}`)
return res
}
else if (layerNm == '중수도시설') { //중수도 시설
const res = await getFetch(fetchType.WR, `/reuseFc/waterreuseFc/1/20/0/${featureCd}`)
return res
}
else if (layerNm == '수요처') { //수요처
const res = await getFetch(fetchType.WR, `/reuseFc/request/1/20/0/${featureCd}`)
return res
}
else {
const res = await getFetch(fetchType.WR, `/drain/facilityList/1/20/0/${featureCd}`)
return res
// setHtdflDetailModal({ isOpen: true, data: htdflSttnRes[0] });
}
}
export { fetchHasuDetail, fetchpbnstDetail, detainSttn };
+185 -122
View File
@@ -376,87 +376,116 @@ export default function CoMatRvw() {
<div className="col-span-12 w-full">
<h1 className={formH1Class}>요구수질</h1>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="grssClfg"
render={({ field }) => (
<FormUi label="총대장균군수 (개/100ml)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<FormUi label={"총대장균군수(개/mg)"}>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
type="text"
className="w-full pr-16 border py-2 text-right rounded-md"
placeholder=""
value={
field.value != -1
? `${field.value}`
: "불검출"
}
readOnly
/>
{/* TODO: 총대장균군수 확인 필요*/}
{field.value != -1 ? (
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
) : (
<></>
)}
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="combResdch"
render={({ field }) => (
<FormUi label="결합잔류염소(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<FormUi label={"결합잔류염소(mg/L)"}>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
type="text"
className="w-full pr-16 border py-2 text-right rounded-md"
placeholder=""
value={field.value ?? ""}
readOnly
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이상
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="trbt"
render={({ field }) => (
<FormUi label="탁도(NTU)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
className="w-full pr-16 border py-2 text-right rounded-md"
type="text"
value={field.value ?? 0}
readOnly
/>
<span className=" text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="blgcOxygDmndQnt"
render={({ field }) => (
<FormUi label="생물학적 산소요구량(BOD)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
type="text"
className="w-full pr-16 border py-2 text-right rounded-md"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? ""}
readOnly
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="smll"
@@ -464,138 +493,172 @@ export default function CoMatRvw() {
<FormUi label="냄새">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
type="text"
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="crmty"
render={({ field }) => (
<FormUi label="색도(도)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
className="w-full pr-16 border py-2 text-right rounded-md"
type="text"
step="0.1"
value={field.value ?? ""}
readOnly
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="tn"
render={({ field }) => (
<FormUi label="총질소 (T-N)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<FormUi label="총질소(T-N)(mg/L)">
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
className="w-full pr-16 border py-2 text-right rounded-md"
type="text"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="tph"
render={({ field }) => (
<FormUi label="총인(T-P)(mg/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
className="w-full pr-16 border py-2 text-right rounded-md"
type="text"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="ph"
render={({ field }) => (
<FormUi label="수소이온농도(pH)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<FormUi label="수소이온농도(PH)">
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
className="w-full pr-16 border py-2 text-right rounded-md"
type="text"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="clIonQnt"
render={({ field }) => (
<FormUi label="염화물(mgCL/L)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
className="w-full pr-16 border py-2 text-right rounded-md"
type="text"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="cdtnv"
render={({ field }) => (
<FormUi label="전기전도도(㎲/cm)">
<Input
placeholder=""
type="number"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
placeholder=""
className="w-full pr-16 border py-2 text-right rounded-md"
type="text"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<div className="col-span-2 mt-4">
<FormField
control={form.control}
name="rmrk"
@@ -648,7 +711,7 @@ export default function CoMatRvw() {
form={form}
type={"mat"}
selectionVersion={selectionVersion}
readonly={regAuthrtYn ==="N"}
readonly={regAuthrtYn === "N"}
/>
</ListDiv>
{/* </ScrollArea> */}
+138 -100
View File
@@ -17,35 +17,45 @@ import {
UiModal,
UiTable,
type SelectDataType,
type SheetParameter,
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { Button, Label } from "@common/components/ui";
import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function RuseCaseMng() {
const { code, ruseCaseMng, selectRuseCaseMng } = useWrStore((state) => state);
const { ruseCaseMngList, status, count } = ruseCaseMng;
const { code, ruseCaseMng, selectRuseCaseMng, ruseCaseMngInit } = useWrStore((state) => state);
const { ruseCaseMngList, status, count, excelList } = ruseCaseMng;
const [selectSgg, setSelectSgg] = useState<SelectDataType[] | []>([]);
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
const [sidoCd, setSidoCd] = useState<string>("");
const [sigunguCd, setSigunguCd] = useState<string>("");
const [selectUtz, setSelectUtz] = useState<string[] | []>(["조경용수"]);
// const [selectUtz, setSelectUtz] = useState<string[] | []>(["조경용수"]);
const [selectUtz, setSelectUtz] = useState<string>("");
const [name, setName] = useState<string>("");
const [resetPage, isResetPage] = useState(false);
const { t } = useTranslation('base');
// 물재이용사례 조회
const searchRuseCaseMng = async (pageNo: number, pageSize: number) => {
const searchRuseCaseMng = async (isExcel: boolean, pageNo: number, pageSize: number) => {
await selectRuseCaseMng(
isExcel,
pageNo,
pageSize,
sidoCd ?? "",
sigunguCd ?? "",
selectUtz[0] ?? "",
sidoCd ?? "",
sigunguCd ?? "",
selectUtz ?? "",
name ?? ""
);
}
useEffect(() => {
ruseCaseMngInit();
}, [])
// 시도 선택
const getSelCity = (val: string | number) => {
const cityValue = String(val);
@@ -69,91 +79,97 @@ export default function RuseCaseMng() {
isModal: boolean;
}>({ isModal: false });
// 다운로드
const download = () => {
searchRuseCaseMng(1, 10000);;
useEffect(() => {
if (excelList !== undefined && excelList.length === 0) {
toast.error(t('excelDownErrMsg'));
return;
}
fetch(`/sample_ruseCaseMng.xlsx`, {}).then(async (response) => {
if (!response.ok) {
throw Error(response.statusText);
}
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer();
const excelData1 = ruseCaseMngList.map((item) => {
return [
item.ruseBizNm,
item.bizBgngDate,
item.bizEndDate,
item.splyFcltKnd,
item.splyFcltNm,
item.splyFcltCpct,
item.dmdFcltNm,
item.dmdFcltAddr,
item.ruseFcltCpct,
item.ruseFcltPplLen,
item.ruseFcltUsg,
item.ruseFcltSplyCpct,
item.ruseFcltPrcsMsrc,
item.grnteWqUsg,
item.grnteWqGrssClfg,
item.grnteWqCombResdch,
item.grnteWqTrbt,
item.grnteWqBod,
item.grnteWqSmll,
item.grnteWqCrmty,
item.grnteWqTn,
item.grnteWqTp,
item.grnteWqPh,
item.grnteWqClIonQnt,
item.grnteWqCndctStat,
item.grnteWqRmrk,
item.reqBizGrssCst,
item.reqBizReuseFcltCst,
item.reqBizPplCst,
item.reqBizArchCst,
item.reqBizMchnCst,
item.reqBizMtrngCst,
item.reqBizGisCst,
item.reqBizCctvCst,
item.reqBizCmcnCst,
item.reqBizWstCst,
item.reqBizDesignCst,
item.reqBizSpvsCst,
item.reqBizSbsdCst,
item.reqBizEtc,
item.prcmPlanGrssCst,
item.prcmPlanNlep,
item.prcmPlanLcep,
item.prcmPlanBrdnCst,
item.prcmPlanEcqrRt,
item.clclnGrssCst,
item.clclnNlep,
item.clclnLcep,
item.clclnBrdnCst,
item.clclnEcqrRt,
];
});
const sheetParameter = [
{
data: excelData1,
headerNum: 2,
headerRange: 'A1:AX1',
sheetName: '물재이용사례',
startCol: 'A'
if (!response.ok) {
throw Error(response.statusText);
}
// 받은 파일 바인너리 처리
const blobRet = await response.arrayBuffer();
if(excelList){
const excelData1 = excelList.map((item) => {
return [
item.ruseBizNm,
item.bizBgngDate,
item.bizEndDate,
item.splyFcltKnd,
item.splyFcltNm,
item.splyFcltCpct,
item.dmdFcltNm,
item.dmdFcltAddr,
item.ruseFcltCpct,
item.ruseFcltPplLen,
item.ruseFcltUsg,
item.ruseFcltSplyCpct,
item.ruseFcltPrcsMsrc,
item.grnteWqUsg,
item.grnteWqGrssClfg,
item.grnteWqCombResdch,
item.grnteWqTrbt,
item.grnteWqBod,
item.grnteWqSmll,
item.grnteWqCrmty,
item.grnteWqTn,
item.grnteWqTp,
item.grnteWqPh,
item.grnteWqClIonQnt,
item.grnteWqCndctStat,
item.grnteWqRmrk,
item.reqBizGrssCst,
item.reqBizReuseFcltCst,
item.reqBizPplCst,
item.reqBizArchCst,
item.reqBizMchnCst,
item.reqBizMtrngCst,
item.reqBizGisCst,
item.reqBizCctvCst,
item.reqBizCmcnCst,
item.reqBizWstCst,
item.reqBizDesignCst,
item.reqBizSpvsCst,
item.reqBizSbsdCst,
item.reqBizEtc,
item.prcmPlanGrssCst,
item.prcmPlanNlep,
item.prcmPlanLcep,
item.prcmPlanBrdnCst,
item.prcmPlanEcqrRt,
item.clclnGrssCst,
item.clclnNlep,
item.clclnLcep,
item.clclnBrdnCst,
item.clclnEcqrRt,
];
});
const sheetParameter: SheetParameter[] = [
{
data: excelData1,
headerNum: 2,
headerRange: 'A1:AX1',
sheetName: '물재이용사례',
startCol: 'A'
}
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(blobRet, '물재이용사례현황', sheetParameter);
}
];
// 버퍼에 있는 엑셀데이터 전달 후 json으로 변환
await filePickedBlobArray(blobRet, '물재이용사례현황', sheetParameter);
});
}
}, [excelList])
// 양식받기
const sampleDownLoad = () => {
excelDownload(
[[]],
"물재이용사례 관리",
"물재이용사례 관리 등록양식",
"sample_ruseCaseMng.xlsx",
"A1:AX1",
2
@@ -161,7 +177,7 @@ export default function RuseCaseMng() {
}
useEffect(() => {
if(status === 200){
if (status === 200) {
setIsExcelOpen({ isModal: false });
}
}, [status]);
@@ -174,7 +190,7 @@ export default function RuseCaseMng() {
<Title title={"물재이용사례 관리"} />
<SearchDiv>
<SearchFormLeft>
<div className="col-span-8 flex flex-row">
<div className="col-span-8 flex flex-row items-center">
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
label="시도"
@@ -183,24 +199,28 @@ export default function RuseCaseMng() {
onSelectValue={getSelCity}
/>
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
className="col-span-2 w-1/3 h-full text-2xl ml-4"
label="시군구"
selectClass={""}
selectArray={selectSgg || []}
onSelectValue={getSgg}
/>
<SelectBox
className="col-span-2 w-1/3 h-full text-2xl"
className="col-span-2 w-1/3 h-full text-2xl ml-4"
label="용도"
selectClass={""}
selectArray={ruseUtzType}
onSelectValue={(val) => {
if (val) setSelectUtz([String(val)]);
if (val) setSelectUtz(String(val));
}}
value={selectUtz || ruseUtzType[0]?.val}
/>
<Label className="w-28 text-xl ml-4 mr-6">
{"수요처명"}
</Label>
<SearchInput
className={"text-2xl"}
label="수요처명"
className={"col-span-2 w-1/3 text-2xl"}
label=""
textValue={name}
setText={(e) => {
setName(e);
@@ -211,13 +231,29 @@ export default function RuseCaseMng() {
<SearchFormRight className="w-2/12 mx-5 flex flex-col items-center justify-center space-x-2">
<div className="space-y">
<div className="flex flex-row space-x-2">
<Button size={"sm"} onClick={() => { searchRuseCaseMng(1, 20) }}>
<Button size={"sm"} onClick={() => {
searchRuseCaseMng(false, 1, 10);
isResetPage(true);
}}>
조회
</Button>
<Button size={"sm"} onClick={() => { setIsExcelOpen({ isModal: true }); }}>
엑셀등록
</Button>
<Button size={"sm"} onClick={() => { download() }}>
<Button size={"sm"} onClick={() => {
selectRuseCaseMng(
true,
1,
count,
sidoCd ?? "",
sigunguCd ?? "",
selectUtz ?? "",
name ?? ""
);
// download()
}} className={"green"}>
다운로드
</Button>
<Button size={"sm"} onClick={() => { sampleDownLoad() }}>
@@ -239,10 +275,12 @@ export default function RuseCaseMng() {
headlist={ruseCaseMng.ruseHeadList}
pageSize={20}
total={count}
cellClick={() => {}}
cellClick={undefined}
onPageChange={(pageNo: number) => {
searchRuseCaseMng(pageNo, 10);
searchRuseCaseMng(false, pageNo, 10);
isResetPage(false)
}}
resetPageNo={resetPage}
/>
</div>
</ListDiv>
@@ -254,9 +292,9 @@ export default function RuseCaseMng() {
<UiModal
open={isExcelOpen.isModal}
onOpenChange={() => {
setIsExcelOpen({ isModal: !isExcelOpen.isModal })
setIsExcelOpen({ isModal: !isExcelOpen.isModal })
}}
bodyClass={"w-[40vw] max-w-none"}
bodyClass={"w-[35vw] max-w-none"}
body={<RuseCaseMngExcel />}
/>
</>

Some files were not shown because too many files have changed in this diff Show More