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
236 changed files with 3301 additions and 14026 deletions
-8
View File
@@ -1,8 +0,0 @@
# 디폴트 무시된 파일
/shelf/
/workspace.xml
# 에디터 기반 HTTP 클라이언트 요청
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+10 -7
View File
@@ -1,16 +1,19 @@
NEXT_PUBLIC_SITE_ID = DM
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_PORT = 11035
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11035
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://localhost:3000
NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1
NEXT_PUBLIC_FO_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000
NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload
NEXT_PUBLIC_CLAIM_NAME = Authorization
NEXT_PUBLIC_AUTH_USER_ID = token-id
NEXT_PUBLIC_ACCESS_TOKEN = access-token
NEXT_PUBLIC_REFRESH_TOKEN = refresh-token
NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
# NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정
+2 -2
View File
@@ -1,6 +1,6 @@
NEXT_PUBLIC_SITE_ID = DM
NEXT_PUBLIC_PORT = 11035
NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11035
NEXT_PUBLIC_PORT = 3000
NEXT_PUBLIC_PROXY_HOST = http://wr.hasuon.or.kr
NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/api/v1
NEXT_PUBLIC_FO_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000/operation-service/api/v1
NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000
-3
View File
@@ -30,9 +30,6 @@ export default function Home() {
<Button className='ml-5 place-self-auto'>
<Link href="/pages/sdmMng/sdmApplyList">수요처 신청 현황(개발중)</Link>
</Button>
<Button className='ml-5 place-self-auto'>
<Link href="/pages/map/mainMap">지도팝업 (임시)</Link>
</Button>
</div>
</>
);
-14
View File
@@ -1,14 +0,0 @@
"use client";
const Map = () => {
return (
<>
</>
);
};
export default Map;
-132
View File
@@ -1,132 +0,0 @@
"use client";
import Gis from "@common/business_components/ui/map/Gis";
import { useEffect, useRef, useState, useCallback } from "react";
import { mapService } from "../service";
import GisApp from "@common/business_components/ui/map/lib/gis.core";
const Map = () => {
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
const gisMaps = useRef<any | null>(null);
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
const [isSearchModalOpen, setIsSearchModalOpen] = useState(true); // SearchModal 열림 상태
const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터
const [checkedLayers, setCheckedLayers] = useState<string[]>([]);
const [checkedLayersData, setCheckedLayersData] = useState<any[]>([]);
const fetchData = async () => {
try {
const response = await mapService.getLyrStngs();
setTreeData(response); // API 응답 저장
} catch (error) {
console.error("데이터 불러오기 실패:", error);
}
};
// 팝업 닫기 핸들러를 useCallback으로 메모이제이션
const handlePopupClose = useCallback(() => {
setIsOpen(false);
setFeatureData(null);
}, []);
// 컴포넌트 마운트 시 1회 실행
useEffect(() => {
fetchData();
}, []);
// 체크된 레이어 정보를 받는 핸들러
const handleCheckedLayersChange = (
checkedIds: string[],
checkedNodesData: any[]
) => {
setCheckedLayers(checkedIds);
setCheckedLayersData(checkedNodesData);
};
// SearchModal, GisContent 등에서 호출
const onFeatureSelect = (data: any) => {
const map = gisMaps.current;
if (!map) {
console.warn("지도가 초기화되지 않았습니다.");
return;
}
// 항상 같은 select 객체 사용
const select = GisApp.Module.select as any;
if (!select) return;
// 1. 기존 선택 초기화
select.resetSelectedFeature();
// 2. data가 OpenLayers Feature 인스턴스인지 확인
let foundFeature: any = null;
if (
data &&
typeof data.getGeometry === "function" &&
typeof data.setStyle === "function"
) {
// 이미 Feature 인스턴스라면 그대로 사용
foundFeature = data;
} else {
// 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용
const featureId = data.fid || data.ftrIdn || data.id;
map
.getLayers()
.getArray()
.forEach((layer: any) => {
const source = layer.getSource?.();
if (source?.getFeatureById) {
const feature = source.getFeatureById(String(featureId).trim());
if (feature) foundFeature = feature;
}
});
}
// 3. 피처 선택
if (foundFeature) {
const geometry = foundFeature.getGeometry();
if (geometry) {
const extent = geometry.getExtent();
map.getView().fit(extent, {
duration: 300,
padding: [50, 50, 50, 50],
maxZoom: 16,
constrainResolution: true,
nearest: true,
});
}
select.selectFeature(foundFeature, true);
} else {
console.warn("OpenLayers Feature를 찾을 수 없습니다:", data);
}
setFeatureData(data);
setIsOpen(true);
setIsSearchModalOpen(false);
};
return (
<div className="bg-container">
<Gis
treeData={treeData}
isSearch={false}
gisMaps={gisMaps}
isMiniMap={false}
searchView={undefined}
detailView={null}
onFeatureSelect={onFeatureSelect}
setIsOpen={setIsOpen}
setFeatureData={setFeatureData}
featureData={featureData}
setIsSearchModalOpen={setIsSearchModalOpen}
isOpen={isOpen}
isSearchModalOpen={isSearchModalOpen}
onCheckedLayersChange={handleCheckedLayersChange}
imgVisble={true}
/>
</div>
);
};
export default Map;
@@ -1,94 +0,0 @@
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { createPortal } from 'react-dom';
// 현재 문서의 스타일(CSS)을 새 창으로 복사하는 함수
const copyStyles = (sourceDoc: Document, targetDoc: Document) => {
Array.from(sourceDoc.styleSheets).forEach(styleSheet => {
try {
if (styleSheet.cssRules) { // <style> 태그로 주입된 CSS
const newStyleEl = sourceDoc.createElement('style');
Array.from(styleSheet.cssRules).forEach(cssRule => {
newStyleEl.appendChild(sourceDoc.createTextNode(cssRule.cssText));
});
targetDoc.head.appendChild(newStyleEl);
} else if (styleSheet.href) { // <link> 태그로 연결된 CSS 파일
const newLinkEl = sourceDoc.createElement('link');
newLinkEl.rel = 'stylesheet';
newLinkEl.href = styleSheet.href;
targetDoc.head.appendChild(newLinkEl);
}
} catch (e) {
console.warn('스타일시트를 복사할 수 없습니다:', e);
}
});
};
interface NewWindowPortalProps {
children: React.ReactNode;
onClose: () => void;
title?: string;
width?: number;
height?: number;
resizable?: string;
scrollbars?: string;
}
const NewWindowPortal: React.FC<NewWindowPortalProps> = ({ children, onClose, title = "" , width = 900, height = 800, resizable = "yes", scrollbars= "yes" }) => {
const [container, setContainer] = useState<HTMLElement | null>(null);
const newWindowRef = useRef<Window | null>(null);
const onCloseRef = useRef(onClose);
// onClose 함수를 ref로 저장하여 의존성 문제 해결
useEffect(() => {
onCloseRef.current = onClose;
}, [onClose]);
const handleUnload = useCallback(() => {
onCloseRef.current();
}, []);
useEffect(() => {
// 이미 창이 열려있으면 새로 열지 않음
if (newWindowRef.current && !newWindowRef.current.closed) return;
// 1. 새 창을 열고 참조를 저장합니다.
const popupOptions = `width=${width},height=${height},resizable=${resizable},scrollbars=${scrollbars}`;
newWindowRef.current = window.open('', title, popupOptions);
if (newWindowRef.current) {
newWindowRef.current.document.title = title;
// 2. React 컴포넌트를 마운트할 컨테이너 div를 생성하여 새 창의 body에 추가합니다.
const div = newWindowRef.current.document.createElement('div');
newWindowRef.current.document.body.appendChild(div);
setContainer(div);
// 3. 메인 창의 스타일을 새 창으로 복사합니다. (매우 중요)
copyStyles(document, newWindowRef.current.document);
// 4. 사용자가 창을 닫을 때 부모에게 알리기 위한 이벤트 리스너를 설정합니다.
// const handleUnload = () => {
// onClose();
// };
newWindowRef.current.addEventListener('unload', handleUnload);
// 5. 컴포넌트가 사라질 때 창을 닫는 클린업 함수를 반환합니다.
return () => {
if (newWindowRef.current) {
newWindowRef.current.removeEventListener('unload', handleUnload);
if (!newWindowRef.current.closed) {
newWindowRef.current.close();
}
}
};
} else {
alert('팝업이 차단되었습니다. 팝업 차단을 해제하고 다시 시도해주세요.');
onCloseRef.current();
}
}, [handleUnload, onClose, title]);
// `createPortal`을 사용해 children을 새 창의 container div에 렌더링합니다.
return container ? createPortal(children, container) : null;
};
export default NewWindowPortal;
-1
View File
@@ -1 +0,0 @@
export * from './map'
-46
View File
@@ -1,46 +0,0 @@
/**
* 관망도 API
*/
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}/v1/map`
export type LyrStngProps = {
lyr_sn: string
lyr_nm: string
upper_lyr_sn: string
drawOrdr: string
flterSql: string
gobjTy: string
lyrTpNm: string
useYn: string
minViewSize: string
iconNm: string
lblAtrbNm: string
fontNm: string
fontIntnColor: string
fontExtnColor: string
fontExtnWdth: string
lnWdth: string
lnColor: string
polgnColor: string
initEprssYn: string
clickPsblYn: string
}
export const mapService = {
//레이어 설정 조회
getLyrStngs: async () => {
const response = await fetch(`${API_URL}/lyrStngs/WR_NETWORK`, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
}
@@ -13,7 +13,7 @@ import { Toaster } from "react-hot-toast";
import * as z from "zod";
import SdmLogin from "../sdmLogin/page";
const sdmInfoFormSchema = z.object({
const createFormSchema = () => z.object({
sdmNm: z.string()
.min(1, "수요처를 선택해주세요"),
demandYmd: z.date().optional(),
@@ -67,14 +67,14 @@ const sdmInfoFormSchema = z.object({
candidateTitle: z.string().optional(),
});
export type FormData = z.infer<typeof sdmInfoFormSchema>;
export type FormData = z.infer<ReturnType<typeof createFormSchema>>;
function SdmInfoInsertContent() {
const searchParams = useSearchParams();
const {insertSdmInfoData, Sdm} = useDmStore((state) => state);
const {successLogin} = Sdm;
const [ismoneyDisabled, setIsmoneyDisabled] = useState(false);
const formSchema = sdmInfoFormSchema;
const formSchema = createFormSchema();
const [isLogin, setIsLogin] = useState(false);
const [facilityName, setFacilityName] = useState<string>('');
@@ -21,7 +21,6 @@ export default function MyForm() {
useEffect(() => {
if (successNextPage && formDataRef.current) {
const data = formDataRef.current;
console.log(data);
const queryParams = new URLSearchParams({
dmdCoNm: data.dmdCoNm || '',
ctpvCd: data.ctpvCd || '',
@@ -1,15 +1,7 @@
import ModalSimilarPage from "@/app/pages/sdmMng/sdmInfoInsert/modalSimilar/page";
import type { FormData } from "@/app/pages/sdmMng/sdmInfoInsert/page";
import { useDmStore } from "@/app/store";
import {
CANDIDATE,
DatePicker,
FormField,
FormLabel,
FormUi,
SelectBox,
UiModal,
} from "@common/business_components";
import { CANDIDATE, DatePicker, FormField, FormLabel, FormUi, SelectBox, UiModal } from "@common/business_components";
import { Input } from "@common/components";
import { Button } from "@common/components/ui";
import { useSearchParams } from "next/navigation";
@@ -18,8 +10,6 @@ import { AccessibleFormField } from "./AccessibleFormField";
import type { ControllerRenderProps, UseFormReturn } from "react-hook-form";
import SearchInputText from "../common/searhDemandInput/component";
import type { DemandCompType } from "@/app/store/sdmMng";
import NewWindowPortal from "@/app/pages/map/popup/windowPotal";
import Map from "@/app/pages/map/popup/sdmInfoMap";
export interface SdmInfoRegFormProps {
form: UseFormReturn<FormData>;
@@ -27,31 +17,21 @@ export interface SdmInfoRegFormProps {
facilityName?: string;
}
type FieldComponent = (
field: ControllerRenderProps<FormData, keyof FormData>
) => JSX.Element;
type FieldComponent = (field: ControllerRenderProps<FormData, keyof FormData>) => JSX.Element;
export function SdmInfoRegForm({
form,
onCheckboxChange,
facilityName,
}: SdmInfoRegFormProps) {
export function SdmInfoRegForm({ form, onCheckboxChange, facilityName }: SdmInfoRegFormProps) {
const { initializeCommonData, Sdm } = useDmStore((state) => state);
const { useTypesData } = Sdm;
const searchParams = useSearchParams();
const [sdmNmValue, setSdmNmValue] = useState<string>(
searchParams.get("dmdCoNm") || ""
);
const [sdmNmValue, setSdmNmValue] = useState<string>(searchParams.get('dmdCoNm') || '');
const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(false);
const [isSimilarCase, setIsSimilarCase] = useState(false);
const [key, setKey] = useState(0);
// 후보지 팝업 오픈 상태
const [isCandidatePopup, setIsCandidatePopup] = useState(false);
//모달 조회에 필요한 데이터
const [sply, setSply] = useState<number>(0);
const [usageCd, setUsageCd] = useState<string>("청소");
const [usageCd, setUsageCd] = useState<string>('청소');
const [money, setMoney] = useState<number>(0);
useEffect(() => {
@@ -61,7 +41,7 @@ export function SdmInfoRegForm({
useEffect(() => {
if (useTypesData && useTypesData.length > 0) {
setTimeout(() => {
form.setValue("usePurpose", useTypesData[0]?.val?.toString() || "");
form.setValue('usePurpose', useTypesData[0]?.val?.toString() || '');
}, 500);
}
}, [useTypesData, form]);
@@ -69,45 +49,32 @@ export function SdmInfoRegForm({
useEffect(() => {
if (facilityName) {
setSdmNmValue(facilityName);
form.setValue("sdmNm", facilityName);
setKey((prev) => prev + 1);
form.setValue('sdmNm', facilityName);
setKey(prev => prev + 1);
}
}, [facilityName, form]);
useEffect(() => {
if (searchParams.get("dmdCoNm")) {
form.setValue("sdmNm", searchParams.get("dmdCoNm") || "");
setSdmNmValue(searchParams.get("dmdCoNm") || "");
setKey((prev) => prev + 1);
}
}, [searchParams, form]);
const searchCandidate = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
console.log(1);
setIsCandidatePopup(true);
};
}
const searchSimilarCase = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
setIsSimilarCase(true);
};
}
const handleCheckboxChange = (checked: boolean) => {
setIsBznmTotNoDisabled(checked);
onCheckboxChange?.(checked);
};
// 시설 선택시 이벤트
const selectComp = useCallback(
(rtnData: DemandCompType[]) => {
const rtnCompData = rtnData?.[0];
form.setValue("sdmNm", rtnCompData?.dmdCoNm || "");
},
[form]
);
const selectComp = useCallback((rtnData: DemandCompType[]) => {
const rtnCompData = rtnData?.[0];
form.setValue('sdmNm', rtnCompData?.dmdCoNm || '');
}, [form]);
const formFields: Array<{
name: keyof FormData;
@@ -126,15 +93,15 @@ export function SdmInfoRegForm({
<SearchInputText
label="수요처명"
setValue={(val) => {
setSdmNmValue(val || "");
field.onChange(val || "");
setSdmNmValue(val || '');
field.onChange(val || '');
}}
setRtnData={selectComp}
initValue={facilityName || sdmNmValue}
{...field}
/>
</div>
),
)
},
{
name: "demandYmd",
@@ -143,7 +110,7 @@ export function SdmInfoRegForm({
required: true,
component: (field) => (
<div className="w-full">
<DatePicker
<DatePicker
mode="single"
selected={field.value as Date}
onSelect={(date) => {
@@ -155,12 +122,12 @@ export function SdmInfoRegForm({
value: field.value as Date,
onChange: (date: Date | undefined) => {
field.onChange(date as Date);
},
}
}}
selectClass={undefined}
/>
</div>
),
)
},
{
name: "demandQnty",
@@ -168,8 +135,8 @@ export function SdmInfoRegForm({
formIndex: 0,
required: true,
component: (field) => (
<Input
placeholder="요구수량(㎥/d)을 입력하세요"
<Input
placeholder="요구수량(㎥/d)을 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -181,7 +148,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "usePurpose",
@@ -191,16 +158,16 @@ export function SdmInfoRegForm({
component: (field) => (
<SelectBox
selectClass={undefined}
label=""
selectArray={useTypesData}
label=""
selectArray={useTypesData}
onSelectValue={(val) => {
field.onChange(val.toString());
setUsageCd(val.toString());
}}
className=""
className=""
value={field.value as string}
/>
),
)
},
{
name: "money",
@@ -234,14 +201,14 @@ export function SdmInfoRegForm({
</FormUi>
}
/>
),
)
},
{
name: "reqWaterQlty",
label: "요구수질",
formIndex: 0,
required: true,
component: undefined,
component: undefined
},
{
name: "grssClfg",
@@ -249,8 +216,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="총대장균군수를 입력하세요"
<Input
placeholder="총대장균군수를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -259,7 +226,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "tn",
@@ -267,8 +234,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="총질소를 입력하세요"
<Input
placeholder="총질소를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -277,7 +244,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "combResdch",
@@ -285,8 +252,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="결합잔류염소를 입력하세요"
<Input
placeholder="결합잔류염소를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -295,7 +262,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "tph",
@@ -303,8 +270,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="총인을 입력하세요"
<Input
placeholder="총인을 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -313,16 +280,16 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "trbt",
label: "탁도(NTU)",
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="탁도를 입력하세요"
component: (field) => (
<Input
placeholder="탁도를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -331,7 +298,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "ph",
@@ -339,8 +306,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="수소이온농도를 입력하세요"
<Input
placeholder="수소이온농도를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -349,7 +316,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "bod",
@@ -357,8 +324,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="생물학적 산소요구량을 입력하세요"
<Input
placeholder="생물학적 산소요구량을 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -367,7 +334,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "clIonQnt",
@@ -375,8 +342,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="염화물을 입력하세요"
<Input
placeholder="염화물을 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -385,16 +352,16 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
},
)
},
{
name: "smll",
label: "냄새",
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="냄새를 입력하세요"
<Input
placeholder="냄새를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -403,7 +370,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "cdtnv",
@@ -411,8 +378,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="전기전도도를 입력하세요"
<Input
placeholder="전기전도도를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -421,7 +388,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "crmty",
@@ -429,8 +396,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="색도를 입력하세요"
<Input
placeholder="색도를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -439,7 +406,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "rmrk",
@@ -447,8 +414,8 @@ export function SdmInfoRegForm({
formIndex: 1,
required: true,
component: (field) => (
<Input
placeholder="비고를 입력하세요"
<Input
placeholder="비고를 입력하세요"
type="text"
className="!text-xl text-gray-600"
value={field.value as string}
@@ -457,7 +424,7 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
),
)
},
{
name: "candidateTitle",
@@ -466,16 +433,16 @@ export function SdmInfoRegForm({
component: (field) => (
<div>
<div className="-mt-14 float-right flex gap-10">
<Button className={"bg-gray-200"} onClick={searchCandidate}>
<Button className={'bg-gray-200'} onClick={searchCandidate}>
후보지 조회
</Button>
<Button className={"bg-gray-200"} onClick={searchSimilarCase}>
<Button className={'bg-gray-200'} onClick={searchSimilarCase}>
유사사례
</Button>
</div>
<div className="flex justify-center gap-10 mt-5">
<Input
placeholder="후보지1"
<Input
placeholder="후보지1"
type="text"
className="!text-xl w-[130px] text-gray-600"
value={field.value as string}
@@ -484,8 +451,8 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
<Input
placeholder="후보지2"
<Input
placeholder="후보지2"
type="text"
className="!text-xl w-[130px] text-gray-600"
value={field.value as string}
@@ -494,8 +461,8 @@ export function SdmInfoRegForm({
name={field.name}
ref={field.ref}
/>
<Input
placeholder="후보지3"
<Input
placeholder="후보지3"
type="text"
className="!text-xl w-[130px] text-gray-600"
value={field.value as string}
@@ -506,32 +473,24 @@ export function SdmInfoRegForm({
/>
</div>
</div>
),
)
},
];
const normalFields = formFields.filter(
(f) => f.formIndex === 0 && f.component
);
const groupFields = formFields.filter(
(f) => f.formIndex === 1 && f.component
);
const candidateFields = formFields.filter(
(f) => f.formIndex === 2 && f.component
);
const normalFields = formFields.filter(f => f.formIndex === 0 && f.component);
const groupFields = formFields.filter(f => f.formIndex === 1 && f.component);
const candidateFields = formFields.filter(f => f.formIndex === 2 && f.component);
return (
<>
{normalFields.map(({ name, label, component, required }) =>
{normalFields.map(({ name, label, component, required }) => (
component ? (
<FormField
key={name}
control={form.control}
name={name}
render={({ field }) =>
name === "money" ? (
component(field)
) : (
render={({ field }) => (
name === 'money' ? component(field) : (
// <FormUi label={label}>
// {component(field)}
// </FormUi>
@@ -543,10 +502,10 @@ export function SdmInfoRegForm({
inputComponent={component(field)}
/>
)
}
)}
/>
) : null
)}
))}
{groupFields.length > 0 && (
<div className="mt-10">
@@ -576,7 +535,7 @@ export function SdmInfoRegForm({
</div>
)}
{candidateFields.map(({ name, label, component, required }, index) =>
{candidateFields.map(({ name, label, component, required }, index) => (
component ? (
<FormField
key={name + index}
@@ -596,13 +555,11 @@ export function SdmInfoRegForm({
)}
/>
) : null
)}
))}
{isSimilarCase && (
<UiModal
body={
<ModalSimilarPage sply={sply} usageCd={usageCd} money={money} />
}
body={<ModalSimilarPage sply={sply} usageCd={usageCd} money={money} />}
bodyClass="sm:max-w-[100vw] w-[1400px] h-[900px]"
open={isSimilarCase}
onOpenChange={(open) => !open && setIsSimilarCase(false)}
@@ -610,20 +567,6 @@ export function SdmInfoRegForm({
noFooterYn="Y"
/>
)}
{/* 후보지 조회 새 창 포털 */}
{isCandidatePopup && (
<NewWindowPortal
onClose={() => setIsCandidatePopup(false)}
title="공급처 후보지 조회"
width={window.screen.availWidth}
height={window.screen.availHeight}
resizable="no"
scrollbars="yes"
>
<Map />
</NewWindowPortal>
)}
</>
);
}
}
@@ -4,16 +4,14 @@ import { BZNM_TOT_NO, FormField, FormUi } from "@common/business_components";
import { Button, Input } from "@common/components";
import { zodResolver } from "@hookform/resolvers/zod";
import { sha512 } from 'js-sha512';
import { useEffect, useState, useMemo } from "react";
import { useEffect, useState } from "react";
import { FormProvider, useForm, type ControllerRenderProps } from "react-hook-form";
import * as z from "zod";
export function SdmLoginForm() {
const { actionLogin, initializeCommonData } = useDmStore((state) => state);
const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(false);
// 스키마를 useMemo로 최적화
const sdmLoginFormSchema = useMemo(() => z.object({
type FormData = z.infer<ReturnType<typeof createFormSchema>>;
type FieldComponent = (field: ControllerRenderProps<FormData, keyof FormData>) => JSX.Element;
const createFormSchema = () => z.object({
dmdInfoId: z.string()
.min(1, "사업자등록번호를 입력해주세요")
.regex(/^\d{10}$/, "사업자등록번호는 10자리 숫자만 입력 가능합니다"),
@@ -26,12 +24,11 @@ export function SdmLoginForm() {
.max(16, "비밀번호는 16자 이내로 입력해주세요"),
rgtr: z.string().optional(),
dmdAplyPswd: z.string().optional(),
}), [isBznmTotNoDisabled]);
});
type FormData = z.infer<typeof sdmLoginFormSchema>;
type FieldComponent = (field: ControllerRenderProps<FormData, keyof FormData>) => JSX.Element;
const formSchema = sdmLoginFormSchema;
const { actionLogin, initializeCommonData } = useDmStore((state) => state);
const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(false);
const formSchema = createFormSchema();
useEffect(() => {
initializeCommonData();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 961 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1016 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

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