Compare commits

...
Author SHA1 Message Date
leedj312 c5f4f6ddd0 물재이용 화면 건축물 재이용여부 수정 2025-07-24 14:09:43 +09:00
leedj312 f332d64aa6 물재이용 화면별 등록/수정 권한 추가 2025-07-24 14:06:20 +09:00
leedj312 0d48a0b579 페이지별 이벤트 권한체크, 시설 등록,현황, 수요처 관리 까지 완료 2025-07-23 17:51:47 +09:00
leedj312 fc3ef2c59e Merge branch 'iipbs/wr/dev' into iipbs/wr/login-test 2025-07-23 13:16:03 +09:00
truthwing 21e0ea086e Merge commit 'f50a9aaf3a41fb542c18f6f655ee5adeb69b4258' 2025-07-23 10:46:32 +09:00
YangJinSoo94 f50a9aaf3a 임시로 개발서버로 바라보고 수정 2025-07-23 10:08:47 +09:00
YangJinSoo94 60e73212e8 hostm port 변경경 2025-07-23 09:19:15 +09:00
swcho 6660c85150 Merge remote-tracking branch 'origin/iipbs/sn/dev' 2025-07-22 22:24:16 +09:00
swcho 2cfd57fdc3 fix: 하수관로 상세페이지 useEffect 의존성 배열 수정 2025-07-22 22:23:00 +09:00
swcho 5e5411a34f Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2025-07-22 22:19:09 +09:00
swcho 01852c1528 refactor:
- MsSwagePpl.tsx 리팩토링
- index.ts Merge
2025-07-22 22:16:34 +09:00
mind-one005 4488bd23c7 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2025-07-22 21:49:36 +09:00
mind-one005 c2696c6eeb Merge branch 'iipbs/sn/dev' 2025-07-22 21:49:21 +09:00
mind-one005 4ef86a3e6a 기본계획 download 수정 2025-07-22 21:48:37 +09:00
truthwing badea83e9e Merge commit '268c45ed05efa45f966d33556a6ea974472b4b81' 2025-07-22 21:26:32 +09:00
truthwing fc2f119584 Merge commit '4e2fe7aaa1433c22886685d802662872df6e3c11' 2025-07-22 21:26:21 +09:00
truthwing 23a92ec38c Merge commit 'fe2f3faee4bc2250684b494c14c692aa45f08b28' 2025-07-22 21:25:58 +09:00
truthwing fe2f3faee4 js cookie 재설치 2025-07-22 21:15:33 +09:00
swcho 3e5a14fbc8 Merge branch 'iipbs/sn/ii' into iipbs/sn/dev 2025-07-22 21:08:17 +09:00
swcho 527b4293c4 feat, refactor:
- 하수관로 상세 페이지  운영정보 연계 기능 구현
- 운영정보 탭 검색 기능 구현
- UITab2, UITable2 삭제 후 공통 컴포넌트 적용 (UITab, UITable)
- SearchModal.tsx UI 수정
- featureClickEvent에 isClicked state 추가
2025-07-22 21:06:09 +09:00
leedj312 4e2fe7aaa1 Merge commit '0a109111cbf2cae77a348bddb2116a56950852e8' into iipbs/wr/dev 2025-07-22 20:58:02 +09:00
jyha00 0a109111cb 중수도통계 상세 엑셀 다운로드 수정 2025-07-22 20:55:14 +09:00
leedj312 3b6e8ceedb 빗물 통계 수정 2025-07-22 20:55:00 +09:00
jyha00 99229a8453 불필요한 출력창 삭제 2025-07-22 20:41:37 +09:00
jyha00 383e5f8382 중수도통계 테이블, 엑셀 수정 2025-07-22 20:38:42 +09:00
mind-one005 a11570b563 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2025-07-22 20:17:58 +09:00
mind-one005 af1feb3920 Merge branch 'iipbs/sn/dev' 2025-07-22 20:17:52 +09:00
mind-one005 a6df8d261a RSON 제거 2025-07-22 20:15:14 +09:00
truthwing f96942beee LOCAL_URL 경로 오류로 수정. 2025-07-22 20:08:32 +09:00
truthwing 7994698349 js-cookie 추가. 2025-07-22 19:48:04 +09:00
swcho ab495c6572 Merge remote-tracking branch 'origin/iipbs/common/main' into iipbs/sn/ii 2025-07-22 16:30:23 +09:00
swcho 804688b3c1 remove: UITable2 컴포넌트 삭제 2025-07-22 16:28:48 +09:00
swcho 47c986d517 Merge remote-tracking branch 'origin/iipbs/common/main' into iipbs/sn/ii 2025-07-22 16:17:45 +09:00
swcho 8435096e5a remove: UITab2 컴포넌트 삭제 2025-07-22 16:16:42 +09:00
leedj312 e30a7d184b 권한 체크 작업중 작업해야함 2025-07-22 15:57:20 +09:00
leedj312 b4e3d922b1 Merge commit 'a028b6ae8bba8e074e82900d05925d4e5a9c6951' into iipbs/wr/dev 2025-07-22 15:38:12 +09:00
leedj312 a028b6ae8b ui 테이블 체크박스 사용시 클래스 타입을 사용 체크 2025-07-22 15:37:54 +09:00
swcho 9565931042 Merge remote-tracking branch 'origin/iipbs/common/main' into iipbs/sn/ii 2025-07-22 15:28:36 +09:00
yschoi 1042391702 Merge remote-tracking branch 'origin/iipbs/dm/dev' 2025-07-22 15:12:49 +09:00
yschoi 7c2ff7c037 build": "turbo run build 2025-07-22 14:48:33 +09:00
leedj312 ad0803f405 Merge commit '03675aaa6062402fbb3772e97cd966c0f7abd890' into iipbs/wr/dev 2025-07-22 14:38:24 +09:00
jyha00 03675aaa60 재이용통계 엑셀 다운로드시 시도명 없음 수정 2025-07-22 14:36:09 +09:00
leedj312 c0c19c0425 매칭완료 오류사항 수정 2025-07-22 14:32:25 +09:00
yschoi 0bbb27e3d3 불필요 삭제 2025-07-22 13:58:24 +09:00
leedj312 214d283366 Merge commit '7d95ddf6a521f108b3b49d71760ba6e92a56d2dc' into iipbs/wr/login-test 2025-07-22 13:56:46 +09:00
truthwing 7d95ddf6a5 ChkClass 타입의 정보로 동작되는 체크박스 추가. 2025-07-22 13:55:31 +09:00
jyha00 a19c5c269a 지도점검 테이블 재수정 2025-07-22 13:37:35 +09:00
YangJinSoo94 d641866cc4 -대시보드 메뉴 및 로그인 기능완료, 권한 완료
-대시보드 운영현황 데이터 수정, 시설명 div z-index 수정정
2025-07-22 13:21:39 +09:00
jyha00 6102e0af6b 지도점검 테이블 수정 2025-07-22 13:10:22 +09:00
jyha00 225bae08d3 readOnly 수정 2025-07-22 13:09:20 +09:00
leedj312 d8b5abb12f 미들웨어 반영 기본값 반영 2025-07-22 10:36:56 +09:00
leedj312 d9a3da96bb 베이스 변경사항 2025-07-22 09:24:19 +09:00
leedj312 87d1f33c05 Merge commit 'd68c6c151c5135ccb1f326fd36cd4b02200106f7' into iipbs/wr/login-test 2025-07-22 09:23:56 +09:00
leedj312 d68c6c151c Merge commit 'ddf3a5cfa0aedbb2bb73e073ff97fa68ca2c5d9a' into iipbs/wr/dev 2025-07-21 20:00:43 +09:00
leedj312 dfb910f270 Merge commit '5976b35c902b1fb1da1fdc637e620a0d0d3e9ede' into iipbs/wr/dev 2025-07-21 19:58:48 +09:00
leedj312 ddf3a5cfa0 캘린더 함수 오류 2025-07-21 19:56:57 +09:00
jyha00 5976b35c90 결함 오류 수정 2025-07-21 19:56:41 +09:00
truthwing 6b204fce15 djlee product 2025-07-21 19:51:52 +09:00
leedj312 f731d0f9f0 변경사항 2025-07-21 19:04:13 +09:00
leedj312 e231d0c4be 수정 사항 발견 2025-07-21 18:05:13 +09:00
leedj312 e4328a2ed4 Merge commit '069e489d031203200fc4d73e470767503a3dc227' into iipbs/wr/dev 2025-07-21 18:01:43 +09:00
leedj312 069e489d03 온배수 현황 수질 작업중 2025-07-21 17:59:55 +09:00
leedj312 990dffc11c 물재이용 / 이동시 메인으로 이동 2025-07-21 17:59:38 +09:00
jyha00 b4140d6457 결함 수정 2025-07-21 17:50:47 +09:00
jyha00 91af5fd27c Merge branch 'iipbs/common/main' into iipbs/wr/pfmncSttn 2025-07-21 16:15:56 +09:00
jyha00 0bb16f9795 도넛차트 범례 높이 조정 2025-07-21 15:28:42 +09:00
jyha00 be7efb2ad0 결함 오류 수정 2025-07-21 15:27:18 +09:00
jyha00 fbd9575df7 잠재수요처 페이지 오류 수정 2025-07-21 11:07:51 +09:00
swcho 7816b4e450 Merge remote-tracking branch 'origin/main' into iipbs/sn/ii 2025-07-17 17:27:17 +09:00
swcho 240c2f847c Merge remote-tracking branch 'origin/iipbs_cs' into iipbs/sn/ii 2025-07-17 17:10:34 +09:00
swcho e39a102c14 Merge remote-tracking branch 'origin/iipbs/common/main' into iipbs/sn/ii 2025-07-17 17:08:36 +09:00
103 changed files with 3188 additions and 2470 deletions
-8
View File
@@ -1,8 +0,0 @@
# 디폴트 무시된 파일
/shelf/
/workspace.xml
# 에디터 기반 HTTP 클라이언트 요청
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+5 -1
View File
@@ -1,7 +1,9 @@
NEXT_PUBLIC_SITE_ID = FO
NEXT_PUBLIC_PORT = 11300
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
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
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_CLAIM_NAME = Authorization
@@ -10,3 +12,5 @@ NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
+7 -4
View File
@@ -1,7 +1,9 @@
NEXT_PUBLIC_SITE_ID = FO
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_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_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
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_CLAIM_NAME = Authorization
@@ -10,4 +12,5 @@ NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성 PC 서버 API
+22 -6
View File
@@ -1,12 +1,28 @@
# NEXT_PUBLIC_SITE_ID = WR
# NEXT_PUBLIC_PORT = 11301
# NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11301
# NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
# NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
# NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
# NEXT_PUBLIC_CLAIM_NAME = Authorization
# NEXT_PUBLIC_AUTH_USER_ID = token-id
# NEXT_PUBLIC_ACCESS_TOKEN = access-token
# NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SITE_ID = FO
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://fo.hasuon.or.kr
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl
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_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
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
NEXT_PUBLIC_SEWERAGE_API_URL= http://apigateway.iipbs-dev.svc.cluster.local:8000/sewerage-service/api
+22
View File
@@ -0,0 +1,22 @@
"use client";
import { BaseLayout } from "@common/components";
import type { MenuItem } from "./store/common";
import { useFoStore } from "./store";
import { useRouter } from "next/navigation";
export default function Base({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const { getMenuAuth } = useFoStore((state) => state);
const router = useRouter();
const handleClick = (id:MenuItem) =>{
getMenuAuth(id.menuCd);
router.push(id.urlPath);
}
return <BaseLayout handleMenuClick={handleClick}>{children}</BaseLayout>;
}
+4 -11
View File
@@ -1,12 +1,5 @@
const DEV_PORT_COMMON = "11081";
const DEV_PORT_FO = "11082";
const DEV_PORT_WR = "11080";
import { PROXY_HOST, SERVER_API_URL, SERVER_API_WR_URL } from "@/src/shared/config/env";
export const LOCAL_URL_COMMON = `http://192.168.1.129:${DEV_PORT_COMMON}/api/v1`;
export const DEV_URL_COMMON = `http://con.mind-one.co.kr:${DEV_PORT_COMMON}/api/v1`;
export const LOCAL_URL_FO = `http://192.168.1.129:${DEV_PORT_FO}/api/v1`;
export const DEV_URL_FO = `http://con.mind-one.co.kr:${DEV_PORT_FO}/api/v1`;
export const LOCAL_URL_WR = `http://192.168.1.129:${DEV_PORT_WR}/api/v1`;
export const DEV_URL_WR = `http://con.mind-one.co.kr:${DEV_PORT_WR}/api/v1`;
export const DEV_URL_FO = SERVER_API_URL;
export const LOCAL_URL = PROXY_HOST;
export const DEV_URL_WR = SERVER_API_WR_URL;
+5 -5
View File
@@ -1,8 +1,8 @@
import { DEV_URL_COMMON, DEV_URL_FO, DEV_URL_WR } from "./config/env";
import { DEV_URL_FO, DEV_URL_WR, LOCAL_URL } from "./config/env";
export const getFetch = async (part : string, url: string) => {
let reqUrl = "";
reqUrl = part === "fo" ? DEV_URL_FO+url : part === "wr" ? DEV_URL_WR+url : DEV_URL_COMMON+url;
reqUrl = part === "fo" ? DEV_URL_FO+url : part === 'local' ? LOCAL_URL+url : DEV_URL_WR+url;
const response = await fetch(reqUrl , {
method: "GET",
headers: {
@@ -32,7 +32,7 @@ export const getFetchAreaList = async (url: string) => {
export const postFetch = async (part : string, url: string, params: unknown) => {
let reqUrl = "";
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_WR+url;
const response = await fetch(reqUrl, {
method: "POST",
headers: {
@@ -48,7 +48,7 @@ export const postFetch = async (part : string, url: string, params: unknown) =>
export const putFetch = async (part : string, url: string, params: unknown) => {
let reqUrl = "";
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_WR+url;
const response = await fetch(reqUrl, {
method: "PUT",
headers: {
@@ -64,7 +64,7 @@ export const putFetch = async (part : string, url: string, params: unknown) => {
export const deleteFetch = async (part : string, url: string, params: unknown) => {
let reqUrl = "";
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_COMMON+url;
reqUrl = part === "fo" ? DEV_URL_FO+url : DEV_URL_WR+url;
const response = await fetch(reqUrl, {
method: "DELETE",
headers: {
+2 -6
View File
@@ -1,10 +1,8 @@
"use client"
import { BaseLayout } from "@common/components/ui";
import Base from "./base";
import "./globals.css";
import { StoreProvider } from "./store";
export default function RootLayout({
children,
}: Readonly<{
@@ -14,9 +12,7 @@ export default function RootLayout({
<html lang="en">
<body>
<StoreProvider>
<BaseLayout>
{children}
</BaseLayout>
<Base>{children}</Base>
</StoreProvider>
</body>
</html>
+2 -2
View File
@@ -51,8 +51,8 @@ export default function DashBoardFclty({ onFacilityChange, sidoSigun, facilityNm
console.log('bscFctNm : ', bscFctNm);
return (
<>
<div className="z-50">
<SearchInput label={'시설명'} setValue={fncNextPage} sidoSigun={sidoSigun} fcltyName={bscFctNm}/>
</>
</div>
);
}
+79 -10
View File
@@ -3,6 +3,8 @@
====================================**/
import { getFetch } from "@/app/components/api";
import { LoginApi } from "@/src/entities/auth";
import type { ILogin } from "@/src/entities/auth/model/login-interface";
/**
* STORE - TYPE
@@ -63,6 +65,26 @@ export type envPartSelectDataType = SelectDataType & {
adstDliStrCd: string,
}
export interface MenuItem {
menuCd: number;
menuKornNm: string;
menuEngNm: string;
parentId: number | null;
sortSeq: number;
iconNm?: string;
children: MenuItem[] | null;
levelNo: number;
urlPath: string;
menuLnkgTypeCd: string;
menuLnkgSn: number;
menuPath: string;
qrcd: string;
useYn: string;
otptYn: string;
newWndwYn: string;
requiredUrlPath: boolean;
}
/**
* STORE - DATA
*/
@@ -305,6 +327,7 @@ const fetchEnvPartData = async (): Promise<envPartSelectDataType[]> => {
* Store - expaort
====================================*/
export type CommonAction = {
getMenuAuth : (menuCd : number) => Promise<void>;
initializeCommonData: () => Promise<void>;
}
@@ -326,10 +349,18 @@ export type CommonType = {
selectFlowPanel: SelectDataType[];
selectEnvPartData: envPartSelectDataType[];
btnClass: string;
}
}
};
export const commonState:CommonType = {
auth: {
mngAuthrtYn: string;
inqAuthrtYn: string;
regAuthrtYn: string;
mdfcnAuthrtYn: string;
delAuthrtYn: string;
};
};
export const commonState: CommonType = {
Common: {
isInit: false,
selectSidoData: selectSidoData,
@@ -341,22 +372,60 @@ export const commonState:CommonType = {
selectRegionData: selectRegionData,
selectUnitWaterShedData: selectUnitWaterShedData,
selectMiddleRegionData: selectMiddleRegionData,
selectEnvPartSidoData : selectEnvPartSidoData,
selectEnvPartSigunData : selectEnvPartSigunData,
selectEnvPartSidoData: selectEnvPartSidoData,
selectEnvPartSigunData: selectEnvPartSigunData,
selectFlowTerm: selectFlowTerm,
selectFlowPanel: selectFlowPanel,
selectEnvPartData : selectEnvPartData,
btnClass: "p-4 m-2 text-white rounded-sm text-lg font-medium"
}
}
selectEnvPartData: selectEnvPartData,
btnClass: "p-4 m-2 text-white rounded-sm text-lg font-medium",
},
auth: {
mngAuthrtYn: "N",
inqAuthrtYn: "N",
regAuthrtYn: "N",
mdfcnAuthrtYn: "N",
delAuthrtYn: "N",
},
};
export const CommonReducer:(set:(fn: (state: CommonType) => CommonType) => void)=>CommonAction=(set: (fn: (state: CommonType) => CommonType) => void) => {
return {
// 메뉴 권한 확인
getMenuAuth : async (menuCd : number) =>{
const response = await getFetch(
"local",
`/cms-service/api/v1/menu-authrts/pageinfo/${menuCd}`
);
set((state: CommonType) => {
return {
...state,
auth: {
mngAuthrtYn: response[0].mngAuthrtYn,
inqAuthrtYn: response[0].mngAuthrtYn,
regAuthrtYn: response[0].mngAuthrtYn,
mdfcnAuthrtYn: response[0].mngAuthrtYn,
delAuthrtYn: response[0].mngAuthrtYn,
},
};
});
},
// 시도 변경 이벤트
initializeCommonData: async () => {
const payLoad : ILogin = {
userId: "tuser10003",
password: "test1234!"
};
console.log(payLoad.userId)
console.log(payLoad.password)
LoginApi.login(payLoad);
const promiseSet = await Promise.all([fetchSidoData(), fetchSigunData(), fetchRegionData(), fetchUnitWaterShedData(), fetchMiddleRegionData(), fetchEnvPartData()]);
const [sidoData, sggData, regionData, unitData, midData, envData] = promiseSet;
set((state: CommonType) => ({
...state,
Common: {
...state.Common,
selectSidoData: sidoData,
@@ -371,4 +440,4 @@ export const CommonReducer:(set:(fn: (state: CommonType) => CommonType) => void)
}
}
export type CommonStore = CommonType & CommonAction;
export type CommonStore = CommonType & CommonAction;
+80 -285
View File
@@ -356,7 +356,7 @@ const upHeadListRainManage : TableUpperProps[] = [
{ id: "A", title: "유입(㎥/일)", row:0, colSpan:2 },
{ id: "inflAmnt", title: "유입유량", row:1 },
{ id: "fctCpc", title: "시설용량대비", row:1 },
{ id: "B", title: "설계유입수질(㎎/L)", row:0, colSpan:5 },
{ id: "B", title: "설계유입수질(㎎/L)", row:0, colSpan:5 },
{ id: "dsInflWqltBod", title: "BOD", row:1 },
{ id: "dsInflWqltCod", title: "TOC\n(COD)", row:1 },
{ id: "dsInflWqltSs", title: "SS", row:1 },
@@ -896,6 +896,49 @@ export const dataFormSetting=(item : OperationalStatusListProps)=> {
DataForm({ type: 'float2', column: 'rainRate', item: item as unknown as Record<string, unknown>});
};
const changeValue=(operationalStatus, data, keyTxt = 'INFL_AMNT')=>{
operationalStatus.yearAvg = data.yearData ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.yearData?Number(Math.round(data.yearData['AVG_'+keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.yearData['AVG_'+keyTxt] : '';
operationalStatus.yearMax = data.yearData ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.yearData?Number(Math.round(data.yearData['MAX_'+keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.yearData['MAX_'+keyTxt] : '';
operationalStatus.yearMin = data.yearData ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.yearData?Number(Math.round(data.yearData['MIN_'+keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.yearData['MIN_'+keyTxt] : '';
// 여름
operationalStatus.summerAll = data.summer ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.summer?Number(Math.round(data.summer['AVG_'+keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.summer['AVG_'+keyTxt] : '';
operationalStatus.summerThree = data.summerRainy ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.summerRainy?Number(Math.round(data.summerRainy["AVG_" + keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.summerRainy["AVG_" + keyTxt] : '';
operationalStatus.summerRain = data.summerSunny ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.summerSunny?Number(Math.round(data.summerSunny["AVG_" + keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.summerSunny["AVG_" + keyTxt] : '';
// 겨울
operationalStatus.winterAll = data.winter ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.winter?Number(Math.round(data.winter["AVG_" + keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.winter["AVG_" + keyTxt] : '';
operationalStatus.winterSunnyMin = data.winterSunny ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.winterSunny?Number(Math.round(data.winterSunny["MIN_" + keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.winterSunny["MIN_" + keyTxt] : '';
operationalStatus.winterSunnyAvg = data.winterSunny ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.winterSunny?Number(Math.round(data.winterSunny["AVG_" + keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.winterSunny["AVG_" + keyTxt] : '';
operationalStatus.winterSunnyMax = data.winterSunny ? (keyTxt.includes('_TP') || keyTxt.includes("_TN"))? data.winterSunny?Number(Math.round(data.winterSunny["MAX_" + keyTxt] * 1000) / 1000).toFixed(3).toString():'': data.winterSunny["MAX_" + keyTxt] : '';
// 지하수
operationalStatus.groundWaterAvg = 10;
operationalStatus.groundWaterSummer = 11;
operationalStatus.groundWaterWinter = 12;
// 오염물질
// RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
const summerLowFlow = data.summerBod && data.summerBod.INFL_AMNT && data.summerBod.INFL_AMNT != 'null' ? Number(data.summerBod.INFL_AMNT) : 0;
const winterAvgBod = data.winterSunny && data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD && data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD != 'null' ? Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD) : 0;
const summerLowBod = data.summerBod && data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD && data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD != 'null' ? Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD) : 0;
const summerLowRain = data.summerBod && data.summerBod.INFO_RN_DAY && data.summerBod.INFO_RN_DAY != 'null' ? Number(data.summerBod.INFO_RN_DAY) : 0;
operationalStatus.rdi = winterAvgBod === 0 ? 0 : summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatus.rdiRain = summerLowRain;
}
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.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.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() : '';
}
export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) => void)=>DashBoardActions=(set: (fn: (state: DashBoardType) => DashBoardType) => void) => {
return {
initializeDashBoardData: async () => {
@@ -969,18 +1012,33 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
// 유량 - 유입
if (operationalStatusList?.[0]) {
// 연간
operationalStatusList[0].yearAvg = data.yearData===null?'':data.yearData.AVG_INFL_AMNT?data.yearData.AVG_INFL_AMNT:0+data.yearData.AVG_SUM_FLOW?data.yearData.AVG_SUM_FLOW:0+data.yearData.AVG_TP_INFL_WQLT_TP?data.yearData.AVG_TP_INFL_WQLT_TP:0;
operationalStatusList[0].yearMax = data.yearData===null?'':data.yearData.MAX_INFL_AMNT?data.yearData.MAX_INFL_AMNT:0+data.yearData.MAX_SUM_FLOW?data.yearData.MAX_SUM_FLOW:0+data.yearData.MAX_TP_INFL_WQLT_TP?data.yearData.MAX_TP_INFL_WQLT_TP:0;
operationalStatusList[0].yearMin = data.yearData===null?'':data.yearData.MIN_INFL_AMNT?data.yearData.MIN_INFL_AMNT:0+data.yearData.MIN_SUM_FLOW?data.yearData.MIN_SUM_FLOW:0+data.yearData.MIN_TP_INFL_WQLT_TP?data.yearData.MIN_TP_INFL_WQLT_TP:0;
const yearAvg = data.yearData===null?'':(data.yearData.AVG_INFL_AMNT?data.yearData.AVG_INFL_AMNT:0)+(data.yearData.AVG_SUM_FLOW?data.yearData.AVG_SUM_FLOW:0)+(data.yearData.AVG_RETURN_AMNT?data.yearData.AVG_RETURN_AMNT:0);
const yearMax = data.yearData===null?'':(data.yearData.MAX_INFL_AMNT?data.yearData.MAX_INFL_AMNT:0)+(data.yearData.MAX_SUM_FLOW?data.yearData.MAX_SUM_FLOW:0)+(data.yearData.MAX_RETURN_AMNT?data.yearData.MAX_RETURN_AMNT:0);
const yearMin = data.yearData===null?'':(data.yearData.MIN_INFL_AMNT?data.yearData.MIN_INFL_AMNT:0)+(data.yearData.MIN_SUM_FLOW?data.yearData.MIN_SUM_FLOW:0)+(data.yearData.MIN_RETURN_AMNT?data.yearData.MIN_RETURN_AMNT:0);
operationalStatusList[0].yearAvg = yearAvg;
operationalStatusList[0].yearMax = yearMax;
operationalStatusList[0].yearMin = yearMin;
// 여름
operationalStatusList[0].summerAll = data.summer===null?'':data.summer.AVG_INFL_AMNT?data.summer.AVG_INFL_AMNT:0+data.summer.AVG_SUM_FLOW?data.summer.AVG_SUM_FLOW:0+data.summer.AVG_TP_INFL_WQLT_TP?data.summer.AVG_TP_INFL_WQLT_TP:0;
operationalStatusList[0].summerThree = data.summerRainy===null?'':data.summerRainy.AVG_INFL_AMNT?data.summerRainy.AVG_INFL_AMNT:0+data.summerRainy.AVG_SUM_FLOW?data.summerRainy.AVG_SUM_FLOW:0+data.summerRainy.AVG_TP_INFL_WQLT_TP?data.summerRainy.AVG_TP_INFL_WQLT_TP:0;
operationalStatusList[0].summerRain = data.summerSunny===null?'':data.summerSunny.AVG_INFL_AMNT?data.summerSunny.AVG_INFL_AMNT:0+data.summerSunny.AVG_SUM_FLOW?data.summerSunny.AVG_SUM_FLOW:0+data.summerSunny.AVG_TP_INFL_WQLT_TP?data.summerSunny.AVG_TP_INFL_WQLT_TP:0;
operationalStatusList[0].summerAll = data.summer === null ? '' : (
(data.summer.AVG_INFL_AMNT ? data.summer.AVG_INFL_AMNT : 0) +
(data.summer.AVG_SUM_FLOW ? data.summer.AVG_SUM_FLOW : 0) +
(data.summer.AVG_TP_INFL_WQLT_TP ? data.summer.AVG_TP_INFL_WQLT_TP : 0)
);
operationalStatusList[0].summerThree = data.summerRainy === null ? '' : (
(data.summerRainy.AVG_INFL_AMNT ? data.summerRainy.AVG_INFL_AMNT : 0) +
(data.summerRainy.AVG_SUM_FLOW ? data.summerRainy.AVG_SUM_FLOW : 0) +
(data.summerRainy.AVG_TP_INFL_WQLT_TP ? data.summerRainy.AVG_TP_INFL_WQLT_TP : 0)
);
operationalStatusList[0].summerRain = data.summerSunny === null ? '' : (
(data.summerSunny.AVG_INFL_AMNT ? data.summerSunny.AVG_INFL_AMNT : 0) +
(data.summerSunny.AVG_SUM_FLOW ? data.summerSunny.AVG_SUM_FLOW : 0) +
(data.summerSunny.AVG_TP_INFL_WQLT_TP ? data.summerSunny.AVG_TP_INFL_WQLT_TP : 0)
);
// 겨울
operationalStatusList[0].winterAll = data.winter===null?'':data.winter.AVG_INFL_AMNT?data.winter.AVG_INFL_AMNT:0+data.winter.AVG_SUM_FLOW?data.winter.AVG_SUM_FLOW:0+data.winter.AVG_TP_INFL_WQLT_TP?data.winter.AVG_TP_INFL_WQLT_TP:0;
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].winterAll = data.winter === null ? '' : (data.winter.AVG_INFL_AMNT ? data.winter.AVG_INFL_AMNT : 0) + (data.winter.AVG_SUM_FLOW ? data.winter.AVG_SUM_FLOW : 0) + (data.winter.AVG_TP_INFL_WQLT_TP ? data.winter.AVG_TP_INFL_WQLT_TP : 0);
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 = 10;
operationalStatusList[0].groundWaterSummer = 11;
@@ -996,280 +1054,16 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
dataFormSetting(operationalStatusList[0]);
}
// 유량 - 순수하수
if (operationalStatusList?.[1]) {
// 연간
operationalStatusList[1].yearAvg = data.yearData?data.yearData.AVG_INFL_AMNT:'';
operationalStatusList[1].yearMax = data.yearData?data.yearData.MAX_INFL_AMNT:'';
operationalStatusList[1].yearMin = data.yearData?data.yearData.MIN_INFL_AMNT:'';
// 여름
operationalStatusList[1].summerAll = data.summer?data.summer.AVG_INFL_AMNT:'';
operationalStatusList[1].summerThree = data.summerRainy?data.summerRainy.AVG_INFL_AMNT:'';
operationalStatusList[1].summerRain = data.summerSunny?data.summerSunny.AVG_INFL_AMNT:'';
// 겨울
operationalStatusList[1].winterAll = data.winter?data.winter.AVG_INFL_AMNT:'';
operationalStatusList[1].winterSunnyMin = data.winterSunny?data.winterSunny.MIN_INFL_AMNT:'';
operationalStatusList[1].winterSunnyAvg = data.winterSunny?data.winterSunny.AVG_INFL_AMNT:'';
operationalStatusList[1].winterSunnyMax = data.winterSunny?data.winterSunny.MAX_INFL_AMNT:'';
// 지하수
operationalStatusList[1].groundWaterAvg = 10;
operationalStatusList[1].groundWaterSummer = 11;
operationalStatusList[1].groundWaterWinter = 12;
// 오염물질
// RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
const summerLowFlow = data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0;
const winterAvgBod = data.winterSunny&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowBod = data.summerBod&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0;
operationalStatusList[1].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatusList[1].rdiRain = summerLowRain;
dataFormSetting(operationalStatusList[1]);
}
// 유량 - 연계처리수
if (operationalStatusList?.[2]) {
// 연간
operationalStatusList[2].yearAvg = data.yearData?data.yearData.AVG_SUM_FLOW:'';
operationalStatusList[2].yearMax = data.yearData?data.yearData.MAX_SUM_FLOW:'';
operationalStatusList[2].yearMin = data.yearData?data.yearData.MIN_SUM_FLOW:'';
// 여름
operationalStatusList[2].summerAll = data.summer?data.summer.AVG_SUM_FLOW:'';
operationalStatusList[2].summerThree = data.summerRainy?data.summerRainy.AVG_SUM_FLOW:'';
operationalStatusList[2].summerRain = data.summerSunny?data.summerSunny.AVG_SUM_FLOW:'';
// 겨울
operationalStatusList[2].winterAll = data.winter?data.winter.AVG_SUM_FLOW:'';
operationalStatusList[2].winterSunnyMin = data.winterSunny?data.winterSunny.MIN_SUM_FLOW:'';
operationalStatusList[2].winterSunnyAvg = data.winterSunny?data.winterSunny.AVG_SUM_FLOW:'';
operationalStatusList[2].winterSunnyMax = data.winterSunny?data.winterSunny.MAX_SUM_FLOW:'';
// 지하수
operationalStatusList[2].groundWaterAvg = 10;
operationalStatusList[2].groundWaterSummer = 11;
operationalStatusList[2].groundWaterWinter = 12;
// 오염물질
// RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
const summerLowFlow = data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0;
const winterAvgBod = data.winterSunny&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowBod = data.summerBod&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0;
operationalStatusList[2].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatusList[2].rdiRain = summerLowRain;
dataFormSetting(operationalStatusList[2]);
}
// 유량 - 총인설비방류수
if (operationalStatusList?.[3]) {
// 연간
operationalStatusList[3].yearAvg = data.yearData?data.yearData.AVG_TP_INFL_WQLT_TP:'';
operationalStatusList[3].yearMax = data.yearData?data.yearData.MAX_TP_INFL_WQLT_TP:'';
operationalStatusList[3].yearMin = data.yearData?data.yearData.MIN_TP_INFL_WQLT_TP:'';
// 여름
operationalStatusList[3].summerAll = data.summer?data.summer.AVG_TP_INFL_WQLT_TP:'';
operationalStatusList[3].summerThree = data.summerRainy?data.summerRainy.AVG_TP_INFL_WQLT_TP:'';
operationalStatusList[3].summerRain = data.summerSunny?data.summerSunny.AVG_TP_INFL_WQLT_TP:'';
// 겨울
operationalStatusList[3].winterAll = data.winter?data.winter.AVG_TP_INFL_WQLT_TP:'';
operationalStatusList[3].winterSunnyMin = data.winterSunny?data.winterSunny.MIN_TP_INFL_WQLT_TP:'';
operationalStatusList[3].winterSunnyAvg = data.winterSunny?data.winterSunny.AVG_TP_INFL_WQLT_TP:'';
operationalStatusList[3].winterSunnyMax = data.winterSunny?data.winterSunny.MAX_TP_INFL_WQLT_TP:'';
// 지하수
operationalStatusList[3].groundWaterAvg = 10;
operationalStatusList[3].groundWaterSummer = 11;
operationalStatusList[3].groundWaterWinter = 12;
// 오염물질
// RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
const summerLowFlow = data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0;
const winterAvgBod = data.winterSunny&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowBod = data.summerBod&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0;
operationalStatusList[3].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatusList[3].rdiRain = summerLowRain;
dataFormSetting(operationalStatusList[3]);
}
// 유량 - 방류수
if (operationalStatusList?.[4]) {
// 연간
operationalStatusList[4].yearAvg = data.yearData?data.yearData.AVG_EFFL_AMNT:'';
operationalStatusList[4].yearMax = data.yearData?data.yearData.MAX_EFFL_AMNT:'';
operationalStatusList[4].yearMin = data.yearData?data.yearData.MIN_EFFL_AMNT:'';
// 여름
operationalStatusList[4].summerAll = data.summer?data.summer.AVG_EFFL_AMNT:'';
operationalStatusList[4].summerThree = data.summerRainy?data.summerRainy.AVG_EFFL_AMNT:'';
operationalStatusList[4].summerRain = data.summerSunny?data.summerSunny.AVG_EFFL_AMNT:'';
// 겨울
operationalStatusList[4].winterAll = data.winter?data.winter.AVG_EFFL_AMNT:'';
operationalStatusList[4].winterSunnyMin = data.winterSunny?data.winterSunny.MIN_EFFL_AMNT:'';
operationalStatusList[4].winterSunnyAvg = data.winterSunny?data.winterSunny.AVG_EFFL_AMNT:'';
operationalStatusList[4].winterSunnyMax = data.winterSunny?data.winterSunny.MAX_EFFL_AMNT:'';
// 지하수
operationalStatusList[4].groundWaterAvg = 10;
operationalStatusList[4].groundWaterSummer = 11;
operationalStatusList[4].groundWaterWinter = 12;
// 오염물질
// RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
const summerLowFlow = data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0;
const winterAvgBod = data.winterSunny&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowBod = data.summerBod&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0;
operationalStatusList[4].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatusList[4].rdiRain = summerLowRain;
dataFormSetting(operationalStatusList[4]);
}
/*
* 수질 - 유입(BOD)
*/
if (operationalStatusList?.[5]) {
// 연간
operationalStatusList[5].yearAvg = data.yearData?data.yearData.AVG_INFL_ASSCT_BFR_WQLT_BOD:'';
operationalStatusList[5].yearMax = data.yearData?data.yearData.MAX_INFL_ASSCT_BFR_WQLT_BOD:'';
operationalStatusList[5].yearMin = data.yearData?data.yearData.MIN_INFL_ASSCT_BFR_WQLT_BOD:'';
dataFormSetting(operationalStatusList[5]);
// 여름
operationalStatusList[5].summerAll = data.summer?data.summer.AVG_INFL_ASSCT_BFR_WQLT_BOD:'';
operationalStatusList[5].summerThree = data.summerRainy?data.summerRainy.AVG_INFL_ASSCT_BFR_WQLT_BOD:'';
operationalStatusList[5].summerRain = data.summerSunny?data.summerSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD:'';
// 겨울
operationalStatusList[5].winterAll = data.winter?data.winter.AVG_INFL_ASSCT_BFR_WQLT_BOD:'';
operationalStatusList[5].winterSunnyMin = data.winterSunny?data.winterSunny.MIN_INFL_ASSCT_BFR_WQLT_BOD:'';
operationalStatusList[5].winterSunnyAvg = data.winterSunny?data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD:'';
operationalStatusList[5].winterSunnyMax = data.winterSunny?data.winterSunny.MAX_INFL_ASSCT_BFR_WQLT_BOD:'';
// 오염물질
// RDII 추정 = 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD))
const summerLowFlow = data.summerBod&&data.summerBod.INFL_AMNT&&data.summerBod.INFL_AMNT!='null'?Number(data.summerBod.INFL_AMNT):0;
const winterAvgBod = data.winterSunny&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD&&data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowBod = data.summerBod&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD&&data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD!='null'?Number(data.summerBod.MIN_INFL_ASSCT_BFR_WQLT_BOD):0;
const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0;
operationalStatusList[5].rdi = winterAvgBod===0?0:summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod);
operationalStatusList[5].rdiRain = summerLowRain;
dataFormSetting(operationalStatusList[5]);
}
/**
* 수질-방류(BOD)
*/
if (operationalStatusList?.[6]) {
// 연간
operationalStatusList[6].yearAvg = data.yearData?data.yearData.AVG_EFFL_WQLT_BOD:'';
operationalStatusList[6].yearMax = data.yearData?data.yearData.MAX_EFFL_WQLT_BOD:'';
operationalStatusList[6].yearMin = data.yearData?data.yearData.MIN_EFFL_WQLT_BOD:'';
dataFormSetting(operationalStatusList[6]);
// 여름
operationalStatusList[6].summerAll = data.summer?data.summer.AVG_EFFL_WQLT_BOD:'';
operationalStatusList[6].summerThree = data.summerRainy?data.summerRainy.AVG_EFFL_WQLT_BOD:'';
operationalStatusList[6].summerRain = data.summerSunny?data.summerSunny.AVG_EFFL_WQLT_BOD:'';
// 겨울
operationalStatusList[6].winterAll = data.winter?data.winter.AVG_EFFL_WQLT_BOD:'';
operationalStatusList[6].winterSunnyMin = data.winterSunny?data.winterSunny.MIN_EFFL_WQLT_BOD:'';
operationalStatusList[6].winterSunnyAvg = data.winterSunny?data.winterSunny.AVG_EFFL_WQLT_BOD:'';
operationalStatusList[6].winterSunnyMax = data.winterSunny?data.winterSunny.MAX_EFFL_WQLT_BOD:'';
dataFormSetting(operationalStatusList[6]);
}
// 수질-유입(T-N)
if (operationalStatusList?.[7]) {
// 연간
operationalStatusList[7].yearAvg = data.yearData?Number(Math.round(data.yearData.AVG_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[7].yearMax = data.yearData?Number(Math.round(data.yearData.MAX_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[7].yearMin = data.yearData?Number(Math.round(data.yearData.MIN_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
// 여름
operationalStatusList[7].summerAll = data.summer?Number(Math.round(data.summer.AVG_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[7].summerThree = data.summerRainy?Number(Math.round(data.summerRainy.AVG_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[7].summerRain = data.summerSunny?Number(Math.round(data.summerSunny.AVG_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
// 겨울
operationalStatusList[7].winterAll = data.winter?Number(Math.round(data.winter.AVG_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[7].winterSunnyMin = data.winterSunny?Number(Math.round(data.winterSunny.MIN_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[7].winterSunnyAvg = data.winterSunny?Number(Math.round(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[7].winterSunnyMax = data.winterSunny?Number(Math.round(data.winterSunny.MAX_INFL_ASSCT_BFR_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
}
// 수질-방류(T-N)
if (operationalStatusList?.[8]) {
// 연간
operationalStatusList[8].yearAvg = data.yearData?Number(Math.round(data.yearData.AVG_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[8].yearMax = data.yearData?Number(Math.round(data.yearData.MAX_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[8].yearMin = data.yearData?Number(Math.round(data.yearData.MIN_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
// 여름
operationalStatusList[8].summerAll = data.summer?Number(Math.round(data.summer.AVG_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[8].summerThree = data.summerRainy?Number(Math.round(data.summerRainy.AVG_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[8].summerRain = data.summerSunny?Number(Math.round(data.summerSunny.AVG_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
// 겨울
operationalStatusList[8].winterAll = data.winter?Number(Math.round(data.winter.AVG_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[8].winterSunnyMin = data.winterSunny?Number(Math.round(data.winterSunny.MIN_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[8].winterSunnyAvg = data.winterSunny?Number(Math.round(data.winterSunny.AVG_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[8].winterSunnyMax = data.winterSunny?Number(Math.round(data.winterSunny.MAX_EFFL_WQLT_TN * 1000) / 1000).toFixed(3).toString():'';
}
// 수질-유입(T-P)
if (operationalStatusList?.[9]) {
// 연간
operationalStatusList[9].yearAvg = data.yearData?Number(Math.round(data.yearData.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[9].yearMax = data.yearData?Number(Math.round(data.yearData.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[9].yearMin = data.yearData?Number(Math.round(data.yearData.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 여름
operationalStatusList[9].summerAll = data.summer?Number(Math.round(data.summer.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[9].summerThree = data.summerRainy?Number(Math.round(data.summerRainy.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[9].summerRain = data.summerSunny?Number(Math.round(data.summerSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 겨울
operationalStatusList[9].winterAll = data.winter?Number(Math.round(data.winter.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[9].winterSunnyMin = data.winterSunny?Number(Math.round(data.winterSunny.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[9].winterSunnyAvg = data.winterSunny?Number(Math.round(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[9].winterSunnyMax = data.winterSunny?Number(Math.round(data.winterSunny.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
}
// 수질-방류(T-P)
if (operationalStatusList?.[10]) {
// 연간
operationalStatusList[10].yearAvg = data.yearData?Number(Math.round(data.yearData.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[10].yearMax = data.yearData?Number(Math.round(data.yearData.MAX_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[10].yearMin = data.yearData?Number(Math.round(data.yearData.MIN_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 여름
operationalStatusList[10].summerAll = data.summer?Number(Math.round(data.summer.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[10].summerThree = data.summerRainy?Number(Math.round(data.summerRainy.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[10].summerRain = data.summerSunny?Number(Math.round(data.summerSunny.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 겨울
operationalStatusList[10].winterAll = data.winter?Number(Math.round(data.winter.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[10].winterSunnyMin = data.winterSunny?Number(Math.round(data.winterSunny.MIN_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[10].winterSunnyAvg = data.winterSunny?Number(Math.round(data.winterSunny.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[10].winterSunnyMax = data.winterSunny?Number(Math.round(data.winterSunny.MAX_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
}
/**
* 총인설비
*/
//
// 유입
if (operationalStatusList?.[11]) {
// 연간
operationalStatusList[11].yearAvg = data.yearData?Number(Math.round(data.yearData.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[11].yearMax = data.yearData?Number(Math.round(data.yearData.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[11].yearMin = data.yearData?Number(Math.round(data.yearData.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 여름
operationalStatusList[11].summerAll = data.summer?Number(Math.round(data.summer.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[11].summerThree = data.summerRainy?Number(Math.round(data.summerRainy.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[11].summerRain = data.summerSunny?Number(Math.round(data.summerSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 겨울
operationalStatusList[11].winterAll = data.winter?Number(Math.round(data.winter.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[11].winterSunnyMin = data.winterSunny?Number(Math.round(data.winterSunny.MIN_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[11].winterSunnyAvg = data.winterSunny?Number(Math.round(data.winterSunny.AVG_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[11].winterSunnyMax = data.winterSunny?Number(Math.round(data.winterSunny.MAX_INFL_ASSCT_BFR_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
}
// 방류
if (operationalStatusList?.[12]) {
// 연간
operationalStatusList[12].yearAvg = data.yearData?Number(Math.round(data.yearData.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[12].yearMax = data.yearData?Number(Math.round(data.yearData.MAX_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[12].yearMin = data.yearData?Number(Math.round(data.yearData.MIN_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 여름
operationalStatusList[12].summerAll = data.summer?Number(Math.round(data.summer.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[12].summerThree = data.summerRainy?Number(Math.round(data.summerRainy.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[12].summerRain = data.summerSunny?Number(Math.round(data.summerSunny.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
// 겨울
operationalStatusList[12].winterAll = data.winter?Number(Math.round(data.winter.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[12].winterSunnyMin = data.winterSunny?Number(Math.round(data.winterSunny.MIN_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[12].winterSunnyAvg = data.winterSunny?Number(Math.round(data.winterSunny.AVG_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
operationalStatusList[12].winterSunnyMax = data.winterSunny?Number(Math.round(data.winterSunny.MAX_EFFL_WQLT_TP * 1000) / 1000).toFixed(3).toString():'';
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'];
if(operationalStatusList[i]){
if(i < 7){
changeValue(operationalStatusList[i], data, txtArray[i]);
dataFormSetting(operationalStatusList[i]!);
}else{
calcValue(operationalStatusList[i], data, txtArray[i]);
}
}
}
}
//const excelDownList: RainManageExcelType[] = [];
@@ -1446,6 +1240,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType)
const efflWqltTp = [0, 0, 0, 0, 0, 0, 0, 0, 0];
// 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;
+1
View File
@@ -12,6 +12,7 @@
},
"aliases": {
"components": "@/components",
"src": "@/src",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
+8 -5
View File
@@ -1,8 +1,8 @@
import { NextRequest, NextResponse } from "next/server";
import { SERVER_API_CS_URL } from "./src/shared/config/env";
const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id";
const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization";
const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || "";
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
@@ -14,7 +14,7 @@ export function middleware(req: NextRequest) {
if (pathname.startsWith("/server")) {
const queryParams = searchParams.toString();
const newUrl = `${SERVER_API_URL}${pathname.replace("/server", "")}${
const newUrl = `${SERVER_API_CS_URL}${pathname.replace("/server", "")}${
queryParams ? `?${queryParams}` : ""
}`;
console.log(`[Middleware] Rewriting from '/server' path to: ${newUrl}`);
@@ -76,7 +76,7 @@ export function middleware(req: NextRequest) {
const requestHeaders = new Headers(req.headers);
const token = req.cookies.get(CLAIM_NAME)?.value;
const userId = req.cookies.get(AUTH_USER_ID)?.value;
const newUrl = `${SERVER_API_URL}${pathname}`;
const newUrl = `${SERVER_API_CS_URL}${pathname}`;
if (token) requestHeaders.set(CLAIM_NAME, token);
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
@@ -91,7 +91,7 @@ export function middleware(req: NextRequest) {
if (pathname.startsWith("/user-service")) {
const requestHeaders = new Headers(req.headers);
const newUrl = `${SERVER_API_URL}${pathname}`;
const newUrl = `${SERVER_API_CS_URL}${pathname}`;
console.log(
`[Middleware] Rewriting from '/user-service' path to: ${newUrl}`,
@@ -100,7 +100,9 @@ export function middleware(req: NextRequest) {
headers: requestHeaders,
});
}
if (pathname === "/") {
return NextResponse.redirect(new URL("/pages/dashboard", req.url));
}
return NextResponse.next();
}
@@ -111,5 +113,6 @@ export const config = {
"/attach-service/:path*",
"/user-service/:path*",
"/cms-service/:path*",
"/"
],
};
+1
View File
@@ -13,6 +13,7 @@
"@common/components": "workspace:*",
"@tailwindcss/vite": "^4.0.10",
"html2canvas": "^1.4.1",
"js-cookie": "^3.0.5",
"next": "15.1.7",
"select": "^1.1.2",
"webpack": "^5.98.0",
@@ -0,0 +1,81 @@
import type { LoginService, ILogin } from "../model/login-interface";
import { tokenManager } from "../lib/token-manager";
import {PROXY_HOST, ACCESS_TOKEN, AUTH_USER_ID,SITE_ID, CLAIM_NAME, ENDPOINT, JWT_EXPIRATION_TIME } from "../../../shared/config";
export class LoginApiService implements LoginService {
private static instance: LoginApiService;
private constructor() {}
public static getInstance(): LoginApiService {
if (!LoginApiService.instance) {
LoginApiService.instance = new LoginApiService();
}
return LoginApiService.instance;
}
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({
userId: payload.userId,
password: payload.password,
}),
});
// const data = response.headers.get(ACCESS_TOKEN);
const accessToken = response.headers.get(ACCESS_TOKEN);
const tokenId = response.headers.get(AUTH_USER_ID);
console.log('accessToken ', accessToken)
console.log('tokenId ', tokenId)
if (!accessToken || !tokenId) {
throw new Error("Missing required authentication tokens");
}
tokenManager.setToken(CLAIM_NAME, accessToken);
tokenManager.setToken(AUTH_USER_ID, tokenId);
tokenManager.setToken("site-id-key", SITE_ID);
tokenManager.setupRefreshTimer(
() => this.silentRefresh(),
JWT_EXPIRATION_TIME,
);
} catch (error) {
console.log(' login err ' , error)
throw new Error(`Login failed: ${error}`);
}
}
public async silentRefresh(): Promise<void> {
console.log(' silentRefresh ')
try {
const response = await fetch(PROXY_HOST+
`${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`,
{ method: "PUT" },
);
const data = await response.json();
const accessToken = data[ACCESS_TOKEN];
const tokenId = data[AUTH_USER_ID];
if (!accessToken || !tokenId) {
throw new Error("Missing required authentication tokens");
}
tokenManager.setToken(CLAIM_NAME, accessToken);
tokenManager.setToken(AUTH_USER_ID, tokenId);
} catch (error) {
tokenManager.clearAuthToken();
throw new Error(`Silent refresh failed: ${error}`);
}
}
}
export const LoginApi = LoginApiService.getInstance();
+2
View File
@@ -0,0 +1,2 @@
export { LoginApi } from "./api/login-service";
//export { AuthWrapper } from "./lib/auth-wrapper";
@@ -0,0 +1,59 @@
import { AUTH_USER_ID, CLAIM_NAME } from "@/src/shared/config";
import { getCookie, removeCookie, setCookie } from "@/src/shared/lib/cookie";
export class TokenManager {
private static instance: TokenManager;
private refreshTimer: NodeJS.Timeout | null = null;
private constructor() {}
public static getInstance(): TokenManager {
if (!TokenManager.instance) {
TokenManager.instance = new TokenManager();
}
return TokenManager.instance;
}
public getToken(key: string): string | undefined {
return getCookie(key);
}
public setToken(key: string, value: string): void {
setCookie(key, value, {
secure: window.location.protocol === "https:",
sameSite: "lax",
});
}
public removeToken(key: string): void {
removeCookie(key);
}
public setupRefreshTimer(
callback: () => Promise<void>,
expirationTime: number,
): void {
if (this.refreshTimer) {
clearTimeout(this.refreshTimer);
}
this.refreshTimer = setTimeout(() => {
callback().catch((error) => {
console.error("Silent refresh failed:", error);
this.clearAuthToken();
});
}, expirationTime - 60000);
}
public clearAuthToken(): void {
if (this.refreshTimer) {
clearTimeout(this.refreshTimer);
this.refreshTimer = null;
}
this.removeToken(CLAIM_NAME);
this.removeToken(AUTH_USER_ID);
}
}
export const tokenManager = TokenManager.getInstance();
@@ -0,0 +1,9 @@
export interface ILogin {
userId: string;
password: string;
}
export interface LoginService {
login(payload: ILogin): Promise<void>;
silentRefresh(): Promise<void>;
}
+56
View File
@@ -0,0 +1,56 @@
import { PROXY_HOST } from "./env";
export const BASE_URL = `${PROXY_HOST}/server`;
export const ENDPOINT = {
ATTACH_SERVICE: {
TUS_UPLOAD: "/attach-service/api/v1/tus/upload",
EDITOR_UPLOAD: "/attach-service/api/v1/upload/editor",
IMAGES: "/attach-service/api/v1/images",
MOVIE_THUMBNAIL: "/attach-service/api/v1/movie/thumbnail",
ATTACHMENTS: "/attach-service/api/v1/atfl/attachments",
DOWNLOAD: "/attach-service/api/v1/atflcd/download",
STREAM_VIDEO: "/attach-service/api/v1/stream/video",
},
USER_SERVICE: {
LOGIN: "/user-service/login",
USERS: "/user-service/api/v1/users",
SILENT_REFRESH: "/user-service/api/v1/users/token/refresh",
AUTHORIZATIONS: "/user-service/api/v1/authorizations",
ROLE_AUTHORIZATIONS: "/user-service/api/v1/role-authorizations",
ROLES: "/user-service/api/v1/roles",
},
CMS_SERVICE: {
SITES: "/cms-service/api/v1/sites",
IPS: "/cms-service/api/v1/site-ips",
DOMAINS: "/cms-service/api/v1/site-dmns",
POSTINGS: "/cms-service/api/v1/site-pstgs",
CODE: "/cms-service/api/v1/code/cache",
MENUS: "/cms-service/api/v1/menus",
MENU_ROLES: "/cms-service/api/v1/menu-roles",
MENU_AUTHRTS: "/cms-service/api/v1/menu-authrts",
CONTENTS: "/cms-service/api/v1/contents",
CONTENTS_DETAILS: "/cms-service/api/v1/contents-details",
ORGANIZATIONS: "/cms-service/api/v1/ognzs",
USER_ORGANIZATION: "/cms-service/api/v1/user-ognz",
IMAGES: "/cms-service/api/v1/images",
BANNERS: "/cms-service/api/v1/bnrs",
TEMPLATE: "/cms-service/api/v1/tmplt",
TERMS: "/cms-service/api/v1/trms",
LWPO_CODE: "/cms-service/api/v1/lwpo-cds",
UP_CODE: "/cms-service/api/v1/up-codes",
POPUPS: "/cms-service/api/v1/popups",
SCHEDULES: "/cms-service/api/v1/schdls",
SURVEY: "/cms-service/api/v1/srvy",
SURVEY_QUESTION: "/cms-service/api/v1/srvy-qitem",
SURVEY_ARTICLE: "/cms-service/api/v1/srvy-artcl",
},
BOARD_SERVICE: {
BBS: "/board-service/api/v1/bbs",
BBS_TEMPLATES: "/board-service/api/v1/bbsTmplt",
POSTS: "/board-service/api/v1/posts",
POSTS_COMMENTS: "/board-service/api/v1/posts-cmnts",
},
};
export const JWT_EXPIRATION_TIME = 1800000;
+14
View File
@@ -0,0 +1,14 @@
export const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "FO";
export const PORT = process.env.NEXT_PUBLIC_PORT || "3000";
export const PROXY_HOST = process.env.NEXT_PUBLIC_PROXY_HOST || `http://localhost:${PORT}`;
export const SERVER_API_WR_URL = process.env.NEXT_PUBLIC_WR_SERVER_API_URL ||'http://con.mind-one.co.kr:11080/api/v1';
export const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL||' http://con.mind-one.co.kr:11082/api/v1';
export const SERVER_API_CS_URL = process.env.NEXT_PUBLIC_CS_SERVER_API_URL||'http://dev.onasys.co.kr:8000';
export const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization";
export const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN || "access-token";
export const REFRESH_TOKEN =process.env.NEXT_PUBLIC_REFRESH_TOKEN || "refresh-token";
export const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id";
export const SERVER_SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL;
+2
View File
@@ -0,0 +1,2 @@
export * from "./api";
export * from "./env";
+31
View File
@@ -0,0 +1,31 @@
import Cookies from "js-cookie";
export function getCookie(name: string): string | undefined {
if (typeof window === "undefined") {
return undefined;
}
return Cookies.get(name);
}
export function setCookie(
name: string,
value: string,
options?: Cookies.CookieAttributes,
): void {
if (typeof window === "undefined") {
return;
}
Cookies.set(name, value, options);
}
export function removeCookie(
name: string,
options?: Cookies.CookieAttributes,
): void {
if (typeof window === "undefined") {
return;
}
Cookies.remove(name, options);
}
+1 -1
View File
@@ -5,7 +5,7 @@ NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver #TODO 운영에서 바꿔야 함
NEXT_PUBLIC_RSONE_DC_URL = https://apigateway.rsonesoft.com #자료관 데이터
NEXT_PUBLIC_DC_URL = https://apigateway.rsonesoft.com #자료관 데이터
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
+1 -1
View File
@@ -5,7 +5,7 @@ NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver
NEXT_PUBLIC_RSONE_DC_URL = https://apigateway.rsonesoft.com #자료관 데이터
NEXT_PUBLIC_DC_URL = https://apigateway.rsonesoft.com #자료관 데이터
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
+7 -3
View File
@@ -1,7 +1,11 @@
NEXT_PUBLIC_SITE_ID = SN
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://sn.hasuon.or.kr
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
NEXT_PUBLIC_PORT = 11302
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302
NEXT_PUBLIC_ADDR_URL = http://con.mind-one.co.kr:11082
NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver
NEXT_PUBLIC_LX_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver_swl
NEXT_PUBLIC_DC_URL = https://apigateway.rsonesoft.com #자료관 데이터
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
@@ -3,7 +3,7 @@ import React from "react";
interface InputSectionProps {
title: string;
data: { year: string; type: string }[];
data: { year: string; type: string, bizNm: string, bizType: string }[];
sectionKey: string;
onInputChange: (section: string, index: number, field: string, value: string) => void;
}
@@ -13,21 +13,26 @@ const InputSection: React.FC<InputSectionProps> = ({ title, data, sectionKey, on
<div>
{/* 섹션 제목 */}
<div className="card-header">
<h3 className="text-2xl mx-3 font-medium text-label">{title}</h3>
<h3 className="text-2xl mx-3 font-medium text-label whitespace-nowrap">{title}</h3>
</div>
{/* 테이블 */}
<div className="card !m-[1.2rem] !p-0r">
<Table variant="secondary" className="w-full">
<TableHeader>
<TableRow>
<TableHead className="border border-gray-300 px-2 py-2 text-sm w-[80px]">년도</TableHead>
<TableHead className="border border-gray-300 px-2 py-2 text-sm w-auto">구분</TableHead>
<TableHead className="border border-gray-300 px-2 py-2 text-sm w-auto whitespace-nowrap">구분</TableHead>
<TableHead className="border border-gray-300 px-2 py-2 text-sm w-[80px] whitespace-nowrap">년도</TableHead>
<TableHead className="border border-gray-300 px-2 py-2 text-sm w-auto whitespace-nowrap">사업명</TableHead>
<TableHead className="border border-gray-300 px-2 py-2 text-sm w-auto whitespace-nowrap">유형</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data.map((row, index) => (
<TableRow key={index}>
<TableCell className="border border-gray-300 px-2 py-2 text-sm w-[80px]">
<TableCell className="border border-gray-300 px-2 py-2 text-sm text-center leading-normal w-auto whitespace-nowrap">
{row.type}
</TableCell>
<TableCell className="border border-gray-300 px-2 py-2 text-sm w-[80px] whitespace-nowrap">
<input
type="text"
value={row.year}
@@ -35,8 +40,11 @@ const InputSection: React.FC<InputSectionProps> = ({ title, data, sectionKey, on
className="w-full text-xl border-radius-0 px-3 py-2 text-base text-center leading-normal"
/>
</TableCell>
<TableCell className="border border-gray-300 px-2 py-2 text-sm text-center leading-normal w-auto">
{row.type}
<TableCell className="border border-gray-300 px-2 py-2 text-sm text-center leading-normal w-auto whitespace-nowrap">
{row.bizNm}
</TableCell>
<TableCell className="border border-gray-300 px-2 py-2 text-sm text-center leading-normal w-auto whitespace-nowrap">
{row.bizType}
</TableCell>
</TableRow>
))}
@@ -49,8 +49,8 @@ export const handleInputChange = (section: string,
value: string,
dataMap: {
[key: string]: {
data: { year: string; type: string }[];
setData: React.Dispatch<React.SetStateAction<{ year: string; type: string }[]>>;
data: { year: string; type: string, bizNm: string, bizType: string }[];
setData: React.Dispatch<React.SetStateAction<{ year: string; type: string, bizNm: string, bizType: string }[]>>;
};
}
) => {
@@ -28,22 +28,17 @@ export const MsSwagePplCol = [
// { id: 'lyrTypeNm', title: '레이어타입명' },
]
export const MsSwagePplCol2 = [
{ id: 'fcltMngNo', title: '시설관리번호' },
{ id: 'instMngNo', title: '기관관리번호' },
{ id: 'fcltMngNo', title: '시설 관리번호' },
{ id: 'instMngNo', title: '기관 관리번호' },
{ id: 'instlYmd', title: '설치일자' },
{ id: 'mapshtNo', title: '도엽번호' },
{ id: 'pdmt', title: '관경(mm)' },
{ id: 'prlg', title: '연장(m)' },
{ id: 'avgGrdn', title: '평균구배(m/m)' },
{ id: 'rnysnFvlc', title: '우기 시 유속(m/s)' },
{ id: 'clarFvlc', title: '건기 시 유속(m/s)' },
{ id: 'drtwMltvArea', title: '오수배수면적(m²)' },
{ id: 'exclnMltvArea', title: '우수배수면적(m²)' },
{ id: 'tmptDpth', title: '시점깊이(m)' },
{ id: 'tmptMhlMngNo', title: '시점맨홀관리번호' },
{ id: 'tmptMhlMngNo', title: '시점맨홀 관리번호' },
{ id: 'scendDpth', title: '종점깊이(m)' },
{ id: 'scendMhlMngNo', title: '종점맨홀관리번호' },
{ id: 'trflnCnt', title: '차선수' },
{ id: 'scendMhlMngNo', title: '종점맨홀 관리번호' },
{ id: 'vrtcLen', title: '세로길이(m)' },
{ id: 'wdthLen', title: '가로길이(m)' },
// { id: 'fcltyShpCd', title: '시설물형태코드' },
@@ -306,35 +301,35 @@ export const SwtrmtFcltCol2 = [
{ id: 'rgnExpln', title: '지역설명' },
{ id: 'cmcnYmd', title: '준공일자' },
{ id: 'oprtngStrtYmd', title: '가동개시일자' },
{ id: 'clsgYmd', title: '폐쇄일자' },
// { id: 'clsgYmd', title: '폐쇄일자' },
// { id: 'prcsMsrcCd', title: '처리공법코드' },
// { id: 'laeCd', title: '지자체코드' },
{ id: 'laeNm', title: '지자체명' },
{ id: 'ctpvNm', title: '시도명' },
{ id: 'sggNm', title: '시군구명' },
// { id: 'ctpvNm', title: '시도명' },
// { id: 'sggNm', title: '시군구명' },
// { id: 'sareaCd', title: '권역코드' },
{ id: 'sareaNm', title: '권역명' },
{ id: 'lrgeSareaNm', title: '대권역명' },
{ id: 'rvrNm', title: '하천명' },
{ id: 'addr', title: '주소' },
{ id: 'dtlAddr', title: '상세주소' },
{ id: 'rdnmAddr', title: '도로명주소' },
{ id: 'dtlRdnmAddr', title: '상세도로명주소' },
// { id: 'addr', title: '주소' },
// { id: 'dtlAddr', title: '상세주소' },
// { id: 'rdnmAddr', title: '도로명주소' },
// { id: 'dtlRdnmAddr', title: '상세도로명주소' },
{ id: 'dschgWtstNm', title: '방류수계명' },
{ id: 'pllnArea', title: '부지면적(m²)' },
{ id: 'mngRprtvBzentyNm', title: '관리대행업제명' },
// { id: 'pllnArea', title: '부지면적(m²)' },
// { id: 'mngRprtvBzentyNm', title: '관리대행업체명' },
{ id: 'swtrmtPpltnCnt', title: '하수처리인구수(인)' },
{ id: 'prcsZoneAreaSum', title: '처리구역면적합계(m²)' },
{ id: 'xcrd', title: 'X좌표' },
{ id: 'ycrd', title: 'Y좌표' },
// { id: 'xcrd', title: 'X좌표' },
// { id: 'ycrd', title: 'Y좌표' },
// { id: 'oprtngSttsCd', title: '가동상태코드' },
{ id: 'rprsMsrcCn', title: '대표공법내용' },
{ 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: '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: 'obsrvnSptCd', title: '관측지점코드' },
];
@@ -3,6 +3,8 @@ import { VerticalTable } from '@/components/ui/verticalTable';
import React, { useState, useEffect } from 'react'
import InputSection from '../InputSection';
import { handleInputChange } from '../common';
import { getData } from "@/components/lib/api";
// import { useBizByFcltStore } from "../../../../store/StoreProvider";
// 하수관로
const inputColumn = [
@@ -15,33 +17,98 @@ const inputColumn = [
{ id: "layCd", title: "매설위치", type: "select", options: ["도로", "하상"] },
];
type operationDataType = { year: string; type: string, bizNm: string, bizType: string };
const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClick?: () => void }) => {
const [repairData, setRepairData] = useState([
{ year: "2025", type: "개대체" },
{ year: "2025", type: "보수" },
]);
const [cleaningData, setCleaningData] = useState([
{ year: "2025", type: "청소" },
{ year: "2025", type: "준설" },
]);
const [inspectionData, setInspectionData] = useState([
{ year: "2025", type: "관로기술진단" },
{ year: "2025", type: "관로기술진단" },
]);
const [formData, setFormData] = useState<any>({});
const [repairData, setRepairData] = useState<operationDataType[]>([]);
const [cleaningData, setCleaningData] = useState<operationDataType[]>([]);
const [inspectionData, setInspectionData] = useState<operationDataType[]>([]);
const dataMap = {
repair: { data: repairData, setData: setRepairData },
cleaning: { data: cleaningData, setData: setCleaningData },
inspection: { data: inspectionData, setData: setInspectionData },
};
const [formData, setFormData] = useState<any>({});
// featureData가 변경될 때 formData 초기화
// const BIZ_SE_CD = useBizByFcltStore(state => state.BIZ_SE_CD);
const BIZ_SE_CD = [
{ lwpoCd: "100", lwpoCdNm: "관로기술진단" },
{ lwpoCd: "200", lwpoCdNm: "개대체" },
{ lwpoCd: "201", lwpoCdNm: "유지보수" },
{ lwpoCd: "203", lwpoCdNm: "청소, 준설" },
{ lwpoCd: "204", lwpoCdNm: "단순보수" },
];
const BIZ_TY_CD = [
{ lwpoCd: "SV", lwpoCdNm: "용역" },
{ lwpoCd: "SF", lwpoCdNm: "자체" },
{ lwpoCd: "SC", lwpoCdNm: "공사" },
];
console.log('BIZ_SE_CD', BIZ_SE_CD);
// 마운트 및 업데이트 시 API 호출
useEffect(() => {
if (featureData) {
setFormData(featureData);
}
}, [featureData]);
const fetchAll = async () => {
const operationData = await getData(`v1/bizInfo/bizByFclt?mngInstCd=${featureData?.mng_inst_cd}&fcltMngNo=${featureData?.fclt_mng_no}&page=0&size=1`);
let inspectionArr: operationDataType[] = [];
let cleaningArr: operationDataType[] = [];
let repairArr: operationDataType[] = [];
if (Array.isArray(operationData)) {
operationData.forEach(item => {
if (!item.flfmt_yr) return;
// biz_se_cd에 해당하는 type명 찾기
const seCodeObj = BIZ_SE_CD.find(code => code.lwpoCd === item.biz_se_cd);
const tyCodeObj = BIZ_TY_CD.find(code => code.lwpoCd === item.biz_ty_cd);
const seTypeName = seCodeObj ? seCodeObj.lwpoCdNm : "";
const tyTypeName = tyCodeObj ? tyCodeObj.lwpoCdNm : "";
switch (item.biz_se_cd) {
case "100":
inspectionArr.push({
year: String(item.flfmt_yr),
type: seTypeName,
bizNm: String(item.biz_nm),
bizType: tyTypeName,
});
break;
case "203":
cleaningArr.push({
year: String(item.flfmt_yr),
type: seTypeName,
bizNm: String(item.biz_nm),
bizType: tyTypeName,
});
break;
case "200":
case "201":
case "204":
repairArr.push({
year: String(item.flfmt_yr),
type: seTypeName,
bizNm: String(item.biz_nm),
bizType: tyTypeName,
});
break;
}
});
}
setInspectionData(inspectionArr);
setCleaningData(cleaningArr);
setRepairData(repairArr);
console.log('inspectionArr', inspectionArr);
console.log('cleaningArr', cleaningArr);
console.log('repairArr', repairArr);
};
fetchAll();
}, []);
// 폼 데이터가 변경될 때 호출될 핸들러
const handleFormDataChange = (newFormData: any) => {
@@ -56,6 +123,18 @@ const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClic
}
};
// 변환 함수: 객체 → [{ year, type }]
// function convertToYearTypeArray(obj: any): { year: string, type: string }[] {
// if (!obj || typeof obj !== "object") return [];
// // 이미 배열이면 그대로 반환
// if (Array.isArray(obj)) return obj;
// // 객체의 각 key를 type, value를 year로 변환
// return Object.entries(obj).map(([type, year]) => ({
// year: String(year ?? ""),
// type: String(type ?? ""),
// }));
// }
return (
<>
@@ -8,7 +8,7 @@ import { getData } from "@/components/lib/api";
import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue';
const inputColumn = [
{ id: "prrtymngYn", title: "중점여부", type: "select", options: ["중점우수토실", "우수토실"] },
{ id: "prrtymngYn", title: "중점여부", type: "select", options: ["우수토실", "중점우수토실"] },
{ id: "swtrmtZoneCd", title: "처리구역", type: "input" },
];
@@ -152,7 +152,7 @@ const InfilChart = ({ pplMngNo }: ModalOpenProp) => {
<div className="bg-white px-4 py-2 ">
<span className="text-2xl text-red-600 font-bold">● 상수사용량 적용연월</span>
<div className="flex items-center mt-2">
<span className="text-black text-xl font-bold">
<span className="ml-5 text-black text-xl font-bold">
{(selectedAplcnYm) ? moment(selectedAplcnYm, "YYYYMM").format("YYYY-MM") : ""}
</span>
</div>
@@ -161,7 +161,7 @@ const InfilChart = ({ pplMngNo }: ModalOpenProp) => {
<div className="bg-white px-4 py-2 ">
<span className="text-2xl text-red-600 font-bold">● 침입수량 산정결과</span>
<div className="flex items-center mt-2">
<span className="ml-2 text-black text-xl">침입수량 : </span>
<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="ml-2 text-black text-xl">m³/d</span>
</div>
@@ -129,7 +129,7 @@ const RdiiChart = ({ pplMngNo }: ModalOpenProp) => {
<div className="bg-white px-4 py-2 ">
<span className="text-2xl text-red-600 font-bold">● 상수사용량 적용연월</span>
<div className="flex items-center mt-2">
<span className="text-black text-xl font-bold">
<span className="ml-5 text-black text-xl font-bold">
{(aplcnYm)? moment(aplcnYm, "YYYYMM").format("YYYY-MM"):""}
</span>
</div>
@@ -139,12 +139,12 @@ const RdiiChart = ({ pplMngNo }: ModalOpenProp) => {
<div className="bg-white px-4 py-2 ">
<span className="text-2xl text-red-600 font-bold">● 강우유입수량 분석결과</span>
<div className="flex items-center mt-2">
<span className="w-[90px] inline-block text-right ml-2 text-black text-xl">평균RDII : </span>
<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="ml-2 text-black"> m³/d</span>
</div>
<div className="flex items-center mt-2">
<span className="w-[90px] inline-block text-right ml-2 text-black text-xl">강우량대비RDII : </span>
<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="ml-2 text-black"> m³/mm</span>
</div>
@@ -110,7 +110,8 @@ export const addFileName = async (data:FlattenedFolder[]) => {
data.map(async (item) => {
const filenameArr:ReportDataFile[] = await getDcFile(String(item.clsfSystmSn));
const f = filenameArr[0];
const result = {...item, fileName:f?.fileTitle, regDate:f?.regDt, fileSn:f?.fileSn, filePath:""};
//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)
@@ -149,11 +150,12 @@ export const fileDownload = (data:Blob, fileName:string) => { // Blob데이터
link.remove();
window.URL.revokeObjectURL(url);
}
export const getFileDownload = async (fileSn:string, fileName:string) => {
const fileprcsData = await getDcFileprcs(fileSn); // filePath 조회
if (fileprcsData?.length === 0 ) { alert("filePath 조회 오류"); }
if (fileprcsData[0].filePath === "") alert("filePath 정보 없으므로 다운로드 불가");
const blobData = await getDcFileDownload(fileprcsData[0].filePath); // 실제 다운로드 API
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);
}
// 시도 데이터
@@ -6,7 +6,7 @@ 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, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, ExclnSewagePumpCol, MsSwageMhlCol, stofcbrCol, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table";
import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol1, 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";
@@ -33,6 +33,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
const { setIsOpen: setIsModalInfil } = useInfilChartModalStore();
const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore();
const [curPage, setCurPage] = useState(1); // 현재 페이지 상태
const [isClicked, setIsClicked] = useState(true); // 클릭 여부 상태
// 🎯 관로관리번호 추출
const pplMngNo = featureData?.values_?.fclt_mng_no || "";
@@ -66,8 +67,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
}
});
// console.log("featureLayer.get('lyrTyNm');", featureLayer.get('lyrTyNm'));
// SearchModal 클릭 이벤트와 Gis 클릭 이벤트 구분하기
// SearchModal 클릭 이벤트
if (featureLayer.get('lyrNm') === null) {
setIsClicked(false);
if (featureData.lyrTypeNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설';
else if (featureData.lyrTypeNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역';
else if (featureData.lyrTypeNm === 'tb_ms_stofcbr') result = '우수토실';
@@ -77,15 +79,17 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장');
console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val);
if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) {
setIsDrtwSewagePump(true);
} else {
setIsDrtwSewagePump(false);
} else {
setIsDrtwSewagePump(true);
}
result = '하수펌프장';
}
else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') result = '하수맨홀';
}
else {
// Gis 레이어 클릭 이벤트
setIsClicked(true);
const lyrTyNm = featureLayer.get('lyrTyNm');
if (lyrTyNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설';
else if (lyrTyNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역';
@@ -96,9 +100,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장');
console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val);
if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) {
setIsDrtwSewagePump(true);
} else {
setIsDrtwSewagePump(false);
} else {
setIsDrtwSewagePump(true);
}
result = '하수펌프장';
}
@@ -135,15 +139,16 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
// 🎯 기본 데이터 포맷팅
const formattedData = formatDisplayData(data);
if (featureData.values_.fclt_mng_no) setLayerSpecificNm(featureData.values_.fclt_mng_no);
else if (featureData.values_.swtrmt_fclt_cd) setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd);
else setLayerSpecificNm(featureData.values_.manage_no);
if (featureData?.values_?.fclt_mng_no) setLayerSpecificNm(featureData.values_.fclt_mng_no);
else if (featureData?.values_?.swtrmt_fclt_cd) setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd);
else setLayerSpecificNm(featureData?.values_?.manage_no);
setFetchData(formattedData);
setTableData(formattedData);
switch (selectedLayerName) {
case '하수관로':
setHeadlist(MsSwagePplCol)
if (isClicked) setHeadlist(MsSwagePplCol)
else setHeadlist(MsSwagePplCol2)
setButtonChk(true)
// ✅ codeMapper 사용하여 API 결과도 변환
@@ -155,7 +160,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
// setTableData(mappedData);
break;
case '하수맨홀':
setHeadlist(MsSwageMhlCol)
if (isClicked) setHeadlist(MsSwageMhlCol)
else setHeadlist(MsSwageMhlCol2)
setButtonChk(true)
// ✅ codeMapper 사용하여 API 결과도 변환
@@ -167,10 +173,17 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
// setTableData(mappedData);
break;
case '하수펌프장':
setHeadlist(ExclnSewagePumpCol)
if (isDrtwSewagePump) {
if (isClicked) setHeadlist(DrtwSewagePumpCol1)
else setHeadlist(DrtwSewagePumpCol2)
} else {
if (isClicked) setHeadlist(ExclnSewagePumpCol)
else setHeadlist(ExclnSewagePumpCol2)
}
setButtonChk(true)
setTableData(codeMapper({
setTableData(codeMapper({
layerName: selectedLayerName,
data: { ...formattedData }
}));
@@ -178,15 +191,18 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
// setTableData(mappedData);
break;
case '하수처리시설':
setHeadlist(SwtrmtFcltCol);
if (isClicked) setHeadlist(SwtrmtFcltCol)
else setHeadlist(SwtrmtFcltCol2)
setButtonChk(false)
break;
case '하수처리구역':
setHeadlist(SwtrmtPrcsZoneCol)
if (isClicked) setHeadlist(SwtrmtPrcsZoneCol)
else setHeadlist(SwtrmtPrcsZoneCol2)
setButtonChk(false)
break;
case '우수토실':
setHeadlist(stofcbrCol)
if (isClicked) setHeadlist(stofcbrCol)
else setHeadlist(stofcbrCol2)
setButtonChk(true)
setIsMainSsc(false)
break;
@@ -477,7 +493,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
<Modal isModalOpen={isModalOpen} title="자체입력정보 저장" setIsModalOpen={setIsModalOpen} closeModal={handleModalClose} saveModal={handleModalSave}><div className="text-lg">정보를 저장하시겠습니까?</div></Modal>
{ContentComponent &&
<ContentComponent
featureData={tableData}
featureData={fetchData}
isMainSsc={isMainSsc}
isDrtwSewagePump={isDrtwSewagePump}
rainMeasureData={rainMeasureData}
+17 -17
View File
@@ -4,7 +4,7 @@ import Gis, { useGisContext } from "@common/business_components/ui/map/Gis";
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";
import SearchModal from "./searchModal/searchModal";
import FeatureClickEventPopup from "./featureClickEventPopup";
// 타입 정의 추가
@@ -115,22 +115,22 @@ const Map = () => {
};
return (
<div className="bg-container">
<Gis
treeData={treeData}
isSearch={true}
gisMaps={gisMaps}
isMiniMap={false}
searchView={SearchModal}
detailView={FeatureClickEventPopup}
onFeatureSelect={onFeatureSelect}
setIsOpen={setIsOpen}
setFeatureData={setFeatureData}
featureData={featureData}
setIsSearchModalOpen={setIsSearchModalOpen}
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={undefined}
/>
<Gis
treeData={treeData}
isSearch={true}
gisMaps={gisMaps}
isMiniMap={false}
searchView={SearchModal}
detailView={FeatureClickEventPopup}
onFeatureSelect={onFeatureSelect}
setIsOpen={setIsOpen}
setFeatureData={setFeatureData}
featureData={featureData}
setIsSearchModalOpen={setIsSearchModalOpen}
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={undefined}
/>
</div>
);
};
@@ -219,7 +219,7 @@ const BaseLayout = ({
<div className="flex items-center w-full">
{showDatePicker && ( // showDatePicker 값에 따라 DatePicker 렌더링
<>
<Label className="ml-4 w-20 text-xl text-gray-600 whitespace-nowrap">분석기간</Label>
<Label className="ml-4 w-20 text-xl text-gray-600 whitespace-nowrap">상수사용기간</Label>
<DateMonthPicker
field={{
value: aplcnYmFrom || (() => { // aplcnYm이 없으면 현재 연월을 기본값으로 설정
+41 -30
View File
@@ -1,5 +1,18 @@
import {useState, useEffect} from 'react';
const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
import { useEffect, useState } from "react";
const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || '';
export const getData = async (url: string, data?: object): Promise<any> => {
const res = await fetch(url.startsWith('/') ? `${url}` : `${BASE_URL}/${url}`, {
method: "GET",
body: JSON.stringify(data),
});
if (res.ok) {
const data = await res.json();
return data;
}
throw new Error('Failed to fetch data');
};
export const postData = async (url: string, data: object): Promise<any> => {
const options: RequestInit = {
@@ -15,11 +28,6 @@ export const postData = async (url: string, data: object): Promise<any> => {
if (res.ok) {
const resData = await res.json();
return resData;
// const text = await res.text();
// if (text) {
// return JSON.parse(text); // JSON 데이터가 있으면 파싱하여 반환
// }
// return true; // 응답 본문이 비어 있으면 true 반환
}
};
@@ -46,29 +54,6 @@ export const putData = async (url: string, data: object): Promise<any> => {
return resData;
};
export const getData = async (url: string, data?: object): Promise<any> => {
const res = await fetch(url.startsWith('/') ? `${url}` : `${BASE_URL}/${url}`, {
method: "GET",
});
if (res.ok) {
const data = await res.json();
return data;
}
throw new Error('Failed to fetch data');
};
export const getDcData = async (url: string, data?: object): Promise<any> => {
console.log(url);
const res = await fetch('/dc-service'+url, {
method: "GET",
});
if (res.ok) {
const data = await res.json();
return data;
}
throw new Error('Failed to fetch data');
};
export const deleteData = async (url: string, data?: object): Promise<any> => {
const options: RequestInit = {
method: "DELETE",
@@ -82,6 +67,32 @@ export const deleteData = async (url: string, data?: object): Promise<any> => {
return res;
};
// RSONE DC API 호출
export const getDcData = async (url: string, data?: object): Promise<any> => {
console.log(url);
const res = await fetch('/dc-service' + url, {
method: "GET",
});
if (res.ok) {
const data = await res.json();
return data;
}
throw new Error('Failed to fetch data');
};
// RSONE DC API 호출
export const getCmsData = async (url: string, data?: object): Promise<any> => {
console.log(url);
const res = await fetch('/cms-service' + 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]) {
@@ -90,7 +90,7 @@ export function YearRangeSelectBox({
return (
<div className={`flex items-center ${className}`}>
<SelectBox2
className="flex-1 mr-3 min-w-[120px] max-w-[170px]"
className="flex-1 mr-3"
selectClass={selectClass}
label={startLabel}
selectArray={getStartYearArray()}
@@ -99,7 +99,7 @@ export function YearRangeSelectBox({
/>
<span className="font-semibold text-xl mx-2">~</span>
<SelectBox2
className="flex-1 ml-1 mr-6 min-w-[70px] max-w-[150px]"
className="flex-1 ml-1"
selectClass={selectClass}
label={endLabel}
selectArray={getEndYearArray()}
+2 -2
View File
@@ -7,7 +7,7 @@ const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || "";
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
const RSONE_DC_URL = process.env.NEXT_PUBLIC_RSONE_DC_URL || "";
const DC_URL = process.env.NEXT_PUBLIC_DC_URL || "";
export function middleware(req: NextRequest) {
console.log("Middleware 진입:", req.nextUrl.pathname);
@@ -106,7 +106,7 @@ export function middleware(req: NextRequest) {
.map(([key, value]) => `${key}=${decodeURIComponent(value)}`)
.join("&");
const newUrl = `${RSONE_DC_URL}${pathname}${decodedParams ? `?${decodedParams}` : ""}`;
const newUrl = `${DC_URL}${pathname}${decodedParams ? `?${decodedParams}` : ""}`;
console.log(
`[Middleware] Rewriting from '/dc-service' path to: ${newUrl}`,
);
+24
View File
@@ -0,0 +1,24 @@
"use client"
import { BaseLayout } from "@common/components/ui"
import { useWrStore } from "./store"
import { MainDiv } from "@common/business_components/ui"
import type { MenuItem } from "./store/common/type/menu"
import { useRouter } from "next/navigation"
export default function Base({
children,
}: Readonly<{
children: React.ReactNode
}>) {
const { getMenuAuthrts } = useWrStore((state) => state)
const router = useRouter()
const changeMenu = (path: MenuItem) => {
getMenuAuthrts(path.menuCd)
router.push(path.urlPath)
}
return (
<BaseLayout handleMenuClick={changeMenu}>
<MainDiv>{children}</MainDiv>
</BaseLayout>
)
}
+11 -21
View File
@@ -1,12 +1,10 @@
'use client'
import { BaseLayout } from "@common/components";
"use client";
import "./globals.css";
import { StoreProvider } from "./store";
import { MainDiv } from "@common/business_components";
import koBase from '../public/locales/ko/message.json';
import { StoreProvider} from "./store";
import koBase from "../public/locales/ko/message.json";
import i18next from "i18next";
import { I18nextProvider } from "react-i18next";
import { useRouter } from "next/navigation";
import Base from "./base";
export default function RootLayout({
children,
@@ -14,34 +12,26 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
i18next.init({
lng: 'ko',
fallbackLng: 'ko',
lng: "ko",
fallbackLng: "ko",
resources: {
ko: {
base: koBase,
},
}
},
});
const router = useRouter();
return (
<html lang="en">
<body>
<I18nextProvider i18n={i18next}>
<StoreProvider>
<BaseLayout
handleMenuClick={(e) =>{
router.push(e.urlPath)
}}
>
<MainDiv>
{children}
</MainDiv>
</BaseLayout>
<Base>
{children}
</Base>
</StoreProvider>
</I18nextProvider>
</body>
</html >
</html>
);
}
+418 -411
View File
@@ -41,9 +41,11 @@ import toast, { Toaster } from "react-hot-toast";
import { z } from "zod";
export default function CoMatRvw() {
const { code, coRvw, coMatRvwInit, coMatRvwSearch, coMatRvwInqua } =
const { auth, code, coRvw, coMatRvwInit, coMatRvwSearch, coMatRvwInqua } =
useWrStore((state) => state);
const { coMatRvwRes,coMatRvwCount } = coRvw;
const { coMatRvwRes, coMatRvwCount } = coRvw;
const { regAuthrtYn } = auth;
//init, sub, match
const initRef = useRef<boolean>(false);
const { coRvwHeadList } = coRvw;
@@ -91,10 +93,9 @@ export default function CoMatRvw() {
const form = useForm<z.infer<typeof DmdCoReqSchema>>({
resolver: zodResolver(DmdCoReqSchema),
shouldUnregister: false,
// defaultValues: DmdCoReqSchema.parse({})
// defaultValues: DmdCoReqSchema.parse({})
});
const TableCellClick = (index: number) => {
if (coMatRvwRes && coMatRvwRes[index]) {
setSelectData(coMatRvwRes[index]);
@@ -103,23 +104,21 @@ export default function CoMatRvw() {
};
const useUsgCdWatch = useWatch({ control: form.control, name: "useUsgCd" });
useEffect(() => {
if (useUsgCdWatch) {
form.setValue(
"demandCst.usgPrcsProcs",
usageProcData?.find(
(item) => item.usage === useUsgCdWatch
)?.process ?? ""
usageProcData?.find((item) => item.usage === useUsgCdWatch)?.process ??
""
);
}
}, [useUsgCdWatch, form,selectionVersion]);
}, [useUsgCdWatch, form, selectionVersion]);
useEffect(() => {
if (coMatRvwRes&&coMatRvwRes.length > 0) {
if (coMatRvwRes && coMatRvwRes.length > 0) {
const data = coMatRvwRes?.map((item) => {
let flag = "";
flag = getdmdMatFlag(item?.demandMatching?.splyFcltFlg ||undefined);
flag = getdmdMatFlag(item?.demandMatching?.splyFcltFlg || undefined);
return {
...item,
@@ -127,7 +126,7 @@ export default function CoMatRvw() {
sggCd: item.demandCo?.sggCd,
dmdCoNm: item.demandCo?.dmdCoNm,
daddr: item.demandCo?.daddr,
telno: formatPhoneNumber(item?.demandCo?.telno||''),
telno: formatPhoneNumber(item?.demandCo?.telno || ""),
dmndTmng: item?.dmndTmng,
splyFcltFlg: flag,
};
@@ -156,7 +155,6 @@ export default function CoMatRvw() {
useEffect(() => {
if (selectData) {
try {
DmdCoReqSchema.parse(selectData);
} catch (e) {
@@ -164,15 +162,14 @@ export default function CoMatRvw() {
console.log(e.flatten());
}
}
form.reset( selectData);
setSelectionVersion((v) => v + 1); // 강제로 바뀌었다고 알리기
form.reset(selectData);
setSelectionVersion((v) => v + 1); // 강제로 바뀌었다고 알리기
}
}, [selectData, form]);
return (
<>
<ContentsDiv>
<div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Title title={"수요매칭검토"} />
<SearchDiv>
@@ -195,7 +192,7 @@ export default function CoMatRvw() {
<div className="col-span-7 w-full">
<div className="flex flex-row items-center">
<Label className="text-xl text-gray-600 mx-6">
수요신청년도
수요신청년도
</Label>
<SelectBox
className="h-full w-32 text-2xl"
@@ -248,7 +245,10 @@ export default function CoMatRvw() {
if (String(objSearch.city).length > 0) {
con = String(objSearch.city);
}
if (String(objSearch.sgg).length > 0 && String(objSearch.sgg) !== "0") {
if (
String(objSearch.sgg).length > 0 &&
String(objSearch.sgg) !== "0"
) {
con = String(objSearch.sgg);
}
getSearch(fromNum, toNum, con, dmdCoNm);
@@ -279,403 +279,410 @@ export default function CoMatRvw() {
TableCellClick(index);
}
}}
onPageChange={(val) => {setPageNatiion(val)}}
onPageChange={(val) => {
setPageNatiion(val);
}}
></UiTable>
</ListDiv>
<hr />
{/* <ScrollArea className="h-[49vh]"> */}
<ListDiv>
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
수요신청 상세현황
</h3>
<Form {...form}>
<div className="grid grid-cols-12 gap-4 ml-4 mr-4">
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndTmng"
render={({ field }) => (
<FormUi label="요구시기">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={
moment(field.value).format("YYYY-MM-DD") ?? ""
}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndQty"
render={({ field }) => (
<FormUi label="요구수량(M3/d)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="useUsgCd"
render={({ field }) => (
<FormUi label="사용용도">
<Input
placeholder=""
type="text"
step="0.1"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="wntUntprc"
render={({ field }) => (
<FormUi label="희망단가(원/m3)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>요구수질</h1>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="smll"
render={({ field }) => (
<FormUi label="냄새">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="rmrk"
render={({ field }) => (
<FormUi label="비고">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>공급처 후보지</h1>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${0}`}
render={({ field }) => (
<FormUi label="후보지1">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${1}`}
render={({ field }) => (
<FormUi label="후보지2">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${2}`}
render={({ field }) => (
<FormUi label="후보지3">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<ListDiv>
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
수요신청 상세현황
</h3>
<Form {...form}>
<div className="grid grid-cols-12 gap-4 ml-4 mr-4">
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndTmng"
render={({ field }) => (
<FormUi label="요구시기">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={
moment(field.value).format("YYYY-MM-DD") ?? ""
}
readOnly
/>
</FormUi>
)}
/>
</div>
</Form>
<ConCostForm form={form} type={"mat"} selectionVersion={selectionVersion} />
</ListDiv>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="dmndQty"
render={({ field }) => (
<FormUi label="요구수량(m³/일)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="useUsgCd"
render={({ field }) => (
<FormUi label="사용용도">
<Input
placeholder=""
type="text"
step="0.1"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="wntUntprc"
render={({ field }) => (
<FormUi label="희망단가(원/m3)">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>요구수질</h1>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="smll"
render={({ field }) => (
<FormUi label="냄새">
<Input
placeholder=""
type="number"
step="0.1"
onChange={(e) => {
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 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
/>
</FormUi>
)}
/>
</div>
<div className="col-span-3 mt-4">
<FormField
control={form.control}
name="rmrk"
render={({ field }) => (
<FormUi label="비고">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-12 w-full">
<h1 className={formH1Class}>공급처 후보지</h1>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${0}`}
render={({ field }) => (
<FormUi label="후보지1">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${1}`}
render={({ field }) => (
<FormUi label="후보지2">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
<div className="col-span-4 mt-4">
<FormField
control={form.control}
name={`demandMatching.splyCndtList.${2}`}
render={({ field }) => (
<FormUi label="후보지3">
<Input
placeholder=""
type="text"
onChange={(e) => {
field.onChange(e.target.value);
}}
value={field.value ?? ""}
readOnly
/>
</FormUi>
)}
/>
</div>
</div>
</Form>
<ConCostForm
form={form}
type={"mat"}
selectionVersion={selectionVersion}
readonly={regAuthrtYn ==="N"}
/>
</ListDiv>
{/* </ScrollArea> */}
</div>
</div>
+60 -56
View File
@@ -1,12 +1,9 @@
"use client";
import { useWrStore } from "@/app/store";
import { type RvwHistTableType } from "@/app/store/matDmd/coMatRvw/type";
import {
DmdCoReqSchema,
type DmdCoReqType,
type RvwHistTableType,
} from "@/app/store/matDmd/coMatRvw/type";
import {
confirmToast,
formatPhoneNumber,
getCity,
getdmdMatFlag,
@@ -27,13 +24,13 @@ import {
} from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Button, Label } from "@common/components/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import moment from "moment";
import { useCallback, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function RuseRvwHstry() {
const {
auth,
code,
ruseHist,
ruseRvwHistInit,
@@ -42,6 +39,8 @@ export default function RuseRvwHstry() {
ruseRvwComplete,
} = useWrStore((state) => state);
const { rvwHistRes, ruseHistHeadList, rvwHistCount } = ruseHist;
const { regAuthrtYn } = auth;
const [pageNation, setPageNatiion] = useState<number>(1);
const [dmdCoNm, setDmdCoNm] = useState<string>("");
@@ -51,6 +50,7 @@ export default function RuseRvwHstry() {
sgg: "",
city: "",
});
const { t } = useTranslation('base');
const [fromDate, setFromDate] = useState<string>(
String(new Date().getFullYear())
@@ -116,53 +116,65 @@ export default function RuseRvwHstry() {
}
};
const form = useForm<DmdCoReqType>({
resolver: zodResolver(DmdCoReqSchema),
mode: "onChange",
});
const TableCellClick = useCallback(
(index: number | undefined) => {
if (
index !== undefined &&
index >= 0 &&
rvwHistRes &&
rvwHistRes[index]
) {
form.reset(rvwHistRes[index]);
(index: number | undefined, headId: string) => {
if (index !== undefined && index >= 0) {
const selectedData = rvwHistData;
if (selectedData && selectedData.length > 0) {
if (
selectedData[index]?.splyFcltFlg === "검토완료" &&
headId === "completeYn"
) {
setRvwHistData([...selectedData]);
} else if (
selectedData[index]?.splyFcltFlg === "매칭완료" &&
headId === "completeYn"
) {
toast.error(t("canNotChangeMatStateMsg"));
return;
}
}
}
},
[rvwHistRes, form]
[rvwHistData]
);
const confrirmToast = () => {
const completeData = rvwHistData
?.map((item) => {
form.clearErrors();
if (item?.completeYn) {
if (item?.completeYn.chk && item.splyFcltFlg === "검토완료") {
return Number(item.dmdInfoSn);
}
})
.filter((item) => item !== undefined);
if (form.formState.isDirty) {
toast((t) => (
<span className="flex flex-col items-center">
표준공사비 정보가 변경되었습니다. 검토 완료 진행시 입력한 정보는
초기화 됩니다.
<br />
진행하시겠습니까?
<button
onClick={() => {
toast.dismiss(t.id);
ruseRvwComplete(completeData as number[]);
}}
>
확인
</button>
<button onClick={() => toast.dismiss(t.id)}>취소</button>
</span>
));
if (completeData && completeData?.length > 0) {
confirmToast(t('isMatchFinishMsg'), () => ruseRvwComplete(completeData as number[]));
// const handleConfirm = async () => {
// ruseRvwComplete(completeData as number[]);
// };
// toast((t) => (
// <span className="flex flex-col items-center">
// 매칭완료를 진행하시겠습니까?
// <br />
// <div className="mt-2 flex flex-row space-x-2">
// <Button
// size={"sm"}
// onClick={() => {
// toast.dismiss(t.id);
// ruseRvwComplete(completeData as number[]);
// }}
// >
// 확인
// </Button>
// <Button size={"sm"} onClick={() => toast.dismiss(t.id)}>
// 취소
// </Button>
// </div>
// </span>
// ));
} else {
ruseRvwComplete(completeData as number[]);
toast.error( t('isNotMatchFinishMsg'));
}
};
useEffect(() => {
@@ -203,11 +215,10 @@ export default function RuseRvwHstry() {
rvwCmptnYmd: formatDate(item.demandMatching?.rvwCmptnYmd),
mtchnCmptnYmd: formatDate(item.demandMatching?.mtchnCmptnYmd),
ruseUtztnFcltNm: item.ruseUtztnFcltNm,
dmndQty: item.dmndQty,
splyFcltFlg: flag,
completeYn: false,
completeYn: {chk:flag=="매칭완료", readonly:flag=="매칭완료"},
} as unknown as RvwHistTableType;
});
@@ -215,9 +226,6 @@ export default function RuseRvwHstry() {
}
}, [rvwHistRes]);
useEffect(() => {
console.log("변경여부 ", form.formState.isDirty);
}, [form.formState]);
return (
<ContentsDiv>
@@ -300,8 +308,8 @@ export default function RuseRvwHstry() {
>
조회
</Button>
<Button size={"sm"} onClick={confrirmToast}>
검토완료
<Button size={"sm"} onClick={confrirmToast} disabled={regAuthrtYn==='N'}>
저장
</Button>
</div>
</div>
@@ -319,18 +327,14 @@ export default function RuseRvwHstry() {
headlist={ruseHistHeadList}
pageSize={20}
total={rvwHistCount}
cellClick={(index: number | undefined) => {
TableCellClick(index);
cellClick={(index: number | undefined, headId: string) => {
console.log("테이블 클릭", index);
TableCellClick(index, headId);
}}
onPageChange={(page) => {
setPageNatiion(page);
}}
></UiTable>
{/* <hr />
<h3 className="mt-4 ml-2 text-2xl font-medium text-label">
수요신청 상세현황
</h3>
<ConCostForm form={form} type={"hist"} selectionVersion={0} /> */}
</ListDiv>
</div>
</div>
+7 -1
View File
@@ -33,6 +33,7 @@ import toast, { Toaster } from "react-hot-toast";
export default function CoSttn() {
const {
auth,
code,
coSttn,
coSttnInit,
@@ -43,6 +44,7 @@ export default function CoSttn() {
coSttnTxtSearch,
demandCompList,
} = useWrStore((state) => state);
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const [bdstTable, setBdstTable] = useState<DemandCompType[]>();
const [pageNation, setPageNation] = useState(1);
@@ -101,7 +103,9 @@ export default function CoSttn() {
...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)}`
}));
console.log("chData:", chData)
// .filter((item: any) => item !== undefined);
setBdstTable(chData);
} else if (coSttnRes?.length == 0) {
@@ -203,6 +207,7 @@ export default function CoSttn() {
setUpdateData(undefined);
setIsDmdModal({ ...isDmdModal, isMoal: true });
}}
disabled={regAuthrtYn === "N"}
>
등록
</Button>
@@ -220,6 +225,7 @@ export default function CoSttn() {
});
}
}}
disabled={mdfcnAuthrtYn === "N"}
>
수정
</Button>
+26 -28
View File
@@ -43,8 +43,9 @@ export default function LdrmntCoSttn() {
const [objSearch, setObjSearch] = useState<objSearchType>({ sgg: "", city: "" });
const [bdstTable, setBdstTable] = useState<customLdrmnt[]>();
const [searchTxt, setSearchTxt] = useState<string>();
const [excelData, setExcelData] = useState<any[]>();
const [excelData, setExcelData] = useState<any[] | undefined>()
const [resetPage, isResetPage] = useState(false);
const [isDownloadClicked, setIsDownloadClicked] = useState(false);
const { t } = useTranslation('base');
const excelClick = useCallback(() => {
@@ -79,10 +80,31 @@ export default function LdrmntCoSttn() {
const excelDownloadClick = useCallback(() => {
const cityNm = computeCityNm();
setExcelData(undefined);
setIsDownloadClicked(true);
ldrmntSearch(true, 1, String(ldrmntResCount), cityNm, searchTxt || "");
}, [objSearch, searchTxt, code, ldrmntSearch, computeCityNm, ldrmntResCount]);
useEffect(() => {
const transData = Array.isArray(excelList) ? excelList : [excelList];
const exData = tableData(transData, { code });
const data = Array.isArray(exData)
? exData.map((item: customLdrmnt) => {
return {
"시도": item.fctryAddr?.split(" ")[0] || "",
"시군구": item.fctryAddr?.split(" ")[1] || "",
"회사명": item.dmdCoNm,
"공장주소": item.fctryAddr,
"공장관리번호": item.fctryMngNo,
"전화번호": item.telno
}
}) : [];
setExcelData(data)
}, [excelList])
useEffect(() => {
if (!isDownloadClicked) return;
if (excelData === undefined) return;
if (excelData && excelData.length > 0) {
downloadExcel({
data: excelData,
@@ -93,7 +115,8 @@ export default function LdrmntCoSttn() {
} else {
toast.error(t('excelDownErrMsg'));
}
}, [excelData]);
setIsDownloadClicked(false);
}, [excelData, isDownloadClicked]);
const [isExcelOpen, setIsExcelOpen] = useState<{
isModal: boolean;
@@ -125,7 +148,7 @@ export default function LdrmntCoSttn() {
useEffect(() => {
if (!ldrmnt.isInit) {
ldrmntInit("0");
ldrmntInit(false, "0");
}
}, [ldrmnt.isInit, ldrmntInit]);
@@ -144,23 +167,6 @@ export default function LdrmntCoSttn() {
setBdstTable(tbData);
}, [ldrmntRes, code]);
useEffect(() => {
const transData = Array.isArray(excelList) ? excelList : [excelList];
const exData = tableData(transData, { code });
const data = Array.isArray(exData)
? exData.map((item: customLdrmnt) => {
return {
"시도": item.fctryAddr?.split(" ")[0] || "",
"시군구": item.fctryAddr?.split(" ")[1] || "",
"회사명": item.dmdCoNm,
"공장주소": item.fctryAddr,
"공장관리번호": item.fctryMngNo,
"전화번호": item.telno
}
}) : [];
setExcelData(data)
}, [excelList])
useEffect(() => {
ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || "");
isResetPage(false)
@@ -264,10 +270,6 @@ export default function LdrmntCoSttn() {
}}
bodyClass={"w-[40vw] max-w-none max-h-[calc(100%-70px)]"}
body={<CoDetailModal formObj={detailModal.data} onFormSubmit={async (value) => {
// confirmToast(t('isUpdateMsg'), await ldrmntUpdate(value))
// // await ldrmntUpdate(value)
// setDetailModal({ ...detailModal, isOpen: false })
// ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || "");
const handleConfirm = async () => {
await ldrmntUpdate(value);
setDetailModal({ ...detailModal, isOpen: false });
@@ -286,12 +288,8 @@ export default function LdrmntCoSttn() {
body={<CoRegExcel isModal={(isOpen) => setIsExcelOpen({ isModal: isOpen })} />}
/>
<Toaster position="top-center"></Toaster>
</div>
</ContentsDiv>
</>
)
}
@@ -21,7 +21,7 @@ import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
export default function Home() {
const { code, htdfl, initHtdflReg, getHtdflBdstData, htdflNmSearch } =
const { auth,code, htdfl, initHtdflReg, getHtdflBdstData, htdflNmSearch } =
useWrStore((state) => state);
const [searchTxt, setSearchTxt] = useState("");
const [pageNation, setPageNation] = useState(1);
@@ -30,12 +30,9 @@ export default function Home() {
const [bdstTable, setbdstTable] = useState<customHtdflBdst[]>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
// const [bdstChgProps, setBdstChgProps] = useState<{
// isOpen: boolean;
// chgBuilding: chgBuilding[];
// }>({ isOpen: false, chgBuilding: [] });
const { htdflRes ,htdflResCount} = htdfl;
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
useEffect(() => {
if (!htdfl.isInit) {
@@ -116,7 +113,10 @@ export default function Home() {
>
조회
</Button>
<Button size={"sm"} onClick={() => setIsNewReg(!issNewReg)}>
<Button size={"sm"}
onClick={() => setIsNewReg(!issNewReg)}
disabled={regAuthrtYn === "N"}
>
신규등록
</Button>
</div>
@@ -149,6 +149,7 @@ export default function Home() {
<HtdflRegForm
htdflForm={htdflForm ?? ({} as customHtdflBdst)}
isModal={false}
readonly={mdfcnAuthrtYn === "N"}
/>
</ScrollArea>
</ListDiv>
@@ -38,6 +38,7 @@ import { useTranslation } from "react-i18next";
export default function PublicReuseFaciltyInsert() {
const {
auth,
code,
pbnst,
pubHasuInit,
@@ -47,8 +48,10 @@ export default function PublicReuseFaciltyInsert() {
pubHasuSearch,
pbnstRuseBizUpdate,
} = useWrStore((state) => state);
const { t } = useTranslation("base");
const { pubFacHeadList, pbnstHasuResCount, pbnstHasuRes, pbnstRes } = pbnst;
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const [, setCurrentTab] = useState<string>("mng");
const [isRuseReg, setIsRuseReg] = useState<{
isModal: boolean;
@@ -290,6 +293,7 @@ export default function PublicReuseFaciltyInsert() {
}
isResetPage(true);
}}
>
조회
</Button>
@@ -307,6 +311,7 @@ export default function PublicReuseFaciltyInsert() {
appendPbnstRuseFclt();
}
}}
disabled={regAuthrtYn === "N"}
>
신규등록
</Button>
@@ -319,19 +324,17 @@ export default function PublicReuseFaciltyInsert() {
<div className="grid grid-cols-8 gap-4">
<div className="col-span-5 h-full min-h-0">
<ListDiv className="min-h-0">
{/* <ScrollArea className="h-[60vh]"> */}
{" "}
{/* 높이 조정 */}
<UiTable
tableData={bdstTable || []}
headlist={pubFacHeadList}
pageSize={10}
total={pbnstHasuResCount || 20}
headName={"공공 하수처리시설 목록"}
cellClick={cellClick}
onPageChange={setPageNation}
resetPageNo={resetPage}
/>
{/* <ScrollArea className="h-[60vh]"> */} {/* 높이 조정 */}
<UiTable
tableData={bdstTable || []}
headlist={pubFacHeadList}
pageSize={10}
total={pbnstHasuResCount || 20}
headName={"공공 하수처리시설 목록"}
cellClick={cellClick}
onPageChange={setPageNation}
resetPageNo={resetPage}
/>
{/* </ScrollArea> */}
</ListDiv>
</div>
@@ -351,6 +354,7 @@ export default function PublicReuseFaciltyInsert() {
size={"sm"}
onClick={form.handleSubmit(onSubmit, onInvalid)}
className="mr-5 mt-2"
disabled={mdfcnAuthrtYn === "N"}
>
저장
</Button>
@@ -364,6 +368,7 @@ export default function PublicReuseFaciltyInsert() {
setIndexMng(index);
}}
indexMng={indexMng}
readonly={mdfcnAuthrtYn === "N"}
/>
</TabsContent>
<TabsContent className="max-h-full" value="buse">
@@ -375,9 +380,9 @@ export default function PublicReuseFaciltyInsert() {
}}
indexMng={indexMng}
indexBiz={indexBiz}
readonly={mdfcnAuthrtYn === "N"}
/>
</TabsContent>
</ScrollArea>
</Tabs>
) : (
@@ -1,9 +1,7 @@
"use client";
import { useWrStore } from "@/app/store";
import {
type customRainBdst,
} from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { tableData } from "@/components/lib/func/commom";
import { type customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { formatCommaNumber, tableData } from "@/components/lib/func/commom";
import RainRegForm from "@/components/ui/form/fcltReg/rainReg/rainRegForm";
import { BdstReg } from "@/components/ui/modal/fcltReg/bdstRegModal/bdstRegModal";
import {
@@ -19,14 +17,19 @@ import {
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components";
import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
import { Toaster } from "react-hot-toast";
export default function Home() {
const { rain, code, initRain, rainSearch, getRainData } = useWrStore(
const { auth, rain, code, initRain, rainSearch, getRainData } = useWrStore(
(state) => {
return state;
}
);
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const { rainRes, rainResCount } = rain;
const [rainForm, setRainForm] = useState<customRainBdst>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
@@ -52,8 +55,8 @@ export default function Home() {
: "확인불가";
return {
...item,
archArea: archArea,
archArea: formatCommaNumber(archArea),
bdstChgYn: item.chgBuilding[0]?.bdstChgNm != null ? "Y" : "N",
};
}
);
@@ -64,13 +67,10 @@ export default function Home() {
}
}
}, [code, rainRes]);
const cellClick: (val: number | undefined) => void = (
val
) => {
const cellClick: (val: number | undefined) => void = (val) => {
if (val !== undefined) {
setRainForm(rainRes[val]);
}
};
useEffect(() => {
@@ -99,7 +99,7 @@ export default function Home() {
size={"sm"}
onClick={() => {
rainSearch(searchTxt || "", 1, "41");
//rainSearch(searchTxt || "", pageNation, "41");
//rainSearch(searchTxt || "", pageNation, "41");
}}
>
조회
@@ -107,7 +107,10 @@ export default function Home() {
<Button
size={"sm"}
className=""
onClick={() => setIsNewReg(!issNewReg)}
onClick={() => {
setIsNewReg(!issNewReg);
}}
disabled={regAuthrtYn === "N"}
>
신규등록
</Button>
@@ -143,6 +146,7 @@ export default function Home() {
<RainRegForm
rainForm={rainForm ?? ({} as customRainBdst)}
isModal={false}
readonly={mdfcnAuthrtYn !== "Y"}
></RainRegForm>
</ScrollArea>
</ListDiv>
@@ -20,9 +20,11 @@ import { useEffect, useState } from "react";
import { Toaster } from "react-hot-toast";
export default function Home() {
const { code, rswt, initRswt, rswtBdstSearch, getRswtBdstData } = useWrStore(
const { auth,code, rswt, initRswt, rswtBdstSearch, getRswtBdstData } = useWrStore(
(state) => state
);
const { regAuthrtYn, mdfcnAuthrtYn } = auth;
const [rswtForm, setRswtForm] = useState<customRswtBdst>();
const [searchTxt, setSearchTxt] = useState<string>();
const [issNewReg, setIsNewReg] = useState<boolean>(false);
@@ -114,6 +116,7 @@ export default function Home() {
size={"sm"}
className="mr-4"
onClick={() => setIsNewReg(!issNewReg)}
disabled={regAuthrtYn === "N"}
>
신규등록
</Button>
@@ -146,6 +149,7 @@ export default function Home() {
<RswtrRegForm
rswtForm={rswtForm ?? ({} as customRswtBdst)}
isModal={false}
readonly={mdfcnAuthrtYn === "N"}
/>
</ScrollArea>
</ListDiv>
@@ -166,8 +166,8 @@ export default function HtdflSttn() {
value={objSearch.sgg} // value props 추가
onSelectValue={getSgg}
/>
<div className="col-span-2 flex flex-row space-x-2">
<Label className="w-28 mt-2 text-xl text-gray-600">
<div className="col-span-2 flex flex-row space-x-2 ml-3 mt-2">
<Label className="w-28 mt-2 text-xl">
{"시설명"}
</Label>
<SearchInput
@@ -124,8 +124,13 @@ export default function RainSttn() {
item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct === -1
? "확인불가"
: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct,
archArea:
Math.floor(item.archArea) === -1 ? "확인불가" : item.archArea,
// archArea:
// Math.floor(item.archArea) === -1 ? "확인불가" : Math.trunc(item.archArea) ? item.archArea,
archArea: isNaN(Number(item.archArea))
? item.archArea
: Math.floor(Number(item.archArea)) === -1
? '확인불가'
: Math.trunc(Number(item.archArea))
};
})
.filter((item: any) => item.rainyObj !== undefined);
@@ -206,12 +211,12 @@ export default function RainSttn() {
value={objSearch.sgg} // value props 추가
onSelectValue={getSgg}
/>
<div className="col-span-2 flex flex-row space-x-2">
<Label className="w-28 mt-2 text-xl text-gray-600">
<div className="col-span-2 flex flex-row space-x-2 ml-3 mt-2">
<Label className="w-28 mt-2 text-xl">
{"시설명"}
</Label>
<SearchInput
className={"w-full h-full text-2xl"}
className={"w-full text-2xl"}
label={""}
textValue={fcltNm || ""}
setText={setFcltNm}
@@ -164,8 +164,8 @@ export default function RswtSttn() {
getSgg
}
/>
<div className="col-span-2 flex flex-row space-x-2">
<Label className="w-28 mt-2 text-xl text-gray-600">
<div className="col-span-2 flex flex-row space-x-2 ml-3 mt-2">
<Label className="w-28 mt-2 text-xl">
{"시설명"}
</Label>
<SearchInput
@@ -99,7 +99,9 @@ export default function Page() {
isRainSttn(true)
rainChkSttnInit(1, rainPageSize, new Date().getFullYear().toString(), commonCd);
setIsModal({ data: {}, open: false });
}
}, [rainChkSttn.isInit, rainChkSttnInit, rainPageSize]);
useEffect(() => {
+88 -76
View File
@@ -16,50 +16,44 @@ import {
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function RainStat() {
const { code, rainStat, searchRainStatList } = useWrStore((state) => state);
const { rainStatList, excelList, rainDetailList } = rainStat;
const { rainStatList, rainDetailList } = rainStat;
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
const [exData, setExData] = useState<Array<Record<string, string | number>>>();
//const [exData, setExData] = useState<Array<Record<string, string | number>>>();
const [bdstTable, setBdstTable] = useState<RainStatProps[]>();
const { t } = useTranslation('base');
useEffect(() => {
searchRainStatList(searchYear);
}, [code.cityCd, code.sggCd, searchRainStatList])
searchRainStatList(searchYear ,code.cityCd);
}, [code.cityCd, searchRainStatList])
const excelDetailDownLoad=() =>{
const sidoList = new Set<string>();
const sidoDataMap = new Map<string, (string | number)[]>(); // 시도별 데이터를 저장할 Map
const sidoDetailMap = new Map<string, (string | number)[][]>(); // 시도별 상세 데이터를 저장할 Map
// 먼저 시도별 상세 데이터를 그룹화
rainDetailList.forEach((item: RainStatProps[]) => {
// 복사된 배열을 사용
const transformedRainDetailList = rainDetailList.map((originItem: RainStatProps[]) => {
const item = [...originItem]; // 원본 복사
const sidoVal = item.at(0)?.toString().trim();
const sigunVal = item.at(1)?.toString().trim();
let sidoText = '';
let sigunText = '';
const sido = code.cityCd.find((city) => city.val === sidoVal);
const sigun = code.sggCd.find((sgg) => sgg.val === sigunVal);
sidoText = sido?.text || '';
sigunText = sigun?.text || '';
// 시도, 시군구 코드를 텍스트로 변환하여 데이터에 할당
if (item.length > 0) {
item[0] = sidoText as unknown as RainStatProps;
}
if (item.length > 1) {
item[1] = sigunText as unknown as RainStatProps;
}
if (item.length > 2) {
item[2] = sidoText+' '+sigunText as unknown as RainStatProps;
}
const sidoText = sido?.text || '';
const sigunText = sigun?.text || '';
if (item.length > 0) item[0] = sidoText as unknown as RainStatProps;
if (item.length > 1) item[1] = sigunText as unknown as RainStatProps;
if (item.length > 2) item[2] = `${sidoText} ${sigunText}` as unknown as RainStatProps;
// 시도별 상세 데이터 수집
if (sidoText) {
@@ -72,53 +66,40 @@ export default function RainStat() {
// 시도별 합계 데이터 수집
if (sidoText && !sidoList.has(sidoText)) {
sidoList.add(sidoText);
// 시도별 초기 데이터 구조 생성 (예: [시도명, 0, 0, 0, ...])
const initialData: (string | number)[] = [sidoText];
// 데이터의 나머지 컬럼들을 0으로 초기화 (실제 컬럼 수에 맞게 조정 필요)
for (let i = 1; i < item.length; i++) {
initialData.push(0);
}
sidoDataMap.set(sidoText, initialData);
}
return item;
});
// 시도별 합계 계산
rainDetailList.forEach((item: RainStatProps[]) => {
// 이후 합계 계산에서도 transformedRainDetailList 사용
transformedRainDetailList.forEach((item: RainStatProps[]) => {
const sidoText = item[0]?.toString();
if (sidoText && sidoDataMap.has(sidoText)) {
const sidoData = sidoDataMap.get(sidoText)!;
// 각 컬럼의 값을 합계에 더하기 (1번 인덱스부터 시작)
for (let i = 1; i < item.length && i < sidoData.length; i++) {
if(i == 2){
sidoData[i] = '합계';
} else if(i == 3){
// 해당 시도의 데이터 개수를 계산
const sidoDataCount = rainDetailList.filter((data: unknown[]) =>
} else if (i == 3) {
const sidoDataCount = transformedRainDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText
).length;
sidoData[i] = sidoDataCount;
} else if( i == 4){
sidoData[i] = '';
} else if(i == 6){
// 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우)
const bumCnt = rainDetailList.filter((data: unknown[]) =>
} else if (i == 6) {
const bumCnt = transformedRainDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 6 && String(data[0]) === sidoText
).filter((data: unknown[]) => String(data[6]) === '대상').length;
sidoData[i] = bumCnt;
} else if(i==8){
const value = Number(item[8]) || 0;
} else if ([8, 11, 12, 14].includes(i)) {
const value = Number(item[i]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==11){
const value = Number(item[11]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==12){
const value = Number(item[12]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==14){
const value = Number(item[14]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
}
else {
} else {
sidoData[i] = '';
}
}
@@ -144,7 +125,7 @@ export default function RainStat() {
});
const sidoSummaryList = Array.from(sidoDataMap.values());
const sidoTotalSummary = [['전체', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '', 0]];
const sidoTotalSummary = [['전국', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '']];
sidoSummaryList.forEach((item: (string | number)[]) => {
item.forEach((value: string | number, index: number) => {
if(typeof value === 'number') {
@@ -158,48 +139,77 @@ export default function RainStat() {
// sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
console.log(' excelData ', excelData)
excelDownload(
excelData as unknown as [][],
"빗물이용시설 통계",
"sample_rainStats.xlsx",
"A1:V3",
"A1:O3",
4
);
}
const excelClick = () => {
if(bdstTable){
const tbData = bdstTable .map((item: RainStatProps) => {
return {
"시도": item.cityText,
"개소": item.tmp,
"설치비(백만원)": item.instlCst,
"저류조용량(m³/년)": item.dtfcltCpct,
"연간사용량(m³/년)": item.wtrUsqty,
"조경용수": item.lndwtr,
"청소화장실용수": item.cleanToilUswtr,
"세척살수용수": item.resn,
"농업용수": item.farmUswtr,
"공업용수": item.indstUswtr,
"친수용수": item.hydUswtr,
"기타": item.ithlEtcUswtr,
"연간운영비(백만원/년)": item.anlOperCst,
};
})
downloadExcel({
data: (exData as unknown as JSON[]) ?? [],
data: (tbData as unknown as JSON[]) ?? [],
fileName: "재이용통계",
sheetNameArray: ["Sheet1"],
headerRange: "A1:M1"
})
}else{
toast.error(t('excelDownErrMsg'));
}
}
useEffect(() => {
const transExcel = Array.isArray(excelList) ? excelList : [excelList];
const excelData = tableData(transExcel, { code });
const tbData = Array.isArray(excelData)
? excelData.map((item: RainStatProps) => {
return {
"시도": item.cityText,
"개소": item.tmp,
"설치비(백만원)": item.instlCst,
"저류조용량(m³/년)": item.dtfcltCpct,
"연간사용량(m³/년)": item.wtrUsqty,
"조경용수": item.lndwtr,
"청소화장실용수": item.cleanToilUswtr,
"세척살수용수": item.resn,
"농업용수": item.farmUswtr,
"공업용수": item.indstUswtr,
"친수용수": item.hydUswtr,
"기타": item.ithlEtcUswtr,
"연간운영비(백만원/년)": item.anlOperCst,
};
})
: [];
setExData(tbData);
}, [code, excelList])
// useEffect(() => {
// if(excelList && excelList.length>0){
// console.log('excelList ', excelList)
// const transExcel = Array.isArray(excelList) ? excelList : [excelList];
// const excelData = tableData(transExcel, { code });
// const tbData = Array.isArray(excelData)
// ? excelData
// .filter((item: RainStatProps) => item.cityText !== '없음')
// .map((item: RainStatProps) => {
// return {
// "시도": item.cityText,
// "개소": item.tmp,
// "설치비(백만원)": item.instlCst,
// "저류조용량(m³/년)": item.dtfcltCpct,
// "연간사용량(m³/년)": item.wtrUsqty,
// "조경용수": item.lndwtr,
// "청소화장실용수": item.cleanToilUswtr,
// "세척살수용수": item.resn,
// "농업용수": item.farmUswtr,
// "공업용수": item.indstUswtr,
// "친수용수": item.hydUswtr,
// "기타": item.ithlEtcUswtr,
// "연간운영비(백만원/년)": item.anlOperCst,
// };
// })
// : [];
// setExData(tbData);
// }
// }, [code, excelList])
useEffect(() => {
const transData = Array.isArray(rainStatList) ? rainStatList : [rainStatList];
@@ -208,11 +218,13 @@ export default function RainStat() {
? data.map((item: RainStatProps) => {
return {
...item,
ctpvCd: item.cityText
ctpvCd: item.cityText==='전체'?'전국': item.cityText,
cityText: item.cityText==='전체'?'전국': item.cityText,
};
}).filter((item: RainStatProps) => item.cityText !== '없음')
: [];
setBdstTable(tbData);
}, [code, rainStatList]);
@@ -237,7 +249,7 @@ export default function RainStat() {
/>
</div>
<div className="flex flex-row space-x-2 items-center">
<Button className="" size={"sm"} onClick={()=>{searchRainStatList(searchYear);}}>
<Button className="" size={"sm"} onClick={() => { searchRainStatList(searchYear ,code.cityCd); }}>
조회
</Button>
<Button className="" size={"sm"} onClick={() => excelClick()}>
+67 -60
View File
@@ -14,48 +14,26 @@ import {
import ListDiv from "@common/business_components/ui/list_div";
import { Button } from "@common/components/ui";
import { useEffect, useState } from "react";
import toast, { Toaster } from "react-hot-toast";
import { useTranslation } from "react-i18next";
export default function RswtStat() {
const { code, rswtStat, searchRswtStatList } = useWrStore((state) => state);
const { rswtStatList, excelList, rswtDetailList } = rswtStat;
const { rswtStatList, rswtDetailList } = rswtStat;
const [rswtTable, setRswtTable] = useState<RswtStatProps[]>();
const [searchYear, setSearchYear] = useState<string>(
String(new Date().getFullYear())
);
const [excelData, setExceData] = useState<Record<string, string | number>[]>();
const { t } = useTranslation('base');
useEffect(() => {
searchRswtStatList(searchYear)
}, [searchRswtStatList])
searchRswtStatList(searchYear, code.cityCd)
}, [searchRswtStatList, code.cityCd])
const excelClick = () => {
downloadExcel({
data: (excelData as unknown as JSON[]) ?? [],
fileName: "중수도재이용통계",
sheetNameArray: ["Sheet1"],
headerRange: "A1:N1"
})
}
useEffect(() => {
const transData = Array.isArray(rswtStatList) ? rswtStatList : [rswtStatList];
const data = tableData(transData, { code });
const tbData = Array.isArray(data)
? data.map((item: RswtStatProps) => {
return {
...item,
ctpvCd: item.cityText
};
}).filter((item: RswtStatProps) => item.cityText !== '없음')
: [];
setRswtTable(tbData);
}, [code, rswtStatList])
useEffect(() => {
const transExcel = Array.isArray(excelList) ? excelList : [excelList];
const exData = tableData(transExcel, { code });
const tbData = Array.isArray(exData) ?
exData.map((item: RswtStatProps) => {
if (rswtTable) {
const data = rswtTable.map((item: RswtStatProps) => {
return {
"시도": item.cityText,
"개소": item.ctpvCnt,
@@ -73,17 +51,44 @@ export default function RswtStat() {
"기타": item.ithlEtcUswtr,
"연간운영비(백만원/년)": item.anlOperCst,
};
}) : [];
setExceData(tbData);
}, [code, excelList])
})
downloadExcel({
data: (data as unknown as JSON[]) ?? [],
fileName: "중수도재이용통계",
sheetNameArray: ["Sheet1"],
headerRange: "A1:N1"
})
} else {
toast.error(t("excelDownErrMsg"))
}
}
useEffect(() => {
const transData = Array.isArray(rswtStatList) ? rswtStatList : [rswtStatList];
const cityData = tableData(transData, { code });
const tbData = Array.isArray(cityData)
? cityData.map((item: RswtStatProps) => {
return {
...item,
ctpvCd: item.cityText === '전체' ? '전국' : item.cityText,
cityText: item.cityText === '전체' ? '전국' : item.cityText
};
}) : [];
setRswtTable(tbData);
}, [code, rswtStatList]);
const excelDetailDownLoad = () => {
const excelDetailDownLoad=() =>{
const sidoList = new Set<string>();
const sidoDataMap = new Map<string, (string | number)[]>(); // 시도별 데이터를 저장할 Map
const sidoDetailMap = new Map<string, (string | number)[][]>(); // 시도별 상세 데이터를 저장할 Map
// 먼저 시도별 상세 데이터를 그룹화
rswtDetailList.forEach((item: RswtStatProps[]) => {
const transformedRswtDetailList = rswtDetailList.map((originItem: RswtStatProps[]) => {
// rswtDetailList.forEach((item: RswtStatProps[]) => {
const item = [...originItem]; // 원본 복사
const sidoVal = item.at(0)?.toString().trim();
const sigunVal = item.at(1)?.toString().trim();
let sidoText = '';
@@ -94,7 +99,7 @@ export default function RswtStat() {
sidoText = sido?.text || '';
sigunText = sigun?.text || '';
// 시도, 시군구 코드를 텍스트로 변환하여 데이터에 할당
if (item.length > 0) {
item[0] = sidoText as unknown as RswtStatProps;
@@ -103,7 +108,7 @@ export default function RswtStat() {
item[1] = sigunText as unknown as RswtStatProps;
}
if (item.length > 2) {
item[2] = sidoText+' '+sigunText as unknown as RswtStatProps;
item[2] = sidoText + ' ' + sigunText as unknown as RswtStatProps;
}
// 시도별 상세 데이터 수집
@@ -113,7 +118,7 @@ export default function RswtStat() {
}
sidoDetailMap.get(sidoText)!.push(item as unknown as (string | number)[]);
}
// 시도별 합계 데이터 수집
if (sidoText && !sidoList.has(sidoText)) {
sidoList.add(sidoText);
@@ -125,50 +130,51 @@ export default function RswtStat() {
}
sidoDataMap.set(sidoText, initialData);
}
return item;
});
// 시도별 합계 계산
rswtDetailList.forEach((item: RswtStatProps[]) => {
transformedRswtDetailList.forEach((item: RswtStatProps[]) => {
const sidoText = item[0]?.toString();
if (sidoText && sidoDataMap.has(sidoText)) {
const sidoData = sidoDataMap.get(sidoText)!;
// 각 컬럼의 값을 합계에 더하기 (1번 인덱스부터 시작)
for (let i = 1; i < item.length && i < sidoData.length; i++) {
if(i == 2){
if (i == 2) {
sidoData[i] = '합계';
} else if(i == 3){
} else if (i == 3) {
// 해당 시도의 데이터 개수를 계산
const sidoDataCount = rswtDetailList.filter((data: unknown[]) =>
const sidoDataCount = rswtDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText
).length;
sidoData[i] = sidoDataCount;
} else if( i == 4){
} else if (i == 4) {
sidoData[i] = '';
} else if(i == 6){
} else if (i == 6) {
// 법정 대상 건축물 개수 (인덱스 6이 'Y'인 경우)
const bumCnt = rswtDetailList.filter((data: unknown[]) =>
const bumCnt = rswtDetailList.filter((data: unknown[]) =>
Array.isArray(data) && data.length > 6 && String(data[0]) === sidoText
).filter((data: unknown[]) => String(data[6]) === '대상').length;
sidoData[i] = bumCnt;
} else if(i==9){
} else if (i == 9) {
const value = Number(item[9]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==10){
} else if (i == 10) {
const value = Number(item[10]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==11){
} else if (i == 11) {
const value = Number(item[11]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==12){
} else if (i == 12) {
const value = Number(item[12]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
}else if(i==13){
} else if (i == 13) {
const value = Number(item[13]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==14){
} else if (i == 14) {
const value = Number(item[14]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else if(i==16){
} else if (i == 16) {
const value = Number(item[16]) || 0;
sidoData[i] = (Number(sidoData[i]) + value) as string | number;
} else {
@@ -177,15 +183,15 @@ export default function RswtStat() {
}
}
});
// 시도별로 합계와 상세 데이터를 순서대로 배치
const summaryExcelData: (string | number)[][] = [];
// 시도별로 순회하면서 합계와 상세 데이터를 추가
Array.from(sidoList).forEach((sidoText) => {
const sidoSummary = sidoDataMap.get(sidoText);
const sidoDetails = sidoDetailMap.get(sidoText) || [];
if (sidoSummary) {
// 시도 합계 데이터 추가
summaryExcelData.push(sidoSummary);
@@ -197,10 +203,10 @@ export default function RswtStat() {
});
const sidoSummaryList = Array.from(sidoDataMap.values());
const sidoTotalSummary = [['전체', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '', 0]];
const sidoTotalSummary = [['전국', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '']];
sidoSummaryList.forEach((item: (string | number)[]) => {
item.forEach((value: string | number, index: number) => {
if(typeof value === 'number') {
if (typeof value === 'number') {
if (sidoTotalSummary[0] && index < sidoTotalSummary[0].length) {
sidoTotalSummary[0][index] = Number(sidoTotalSummary[0][index]) + Number(value);
}
@@ -209,13 +215,13 @@ export default function RswtStat() {
});
// sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성
const excelData = [...sidoTotalSummary,...sidoSummaryList, ...summaryExcelData];
const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData];
excelDownload(
excelData as unknown as [][],
"중수도시설 통계",
"sample_rswtStats.xlsx",
"A1:Q3",
"A1:P3",
4
);
}
@@ -242,7 +248,7 @@ export default function RswtStat() {
className=""
size="sm"
onClick={() => {
searchRswtStatList(searchYear)
searchRswtStatList(searchYear, code.cityCd)
}}
>
조회
@@ -283,6 +289,7 @@ export default function RswtStat() {
</ListDiv>
</div>
</div>
<Toaster position="top-center"></Toaster>
</ContentsDiv>
</>
);
+60
View File
@@ -0,0 +1,60 @@
import { getFetchWithCount } from "@/components/lib/api";
import toast from "react-hot-toast";
export type authState = {
auth: {
mngAuthrtYn: string;
inqAuthrtYn: string;
regAuthrtYn: string;
mdfcnAuthrtYn: string;
delAuthrtYn: string;
};
};
export type authType = authState & authActions;
export const authStateExport: authState = {
auth: {
mngAuthrtYn: "Y",
inqAuthrtYn: "Y",
regAuthrtYn: "Y",
mdfcnAuthrtYn: "Y",
delAuthrtYn: "Y",
},
};
export type authActions = {
getMenuAuthrts: (menuCd: number) => void;
};
export const authActionsExport: (set: any) => authActions = (set: any) => {
return {
getMenuAuthrts: async (menuCd: number) => {
try{
const response = await getFetchWithCount( 'LOCAL',
`/cms-service/api/v1/menu-authrts/pageinfo/${menuCd}`
);
set((state: authState) => {
return {
...state,
auth: {
mngAuthrtYn: response[0].mngAuthrtYn,
inqAuthrtYn: response[0].mngAuthrtYn,
regAuthrtYn: response[0].mngAuthrtYn,
mdfcnAuthrtYn: response[0].mngAuthrtYn,
delAuthrtYn: response[0].mngAuthrtYn,
},
};
});
}catch(e){
toast.error('권한 정보를 가져오는 중 오류가 발생했습니다. 관리자에게 문의하세요.');
console.error('Error fetching menu authorities:', e);
}
},
};
};
@@ -0,0 +1,19 @@
export interface MenuItem {
menuCd: number;
menuKornNm: string;
menuEngNm: string;
parentId: number | null;
sortSeq: number;
iconNm?: string;
children: MenuItem[] | null;
levelNo: number;
urlPath: string;
menuLnkgTypeCd: string;
menuLnkgSn: number;
menuPath: string;
qrcd: string;
useYn: string;
otptYn: string;
newWndwYn: string;
requiredUrlPath: boolean;
}
@@ -20,7 +20,7 @@ export const coRvwHeadListExport: CommonTableProps[]= [
},
{
id: "daddr",
title: "공장주소",
title: "주소",
visible: true,
},
{
+2 -1
View File
@@ -1,3 +1,4 @@
import type { ChkClass } from "@common/business_components/ui";
import { z } from "zod";
const DemandInfoSchema = z.object({
@@ -130,7 +131,7 @@ export type RvwHistTableType = {
dmndQty: string;
useUsgCd: string;
splyFcltFlg: string;
completeYn: boolean;
completeYn: ChkClass;
dmdInfoSn: string;
};
+52 -33
View File
@@ -29,11 +29,11 @@ type ExcelType = {
[key: string]: string | number | undefined;
};
const excelDownList: ExcelType[] = [];
// const excelDownList: ExcelType[] = [];
type ldrmntActions = {
ldrmntRegData: (data: any[]) => void,
ldrmntInit: (con: string) => void
ldrmntInit: (isExcel: boolean, con: string) => void
ldrmntSearch: (isExcel: boolean, page: number, sggCd: string, total: string, coNm: string) => void;
ldrmntUpdate: (ldrmntRes: customLdrmnt) => void;
ldrmntDelete: () => void;
@@ -58,25 +58,47 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
set: any
) => {
return {
ldrmntInit: async (con: string) => {
ldrmntInit: async (isExcel: boolean,con: string) => {
try {
const ldrmntRes = await getFetchWithCount(
fetchType.WR,
`/reuseFc/request/temp/1/20/${con}`
);
set((state: ldrmntState) => {
return {
...state,
ldrmnt: {
...state.ldrmnt,
ldrmntRes: ldrmntRes.data,
ldrmntResCount: ldrmntRes.count,
isInit: false,
excelList: excelDownList,
},
}
});
if (isExcel) {
const excelDownList: ExcelType[] = [];
ldrmntRes.data.forEach((item: customLdrmnt) => {
excelDownList.push({
ctpvCd: item.ctpvCd,
sggCd: item.sggCd,
dmdCoNm: item.dmdCoNm,
fctryAddr: item.fctryAddr,
fctryMngNo: item.fctryMngNo,
telno: item.telno,
})
})
set((state: ldrmntState) => {
return {
...state,
ldrmnt: {
...state.ldrmnt,
excelList: excelDownList,
ldrmntResCount: ldrmntRes.count,
},
};
});
} else {
set((state: ldrmntState) => {
return {
...state,
ldrmnt: {
...state.ldrmnt,
ldrmntRes: ldrmntRes.data,
ldrmntResCount: ldrmntRes.count,
isInit: false,
},
}
});
}
} catch (e) {
console.log(e)
}
@@ -96,6 +118,7 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
await deleteFectch(
`/reuseFc/request/temp`,
);
console.log("deleteFectch", deleteFectch)
const response = await postFectch(
"/reuseFc/request/temp",
@@ -121,7 +144,6 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
fetchType.WR,
searchUrl
);
console.log("알이에스", ldrmntRes)
if (isExcel) {
const excelDownList: ExcelType[] = [];
ldrmntRes.data.forEach((item: customLdrmnt) => {
@@ -144,7 +166,6 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
},
};
});
return excelDownList;
} else
set((state: ldrmntState) => {
return {
@@ -157,27 +178,26 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
},
};
});
return ldrmntRes;
} catch (e) {
console.log(e)
}
},
ldrmntUpdate: async (ldrmntRes: customLdrmnt) => {
if(ldrmntRes)
try {
ldrmntRes.rgtr = TEST_UUID;
const res = await putFectch(
`/reuseFc/request/temp`,
ldrmntRes
);
if (ldrmntRes)
try {
ldrmntRes.rgtr = TEST_UUID;
const res = await putFectch(
`/reuseFc/request/temp`,
ldrmntRes
);
if (res.ok) {
toast.success("잠재수요처 상세정보가 수정되었습니다.",)
if (res.ok) {
toast.success("잠재수요처 상세정보가 수정되었습니다.",)
}
} catch (error) {
console.error("Error ldrmntUpdate:", error);
toast.error("잠재수요처 상세정보 수정에 실패하였습니다.")
}
} catch (error) {
console.error("Error ldrmntUpdate:", error);
toast.error("잠재수요처 상세정보 수정에 실패하였습니다.")
}
},
ldrmntDelete: async () => {
try {
@@ -193,7 +213,6 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = (
await deleteFectch(
`/reuseFc/request/temp`,
);
} catch (error) {
console.log("error", error)
set((state: ldrmntState) => {
@@ -6,6 +6,7 @@ export const ruseHstryHeadListExport:TableUpperProps[]= [
id: "cityText",
title: "시도",
visible: true,
},
{
id: "sggText",
@@ -19,7 +20,7 @@ export const ruseHstryHeadListExport:TableUpperProps[]= [
},
{
id: "daddr",
title: "공장주소",
title: "주소",
visible: true,
},
{
@@ -49,7 +50,7 @@ export const ruseHstryHeadListExport:TableUpperProps[]= [
},
{
id: "dmndQty", //바꾸기
title: "요구수량(M3/d)",
title: "요구수량(m³/일)",
visible: true,
},
{
@@ -130,7 +130,7 @@ export const ruseHstryActionsExport: (set: any) => ruseHstryActions = (
toast.success("매칭 계산 저장이 완료입니다.");
const rvwHistRes = await irvwHistInit(
1,
10,
13,
new Date().getFullYear().toString(),
new Date().getFullYear().toString(),
);
@@ -217,10 +217,10 @@ export const ruseHstryActionsExport: (set: any) => ruseHstryActions = (
fetchType.WR
);
if (complet.status === 200) {
toast.success("완료 처리가 완료되었습니다.");
toast.success("매칭완료가 완료되었습니다.");
const rvwHistRes = await irvwHistInit(
1,
10,
13,
new Date().getFullYear().toString(),
new Date().getFullYear().toString(),
);
@@ -236,7 +236,7 @@ export const ruseHstryActionsExport: (set: any) => ruseHstryActions = (
}
} catch (e) {
console.log(" error ", e);
toast.error("완료 처리 중 오류가 발생했습니다.");
toast.error("매칭 완료 처리 중 오류가 발생했습니다.");
}
},
};
@@ -195,7 +195,7 @@ export const rainChkgdnHeadListExport: TableUpperProps[] = [
title: "부과금액(천원)",
upName: "feeHist",
upSequnce: 3,
type: "number",
type: "text",
edit: true,
},
];
@@ -42,17 +42,17 @@ const hdtflObjSchema = z.object({
utztnUsg: z
.string()
.min(1, { message: validationMessages.required("이용 용도") }),
grssClfg: z.number().default(0), // Measurements, 0 is fine as default
combResdch: z.number().default(0), // Measurements, 0 is fine as default
trbt: z.number().default(0), // Measurements, 0 is fine as default
bod: z.number().default(0), // Measurements, 0 is fine as default
smll: z.number().default(0), // Measurements, 0 is fine as default
crmty: z.number().default(0), // Measurements, 0 is fine as default
tn: z.number().default(0), // Measurements, 0 is fine as default
tph: z.number().default(0), // Measurements, 0 is fine as default
ph: z.number().default(0), // Measurements, 0 is fine as default
clIonQnt: z.number().default(0), // Measurements, 0 is fine as default
cdtnv: z.number().default(0), // Measurements, 0 is fine as default
grssClfg: z.number().default(0).nullish(), // Measurements, 0 is fine as default
combResdch: z.number().default(0).nullish(), // Measurements, 0 is fine as default
trbt: z.number().default(0).nullish(), // Measurements, 0 is fine as default
bod: z.number().default(0).nullish(), // Measurements, 0 is fine as default
smll:z.string().default('').nullish(), // Measurements, 0 is fine as default
crmty: z.number().default(0).nullish(), // Measurements, 0 is fine as default
tn: z.number().default(0).nullish(), // Measurements, 0 is fine as default
tph:z.number().default(0).nullish(),// Measurements, 0 is fine as default
ph: z.string().default('').nullish(), // Measurements, 0 is fine as default
clIonQnt: z.number().default(0).nullish(), // Measurements, 0 is fine as default
cdtnv: z.number().default(0).nullish(), // Measurements, 0 is fine as default
emsnExitTp: z.number()
.max(100, { message: "온도는 100이상이 될 수 없습니다." })
.default(0), // Changed max to 100 based on message, // Measurements, 0 is fine as default
@@ -53,7 +53,7 @@ export const pbnstDemandHeadListExport: TableUpperProps[] = [
export const pbnstOrgwtHeadListRxport: TableUpperProps[] = [
{ id: "ruseUtztnFcltNm", title: "하수처리장명" },
{ id: "orgwtWtritQnt", title: "원수취수량", type: "number" },
{ id: "orgwtWtritQnt", title: "원수취수량(m³/일)", type: "number" },
{ id: "tmsYn", title: "하수처리량TMS 전후" },
{ id: "dschgFmYn", title: "하수처리장 방류 유량계 전·후​" },
{ id: "dtlPstnExpln", title: "상세위치", edit: true },
@@ -141,7 +141,7 @@ export const pbnstSttNodeListExport: CommonTableProps[] = [
},
{
id: "fctCpc",
title: "시설용량(톤/일)",
title: "시설용량(m³/일)",
visible: true,
row: 1,
rowSpan: 2,
@@ -157,7 +157,7 @@ export const pbnstSttNodeListExport: CommonTableProps[] = [
},
{
id: "rusSup",
title: "재이용수공급가능량",
title: "재이용수공급가능량(m³/일)",
visible: true,
row: 1,
rowSpan: 1,
@@ -226,7 +226,7 @@ export const pbnstSttNodeListExport: CommonTableProps[] = [
},
{
id: "fcltCpct",
title: "시설용량(m³/일)",
title: "시설용량",
upName: "rusSup",
visible: true,
row: 2,
@@ -235,7 +235,7 @@ export const pbnstSttNodeListExport: CommonTableProps[] = [
},
{
id: "splyExtraCpct",
title: "하수처리량(m³/일)",
title: "하수처리량",
upName: "rusSup",
visible: true,
row: 2,
@@ -244,7 +244,7 @@ export const pbnstSttNodeListExport: CommonTableProps[] = [
},
{
id: "ruseCpct",
title: "재이용량(m³/일)",
title: "재이용량",
upName: "rusSup",
visible: true,
row: 2,
@@ -337,7 +337,7 @@ export const ruseFcltNodeListExport: TableUpperProps[] = [
},
{
id: "mainSplyPumpCpct",
title: "메인공급펌프용량",
title: "메인공급펌프용량(m³/일)",
visible: true,
row: 1,
rowSpan: 3,
@@ -345,7 +345,7 @@ export const ruseFcltNodeListExport: TableUpperProps[] = [
},
{
id: "buziFee",
title: "사업비(백만원)",
title: "사업비(원)",
visible: true,
row: 2,
rowSpan: 1,
@@ -418,7 +418,7 @@ export const ruseFcltNodeListExport: TableUpperProps[] = [
},
{
id: "cusrAlotm",
title: "민간투자비",
title: "민간투자비",
visible: true,
row: 3,
rowSpan: 1,
@@ -438,7 +438,7 @@ export const ruseFcltNodeListExport: TableUpperProps[] = [
export const ruseSplyHeadListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true },
{ id: "orgwtWtritQnt", title: "원수취수량", visible: true },
{ id: "orgwtWtritQnt", title: "원수취수량(m³/일)", visible: true },
{ id: "tmsYn", title: "하수처리량TMS 전후", visible: true },
{ id: "dschgFmYn", title: "하수처리장 방류 유량계 전·후​", visible: true },
{ id: "dtlPstnExpln", title: "상세위치 설명", visible: true },
@@ -447,8 +447,8 @@ export const ruseSplyHeadListExport: TableUpperProps[] = [
export const rusePplHeadListExport: TableUpperProps[] = [
{ id: "cycl", title: "차수", visible: true },
{ id: "ppMqlt", title: "관재질", type: "select", visible: true },
{ id: "pdmt", title: "관경", type: "select", visible: true },
{ id: "cpct", title: "연장", edit: true, visible: true },
{ id: "pdmt", title: "관경(mm)", type: "select", visible: true },
{ id: "cpct", title: "연장(m)", edit: true, visible: true },
];
export const ruseGuranteeHeadListExport: TableUpperProps[] = [
@@ -458,10 +458,10 @@ export const ruseGuranteeHeadListExport: TableUpperProps[] = [
{ id: "combResdch", title: "결합잔류염소(mh/L)", visible: true },
{ id: "trbt", title: "탁도(NTU)", visible: true },
{ id: "smll", title: "냄새", visible: true },
{ id: "crmty", title: "색도", visible: true },
{ id: "crmty", title: "색도(도)", visible: true },
{ id: "tn", title: "총질소(mg/L)", visible: true },
{ id: "tph", title: "총인(mg/L)", visible: true },
{ id: "ph", title: "수소이온농도", visible: true },
{ id: "ph", title: "수소이온농도(PH)", visible: true },
{ id: "clIonQnt", title: "염화물(mg/L)", visible: true },
{ id: "cdtnv", title: "전기전도도(μs/cm)​", visible: true },
];
@@ -228,7 +228,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
},
{
id: "archArea",
title: "건축면적",
title: "건축면적(m³)",
upName: "bdnstInfo",
visible: true,
row: 2,
@@ -265,7 +265,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
{
id: "instlCst",
title: "설치비용",
title: "설치비용(원)",
upName: "rainFcltInfo",
visible: true,
row: 2,
@@ -285,7 +285,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
{
id: "pntfColKnd",
title: "집수지점종류",
title: "종류",
upName: "pntfCol",
visible: true,
row: 3,
@@ -294,7 +294,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
},
{
id: "pntfColArea",
title: "집수지점면적",
title: "면적(m²)",
upName: "pntfCol",
visible: true,
row: 3,
@@ -304,7 +304,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
{
id: "dtfcltCpct",
title: "저류조용량",
title: "저류조용량(m³)",
upName: "rainFcltInfo",
visible: true,
row: 2,
@@ -322,7 +322,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
},
{
id: "filtrTrtmfctCpct",
title: "여과처리시설용량",
title: "여과처리시설용량(m³)",
upName: "filtrTrtmfct",
visible: true,
row: 3,
@@ -359,7 +359,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
},
{
id: "instlCstSprtAmt",
title: "설치지원비용",
title: "설치지원비용(원)",
upName: "instlCstSprt",
visible: true,
row: 3,
@@ -379,7 +379,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
{
id: "grntchBdstCertYn",
title: "녹색건축물인증여부",
title: "인증여부",
upName: "grntchBdstCert",
visible: true,
row: 3,
@@ -388,7 +388,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
},
{
id: "grntchBdstCertYr",
title: "녹색건축물인증년도",
title: "인증년도",
upName: "grntchBdstCert",
visible: true,
row: 3,
@@ -397,7 +397,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
},
{
id: "grntchBdstCertNo",
title: "녹색건축물인증번호",
title: "인증번호",
upName: "grntchBdstCert",
visible: true,
row: 3,
@@ -406,7 +406,7 @@ export const rainSttNodeListExport: CommonTableProps[] = [
},
{
id: "grntchBdstCertGrd",
title: "녹색건축물인증등급",
title: "인증등급",
upName: "grntchBdstCert",
visible: true,
row: 3,
+195 -133
View File
@@ -2,158 +2,215 @@ import { fetchType, getFetch } from "@/components/lib/api";
import type { TableUpperProps } from "../../common/type/header";
import { excelRainStat } from "./excel";
import { rainStatHeadListExport } from "./headList";
import type { SelectDataType } from "@common/business_components/ui";
export type RainStatProps = {
cityText: string
ctpvCd: string //시도
sggCd: string //시군구
areaNm: string //행정구역명
bdstNm: string //시설명
bdstUsgCd: string //건축물용도코드
daddr: string //주소
lawTrgtYn: string //법적의무대상여부
instlCmptnDt: string //설치완료일자
instlCst: number //설치비용
pntfColKnd: string //접수면종류
filtrTrtmfctYn: string //여과등처리시설유무
archArea: number //건축연면적
dtfcltCpct: number //처리용량(저류조용량)
wtrUsqty: number //연간사용량
utztnUsgCd: string //이용용도코드
anlOperCst: number //연간운영비
annRnwtQty: number //물사용량
jungsudo: number //중수도​이용량
dachae: number //대체수​이용량
lndwtr: number //조경용수
cleanToilUswtr: number //청소화장실용수
resn: number //세척살수용수
farmUswtr: number //농업용수
indstUswtr: number //공업용수
hydUswtr: number //친수용수
ithlEtcUswtr: number //기타
tmp: number //개소
guideStats: GuideStatProps[]
}
cityText: string;
ctpvCd: string; //시도
sggCd: string; //시군구
areaNm: string; //행정구역명
bdstNm: string; //시설명
bdstUsgCd: string; //건축물용도코드
daddr: string; //주소
lawTrgtYn: string; //법적의무대상여부
instlCmptnDt: string; //설치완료일자
instlCst: number; //설치비용
pntfColKnd: string; //접수면종류
filtrTrtmfctYn: string; //여과등처리시설유무
archArea: number; //건축연면적
dtfcltCpct: number; //처리용량(저류조용량)
wtrUsqty: number; //연간사용량
utztnUsgCd: string; //이용용도코드
anlOperCst: number; //연간운영비
annRnwtQty: number; //물사용량
jungsudo: number; //중수도​이용량
dachae: number; //대체수​이용량
lndwtr: number; //조경용수
cleanToilUswtr: number; //청소화장실용수
resn: number; //세척살수용수
farmUswtr: number; //농업용수
indstUswtr: number; //공업용수
hydUswtr: number; //친수용수
ithlEtcUswtr: number; //기타
tmp: number; //개소
guideStats: GuideStatProps[];
};
export type GuideStatProps = {
utztnUsgCd: string
splyUswtrUtztnQnt : number,
ruseFcltUtztnQnt: number
}
utztnUsgCd: string;
splyUswtrUtztnQnt: number;
ruseFcltUtztnQnt: number;
};
type ExcelType = {
[key: string]: string | number | undefined;
[key: string]: string | number | undefined;
};
const excelDownList: ExcelType[] = [];
const fetchRainStatList = async (year: string) => {
const res = await getFetch(fetchType.WR, `/reuseChk/rainy/stat/${year}`)
return res;
}
const res = await getFetch(fetchType.WR, `/reuseChk/rainy/stat/${year}`);
return res;
};
type rainStatActions = {
searchRainStatList: (year: string) => void
}
searchRainStatList: (year: string, city: SelectDataType[]) => void;
};
export type rainStatState = {
rainStat: {
rainStatHeadList: TableUpperProps[],
rainStatList: RainStatProps[],
excelList: ExcelType[]
rainDetailList : [][]
}
}
rainStat: {
rainStatHeadList: TableUpperProps[];
rainStatList: RainStatProps[];
excelList: ExcelType[];
rainDetailList: [][];
};
};
export type rainStatType = rainStatState & rainStatActions;
export const rainStatExport: rainStatState = {
rainStat: {
rainStatHeadList: rainStatHeadListExport,
rainStatList: [],
excelList: [],
rainDetailList : []
}
}
rainStat: {
rainStatHeadList: rainStatHeadListExport,
rainStatList: [],
excelList: [],
rainDetailList: [],
},
};
export const rainStatActionsExport = (
set: (fn: (state: rainStatState) => rainStatState) => void
set: (fn: (state: rainStatState) => rainStatState) => void
) => {
return {
searchRainStatList: async (year: string) => {
const res = await fetchRainStatList(year);
const cityArr: any[] = [];
res.forEach((item: RainStatProps) => {
return {
searchRainStatList: async (year: string, city: SelectDataType[]) => {
const res = await fetchRainStatList(year);
const cityArr: any[] = [];
let obj = cityArr.find((e) => {
return e.ctpvCd == item.ctpvCd
})
res.filter((resFilter: RainStatProps) =>
city.some((cityCd) =>
resFilter.ctpvCd?.trim() === cityCd.val.trim()
)
)
.forEach((item: RainStatProps) => {
let obj = cityArr.find((e) => {
return e.ctpvCd == item.ctpvCd;
});
if (obj) {
obj.instlCst += item.instlCst
obj.dtfcltCpct += item.dtfcltCpct
obj.wtrUsqty += item.wtrUsqty
obj.anlOperCst += item.anlOperCst
obj.tmp += 1
} else {
obj = {};
obj.ctpvCd = item.ctpvCd
obj.instlCst = item.instlCst
obj.tmp = 1
obj.dtfcltCpct = item.dtfcltCpct
obj.wtrUsqty = item.wtrUsqty
obj.anlOperCst = item.anlOperCst
if (obj) {
obj.instlCst += item.instlCst;
obj.dtfcltCpct += item.dtfcltCpct;
obj.wtrUsqty += item.wtrUsqty;
obj.anlOperCst += item.anlOperCst;
obj.tmp += 1;
} else {
obj = {};
obj.ctpvCd = item.ctpvCd;
obj.instlCst = item.instlCst;
obj.tmp = 1;
obj.dtfcltCpct = item.dtfcltCpct;
obj.wtrUsqty = item.wtrUsqty;
obj.anlOperCst = item.anlOperCst;
cityArr.push(obj)
cityArr.push(obj);
}
if (item.guideStats && item.guideStats.length > 0) {
item.guideStats.forEach((guide: GuideStatProps) => {
rainStatHeadListExport.forEach((headItem: TableUpperProps) => {
if (headItem.title == guide.utztnUsgCd) {
if (!obj[headItem.id] || typeof obj[headItem.id] !== "number")
obj[headItem.id] = 0;
if (typeof obj[headItem.id] === "number") {
obj[headItem.id] += guide.ruseFcltUtztnQnt;
}
}
});
});
}
});
if (item.guideStats && item.guideStats.length > 0) {
item.guideStats.forEach((guide: GuideStatProps) => {
rainStatHeadListExport.forEach((headItem: TableUpperProps) => {
const totalObj = {
ctpvCd: "0",
tmp: 0,
instlCst: 0, //설치비
dtfcltCpct: 0, //저류조용량
bdstUsgCd: 0, //연간사용량
lndwtr: 0, //조경용수
cleanToilUswtr: 0, //청소화장실용수
resn: 0, //세척살수용수
farmUswtr: 0, //농업용수
indstUswtr: 0, //공업용수
hydUswtr: 0, //친수용수
ithlEtcUswtr: 0, //기타
anlOperCst: 0, //연간운영비
} as any;
if (headItem.title == guide.utztnUsgCd) {
if (!obj[headItem.id] || typeof obj[headItem.id] !== "number") obj[headItem.id] = 0;
if (typeof obj[headItem.id] === "number") {
cityArr.forEach((item) => {
// if(item.ctpvCd === '0') return; // Skip total object if exists
totalObj.tmp += !isNaN(Number(item.tmp)) ? Number(item.tmp) : 0;
totalObj.instlCst += !isNaN(Number(item.instlCst))
? Number(item.instlCst)
: 0;
totalObj.dtfcltCpct += !isNaN(Number(item.dtfcltCpct))
? Number(item.dtfcltCpct)
: 0;
totalObj.bdstUsgCd += !isNaN(Number(item.bdstUsgCd))
? Number(item.bdstUsgCd)
: 0;
totalObj.lndwtr += !isNaN(Number(item.lndwtr))
? Number(item.lndwtr)
: 0;
totalObj.cleanToilUswtr += !isNaN(Number(item.cleanToilUswtr))
? Number(item.cleanToilUswtr)
: 0;
totalObj.resn += !isNaN(Number(item.resn)) ? Number(item.resn) : 0;
totalObj.farmUswtr += !isNaN(Number(item.farmUswtr))
? Number(item.farmUswtr)
: 0;
totalObj.indstUswtr += !isNaN(Number(item.indstUswtr))
? Number(item.indstUswtr)
: 0;
totalObj.hydUswtr += !isNaN(Number(item.hydUswtr))
? Number(item.hydUswtr)
: 0;
totalObj.ithlEtcUswtr += !isNaN(Number(item.ithlEtcUswtr))
? Number(item.ithlEtcUswtr)
: 0;
totalObj.anlOperCst += !isNaN(Number(item.anlOperCst))
? Number(item.anlOperCst)
: 0;
obj[headItem.id] += guide.ruseFcltUtztnQnt;
}
}
});
})
}
})
excelDownList.push({
ctpvCd: item.ctpvCd,
tmp: item.tmp,
instlCst: item.instlCst, //설치비
dtfcltCpct: item.dtfcltCpct, //저류조용량
bdstUsgCd: item.bdstUsgCd, //연간사용량
lndwtr: item.lndwtr, //조경용수
cleanToilUswtr: item.cleanToilUswtr, //청소화장실용수
resn: item.resn, //세척살수용수
farmUswtr: item.farmUswtr, //농업용수
indstUswtr: item.indstUswtr, //공업용수
hydUswtr: item.hydUswtr, //친수용수
ithlEtcUswtr: item.ithlEtcUswtr, //기타
anlOperCst: item.anlOperCst, //연간운영비
});
});
cityArr.forEach(item => {
excelDownList.push({
ctpvCd: item.ctpvCd,
tmp: item.tmp,
instlCst: item.instlCst, //설치비
dtfcltCpct: item.dtfcltCpct, //저류조용량
bdstUsgCd: item.bdstUsgCd, //연간사용량
lndwtr: item.lndwtr, //조경용수
cleanToilUswtr: item.cleanToilUswtr, //청소화장실용수
resn: item.resn, //세척살수용수
farmUswtr: item.farmUswtr, //농업용수
indstUswtr: item.indstUswtr, //공업용수
hydUswtr: item.hydUswtr, //친수용수
ithlEtcUswtr: item.ithlEtcUswtr, //기타
anlOperCst: item.anlOperCst, //연간운영비
})
})
//상세
const rainDetailList : RainStatProps[] = [];
res.forEach((item:RainStatProps) => {
const utztnUsgArray = new Array<string>();
item.guideStats.forEach((guideStat) => {
utztnUsgArray.push(guideStat.utztnUsgCd);
})
rainDetailList.push({
...item,
utztnUsgCd : utztnUsgArray.join(', '),
})
})
const excelDetailData = excelRainStat(rainDetailList);
/* const rainStatHeadList = data.map((item:RainStatProps) => ({
//상세
const rainDetailList: RainStatProps[] = [];
res.forEach((item: RainStatProps) => {
const utztnUsgArray = new Array<string>();
item.guideStats.forEach((guideStat) => {
utztnUsgArray.push(guideStat.utztnUsgCd);
});
rainDetailList.push({
...item,
utztnUsgCd: utztnUsgArray.join(", "),
});
});
const excelDetailData = excelRainStat(rainDetailList);
/* const rainStatHeadList = data.map((item:RainStatProps) => ({
...item,
ctpvCd:item.ctpvCd,
sggCd:item.sggCd,
@@ -172,14 +229,19 @@ export const rainStatActionsExport = (
way7:item.way7,
yearMoney:item.yearMoney,
})) */
set((state: rainStatState) => ({
rainStat: {
...state.rainStat,
rainDetailList: excelDetailData as [][],
rainStatList: cityArr,
excelList: excelDownList
}
}));
}
}
}
console.log(" cityArr ", cityArr);
console.log(" excelDownList ", excelDownList);
cityArr.unshift(totalObj);
set((state: rainStatState) => ({
rainStat: {
...state.rainStat,
rainDetailList: excelDetailData as [][],
rainStatList: cityArr,
excelList: excelDownList,
},
}));
},
};
};
+2 -1
View File
@@ -1,4 +1,5 @@
import type { RswtStatProps } from ".";
import { bdstUsgCd } from "../../common/code/basicCode";
export const excelRswtStat = (excelList:RswtStatProps[]) : (string | number)[][] => {
const excelData: (string | number)[][] = [];
@@ -14,7 +15,7 @@ export const excelRswtStat = (excelList:RswtStatProps[]) : (string | number)[][]
String(item.bdstNm) ?? "",
//건축물용도코드(빈칸)
//String(item.bdstUsgCd) ?? "",
"",
bdstUsgCd.find((cd)=> cd.val === item.bdstUsgCd.toString())?.text ?? "", //건축물용도
//주소
String(item.daddr) ?? "",
//법적의무대상여부
+77 -33
View File
@@ -6,7 +6,7 @@ import { excelRswtStat } from "./excel";
export type RswtStatProps = {
cityText: string //시도명
ctpvCd: string //시도
sggCd : string //시군구
sggCd: string //시군구
areaNm: string //행정구역명
bdstNm: string //시설명
daddr: string //주소
@@ -26,9 +26,10 @@ export type RswtStatProps = {
ithlEtcUswtr: number //기타
anlOperCst: number //연간운영비
guideStats: GuideStatProps[]
utztnUsgCd : string //이용코드
lawTrgtYn : string //법적의무대상여부
instlCmptnDt : string //설치완료일자
utztnUsgCd: string //이용코드
lawTrgtYn: string //법적의무대상여부
instlCmptnDt: string //설치완료일자
bdstUsgCd: number
}
export type GuideStatProps = {
@@ -37,7 +38,7 @@ export type GuideStatProps = {
}
type rswtStatActions = {
searchRswtStatList: (year: string) => void;
searchRswtStatList: (year: string, city: { val: string; text: string }[]) => void;
}
export type ExcelType = {
@@ -71,36 +72,44 @@ export const rswtStatActionsExport: (set: any) => rswtStatActions = (
set: any
) => {
return {
searchRswtStatList: async (year: string) => {
searchRswtStatList: async (year: string, city: { val: string; text: string }[]) => {
const res = await getFetch(fetchType.WR, `/reuseChk/reuseWater/stat/${year}`)
const data = res.filter(item => {
const code = item.ctpvCd.trim();
return city.some(el => el.val === code);
});
const cityArr: any[] = [];
res.forEach((item: RswtStatProps) => {
data.forEach((item: RswtStatProps) => {
let obj = cityArr.find((e) => {
return e.ctpvCd == item.ctpvCd
})
if (obj) {
obj.ctpvCnt += 1
obj.archArea += item.archArea
obj.filtrTrtmfctCpct += item.filtrTrtmfctCpct
obj.wtrUsqty += item.wtrUsqty
obj.rswtAltSum += (item.rswtrUsqty + item.altUswtrUtztnQnt)
obj.rswtrUsqty += item.rswtrUsqty
obj.altUswtrUtztnQnt += item.altUswtrUtztnQnt
obj.anlOperCst += item.anlOperCst
obj.ctpvCnt += 1 //개소
// obj.archArea += item.archArea 건축면적 삭제
obj.filtrTrtmfctCpct += item.filtrTrtmfctCpct //처리용량
obj.wtrUsqty += item.wtrUsqty //물사용량
obj.rswtAltSum += (item.rswtrUsqty + item.altUswtrUtztnQnt) //중수도+대체수
obj.rswtrUsqty += item.rswtrUsqty //중수도사용량
obj.altUswtrUtztnQnt += item.altUswtrUtztnQnt //대체수이용량
obj.anlOperCst += item.anlOperCst //연간운영비용
} else {
obj = {};
obj.ctpvCd = item.ctpvCd
obj.ctpvCnt = 1
obj.archArea = item.archArea
obj.filtrTrtmfctCpct = item.filtrTrtmfctCpct
obj.wtrUsqty = item.wtrUsqty
obj.rswtAltSum = item.rswtrUsqty + item.altUswtrUtztnQnt
obj.rswtrUsqty = item.rswtrUsqty
obj.altUswtrUtztnQnt = item.altUswtrUtztnQnt
obj.anlOperCst = item.anlOperCst
obj = {
ctpvCd: item.ctpvCd,
ctpvCnt: 1,
filtrTrtmfctCpct: item.filtrTrtmfctCpct,
wtrUsqty: item.wtrUsqty,
rswtAltSum: item.rswtrUsqty + item.altUswtrUtztnQnt,
rswtrUsqty: item.rswtrUsqty,
altUswtrUtztnQnt: item.altUswtrUtztnQnt,
anlOperCst: item.anlOperCst,
lndwtr: 0,
cleanToilUswtr: 0,
farmUswtr: 0,
indstUswtr: 0,
hydUswtr: 0,
ithlEtcUswtr: 0,
}
cityArr.push(obj)
}
@@ -120,11 +129,47 @@ export const rswtStatActionsExport: (set: any) => rswtStatActions = (
}
});
const total: any = {
ctpvCd: "0",
ctpvCnt: 0,
filtrTrtmfctCpct: 0,
wtrUsqty: 0,
rswtAltSum: 0,
rswtrUsqty: 0,
altUswtrUtztnQnt: 0,
anlOperCst: 0,
lndwtr: 0,
cleanToilUswtr: 0,
farmUswtr: 0,
indstUswtr: 0,
hydUswtr: 0,
ithlEtcUswtr: 0,
};
cityArr.forEach(item => {
total.ctpvCnt += item.ctpvCnt;
total.archArea += item.archArea;
total.filtrTrtmfctCpct += item.filtrTrtmfctCpct;
total.wtrUsqty += item.wtrUsqty;
total.rswtAltSum += item.rswtAltSum;
total.rswtrUsqty += item.rswtrUsqty;
total.altUswtrUtztnQnt += item.altUswtrUtztnQnt;
total.anlOperCst += item.anlOperCst;
total.lndwtr += item.lndwtr;
total.cleanToilUswtr += item.cleanToilUswtr;
total.farmUswtr += item.farmUswtr;
total.indstUswtr += item.indstUswtr;
total.hydUswtr += item.hydUswtr;
total.ithlEtcUswtr += item.ithlEtcUswtr;
});
cityArr.unshift(total);
cityArr.forEach(item => {
excelDownList.push({
ctpvCd: item.ctpvCd,
ctpvCnt: item.ctpvCnt,
archArea: item.archArea,
// archArea: item.archArea,
filtrTrtmfctCpct: item.filtrTrtmfctCpct,
wtrUsqty: item.wtrUsqty,
rswtAltSum: item.rswtAltSum,
@@ -141,19 +186,18 @@ export const rswtStatActionsExport: (set: any) => rswtStatActions = (
})
//상세
const rswtDetailList : RswtStatProps[] = [];
res.forEach((item:RswtStatProps) => {
const rswtDetailList: RswtStatProps[] = [];
res.forEach((item: RswtStatProps) => {
const utztnUsgArray = new Array<string>();
item.guideStats.forEach((guideStat) => {
utztnUsgArray.push(guideStat.utztnUsgCd);
})
rswtDetailList.push({
...item,
rswtAltSum : item.rswtrUsqty + item.altUswtrUtztnQnt,
utztnUsgCd : utztnUsgArray.join(', '),
rswtAltSum: item.rswtrUsqty + item.altUswtrUtztnQnt,
utztnUsgCd: utztnUsgArray.join(', '),
})
});
const excelDetailData = excelRswtStat(rswtDetailList);
set((state: rswtStatState) => ({
rswtStat: {
+10 -4
View File
@@ -98,6 +98,7 @@ import { rainStatActionsExport, rainStatExport, type rainStatState, type rainSta
import { rswtStatActionsExport, rswtStatExport, type rswtStatState, type rswtStatType } from "./stats/rswtStat";
//import { isLogin } from "./common/login";
import { LoginApi } from "@/src/entities/auth";
import { authActionsExport, authStateExport, type authState, type authType } from "./common/auth";
export type WrStore = comCodeType &
pubFacType &
@@ -124,7 +125,9 @@ export type WrStore = comCodeType &
ruseCaseType&
rainStatType&
rswtStatType&
comFcltType
comFcltType &
authType
;
export const StoreZus = (
@@ -153,7 +156,8 @@ export const StoreZus = (
drgtState&
ruseCaseState&
rainStatState&
rswtStatState
rswtStatState&
authState
= {
...comCodeStateExport,
...pubFacStateExport,
@@ -180,7 +184,8 @@ export const StoreZus = (
...ruseCaseStateExport,
...rainStatExport,
...rswtStatExport,
...comFcltStateExport
...comFcltStateExport,
...authStateExport
}
) => {
return createStore<WrStore>()((set) => {
@@ -218,7 +223,8 @@ export const StoreZus = (
...drgtActionsExport(set),
...ruseCaseActionsExport(set),
...rainStatActionsExport(set),
...rswtStatActionsExport(set)
...rswtStatActionsExport(set),
...authActionsExport(set)
};
});
};
+61 -31
View File
@@ -3,6 +3,7 @@ import type { TableUpperProps } from "@/app/store/common/type/header";
import type { rainChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn";
import type { rswtChkZodType } from "@/app/store/prfmncReg/chkgdnReg/rswrtChkgdn";
import { Checkbox, Input, TableCell, TableRow } from "@common/components/ui";
import { formatCommaNumber, handleCommaNumberChange } from "./commom";
export const rainChkTableData = (chkData: rainChkZodType[]) => {
// 1. chkgdnSn + utztnUsgCd 기준 누계 정보 만들기
@@ -141,7 +142,12 @@ export const chRowspanTable = (
) : key === "order" ? (
++order
) : (
value
// value
(["anlOperCst", "dtfcltCpct", "prcsCpct"].includes(head.id)) ? (
formatCommaNumber(value)
) : (
<>{value}</>
)
)}
</TableCell>
);
@@ -155,26 +161,44 @@ export const chRowspanTable = (
onClick={() => handleCellClick(rowIndex, head.id)}
>
{head.edit === true ? (
<Input
className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`}
type={head.type}
onChange={(e) => {
handleChange(rowIndex, head.id, e.target.value);
}}
value={value || ""}
disabled={!selectedIds.includes(row.chkgdnSn)}
maxLength={numSize}
//input type number일때 slice 처리
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
if (head.type === 'number' && e.target.value.length > numSize) {
e.target.value = e.target.value.slice(0, numSize);
}
}}
/>
(["levyAmt", "anlOperCst", "dtfcltCpct", "prcsCpct"].includes(head.id)) ? (
<Input
className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`}
type={head.type}
onChange={(e) => {
handleCommaNumberChange(e, val =>
handleChange(rowIndex, head.id, val))
}}
value={formatCommaNumber(value) || ""}
disabled={!selectedIds.includes(row.chkgdnSn)}
maxLength={numSize}
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
if (head.type === 'number' && e.target.value.length > numSize) {
e.target.value = e.target.value.slice(0, numSize);
}
}}
/>
) : (
<Input
className={`${head.type === "number" ? "text-right" : "text-center"} !text-xl`}
type={head.type}
onChange={(e) => {
handleChange(rowIndex, head.id, e.target.value);
}}
value={value || ""}
disabled={!selectedIds.includes(row.chkgdnSn)}
maxLength={numSize}
onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
if (head.type === 'number' && e.target.value.length > numSize) {
e.target.value = e.target.value.slice(0, numSize);
}
}}
/>
)
) : (
(head.id === "totalSplyUswtrUtztnQnt" || head.id === "totalRuseFcltUtztnQnt" || head.id === "splyUswtrUtztnQnt" || head.id === "ruseFcltUtztnQnt") ? (
<span className="underline text-blue-600 cursor-pointer">
{value}
(["totalSplyUswtrUtztnQnt", "totalRuseFcltUtztnQnt", "splyUswtrUtztnQnt", "ruseFcltUtztnQnt", "levyAmt"].includes(head.id)) ? (
<span className={["totalSplyUswtrUtztnQnt", "totalRuseFcltUtztnQnt", "splyUswtrUtztnQnt", "ruseFcltUtztnQnt"].includes(head.id) ? "underline text-blue-600 cursor-pointer" : ""}>
{formatCommaNumber(value)}
</span>
) : (
<>{value}</>
@@ -182,7 +206,6 @@ export const chRowspanTable = (
)}
</TableCell>
);
})}
</TableRow>
))) : (
@@ -210,20 +233,18 @@ export const headVisibleChange = (headList: TableUpperProps[], isEdit: boolean)
const handleChange = (
rowIndex: number,
field: any,
value: string | number,
value: string,
setInputData: (data: any) => void
) => {
if (Number(value) < 0 || !Number(value)) {
value = 0;
} else {
value = Number(value);
value = "0";
}
setInputData((prevData: any) =>
prevData?.map((row: any, index: number) => {
if (index === rowIndex) {
return {
...row,
[field]: value,
[field]: Number(value.replace(/,/g, "")),
};
}
return row;
@@ -271,7 +292,7 @@ export const InputTableBody = (
// 총합계 행이면 "구분"에서 colSpan=2로 병합
if (
data["구분"] === 0 &&
(data["구분"] === 0 || data["용수명"] === 0) &&
head.id === "구분"
) {
return (
@@ -286,18 +307,27 @@ export const InputTableBody = (
}
// 총합계(합계) 행이면 "용수명" 컬럼은 렌더링하지 않음
if (
data["구분"] === 0 &&
(data["구분"] === 0 || data["용수명"] === 0) &&
head.id === "용수명"
) {
return null;
}
// 총합계 행의 나머지 셀에도 색상 적용
if (data["구분"] === 0 || data["용수명"] === 0) {
return (
<TableCell key={head.id + headIndex} className="bg-[#d5e1eb] font-bold text-right">
{Number(data[head.id]) ? formatCommaNumber(data[head.id as keyof any]) : data[head.id as keyof any] ?? ""}
</TableCell>
);
}
// mergeCell 처리
if (head.mergeCell) {
const rowSpan = getRowSpan(chgRes, head.id, dataIndex);
if (rowSpan === 0) return null;
return (
<TableCell key={head.id + headIndex} rowSpan={rowSpan} className={`w-36 align-middle text-center whitespace-nowrap ${bgClass}`}>
{data[head.id as keyof any] ?? ""}
{Number(data[head.id]) ? formatCommaNumber(data[head.id as keyof any]) : data[head.id as keyof any] ?? ""}
</TableCell>
);
}
@@ -311,7 +341,7 @@ export const InputTableBody = (
onChange={(e) =>
handleChange(dataIndex, head.id, e.target.value, setInputData)
}
value={data[head.id as keyof any] ?? ""}
value={formatCommaNumber(data[head.id as keyof any]) ?? ""}
maxLength={numSize}
/>
</TableCell>
@@ -324,7 +354,7 @@ export const InputTableBody = (
// `}
className={`${textAlignClass} !text-xl w-full h-10`}
>
{data[head.id as keyof any] ?? ""}
{Number(data[head.id]) ? formatCommaNumber(data[head.id as keyof any]) : data[head.id as keyof any] ?? ""}
</div>
</TableCell>
);
+11
View File
@@ -116,6 +116,17 @@ export const handleCommaNumberChange = (
onChange(raw === "" ? "" : Number(raw));
};
export const handleOnlyNumberChange = (
e: React.ChangeEvent<HTMLInputElement>,
onChange: (value: number | "") => void
) => {
// 콤마 제거 후 숫자와 소수점만 남기기
const cleaned = e.target.value.replace(/,/g, "").replace(/[^0-9.]/g, "");
// 숫자 및 소수점 외 입력 차단
if (!/^\d*\.?\d*$/.test(cleaned)) return;
onChange(cleaned === "" ? "" : Number(cleaned));
};
// onchange 텍스트를 숫자로 and ,제거
export const handleMinusNumberChange = (
e: React.ChangeEvent<HTMLInputElement>,
@@ -31,10 +31,12 @@ export default function ConCostForm({
form,
type,
selectionVersion,
readonly = false,
}: {
form: UseFormReturn<DmdCoReqType>;
type: string;
selectionVersion: number;
readonly: boolean;
}) {
const {
constCostRes,
@@ -58,14 +60,11 @@ export default function ConCostForm({
}
}, [ref, getConstCostFee, getRateFee]);
useEffect(() => {
// 다른 행을 선택하면(selectionVersion 변경) 체크박스 상태를 초기화합니다.
setCheckFinish(false);
}, [selectionVersion]);
const zipDowonLoad = () => {
fetch(`/2024_constarctFeeProgram.zip`, {}).then(async (response) => {
const blobRet = await response.blob();
@@ -85,7 +84,7 @@ export default function ConCostForm({
const calculateConstCost = useCallback(() => {
const usgPrcsProcs = usgPrcsProcsWatch;
if (!dmndQtyWatch) {
toast.error("요구수량(M3/d)을 확인해주세요 계산할수 없습니다. ");
toast.error("요구수량(m³/일)을 확인해주세요 계산할수 없습니다. ");
return;
}
if (usgPrcsProcs === null || usgPrcsProcs === undefined) {
@@ -165,29 +164,32 @@ export default function ConCostForm({
cstrnCst: value.demandCst.cstrnCst || 0,
fcltSbsdCstrnCst: value.demandCst.fcltSbsdCstrnCst || 0,
prcsFcltCpctCstrnCst: value.demandCst.prcsFcltCpctCstrnCst || 0,
flg: checkFinish?'Checked':'Sub',
flg: checkFinish ? "Checked" : "Sub",
rgtr: TEST_UUID,
};
if (checkFinish) {
toast((t) => (
<span className="flex flex-col items-center text-2xl" >
검토완료 변경시 공사비는 변경할수 없습니다.
<span className="flex flex-col items-center text-2xl">
검토완료 변경시 공사비는 변경할수 없습니다.
<br />
진행하시겠습니까?
<div className="flex gap-2 mt-2">
<Button
size='sm'
onClick={() => {
toast.dismiss(t.id);
coMatRvwUpdate("11000SW001R1", form.getValues("dmdInfoId"), data);
}}
>
확인
</Button>
<Button
size='sm'
onClick={() => toast.dismiss(t.id)}>취소</Button>
<Button
size="sm"
onClick={() => {
toast.dismiss(t.id);
coMatRvwUpdate(
"11000SW001R1",
form.getValues("dmdInfoId"),
data
);
}}
>
확인
</Button>
<Button size="sm" onClick={() => toast.dismiss(t.id)}>
취소
</Button>
</div>
</span>
));
@@ -229,6 +231,7 @@ export default function ConCostForm({
className="mr-3"
size={"sm"}
onClick={form.handleSubmit(onSubmit)}
disabled={readonly}
>
저장
</Button>
@@ -236,9 +239,14 @@ export default function ConCostForm({
<Checkbox
className="ml-3 mr-6"
checked={checkFinish}
onCheckedChange={(checked) =>
onCheckedChange={
(checked) => {
if (readonly) return;
setCheckFinish(checked === true);
}
// 'indeterminate' 상태를 무시하고 순수 boolean 값으로만 상태를 업데이트합니다.
setCheckFinish(checked === true)}
}
></Checkbox>
<Label>관로 표준공사비 산정 프로그램</Label>
<Button
@@ -278,7 +286,7 @@ export default function ConCostForm({
control={form.control}
name="dmndQty"
render={({ field }) => (
<FormUi label="요구수량(M3/d)">
<FormUi label="요구수량(m³/일)">
<Input
placeholder=""
type="number"
@@ -315,7 +323,7 @@ export default function ConCostForm({
]}
pageSize={0}
total={0}
cellClick={() => {}}
cellClick={undefined}
onPageChange={() => {}}
/>
</>
@@ -344,13 +352,13 @@ export default function ConCostForm({
control={form.control}
name="dmndQty"
render={({ field }) => (
<FormUi label="처리시설 용량(요구수량 * 365일)">
<FormUi label="처리시설용량(m³/일)">
<Input
placeholder=""
type="number"
step="0.001"
onChange={(e) => {
console.log('dmndQty ', e)
console.log("dmndQty ", e);
//field.onChange(Number(e.target.value) * 365 );
}}
value={Number(field.value) * 365 || 0}
@@ -377,7 +385,7 @@ export default function ConCostForm({
}
childrenBody={
<>
<ConstCostFeeTable/>
<ConstCostFeeTable />
</>
}
bodyClassName={"w-[40vw] h-full"}
@@ -414,8 +422,7 @@ export default function ConCostForm({
}
childrenBody={
<>
<RateFeeTableModal/>
<RateFeeTableModal />
</>
}
bodyClassName={"w-[22vw]"}
@@ -476,8 +483,7 @@ export default function ConCostForm({
type="number"
step="0.01"
onChange={(e) => {
console.log('totalConstCost ', e)
console.log("totalConstCost ", e);
}}
value={field.value ?? 0}
readOnly
@@ -521,6 +527,9 @@ export default function ConCostForm({
type="number"
step="0.01"
onChange={(e) => {
if(readonly) return;
field.onChange(Number(e.target.value));
}}
value={field.value ?? 0}
@@ -2,15 +2,14 @@ import { useWrStore } from "@/app/store";
import { numSize, txtSize } from "@/app/store/common/code/basicCode";
import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
import { formH1Class } from "@/components/lib/class/comClass";
import { handleCommaNumberChange } from "@/components/lib/func/commom";
import {
DatePicker,
FormField,
FormUi,
DatePicker,
SelectBox,
type SelectDataType,
} from "@common/business_components";
import { Input } from "@common/components";
import { Input } from "@common/components";
import { useEffect, useState } from "react";
export default function BdstReg({ form, type }: { form: any; type?: string }) {
@@ -18,39 +17,39 @@ export default function BdstReg({ form, type }: { form: any; type?: string }) {
return state;
});
const {userSiSggCd } =code
const { userSiSggCd } = code
const [useCityCd, setUserCityCd] = useState<SelectDataType[]>([])
const [useSggCd, setUserSggCd] = useState<SelectDataType[]>([])
// const [selectSgg, setSelectSgg] = useState<SelectDataType[] | undefined>();
// const [objSearch, setObjSearch] = useState<objSearchType>({
// sgg: "",
// city: "",
// });
useEffect(() =>{
if(userSiSggCd.length===2 && code.cityCd.length>0){
useEffect(() => {
if (userSiSggCd.length === 2 && code.cityCd.length > 0) {
const city = code.cityCd.filter((item) => item.val === userSiSggCd)
const sgg = code.sggCd.filter((item) => item.val.slice(0,2) === userSiSggCd )
sgg.unshift({text:'전체' , val:'0'})
const sgg = code.sggCd.filter((item) => item.val.slice(0, 2) === userSiSggCd)
sgg.unshift({ text: '전체', val: '0' })
setUserCityCd(city) // Fix: Ensure city is of type SelectDataType[]
setUserSggCd(sgg)
if (city[0]?.val) {
// 여기 중요
queueMicrotask(() => {
form.setValue("ctpvCd", Number(city[0]?.val), { shouldDirty: true, shouldTouch: true, shouldValidate: true });
});
// 여기 중요
queueMicrotask(() => {
form.setValue("ctpvCd", Number(city[0]?.val), { shouldDirty: true, shouldTouch: true, shouldValidate: true });
});
}
}else if(userSiSggCd.length===5 && code.cityCd.length>0 && code.sggCd.length>0) {
const city = code.cityCd.filter((item) => item.val === userSiSggCd.slice(0,2))
} else if (userSiSggCd.length === 5 && code.cityCd.length > 0 && code.sggCd.length > 0) {
const city = code.cityCd.filter((item) => item.val === userSiSggCd.slice(0, 2))
const sgg = code.sggCd.filter((item) => item.val === userSiSggCd)
setUserSggCd(sgg)
setUserCityCd(city)
form.setValue('ctpvCd',Number(city[0]?.val) )
form.setValue('sggCd',Number(sgg[0]?.val) )
form.setValue('ctpvCd', Number(city[0]?.val))
form.setValue('sggCd', Number(sgg[0]?.val))
}
},[form, userSiSggCd, code.cityCd, code.sggCd])
}, [form, userSiSggCd, code.cityCd, code.sggCd])
@@ -70,15 +69,13 @@ export default function BdstReg({ form, type }: { form: any; type?: string }) {
useEffect(() =>{
console.log('form.formState ', form.watch())
},[form.formState])
useEffect(() => {
console.log('form.formState ', form.watch("archArea"))
}, [form.formState])
return (
<>
<h1 className={formH1Class}> { type !== "HTB"?"건축물 기본 정보": '시설 기본 정보'}</h1>
<h1 className={formH1Class}> {type !== "HTB" ? "건축물 기본 정보" : '시설 기본 정보'}</h1>
<div className="grid grid-cols-6 gap-2 mt-4">
<div className="col-span-3">
<FormField
@@ -127,16 +124,16 @@ export default function BdstReg({ form, type }: { form: any; type?: string }) {
control={form.control}
name="bdstNm"
render={({ field }) => (
<FormUi label={ type !== "HTB"?"건축물명": '시설명'}>
<FormUi label={type !== "HTB" ? "건축물명" : '시설명'}>
<Input
className={selectClass}
placeholder= {type !== "HTB"?"건축물 명 입력하세요":'시설명 입력하세요' }
placeholder={type !== "HTB" ? "건축물 명 입력하세요" : '시설명 입력하세요'}
type="text"
onChange={(e) => {
field.onChange(e.target.value)
}}
value={field.value||''}
maxLength={txtSize}
onChange={(e) => {
field.onChange(e.target.value)
}}
value={field.value || ''}
maxLength={txtSize}
/>
</FormUi>
)}
@@ -147,16 +144,16 @@ export default function BdstReg({ form, type }: { form: any; type?: string }) {
control={form.control}
name="daddr"
render={({ field }) => (
<FormUi label= { type !== "HTB"?"건축물 주소": '시설 주소'} >
<FormUi label={type !== "HTB" ? "건축물 주소" : '시설 주소'} >
<Input
className={selectClass}
placeholder="위치를 입력해주세요"
type="search"
onChange={(e) => {
field.onChange(e.target.value)
}}
value={field.value||''}
maxLength={50}
}}
value={field.value || ''}
maxLength={50}
/>
</FormUi>
)}
@@ -168,7 +165,7 @@ export default function BdstReg({ form, type }: { form: any; type?: string }) {
control={form.control}
name="frstArchPrmsnDt"
render={({ field }) => (
<FormUi label= { type !== "HTB"?"최초건축허가일": '준공년도'} >
<FormUi label={type !== "HTB" ? "최초건축허가일" : '준공년도'} >
<DatePicker
mode={"single"}
field={{
@@ -221,9 +218,9 @@ export default function BdstReg({ form, type }: { form: any; type?: string }) {
placeholder="면적을 입력하세요"
type="text"
onChange={(e) => {
handleCommaNumberChange(e, field.onChange);
field.onChange(e.target.value)
}}
value={field.value||''}
value={field.value || ''}
maxLength={numSize}
/>
</FormUi>
@@ -251,7 +248,7 @@ export default function BdstReg({ form, type }: { form: any; type?: string }) {
/>
</div>
</div>
</>
</>
) : (
<></>
)}
@@ -12,6 +12,7 @@ import {
confirmToast,
formatCommaNumber,
handleCommaNumberChange,
handleOnlyNumberChange,
} from "@/components/lib/func/commom";
import {
Form,
@@ -19,9 +20,9 @@ import {
FormUi,
SelectBox,
} from "@common/business_components/ui";
import { Button, Input, ScrollArea } from "@common/components/ui";
import { Button, Input, Label, ScrollArea } from "@common/components/ui";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
@@ -40,6 +41,8 @@ export default function HtdflRegForm({
setIsModal?: (modal: boolean) => void;
}) {
const { code, htdflBdstUpdate, htdflBdstReg } = useWrStore((state) => state);
const [frontPHdata, setFrontPHdata] = useState("");
const [backPHdata, setBackPHdata] = useState("");
const defaultValues: z.infer<typeof hdtflZod> = hdtflZod.parse({});
@@ -51,7 +54,7 @@ export default function HtdflRegForm({
const bdstNm = form.watch("bdstNm");
const isPowerPlant = bdstNm?.includes("발전소");
const { t } = useTranslation('base');
const { t } = useTranslation("base");
const onSubmit = (values: z.infer<typeof hdtflZod>) => {
if (isModal) {
const data = regCtpvCd ? regCtpvCd : regSggcd ? regSggcd : "noCd";
@@ -63,13 +66,12 @@ export default function HtdflRegForm({
htdflBdstReg(values, data);
if (setIsModal) setIsModal(false);
};
confirmToast(t('isInsertMsg'), handleConfirm);
confirmToast(t("isInsertMsg"), handleConfirm);
} else {
const handleConfirm = async () => {
htdflBdstUpdate(values, "0");
};
confirmToast(t('isUpdateMsg'), handleConfirm);
confirmToast(t("isUpdateMsg"), handleConfirm);
}
};
@@ -97,12 +99,51 @@ export default function HtdflRegForm({
})),
};
};
const isSetFrontPh = useCallback(
(frontPHdata: string) => {
setFrontPHdata(frontPHdata);
if (!frontPHdata) {
form.setValue(`reuseBuilding.0.htdflObj.ph`, "");
return;
}
const PHdata = form.getValues(`reuseBuilding.0.htdflObj.ph`);
let backPH;
if (PHdata && String(PHdata).includes("~")) {
backPH = PHdata.split("~")[1];
} else {
backPH = String(Number(frontPHdata) + 1);
}
const MatchData = `${frontPHdata}~${backPH}`;
form.setValue(`reuseBuilding.0.htdflObj.ph`, MatchData);
},
[form]
);
const isSetBackPh = useCallback(
(backPHdata: string) => {
setBackPHdata(backPHdata);
if (!backPHdata) {
form.setValue(`reuseBuilding.0.htdflObj.ph`, "");
return;
}
const PHdata = form.getValues(`reuseBuilding.0.htdflObj.ph`);
let frontPH;
if (PHdata && String(PHdata).includes("~")) {
frontPH = PHdata.split("~")[0];
} else {
frontPH = String(Math.max(Number(backPHdata) - 1, 0));
}
const MatchData = `${frontPH}~${backPHdata}`;
form.setValue(`reuseBuilding.0.htdflObj.ph`, MatchData);
},
[form]
);
const [divStyle, setDivStyle] = useState("h-[53vh]");
useEffect(() => {
if (isModal === true) {
setDivStyle("h-[53vh] max-h-[37vh]")
setDivStyle("h-[53vh] max-h-[37vh]");
} else if (readonly === true) {
setDivStyle("h-[62vh]")
setDivStyle("h-[62vh]");
} else {
setDivStyle("h-[57vh]")
}
@@ -116,7 +157,25 @@ export default function HtdflRegForm({
useEffect(() => {
// Case 1: 수정 또는 '복사하여 등록' 등 데이터가 주입되는 경우
if (htdflForm && Object.keys(htdflForm).length > 0) {
const htdflPH = htdflForm.reuseBuilding[0]?.htdflObj.ph
if(htdflPH && String(htdflPH).includes("~")){
const [frontPH, backPH] = htdflPH.split("~");
if (frontPH) {
setFrontPHdata(frontPH);
}
if (backPH) {
setBackPHdata(backPH);
}
} else {
setFrontPHdata("");
setBackPHdata("");
}
form.reset(cleanHtdflData(htdflForm));
}else{
form.reset();
}
// Case 2: 데이터가 없는 순수 신규 등록 모드인 경우
if (isModal) {
@@ -125,15 +184,33 @@ export default function HtdflRegForm({
const firstHtdUtztnUsgCd = code.htdUtztnUsgCd?.[0]?.val;
if (firstHtdPowerMthdCd) {
form.setValue('reuseBuilding.0.htdflObj.etgtType', firstHtdPowerMthdCd, { shouldDirty: true });
form.setValue(
"reuseBuilding.0.htdflObj.etgtType",
firstHtdPowerMthdCd,
{ shouldDirty: true }
);
}
if (firstYnValue) {
form.setValue('reuseBuilding.0.htdflObj.plwtYn', firstYnValue as "Y" | "N", { shouldDirty: true });
form.setValue('reuseBuilding.0.htdflObj.prcsProcsYn', firstYnValue as "Y" | "N", { shouldDirty: true });
form.setValue('reuseBuilding.0.htdflObj.fmYn', firstYnValue as "Y" | "N", { shouldDirty: true });
form.setValue(
"reuseBuilding.0.htdflObj.plwtYn",
firstYnValue as "Y" | "N",
{ shouldDirty: true }
);
form.setValue(
"reuseBuilding.0.htdflObj.prcsProcsYn",
firstYnValue as "Y" | "N",
{ shouldDirty: true }
);
form.setValue(
"reuseBuilding.0.htdflObj.fmYn",
firstYnValue as "Y" | "N",
{ shouldDirty: true }
);
}
if (firstHtdUtztnUsgCd) {
form.setValue('reuseBuilding.0.htdflObj.utztnUsg', firstHtdUtztnUsgCd, { shouldDirty: true });
form.setValue("reuseBuilding.0.htdflObj.utztnUsg", firstHtdUtztnUsgCd, {
shouldDirty: true,
});
}
}
}, [htdflForm, code, form]);
@@ -142,12 +219,37 @@ export default function HtdflRegForm({
if (!isPowerPlant) {
form.setValue(
"reuseBuilding.0.htdflObj.etgtType",
"해당없음", // 빈 문자열로 초기화
{ shouldDirty: true } // dirty 상태로 남길지 여부는 취사선택
"해당없음", // 빈 문자열로 초기화
{ shouldDirty: true } // dirty 상태로 남길지 여부는 취사선택
);
}
}, [isPowerPlant, form]);
// useEffect(() => {
// const watchPH = form.getValues(`items.${indexMng}.fcBizs.${indexBiz}.ph`);
// const checkPkAndCycle =
// form.getValues(`items.${indexMng}.pbnstRuseFcltId`) +
// String(form.getValues(`items.${indexMng}.fcBizs.${indexBiz}.cycl`));
// console.log("checkPkAndCycle ", checkPkAndCycle);
// if (chekcPk !== checkPkAndCycle) {
// if (watchPH && watchPH !== undefined) {
// const [frontPH, backPH] = watchPH.split("~");
// if (frontPH) {
// setFrontPHdata(frontPH);
// }
// if (backPH) {
// setBackPHdata(backPH);
// }
// } else {
// setFrontPHdata("0");
// setBackPHdata("0");
// }
// setCheakPk(checkPkAndCycle);
// }
// }, [form.getValues(`items.${indexMng}.fcBizs.${indexBiz}.ph`), chekcPk]);
return (
<div className="!mx-[1.6rem] !p-0r">
<Form {...form}>
@@ -155,7 +257,7 @@ export default function HtdflRegForm({
{/* <div className="flex justify-between items-center mx-3"> */}
<div>
<h1 className="text-2xl font-bold text-gray-900 mt-3 ml-1">
{readonly && `(${htdflForm?.bdstNm})`}
{readonly && `(시설명 : ${htdflForm?.bdstNm})`}
</h1>
<div className="grid grid-cols-12 flex items-center card-header">
<h1 className="text-2xl font-medium text-label col-span-10">
@@ -198,9 +300,13 @@ export default function HtdflRegForm({
label={""}
selectClass={selectClass}
selectArray={code.htdPowerMthdCd}
onSelectValue={readonly ? () => { } : field.onChange}
onSelectValue={readonly ? () => {} : field.onChange}
// value={field.value ?? ""}
value={field.value || (code?.htdPowerMthdCd[0] &&code?.htdPowerMthdCd[0].val)}
value={
field.value ||
(code?.htdPowerMthdCd[0] &&
code?.htdPowerMthdCd[0].val)
}
readOnly={readonly || !isPowerPlant}
/>
</FormUi>
@@ -241,7 +347,7 @@ export default function HtdflRegForm({
label={""}
selectClass={selectClass}
selectArray={code.yn}
onSelectValue={readonly ? () => { } : field.onChange}
onSelectValue={readonly ? () => {} : field.onChange}
value={field.value ?? ""}
readOnly={readonly}
/>
@@ -254,8 +360,9 @@ export default function HtdflRegForm({
<h1 className={formH1Class}>온배수 시설 운영현황</h1>
</div>
<div className="grid grid-cols-10 gap-1 mt-4">
<div className="col-span-5">
{/* <div className="grid grid-cols-10 gap-1 mt-4"> */}
<div className="grid grid-cols-12 gap-4">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.orgwtWtritSpt"
@@ -265,9 +372,9 @@ export default function HtdflRegForm({
className={selectClass}
placeholder=""
type="text"
value={field.value ?? ''}
value={field.value ?? ""}
onChange={(e) => {
if (!readonly) field.onChange((e.target.value));
if (!readonly) field.onChange(e.target.value);
}}
readOnly={readonly}
maxLength={txtSize}
@@ -276,7 +383,7 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.orgwtOcrnProcs"
@@ -297,7 +404,7 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.wtritEntrcTp"
@@ -319,7 +426,7 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.emsnExitTp"
@@ -341,12 +448,12 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.amtgnr"
render={({ field }) => (
<FormUi label="발생량(m³/년)">
<FormUi label="발생량(m³/일)">
<Input
className={selectClass}
placeholder="1,000,000"
@@ -363,7 +470,7 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.prcsProcsYn"
@@ -374,7 +481,7 @@ export default function HtdflRegForm({
label={""}
selectClass={selectClass}
selectArray={code.yn}
onSelectValue={readonly ? () => { } : field.onChange}
onSelectValue={readonly ? () => {} : field.onChange}
value={field.value ?? ""}
readOnly={readonly}
/>
@@ -382,7 +489,7 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.prcsFcltCpct"
@@ -404,7 +511,7 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.fmYn"
@@ -415,7 +522,7 @@ export default function HtdflRegForm({
selectClass={selectClass}
label={""}
selectArray={code.yn}
onSelectValue={readonly ? () => { } : field.onChange}
onSelectValue={readonly ? () => {} : field.onChange}
value={field.value ?? ""}
readOnly={readonly}
/>
@@ -423,12 +530,12 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.utztnCpct"
render={({ field }) => (
<FormUi label="이용량(m³/년)">
<FormUi label="이용량(m³/일)">
<Input
className={selectClass}
placeholder="1,000,000"
@@ -445,7 +552,7 @@ export default function HtdflRegForm({
)}
/>
</div>
<div className="col-span-5">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.utztnUsg"
@@ -456,7 +563,7 @@ export default function HtdflRegForm({
selectClass={selectClass}
label={""}
selectArray={code.htdUtztnUsgCd}
onSelectValue={readonly ? () => { } : field.onChange}
onSelectValue={readonly ? () => {} : field.onChange}
value={field.value ?? ""}
readOnly={readonly}
/>
@@ -477,18 +584,25 @@ export default function HtdflRegForm({
name="reuseBuilding.0.htdflObj.grssClfg"
render={({ field }) => (
<FormUi label="총대장균군(개/mg)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
@@ -500,18 +614,25 @@ export default function HtdflRegForm({
name="reuseBuilding.0.htdflObj.tn"
render={({ field }) => (
<FormUi label="총질소(T-N)(mg/L)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder=""
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={6}
/>{" "}
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
@@ -548,18 +669,25 @@ export default function HtdflRegForm({
name="reuseBuilding.0.htdflObj.tph"
render={({ field }) => (
<FormUi label="총인(T-P)(mg/L)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
@@ -573,41 +701,57 @@ export default function HtdflRegForm({
name="reuseBuilding.0.htdflObj.trbt"
render={({ field }) => (
<FormUi label="탁도(NTU)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
handleOnlyNumberChange(e, field.onChange);
}}
value={
field.value !== undefined && field.value !== 0
? `${field.value}`
: ""
}
readOnly={readonly}
maxLength={6}
/>
<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-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.ph"
name="reuseBuilding.0.htdflObj.crmty"
render={({ field }) => (
<FormUi label="수소이온농도(PH)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<FormUi label="색도(도)">
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이상
</span>
</div>
</div>
</FormUi>
)}
/>
@@ -621,18 +765,25 @@ export default function HtdflRegForm({
name="reuseBuilding.0.htdflObj.bod"
render={({ field }) => (
<FormUi label="생물학적 산소요구량(mg/L)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
@@ -644,18 +795,25 @@ export default function HtdflRegForm({
name="reuseBuilding.0.htdflObj.clIonQnt"
render={({ field }) => (
<FormUi label="염화물(mg/L)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={7}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
이하
</span>
</div>
</div>
</FormUi>
)}
/>
@@ -669,69 +827,83 @@ export default function HtdflRegForm({
name="reuseBuilding.0.htdflObj.smll"
render={({ field }) => (
<FormUi label="냄새">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
<SelectBox
className={"!text-2xl"}
label={""}
selectClass={undefined}
selectArray={[
{ val: "불쾌하지않을것", text: "불쾌하지않을것" },
{ val: "없음", text: "없음" },
]}
readOnly={readonly}
maxLength={numSize}
/>
onSelectValue={(val) => {
field.onChange(val);
}}
value={field.value || undefined}
></SelectBox>
</FormUi>
)}
/>
</div>
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.cdtnv"
render={({ field }) => (
<FormUi label="전기전도도(μs/cm)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<div className="flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
<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>
<div className="grid grid-cols-12 gap-4">
<div className="col-span-6">
<FormField
control={form.control}
name="reuseBuilding.0.htdflObj.crmty"
render={({ field }) => (
<FormUi label="색도(도)">
<Input
className={selectClass}
placeholder="10"
type="text"
onChange={(e) => {
if (!readonly)
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={readonly}
maxLength={numSize}
/>
</FormUi>
)}
/>
<Label className="text-xl">수소이온농도(PH)</Label>
<div className="flex flex-row items-center gap-2">
<Input
className="!text-xl w-1/2"
placeholder=""
type="text"
onChange={(e) =>
//setFrontPHdata(e.target.value)
isSetFrontPh(e.target.value)
}
value={frontPHdata ?? ""}
readOnly={readonly}
maxLength={3}
/>
<span className="text-xl">~</span>
<Input
className="!text-xl w-1/2"
placeholder=""
type="text"
onChange={(e) => {
isSetBackPh(e.target.value);
}}
value={backPHdata ?? ""}
readOnly={readonly}
maxLength={3}
/>
</div>
</div>
</div>
</ScrollArea>
@@ -44,6 +44,7 @@ export function PbnstBuseForm({
indexBiz = 0,
setIndexBiz,
form,
readonly = false,
}: {
formType: string;
firstBizData?: fcBizType[];
@@ -51,6 +52,7 @@ export function PbnstBuseForm({
indexMng: number;
indexBiz: number;
setIndexBiz: (index: number) => void;
readonly?: boolean;
}) {
const {
code,
@@ -329,6 +331,7 @@ export function PbnstBuseForm({
onClick={addRuseFcltObj}
type="button"
size={commonButonSize}
disabled={readonly}
>
추가
</Button>
@@ -343,6 +346,7 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
key={`buziMoney-${indexMng}-${indexBiz}`}
@@ -353,6 +357,7 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
@@ -364,6 +369,7 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
key={`concertedWater-${indexMng}-${indexBiz}`}
@@ -374,6 +380,7 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<MngRegFormDetail
key={`wasteFcltinfo-${indexMng}-${indexBiz}`}
@@ -384,6 +391,7 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
readonly={readonly}
/>
<h1 className={formH1Class}>재이용 원수취수 현황</h1>
@@ -394,6 +402,7 @@ export function PbnstBuseForm({
onClick={() => setIsFcOrgwts(true)}
size={commonButonSize}
className=""
disabled={readonly}
>
추가등록
</Button>
@@ -412,6 +421,7 @@ export function PbnstBuseForm({
indexMng={indexMng}
formNm={"fcOrgwts"}
indexBiz={indexBiz}
readonly={readonly}
/>
</div>
<h1 className={formH1Class}>재이용 공급관로 설치 현황</h1>
@@ -424,6 +434,7 @@ export function PbnstBuseForm({
className="w-32"
selectClass="w-full"
onSelectValue={(val) => setPpiYn(String(val))}
readOnly={readonly}
/>
<Label className="text-right">합계</Label>
<Input
@@ -439,6 +450,7 @@ export function PbnstBuseForm({
size={commonButonSize}
className="!text-xl"
onClick={plusHist}
disabled={readonly}
>
추가등록
</Button>
@@ -447,6 +459,7 @@ export function PbnstBuseForm({
size={commonButonSize}
className="!text-xl !bg-red-500 !text-white ml-1"
onClick={removeSelected}
disabled={readonly}
>
삭제
</Button>
@@ -471,6 +484,7 @@ export function PbnstBuseForm({
form={form}
formNm={"pplInstls"}
upHeadList={[]}
readonly={readonly}
/>
</div>
@@ -494,7 +508,7 @@ export function PbnstBuseForm({
sonClass="col-span-4"
indexMng={indexMng}
indexBiz={indexBiz}
formType={""}
readonly={readonly}
/>
</div>
@@ -510,6 +524,7 @@ export function PbnstBuseForm({
}}
size={commonButonSize}
className="mt-6 mr-3"
disabled={readonly}
>
수요처 추가
</Button>
@@ -523,6 +538,7 @@ export function PbnstBuseForm({
}}
size={commonButonSize}
className="mt-6"
disabled={readonly}
>
수요처 신규등록
</Button>
@@ -575,6 +591,7 @@ export function PbnstBuseForm({
searchPk: item.dmdInfoId,
};
})}
readonly={readonly}
></SearchInputText>
</FormUi>
)}
@@ -611,6 +628,7 @@ export function PbnstBuseForm({
selectArray={code.dmdUszCd}
onSelectValue={f.onChange}
value={f.value ?? code.dmdUszCd[0]?.val}
readOnly={readonly}
/>
</FormUi>
)}
@@ -630,6 +648,7 @@ export function PbnstBuseForm({
f.onChange(date),
}}
selectClass={"rounded-lg !w-full"}
readOnly={readonly}
/>
</FormUi>
)}
@@ -652,6 +671,7 @@ export function PbnstBuseForm({
f.onChange(date),
}}
selectClass={"rounded-lg !w-full"}
readOnly={readonly}
/>
</FormUi>
)}
@@ -670,6 +690,7 @@ export function PbnstBuseForm({
handleCommaNumberChange(e, f.onChange);
}}
value={formatCommaNumber(f.value)}
readOnly={readonly}
/>
</FormUi>
)}
@@ -690,6 +711,7 @@ export function PbnstBuseForm({
f.onChange(val)
}
value={f.value ?? code.yn[0]?.val}
readOnly={readonly}
/>
</FormUi>
)}
@@ -13,7 +13,7 @@ export function BuseWaterQulity({
sonClass,
indexMng,
indexBiz,
formType,
readonly,
}: {
form: UseFormReturn<{ items: PbnstRegArrrayType }>;
h1Title: string;
@@ -22,7 +22,7 @@ export function BuseWaterQulity({
sonClass: string;
indexMng: number;
indexBiz: number;
formType?: string;
readonly?: boolean;
}) {
const [frontPHdata, setFrontPHdata] = useState("0");
const [backPHdata, setBackPHdata] = useState("0");
@@ -131,7 +131,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -168,7 +168,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={6}
/>
{/* TODO: 총대장균군수 확인 필요*/}
@@ -203,7 +203,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -237,7 +237,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -267,7 +267,7 @@ export function BuseWaterQulity({
field.onChange(String(e.target.value));
}}
value={field.value ?? ""}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly === "sttn" ? true : false}
maxLength={txtSize}
/> */}
<SelectBox
@@ -278,7 +278,7 @@ export function BuseWaterQulity({
{ val: "불쾌하지않을것", text: "불쾌하지않을것" },
{ val: "없음", text: "없음" },
]}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
onSelectValue={(val) => {
field.onChange(val);
}}
@@ -310,7 +310,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -344,7 +344,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -379,7 +379,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={6}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -413,7 +413,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={7}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -448,7 +448,7 @@ export function BuseWaterQulity({
? `${field.value}`
: ""
}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={7}
/>
<span className="text-xl absolute inset-y-0 right-3 flex items-center text-gray-500 pointer-events-none">
@@ -472,7 +472,7 @@ export function BuseWaterQulity({
isSetFrontPh(e.target.value)
}
value={frontPHdata ?? ""}
readOnly={formType === "sttn"}
readOnly={readonly}
maxLength={3}
/>
<span className="text-xl">~</span>
@@ -484,7 +484,7 @@ export function BuseWaterQulity({
isSetBackPh(e.target.value);
}}
value={backPHdata ?? ""}
readOnly={formType === "sttn"}
readOnly={readonly}
maxLength={3}
/>
</div>
@@ -41,11 +41,13 @@ export function PbnstMngForm({
formType,
indexMng,
setIndexMng,
readonly,
}: {
form: UseFormReturn<{ items: PbnstRegArrrayType }>;
formType: string;
indexMng: number;
setIndexMng: (index: number) => void;
readonly: boolean;
}) {
const { code, pbnst, fileDelete, fileDownLoad } = useWrStore(
(state) => state
@@ -58,6 +60,7 @@ export function PbnstMngForm({
const [mngMtdCode, setMngMtdCode] =
useState<{ name: string; val: SelectDataType[] }[]>();
const {
fields: fcOpersField,
prepend,
@@ -85,7 +88,6 @@ export function PbnstMngForm({
endDt: new Date(),
});
//trigger(`items.${indexMng}.fcOpers`);
};
const removeSelected = () => {
@@ -286,14 +288,14 @@ export function PbnstMngForm({
render={({ field }) => (
<FormUi label="">
<Input
className="!text-2xl"
className="!text-2xl ml-4 mt-1"
placeholder=""
type="text"
onChange={(e) => {
field.onChange(String(e.target.value));
}}
value={field.value ?? ""}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
maxLength={txtSize}
/>
</FormUi>
@@ -316,6 +318,7 @@ export function PbnstMngForm({
size={commonButonSize}
className="!text-xl"
onClick={plusHist}
disabled={readonly}
>
추가등록
</Button>
@@ -324,6 +327,7 @@ export function PbnstMngForm({
size={commonButonSize}
className="!text-xl !bg-red-500 !text-white ml-1"
onClick={removeSelected}
disabled={readonly}
>
삭제
</Button>
@@ -333,20 +337,11 @@ export function PbnstMngForm({
<div className="h-[200px] overflow-y-auto">
<RuseMngTableForm
key={`ruse-table-${indexMng}-${fcOpersField.length}`} // 🔥 length까지 넣어야 동기화됨
tableData={form.getValues(`items.${indexMng}.fcOpers`) ||[]}
headList={
formType === "sttn"
? pbnst.pbnstMngUpHeadList.map((item) => {
return {
...item,
readonly: true,
};
})
: pbnst.pbnstMngUpHeadList
}
tableData={form.getValues(`items.${indexMng}.fcOpers`) || []}
headList={pbnst.pbnstMngUpHeadList}
upHeadList={pbnst.pbnstMngNm}
code={mngMtdCode || []}
readonly={readonly}
indexMng={indexMng}
form={form}
formNm={"fcOpers"}
@@ -370,11 +365,10 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
/>
</FormUi>
)}
@@ -394,11 +388,10 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
/>
</FormUi>
)}
@@ -417,11 +410,10 @@ export function PbnstMngForm({
maxLength={numSize} //입력제한
type="text"
onChange={(e) => {
if (formType !== "sttn")
handleCommaNumberChange(e, field.onChange);
}}
value={formatCommaNumber(field.value)}
readOnly={formType === "sttn" ? true : false}
readOnly={readonly}
/>
</FormUi>
)}
@@ -433,7 +425,7 @@ export function PbnstMngForm({
</div>
<div className="grid grid-cols-12 gap-4 my-4">
<div className="col-span-6">
{formType === "sttn" ? (
{readonly ? (
relationfiles && relationfiles?.length > 0 ? (
<>
<Label className="text-3xl">계통도</Label>
@@ -470,7 +462,7 @@ export function PbnstMngForm({
)}
</div>
<div className="col-span-6">
{formType === "sttn" ? (
{readonly ? (
planFiles && planFiles?.length > 0 ? (
<>
<Label className="text-3xl">평면도</Label>
@@ -21,6 +21,7 @@ export default function MngRegFormDetail({
sonClass,
indexBiz,
indexMng,
readonly
}: {
formList: formDetailType[];
h1Title?: string;
@@ -30,6 +31,7 @@ export default function MngRegFormDetail({
indexBiz?: number;
indexMng?: number;
sonClass?: string;
readonly?:boolean
}) {
const { code } = useWrStore((state) => state);
@@ -67,7 +69,10 @@ export default function MngRegFormDetail({
field.onChange(date),
}}
selectClass={"w-full"}
disabled={formHead.option === "disabled" ? true : false}
readOnly={readonly
//|| formHead.option === "disabled" ? true : false
}
/>
) : formHead.type === "number" ? (
@@ -81,7 +86,9 @@ export default function MngRegFormDetail({
);
}}
value={formatCommaNumber(field.value)}
readOnly={formHead.option === "readOnly" ? true : false}
readOnly={readonly
// || formHead.option === "readOnly" ? true : false
}
disabled={formHead.option === "disabled" ? true : false}
maxLength={numSize}
/>
@@ -103,7 +110,9 @@ export default function MngRegFormDetail({
}
onSelectValue={field.onChange}
value={field.value?.trim() ?? (Array.isArray(potentialOptions) && potentialOptions[0]?.val)}
readOnly={formHead.option === "readOnly"}
readOnly={readonly
// || formHead.option === "readOnly"
}
/>
);
})()
@@ -113,7 +122,9 @@ export default function MngRegFormDetail({
type="text"
value={field.value ?? ""}
onChange={field.onChange}
readOnly={formHead.option === "readOnly" ? true : false}
readOnly={readonly
// || formHead.option === "readOnly" ? true : false
}
disabled={formHead.option === "disabled" ? true : false}
maxLength={txtSize}
/>
@@ -159,7 +159,7 @@ export default function RainRegForm({
<form onSubmit={form.handleSubmit(onSubmit)}>
<div>
<h1 className="text-2xl font-bold text-gray-900 mt-3 ml-1">
{readonly && `(${rainForm?.bdstNm})`}
{readonly && `(시설명 : ${rainForm?.bdstNm})`}
</h1>
<div className="grid grid-cols-12 flex items-center card-header">
<h1 className="text-2xl font-medium text-label col-span-10">
@@ -315,8 +315,8 @@ export default function RainRegForm({
const value = field.value;
const isUnknown = value === null || value === -1; // 또는 Number(value) === -1
return (
<div className="flex items-center gap-2">
<FormUi label="집수면 용량(m³)">
// <div className="flex items-center gap-2">
<FormUi label="집수면 면적(m²)">
<Input
className={selectClass}
placeholder="1,000,000"
@@ -338,7 +338,7 @@ export default function RainRegForm({
maxLength={numSize}
/>
</FormUi>
</div>
// </div>
);
}}
/>
@@ -413,7 +413,7 @@ export default function RainRegForm({
// const isUnknown = value === null || value === "-"; // 또는 Number(value) === -1
return (
<div className="flex items-center gap-2">
// <div className="flex items-center gap-2">
<FormUi label="처리공정">
<Input
className={" h-full !text-xl col-span-4"}
@@ -426,7 +426,7 @@ export default function RainRegForm({
maxLength={txtSize}
/>
</FormUi>
</div>
// </div>
);
}}
/>
@@ -5,21 +5,17 @@ import type {
conCostFeeType,
ContCostMap,
} from "@/app/store/common/searchCode/type";
import { yearOptions } from "@/components/lib/func/commom";
import { SelectBox, UiTable } from "@common/business_components/ui";
import { UiTable } from "@common/business_components/ui";
import ListDiv from "@common/business_components/ui/list_div";
import { Label, } from "@common/components/ui";
import { useEffect, useState } from "react";
import { useEffect, useState } from "react";
export function ConstCostFeeTable() {
const { coRvw, constCostRes } = useWrStore((state) => state);
const [year, setYear] = useState<string>(String(new Date().getFullYear()));
const [constCostData, setConstCostData] = useState<ContCostMap[]>([]);
const getFctDescription = (fctCd: string) => {
const getFctDescription = (fctCd: string) => {
const fctMap: { [key: string]: string } = {
"001": "총인처리시설",
"002": "염소소독",
@@ -73,26 +69,19 @@ export function ConstCostFeeTable() {
공사비 산정표 보기
</h3>
<hr />
<div className="flex items-center">
<Label className="text-xl text-gray-600">기준년도</Label>
<SelectBox
className="h-full text-2xl"
label=""
selectClass={"ml-4"}
selectArray={yearOptions}
value={year}
onSelectValue={(val: string | number) => setYear(String(val))}
/>
<div className="col-span-5 flex items-center">
<Label className="ml-2 mr-1 text-xl text-gray-600">기준년도</Label>
<span>{new Date().getFullYear() || ""}</span>
</div>
<UiTable
headName={""}
tableData={constCostData || []}
headlist={coRvw.constCostHeadList}
pageSize={0}
total={0}
cellClick={() => {}}
onPageChange={() => {}}
/>
<UiTable
headName={""}
tableData={constCostData || []}
headlist={coRvw.constCostHeadList}
pageSize={0}
total={0}
cellClick={undefined}
onPageChange={() => { }}
/>
</ListDiv>
</>
);
@@ -80,7 +80,7 @@ export function RateFeeTableModal() {
<hr className="col-span-6 border-gray-300" />
<div className="col-span-5 flex items-center">
<Label className=" text-xl text-gray-600">기준년도</Label>
<Label className="mr-1 text-xl text-gray-600">기준년도</Label>
<span>{new Date().getFullYear() || ""}</span>
</div>
<div className="col-span-6 pr-6">
@@ -89,7 +89,7 @@ export default function CoRegExcel({
<h3 className="text-2xl font-bold text-gray-900 mt-1 ml-7">
{"잠재수요처 파일"}
</h3>
<Button className="" type="submit" size={"sm"} onClick={onSubmit}>
<Button className="" type="submit" size={"sm"}>
저장
</Button>
</div>
@@ -99,6 +99,7 @@ export function PbnstRegModal({
formType={"reg"}
indexMng={indexMng}
setIndexMng={setIndexMng}
readonly={false}
/>
</TabsContent>
<TabsContent className="max-h-full" value="buse">
@@ -35,7 +35,7 @@ import { useForm } from "react-hook-form";
import { z } from "zod";
export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titleVisible?: boolean }) {
const { pbnstSttn, prfmnc , pbnstPrfmncSttn} = useWrStore((state) => state);
const { pbnstSttn, prfmnc, pbnstPrfmncSttn } = useWrStore((state) => state);
const [fcltTab, setFcltTab] = useState<string>("fclt");
const [ruseTab, setRuseTab] = useState<string>("totalPrf");
const [ruseHeadList, setRuseHeadList] = useState<TableUpperProps[]>([]);
@@ -67,10 +67,10 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
cusrAlotm: item.cusrAlotm ?? "-",
etc: item.etc ?? "-",
totalMoney:
Number(item.addr) +
Number(item.gvsbs) +
Number(item.lcep) +
Number(item.cusrAlotm),
Number(item.cusrAlotm) +
(isNaN(Number(item.etc)) ? 0 : Number(item.etc)),
instlAprvSncnDt: item.instlAprvSncnDt?.toISOString ?? "-",
bizCmcnDay: item.bizCmcnDay?.toISOString ?? "-",
rprcsFcltCpct: item.rprcsFcltCpct ?? "-",
@@ -167,8 +167,8 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
const getTablePrfData = (prfList: PrfType[]) => {
const inUsageData = structuredClone(initValInUsage);
const outUsageData = structuredClone(initValOutUsage);
const inSubtotal = structuredClone(subTotalObj);
const outSubtotal = structuredClone(subTotalObj);
const inSubtotal = { ...structuredClone(subTotalObj), 구분: "장내용수" };
const outSubtotal = { ...structuredClone(subTotalObj), 구분: "장외용수" };
if (prfList) {
prfList?.forEach((prfItem) => {
@@ -216,7 +216,9 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
(usageTotalObj as any)[key] = val;
}
const tableData = [...inUsageData, ...outUsageData, usageTotalObj];
console.log("inusageData", inUsageData)
console.log("outUsageData", outUsageData)
console.log("tableData", tableData)
setPrfData({
inPrf: inUsageData,
outPrf: outUsageData,
@@ -264,6 +266,7 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
formType={"sttn"}
indexMng={indexMng}
setIndexMng={setIndexMng}
readonly={true}
/>
<div className="px-6">
<div className="">
@@ -300,8 +303,8 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
}}
>
{fcltTab === "fclt" ? (
<HeadMakeColSpan upHeadList={pbnstSttn.ruseFcltNodeList} />
) : undefined}
<HeadMakeColSpan upHeadList={pbnstSttn.ruseFcltNodeList} />
) : undefined}
</UiTable>
</TabsContent>
</Tabs>
@@ -323,22 +326,22 @@ export function PbnstSttnModal({ data, titleVisible }: { data: customPbnst; titl
<TabsContent className="max-h-full" value={ruseTab}>
{prfData && (
<ListDiv className="col-span-8 pr-6 ">
<ScrollArea className="h-[60vh]">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
{"하수처리수재이용 실적(m³) 등록결과"}
</h3>
</div>
<Table variant="secondary">
<TableHeader className="font-bold">
{headMakeprfmnc(pbnstPrfmncSttn.monthSttnHeadList, [])}
</TableHeader>
<TableBody key={prfmnc.pageKey + 'pageKey'}>
{InputTableBody(prfData[ruseTab as keyof typeof prfData] || [], pbnstPrfmncSttn.monthSttnHeadList, setPrfData as any)}
</TableBody>
</Table>
</ScrollArea>
</ListDiv>
<ScrollArea className="h-[60vh]">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">
{"하수처리수재이용 실적(m³) 등록결과"}
</h3>
</div>
<Table variant="secondary">
<TableHeader className="font-bold">
{headMakeprfmnc(pbnstPrfmncSttn.monthSttnHeadList, [])}
</TableHeader>
<TableBody key={prfmnc.pageKey + 'pageKey'}>
{InputTableBody(prfData[ruseTab as keyof typeof prfData] || [], pbnstPrfmncSttn.monthSttnHeadList, setPrfData as any)}
</TableBody>
</Table>
</ScrollArea>
</ListDiv>
)}
</TabsContent>
</Tabs>
@@ -421,11 +421,11 @@ export default function CoDetailModal({
<Input
className={selectClass}
placeholder=""
type="number"
type="text"
onChange={(e) => {
field.onChange(e.target.value);
handleCommaNumberChange(e, field.onChange);
}}
value={field.value ?? 0}
value={formatCommaNumber(field.value) ?? 0}
min={0}
readOnly={true}
/>
@@ -1,3 +1,4 @@
import { Input } from "@common/components/ui";
import React, { useCallback, useEffect, useRef, useState } from "react";
type SearchType = {
@@ -10,6 +11,7 @@ type thisProps = {
setValue: (searchNm?: string) => void;
setRtnData: (rtnData: any) => void;
searchList?: any[];
readonly?:boolean
};
export default function SearchInputText({
label = undefined,
@@ -17,6 +19,7 @@ export default function SearchInputText({
setValue = () => {},
setRtnData = () => {},
searchList = undefined,
readonly = false, // 추가: readonly prop
}: thisProps) {
const [isOpen, setIsOpen] = useState(false);
@@ -65,13 +68,14 @@ export default function SearchInputText({
return (
<div ref={wrapperRef}>
<input
<Input
type="text"
value={textValue}
onChange={handleInputChange}
/* onFocus={() => setIsOpen(true)} */
className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder={`${label}을(를) 입력하세요`}
readOnly={readonly} // readonly 상태 적용
/>
{isOpen && (
<div className=" z-1 w-full mt-2 bg-white border border-gray-300 rounded-md shadow-lg h-90 overflow-auto">
@@ -35,6 +35,7 @@ type RuseMngTableProps = {
indexBiz?: number;
form?: any;
formNm?: string;
readonly?: boolean;
};
const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
@@ -48,6 +49,7 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
form,
formNm,
indexBiz,
readonly= false
},
ref
) => {
@@ -111,7 +113,7 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
? formatCommaNumber(field.value)
: field.value || ""
}
readOnly={head.readonly ? true : false}
readOnly={readonly|| head.readonly ? true : false}
maxLength={head.maxLength?head.maxLength:15}
/>
) : head.type === "select" ? (
@@ -132,7 +134,7 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
field.onChange(val);
}
}}
readOnly={head.readonly ? true : false}
readOnly={ readonly||head.readonly ? true : false}
// Disabled prop removed as SelectBox does not support it
></SelectBox>
) : head.type === "date" ? (
@@ -149,14 +151,18 @@ const RuseMngTableForm = React.forwardRef<any, RuseMngTableProps>(
},
}}
selectClass={"w-full"}
readOnly={head.readonly ? true : false}
readOnly={readonly||head.readonly ? true : false}
/>
) : head.type === "checkbox" ? (
<Checkbox
className=""
checked={field.value || false}
onCheckedChange={(checked) => {
field.onChange(checked);
if(readonly || head.readonly) {
return;
}else{
field.onChange(checked);
}
}}
></Checkbox>
) : (
+57 -35
View File
@@ -4,7 +4,7 @@ import { CLAIM_NAME, AUTH_USER_ID } from "./src/shared/config";
// const CLAIM_NAME = "Authorization";
// const AUTH_USER_ID = "token-id";
const serverApiUrl = CS_URL;
const serverApiUrl = CS_URL;
const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || "";
const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || "";
const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || "";
@@ -25,28 +25,43 @@ export function middleware(req: NextRequest) {
if (pathname.startsWith("/server")) {
const decodedParams = Array.from(searchParams.entries())
.map(([key, value]) => `${key}=${decodeURIComponent(value)}`)
.join("&");
.map(([key, value]) => `${key}=${decodeURIComponent(value)}`)
.join("&");
console.log(' sesesesesesevereveraserwereqwrewbrtkehjwrtg server')
const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${
decodedParams ? `?${decodedParams}` : ""
}`;
return NextResponse.rewrite(new URL(newUrl));
}
if (pathname === "/") {
console.log(" maim 화면이동 ");
return NextResponse.redirect(new URL("/map/mainMap", req.url));
}
if (pathname.startsWith("/cms-service")) {
const requestHeaders = new Headers(req.headers);
const Authorization = req.cookies.get(CLAIM_NAME)?.value;
const newUrl = `${serverApiUrl}${pathname}`;
console.log("Authorization cms-service ", Authorization);
if (Authorization) requestHeaders.set(CLAIM_NAME, Authorization);
//if (userId) requestHeaders.set(AUTH_USER_ID, userId);
console.log(
`[Middleware] Rewriting from '/cms-service' path to: ${newUrl}`
);
return NextResponse.rewrite(new URL(newUrl), {
headers: requestHeaders,
});
}
if (pathname.startsWith("/attach-service")) {
const requestHeaders = new Headers(req.headers);
// const token =
// "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhMGVjN2EwNy03NTJhLTRmN2YtODlhNi04NTRlNjNkMmUzYTAiLCJhdXRob3JpdGllcyI6IlJPTEVfQURNSU4sUk9MRV9BTk9OWU1PVVMiLCJtbmdyWW4iOiJZIiwiZXhwIjoxNzUyMTM1OTk3fQ.itGY6M6mC2iwKvEpXw2KS6354T_B_OFz4hD26ResIgwJhpwiDJCMuSXD-rZ3AarmAIKd0udpCuJR7UlvFMN2ww";
// const userId = "a0ec7a07-752a-4f7f-89a6-854e63d2e3a0";
const token = req.cookies.get(CLAIM_NAME)?.value;
const userId = req.cookies.get(AUTH_USER_ID)?.value;
const newUrl = `${serverApiUrl}${pathname}`;
//wr:dev: pathname /attach-service/api/v1/tus/upload/5e60b70a-956e-40c3-be5a-cdd3100bf8ad
//http://dev.onasys.co.kr:8000/attach-service/api/v1/tus/upload/5e60b70a-956e-40c3-be5a-cdd3100bf8ad
if (token) requestHeaders.set(CLAIM_NAME, token);
if (userId) requestHeaders.set(AUTH_USER_ID, userId);
@@ -66,7 +81,7 @@ export function middleware(req: NextRequest) {
`[Middleware] Rewriting from '/user-service' path to: ${newUrl}`
);
return NextResponse.rewrite(new URL(newUrl), {
headers: requestHeaders
headers: requestHeaders,
});
}
@@ -78,33 +93,31 @@ export function middleware(req: NextRequest) {
let newUrl = `${GEOSERVER_URL}${pathname.replace("/geoserver", "")}${queryParams ? `?${queryParams}` : ""}`;
if (
typename == "hasudo:tb_il_swage_prcs_fclt" //하수처리시설
|| typename == "hasudo:tb_ms_swage_prcs_zone" //하수처리구역
|| typename == "hasudo:tb_ms_sbmrg_dngr_map" //침수위험지도
|| typename == "hasudo:tb_ms_flood_dngr_map" //도시침수지도
typename == "hasudo:tb_il_swage_prcs_fclt" || //하수처리시설
typename == "hasudo:tb_ms_swage_prcs_zone" || //하수처리구역
typename == "hasudo:tb_ms_sbmrg_dngr_map" || //침수위험지도
typename == "hasudo:tb_ms_flood_dngr_map" //도시침수지도
) {
newUrl = `${GEOSERVER_URL}${pathname.replace("/geoserver", "")}${queryParams ? `?${queryParams}` : ""}`;
}
else if (
typename == "hasudo:tb_ms_swage_ppl" //관로
|| typename == "hasudo:tb_ms_swage_mhl" //맨홀
|| typename == "hasudo:tb_ms_swage_pmstn" //펌프장
|| typename == "hasudo:tb_ms_stofcbr" //우수토실
} else if (
typename == "hasudo:tb_ms_swage_ppl" || //관로
typename == "hasudo:tb_ms_swage_mhl" || //맨홀
typename == "hasudo:tb_ms_swage_pmstn" || //펌프장
typename == "hasudo:tb_ms_stofcbr" //우수토실
) {
newUrl = `${LX_GEOSERVER_URL}${pathname.replace("/geoserver", "")}${queryParams ? `?${queryParams}` : ""}`;
}
else if (
typename == "hasudo:om_dt_untrt_swg_rain" //중점우수토실
|| typename == "hasudo:om_wqlt_station" //관측소
|| typename == "hasudo:tb_wr_bdst_ruse_fclt" //재이용시설
|| typename == "hasudo:tb_wr_rnwtr_utztn_fclt" //빗물이용시설
|| typename == "hasudo:tb_wr_rswtr_fclt" //중수도시설
|| typename == "hasudo:tb_wr_htdfl_fclt" //온배수시설
|| typename == "hasudo:tb_wr_ruse_fclt_dmd_co" //수요처
|| typename == "hasudo:tb_wr_tmpr_dmd_co" //잠재수요처
){
} else if (
typename == "hasudo:om_dt_untrt_swg_rain" || //중점우수토실
typename == "hasudo:om_wqlt_station" || //관측소
typename == "hasudo:tb_wr_bdst_ruse_fclt" || //재이용시설
typename == "hasudo:tb_wr_rnwtr_utztn_fclt" || //빗물이용시설
typename == "hasudo:tb_wr_rswtr_fclt" || //중수도시설
typename == "hasudo:tb_wr_htdfl_fclt" || //온배수시설
typename == "hasudo:tb_wr_ruse_fclt_dmd_co" || //수요처
typename == "hasudo:tb_wr_tmpr_dmd_co" //잠재수요처
) {
const url = req.nextUrl.clone();
url.searchParams.set('TYPENAME', typename.replace("hasudo:",""));
url.searchParams.set("TYPENAME", typename.replace("hasudo:", ""));
queryParams = url.searchParams.toString();
newUrl = `${SEWERAGE_API_URL}/v1/map/geometry${queryParams ? `?${queryParams}` : ""}`;
}
@@ -115,8 +128,9 @@ export function middleware(req: NextRequest) {
if (pathname.startsWith("/sewerage-service")) {
const queryParams = searchParams.toString();
const newUrl = `${SEWERAGE_API_URL}${pathname.replace("/sewerage-service/api", "")}${queryParams ? `?${queryParams}` : ""
}`;
const newUrl = `${SEWERAGE_API_URL}${pathname.replace("/sewerage-service/api", "")}${
queryParams ? `?${queryParams}` : ""
}`;
console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`);
return NextResponse.rewrite(new URL(newUrl));
}
@@ -125,5 +139,13 @@ export function middleware(req: NextRequest) {
}
export const config = {
matcher: ["/server/:path*", "/user-service/:path*", "/attach-service/:path*", "/geoserver/:path*", "/sewerage-service/:path*"],
matcher: [
"/cms-service/:path*",
"/server/:path*",
"/user-service/:path*",
"/attach-service/:path*",
"/geoserver/:path*",
"/sewerage-service/:path*",
"/"
],
};
+7 -2
View File
@@ -12,14 +12,19 @@
"isUpdateMsg": "수정한 정보를 저장하시겠습니까?",
"isInsertMsg": "등록하시겠습니까?",
"isUpdatetMsg": "수정하시겠습니까?",
"matchFinishMsg" : "{{name}}이(가) 완료되었습니다.",
"excelDownErrMsg": "다운로드할 데이터가 없습니다.",
"isMatchFinishMsg":" 매칭완료를 진행하시겠습니까?",
"isNotMatchFinishMsg":"검토완료중 매칭완료 여부를 체크한 항목이 없습니다.",
"canNotChangeMatStateMsg":"매칭완료된 항목은 상태를 변경할 수 없습니다.",
"alreadyInsertedErrMsg": "사업자번호 {{num}}(은)는 이미 등록되었습니다. 다시 등록해주세요.",
"saveRowErrMsg": "수정을 원하는 행을 선택하고 저장버튼을 눌러주세요.",
"costCalcErrMsg":"공사비 계산 진행 후 저장을 눌러주세요",
"maxYearErrMsg": "최대 {{year}}년까지 선택가능합니다.",
"checkQtyMsg": "요구수량(M3/d)을 확인해주세요 계산할 수 없습니다."
"checkQtyMsg": "요구수량(m³/일)을 확인해주세요 계산할 수 없습니다."
}
Binary file not shown.
@@ -29,23 +29,18 @@ export class LoginApiService implements LoginService {
const accessToken = response.headers.get(ACCESS_TOKEN);
const tokenId = response.headers.get(AUTH_USER_ID);
console.log('accessToken ', accessToken)
console.log('tokenId ', tokenId)
if (!accessToken || !tokenId) {
throw new Error("Missing required authentication tokens");
}
tokenManager.setToken(CLAIM_NAME, accessToken);
tokenManager.setToken(AUTH_USER_ID, tokenId);
tokenManager.setToken("site-id-key", SITE_ID);
tokenManager.setToken(CLAIM_NAME, accessToken)
tokenManager.setToken(AUTH_USER_ID, tokenId)
tokenManager.setToken("site-id-key", SITE_ID)
tokenManager.setupRefreshTimer(
() => this.silentRefresh(),
JWT_EXPIRATION_TIME,
);
} catch (error) {
console.log(' login err ' , error)
throw new Error(`Login failed: ${error}`);
}
}
@@ -67,7 +62,7 @@ export class LoginApiService implements LoginService {
if (!accessToken || !tokenId) {
throw new Error("Missing required authentication tokens");
}
tokenManager.setToken(CLAIM_NAME, accessToken);
tokenManager.setToken(AUTH_USER_ID, tokenId);
} catch (error) {
+1 -1
View File
@@ -1,6 +1,6 @@
import { PROXY_HOST } from "./env";
export const BASE_URL = `${PROXY_HOST}/server`;
export const BASE_URL = `${PROXY_HOST}`;
export const ENDPOINT = {
ATTACH_SERVICE: {
+1 -1
View File
@@ -9,7 +9,7 @@
"packages/*"
],
"scripts": {
"build": "turbo run build --filter=!cs",
"build": "turbo run build",
"build:common": "turbo run build --filter=@common/*",
"dev": "turbo run dev",
"dev:cs": "turbo run dev --filter=cs",
@@ -50,7 +50,7 @@ const customStyles = {
fontWeight: "normal",
marginTop: "16px",
marginBottom: "8px",
minHeight: "32px", // 범례 영역 높이 통일
minHeight: "60px", // 범례 영역 높이 통일
} as CSSProperties,
};
const renderCustomizedLabel = ({
@@ -108,12 +108,11 @@ export function DatePicker({
// captionLayout="dropdown-buttons"
// fromYear={2000}
// toYear={new Date().getFullYear()}
toDate={new Date()} // 금일까지만 표시됨 (금일 이후는 안보임)
showOutsideDays={false} // 금월 까지만 표출되도록
mode="single"
selected={field?.value}
onSelect={handleSelect}
initialFocus
disabled={{ after: new Date() }} // 금일까지만 표시됨 (금일 이후는 안보임) 20250721 캘린더가 변경됨!!
locale={ko}
/>
</PopoverContent>

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