From 43bbc81616c7129fae23668c488b22d95a40c1a3 Mon Sep 17 00:00:00 2001 From: ljpark Date: Tue, 17 Mar 2026 15:17:43 +0900 Subject: [PATCH 01/25] =?UTF-8?q?wr:=20alert=20=EC=8B=9C=ED=97=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx | 11 ++++++----- apps/wr/app/store/matDmd/coSttn/index.tsx | 1 + apps/wr/src/shared/ui/alert-dialog.tsx | 10 ++++++---- apps/wr/tsconfig.json | 10 +++------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx index f5104154f..bf471c564 100644 --- a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx @@ -31,6 +31,7 @@ import moment from "moment"; import { useCallback, useEffect, useState } from "react"; import toast, { Toaster } from "react-hot-toast"; import { useTranslation } from "react-i18next"; +import { useAlertStore } from "@/src/shared/lib"; export default function CoSttn() { const { @@ -48,7 +49,7 @@ export default function CoSttn() { getMyUUID } = useWrStore((state) => state); const { regAuthrtYn, mdfcnAuthrtYn } = auth; - + const alert = useAlertStore((state) => state.setMessage); const [bdstTable, setBdstTable] = useState(); const [pageNation, setPageNation] = useState(1); const { coSttnRes, coSttnResCount } = coSttn; @@ -98,7 +99,7 @@ export default function CoSttn() { useEffect(() => { if (!coSttn.isInit) { - coSttnInit("1", "13", "0"); + coSttnInit("1", "13", "0"); // 수요처 목록 조회 } }, [coSttn.isInit, coSttnInit]); @@ -274,8 +275,8 @@ export default function CoSttn() { headName={[]} tableData={bdstTable || []} headlist={coSttn.coSttHeadList} - pageSize={20} - total={coSttnResCount + 10 || 0} + pageSize={13} + total={coSttnResCount || 0} cellClick={ async(index: number | undefined) => { const uuid = await getMyUUID(); const updateData = coSttnRes[index as number]; @@ -332,7 +333,7 @@ export default function CoSttn() { `/reuseFc/request/${data.dmdInfoId}` ); if (dmd) { - toast.error( + alert( `사업자번호 ${dmd.dmdInfoId}는 이미 등록되었습니다. 다시등록해주세요` ); return; diff --git a/apps/wr/app/store/matDmd/coSttn/index.tsx b/apps/wr/app/store/matDmd/coSttn/index.tsx index 1f7b2c54b..4c326d283 100644 --- a/apps/wr/app/store/matDmd/coSttn/index.tsx +++ b/apps/wr/app/store/matDmd/coSttn/index.tsx @@ -46,6 +46,7 @@ export const coSttnActionsExport: (set: any) => coSttnActions = ( set: any ) => { return { + // 수요처 목록 조회 coSttnInit: async (pageNo: string, pageCnt: string, con: string) => { try { diff --git a/apps/wr/src/shared/ui/alert-dialog.tsx b/apps/wr/src/shared/ui/alert-dialog.tsx index 6160d5301..51e82798c 100644 --- a/apps/wr/src/shared/ui/alert-dialog.tsx +++ b/apps/wr/src/shared/ui/alert-dialog.tsx @@ -21,10 +21,12 @@ function AlertDialog() { {message}

- - - - + +
+ + + +
diff --git a/apps/wr/tsconfig.json b/apps/wr/tsconfig.json index 493584782..221de4580 100644 --- a/apps/wr/tsconfig.json +++ b/apps/wr/tsconfig.json @@ -28,13 +28,9 @@ "@/*": ["./*"], "@common/components/*": ["../../packages/common/components/src/*"], "@common/components": ["../../packages/common/components/src/index"], - "@common/business_components/*": [ - "../../packages/common/business_components/src/*" - ], - "@common/business_components": [ - "../../packages/common/business_components/src/index" - ], - "@common/network": ["../../packages/common/network"] + "@common/business_components/*": ["../../packages/common/business_components/src/*"], + "@common/business_components": ["../../packages/common/business_components/src/index"], + "@common/network": ["../../packages/common/network"], } }, "include": [ From 908ec81fb7584a1c935042d2e5444b4922cadaf5 Mon Sep 17 00:00:00 2001 From: LGS Date: Tue, 17 Mar 2026 15:47:34 +0900 Subject: [PATCH 02/25] =?UTF-8?q?=EC=B9=A8=EC=9E=85=EC=88=98=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=20=ED=8C=9D=EC=97=85=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/infilChart.tsx | 447 +++++++++--------- 1 file changed, 226 insertions(+), 221 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 9f481a2b9..094936638 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -1,268 +1,273 @@ 'use client' -import { CHART_FORM, type ChartConfig, MainChart, UiModal } from "@common/business_components"; + +import React, { useEffect, useMemo, useState } from 'react'; +import moment from 'moment'; + +import { + CHART_FORM, + type ChartConfig, + MainChart, + UiModal, +} from '@common/business_components'; import { SelectBox } from '@common/business_components/ui'; import { Button, Input, Label } from '@common/components'; -import React, { useEffect, useState } from 'react'; -import moment from "moment"; import type { TInftwtAnls } from './aplcnYms'; import * as fn from './aplcnYms'; -import { useInfilChartModalStore } from '../chartModalStore'; // 모달 상태 관리 스토어 +import { useInfilChartModalStore } from '../chartModalStore'; + type ModalOpenProp = { - pplMngNo?: string, // 관로관리번호 -} -type DataType = { label: string; val: number }; + pplMngNo?: string; // 관로관리번호 +}; -const InfilChart = ({ pplMngNo }: ModalOpenProp) => { - const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useInfilChartModalStore(); // 모달 상태 관리 스토어 - const [popupOpen, setPopupOpen] = React.useState(false); // 조회조건팝업 - const buttonRef = React.useRef(null); // 버튼 참조 - const [popupPosition, setPopupPosition] = useState<{ top: number; left: number }>({ top: 0, left: 0 }); // 팝업 위치 - const [selectedAplcnYm, setSelectedAplcnYm] = useState(""); +type DataType = { + label: string; + val: number; +}; + +const INITIAL_ANALYSIS_OPTIONS = [{ val: 0, text: '선택' }]; + +const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { + const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useInfilChartModalStore(); + + const [selectedAplcnYm, setSelectedAplcnYm] = useState(''); const [inftwtAnlss, setInftwtAnlss] = useState([]); - const [inftwtAnlsInfos, setInftwtAnlsInfos] = useState<{ text: string; val: number; hidden?: boolean }[]>([{ val: 0, text: '선택' }]); // 침입수분석정보 options - const [inftwtAnls, setInftwtAnls] = useState(null); // 침입수분석정보 - const [selectedInftwtAnls, setSelectedInftwtAnls] = useState(0); // 침입수분석 정보 선택시 사용 + const [inftwtAnlsInfos, setInftwtAnlsInfos] = useState<{ text: string; val: number; hidden?: boolean }[]>( + INITIAL_ANALYSIS_OPTIONS, + ); + const [inftwtAnls, setInftwtAnls] = useState(null); + const [selectedInftwtAnls, setSelectedInftwtAnls] = useState(0); const [chartData, setChartData] = useState<{ chartData1: DataType[]; chartData2: DataType[] }>({ - chartData1: [], chartData2: [], + chartData1: [], + chartData2: [], }); - const [inftwtQty, setInftwtQty] = useState("0"); // 침입수량 - const aplcnYms = fn.useAplcnYms('inftwtAnlsRslt'); // 상수사용월 데이터 가져오기 + const [inftwtQty, setInftwtQty] = useState('0'); - pplMngNo = "L" + pplMngNo; // inp파일에 하수관로와 맨홀의 번호가 같으면 분석 오류가 발행하여 - const openPopup = () => { - if (buttonRef.current) { - const rect = buttonRef.current.getBoundingClientRect(); // 버튼 위치 계산 - setPopupPosition({ - top: rect.bottom + window.scrollY, // 버튼 아래쪽 - left: rect.left + window.scrollX, // 버튼 왼쪽 - }); - } - setPopupOpen(true); // 팝업 열기 - }; + const aplcnYms = fn.useAplcnYms('inftwtAnlsRslt'); + const normalizedPplMngNo = pplMngNo ? `L${pplMngNo}` : ''; const chartForm = CHART_FORM.LINE; const chartConfig = { - chartData1: { label: '순오수량', color: "red", }, - chartData2: { label: '실측하수량', color: "orange", } + chartData1: { label: '순오수량', color: 'red' }, + chartData2: { label: '실측하수량', color: 'orange' }, } as ChartConfig; + const hasChartData = useMemo(() => { + return chartData.chartData1.length > 0 || chartData.chartData2.length > 0; + }, [chartData]); + + const resetState = () => { + setSelectedAplcnYm(''); + setInftwtAnlss([]); + setInftwtAnlsInfos(INITIAL_ANALYSIS_OPTIONS); + setInftwtAnls(null); + setSelectedInftwtAnls(0); + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); + }; + useEffect(() => { - if (isModalOpen === false) { - setPopupOpen(true); // 모달이 닫힐 때 조회조건팝업은 열어두기 - setSelectedAplcnYm(""); // 상수사용월 초기화 - setInftwtAnlss([]); // 침입수분석 초기화 - setInftwtAnlsInfos([{ val: 0, text: '선택' }]); // 침입수분석정보 초기화 - setInftwtAnls(null); // 침입수분석정보 초기화 - setSelectedInftwtAnls(0); // 침입수분석 일련번호 초기화 - setChartData({ chartData1: [], chartData2: [], }); // 차트 데이터 초기화 - setInftwtQty("0"); // 침입수량 초기화 + if (!isModalOpen) { + resetState(); } }, [isModalOpen]); - // 상수사용월 변경 핸들러 const handleAplcnYmChange = async (val: string | number) => { const selectedValue = String(val); setSelectedAplcnYm(selectedValue); - - // 즉시 관련 상태 초기화 + setInftwtAnlss([]); setInftwtAnls(null); + setSelectedInftwtAnls(0); + setInftwtQty('0'); + setChartData({ chartData1: [], chartData2: [] }); - // 빈 값이면 초기화만 하고 종료 - if (!selectedValue || selectedValue === "0" || selectedValue === "") { - setInftwtAnlsInfos([{ val: 0, text: '선택' }]); + if (!selectedValue || selectedValue === '0') { + setInftwtAnlsInfos(INITIAL_ANALYSIS_OPTIONS); return; } - // API 호출 try { const data = await fn.selectInftwtAnls(selectedValue); - setInftwtAnlss(data ?? []); - setInftwtAnlsInfos(fn.getOptionsInftwtAnlsInfo(data)); + const list = data ?? []; + setInftwtAnlss(list); + setInftwtAnlsInfos(fn.getOptionsInftwtAnlsInfo(list)); } catch (error) { - console.error("selectInftwtAnls 에러:", error); + console.error('selectInftwtAnls 에러:', error); setInftwtAnlss([]); - setInftwtAnlsInfos([{ val: 0, text: '선택' }]); + setInftwtAnlsInfos(INITIAL_ANALYSIS_OPTIONS); } - setSelectedInftwtAnls(0); }; - // 분석정보 변경 핸들러 const handleInftwtAnlsSnChange = (val: string | number) => { const selectedValue = Number(val); - setSelectedInftwtAnls(selectedValue); - // 선택된 침입수분석 정보에 대한 처리 로직 + setSelectedInftwtAnls(selectedValue); + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); + if (selectedValue === 0) { setInftwtAnls(null); return; } - const selectedAnls = inftwtAnlss.find(anls => anls.inftwtAnlsSn === selectedValue); - if (selectedAnls) { - setInftwtAnls(selectedAnls); + const selectedAnls = inftwtAnlss.find((anls) => anls.inftwtAnlsSn === selectedValue) ?? null; + setInftwtAnls(selectedAnls); + }; + + const infilRsltChart = async () => { + if (!selectedAplcnYm || selectedInftwtAnls === 0 || !normalizedPplMngNo) { + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); + return; + } + + try { + const [inftwtAnlsRslt, oilq, qty] = await Promise.all([ + fn.selectInftwtAnlsRslt(selectedInftwtAnls, normalizedPplMngNo), + fn.selectOilq(selectedInftwtAnls, normalizedPplMngNo).catch((err) => { + console.error('selectOilq 에러:', err); + return []; + }), + fn.selectPplInftwtQty(selectedInftwtAnls, normalizedPplMngNo).catch((err) => { + console.error('selectPplInftwtQty 에러:', err); + return 0; + }), + ]); + + setChartData({ + chartData1: fn.getChartDataInftwtAnlsRslt(inftwtAnlsRslt ?? []), + chartData2: fn.getChartDataOilq(oilq ?? []), + }); + + const normalizedQty = Number(qty ?? 0); + setInftwtQty(normalizedQty.toLocaleString('ko-KR')); + } catch (error) { + console.error('infilRsltChart 에러:', error); + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); } }; - const closePopup = () => { // 팝업 닫기 - setPopupOpen(false); - } - const infilRsltChart = () => { // 그래프 & 팝업 닫기 - - fn.selectInftwtAnlsRslt(selectedInftwtAnls, pplMngNo).then((data) => {// 침입수분석 결과 조회 - const rsltData = fn.getChartDataInftwtAnlsRslt(data ?? []); - setChartData(prev => ({ - ...prev, - chartData1: rsltData // 침입수분석결과 - })); - }); - fn.selectOilq(selectedInftwtAnls, pplMngNo).then((data) => {// 유량 조회 - const rsltData = fn.getChartDataOilq(data ?? []); - setChartData(prev => ({ - ...prev, - chartData2: rsltData // 유량 - })); - }).catch((err) => { - console.error("selectOilq 에러:", err); - setChartData(prev => ({ - ...prev, - chartData2: [] // 유량 데이터 초기화 - })); - }); - fn.selectPplInftwtQty(selectedInftwtAnls, pplMngNo).then((data) => {// 침입수량 조회 - if (data > 0) { - setInftwtQty(data.toLocaleString('ko-KR')); - } - }); - setPopupOpen(false); - }; + const renderInfoInput = (label: string, value?: string | number | null) => ( +
+ + +
+ ); const renderBody = () => ( - <> -
침입수분석결과
- -
-
- - {/* 상수사용량 적용연월 */} -
- ● 상수사용량 적용연월 -
- - {(selectedAplcnYm) ? moment(selectedAplcnYm, "YYYYMM").format("YYYY-MM") : ""} - -
-
- {/* 침입수량 분석결과 */} -
- ● 침입수량 산정결과 -
- 침입수량 : - {inftwtQty} - m³/d -
-
-
- {/* 차트 */} -
- -
+
+
+
- {popupOpen && ( -
-
침입수분석 입력현황
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - + +
+
+

+ 침입수 분석 선택 조건 +

+ +
+
+
+ + +
+ +
+ + +
+ + {renderInfoInput('오수전환율:', inftwtAnls?.drtwSwtcRt ?? '')} + {renderInfoInput('시간패턴 파일명:', inftwtAnls?.atflHrPttnNm ?? '')} + {renderInfoInput('수용가-맨홀 매칭:', inftwtAnls?.atflMpngNm ?? '')} + {renderInfoInput('관망도 파일명:', inftwtAnls?.atflInpNm ?? '')} + {renderInfoInput('유량 파일명:', inftwtAnls?.atflOilqNm ?? '')}
-
- - +
-
)} - {/* */} - - ) + + +
+

침입수 분석 결과

+ +
+
+
+ ● + 상수사용량 적용연월 +
+
+ {selectedAplcnYm ? moment(selectedAplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} +
+
+ +
+
+ ● + 침입수량 산정결과 +
+
+ 침입수량 + {inftwtQty} + m³/d +
+
+
+ +
+ {hasChartData ? ( + + ) : ( +
+ 데이터가 없습니다. +
+ )} +
+
+
+
+ ); return ( { onOpenChange={setIsModalOpen} headerTitle="" bodyClass={` - min-h-[50vh] - w-[55vw] - max-w-none - max-h-none - overflow-visible - z-[50] - `} + w-[78vw] + max-w-none + min-h-[74vh] + max-h-none + overflow-visible + z-[50] + `} body={renderBody()} - noFooterYn='Y' + noFooterYn="Y" /> - ) -} + ); +}; -export default React.memo(InfilChart); \ No newline at end of file +export default React.memo(InfilChart); From c57c7ce1f71afc391266133b8025a5c00a0eefb4 Mon Sep 17 00:00:00 2001 From: ljpark Date: Tue, 17 Mar 2026 18:05:02 +0900 Subject: [PATCH 03/25] =?UTF-8?q?wr:=20=EA=B3=B5=ED=86=B5=20alet=20=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../matMng/coMng/coSttn/page.tsx | 29 +++++++++++-------- apps/wr/app/store/matDmd/coSttn/index.tsx | 17 +++++------ apps/wr/src/shared/ui/confirm-dialog.tsx | 24 ++++++++------- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx index bf471c564..f5fcf7d91 100644 --- a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx @@ -5,7 +5,7 @@ import { btnClass } from "@/app/store/common/code"; import { excelCoSttnParsing } from "@/app/store/matDmd/coSttn/excel"; import { fetchType, getFetch } from "@/components/lib/api"; import { - confirmToast, + //confirmToast, excelDownload, formatPhoneNumber, getCity, @@ -29,9 +29,10 @@ import type { DemandCompType } from "@common/business_components/ui/sdmInsertFor import { Button } from "@common/components/ui"; import moment from "moment"; import { useCallback, useEffect, useState } from "react"; -import toast, { Toaster } from "react-hot-toast"; +// import toast, { Toaster } from "react-hot-toast"; import { useTranslation } from "react-i18next"; import { useAlertStore } from "@/src/shared/lib"; +import { useConfirm } from "@frontend-opensource/use-react-hooks"; export default function CoSttn() { const { @@ -50,6 +51,7 @@ export default function CoSttn() { } = useWrStore((state) => state); const { regAuthrtYn, mdfcnAuthrtYn } = auth; const alert = useAlertStore((state) => state.setMessage); + const { confirm } = useConfirm(); const [bdstTable, setBdstTable] = useState(); const [pageNation, setPageNation] = useState(1); const { coSttnRes, coSttnResCount } = coSttn; @@ -168,16 +170,21 @@ export default function CoSttn() { } }; const { t } = useTranslation('base'); - const initPassword = () => { + const initPassword = async () => { if (updateData) { const dmdInfoId = updateData.dmdInfoId; const dmdInfoSliceId = `${dmdInfoId.slice(0, 3)}-${dmdInfoId.slice(3, 5)}-${dmdInfoId.slice(5, 10)}-${dmdInfoId.slice(10)}` - const handleConfirm = () => { - coSttnPwInit(dmdInfoId); + const handleConfirm = async () => { + const message = await coSttnPwInit(dmdInfoId); + alert(message); }; - confirmToast( t('isInitPw', { dmdInfoId: dmdInfoSliceId }), handleConfirm, 'text-2xl'); + //confirmToast( t('isInitPw', { dmdInfoId: dmdInfoSliceId }), handleConfirm, 'text-2xl'); + if (await confirm(t('isInitPw', { dmdInfoId: dmdInfoSliceId }))) { + await handleConfirm(); + } } else { - toast.error("비밀번호 초기화를 원하는 행을 선택해주세요.") + alert("비밀번호 초기화를 원하는 행을 선택해주세요."); + // toast.error("비밀번호 초기화를 원하는 행을 선택해주세요.") } } @@ -239,7 +246,7 @@ export default function CoSttn() { onClick={() => { /* 저장 로직 */ if (!updateData) { - toast.error("수요처 변경을 원하는 행을 선택해주세요"); + alert("수요처 변경을 원하는 행을 선택해주세요"); } else { setIsDmdModal({ ...isDmdModal, @@ -333,9 +340,7 @@ export default function CoSttn() { `/reuseFc/request/${data.dmdInfoId}` ); if (dmd) { - alert( - `사업자번호 ${dmd.dmdInfoId}는 이미 등록되었습니다. 다시등록해주세요` - ); + alert(`사업자번호 ${dmd.dmdInfoId}는 이미 등록되었습니다. 다시등록해주세요`); return; } await regDemandCompany(data as DemandCompType); @@ -353,7 +358,7 @@ export default function CoSttn() { } > - + {/* */} ); } diff --git a/apps/wr/app/store/matDmd/coSttn/index.tsx b/apps/wr/app/store/matDmd/coSttn/index.tsx index 4c326d283..ca610c381 100644 --- a/apps/wr/app/store/matDmd/coSttn/index.tsx +++ b/apps/wr/app/store/matDmd/coSttn/index.tsx @@ -2,7 +2,6 @@ import type { CommonTableProps } from "@/app/store/common/type/header"; import { fetchType, getFetchWithCount, putFectch } from "@/components/lib/api"; import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form"; import { coSttHeadListExport, coSttNodeListExport } from "./headList"; -import toast from "react-hot-toast"; // 테이블 헤드 리스트 const coSttNodeList = coSttNodeListExport; @@ -25,7 +24,7 @@ type coSttnActions = { coSttnInit: (pageNo: string, pageCnt: string, con: string) => void; coSttnSearch: (pageNo: string, pageCnt: string, con: string) => void; coSttnTxtSearch: (pageNo: string, pageCnt: string, con: string, txt: string) => void; - coSttnPwInit: (dmdInfoId: string) => void; + coSttnPwInit: (dmdInfoId: string) => Promise; }; export type coSttnType = coSttnState & coSttnActions; @@ -127,10 +126,14 @@ export const coSttnActionsExport: (set: any) => coSttnActions = ( try { const response = await putFectch(`/reuseFc/request/chgPassword/${dmdInfoId}`,[]) if (response.status === 200) { - toast.success('비밀번호가 초기화 되었습니다.') + return "비밀번호가 초기화되었습니다."; } else { - toast.error('비밀번호 초기화에 실패하였습니다') + return "비밀번호 초기화에 실패하였습니다."; } + } catch (err) { + console.log(err); + return "비밀번호 초기화에 실패하였습니다."; + } finally { set((state: coSttnState) => { return { ...state, @@ -140,11 +143,7 @@ export const coSttnActionsExport: (set: any) => coSttnActions = ( } } }); - } catch (err) { - console.log(err); - toast.error('비밀번호 초기화에 실패하였습니다.') - } } } -} \ No newline at end of file +} diff --git a/apps/wr/src/shared/ui/confirm-dialog.tsx b/apps/wr/src/shared/ui/confirm-dialog.tsx index 6a4996bfb..7a8065a98 100644 --- a/apps/wr/src/shared/ui/confirm-dialog.tsx +++ b/apps/wr/src/shared/ui/confirm-dialog.tsx @@ -28,17 +28,19 @@ function ConfirmDialog({ {message}

- - - - - - - + +
+ + + + + + +
From 630c9492cdc380c885903408c592351cb6d66187 Mon Sep 17 00:00:00 2001 From: dongsilove Date: Tue, 17 Mar 2026 22:42:46 +0900 Subject: [PATCH 04/25] =?UTF-8?q?sn:=20=EC=B9=A8=EC=9E=85=EC=88=98=201?= =?UTF-8?q?=EC=B0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/infilChart.tsx | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 094936638..9b2401c28 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -150,10 +150,10 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { }; const renderInfoInput = (label: string, value?: string | number | null) => ( -
- +
+ {
); + const handleReset = () => { + resetState(); + } const renderBody = () => (
@@ -169,14 +172,14 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => {
-

+

침입수 분석 선택 조건

-
-
-

침입수 분석 결과

+

침입수 분석 결과

@@ -259,7 +262,7 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { yFieldText2="" /> ) : ( -
+
데이터가 없습니다.
)} From f993a4a13e922af92343a6659ab2bb86d2065369 Mon Sep 17 00:00:00 2001 From: dongsilove Date: Tue, 17 Mar 2026 22:53:00 +0900 Subject: [PATCH 05/25] =?UTF-8?q?sn:=20=ED=8F=B0=ED=8A=B8=20=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/popupComponent/chart/infilChart.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 9b2401c28..0f4d0bdb7 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -230,23 +230,23 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => {
- ● + {/* ● */} 상수사용량 적용연월
-
+
{selectedAplcnYm ? moment(selectedAplcnYm, 'YYYYMM').format('YYYY-MM') : '-'}
- ● + {/* ● */} 침입수량 산정결과
- 침입수량 - {inftwtQty} - m³/d + 침입수량 + {inftwtQty} + m³/d
From 13fad0c692906b7ee6c780bac6ba1769aa161643 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 09:38:43 +0900 Subject: [PATCH 06/25] =?UTF-8?q?sn:=20=EC=B9=A8=EC=9E=85=EC=88=982?= =?UTF-8?q?=EC=B0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/popupComponent/chart/infilChart.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 0f4d0bdb7..4086f1966 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -151,9 +151,9 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { const renderInfoInput = (label: string, value?: string | number | null) => (
- + {
-
-
-

- 강우유입수분석 결과 -

+

+ 강우유입수분석 결과 +

-
-
-
- 상수사용량 적용연월 -
-
- {aplcnYm ? moment(aplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} -
+
+ {/* 좌측 카드 */} +
+
+ 상수사용량 적용연월 +
+
+ {aplcnYm ? moment(aplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} +
+
+ + {/* 우측 카드 */} +
+ {/* 좌측: 제목 (세로 가운데 정렬) */} +
+ + 강우유입수량 분석결과 + +
+ + {/* 우측: 지표 영역 */} +
+ +
+ 평균RDII +
+ {rdiiQty} + m³/d +
+
+ +
+ 적용 강우량 +
+ {rainTotal} + mm +
+
+ +
+ 강우량 대비 RDII +
+ {totalVolume} + m³/mm +
+
+
+
-
-
- 강우유입수량 분석결과 -
-
-
- 평균RDII -
- {rdiiQty} - m³/d -
+
+ {hasChartData ? ( + + ) : ( +
+ 데이터가 없습니다.
-
- 적용강우량 -
- {rainTotal} - mm -
-
-
- 강우량대비 RDII -
- {totalVolume} - m³/mm -
-
-
+ )}
-
- -
- {hasChartData ? ( - - ) : ( -
- 데이터가 없습니다. -
- )} -
From 3d11a8be21dc34afbe5431164a8bb7d85a82bbbc Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 13:20:32 +0900 Subject: [PATCH 09/25] wr: message alert --- .../matMng/coMat/coMatRvw/page.tsx | 21 ++++++++++--------- .../matMng/coMat/ruseCaseMng/page.tsx | 6 ++++-- .../matMng/coMat/ruseRvwHstry/page.tsx | 10 +++++---- .../matMng/coMng/coSttn/page.tsx | 6 ++++-- .../ruseFcltMng/fcltReg/pbnstReg/page.tsx | 16 +++++++------- apps/wr/app/store/common/searchCode/index.ts | 19 +++++++++-------- .../fcltReg/pbnstReg/buseReg/bugRegForm.tsx | 11 ++++++---- 7 files changed, 51 insertions(+), 38 deletions(-) diff --git a/apps/wr/app/(with-layout)/matMng/coMat/coMatRvw/page.tsx b/apps/wr/app/(with-layout)/matMng/coMat/coMatRvw/page.tsx index d48c24960..0551b07a2 100644 --- a/apps/wr/app/(with-layout)/matMng/coMat/coMatRvw/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMat/coMatRvw/page.tsx @@ -1,5 +1,11 @@ "use client"; - +/** + * 📄 CoMatRvw 수요매칭 검토 + * Next.js App Router (app/) 기반 페이지 컴포넌트 예시 + * + * - 대민에서 신청하는 수요처의 수요등록 정보를 운영담당자가 수요 매칭 검토를 진행한다. + * - 전체적으로 form을 만들어서 form안에 데이터를 넣고 api를 호출하여 저장한다. + */ import { useWrStore } from "@/app/store"; import { btnClass } from "@/app/store/common/code"; import { usageProcData } from "@/app/store/matDmd/coMatRvw/headList"; @@ -33,26 +39,21 @@ import { } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, Input, Label } from "@common/components/ui"; +import { useAlertStore } from "@/src/shared/lib"; import { zodResolver } from "@hookform/resolvers/zod"; import moment from "moment"; import { useEffect, useRef, useState } from "react"; import { useForm, useWatch } from "react-hook-form"; -import toast, { Toaster } from "react-hot-toast"; +import { Toaster } from "react-hot-toast"; import { z } from "zod"; -/** - * 📄 CoMatRvw 수요매칭 검토 - * Next.js App Router (app/) 기반 페이지 컴포넌트 예시 - * - * - 대민에서 신청하는 수요처의 수요등록 정보를 운영담당자가 수요 매칭 검토를 진행한다. - * - 전체적으로 form을 만들어서 form안에 데이터를 넣고 api를 호출하여 저장한다. - */ export default function CoMatRvw() { const { auth, code, coRvw, coMatRvwInit, coMatRvwSearch, coMatRvwInqua } = useWrStore((state) => state); const { coMatRvwRes, coMatRvwCount } = coRvw; const { regAuthrtYn } = auth; + const alert = useAlertStore((state) => state.setMessage); //init, sub, match const initRef = useRef(false); @@ -253,7 +254,7 @@ export default function CoMatRvw() { const fromNum = Number(fromDate); const toNum = Number(toDate); if (fromNum > toNum) { - toast.error( + alert( "시작년도가 종료년도 이후로 설정할 수 없습니다." ); } else { diff --git a/apps/wr/app/(with-layout)/matMng/coMat/ruseCaseMng/page.tsx b/apps/wr/app/(with-layout)/matMng/coMat/ruseCaseMng/page.tsx index d76549153..d315b2c25 100644 --- a/apps/wr/app/(with-layout)/matMng/coMat/ruseCaseMng/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMat/ruseCaseMng/page.tsx @@ -21,8 +21,9 @@ import { } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, Label } from "@common/components/ui"; +import { useAlertStore } from "@/src/shared/lib"; import { useEffect, useState } from "react"; -import toast, { Toaster } from "react-hot-toast"; +import { Toaster } from "react-hot-toast"; import { useTranslation } from "react-i18next"; import * as XLSX from "xlsx"; @@ -44,6 +45,7 @@ export default function RuseCaseMng() { const [name, setName] = useState(""); const [resetPage, isResetPage] = useState(false); const { t } = useTranslation("base"); + const alert = useAlertStore((state) => state.setMessage); // 엑셀 등록 모달 const [isExcelOpen, setIsExcelOpen] = useState(false); @@ -84,7 +86,7 @@ export default function RuseCaseMng() { if (!excelList) return; if (excelList.length === 0) { - toast.error(t("excelDownErrMsg")); + alert(t("excelDownErrMsg")); return; } fetch(`/sample_ruseCaseMng.xlsx`, {}).then(async (response) => { diff --git a/apps/wr/app/(with-layout)/matMng/coMat/ruseRvwHstry/page.tsx b/apps/wr/app/(with-layout)/matMng/coMat/ruseRvwHstry/page.tsx index 9b7737236..782becca9 100644 --- a/apps/wr/app/(with-layout)/matMng/coMat/ruseRvwHstry/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMat/ruseRvwHstry/page.tsx @@ -24,9 +24,10 @@ import { } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, Label } from "@common/components/ui"; +import { useAlertStore } from "@/src/shared/lib"; import moment from "moment"; import { useCallback, useEffect, useState } from "react"; -import toast, { Toaster } from "react-hot-toast"; +import { Toaster } from "react-hot-toast"; import { useTranslation } from "react-i18next"; export default function RuseRvwHstry() { const { @@ -40,6 +41,7 @@ export default function RuseRvwHstry() { } = useWrStore((state) => state); const { rvwHistRes, ruseHistHeadList, rvwHistCount } = ruseHist; const { regAuthrtYn } = auth; + const alert = useAlertStore((state) => state.setMessage); const [pageNation, setPageNatiion] = useState(1); @@ -79,7 +81,7 @@ export default function RuseRvwHstry() { const fromNum = Number(fromDate); const toNum = Number(toDate); if (fromNum > toNum) { - toast.error("시작년도가 종료년도 이후로 설정할 수 없습니다."); + alert("시작년도가 종료년도 이후로 설정할 수 없습니다."); } else { let con: string | number = ""; if (String(objSearch.city).length > 0) { @@ -133,7 +135,7 @@ export default function RuseRvwHstry() { selectedData[index]?.splyFcltFlg === "매칭완료" && headId === "completeYn" ) { - toast.error(t("canNotChangeMatStateMsg")); + alert(t("canNotChangeMatStateMsg")); return; } } @@ -177,7 +179,7 @@ export default function RuseRvwHstry() { // // )); } else { - toast.error( t('isNotMatchFinishMsg')); + alert(t('isNotMatchFinishMsg')); } }; useEffect(() => { diff --git a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx index f5fcf7d91..85d9ef635 100644 --- a/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMng/coSttn/page.tsx @@ -327,7 +327,8 @@ export default function CoSttn() { ? objSearch.sgg : objSearch.city; if (updateData?.dmdInfoId) { - await updateDemandCompany(data as DemandCompType); + const message = await updateDemandCompany(data as DemandCompType); + alert(message); coSttnInit("1", "13", String(con)); setIsDmdModal({ isMoal: false, @@ -343,7 +344,8 @@ export default function CoSttn() { alert(`사업자번호 ${dmd.dmdInfoId}는 이미 등록되었습니다. 다시등록해주세요`); return; } - await regDemandCompany(data as DemandCompType); + const message = await regDemandCompany(data as DemandCompType); + alert(message); coSttnInit("1", "13", String(con)); setIsDmdModal({ isMoal: false, diff --git a/apps/wr/app/(with-layout)/ruseFcltMng/fcltReg/pbnstReg/page.tsx b/apps/wr/app/(with-layout)/ruseFcltMng/fcltReg/pbnstReg/page.tsx index 396edb8f0..9ad16e84d 100644 --- a/apps/wr/app/(with-layout)/ruseFcltMng/fcltReg/pbnstReg/page.tsx +++ b/apps/wr/app/(with-layout)/ruseFcltMng/fcltReg/pbnstReg/page.tsx @@ -44,13 +44,14 @@ import { import { PbnstMngForm } from "@/components/ui/form/fcltReg/pbnstReg/mngReg/mngRegForm"; import { PbnstBuseForm } from "@/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm"; import { PbnstRegModal } from "@/components/ui/modal/fcltReg/pbnstRegModal/pbnstRegModal"; -import toast, { Toaster } from "react-hot-toast"; // toast 이미 import 되어 있음 +import { Toaster } from "react-hot-toast"; import { writeRgtrAndMdfr } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg"; import { useFieldArray, useForm, type FieldErrors } from "react-hook-form"; // FieldErrors 타입 추가 import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { createDefaultPbnstItem } from "./utilsZod"; import { useTranslation } from "react-i18next"; +import { useAlertStore } from "@/src/shared/lib"; export default function PublicReuseFaciltyInsert() { const { auth, @@ -66,6 +67,7 @@ export default function PublicReuseFaciltyInsert() { } = useWrStore((state) => state); const { t } = useTranslation("base"); + const alert = useAlertStore((state) => state.setMessage); const { pubFacHeadList, pbnstHasuResCount, pbnstHasuRes, pbnstRes } = pbnst; const { regAuthrtYn, mdfcnAuthrtYn, laeSeCd } = auth; const [, setCurrentTab] = useState("mng"); @@ -140,7 +142,7 @@ export default function PublicReuseFaciltyInsert() { const isFcltSuccess = resFclt.status === "fulfilled"; const isBizSuccess = resBiz.status === "fulfilled"; if (isFcltSuccess && isBizSuccess) { - toast.success("하수 재이용 시설 및 사업이 수정되었습니다. "); + alert("하수 재이용 시설 및 사업이 수정되었습니다."); // 메시지 표시, 페이지 이동 등 } else { let message = ""; @@ -151,7 +153,7 @@ export default function PublicReuseFaciltyInsert() { if (!isBizSuccess) { message += "하수재이용 시설 사업 "; } - toast.error(message + "오류 입니다 "); + alert(message + "오류 입니다 "); pubHasuInit("1", laeSeCd); } }); @@ -215,7 +217,7 @@ export default function PublicReuseFaciltyInsert() { } } // 최종 오류 메시지 출력 - toast.error(`${prefix}${message}`); + alert(`${prefix}${message}`); }); } }; @@ -321,8 +323,8 @@ export default function PublicReuseFaciltyInsert() { onClick={() => { // pbnstMngData([] as customPbnst[]); if (!selectRow) { - toast.error( - "하수리시시설을 테이블을 선택하고 등록버튼을 눌러주세요" + alert( + "재시용시설을 등록할 하수리시시설을 테이블에서 선택하고 등록버튼을 눌러주세요" ); return; } else { @@ -416,7 +418,7 @@ export default function PublicReuseFaciltyInsert() { onClick={() => { // pbnstMngData([] as customPbnst[]); if (!selectRow) { - toast.error( + alert( "하수리시시설을 테이블을 선택하고 등록버튼을 눌러주세요" ); return; diff --git a/apps/wr/app/store/common/searchCode/index.ts b/apps/wr/app/store/common/searchCode/index.ts index 03d1b0fc5..1478b10a8 100644 --- a/apps/wr/app/store/common/searchCode/index.ts +++ b/apps/wr/app/store/common/searchCode/index.ts @@ -7,7 +7,6 @@ import { import type { pubHasuType } from "../../ruseFcltMng/fcltReg/pbnstReg/type"; import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form"; import type { conCostFeeType, rateFeeType } from "./type"; -import toast from "react-hot-toast"; export const comFcltStateExport: comFcltState = { @@ -59,8 +58,8 @@ export type comFcltState = { type comFcltActions = { getSwtrmtFcltNm: (searchNm: string) => void; getDemandCompList: (searchNm: string, cnt: number) => void; - regDemandCompany: (data: DemandCompType) => void; - updateDemandCompany: (data: DemandCompType) => void; + regDemandCompany: (data: DemandCompType) => Promise; + updateDemandCompany: (data: DemandCompType) => Promise; getConstCostFee: (year: string) => void; getRateFee: (year: string) => void; }; @@ -109,7 +108,6 @@ export const comFcltSearchAction: (set: any) => comFcltActions = (set: any) => { fetchType.WR ); if (response.status === 200) { - toast.success('수요처가 등록되었습니다. ') set((state: comFcltState) => { return { @@ -117,11 +115,12 @@ export const comFcltSearchAction: (set: any) => comFcltActions = (set: any) => { dmdIsSucees: "success" } }); + return "수요처가 등록되었습니다."; } + return "수요처 등록에 실패하였습니다."; } catch (err) { console.log(err); - toast.error('수요처가 등록 오류입니다.. ') - + return "수요처 등록 중 오류가 발생했습니다."; } }, updateDemandCompany: async (data: DemandCompType) => { @@ -131,7 +130,6 @@ export const comFcltSearchAction: (set: any) => comFcltActions = (set: any) => { let message = ""; if (response.status === 200) { message = "success"; - toast.success('수요처 정보가 변경되었습니다. ' ) } else { message = "fail"; } @@ -142,10 +140,13 @@ export const comFcltSearchAction: (set: any) => comFcltActions = (set: any) => { dmdIsSucees: message } }); + if (response.status === 200) { + return "수요처 정보가 변경되었습니다."; + } + return "수요처 정보 변경에 실패하였습니다."; } catch (err) { console.log(err); - toast.success('수요처 정보가 오류입니다. ' ) - + return "수요처 정보 변경 중 오류가 발생했습니다."; } }, getRateFee: async (year: string) => { diff --git a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx index 614a6a7a3..1fffe2cdb 100644 --- a/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx +++ b/apps/wr/components/ui/form/fcltReg/pbnstReg/buseReg/bugRegForm.tsx @@ -39,8 +39,9 @@ import type { DemandCompType } from "@common/business_components/ui/sdmInsertFor import RuseMngTableForm from "@/components/ui/table/pbnstReg/ruseMngTableForm/ruseMngTableForm"; import type { SelectDataType } from "@common/business_components"; import { BuseWaterQulity } from "./buseWaterQulity/buseWaterQulity"; -import toast from "react-hot-toast"; +// import toast from "react-hot-toast"; import { useTranslation } from "react-i18next"; +import { useAlertStore } from "@/src/shared/lib"; //import { useTranslation } from "react-i18next"; @@ -74,6 +75,7 @@ export function PbnstBuseForm({ readonly?: boolean; }) { const { t } = useTranslation("base"); + const alert = useAlertStore((state) => state.setMessage); const { code, @@ -193,7 +195,7 @@ export function PbnstBuseForm({ fcDemands: [], }); await appendBiz(newItem); - toast.success(t('insertRuseBiz',{cycle: pbnstBizCycle + 1})) + alert(t('insertRuseBiz',{cycle: pbnstBizCycle + 1})) setIndexBiz(pbnstBizCycle); }, [form, indexMng, indexBiz, appendBiz, setIndexBiz]); @@ -779,8 +781,9 @@ export function PbnstBuseForm({ rtnValue={(searchText: string, pageCnt: number) => { getDemandCompList(searchText, pageCnt); }} - rtnInputData={(data) => { - regDemandCompany(data as DemandCompType); + rtnInputData={async (data) => { + const message = await regDemandCompany(data as DemandCompType); + alert(message); setIsDmdModal({ isMoal: false, data: data as DemandCompType, From 165c7bcbbfa9a4a241f6cdc3c6c404b4f1a33aef Mon Sep 17 00:00:00 2001 From: LGS Date: Wed, 18 Mar 2026 14:13:08 +0900 Subject: [PATCH 10/25] =?UTF-8?q?=EC=B9=A8=EC=9E=85=EC=88=98=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=EA=B2=B0=EA=B3=BC=20[=EA=B0=95=EC=9A=B0=EC=9C=A0?= =?UTF-8?q?=EC=9E=85=EC=88=98=EB=B6=84=EC=84=9D=EA=B2=B0=EA=B3=BC]=20?= =?UTF-8?q?=EB=B0=95=EC=8A=A4=20=E5=85=A7=203=EA=B0=9C=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=20=EB=8B=A8=EC=9C=84=20=EC=A0=95=EB=A0=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/rdiiChart.tsx | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx index 359b7978c..58d9f9a49 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -275,28 +275,39 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => { {/* 우측: 지표 영역 */}
- -
+
평균RDII -
- {rdiiQty} - m³/d +
+
+ + {rdiiQty} + + m³/d +
-
+
적용 강우량 -
- {rainTotal} - mm +
+
+ + {rainTotal} + + mm +
-
+
강우량 대비 RDII -
- {totalVolume} - m³/mm +
+
+ + {totalVolume} + + m³/mm +
From 59e3dd0804eb4e4a0d06218b216741e7212674d5 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 14:46:36 +0900 Subject: [PATCH 11/25] wr: message alert matMng --- .../matMng/coMng/drgtSttn/page.tsx | 6 ++-- .../matMng/coMng/ldrmntCoSttn/page.tsx | 9 ++++-- apps/wr/app/store/matDmd/coMatRvw/index.tsx | 25 +++++++--------- .../app/store/matDmd/ldrmntCoSttn/index.tsx | 11 +++---- .../wr/app/store/matDmd/ruseCaseMng/index.tsx | 10 +++---- .../ui/form/coMat/conCostForm/conCostForm.tsx | 30 +++++++++++++------ .../ruseCaseMng/ruseCaseMngExcelModal.tsx | 9 ++++-- 7 files changed, 59 insertions(+), 41 deletions(-) diff --git a/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx b/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx index b55878487..b4ca64268 100644 --- a/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx @@ -9,12 +9,14 @@ import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/b import { ContentsDiv, DateMonthPicker, downloadExcel, SearchDiv, SearchFormLeft, SearchFormRight, SelectBox, UiModal, UiTable, type SelectDataType } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, Label, ScrollArea } from "@common/components/ui"; +import { useAlertStore } from "@/src/shared/lib"; import { useEffect, useState, useRef } from "react"; -import { toast, Toaster } from "react-hot-toast"; +import { Toaster } from "react-hot-toast"; export default function DrgtSttn() { const { code, drgt, drgtSearch, drgtModalSearch, drgtInit } = useWrStore((state) => state); const { drgtRes, drgtMoRes } = drgt; + const alert = useAlertStore((state) => state.setMessage); const [fromDate, setFromDate] = useState('202506'); const [toDate, setToDate] = useState('202506'); const [selectSgg, setSelectSgg] = useState([{ val: '0', text: '전체' }]); @@ -32,7 +34,7 @@ export default function DrgtSttn() { if (fromDate && toDate && drgtRes[index]) { drgtModalSearch(fromDate, toDate, drgtRes[index].sggNm ?? ''); } else { - toast.error("조회기간을 선택해주세요."); + alert("조회기간을 선택해주세요."); } } diff --git a/apps/wr/app/(with-layout)/matMng/coMng/ldrmntCoSttn/page.tsx b/apps/wr/app/(with-layout)/matMng/coMng/ldrmntCoSttn/page.tsx index eee7d9f73..13b596b5c 100644 --- a/apps/wr/app/(with-layout)/matMng/coMng/ldrmntCoSttn/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMng/ldrmntCoSttn/page.tsx @@ -27,8 +27,9 @@ import { } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; +import { useAlertStore } from "@/src/shared/lib"; import { useCallback, useEffect, useState } from "react"; -import toast, { Toaster } from "react-hot-toast"; +import { Toaster } from "react-hot-toast"; import { useTranslation } from "react-i18next"; export default function LdrmntCoSttn() { @@ -46,6 +47,7 @@ export default function LdrmntCoSttn() { const [resetPage, isResetPage] = useState(false); const [isDownloadClicked, setIsDownloadClicked] = useState(false); const { t } = useTranslation('base'); + const alert = useAlertStore((state) => state.setMessage); const { regAuthrtYn, mdfcnAuthrtYn } = auth; const excelClick = useCallback(() => { @@ -113,7 +115,7 @@ export default function LdrmntCoSttn() { headerRange: "A1:F1" }); } else { - toast.error(t('excelDownErrMsg')); + alert(t('excelDownErrMsg')); } setIsDownloadClicked(false); }, [excelData, isDownloadClicked]); @@ -270,7 +272,8 @@ export default function LdrmntCoSttn() { readonly={mdfcnAuthrtYn === 'N'} onFormSubmit={async (value) => { const handleConfirm = async () => { - await ldrmntUpdate(value); + const message = await ldrmntUpdate(value); + alert(message); setDetailModal({ ...detailModal, isOpen: false }); ldrmntSearch(false, pageNation, '20', computeCityNm(), searchTxt || ""); }; diff --git a/apps/wr/app/store/matDmd/coMatRvw/index.tsx b/apps/wr/app/store/matDmd/coMatRvw/index.tsx index 9e857d4d3..0c58db9a6 100644 --- a/apps/wr/app/store/matDmd/coMatRvw/index.tsx +++ b/apps/wr/app/store/matDmd/coMatRvw/index.tsx @@ -1,5 +1,4 @@ import { fetchType, getFetchWithCount, putFectch } from "@/components/lib/api"; -import toast from "react-hot-toast"; import type { CommonTableProps } from "../../common/type/header"; import { constCostHeadListExport, @@ -50,7 +49,7 @@ type coRvwActions = { splyCd: string, dmdCd: string, data: DedMatUpdateType - ) => void; + ) => Promise; coMatRvwSearch: ( pageNo: number, pageCnt: number, @@ -104,20 +103,17 @@ export const coRvwActionsExport: (set: any) => coRvwActions = (set: any) => { splyCd: string, dmdCd: string, data: DedMatUpdateType - ) => { + ): Promise => { try { const response = await putFectch( `/reuseFc/request/cst/${splyCd}/${dmdCd}`, data ); if (response.status === 200) { - - if(data.flg ==='Sub'){ - - toast.success("매칭 검토로 저장되었습니다."); - }else{ - toast.success("매칭 검토완료로 저장되었습니다."); - } + const successMessage = + data.flg === "Sub" + ? "매칭 검토로 저장되었습니다." + : "매칭 검토완료로 저장되었습니다."; const coMatRvwRes = await coMatInit( 1, @@ -125,21 +121,22 @@ export const coRvwActionsExport: (set: any) => coRvwActions = (set: any) => { new Date().getFullYear().toString(), new Date().getFullYear().toString() ); - return set((state: coRvwState) => ({ + set((state: coRvwState) => ({ ...state, coRvw: { ...state.coRvw, coMatRvwRes: coMatRvwRes.data, - coMatRvwCount:coMatRvwRes.count, + coMatRvwCount: coMatRvwRes.count, init: false, }, })); + return successMessage; } else { - toast.error("매칭 검토 저장에 실패했습니다."); + return "매칭 검토 저장에 실패했습니다."; } } catch (e) { - toast.error("매칭 검토 저장 오류입니다."); console.error("coMatRvwUpdate error", e); + return "매칭 검토 저장 오류입니다."; } }, coMatRvwSearch: async ( diff --git a/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx b/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx index fed013417..8de791c89 100644 --- a/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx +++ b/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx @@ -1,6 +1,5 @@ import type { CommonTableProps } from "@/app/store/common/type/header"; import { deleteFectch, fetchType, getFetchWithCount, postFectch, putFectch } from "@/components/lib/api"; -import toast from "react-hot-toast"; import { z } from "zod"; import { TEST_UUID } from "../../ruseFcltMng/fcltReg/rainReg"; import { ldrmntHeadListExport, ldrmntNodeListExport, ldrmntZod } from "./headList"; @@ -35,7 +34,7 @@ type ldrmntActions = { ldrmntRegData: (data: any[]) => void, ldrmntInit: (isExcel: boolean, con: string) => void ldrmntSearch: (isExcel: boolean, page: number, sggCd: string, total: string, coNm: string) => void; - ldrmntUpdate: (ldrmntRes: customLdrmnt) => void; + ldrmntUpdate: (ldrmntRes: customLdrmnt) => Promise; ldrmntDelete: () => void; loadingOpen: (isOpen: boolean) => void }; @@ -192,12 +191,14 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = ( ); if (res.ok) { - toast.success("잠재수요처 상세정보가 수정되었습니다.",) + return "잠재수요처 상세정보가 수정되었습니다."; } + return "잠재수요처 상세정보 수정에 실패하였습니다."; } catch (error) { console.error("Error ldrmntUpdate:", error); - toast.error("잠재수요처 상세정보 수정에 실패하였습니다.") + return "잠재수요처 상세정보 수정에 실패하였습니다."; } + return "잠재수요처 상세정보가 없습니다."; }, ldrmntDelete: async () => { try { @@ -228,4 +229,4 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = ( } }, } -} \ No newline at end of file +} diff --git a/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx b/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx index 587e08fd9..49cc61d1f 100644 --- a/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx +++ b/apps/wr/app/store/matDmd/ruseCaseMng/index.tsx @@ -1,5 +1,4 @@ import { fetchType, getFetchWithCount, postFectch } from "@/components/lib/api"; -import { toast } from "react-hot-toast"; import type { TableUpperProps } from "../../common/type/header"; import { ruseCaseHeadListExport } from "./headList"; import type { ruseCaseMngExcelProps } from "./excel"; @@ -24,7 +23,7 @@ type ruseCaseActions = { usageCd: string, name: string ) => Promise; - insertRuseCaseMng: (data: any) => Promise; + insertRuseCaseMng: (data: any) => Promise; }; const fetchSearchRuseCaseMng = async ( @@ -131,11 +130,10 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = ( } }, - insertRuseCaseMng: async (data: any) => { + insertRuseCaseMng: async (data: any): Promise => { try { const response = await fetchInsertRuseCaseMng(data); if (response.status === 200) { - toast.success("물재이용사례 등록이 완료되었습니다. "); const res = await getFetchWithCount( fetchType.WR, `/reuseFc/pubFcRuseCase/1/10/0/0` @@ -147,11 +145,13 @@ export const ruseCaseActionsExport: (set: any) => ruseCaseActions = ( count: res.count, }, })); + return "물재이용사례 등록이 완료되었습니다."; } else { + return "물재이용사례 등록에 실패했습니다."; } } catch (e) { console.log(e); - toast.error("물재이용사례 등록에 실패하였습니다. "); + return "물재이용사례 등록에 실패했습니다."; } }, }; diff --git a/apps/wr/components/ui/form/coMat/conCostForm/conCostForm.tsx b/apps/wr/components/ui/form/coMat/conCostForm/conCostForm.tsx index 186e0bb77..cfb388264 100644 --- a/apps/wr/components/ui/form/coMat/conCostForm/conCostForm.tsx +++ b/apps/wr/components/ui/form/coMat/conCostForm/conCostForm.tsx @@ -13,6 +13,7 @@ import { getInterpolation, transformAndInterpolate, } from "@/components/lib/func/calculateConstCost "; +import { useAlertStore } from "@/src/shared/lib"; import { ConstCostFeeTable } from "@/components/ui/modal/coMat/constCostFeeTable"; import { RateFeeTableModal } from "@/components/ui/modal/coMat/rateFeeModal"; import { @@ -53,6 +54,7 @@ export default function ConCostForm({ getRateFee, getConstCostFee, } = useWrStore((state) => state); + const alert = useAlertStore((state) => state.setMessage); const ref = useRef(false); @@ -108,11 +110,11 @@ export default function ConCostForm({ const calculateConstCost = useCallback(() => { const usgPrcsProcs = usgPrcsProcsWatch; if (!dmndQtyWatch) { - toast.error("요구수량(m³/일)을 확인해주세요 계산할수 없습니다. "); + alert("요구수량(m³/일)을 확인해주세요 계산할수 없습니다. "); return; } if (usgPrcsProcs === null || usgPrcsProcs === undefined) { - toast.error( + alert( "용도에 따른 처리공정을 확인할수 없습니다. 용도를 확인해주세요. " ); return; @@ -175,9 +177,9 @@ export default function ConCostForm({ form.setValue("totalConstCost", Math.round(realResult)); } }, [constCostRes, rateFeeRes, usgPrcsProcsWatch, dmndQtyWatch]); - const onSubmit = (value: DmdCoReqType) => { + const onSubmit = async (value: DmdCoReqType) => { if (value.demandCst && !value.demandCst.prcsFcltCpctCstrnCst) { - toast.error("공사비 계산 진행 후 저장을 눌러주새요"); + alert("공사비 계산 진행 후 저장을 눌러주새요"); return; } @@ -211,10 +213,15 @@ export default function ConCostForm({
); -} \ No newline at end of file +} From 53356228a7dc31236905bcd9b8a18ca346b7da94 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 15:24:32 +0900 Subject: [PATCH 12/25] =?UTF-8?q?sn:=20=EA=B0=95=EC=9A=B0=EC=9C=A0?= =?UTF-8?q?=EC=9E=85=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/rdiiChart.tsx | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx index 58d9f9a49..07286bcbe 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -265,49 +265,49 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => {
{/* 우측 카드 */} -
+
{/* 좌측: 제목 (세로 가운데 정렬) */} -
- - 강우유입수량 분석결과 - +
+
+ 강우유입수량 분석결과 +
{/* 우측: 지표 영역 */} -
-
- 평균RDII -
-
- - {rdiiQty} - - m³/d -
+
+
+
+ 평균RDII +
+
+ {rdiiQty} +
+
+ m³/d
-
- 적용 강우량 -
-
- - {rainTotal} - - mm -
+
+
+ 적용 강우량 +
+
+ {rainTotal} +
+
+ mm
-
- 강우량 대비 RDII -
-
- - {totalVolume} - - m³/mm -
+
+
+ 강우량 대비 RDII +
+
+ {totalVolume} +
+
+ m³/mm
From cb8743ea3932b1b3d556e8f2c5b6040ca94fd2d3 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 16:15:25 +0900 Subject: [PATCH 13/25] =?UTF-8?q?sn:=20=EB=B6=84=EC=84=9D=ED=99=94?= =?UTF-8?q?=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/infilChart.tsx | 12 +++--- .../popupComponent/chart/rdiiChart.tsx | 42 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index b01ce79c9..3836b87f6 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -150,7 +150,7 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { }; const renderInfoInput = (label: string, value?: string | number | null) => ( -
+
{
-
+

침입수 분석 선택 조건 @@ -179,7 +179,7 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => {
-
+
@@ -193,7 +193,7 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { />
-
+
@@ -283,8 +283,8 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { bodyClass={` w-[78vw] max-w-none - min-h-[74vh] - max-h-none + min-w-[1000px] + min-h-[72vh] overflow-visible z-[50] `} diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx index 07286bcbe..aa622be1b 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -174,7 +174,7 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => { }; const renderInfoInput = (label: string, value?: string | number | null) => ( -
+
@@ -193,7 +193,7 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => {
-
+

강우유입수분석 선택 조건 @@ -201,7 +201,7 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => {
-
+
@@ -215,7 +215,7 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => { />
-
+
@@ -253,19 +253,19 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => { 강우유입수분석 결과

-
+
{/* 좌측 카드 */} -
-
- 상수사용량 적용연월 -
-
- {aplcnYm ? moment(aplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} -
+
+
+ 상수사용량 적용연월 +
+
+ {aplcnYm ? moment(aplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} +
{/* 우측 카드 */} -
+
{/* 좌측: 제목 (세로 가운데 정렬) */}
@@ -276,10 +276,10 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => { {/* 우측: 지표 영역 */}
-
+
평균RDII
-
+
{rdiiQty}
@@ -288,10 +288,10 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => {
-
+
적용 강우량
-
+
{rainTotal}
@@ -300,10 +300,10 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => {
-
+
강우량 대비 RDII
-
+
{totalVolume}
@@ -343,8 +343,8 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => { bodyClass={` w-[78vw] max-w-none - min-h-[74vh] - max-h-none + min-w-[1100px] + min-h-[72vh] overflow-visible z-[50] `} From b711dae3edc9c322a8d0904c83938992eb6aede1 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 17:20:39 +0900 Subject: [PATCH 14/25] =?UTF-8?q?wr:=20=EA=B3=B5=EC=9E=A5=EC=A3=BC?= =?UTF-8?q?=EC=86=8C>=ED=9A=8C=EC=82=AC=EC=A3=BC=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx b/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx index 294371c44..bb7c79024 100644 --- a/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx +++ b/apps/wr/app/store/matDmd/ldrmntCoSttn/headList.tsx @@ -72,7 +72,7 @@ export const ldrmntHeadListExport: CommonTableProps[] = [ }, { id: "fctryAddr", - title: "공장주소", + title: "회사주소", visible: true, row: 1, rowSpan: 1, From f9a1af43f553266bfec10d77bfd1a528b8a7ecf1 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 17:45:29 +0900 Subject: [PATCH 15/25] sn: zoom level --- apps/dm/app/(popup-layout)/map/popup/page.tsx | 1 + apps/fo/app/pages/(map-layout)/map/page.tsx | 1 + apps/sn/app/(map-layout)/map/page.tsx | 1 + apps/wr/app/(map-layout)/map/mainMap/page.tsx | 1 + .../app/(popUp-layout)/mapDrgtPopUp/page.tsx | 1 + apps/wr/app/(popUp-layout)/splyPopup/page.tsx | 1 + .../business_components/src/ui/map/Gis.js | 3 + .../src/ui/map/GisZoomLevel.js | 80 +++++++++++++++++ .../src/ui/map/lib/css/gis.common.css | 86 +++++++++++++++++++ 9 files changed, 175 insertions(+) create mode 100644 packages/common/business_components/src/ui/map/GisZoomLevel.js diff --git a/apps/dm/app/(popup-layout)/map/popup/page.tsx b/apps/dm/app/(popup-layout)/map/popup/page.tsx index ea1e4b174..e410ad2a7 100644 --- a/apps/dm/app/(popup-layout)/map/popup/page.tsx +++ b/apps/dm/app/(popup-layout)/map/popup/page.tsx @@ -235,6 +235,7 @@ const Map = () => { <>
{ return (
{ setIsPlaying={setIsPlaying as any} targetLayerTypes={WATER_DEPTH_LAYER_TYPES as any} checkInterval={2500} + showZoomLevel={true} defaultZoom={7.5} defaultLonLat={[127.75, 36]} diff --git a/apps/wr/app/(map-layout)/map/mainMap/page.tsx b/apps/wr/app/(map-layout)/map/mainMap/page.tsx index 927703ad9..652fe1924 100644 --- a/apps/wr/app/(map-layout)/map/mainMap/page.tsx +++ b/apps/wr/app/(map-layout)/map/mainMap/page.tsx @@ -388,6 +388,7 @@ const Map = () => { return (
{ <>
)} + {showZoomLevel && }
diff --git a/packages/common/business_components/src/ui/map/GisZoomLevel.js b/packages/common/business_components/src/ui/map/GisZoomLevel.js new file mode 100644 index 000000000..2d1f2848f --- /dev/null +++ b/packages/common/business_components/src/ui/map/GisZoomLevel.js @@ -0,0 +1,80 @@ +import React, { useEffect, useState } from 'react'; +import { useGisContext } from './Gis'; + +export default React.memo(function GisZoomLevel() { + const { gisMap } = useGisContext(); + const [zoomInfo, setZoomInfo] = useState({ + zoom: 0, + minZoom: 0, + maxZoom: 0, + }); + + useEffect(() => { + if (!gisMap) return undefined; + + const view = gisMap.getView(); + if (!view) return undefined; + + const updateZoomInfo = () => { + setZoomInfo({ + zoom: view.getZoom() ?? 0, + minZoom: view.getMinZoom?.() ?? 0, + maxZoom: view.getMaxZoom?.() ?? 20, + }); + }; + + updateZoomInfo(); + view.on('change:resolution', updateZoomInfo); + + return () => { + view.un('change:resolution', updateZoomInfo); + }; + }, [gisMap]); + + if (!gisMap) return <>; + + const { zoom, minZoom, maxZoom } = zoomInfo; + const range = Math.max(maxZoom - minZoom, 1); + const normalized = Math.min(Math.max((zoom - minZoom) / range, 0), 1); + const fillHeight = `${normalized * 100}%`; + const thumbBottom = `calc(${fillHeight} - 1px)`; + + const zoomIn = () => { + const view = gisMap.getView(); + if (view.getMaxZoom() > view.getZoom()) { + view.animate({ + zoom: view.getZoom() + 1, + duration: 250, + }); + } + }; + + const zoomOut = () => { + const view = gisMap.getView(); + if (view.getMinZoom() < view.getZoom()) { + view.animate({ + zoom: view.getZoom() - 1, + duration: 250, + }); + } + }; + + return ( +
+
+ +
+
+
+
+
+
+ +
+
+ ); +}); diff --git a/packages/common/business_components/src/ui/map/lib/css/gis.common.css b/packages/common/business_components/src/ui/map/lib/css/gis.common.css index f9b67a07b..7158fdbec 100644 --- a/packages/common/business_components/src/ui/map/lib/css/gis.common.css +++ b/packages/common/business_components/src/ui/map/lib/css/gis.common.css @@ -173,6 +173,92 @@ text-indent: -9999px; } +.zoom-level-control { + position: absolute; + right: 20px; + bottom: 60px; + z-index: 2; +} + +.zoom-level-panel { + overflow: hidden; + width: 40px; + background: #fff; + border: 1px solid #9aa7b8; + border-radius: 3px; + box-shadow: 0px 0px 5px #999; + box-sizing: border-box; +} + +.zoom-level-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + padding: 0; + border: 0; + border-bottom: 1px solid #eeeeee; + background: #fff; + color: #333; + font-size: 26px; + line-height: 1; + cursor: pointer; +} + +.zoom-level-panel .zoom-level-btn:last-child { + border-top: 1px solid #eeeeee; + border-bottom: 0 none; +} + +.zoom-level-btn:hover { + background: #67aee3; + color: #fff; +} + +.zoom-level-gauge { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 128px; + background: #fff; +} + +.zoom-level-track { + position: relative; + width: 12px; + height: 96px; + border-radius: 6px; + background: + repeating-linear-gradient( + to top, + transparent 0, + transparent 8px, + #d9d9d9 8px, + #d9d9d9 9px + ), + linear-gradient(to top, #f5f5f5, #fafafa); +} + +.zoom-level-fill { + position: absolute; + left: 5px; + bottom: 0; + width: 2px; + background: #3b82f6; + border-radius: 999px; +} + +.zoom-level-thumb { + position: absolute; + left: 50%; + width: 22px; + height: 2px; + background: #111; + transform: translateX(-50%); +} + .ol-scale-line { background: rgba(0, 60, 136, 0.3); border-radius: 4px; From 96db2b4ed4525cfbb7f60acfe6e5c8503ed30b47 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 18:07:26 +0900 Subject: [PATCH 16/25] =?UTF-8?q?sn:=20zoom=20level=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/map/GisZoomLevel.js | 37 ++++++++++++++++++- .../src/ui/map/lib/css/gis.common.css | 18 ++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/packages/common/business_components/src/ui/map/GisZoomLevel.js b/packages/common/business_components/src/ui/map/GisZoomLevel.js index 2d1f2848f..34d74f252 100644 --- a/packages/common/business_components/src/ui/map/GisZoomLevel.js +++ b/packages/common/business_components/src/ui/map/GisZoomLevel.js @@ -1,8 +1,9 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useGisContext } from './Gis'; export default React.memo(function GisZoomLevel() { const { gisMap } = useGisContext(); + const trackRef = useRef(null); const [zoomInfo, setZoomInfo] = useState({ zoom: 0, minZoom: 0, @@ -39,6 +40,17 @@ export default React.memo(function GisZoomLevel() { const fillHeight = `${normalized * 100}%`; const thumbBottom = `calc(${fillHeight} - 1px)`; + const updateZoomFromClientY = clientY => { + if (!gisMap || !trackRef.current) return; + + const view = gisMap.getView(); + const rect = trackRef.current.getBoundingClientRect(); + const offsetY = rect.bottom - clientY; + const nextNormalized = Math.min(Math.max(offsetY / rect.height, 0), 1); + const nextZoom = minZoom + nextNormalized * range; + view.setZoom(nextZoom); + }; + const zoomIn = () => { const view = gisMap.getView(); if (view.getMaxZoom() > view.getZoom()) { @@ -59,6 +71,23 @@ export default React.memo(function GisZoomLevel() { } }; + const handleTrackPointerDown = event => { + event.preventDefault(); + updateZoomFromClientY(event.clientY); + + const handlePointerMove = moveEvent => { + updateZoomFromClientY(moveEvent.clientY); + }; + + const handlePointerUp = () => { + window.removeEventListener('pointermove', handlePointerMove); + window.removeEventListener('pointerup', handlePointerUp); + }; + + window.addEventListener('pointermove', handlePointerMove); + window.addEventListener('pointerup', handlePointerUp); + }; + return (
@@ -66,7 +95,11 @@ export default React.memo(function GisZoomLevel() { +
-
+
diff --git a/packages/common/business_components/src/ui/map/lib/css/gis.common.css b/packages/common/business_components/src/ui/map/lib/css/gis.common.css index 7158fdbec..5ce46a912 100644 --- a/packages/common/business_components/src/ui/map/lib/css/gis.common.css +++ b/packages/common/business_components/src/ui/map/lib/css/gis.common.css @@ -195,7 +195,7 @@ align-items: center; justify-content: center; width: 40px; - height: 40px; + height: 30px; padding: 0; border: 0; border-bottom: 1px solid #eeeeee; @@ -230,7 +230,10 @@ width: 12px; height: 96px; border-radius: 6px; + cursor: ns-resize; + touch-action: none; background: + linear-gradient(to top, #b8b8b8, #b8b8b8) center / 4px 100% no-repeat, repeating-linear-gradient( to top, transparent 0, @@ -243,20 +246,25 @@ .zoom-level-fill { position: absolute; - left: 5px; + left: 50%; bottom: 0; - width: 2px; + width: 4px; background: #3b82f6; border-radius: 999px; + transform: translateX(-50%); } .zoom-level-thumb { position: absolute; left: 50%; width: 22px; - height: 2px; - background: #111; + height: 5px; + border: 0.5px solid #111; + border-radius: 2px; + background: #fff; transform: translateX(-50%); + box-sizing: border-box; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18); } .ol-scale-line { From 72f5fdd7a858ba59f43c7361105dbd76a54bcb13 Mon Sep 17 00:00:00 2001 From: dongsilove Date: Wed, 18 Mar 2026 22:50:12 +0900 Subject: [PATCH 17/25] =?UTF-8?q?sn:=20=ED=95=98=EC=88=98=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=EC=8B=9C=EC=84=A4500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../images/map/layericon/RDL_TSCT_PS500.png | Bin 0 -> 1860 bytes .../images/map/layericon/RDL_TSCT_PS500.png | Bin 0 -> 1860 bytes .../images/map/layericon/RDL_TSCT_PS500.png | Bin 0 -> 1860 bytes .../images/map/layericon/RDL_TSCT_PS500.png | Bin 0 -> 1860 bytes .../src/ui/map/lib/gis.layer.js | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 apps/dm/public/images/map/layericon/RDL_TSCT_PS500.png create mode 100644 apps/fo/public/images/map/layericon/RDL_TSCT_PS500.png create mode 100644 apps/sn/public/images/map/layericon/RDL_TSCT_PS500.png create mode 100644 apps/wr/public/images/map/layericon/RDL_TSCT_PS500.png diff --git a/apps/dm/public/images/map/layericon/RDL_TSCT_PS500.png b/apps/dm/public/images/map/layericon/RDL_TSCT_PS500.png new file mode 100644 index 0000000000000000000000000000000000000000..b82e2ff89b8ad38ed088df89ddabe5b8aa5b1c51 GIT binary patch literal 1860 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 Date: Thu, 19 Mar 2026 16:35:16 +0900 Subject: [PATCH 18/25] =?UTF-8?q?sn:=20icon=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../images/map/layericon/RDL_TSCT_PS.png | Bin 1700 -> 956 bytes .../images/map/layericon/RDL_TSCT_PS500.png | Bin 1860 -> 941 bytes .../images/map/layericon/BML_CBAS_PS.png | Bin 919 -> 980 bytes .../images/map/layericon/BML_STMS_PS.png | Bin 810 -> 591 bytes .../images/map/layericon/RDL_ETCT_PS.png | Bin 896 -> 943 bytes .../images/map/layericon/RDL_OCUP_PS.png | Bin 837 -> 935 bytes .../images/map/layericon/RDL_TSCT_PS.png | Bin 923 -> 956 bytes .../images/map/layericon/RDL_TSCT_PS500.png | Bin 1860 -> 941 bytes 8 files changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/sn/public/images/map/layericon/RDL_TSCT_PS.png b/apps/sn/public/images/map/layericon/RDL_TSCT_PS.png index ffc22515996bacdfbece7d30e3d5afcfd20269d2..81ad25a20d6c5dd238c4455caf3e255e4eb18680 100644 GIT binary patch delta 934 zcmV;X16ll}4ZH`CB!3BTNLh0L01FcU01FcV0GgZ_00001b5ch_0Itp)=>Px#1ZP1_ zK>z@;j|==^1poj54s=CWbW?9;ba!ELWdKHLXKi7gv6f>100TEkL_t(|0c}%jNEB@p zKJQ%it6kmw$ZVC}N=-_PHj1tgNzspjt>_{~H=@w!#}-b#2{CzQ%O6``@#P_*3>4^w3II?&snr`jS$)-0dD=Uv-OtQJTS^Ed6 zzP_GQRrT7%mVb|Q?%Lb5a77C(TG@hUKsWZ$bFXP^IMv_U+Pb*Byxj6TuH09{k4rl#Mwg~^!xuNU-m2ugjy=zRaaMUC@3iS%2ZWVv4oJh zogex^$C5QohS1aFuyno)rY(rT>eW8jv*roWRfQV=<8cXwB(;cP7-uXN;~AUH#_77w zO2ZQNEPn%4Q^Yk{1W@~a%4G3CX+adhWuloN3KhiUM3!Z<1wr5$)EUz0wBT}1Fo**L zp-m5p;oGOPK;y?j7q`HLTOPBzpCB^0rc4m90xmZ<7nr=fJbiF*@Kwb+57Ea`CP;6T zr|WBG!;YF4P`rLQ+<%^rttmipSFH6IAOl$Sh<_~0DuZRH4Gj%9c9t(1bm!TOOr~t# z26(vl%t^5`tV%JmL)Juq1C=Y%fk5Cc0z{F-4BOq^O-o8jRC~5f*uQtvs^G(yTs%HP zkPM*Il#d!R8tmV_ei$Ns?}Ke^Z2`3Tr^d#{wCRJct}fN#aEQsoaNqe;hn5sg&$a5h zN`IX>S!7P>RI<^#7|xv7m1u8!bTb$X`Z{Yl53k&C= z<0j#3jD^GDFQHKA4W;xAhIYE$ZUN)fe})M?&Z4Z@JkL+TU?*mBXqq`U31nSFwFX8< zM-zVz6M=Ci6oCwX@K&pp!?7kv*ccL~)*sc?X=pklhW-lv0gZUWtV$F?r~m)}07*qo IM6N<$f>da~{Qv*} literal 1700 zcmaJ?c~BE~7!4kP+-gKctlNlFwUP@GASK~Qf}|xDLd58lYK{#FklmPF$N^e~ieg(~ zP;3W+CNHncK3J8d++=o7*be86k9Pwol1?dak#)BomwnS08u~!#wj5t!CX~C0F*K&VFQg% z=BwGDLK$w*fYF9^La8A^8XzMCv4B7w0~1hzs2I?x5+Q`4V-m)78Q9#qO(Fo}5Hx{F zc$buj9|^Ew4G7SPKHgF?g#ys&M2atsPN%E^sALM2M8_6zk3poCKWLTQs+ z4lGSlfe<>$l}&N|$kTGIR#2(2$Q)3kOa^6P8dwF4m&{O3p9^PNy$P;t+Fa<|X}KgU z8IrZJ|7!H)7Umx7bjr5aV#@d+gt=XV*_sLU$g!_w5swoh)IA6k#40}H;>T{9-nPDk z^6DR$io9uMF|)VLSzRp(NnBP0h`4K5_Pf4Ugq%pTXYFw)v!8uZqzHa|>VEJxvg_3k z(!a@kRhYK^PUP*JqRj7F^KbNCPBDAlGQ}?S_d(=0hw{zMi<=fo@XMQ5@4480GKa-) z!5{Iz5`(*I^ILMAc4vf*?d>gwjc$BLBt_x5qj1%tr2Dp8Z`%pFzi{hz4|jL6Dah6f zU#=(vo4VJoxw@jFYa``~c!^i=^PN?v3XJm_n}*@k_Xm$$ADnl>h|7s+`lPnUE~mAr zzO42M`Im5|sj6h)_P4V%wAK z(6BYJ@`tl$+)VagHk{*?_zxW4Z7y)kZQ{XpiVJv;!?JSQr!Ivp$zUHFvYqP~QZvf~ zZ;9^EuN`VVACaXZ8m^axX{*w68ok<&8Oisd&Xoa1wbAv_>?H>qf+RunJHL8WwD)Oq zuF;+KI;?$XiqEC~cxQcV+nKDqit>1M*RV_Aa3fA$dO_Xx!lhoa(423YQ*)Xn>`QV{ znIxA6tLr-tIhFa$y0cr|J44(j$w;Wt?HLl5Sw3pZMVuqPxOeSplxsB_|E#;iZMb2y zAHEdn{b(>VGu!fdW@`WS%YmY(I%9LkdtC+fmK)t#{Mi2abALpnZ|-e)t$Ul_8+edd zpOC)3E;r{%-KWy7Itt4oEVkeNsu9=ULaC>*~S)^ X+MJ>?k7n6e{~J8+I!100SsVL_t(|0gY2jNK{c6{?EO4bewT!oNRPLBd3Sin}RYdGDDO=$w1xI zqD4q#Mi9{^$YtR&(3V*nO|wO41d@a=$Z=2xrtmdBMjaeR=i$t~<30DD{(H@E;i3bF z^ZNe(eCPXrzXPy$<0MHs5{*VL1_FV?rlzKJZ4dsVaiS>Rmy+saXjNqk(<)n8P+4?? zE=D4emb$t+8+Lwoz`sRvbFsV zudi2h27bT)czDIq-q)FcqbCiJg}}vGnaHvNR91mf1?MVk##9h^KKp7}VWOj>!#zGe zzNHDn<>lo)_PQmIL<--!<1E7jaI9t(7-aA~ZwUs21_A2~sA|xN zwAaHFFb5lRSCZ3bUPJc5B~ap>Fg)6*Gusw_oiL+05#%^da5x+wIGs*)ZEekcw%C5_ zYj;@3h@ykFwLK*VoYOGpe+yE|g1b~N*QIM#l9VDV$U24>Qx0j+mX?;z;_JpWvjtGd zEusk)Ty=oQQ^Fz}Mv#&ek{Sb|z>R84s;8&t3no}DC@9$C(GaYtsEC>~(}T5lE|mX& z9E=IEh)lHd$yC)wMsZ9_C-D503w})x_YDmV^`OnCT3cIFx(~cwFSXfhp^eDu!n2oU zmvfvMCJbVkR*oEW8A)-e4emY3j(`90`BQIi??d%Iy{oHBCA+Mg77B$9;JZ$t z%gS9Y*Lkbex)1+`?D2SJMn*;^5jKHcj`X4rf{3TPt*kfgquA~COa$d>9dEKJif;Kh zsvg4RD~UuRjyEeiF=US)NiY$I{xFzKCIKBsP%wFZex42t3@C)?A#4Zy2b~$TTIfUh QcK`qY07*qoM6N<$f*PTm?f?J) literal 1860 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 FV1gV5{q+C< delta 788 zcmV+v1MB?H1gZv*BYy(%Nkl@$ikLaoY&Kus+}wP9d3hP0pPx%9FMe3dwY97RIAl+U|>M@58QXd%(3gbVsUXXEEbDD647%2 zB$$~z&!f@N(MJml3%||G%qU|_{QgZuh@vR=eP1juFT2HJag~Uk_kzWWh?tpaV`D=M z4-Y?f9Dk=JgxEYdIA9{;APAU<#LCJ_yHF^6OGIxgm5R#e^C19;-V_FaQmLedhK7D! zT3Y&Lc6OGGF_cUu#p>#6qfjU;6VcnPtu39;=cE6Pvk;=6%!k|C+h%8H=Wk}7?5}fQ zR4SE(<2Y8U)%pm)$5P56t@S5|hlgf;ef^P0Q?rwT| z+M~6#HOu$?bQDD+%$(I)XW}?cODQw0R*SUODw#|MVHny{%9|*PY$CdnQvNeCGGbG2 zci}jWPTUu)k0G&=J5JLDt5SYQi!EU$PHRI#s{^sUp{4d9PpR{5; S2Mx6V0000Q4hTEp6@*G04)D-b8~YWXJ%&hg+igt zZnxX0pDhO@iwl#AR__8+DO;0F2=m z!u0PtfZ+kb)RDFW?r-?fQ(j(vyr7^UR9sxF@_O~);NX@H@Kiq!-Ue0WFbHTGM^uHR z-t}C;d{PpC=V|uoU032YH8rhmZEcc1fRiNY+1!81--_zUM>z$pQ6;OOEr31g;ub9ndAu2?JkIz3okZ*RHPz!7-4#aA7kV3~P zcz?L>ezf^x^V`P8#yY$KUtwY4Bo5ce0x7Q$1R)m*-G(YV=5#uDXJ%$*p*Lio&)4Vm zdjBA-gE8jM%gYNRURh!$)HrXkSTYc_Mh~21R@IbmqR6^{%}3(#cyyte2rT1JY{a2H w3?`F_qDPQSO%4PCN>fvlN>c6s_8A51{Qv*} delta 874 zcmV-w1C{)*2Y?5VBYy)&NklK7=_P&?@ex!Cb6k8%U0JFmZ}x(=At;Z zhq(C?nHyowhz<*T2|_^_+mJG7Ko~`bLx!++WwL=VsAG&FExNT6+p^(I5v^veuB~ZJ zG+mS2rb+L;x%d8iSVh#G$HV`f!~bxARWUPxK>%P!9hf=98h^jSDsSRmwmo+Dq#l|Q zWN1e9(D~x$Bd4SSM%|^2Z@LQkOTmi^8@>GJS84&X*b&HH;YSp89&Yc zhN0XQ+V06Upeg@+q(yev+;9rO@9Ii_tfdF|5QqFdF#nXxBqc?%UPD$DEv3|s+9GWl5m^KP{r&x7JRTQMA3gnQ zeXOBtxHJ-(R%azoorqFZN0V(mBHq_076-+1JDQ{2%sSvjml3l zPfzo|AR(1XiDUUO;m++lXlQFNkG*-!V1ByvU-_e+CpFW^EdT%j07*qoM6N<$f@k-o ACIA2c diff --git a/apps/wr/public/images/map/layericon/RDL_OCUP_PS.png b/apps/wr/public/images/map/layericon/RDL_OCUP_PS.png index aeae3e26680a9415a77f0d9b310eb18b3e5f6c58..f3ff30b853ae39590616e91213d3b802e2621514 100644 GIT binary patch delta 914 zcmV;D18w}p2B!y*BYyx1a7bBm000XU000XU0RWnu7ytkO0drDELIAGL9O(c600d`2 zO+f$vv5yPw5ljbYtQ%>HD5CNuXQ&+H-u@xcR!VP?K_?svZX9pKd= zOQljrCX@Mid3pJrfq{W--Z#8P$YQa0P;acy(b6o@+$ExWQBtW#kJ9P%KRrD?Ax`6! zm4kzWrt7*Vb$={E`mY0|{`{QuU^#U;M-P+QSbsb=HnxYG_+HeBEtC&iH%|RRSB_PF zd>I6i3bI)F`r^4u)*42EHB@96qEKRi4xtv>p)e^qokq6PouT9^($uF#A6HD*Vkt-yWRT10w^FL!!_lx)OZehvQQbP&Vcz{ zJ(vfO&LUXMzHOT38*6K8mKh8NO|7+o^(^6if2BBHf;*ZiOJuqla_2UP77JpxANqQp z%yg=XM}MhFBodb7dxmY>3DhbvK5@u>u~-{5*1j-9Tv#e$kj9^q?Bf3 zV^mUVHr*9woh=j!uF=-k zhS}NKm9B$7e@j=!gYLDb@bxqZ@=Ia7TLt6OYJZq}tKm-Np>DFsza6rVpFMXpl}b%= z?W!?9KTn;VovyFCCeiuBkNfr5Rnxh+BIxlZ^xYEFT;zK6+{nnt z8GpWkneOiHXOT!mi!E06F|8de=zHw4{q61TAJo>?Ht=pZGcz;yW3kvA!)~**arQxi z@$ObDm&03>`uh561~qxfCxw(!-me_1p5o>!`FuXdC##otVQUC(B-tNUAP_Lwae@_h omX?;>iHQm2t%SE6FTl?MHesG0MAVTp01E&B07*qoM6N<$g0#cDKL7v# delta 815 zcmV+~1JL}Z2gL@EBYy)7NklrH6t=wcT|8WdD?9q2*`293yzvFajvAvhRF7aLP*qs7|9(uF2la}H0j>B^&> z7d_|y@^rB|g#27Se7|3KzRv@9QB_e804$Fc)kh1eyKbvK)_@<@2kHO>}>n$n=N%GUJ+Tnrw43R75e%_RZVd9;wSddd#`fk z5|mcaFvPf40@rP}Zd_`9x#^|n>QoPdEUtx!sv0p?OlJ+4O9S(h(wD~*eK@*-wrO1g#;k5PuH;OL#U9jvx=aSe+>p%dn6W zZ}H|1+V-a8=+Qgp(IBj1xdPkcu-PX1sX#Ee1PO!Q4ls>XnB8&AFDo#dC-g%%Zs(j5 zhyf_O$?Moj)m#N42u>{%`H^Zl!XH|qGO&Q&3gCXD;AuHloh^O-S*3TagZYNWVd@(s zyzsZ`Tz`Oh!b2AW(Lx9@P+uVw{LviLZk4$$b?5kfxbVWslOn1rM{W@x82|QM&A_pi zVxr{7y0_a34>@knb6QCR%7?2o_I-#^CG)IaHT+FvvO4^@>X!2xU_26#XmNIU?Eo}M0O tLnz}$L8@v`W-@N3x7SrwgUE*3{{XBoeqw|U;4}aL002ovPDHLkV1mMAlj8sY diff --git a/apps/wr/public/images/map/layericon/RDL_TSCT_PS.png b/apps/wr/public/images/map/layericon/RDL_TSCT_PS.png index 3776f6c0493ee2fb6717ff03adecb0f228bf8673..81ad25a20d6c5dd238c4455caf3e255e4eb18680 100644 GIT binary patch delta 935 zcmV;Y16cf<2fPQ6BYyx1a7bBm000XU000XU0RWnu7ytkO0drDELIAGL9O(c600d`2 zO+f$vv5yPSy}sN6`)?x?vdgVXAcyUxz8GxK(4qKNW^civ&{$dnGnITEi z!bl`C)93U3XM7tkkoQv~WcWEn3-vXFxah(Q~h9Y&g~5+SmT;FA9>Y(MzOT~=0h)o!=v`~7~_xM)6ldU|F(elc`q zXU%=syrvjRXE>le+)t=J22@v#ZN7`KB(NNtvu)F|(SN3mW+q(bG zzV_Eq07~e|BP)q}QYW}Ahu~eW3+gX>Y4rR5CSUd}3xrxK-c?suZzw1z_{vmORk4JS zxt$;SLC2CcO@`3ZS|Ko89h9tF!VHjsD7ULP4&Bp1v z&Pu})_J1q`Ra3+@Sp-n~e#&I=Kxsh~!DXVEAPN=49pW-PB4fA z1ffk2is9R*vq0m=K^M2cgdIuFsuQYJ`m zl&9-!X2Xt}7f`%@IoyAqkF6;{aaXMM7$5^!^?!&g%PNCqs0|GbH+GgU8g%E`j7+9% z-v)TN_smJLGptH6vP0HHfCH5)(t$wWE&@c6#0=Zr-AzkMN>qEcP1wJ8)2iUZms~tP zLXZrg)Rd1JG8*jPy?z)XeeZ*9ZEXRx`KQLl#*=~S}OyBN-#*p+B+dvr4x4Ei~a3wyoZA+)qk{;;w|6vceB^Xyf)3JVM8 zq2nguY>b7&;V+?3=nbXx4Tg5Q-EINn)qjQwJrXbeU)oExtBZmG8{sE16!>mdaL8t%#002ov JPDHLkV1gW0zwQ74 delta 901 zcmV;01A6?t2b%|wBYy*8Nkl0Hs^2dQXj!PgXLQTF8~RVIGYfiSCxE$GAsKdi`F)Y+}`F$a5KX&|m$TbI_R zY5K_H-rU^W`}2d{gnB+6&iNhA4-R1!%uGZ8KrA}}wZQcN%6|b}1DxYTRQyjze9K2` zNmbR`zWgrHaW%GhpQ>3t*-7fX0eAe#eO0IG>t;?8ZOOv5t+yoOti>*laKx4u@F~kySGFrqgHt zdTsABUzpn(e4^*w7AccSli)e1szI7&NEKzKZDM?)^zHYl{Z(6DdTzA>2>|$UWb)~& zV@b&djSsbdE&LVb82Y>c=TG!f?>i?^;hu+@*Wq;;bbsmE6pxNut<86%JQRxldth>A zdHd{K3T3iEODlxI)30FX4j(o({ffsAx8lfC1IXkUlF(@>y+D7b3R`yW+ID9&8e%~J zjH2!~^c>8R3d^#%#y<(*9P*|IzysJ+xd_uxiA@cLk%ws&?OM?#0}z4%cw9W~b%Qlc zh1;H{zJH+y5x;l}9@u{ZH?bO-Dr3ti8{?PT`YjrpH1#*EuP*cx#Cw6%U6WmYom zwC6FIkomx?yU^Np1CPGgjFD^A@Hn!_X0lwn(MNty{_@1le5R+T2ZEXD+=bquLyy&s zuJ^lbD@)6U$C;W#lPzN?8;0sdm|VOCS$SK zG5`x}p(u&~AOr9N*bJZ^Km&j}02^9bT3l;Aw3b+1rwB)*HjIslsi`Rh0)bL@cXx@I b|EK*2JXN2b100SsVL_t(|0gY2jNK{c6{?EO4bewT!oNRPLBd3Sin}RYdGDDO=$w1xI zqD4q#Mi9{^$YtR&(3V*nO|wO41d@a=$Z=2xrtmdBMjaeR=i$t~<30DD{(H@E;i3bF z^ZNe(eCPXrzXPy$<0MHs5{*VL1_FV?rlzKJZ4dsVaiS>Rmy+saXjNqk(<)n8P+4?? zE=D4emb$t+8+Lwoz`sRvbFsV zudi2h27bT)czDIq-q)FcqbCiJg}}vGnaHvNR91mf1?MVk##9h^KKp7}VWOj>!#zGe zzNHDn<>lo)_PQmIL<--!<1E7jaI9t(7-aA~ZwUs21_A2~sA|xN zwAaHFFb5lRSCZ3bUPJc5B~ap>Fg)6*Gusw_oiL+05#%^da5x+wIGs*)ZEekcw%C5_ zYj;@3h@ykFwLK*VoYOGpe+yE|g1b~N*QIM#l9VDV$U24>Qx0j+mX?;z;_JpWvjtGd zEusk)Ty=oQQ^Fz}Mv#&ek{Sb|z>R84s;8&t3no}DC@9$C(GaYtsEC>~(}T5lE|mX& z9E=IEh)lHd$yC)wMsZ9_C-D503w})x_YDmV^`OnCT3cIFx(~cwFSXfhp^eDu!n2oU zmvfvMCJbVkR*oEW8A)-e4emY3j(`90`BQIi??d%Iy{oHBCA+Mg77B$9;JZ$t z%gS9Y*Lkbex)1+`?D2SJMn*;^5jKHcj`X4rf{3TPt*kfgquA~COa$d>9dEKJif;Kh zsvg4RD~UuRjyEeiF=US)NiY$I{xFzKCIKBsP%wFZex42t3@C)?A#4Zy2b~$TTIfUh QcK`qY07*qoM6N<$f*PTm?f?J) literal 1860 zcmaJ?2~ZPf6kd?Faw#G*sEn@B(V`|HAqlYNfE)-Nf(VhLR&+@g2#{>ZE)p2R(2g=P zg5ZHwkRny72RDPLpwwa;FDPI^!B7NLWKh6^A_{3YfV5LfcXs#x-`nqf@BQ!l|JihZ zzs=Sb%Par@u=ep51`wl-@tOZA@m~4*PnZ}?uz<~cptQ+xfH2G=J;j~?P?2Rh0e?c+ z<|^+{3;-517#|ZIdR9g_m*S!jJP?h*6JRw0c*@Xl1oTnBkw^dn%M#;mA#4DccUCS5 z!9&EpkQ7x=U?Ya2QK*P$0ATYpDp(qW;9xisDOYkx!?pD!P%h(;f|+7xu}XkM$-R@* zNMMqmM4A*Mb(fKNTx$!q1|k>~2o8f9MXVBoG#t_tF+|LbZYl|!g5WV6(sWfJVt-J8 zsu7S$aUn~cX*7_vIr&=L!p{wR$?>FBHBjPz$z+@;%r>k2cTH||4@Zu7LDNn$loRZCov{T zR3X#=1ViK1QbN9n)y7mRNT5bw992tDH1VWkxD5pqZb14S;ELGA)3oiAc}F&F|*8coD-iZA9r@jAj&d7<&Bj(V@_+?soF55VVwy5PqgJ9zh;?mgEk9;5Jo%Rshm#BbE zojp26YxejdN*QNe!a5!|qA^Kh`v^Hd}6?bRggAUQrJG))b+yYpk7DKhpY` z12}dK0nYRiTFk_E*$bPF0A?N|fx4ro-LucRUf{%~eG%$cvMiokIM}zualvx?Q+v&- zI;+DHcNvPzymRLr-&eSZ#sCPER}oWRmzh^%VsoBx)1LM+$_s59 zwt;h{T`1Y#o4CTS`gZFfpOm=WtF+0lGB4TNJ!z`H_W0uB+`6aZZMEV2q{^$?3TuAI zd~u6%addZiweIAd=Jdf*yB09bo^k)7^0h|}g}>+RwJnO0v_3bt1A>yEhOzrv5Mc2Q z);2c9i7g%$IZu9~2bUV|UdFoP3=>(tVOROAn$#l}^G#PxKH{a8+qaFKUdwROZY^cN z9kv%XmdAdL2s#!?PVBQ;vdxmb1GQQ}QAS&y`hDOq`P@2_cm16WJT=l2O7!HgoiTT===BZI^uh)zw91~T6Mj2;V%Q-JzF2R0I7x-b~Q&$(-wAl zUZMUxxw!sS%dv*`q51h`W%q9$PS0=HaCyDKvM-r4)Ka21|FMgAH?DVa)}X7TRqF(V zCF@Aq>k$vv<~)}iY%Pen`CPI{8=F=ak) zZ|{Gn-R=-1=4zvRD;+D*<14drac>9nt@VVvYG1F|wa8 Date: Fri, 20 Mar 2026 09:41:07 +0900 Subject: [PATCH 19/25] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=AC=B8=EA=B5=AC=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cm/src/pages/auth/login/ui/login-page.tsx | 6 +++--- apps/st/src/pages/auth/login/ui/login-page.tsx | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/cm/src/pages/auth/login/ui/login-page.tsx b/apps/cm/src/pages/auth/login/ui/login-page.tsx index fed7be4ad..297d28a8f 100644 --- a/apps/cm/src/pages/auth/login/ui/login-page.tsx +++ b/apps/cm/src/pages/auth/login/ui/login-page.tsx @@ -145,11 +145,11 @@ function LoginPage() {

- 유역하수도 통합플랫폼 + 유역하수도통합플랫폼
- 통합관리시스템 + 하수도 포탈

-

유역하수도 통합플랫폼에 오신 것을 환영합니다.

+

유역하수도통합플랫폼 하수도 포탈에 오신 것을 환영합니다.

logo diff --git a/apps/st/src/pages/auth/login/ui/login-page.tsx b/apps/st/src/pages/auth/login/ui/login-page.tsx index 5ce6c9cb6..8d2b3300a 100644 --- a/apps/st/src/pages/auth/login/ui/login-page.tsx +++ b/apps/st/src/pages/auth/login/ui/login-page.tsx @@ -22,11 +22,11 @@ function LoginPage() {

- 하수도정보시스템 + 유역하수도통합플랫폼
- CMS 통합관리시스템 + 하수도통계 관리시스템

-

하수도정보시스템 CMS 통합관리시스템에 오신 것을 환영합니다.

+

유역하수도통합플랫폼 하수도통계 관리시스템에 오신 것을 환영합니다.

logo From 5e56999c6846b6e947f42f018f47154b422eb674 Mon Sep 17 00:00:00 2001 From: bicochan Date: Fri, 20 Mar 2026 10:50:29 +0900 Subject: [PATCH 20/25] =?UTF-8?q?[st]=20fix:=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entities/statistics/api/statistics-analysis-detail-api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/st/src/entities/statistics/api/statistics-analysis-detail-api.ts b/apps/st/src/entities/statistics/api/statistics-analysis-detail-api.ts index 4e7a6e476..957680ec2 100644 --- a/apps/st/src/entities/statistics/api/statistics-analysis-detail-api.ts +++ b/apps/st/src/entities/statistics/api/statistics-analysis-detail-api.ts @@ -5,7 +5,7 @@ import type { StAnlsDtlListApiResponse, StAnlsDtlResponse, StAnlsDtlSearchParams, -} from "../model/statistics-analysis-detail-interface"; +} from "../model/statistics-analysis/statistics-analysis-detail-interface"; export class StAnlsDtlApiService { public async getDetailList( From 4e404abad38cae481a70058a96027eaef07770c5 Mon Sep 17 00:00:00 2001 From: bicochan Date: Fri, 20 Mar 2026 11:09:21 +0900 Subject: [PATCH 21/25] =?UTF-8?q?AGENT.md=20=EB=AC=B8=EC=84=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 1da991844..000000000 --- a/AGENTS.md +++ /dev/null @@ -1 +0,0 @@ -[Next.js Docs Index]|root: ./.next-docs|STOP. What you remember about Next.js is WRONG for this project. Always search docs and read before any task.|01-app/01-getting-started:{01-installation.mdx,02-project-structure.mdx,03-layouts-and-pages.mdx,04-images-and-fonts.mdx,05-css.mdx,06-fetching-data.mdx,07-updating-data.mdx,08-error-handling.mdx,10-metadata-and-og-images.mdx,12-upgrading.mdx}|01-app/03-building-your-application/01-routing:{03-layouts-and-templates.mdx,04-linking-and-navigating.mdx,05-error-handling.mdx,06-loading-ui-and-streaming.mdx,07-redirecting.mdx,08-route-groups.mdx,10-dynamic-routes.mdx,11-parallel-routes.mdx,12-intercepting-routes.mdx,13-route-handlers.mdx,14-middleware.mdx,15-internationalization.mdx}|01-app/03-building-your-application/02-data-fetching:{01-fetching.mdx,03-server-actions-and-mutations.mdx,04-incremental-static-regeneration.mdx}|01-app/03-building-your-application/03-rendering:{01-server-components.mdx,02-client-components.mdx,03-composition-patterns.mdx,04-partial-prerendering.mdx,05-edge-and-nodejs-runtimes.mdx}|01-app/03-building-your-application/05-styling:{01-css.mdx,02-tailwind-css.mdx,03-sass.mdx,04-css-in-js.mdx}|01-app/03-building-your-application/06-optimizing:{01-images.mdx,02-videos.mdx,03-fonts.mdx,04-metadata.mdx,05-scripts.mdx,06-package-bundling.mdx,07-lazy-loading.mdx,08-analytics.mdx,09-instrumentation.mdx,10-open-telemetry.mdx,11-static-assets.mdx,12-third-party-libraries.mdx,13-memory-usage.mdx,14-local-development.mdx}|01-app/03-building-your-application/07-configuring:{03-environment-variables.mdx,05-mdx.mdx,06-src-directory.mdx,10-custom-server.mdx,11-draft-mode.mdx,15-content-security-policy.mdx,16-debugging.mdx,16-progressive-web-apps.mdx}|01-app/03-building-your-application/08-testing:{01-vitest.mdx,02-jest.mdx,03-playwright.mdx,04-cypress.mdx}|01-app/03-building-your-application/10-deploying:{01-production-checklist.mdx,02-static-exports.mdx,03-multi-zones.mdx}|01-app/03-building-your-application/11-upgrading:{01-codemods.mdx,02-canary.mdx,03-version-15.mdx,04-version-14.mdx,05-app-router-migration.mdx,06-from-create-react-app.mdx,07-from-vite.mdx,08-single-page-applications.mdx}|01-app/05-api-reference:{07-edge.mdx,08-turbopack.mdx}|01-app/05-api-reference/01-directives:{use-cache.mdx,use-client.mdx,use-server.mdx}|01-app/05-api-reference/02-components:{font.mdx,form.mdx,image.mdx,link.mdx,script.mdx}|01-app/05-api-reference/03-file-conventions/01-metadata:{app-icons.mdx,manifest.mdx,opengraph-image.mdx,robots.mdx,sitemap.mdx}|01-app/05-api-reference/03-file-conventions:{default.mdx,error.mdx,forbidden.mdx,instrumentation-client.mdx,instrumentation.mdx,layout.mdx,loading.mdx,mdx-components.mdx,middleware.mdx,not-found.mdx,page.mdx,route-segment-config.mdx,route.mdx,template.mdx,unauthorized.mdx}|01-app/05-api-reference/04-functions:{after.mdx,cacheLife.mdx,cacheTag.mdx,connection.mdx,cookies.mdx,draft-mode.mdx,fetch.mdx,forbidden.mdx,generate-image-metadata.mdx,generate-metadata.mdx,generate-sitemaps.mdx,generate-static-params.mdx,generate-viewport.mdx,headers.mdx,image-response.mdx,next-request.mdx,next-response.mdx,not-found.mdx,permanentRedirect.mdx,redirect.mdx,revalidatePath.mdx,revalidateTag.mdx,unauthorized.mdx,unstable_cache.mdx,unstable_noStore.mdx,unstable_rethrow.mdx,use-link-status.mdx,use-params.mdx,use-pathname.mdx,use-report-web-vitals.mdx,use-router.mdx,use-search-params.mdx,use-selected-layout-segment.mdx,use-selected-layout-segments.mdx,userAgent.mdx}|01-app/05-api-reference/05-config/01-next-config-js:{allowedDevOrigins.mdx,appDir.mdx,assetPrefix.mdx,authInterrupts.mdx,basePath.mdx,cacheLife.mdx,compress.mdx,crossOrigin.mdx,cssChunking.mdx,devIndicators.mdx,distDir.mdx,dynamicIO.mdx,env.mdx,eslint.mdx,expireTime.mdx,exportPathMap.mdx,generateBuildId.mdx,generateEtags.mdx,headers.mdx,htmlLimitedBots.mdx,httpAgentOptions.mdx,images.mdx,incrementalCacheHandlerPath.mdx,inlineCss.mdx,logging.mdx,mdxRs.mdx,onDemandEntries.mdx,optimizePackageImports.mdx,output.mdx,pageExtensions.mdx,poweredByHeader.mdx,ppr.mdx,productionBrowserSourceMaps.mdx,reactCompiler.mdx,reactMaxHeadersLength.mdx,reactStrictMode.mdx,redirects.mdx,rewrites.mdx,sassOptions.mdx,serverActions.mdx,serverComponentsHmrCache.mdx,serverExternalPackages.mdx,staleTimes.mdx,staticGeneration.mdx,trailingSlash.mdx,transpilePackages.mdx,turbopack.mdx,typedRoutes.mdx,typescript.mdx,urlImports.mdx,useCache.mdx,useLightningcss.mdx,viewTransition.mdx,webVitalsAttribution.mdx,webpack.mdx}|01-app/05-api-reference/05-config:{02-typescript.mdx,03-eslint.mdx}|01-app/05-api-reference/06-cli:{create-next-app.mdx,next.mdx}|02-pages/01-getting-started:{01-installation.mdx,02-project-structure.mdx}|02-pages/02-building-your-application/01-routing:{01-pages-and-layouts.mdx,02-dynamic-routes.mdx,03-linking-and-navigating.mdx,04-redirecting.mdx,05-custom-app.mdx,06-custom-document.mdx,07-api-routes.mdx,08-custom-error.mdx,10-internationalization.mdx,11-middleware.mdx}|02-pages/02-building-your-application/02-rendering:{01-server-side-rendering.mdx,02-static-site-generation.mdx,04-automatic-static-optimization.mdx,05-client-side-rendering.mdx,06-edge-and-nodejs-runtimes.mdx}|02-pages/02-building-your-application/03-data-fetching:{01-get-static-props.mdx,02-get-static-paths.mdx,03-forms-and-mutations.mdx,03-get-server-side-props.mdx,04-incremental-static-regeneration.mdx,05-client-side.mdx}|02-pages/02-building-your-application/04-styling:{01-css.mdx,02-tailwind-css.mdx,03-css-in-js.mdx,04-sass.mdx}|02-pages/02-building-your-application/05-optimizing:{01-images.mdx,02-fonts.mdx,03-scripts.mdx,05-static-assets.mdx,06-package-bundling.mdx,07-analytics.mdx,08-lazy-loading.mdx,09-instrumentation.mdx,10-open-telemetry.mdx,11-third-party-libraries.mdx}|02-pages/02-building-your-application/06-configuring:{03-environment-variables.mdx,05-src-directory.mdx,06-mdx.mdx,07-amp.mdx,08-babel.mdx,09-post-css.mdx,10-custom-server.mdx,11-draft-mode.mdx,12-error-handling.mdx,13-preview-mode.mdx,14-content-security-policy.mdx,16-debugging.mdx}|02-pages/02-building-your-application/07-testing:{01-vitest.mdx,02-jest.mdx,03-playwright.mdx,04-cypress.mdx}|02-pages/02-building-your-application/09-deploying:{01-production-checklist.mdx,02-static-exports.mdx,03-multi-zones.mdx,04-ci-build-caching.mdx}|02-pages/02-building-your-application/10-upgrading:{01-codemods.mdx,02-app-router-migration.mdx,03-from-vite.mdx,04-from-create-react-app.mdx,05-version-14.mdx,06-version-13.mdx,07-version-12.mdx,08-version-11.mdx,09-version-10.mdx,10-version-9.mdx}|02-pages/03-api-reference:{06-edge.mdx,08-turbopack.mdx}|02-pages/03-api-reference/01-components:{font.mdx,form.mdx,head.mdx,image-legacy.mdx,image.mdx,link.mdx,script.mdx}|02-pages/03-api-reference/02-file-conventions:{instrumentation.mdx}|02-pages/03-api-reference/03-functions:{get-initial-props.mdx,get-server-side-props.mdx,get-static-paths.mdx,get-static-props.mdx,next-request.mdx,next-response.mdx,use-amp.mdx,use-report-web-vitals.mdx,use-router.mdx,userAgent.mdx}|02-pages/03-api-reference/04-config/01-next-config-js:{allowedDevOrigins.mdx,assetPrefix.mdx,basePath.mdx,bundlePagesRouterDependencies.mdx,compress.mdx,crossOrigin.mdx,devIndicators.mdx,distDir.mdx,env.mdx,eslint.mdx,exportPathMap.mdx,generateBuildId.mdx,generateEtags.mdx,headers.mdx,httpAgentOptions.mdx,images.mdx,onDemandEntries.mdx,optimizePackageImports.mdx,output.mdx,pageExtensions.mdx,poweredByHeader.mdx,productionBrowserSourceMaps.mdx,reactStrictMode.mdx,redirects.mdx,rewrites.mdx,runtime-configuration.mdx,serverExternalPackages.mdx,trailingSlash.mdx,transpilePackages.mdx,turbo.mdx,typescript.mdx,urlImports.mdx,useLightningcss.mdx,webVitalsAttribution.mdx,webpack.mdx}|02-pages/03-api-reference/04-config:{01-typescript.mdx,02-eslint.mdx}|02-pages/03-api-reference/05-cli:{create-next-app.mdx,next.mdx}|03-architecture:{accessibility.mdx,fast-refresh.mdx,nextjs-compiler.mdx,supported-browsers.mdx}|04-community:{01-contribution-guide.mdx} From 964268090982029689bbfff50e656a878aaff447 Mon Sep 17 00:00:00 2001 From: ljpark Date: Fri, 20 Mar 2026 14:47:21 +0900 Subject: [PATCH 22/25] =?UTF-8?q?wr:=20=EC=9E=A0=EC=9E=AC=EC=88=98?= =?UTF-8?q?=EC=9A=94=EC=B2=98=20=EC=B6=94=EA=B0=80=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/store/matDmd/ldrmntCoSttn/index.tsx | 12 +++-- .../coReg/coRegExcel/coRegExcelModal.tsx | 48 +++++++++++++++---- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx b/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx index 8de791c89..45c6c5773 100644 --- a/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx +++ b/apps/wr/app/store/matDmd/ldrmntCoSttn/index.tsx @@ -114,10 +114,11 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = ( }); }, ldrmntRegData: async (data) => { - await deleteFectch( - `/reuseFc/request/temp`, - ); - console.log("deleteFectch", deleteFectch) + // 잠재수요처 - 삭제 주석 처리 + // await deleteFectch( + // `/reuseFc/request/temp`, + // ); + // console.log("deleteFectch", deleteFectch) const response = await postFectch( "/reuseFc/request/temp", @@ -125,7 +126,8 @@ export const ldrmntActionsExport: (set: any) => ldrmntActions = ( fetchType.WR ); - console.log('response ', response) + console.log('response ', response); + return response; }, ldrmntSearch: async (isExcel: boolean, page: number, total: string, sggCd: string, coNm: string) => { diff --git a/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx b/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx index 1e51fb11c..bc625ec78 100644 --- a/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx +++ b/apps/wr/components/ui/modal/coReg/coRegExcel/coRegExcelModal.tsx @@ -10,18 +10,20 @@ import { useState } from "react"; import { useForm } from "react-hook-form"; import toast from "react-hot-toast"; import type { z } from "zod"; +import { useConfirm } from "@frontend-opensource/use-react-hooks"; export default function CoRegExcel({ isModal, }: { isModal: (open: boolean) => void; }) { + const { confirm } = useConfirm(); const { ldrmnt, loadingOpen } = useWrStore((state) => state); const { isLoading } = ldrmnt; const form = useForm>({ resolver: zodResolver(coRegExcel), }); - const { ldrmntRegData } = useWrStore((state) => state); + const { ldrmntRegData, ldrmntDelete } = useWrStore((state) => state); const [file, setFiles] = useState(); @@ -32,8 +34,7 @@ export default function CoRegExcel({ // } // }; - //TODO:Onsubmit을 써야하는지 - const onSubmit = () => { + const onSubmit = (isReplaceAll = false) => { loadingOpen(true); if (file) { filePicked(file, 0) @@ -59,10 +60,23 @@ export default function CoRegExcel({ return false; }); } + if (isReplaceAll) { + const isConfirmed = await confirm( + "기존 등록된 잠재수요처를 \n모두 삭제후 등록처리됩니다. 실행하시겠습니까?", + ); + + if (!isConfirmed) { + loadingOpen(false); + return; + } + + await ldrmntDelete(); + } + await ldrmntRegData(array); isModal(false); loadingOpen(false); - toast.success(`잠재수요처 등록이 완료되었습니다.`); + toast.success(`잠재수요처 등록이 요청되었습니다.`); } catch (e) { console.log(e); loadingOpen(false); @@ -72,7 +86,10 @@ export default function CoRegExcel({ }) .catch((e) => { console.log("file", e); + loadingOpen(false); }); + } else { + loadingOpen(false); } }; @@ -81,7 +98,7 @@ export default function CoRegExcel({
- + e.preventDefault()}>
@@ -89,9 +106,24 @@ export default function CoRegExcel({

{"잠재수요처 파일"}

- +
+ + +
From 6c76f9a8107ed92c60b91993971e8a151c11f680 Mon Sep 17 00:00:00 2001 From: bicochan Date: Fri, 20 Mar 2026 17:37:53 +0900 Subject: [PATCH 23/25] =?UTF-8?q?[st]=20remove:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/st/src/entities/statistics/index.ts | 1 - .../model/imr/imr-detail-grid-columns.tsx | 78 ------------------- 2 files changed, 79 deletions(-) delete mode 100644 apps/st/src/entities/statistics/model/imr/imr-detail-grid-columns.tsx diff --git a/apps/st/src/entities/statistics/index.ts b/apps/st/src/entities/statistics/index.ts index 82cc2d995..73cb0fadd 100644 --- a/apps/st/src/entities/statistics/index.ts +++ b/apps/st/src/entities/statistics/index.ts @@ -8,7 +8,6 @@ export { type OutlierRecordDto, } from "./model/analysis/analysis-interface"; export { imrDetailGridColumnInfo } from "./model/imr/imr-detail-grid-column-info"; -export { imrDetailGridColumns } from "./model/imr/imr-detail-grid-columns"; export { type ImrDetailRequest, type ImrDetailResponse, diff --git a/apps/st/src/entities/statistics/model/imr/imr-detail-grid-columns.tsx b/apps/st/src/entities/statistics/model/imr/imr-detail-grid-columns.tsx deleted file mode 100644 index 80aef8bef..000000000 --- a/apps/st/src/entities/statistics/model/imr/imr-detail-grid-columns.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { createColumnHelper } from "@tanstack/react-table"; - -import type { StAnlsRsltResponse } from "../statistics-analysis/statistics-analysis-result-interface"; - -const columnHelper = createColumnHelper(); - -export const imrDetailGridColumns = [ - columnHelper.accessor("sido", { - header: "시도", - cell: (info) => ( -
{info.getValue() ?? "-"}
- ), - }), - columnHelper.accessor("gugun", { - header: "구군", - cell: (info) => ( -
{info.getValue() ?? "-"}
- ), - }), - columnHelper.accessor("admdstNm", { - header: "행정구역", - cell: (info) => ( -
{info.getValue() ?? "-"}
- ), - }), - columnHelper.accessor("admdstCd", { - header: "시설코드", - cell: (info) => ( -
{info.getValue() ?? "-"}
- ), - }), - columnHelper.accessor("fcltNm", { - header: "시설명", - cell: (info) => ( -
{info.getValue() ?? "-"}
- ), - }), - columnHelper.accessor("addr", { - header: "주소", - cell: (info) => ( -
- {info.getValue() ?? "-"} -
- ), - }), - columnHelper.accessor("pipeSeCd", { - header: "관로구분", - cell: (info) => ( -
{info.getValue() ?? "-"}
- ), - }), - columnHelper.accessor("vrfcTrgtSn", { - header: "항목번호", - cell: (info) => ( -
{info.getValue() ?? "-"}
- ), - }), - columnHelper.display({ - id: "statsNm", - header: "항목명", - cell: (info) => { - const statsNm = (info.table.options.meta as { statsNm?: string }) - ?.statsNm; - return
{statsNm ?? "-"}
; - }, - }), - columnHelper.accessor("cryrVl", { - header: "당해년도", - cell: (info) => ( -
- {info.getValue()?.toLocaleString() ?? "-"} -
- ), - }), -]; From bdd3708fde4c3dc5cc4bc62bf9fe4ca9a24d46df Mon Sep 17 00:00:00 2001 From: jcchoi Date: Fri, 20 Mar 2026 17:50:58 +0900 Subject: [PATCH 24/25] =?UTF-8?q?pm2=20config=20=EC=88=98=EC=A0=95(instanc?= =?UTF-8?q?es)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ecosystem.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecosystem.config.js b/ecosystem.config.js index 8c5873da0..497e040bc 100644 --- a/ecosystem.config.js +++ b/ecosystem.config.js @@ -1,6 +1,6 @@ const common = { exec_mode: 'cluster', - instances: 'max', + instances: 2, autorestart: true, max_memory_restart: '1G', From fe930d477325a4a284ac1986cc55f07ae8a747d7 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 23 Mar 2026 17:16:26 +0900 Subject: [PATCH 25/25] =?UTF-8?q?[st]=20feat:=20IMR=20=EA=B2=80=EC=A6=9D?= =?UTF-8?q?=EC=9D=B4=EB=A0=A5=20=EC=8B=9C=EB=8F=84/=EC=8B=9C=EA=B5=B0?= =?UTF-8?q?=EA=B5=AC=20=EC=85=80=EB=A0=89=ED=8A=B8=20API=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../verification/ImrVerificationHistory.tsx | 43 ++++++++----------- .../api/statistics-analysis-master-api.ts | 4 +- .../statistics-analysis-master-interface.ts | 2 +- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/apps/st/src/components/statistics/verification/ImrVerificationHistory.tsx b/apps/st/src/components/statistics/verification/ImrVerificationHistory.tsx index 852d21d08..9592e0cb1 100644 --- a/apps/st/src/components/statistics/verification/ImrVerificationHistory.tsx +++ b/apps/st/src/components/statistics/verification/ImrVerificationHistory.tsx @@ -23,8 +23,9 @@ import { import dayjs from "dayjs"; import { ENDPOINT } from "@/shared/config"; -import { CodeApi, CodeSelect } from "@/entities/code"; +import { CodeSelect } from "@/entities/code"; import type { + AdstZoneResponseDto, StAnlsMstResponse, StAnlsMstSearchParams, StAnlsRsltResponse, @@ -35,6 +36,10 @@ import { } from "@/entities/statistics"; import { stAnlsMstApi } from "@/entities/statistics/api/statistics-analysis-master-api"; import { imrApi } from "@/entities/statistics/api/imr-api"; +import { + useStAnlsSidoCombo, + useStAnlsSigunguCombo, +} from "@/entities/statistics/api/queries"; import { stAnlsRsltApi } from "@/entities/statistics/api/statistics-analysis-result-api"; import { Button, @@ -67,6 +72,7 @@ type DateRangeValue = { }; const EMPTY_DATA: never[] = []; +const EMPTY_ADST_LIST: AdstZoneResponseDto[] = []; const ImrVerificationHistory = () => { // Area A Search States @@ -103,25 +109,10 @@ const ImrVerificationHistory = () => { pageSize: 5, }); - // Codes for Filter - const { data: lwpoCodes } = useQuery({ - queryKey: [ENDPOINT.CMS_SERVICE.CODE, "LAESECD"], - queryFn: () => CodeApi.getCode("LAESECD"), - }); - - const sidoOptions = useMemo(() => { - if (!lwpoCodes) return []; - return lwpoCodes.filter( - (c) => c.lwpoCd.startsWith("G3") && c.lwpoCd.length === 4, - ); - }, [lwpoCodes]); - - const sigunguOptions = useMemo(() => { - if (!lwpoCodes || searchSido === "") return []; - return lwpoCodes.filter( - (c) => c.lwpoCd.startsWith(searchSido) && c.lwpoCd.length === 7, - ); - }, [lwpoCodes, searchSido]); + const { data: sidoData } = useStAnlsSidoCombo(); + const { data: sigunguData } = useStAnlsSigunguCombo(searchSido); + const sidoOptions = sidoData ?? EMPTY_ADST_LIST; + const sigunguOptions = sigunguData ?? EMPTY_ADST_LIST; // Area A Data Fetching const { data: historyData } = useQuery({ @@ -369,10 +360,10 @@ const ImrVerificationHistory = () => { {sidoOptions.map((opt) => ( - {opt.lwpoCdNm} + {opt.adstNm} ))} @@ -394,10 +385,10 @@ const ImrVerificationHistory = () => { {sigunguOptions.map((opt) => ( - {opt.lwpoCdNm} + {opt.adstNm} ))} diff --git a/apps/st/src/entities/statistics/api/statistics-analysis-master-api.ts b/apps/st/src/entities/statistics/api/statistics-analysis-master-api.ts index 19a6bee1c..bcbabda99 100644 --- a/apps/st/src/entities/statistics/api/statistics-analysis-master-api.ts +++ b/apps/st/src/entities/statistics/api/statistics-analysis-master-api.ts @@ -40,7 +40,9 @@ export class StAnlsMstApiService { return response.data; } - public async getSigunguCombo(sidoCd: string): Promise { + public async getSigunguCombo( + sidoCd: string, + ): Promise { const response = await client.get( `${ENDPOINT.STATVERIFY_SERVICE.ST_ANLS_MST}/sigungu`, { params: { sidoCd } }, diff --git a/apps/st/src/entities/statistics/model/statistics-analysis/statistics-analysis-master-interface.ts b/apps/st/src/entities/statistics/model/statistics-analysis/statistics-analysis-master-interface.ts index 046ba891b..781beeb1c 100644 --- a/apps/st/src/entities/statistics/model/statistics-analysis/statistics-analysis-master-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-analysis/statistics-analysis-master-interface.ts @@ -57,7 +57,7 @@ export interface StAnlsMstResponseDto { /** * 분석 현황 마스터 검색 DTO */ -export interface StAnlsMstSearchDto extends PageableParams { +export interface StAnlsMstSearchDto extends PageableParams { /** 분석상태코드 (COMPLETED, FAILED, QUEUED, PROCESSING) */ anlsSttsCd?: string; /** 작업UUID */