From bf241073b02582908ff7a2f3cbb21a1be307d25a Mon Sep 17 00:00:00 2001 From: leedj312 Date: Wed, 9 Jul 2025 01:36:19 +0900 Subject: [PATCH 01/17] =?UTF-8?q?=EC=88=98=EC=9A=94=EC=B2=98=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=8B=9C=20=EC=98=88=EC=99=B8=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80(=ED=8C=A8=EC=8A=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=EB=9E=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/src/ui/sdmInsertForm/form.tsx | 1 + .../common/business_components/src/ui/sdmInsertForm/index.tsx | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx index a42dea012..e58592837 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx @@ -234,6 +234,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun }, [updateList,form]); useEffect(() => { + console.log( 'form.formState.errors ', form.formState.errors) },[form.formState.errors]) const formFields: Array<{ diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index c564b63dd..9b46cc653 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -47,7 +47,9 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean ,up ? z.string().optional() // 패스워드는 선택 사항이며 길이 제한 없음 : z.string().optional() .refine((val) => !val || (val.length >= 8 && val.length <= 16), "패스워드는 8자 이상 16자 이내로 입력해주세요"), - dmdAplyPswdConfirm: z.string() + dmdAplyPswdConfirm: updateList?.dmdInfoPk // 업데이트일경우 + ? z.string().optional() // 패스워드는 선택 사항이며 길이 제한 없음 + :z.string() .min(1, "패스워드확인을 입력해주세요"), }).refine((data) => { // 패스워드 확인 검증 From 4745c87ab0c3ea541d706012d6cbed9b24f3a98d Mon Sep 17 00:00:00 2001 From: leedj312 Date: Wed, 9 Jul 2025 01:44:17 +0900 Subject: [PATCH 02/17] =?UTF-8?q?=EC=88=98=EC=9A=94=EC=B2=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=5F=20rgtr=20nullsh=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/src/ui/sdmInsertForm/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index 9b46cc653..35c609f9e 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -42,7 +42,7 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean ,up .min(8, "전화번호는 8자 이상 입력해주세요") .max(11, "전화번호는 11자 이내로 입력해주세요") .regex(/^[0-9]+$/, "전화번호는 숫자만 입력 가능합니다"), - rgtr: z.string().optional(), + rgtr: z.string().nullish(), dmdAplyPswd : updateList?.dmdInfoPk // 업데이트일경우 ? z.string().optional() // 패스워드는 선택 사항이며 길이 제한 없음 : z.string().optional() From 2aa202ace3dcf4a573a5b498f91b047170edb226 Mon Sep 17 00:00:00 2001 From: swcho Date: Wed, 9 Jul 2025 11:30:12 +0900 Subject: [PATCH 03/17] Revert "Merge branch 'iipbs/sn/ii' into iipbs/sn/main" This reverts commit 63012618a26413f7f53ec7e8062a6dd8d43d956e, reversing changes made to 6573981505c70541c238344b7fc17e065109dddd. --- apps/sn/app/(map-layout)/map/SearchModal.tsx | 35 +-- .../map/components/InputSection.tsx | 8 +- .../map/components/common/table.ts | 289 ++++++------------ .../components/popupComponent/MsSwagePpl.tsx | 2 +- .../map/components/popupComponent/Ssc.tsx | 17 +- .../components/popupComponent/sewagePump.tsx | 13 +- .../map/components/popupComponent/smh.tsx | 3 +- .../map/featureClickEventPopup.tsx | 47 +-- .../(with-base-layout)/oper/floodPre/page.tsx | 47 +-- .../(with-base-layout)/oper/oldPp/page.tsx | 44 +-- apps/sn/app/components/ui/fileUploadForm.tsx | 5 - apps/sn/app/components/ui/verticalTable.tsx | 2 +- .../src/ui/chart/BarChart.tsx | 2 +- .../src/ui/sdmInsertForm/form.tsx | 104 ++----- .../src/ui/sdmInsertForm/index.tsx | 15 +- .../src/ui/sdmInsertForm/sdmNameBox.tsx | 152 ++++----- .../src/ui/search_form_left/index.tsx | 2 +- .../src/ui/table/index.tsx | 10 +- .../src/ui/table/uiPageNations.tsx | 10 +- .../components/src/ui/date-picker/index.tsx | 7 +- 20 files changed, 240 insertions(+), 574 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/SearchModal.tsx b/apps/sn/app/(map-layout)/map/SearchModal.tsx index 73cc5fc8e..e17b80724 100644 --- a/apps/sn/app/(map-layout)/map/SearchModal.tsx +++ b/apps/sn/app/(map-layout)/map/SearchModal.tsx @@ -2,13 +2,13 @@ import FeatureClickEventPopup from './featureClickEventPopup'; import React, { useEffect, useState } from 'react'; import axios from 'axios'; import { UiModal, UiTable } from '@common/business_components/ui'; -import { Button, DatePicker, Input, Label } from '@common/components'; +import { Button, Input, Label } from '@common/components'; import { UiTable2 } from '@common/business_components/ui/table/index-2'; import { UITab2 } from '@common/business_components/ui/tab/index-2'; import { SelectBox2 } from '@common/business_components/ui/select/index-2'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox'; -import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, ExclnSewagePumpCol2, stofcbrCol2 } from './components/common/table'; +import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, SewagePump2, stofcbrCol2 } from './components/common/table'; import LoadingOverlay from '@/components/ui/LoadingBar'; const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`; @@ -122,8 +122,6 @@ const SearchModal: React.FC = ({ const [가동개시_종료_월, set가동개시_종료_월] = useState(''); const [가동개시_시작_일, set가동개시_시작_일] = useState(''); const [가동개시_종료_일, set가동개시_종료_일] = useState(''); - const [fromDate, setFromDate] = useState(() => { const date = new Date(); date.setDate(date.getDate() - 7); return date }) - const [toDate, setToDate] = useState(new Date()) // 로딩바 const [isLoading, setIsLoading] = useState(false); @@ -144,7 +142,7 @@ const SearchModal: React.FC = ({ else if (basicType === 'tb_il_swage_prcs_fclt') dynamicHeadlist = SwtrmtFcltCol2; // 하수처리시설 else if (basicType === 'tb_ms_swage_prcs_zone') dynamicHeadlist = SwtrmtPrcsZoneCol2; // 하수처리구역 else if (basicType === 'tb_ms_swage_mhl') dynamicHeadlist = MsSwageMhlCol2; // 하수맨홀 - else if (basicType === 'tb_ms_swage_pmstn') dynamicHeadlist = ExclnSewagePumpCol2; // 하수펌프장 + else if (basicType === 'tb_ms_swage_pmstn') dynamicHeadlist = SewagePump2; // 하수펌프장 else if (basicType === 'tb_ms_stofcbr') dynamicHeadlist = stofcbrCol2; // 우수토실 // 조회 버튼 클릭 시 1페이지로 이동하도록 수정 @@ -950,8 +948,8 @@ const SearchModal: React.FC = ({ value={workType} /> - {/* 수행기간 */} - {/* @@ -961,29 +959,8 @@ const SearchModal: React.FC = ({ 종료: range.end, }) } - startLabel="수행기간" + startLabel="설치년도" endLabel="" - /> */} - { if (date) setFromDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} - zIndex={102} - /> - ~ - { if (date) setToDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} - zIndex={102} />
{/* 경과년도 */} diff --git a/apps/sn/app/(map-layout)/map/components/InputSection.tsx b/apps/sn/app/(map-layout)/map/components/InputSection.tsx index 209361293..fe8897703 100644 --- a/apps/sn/app/(map-layout)/map/components/InputSection.tsx +++ b/apps/sn/app/(map-layout)/map/components/InputSection.tsx @@ -20,14 +20,14 @@ const InputSection: React.FC = ({ title, data, sectionKey, on - 년도 - 구분 + 년도 + 구분 {data.map((row, index) => ( - + = ({ title, data, sectionKey, on className="w-full text-xl border-radius-0 px-3 py-2 text-base text-center leading-normal" /> - + {row.type} diff --git a/apps/sn/app/(map-layout)/map/components/common/table.ts b/apps/sn/app/(map-layout)/map/components/common/table.ts index f114cf97b..1747106cc 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -1,65 +1,65 @@ // 하수관로 export const MsSwagePplCol = [ + { id: 'avg_grdn', title: '평균구배' }, + { id: 'clar_fvlc', title: '맑음유속' }, + { id: 'drtw_mltv_area', title: '오수배수면적' }, + { id: 'excln_mltv_area', title: '우수배수면적' }, { id: 'fclt_mng_no', title: '시설관리번호' }, - { id: 'inst_mng_no', title: '기관관리번호' }, - { id: 'instl_ymd', title: '설치일자' }, - { id: 'mapsht_no', title: '도엽번호' }, - { id: 'pdmt', title: '관경(mm)' }, - { id: 'prlg', title: '연장(m)' }, - { id: 'usg_cd', title: '용도코드' }, - { id: 'mqlt_cd', title: '재질코드' }, - { id: 'avg_grdn', title: '평균구배(m/m)' }, - { id: 'drtw_mltv_area', title: '오수배수면적(m²)' }, - { id: 'excln_mltv_area', title: '우수배수면적(m²)' }, - { id: 'tmpt_dpth', title: '시점깊이(m)' }, - { id: 'tmpt_mhl_mng_no', title: '시점맨홀관리번호' }, - { id: 'scend_dpth', title: '종점깊이(m)' }, - { id: 'scend_mhl_mng_no', title: '종점맨홀관리번호' }, - { id: 'trfln_cnt', title: '차선수' }, - { id: 'vrtc_len', title: '세로길이(m)' }, - { id: 'wdth_len', title: '가로길이(m)' }, - // { id: 'rnyssn_fvlc', title: '우기 시 유속(m/s)' }, - // { id: 'clar_fvlc', title: '건기 시 유속(m/s)' }, - // { id: 'mng_inst_cd', title: '관리기관코드' }, - // { id: 'pbadms_emd_cd', title: '행정읍면동코드' }, // { id: 'fclty_shp_cd', title: '시설물형태코드' }, // { id: 'fid', title: 'FID' }, // { id: 'ftre_smbol_cd', title: '지형지물부호코드' }, + { id: 'inst_mng_no', title: '기관관리번호' }, + { id: 'instl_ymd', title: '설치일자' }, + { id: 'mapsht_no', title: '도엽번호' }, + // { id: 'mng_inst_cd', title: '관리기관코드' }, + // { id: 'mqlt_cd', title: '재질코드' }, + // { id: 'pbadms_emd_cd', title: '행정읍면동코드' }, + { id: 'pdmt', title: '관경' }, + { id: 'prlg', title: '연장' }, + { id: 'rnyssn_fvlc', title: '우기유속' }, + { id: 'scend_dpth', title: '종점깊이' }, + { id: 'scend_mhl_mng_no', title: '종점맨홀관리번호' }, + { id: 'tmpt_dpth', title: '시점깊이' }, + { id: 'tmpt_mhl_mng_no', title: '시점맨홀관리번호' }, + { id: 'trfln_cnt', title: '차선수' }, + // { id: 'usg_cd', title: '용도코드' }, + { id: 'vrtc_len', title: '세로길이' }, + { id: 'wdth_len', title: '가로길이' }, // { id: 'lyrTypeNm', title: '레이어타입명' }, ] export const MsSwagePplCol2 = [ + { id: 'avgGrdn', title: '평균구배' }, + { id: 'clarFvlc', title: '맑음유속' }, + { id: 'drtwMltvArea', title: '오수배수면적' }, + { id: 'exclnMltvArea', title: '우수배수면적' }, { id: 'fcltMngNo', title: '시설관리번호' }, - { id: 'instMngNo', title: '기관관리번호' }, - { id: 'instlYmd', title: '설치일자' }, - { id: 'mapshtNo', title: '도엽번호' }, - { id: 'pdmt', title: '관경(mm)' }, - { id: 'prlg', title: '연장(m)' }, - { id: 'avgGrdn', title: '평균구배(m/m)' }, - { id: 'rnysnFvlc', title: '우기 시 유속(m/s)' }, - { id: 'clarFvlc', title: '건기 시 유속(m/s)' }, - { id: 'drtwMltvArea', title: '오수배수면적(m²)' }, - { id: 'exclnMltvArea', title: '우수배수면적(m²)' }, - { id: 'tmptDpth', title: '시점깊이(m)' }, - { id: 'tmptMhlMngNo', title: '시점맨홀관리번호' }, - { id: 'scendDpth', title: '종점깊이(m)' }, - { id: 'scendMhlMngNo', title: '종점맨홀관리번호' }, - { id: 'trflnCnt', title: '차선수' }, - { id: 'vrtcLen', title: '세로길이(m)' }, - { id: 'wdthLen', title: '가로길이(m)' }, // { id: 'fcltyShpCd', title: '시설물형태코드' }, // { id: 'fid', title: 'FID' }, // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, + { id: 'instMngNo', title: '기관관리번호' }, + { id: 'instlYmd', title: '설치일자' }, + { id: 'mapshtNo', title: '도엽번호' }, // { id: 'mngInstCd', title: '관리기관코드' }, // { id: 'mqltCd', title: '재질코드' }, // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, + { id: 'pdmt', title: '관경' }, + { id: 'prlg', title: '연장' }, + // { id: 'rnysnFvlc', title: '우기유속' }, + { id: 'scendDpth', title: '종점깊이' }, + { id: 'scendMhlMngNo', title: '종점맨홀관리번호' }, + { id: 'tmptDpth', title: '시점깊이' }, + { id: 'tmptMhlMngNo', title: '시점맨홀관리번호' }, + { id: 'trflnCnt', title: '차선수' }, // { id: 'usgCd', title: '용도코드' }, + { id: 'vrtcLen', title: '세로길이' }, + { id: 'wdthLen', title: '가로길이' }, // { id: 'lyrTypeNm', title: '레이어타입명' }, ] // 하수처리시설 export const SwtrmtFcltCol = [ { id: 'swtrmt_fclt_nm', title: '하수처리시설명' }, - { id: 'fclt_cpct', title: '시설용량(㎥/d)' }, + { id: 'fclt_cpct', title: '시설용량' }, { id: 'rgn_expln', title: '지역설명' }, { id: 'cmcn_ymd', title: '준공일자' }, { id: 'oprtng_strt_ymd', title: '가동개시일자' }, @@ -78,26 +78,26 @@ export const SwtrmtFcltCol = [ { id: 'rdnm_addr', title: '도로명주소' }, { id: 'dtl_rdnm_addr', title: '상세도로명주소' }, { id: 'dschg_wtst_nm', title: '방류수계명' }, - { id: 'plln_area', title: '부지면적(m²)' }, + { id: 'plln_area', title: '부지면적' }, { id: 'mng_rprtv_bzenty_nm', title: '관리대행업제명' }, - { id: 'swtrmt_ppltn_cnt', title: '하수처리인구수(인)' }, - { id: 'prcs_zone_area_sum', title: '처리구역면적합계(m²)' }, + { id: 'swtrmt_ppltn_cnt', title: '하수처리인구수' }, + { id: 'prcs_zone_area_sum', title: '처리구역면적합계' }, { id: 'xcrd', title: 'X좌표' }, { id: 'ycrd', title: 'Y좌표' }, // { id: 'oprtngSttsCd', title: '가동상태코드' }, { id: 'rprs_msrc_cn', title: '대표공법내용' }, - { id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량(mg/L)' }, - { id: 'stty_crtr_toc', title: '법정기준TOC((mg/L))' }, - { id: 'stty_crtr_ss', title: '법정기준SS(mg/L)' }, - { id: 'stty_crtr_tn', title: '법정기준총질소(mg/L)' }, - { id: 'stty_crtr_tph', title: '법정기준총인(mg/L)' }, - { id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수(군수/100mL)' }, + { id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량' }, + { id: 'stty_crtr_toc', title: '법정기준TOC' }, + { id: 'stty_crtr_ss', title: '법정기준SS' }, + { id: 'stty_crtr_tn', title: '법정기준총질소' }, + { id: 'stty_crtr_tph', title: '법정기준총인' }, + { id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수' }, { id: 'bsn_nm', title: '유역명' }, // { id: 'obsrvnSptCd', title: '관측지점코드' }, ]; export const SwtrmtFcltCol2 = [ { id: 'swtrmtFcltNm', title: '하수처리시설명' }, - { id: 'fcltCpct', title: '시설용량(㎥/d)' }, + { id: 'fcltCpct', title: '시설용량' }, { id: 'rgnExpln', title: '지역설명' }, { id: 'cmcnYmd', title: '준공일자' }, { id: 'oprtngStrtYmd', title: '가동개시일자' }, @@ -116,20 +116,20 @@ export const SwtrmtFcltCol2 = [ { id: 'rdnmAddr', title: '도로명주소' }, { id: 'dtlRdnmAddr', title: '상세도로명주소' }, { id: 'dschgWtstNm', title: '방류수계명' }, - { id: 'pllnArea', title: '부지면적(m²)' }, + { id: 'pllnArea', title: '부지면적' }, { id: 'mngRprtvBzentyNm', title: '관리대행업제명' }, - { id: 'swtrmtPpltnCnt', title: '하수처리인구수(인)' }, - { id: 'prcsZoneAreaSum', title: '처리구역면적합계(m²)' }, + { id: 'swtrmtPpltnCnt', title: '하수처리인구수' }, + { id: 'prcsZoneAreaSum', title: '처리구역면적합계' }, { id: 'xcrd', title: 'X좌표' }, { id: 'ycrd', title: 'Y좌표' }, // { id: 'oprtngSttsCd', title: '가동상태코드' }, { id: 'rprsMsrcCn', title: '대표공법내용' }, - { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량(mg/L)' }, - { id: 'sttyCrtrToc', title: '법정기준TOC(mg/L)' }, - { id: 'sttyCrtrSs', title: '법정기준SS(mg/L)' }, - { id: 'sttyCrtrTn', title: '법정기준총질소(mg/L)' }, - { id: 'sttyCrtrTph', title: '법정기준총인(mg/L)' }, - { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수(군수/100mL)' }, + { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량' }, + { id: 'sttyCrtrToc', title: '법정기준TOC' }, + { id: 'sttyCrtrSs', title: '법정기준SS' }, + { id: 'sttyCrtrTn', title: '법정기준총질소' }, + { id: 'sttyCrtrTph', title: '법정기준총인' }, + { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수' }, { id: 'bsnNm', title: '유역명' }, // { id: 'obsrvnSptCd', title: '관측지점코드' }, ]; @@ -170,14 +170,14 @@ export const MsSwageMhlCol = [ // { id: 'usg_cd', title: '용도코드' }, // { id: 'fclty_shp_cd', title: '시설물형태코드' }, // { id: 'mhl_knd_cd', title: '맨홀종류코드' }, - { id: 'swage_mh_diam', title: '하수맨홀구경(mm)' }, - { id: 'mqlt_cd', title: '재질코드' }, - { id: 'wdth_len', title: '가로길이(m)' }, - { id: 'vrtc_len', title: '세로길이(m)' }, + { id: 'swage_mh_diam', title: '하수맨홀구경' }, + { id: 'wdth_len', title: '가로길이' }, + { id: 'vrtc_len', title: '세로길이' }, + // { id: 'mqltCd', title: '재질코드' }, // { id: 'ang_dir', title: '표고' }, - { id: 'altd_vl', title: '표고(EL.m)' }, - { id: 'dpthlVl', title: '심도(m)' }, - // { id: 'inst_mng_no', title: '기관관리번호' } + { id: 'altd_vl', title: '표고' }, + { id: 'dpthlVl', title: '심도' }, + // { id: 'instMngNo', title: '기관관리번호' } ]; export const MsSwageMhlCol2 = [ // { id: 'fid', title: 'FID' }, @@ -192,81 +192,18 @@ export const MsSwageMhlCol2 = [ // { id: 'usgCd', title: '용도코드' }, // { id: 'fcltyShpCd', title: '시설물형태코드' }, // { id: 'mhlKndCd', title: '맨홀종류코드' }, - { id: 'swageMhDiam', title: '하수맨홀구경(mm)' }, - { id: 'mqltCd', title: '재질코드' }, - { id: 'wdthLen', title: '가로길이(m)' }, - { id: 'vrtcLen', title: '세로길이(m)' }, + { id: 'swageMhDiam', title: '하수맨홀구경' }, + { id: 'wdthLen', title: '가로길이' }, + { id: 'vrtcLen', title: '세로길이' }, + // { id: 'mqltCd', title: '재질코드' }, // { id: 'angDir', title: '표고' }, - { id: 'altdVl', title: '표고(EL.m)' }, - { id: 'dpthlVl', title: '심도(m)' }, + { id: 'altdVl', title: '표고' }, + { id: 'dpthlVl', title: '심도' }, // { id: 'instMngNo', title: '기관관리번호' } ]; -// 하수맨홀 뚜껑재질 코드표 -export const MS_SWAGE_MHL_CODES = [ - { val: "SBC000", text: "미분류" }, - { val: "SBC001", text: "주철" }, - { val: "SBC002", text: "철판" }, - { val: "SBC003", text: "콘크리트" }, - { val: "SBC004", text: "그레이팅" }, - { val: "SBC091", text: "칼라" }, - { val: "SBC092", text: "S.G" }, - { val: "SBC999", text: "기타" }, - { val: "SBC900", text: "각주철" }, - { val: "SBC901", text: "강재" }, - { val: "SBC902", text: "나무" }, - { val: "SBC903", text: "나무,널판지,합판" }, - { val: "SBC904", text: "대리석" }, - { val: "SBC905", text: "뚜껑없음" }, - { val: "SBC906", text: "보도용콘크리트" }, - { val: "SBC907", text: "스틸(ST)" }, - { val: "SBC908", text: "신형 CON" }, - { val: "SBC909", text: "알루미늄" }, - { val: "SBC910", text: "염화비닐(PE)" }, - { val: "SBC911", text: "인조석" }, - { val: "SBC912", text: "인조석(주철)" }, - { val: "SBC913", text: "인조CONC" }, - { val: "SBC914", text: "철, 철근" }, - { val: "SBC915", text: "칼라콘크리트" }, - { val: "SBC916", text: "플라스틱" }, - { val: "SBC917", text: "PVC" }, - { val: "SBC918", text: "SP" }, - { val: "SBC919", text: "SS" }, - { val: "SBC920", text: "닥타일주철" }, - { val: "SBC921", text: "철근G" }, - { val: "SBC922", text: "폴리에틸렌(PE)" }, - { val: "SBC923", text: "회주철" } -]; -// 하수맨홀 용도 코드표 -export const MS_SWAGE_MHL_USE_CODES = [ - { val: "SMU000", text: "미분류" }, - { val: "SMU001", text: "우수" }, - { val: "SMU002", text: "오수" }, - { val: "SMU003", text: "집수" }, - { val: "SMU004", text: "합류" }, - { val: "SMU005", text: "차집" }, - { val: "SMU999", text: "기타" }, - { val: "SMU900", text: "1호" }, - { val: "SMU901", text: "2호" }, - { val: "SMU902", text: "3호" }, - { val: "SMU903", text: "4호" }, - { val: "SMU904", text: "5호" }, - { val: "SMU905", text: "6호" }, - { val: "SMU906", text: "7호" }, - { val: "SMU907", text: "8호" }, - { val: "SMU908", text: "구거용맨홀" }, - { val: "SMU909", text: "부관부착맨홀" }, - { val: "SMU910", text: "조립식맨홀" }, - { val: "SMU911", text: "특1호" }, - { val: "SMU912", text: "특2호" }, - { val: "SMU913", text: "특3호" }, - { val: "SMU914", text: "특4호" }, - { val: "SMU915", text: "특5호" }, - { val: "SMU916", text: "하수맨홀용도" }, - { val: "SMU917", text: "현장타설관거용" } -]; -// 우수펌프장 -export const ExclnSewagePumpCol = [ +// 하수펌프장 +export const SewagePump = [ // { id: 'fid', title: 'FID' }, // { id: 'geom', title: 'geometry' }, // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, @@ -276,17 +213,17 @@ export const ExclnSewagePumpCol = [ // { id: 'mngInstCd', title: '관리기관코드' }, { id: 'instl_ymd', title: '설치일자' }, { id: 'swage_pmstn_nm', title: '하수펌프장명' }, - { id: 'plln_area', title: '부지면적(m²)' }, - // { id: 'opngSttsCd', title: '개통상태코드' }, + { id: 'plln_area', title: '부지면적' }, + // { id: 'opngSttsCd', title: '개통상태코드' }, // { id: 'usgCd', title: '용도코드' }, - { id: 'daily_prcs_cpct', title: '일일처리용량(㎥)' }, - { id: 'max_impnd_cpct', title: '최대저수용량(㎥)' }, - { id: 'altd_vl', title: '표고(EL.m)' }, - { id: 'wtlv_vl', title: '수위(m)' }, - { id: 'excln_wpmp_ablt', title: '우수양수능력(m²/d)' }, + { id: 'daily_prcs_cpct', title: '일일처리용량' }, + { id: 'max_impnd_cpct', title: '최대저수용량' }, + { id: 'altd_vl', title: '표고' }, + { id: 'wtlv_vl', title: '수위' }, + { id: 'excln_wpmp_ablt', title: '우수양수능력' }, // { id: 'instMngNo', title: '기관관리번호' }, ] -export const ExclnSewagePumpCol2 = [ +export const SewagePump2 = [ // { id: 'fid', title: 'FID' }, // { id: 'geom', title: 'geometry' }, // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, @@ -296,56 +233,14 @@ export const ExclnSewagePumpCol2 = [ // { id: 'mngInstCd', title: '관리기관코드' }, { id: 'instlYmd', title: '설치일자' }, { id: 'swagePmstnNm', title: '하수펌프장명' }, - { id: 'pllnArea', title: '부지면적(m²)' }, + { id: 'pllnArea', title: '부지면적' }, // { id: 'opngSttsCd', title: '개통상태코드' }, // { id: 'usgCd', title: '용도코드' }, - { id: 'dailyPrcsCpct', title: '일일처리용량(㎥)' }, - { id: 'max_impndCpct', title: '최대저수용량(㎥)' }, - { id: 'altdVl', title: '표고(EL.m)' }, - { id: 'wtlvVl', title: '수위(m)' }, - { id: 'exclnWpmpAblt', title: '우수양수능력(m²/d)' }, - // { id: 'instMngNo', title: '기관관리번호' }, -] - -// 오수펌프장 -export const DrtwSewagePumpCol1 = [ - // { id: 'fid', title: 'FID' }, - // { id: 'geom', title: 'geometry' }, - // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, - { id: 'fclt_mng_no', title: '시설관리번호' }, - // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, - { id: 'mapsht_no', title: '도엽번호' }, - // { id: 'mngInstCd', title: '관리기관코드' }, - { id: 'instl_ymd', title: '설치일자' }, - { id: 'swage_pmstn_nm', title: '하수펌프장명' }, - { id: 'plln_area', title: '부지면적(m²)' }, - // { id: 'opngSttsCd', title: '개통상태코드' }, - // { id: 'usgCd', title: '용도코드' }, - { id: 'daily_prcs_cpct', title: '일일처리용량(㎥)' }, - { id: 'max_impnd_cpct', title: '최대저수용량(㎥)' }, - { id: 'altd_vl', title: '표고(EL.m)' }, - { id: 'wtlv_vl', title: '수위(m)' }, - { id: 'excln_wpmp_ablt', title: '오수양수능력(m²/d)' }, - // { id: 'instMngNo', title: '기관관리번호' }, -] -export const DrtwSewagePumpCol2 = [ - // { id: 'fid', title: 'FID' }, - // { id: 'geom', title: 'geometry' }, - // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, - { id: 'fcltMngNo', title: '시설관리번호' }, - // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, - { id: 'mapshtNo', title: '도엽번호' }, - // { id: 'mngInstCd', title: '관리기관코드' }, - { id: 'instlYmd', title: '설치일자' }, - { id: 'swagePmstnNm', title: '하수펌프장명' }, - { id: 'pllnArea', title: '부지면적(m²)' }, - // { id: 'opngSttsCd', title: '개통상태코드' }, - // { id: 'usgCd', title: '용도코드' }, - { id: 'dailyPrcsCpct', title: '일일처리용량(㎥)' }, - { id: 'max_impndCpct', title: '최대저수용량(㎥)' }, - { id: 'altdVl', title: '표고(EL.m)' }, - { id: 'wtlvVl', title: '수위(m)' }, - { id: 'exclnWpmpAblt', title: '오수양수능력(m²/d)' }, + { id: 'dailyPrcsCpct', title: '일일처리용량' }, + // { id: 'max_impndCpct', title: '최대저수용량' }, + { id: 'altdVl', title: '표고' }, + { id: 'wtlvVl', title: '수위' }, + { id: 'exclnWpmpAblt', title: '우수양수능력' }, // { id: 'instMngNo', title: '기관관리번호' }, ] @@ -358,11 +253,11 @@ export const stofcbrCol = [ // { id: 'mng_inst_cd', title: '관리기관코드' }, { id: 'instl_ymd', title: '설치일자' }, // { id: 'fclty_shp_cd', title: '시설물형태코드' }, - { id: 'worflw_wall_hgt', title: '월류벽높이(m)' }, + { id: 'worflw_wall_hgt', title: '월류벽높이' }, // { id: 'mhl_exst_yn_cd', title: '맨홀존재여부코드' }, // { id: 'swage_mhl_ftre_smbol_cd', title: '하수맨홀지형지물부호코드' }, { id: 'swage_mhl_mng_no', title: '하수맨홀관리번호' }, - { id: 'drtn_angl', title: '방향각도(°)' }, + { id: 'drtn_angl', title: '방향각도' }, ] export const stofcbrCol2 = [ // { id: 'ftre_smbol_cd', title: '지형지물부호코드' }, @@ -372,11 +267,11 @@ export const stofcbrCol2 = [ // { id: 'mng_inst_cd', title: '관리기관코드' }, { id: 'instlYmd', title: '설치일자' }, // { id: 'fclty_shp_cd', title: '시설물형태코드' }, - { id: 'worflwWallHgt', title: '월류벽높이(m)' }, + { id: 'worflwWallHgt', title: '월류벽높이' }, // { id: 'mhl_exst_yn_cd', title: '맨홀존재여부코드' }, // { id: 'swage_mhl_ftre_smbol_cd', title: '하수맨홀지형지물부호코드' }, { id: 'swageMhlMngNo', title: '하수맨홀관리번호' }, - { id: 'drtnAngl', title: '방향각도(°)' }, + { id: 'drtnAngl', title: '방향각도' }, ] // 중점우수토실 측정지점 @@ -392,7 +287,7 @@ export const untrtSwgRainCol1 = [ // 중점우수토실 측정지점 시설현황 export const untrtSwgRainCol2 = [ { id: 'flwmtr_mesure_tp_etc', title: '구분' }, - { id: 'discharge_pipe_spec', title: '방류관로 규격(m)' }, + { id: 'discharge_pipe_spec', title: '방류관로 규격' }, { id: 'swr_ppl_eqp_ar', title: '배수구역 면적(m²)' }, { id: 'swr_trt_popl', title: '하수처리 인구(인)' }, { id: 'screen_instl_at', title: '스크린설치 여부' }, diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx index 26b3a60aa..46537a7dd 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx @@ -7,7 +7,7 @@ import { handleInputChange } from '../common'; // 하수관로 const inputColumn = [ { id: "title", title: "설치주제", type: "select", options: ["BTL", "재정사업"] }, - { id: "swtrmt_zone_cd", title: "처리구역", type: "input" }, + { id: "swtrmt_zone_cd", title: "처리구역", type: "select", options: ["구역1", "구역2"] }, { id: "basu", title: "배수구역", type: "input" }, { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, { id: "wltjs", title: "지선/간선", type: "select", options: ["지선", "간선"] }, diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx index 31aef5172..7e22ea03b 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx @@ -3,19 +3,12 @@ import { UiModal, UiTable } from '@common/business_components/ui'; import { Button, TableHead, TableRow } from '@common/components/ui'; import React, { useState } from 'react'; import { untrtSwgRainCol3, untrtSwgRainCol4, untrtSwgRainCol5 } from '../common/table'; -import { VerticalTable } from '@/components/ui/verticalTable'; import LoadingOverlay from '@/components/ui/LoadingBar'; -const inputColumn = [ - { id: "place", title: "중점여부", type: "select", options: ["중점우수토실", "우수토실"] }, - { id: "guyeok", title: "처리구역", type: "input" }, -]; - -const Ssc = ({ featureData, chkMainSsc, additionalData, onSaveClick }: { +const Ssc = ({ featureData, chkMainSsc, additionalData }: { featureData: any, chkMainSsc?: boolean, - additionalData?: any, - onSaveClick?: () => void + additionalData?: any }) => { const [isModalOpen, setIsModalOpen] = useState(false); const [isDataLoaded, setIsDataLoaded] = useState(false); @@ -100,7 +93,7 @@ const Ssc = ({ featureData, chkMainSsc, additionalData, onSaveClick }: { return (
- + /> */} {chkMainSsc && (
diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx index f0c4d21b3..4eaf1f18d 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx @@ -1,22 +1,17 @@ import { VerticalTable } from '@/components/ui/verticalTable'; import React from 'react' -const exclnInputColumn = [ - { id: "swtrmt_zone_cd", title: "배수구역", type: "input" }, +const inputColumn = [ + { id: "swtrmt_zone_cd", title: "처리구역", type: "select", options: ["구역1", "구역2"] }, { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, - { id: "freq", title: "설계빈도(년)", type: "input" }, + { id: "freq", title: "설계빈도", type: "input" }, ] -const drtwInputColumn = [ - { id: "swtrmt_zone_cd", title: "배수구역", type: "input" }, - { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, -] - // 하수펌프장 const sewagePump = ({ featureData, onSaveClick }: { featureData: any, onSaveClick?: () => void }) => { return ( void }) => { return ( diff --git a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx index 72831902f..16c4f99a8 100644 --- a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx @@ -6,7 +6,7 @@ import { useGisContext } from "@common/business_components/ui/map/Gis"; import { Button } from "@common/components/ui"; import { useEffect, useRef, useState, useCallback, useMemo } from "react"; import { getLayerContentComponent } from "./components/common"; -import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, ExclnSewagePumpCol, MsSwageMhlCol, stofcbrCol, MS_SWAGE_MHL_CODES } from "./components/common/table"; +import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, SewagePump, MsSwageMhlCol, stofcbrCol } from "./components/common/table"; import InfilChart from './components/popupComponent/chart/infilChart'; import RdiiChart from './components/popupComponent/chart/rdiiChart'; import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore"; @@ -29,8 +29,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, const [isAdditionalDataLoading, setIsAdditionalDataLoading] = useState(false); const [additionalDataError, setAdditionalDataError] = useState(null); // 🎯 InfilChart 및 RdiiChart 관련 상태 추가 - const { setIsOpen: setIsModalInfil } = useInfilChartModalStore(); - const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore(); + const { setIsOpen:setIsModalInfil } = useInfilChartModalStore(); + const { setIsOpen:setIsModalRdii } = useRdiiChartModalStore(); // 🎯 관로관리번호 추출 const pplMngNo = featureData?.values_?.fclt_mng_no || ""; @@ -135,27 +135,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, console.log('gis data', featureData.values_); let data = featureData.values_; - - // 하수맨홀인 경우 용도코드를 텍스트로 변환 - if (selectedLayerName === '하수맨홀' && data) { - const processedData = { ...data }; - - // mqlt_cd 값 변환 (재질코드) - if (processedData.mqlt_cd) { - const materialCodeItem = MS_SWAGE_MHL_CODES.find( - code => code.val === processedData.mqlt_cd.trim() - ); - if (materialCodeItem) { - processedData.mqlt_cd = `${materialCodeItem.text}`; - } - } - - setfetchData(processedData); - setTableData(processedData); - } else { - setfetchData(data); - setTableData(data); - } + setfetchData(data) + setTableData(data); switch (selectedLayerName) { case '하수처리시설': @@ -192,7 +173,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, case '우수토실': setHeadlist(stofcbrCol) setButtonChk(false) - setChkMainSsc(false) break; case '하수관로': setHeadlist(MsSwagePplCol) @@ -205,7 +185,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // setButtonChk(true) // break; case '하수펌프장': - setHeadlist(ExclnSewagePumpCol) + setHeadlist(SewagePump) setButtonChk(true) break; case '하수맨홀': @@ -257,41 +237,32 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, setIsModalOpen(false); // 모달 닫기 }; - // 저장 버튼 이벤트 const btnClickEvent = async () => { const bodyData: Record = {} - if (buttonChk && contentRef.current) { const inputElements = contentRef.current.querySelectorAll('input'); const selectElements = contentRef.current.querySelectorAll('select'); - // 카멜케이스 변환 함수 const toCamelCase = (str: string) => str.replace(/_([a-z])/g, (_, char) => char.toUpperCase()); - // select 태그의 값 가져오기 selectElements.forEach((select) => { const camelCaseId = toCamelCase(select.id); bodyData[camelCaseId] = select.value; }); - // input 태그의 값 가져오기 inputElements.forEach((input) => { const camelCaseId = toCamelCase(input.id); bodyData[camelCaseId] = input.value; }); - if (layerNm === '하수관로') bodyData['lyrTypeNm'] = 'tb_ms_swage_ppl' else if (layerNm === '우수토실') bodyData['lyrTypeNm'] = 'tb_ms_stofcbr' else if (layerNm === '중점우수토실') bodyData['lyrTypeNm'] = 'om_dt_untrt_swg_rain' else if (layerNm === '오수펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn' else if (layerNm === '빗물펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn' else if (layerNm === '하수맨홀') bodyData['lyrTypeNm'] = 'tb_ms_swage_mnhl' - bodyData['fid'] = featureId - const data = await putData(`v1/fclts/${featureId}`, bodyData); - if (data.status == 200) { alert('저장되었습니다') setTableData(data) @@ -315,13 +286,13 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, {/* 🎯 하수관로일 때만 Infil/RDII 버튼 표시 */} {layerNm === '하수관로' && ( <> - -
) } diff --git a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx index 3578ff967..6ae0b3609 100644 --- a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx @@ -27,16 +27,16 @@ const Page = () => { const [curPage, setCurPage] = useState(1) //현재 페이지 const [totalData, setTotalData] = useState(0) //총 데이터 수 const [isLoading, setIsLoading] = useState(true) //로딩 상태 - - // 조회 const fetchData = async () => { setIsLoading(true) - // searchCmmnCd('SITEKNDCD') + searchCmmnCd('SITEKNDCD') try { const { data, total } = await searchData('v1/sbmrgPrevnt', { fromRegDt: formatDate(fromDate), + fromMngYr: manageYear, + toMngYr: mngQu, toRegDt: formatDate(toDate), - sbmrgPrevntBizNm: pjNm, + atflNm: pjNm, rgtrNm: usr, page: curPage - 1, size: '10' @@ -45,18 +45,12 @@ const Page = () => { setTotalData(total) } catch (error) { console.error('Error fetching data:', error) } - finally { - setFileNm(''); - setAtflId(''); - setSbmrgPrevntBizSn(''); - setIsLoading(false); - } + finally { setIsLoading(false); } } useEffect(() => { setCurPage(1) fetchData() }, []) - // 파일 다운로드 const isChckFile = () => { if (fileNm === '' || fileNm === undefined) { @@ -65,7 +59,6 @@ const Page = () => { } handleDownload(`/attach-service/api/v1/download/${atflId}`, fileNm) } - // 선택 파일 삭제 const isDeleteFile = async () => { if (sbmrgPrevntBizSn === '' || sbmrgPrevntBizSn === undefined) { @@ -103,19 +96,11 @@ const Page = () => { { if (date) setFromDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} - /> + onSelect={(date: Date | undefined) => { if (date) setFromDate(date) }} /> ~ { if (date) setToDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} - /> + onSelect={(date: Date | undefined) => { if (date) setToDate(date) }} />
@@ -147,23 +132,7 @@ const Page = () => {
- { - if (index != null) { - const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; - const id = tableData[index]?.atflId ?? ''; - setFileNm(fileName); - setAtflId(id); - setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn); - } - }} - onPageChange={async (page: number) => { setCurPage(page); await fetchData() }} - /> + { if (index != null) { const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn); } }} onPageChange={async (page: number) => { setCurPage(page); await fetchData() }}> { await registFile(file, year, quater, cd, id) }} /> diff --git a/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx b/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx index c4bac35b7..307452e2d 100644 --- a/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx @@ -25,13 +25,14 @@ const Page = () => { const [curPage, setCurPage] = useState(1) const [totalData, setTotalData] = useState(0) //총 데이터 수 const [isLoading, setIsLoading] = useState(true) //로딩 상태 - // 데이터 조회 const fetchData = async () => { setIsLoading(true) try { const { data, total } = await searchData('v1/dcrpPpl', { fromRegDt: formatDate(fromDate), + fromMngYr: manageYear, + toMngYr: mngQu, toRegDt: formatDate(toDate), dcrpPplMtncBizNm: pjNm, rgtrNm: usr, @@ -43,18 +44,12 @@ const Page = () => { console.log(data, total) } catch (error) { console.error('Error fetching data:', error) - } finally { - setFileNm(''); - setAtflId(''); - setDcrpPplMtncBizSn(''); - setIsLoading(false) - } + } finally { setIsLoading(false) } } useEffect(() => { setCurPage(1) fetchData() }, []) - // 파일 다운로드 const isChckFile = () => { if (fileNm === '' || fileNm === undefined) { @@ -64,7 +59,6 @@ const Page = () => { handleDownload(`/attach-service/api/v1/download/${atflId}`, fileNm) return true } - // 파일 삭제 const isDeleteFile = async () => { if (dcrpPplMtncBizSn === '' || dcrpPplMtncBizSn === undefined) { @@ -82,7 +76,6 @@ const Page = () => { } } } - // 파일 등록 const registFile = async (fileNm: string, year: string, quater: string, cd: string, id: string) => { const data = await postData('v1/dcrpPpl', { @@ -95,8 +88,6 @@ const Page = () => { }) if (data) { alert('파일이 등록되었습니다.'); fetchData() } } - - return ( <> @@ -107,17 +98,11 @@ const Page = () => { { if (date) setFromDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} /> + onSelect={(date: Date | undefined) => { if (date) setFromDate(date) }} /> ~ { if (date) setToDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} /> + onSelect={(date: Date | undefined) => { if (date) setToDate(date) }} />
{
- { - if (index != null) { - const fileName = tableData[index]?.dcrpPplMtncBizNm ?? ""; - const id = tableData[index]?.atflId ?? ''; - setFileNm(fileName); - setAtflId(id); - setDcrpPplMtncBizSn(tableData[index]?.dcrpPplMtncBizSn); - } - }} - onPageChange={async (page: number) => { setCurPage(page); await fetchData() }} - /> + { if (index != null) { const fileName = tableData[index]?.dcrpPplMtncBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setDcrpPplMtncBizSn(tableData[index]?.dcrpPplMtncBizSn) } }} onPageChange={async (page: number) => { setCurPage(page); await fetchData() }}>
{ await registFile(file, year, quater, cd, id) }} /> diff --git a/apps/sn/app/components/ui/fileUploadForm.tsx b/apps/sn/app/components/ui/fileUploadForm.tsx index fb626348e..3cd663e01 100644 --- a/apps/sn/app/components/ui/fileUploadForm.tsx +++ b/apps/sn/app/components/ui/fileUploadForm.tsx @@ -29,8 +29,6 @@ const FileUploadForm = ({ const [files, setFiles] = useState(null); const [upload, setUpload] = useState(null); const uniqueId = useId(); // 각 FileUploadForm 인스턴스에 대한 고유 ID 생성 - // FileUploader 컴포넌트를 강제로 재마운트하기 위한 key 상태 추가 - const [uploaderKey, setUploaderKey] = useState(0); const quater = [{ text: '1분기', val: '1' }, { text: '2분기', val: '2' }, { text: '3분기', val: '3' }, { text: '4분기', val: '4' }]; // 현재 년도부터 10년 전까지의 년도 옵션 생성 @@ -66,7 +64,6 @@ const FileUploadForm = ({
{/* FileUploader와 Button을 정렬하는 메인 flex 컨테이너 */}
{/* FileUploader의 너비와 오른쪽 여백을 제어하는 컨테이너 */} prev + 1); } }} > diff --git a/apps/sn/app/components/ui/verticalTable.tsx b/apps/sn/app/components/ui/verticalTable.tsx index 19e302c30..1455c9e4a 100644 --- a/apps/sn/app/components/ui/verticalTable.tsx +++ b/apps/sn/app/components/ui/verticalTable.tsx @@ -141,7 +141,7 @@ export function VerticalTable({ handleInputChange(head.id, e.target.value)} className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1" /> diff --git a/packages/common/business_components/src/ui/chart/BarChart.tsx b/packages/common/business_components/src/ui/chart/BarChart.tsx index 02d3a7c60..0802a72e4 100644 --- a/packages/common/business_components/src/ui/chart/BarChart.tsx +++ b/packages/common/business_components/src/ui/chart/BarChart.tsx @@ -75,7 +75,7 @@ const CustomLegend = (props: any) => { }; export default function Chart({chartConfig=undefined, chartData=[], chartTitle='차트', chartClassName='w-full h-full', graphSize=40, yFieldText='', showLegend=false} : BarChartProps) { - const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FED16A", "#FFEEAD", "#D4A5A5"]; + const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEEAD", "#D4A5A5"]; const getMaxValue = (data: any[], keyPrefix: string) => { return Math.max(...data.map(item => Object.keys(item) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx index a42dea012..2d7d2bf90 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import { FormField } from "../form"; +import { FormField } from "../form"; import { SelectBox } from "../select"; import { Input } from "@common/components"; import { FormUi } from "../form_ui"; @@ -56,7 +55,6 @@ interface FormSchema { bznmTotNo?: string; rgtr?: string; dmdAplyPswd?: string; - dmdAplyPswdConfirm?: string; } interface SdmRegFormProps { @@ -87,25 +85,10 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun const formatter = new AsYouType("KR"); const formatted = formatter.input(input); - return formatted - }; + // 저장할 값 처리: 숫자만 추출 + const digitsOnly = input.replace(/\D/g, ""); - // 사업자등록번호 포맷팅 함수 (3-2-5 형식) - const formatBusinessNumber = (value: string) => { - // 숫자만 추출 - const digitsOnly = value.replace(/\D/g, ""); - - // 10자리까지만 처리 - const limitedDigits = digitsOnly.slice(0, 10); - - // 3-2-5 형식으로 포맷팅 - if (limitedDigits.length <= 3) { - return limitedDigits; - } else if (limitedDigits.length <= 5) { - return `${limitedDigits.slice(0, 3)}-${limitedDigits.slice(3)}`; - } else { - return `${limitedDigits.slice(0, 3)}-${limitedDigits.slice(3, 5)}-${limitedDigits.slice(5)}`; - } + return formatted }; @@ -196,15 +179,12 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun const value = e.target.value; if(noType === 'dmdInfoPk') { - // 숫자만 추출하여 저장 (포맷팅 제거) - const digitsOnly = value.replace(/\D/g, ""); - - if(orgBznmNo.substring(0,10) === digitsOnly) { + if(orgBznmNo.substring(0,10) === value) { setIsDuplicate(true); } else { setIsDuplicate(false); } - field?.onChange(digitsOnly); + field?.onChange(value); } else { if(orgBznmNo.substring(10,14) === value) { setIsDuplicate(true); @@ -316,7 +296,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun type="text" className="!text-xl text-gray-600" onChange={(e) => bznNoChange(e, 'dmdInfoPk', field)} - value={formatBusinessNumber(field.value || '')} + value={field.value} readOnly={!!updateList?.dmdInfoPk} /> ) @@ -388,60 +368,32 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun {...field} /> ) - }, - { - name: "dmdAplyPswdConfirm", - label: "패스워드확인", - component: (field) => ( - - ) } ] return ( <> - {formFields - .filter(({ name }) => !(updateList?.dmdInfoPk && (name === "dmdAplyPswd" || name === "dmdAplyPswdConfirm"))) - .map(({ name, label, component }) => { - const error = form.formState.errors[name]; - const inputId = `${name}-input`; - const errorId = `${name}-error`; - const isRequired = ["ctpvCd", "sggCd", "dmdCoNm", "dmdInfoPk", "daddr", "telno", "dmdAplyPswd", "dmdAplyPswdConfirm"].includes(name); - - return ( - ( -
- - - {React.cloneElement(component(field), { - id: inputId, - "aria-required": isRequired, - "aria-invalid": !!error, - "aria-describedby": error ? errorId : undefined - })} - - {error?.message && ( - - )} -
- )} - /> - ); - })} + {formFields.filter((item)=> + {if(updateList?.dmdInfoPk){ + return item.name !== 'dmdAplyPswd' + }else{ + return item + } + }) + .map(({ name, label, component }) => ( + ( + name === 'bznmTotNo' ? component(field) : ( + + {component(field)} + + ) + )} + /> + ))} ); } \ No newline at end of file diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index c564b63dd..4219602e6 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -47,17 +47,7 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean ,up ? z.string().optional() // 패스워드는 선택 사항이며 길이 제한 없음 : z.string().optional() .refine((val) => !val || (val.length >= 8 && val.length <= 16), "패스워드는 8자 이상 16자 이내로 입력해주세요"), - dmdAplyPswdConfirm: z.string() - .min(1, "패스워드확인을 입력해주세요"), -}).refine((data) => { - // 패스워드 확인 검증 - if (data.dmdAplyPswd && data.dmdAplyPswdConfirm) { - return data.dmdAplyPswd === data.dmdAplyPswdConfirm; - } - return true; -}, { - message: "패스워드가 일치하지 않습니다", - path: ["dmdAplyPswdConfirm"], // 에러를 패스워드 확인 필드에 표시 + }); type FormSchema = z.infer>; @@ -72,7 +62,6 @@ const defaultValues: FormSchema = { telno: '', rgtr: '', dmdAplyPswd: '', - dmdAplyPswdConfirm: '', }; /** @@ -160,7 +149,7 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList console.log(' formData ', formData) /* await insertSdmData(formData); */ - rtnInputData(formData as unknown as DemandCompType); + rtnInputData(formData as DemandCompType); //router.push(`/pages/sdmMng/sdmInfoInsert?${queryParams.toString()}`); diff --git a/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx b/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx index 059d63d90..3c8fd7192 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx @@ -1,14 +1,14 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; -import type { DemandCompType } from "./form"; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import type { DemandCompType } from './form'; export type thisProps = { label: string | undefined; initValue: string | undefined; - dataList: DemandCompType[]; - rtnValue: (searchText: string, pageCnt: number) => void; - rtnData: (item: DemandCompType) => void; - rtnText: (text: string) => void; -}; + dataList : DemandCompType[]; + rtnValue : (searchText: string, pageCnt: number) => void; + rtnData : (item: DemandCompType) => void; + rtnText : (text: string) => void; +} /** * 수요처 검색 컴포넌트 @@ -18,110 +18,88 @@ export type thisProps = { * @param dataList 검색할 때 넘기는 데이터 리스트 * @param rtnData 검색 결과 반환 함수 */ -export const SdmSearchForm = ({ - label = undefined, - initValue = undefined, - rtnValue = () => {}, - dataList = [], - rtnData = () => {}, - rtnText = () => {}, -}: thisProps) => { +export const SdmSearchForm = ({label=undefined, initValue=undefined, rtnValue=()=>{}, dataList=[], rtnData=()=>{}, rtnText=()=>{} } :thisProps) => { + const [isOpen, setIsOpen] = useState(false); - const [textValue, setTextValue] = useState(initValue || ""); + const [textValue, setTextValue] = useState(initValue || ''); const wrapperRef = useRef(null); - const handleInputChange = useCallback( - (e: React.ChangeEvent) => { - const value = e.target.value; - setTextValue(value); - rtnValue(value, 10); - rtnText(value); - if (value) { - setIsOpen(true); - } else { - setIsOpen(false); - } - }, - [rtnValue, rtnText], - ); - - const handleSuggestionClick = useCallback( - (item: DemandCompType) => { - setTextValue(item.dmdCoNm); - rtnData(item); + const handleInputChange = useCallback((e: React.ChangeEvent) => { + const value = e.target.value; + setTextValue(value); + rtnValue(value, 10); + rtnText(value); + if (value) { + setIsOpen(true); + } else { setIsOpen(false); - }, - [rtnData], - ); + } + }, [rtnValue, rtnText]); + + const handleSuggestionClick = useCallback((item: DemandCompType) => { + setTextValue(item.dmdCoNm); + rtnData(item); + setIsOpen(false); + }, [rtnData]); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { - if ( - wrapperRef.current && - !wrapperRef.current.contains(event.target as Node) - ) { + if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) { setIsOpen(false); } }; - document.addEventListener("mousedown", handleClickOutside); + document.addEventListener('mousedown', handleClickOutside); return () => { - document.removeEventListener("mousedown", handleClickOutside); + document.removeEventListener('mousedown', handleClickOutside); }; }, []); useEffect(() => { - if (initValue && initValue?.length > 0) { - setTextValue(initValue); + if(initValue&& initValue?.length>0){ + setTextValue(initValue) } - }, [initValue]); - + },[initValue]) + return ( -
+
setIsOpen(true)} */ - className="h-[3.2rem] w-full rounded-md border border-gray-300 pl-3 !text-xl text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" + className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder={`${label}을(를) 입력하세요`} /> {isOpen && ( -
+
- {dataList && dataList.length > 0 ? ( - dataList.map((item: DemandCompType, index: number) => ( -
handleSuggestionClick(item)} - role="button" - tabIndex={0} - onKeyDown={(e) => { - if (e.key === "Enter" || e.key === " ") { - handleSuggestionClick(item); - } - }} - > - {item.dmdInfoPk.substring(10, 14) !== "0000" ? ( - <> - 사업자번호 : {" "} - {item.dmdInfoPk.substring(0, 10)}  - - 종사업자번호 :{" "} - {" "} - {item.dmdInfoPk.substring(10, 14)}  - - ) : ( - <> - 사업자번호 : {" "} - {item.dmdInfoPk.substring(0, 10)}  - - )} - {item.dmdCoNm} -
- )) - ) : ( -
+ {dataList && dataList.length > 0 ? dataList.map((item : DemandCompType, index : number) => ( +
handleSuggestionClick(item)} + role="button" + tabIndex={0} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + handleSuggestionClick(item); + } + }} + > + {item.dmdInfoPk.substring(10,14) !== '0000' ? ( + <> + 사업자번호 : {item.dmdInfoPk.substring(0,10)}  + 종사업자번호 : {item.dmdInfoPk.substring(10,14)}  + + ) : ( + <> + 사업자번호 : {item.dmdInfoPk.substring(0,10)}  + + )} + {item.dmdCoNm} +
+ )) : ( +
검색 결과가 없습니다.
)} @@ -129,5 +107,5 @@ export const SdmSearchForm = ({
)}
- ); -}; + ) +} \ No newline at end of file diff --git a/packages/common/business_components/src/ui/search_form_left/index.tsx b/packages/common/business_components/src/ui/search_form_left/index.tsx index 4f36c078c..e7858df2a 100644 --- a/packages/common/business_components/src/ui/search_form_left/index.tsx +++ b/packages/common/business_components/src/ui/search_form_left/index.tsx @@ -199,7 +199,7 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel setRtnSidoText(selectedSido?.text || ''); } initializeSigunData(val); - onSelectValue('0', 'sigun'); + onSelectValue(selectSigunData[0]?.val || '0', 'sigun'); break; case 'sigun': if (setRtnSigunValue) { diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index 01bb18ba2..fe720abc0 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -49,12 +49,6 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr } }, [resetSelection]); - // 테이블 데이터가 변경될 때마다 선택된 행 초기화하는 useEffect 추가 - useEffect(() => { - // 새로운 데이터가 로드되면 선택 상태 초기화 - setIdx(-1); - }, [tableData]); - const handlePageChange = (page: number) => { setCur(page); onPageChange(page); @@ -89,7 +83,7 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr ? handleCellClick(index, head.id)} key={`cell-${head.id}-${index}`} @@ -103,7 +97,7 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr : handleCellClick(index, head.id)} key={`cell-${head.id}-${index}`} diff --git a/packages/common/business_components/src/ui/table/uiPageNations.tsx b/packages/common/business_components/src/ui/table/uiPageNations.tsx index ca1f8e0c0..891fc4c81 100644 --- a/packages/common/business_components/src/ui/table/uiPageNations.tsx +++ b/packages/common/business_components/src/ui/table/uiPageNations.tsx @@ -40,8 +40,7 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP { - e.preventDefault(); + onClick={() => { if (startPage > 1) handlePageChange(startPage - 1); }} /> @@ -54,9 +53,7 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP { - e.preventDefault(); - handlePageChange(pageNum)}} + onClick={() => handlePageChange(pageNum)} > {pageNum} @@ -68,8 +65,7 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP { - e.preventDefault(); + onClick={() => { if (endPage < totalPages) handlePageChange(endPage + 1); }} /> diff --git a/packages/common/components/src/ui/date-picker/index.tsx b/packages/common/components/src/ui/date-picker/index.tsx index 85c584e5f..919e22435 100644 --- a/packages/common/components/src/ui/date-picker/index.tsx +++ b/packages/common/components/src/ui/date-picker/index.tsx @@ -13,14 +13,12 @@ type DatePickerProps = { placeholder?: string; disabled?: boolean; selected?: Date; - zIndex?: number; // z-index prop 추가 } & React.ComponentProps; export function DatePicker({ className, placeholder = "날짜 선택", disabled, - zIndex, // zIndex prop 받기 ...props }: DatePickerProps) { return ( @@ -39,10 +37,7 @@ export function DatePicker({ )} - + From fc1aa4fe061fe26826292695cddbf8220861b8c1 Mon Sep 17 00:00:00 2001 From: JIeunhuh Date: Wed, 9 Jul 2025 11:45:53 +0900 Subject: [PATCH 04/17] =?UTF-8?q?=ED=98=84=ED=99=A9=20=EC=98=A4=ED=94=88?= =?UTF-8?q?=20=EC=8B=9C=20=EB=A0=88=EC=9D=B4=EC=96=B4=EB=AA=85=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20featureid=20=EA=B5=AC=EB=B6=84=20=EC=9E=91?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/map/Gis.js | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index ef5c21d5b..880c116cd 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -46,7 +46,7 @@ function Gis({ const gisCore = useMemo(() => new GisApp.core({ targetId: mapRef.current }), []); const mapInstanceRef = useRef(null); const checkedLayerIds = useRef([]); - + const layerNmRef = useRef('') // 팝업 데이터를 저장할 상태와 오버레이 참조를 저장할 ref 추가 // const [facilityInfoPopupData, setFacilityInfoPopupData] = useState([]); @@ -84,12 +84,32 @@ function Gis({ foundFeature = data; } else { // 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용 - const featureId = data.fid || data.ftrIdn || data.id; + let featureId + const layerName = layerNmRef.current + if (layerName === '하수재이용시설') { + featureId = data.searchPk; + } else if (layerName === '빗물이용시설') { + featureId = data.bdstInfoPk; + } else if (layerName === '하수처리시설') { + featureId = data.bscFctCd; + } else if (layerName === '중수도시설' || layerName == '온배수시설') { + featureId = data.bdstRuseFcltPk; + } else { + console.warn('해당 레이어에 대한 featureId 매핑 없음', layerNm); + featureId = data.fid || data.id || data.ftrIdn; + } gisMap.getLayers().getArray().forEach(layer => { const source = layer.getSource?.(); - if (source?.getFeatureById) { - const feature = source.getFeatureById(String(featureId).trim()); - if (feature) foundFeature = feature; + if (source?.getFeatures) { + const allFeatures = source.getFeatures(); + for (const f of allFeatures) { + const id = String(f.getId()); + // console.log('id', id, featureId) + if (id && id.split('.')[1] === String(featureId)) { + foundFeature = f; + break; + } + } } }); } @@ -360,6 +380,7 @@ function Gis({ setVisible={setTabVisible} onCheckedChange={handleCheckedLayersChange} onLayerIconClick={(nodeNm) => { + layerNmRef.current = nodeNm setLayerNm(nodeNm); setIsOpen(true); const dummyFeature = { getProperties: () => ({}), // 최소 구조 }; @@ -375,6 +396,7 @@ function Gis({ featureData={featureData || { getProperties: () => ({}) }} seletectedLayerNm={layerNm} onClose={closePopup} // 닫기 콜백 전달 + onFeatureSelect={handleFeatureSelect} /> )} {/* SearchView가 존재할 때만 렌더링 */} From e4426d61b3872617209259dfe9688accd0cbbcff Mon Sep 17 00:00:00 2001 From: swcho Date: Wed, 9 Jul 2025 11:55:08 +0900 Subject: [PATCH 05/17] Reapply "Merge branch 'iipbs/sn/ii' into iipbs/sn/main" This reverts commit 2aa202ace3dcf4a573a5b498f91b047170edb226. --- apps/sn/app/(map-layout)/map/SearchModal.tsx | 35 ++- .../map/components/InputSection.tsx | 8 +- .../map/components/common/table.ts | 285 ++++++++++++------ .../components/popupComponent/MsSwagePpl.tsx | 2 +- .../map/components/popupComponent/Ssc.tsx | 17 +- .../components/popupComponent/sewagePump.tsx | 13 +- .../map/components/popupComponent/smh.tsx | 3 +- .../map/featureClickEventPopup.tsx | 47 ++- .../(with-base-layout)/oper/floodPre/page.tsx | 47 ++- .../(with-base-layout)/oper/oldPp/page.tsx | 44 ++- apps/sn/app/components/ui/fileUploadForm.tsx | 5 + apps/sn/app/components/ui/verticalTable.tsx | 2 +- .../src/ui/chart/BarChart.tsx | 2 +- .../src/ui/sdmInsertForm/form.tsx | 104 +++++-- .../src/ui/sdmInsertForm/index.tsx | 15 +- .../src/ui/sdmInsertForm/sdmNameBox.tsx | 152 ++++++---- .../src/ui/search_form_left/index.tsx | 2 +- .../src/ui/table/index.tsx | 10 +- .../src/ui/table/uiPageNations.tsx | 10 +- .../components/src/ui/date-picker/index.tsx | 7 +- 20 files changed, 572 insertions(+), 238 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/SearchModal.tsx b/apps/sn/app/(map-layout)/map/SearchModal.tsx index e17b80724..73cc5fc8e 100644 --- a/apps/sn/app/(map-layout)/map/SearchModal.tsx +++ b/apps/sn/app/(map-layout)/map/SearchModal.tsx @@ -2,13 +2,13 @@ import FeatureClickEventPopup from './featureClickEventPopup'; import React, { useEffect, useState } from 'react'; import axios from 'axios'; import { UiModal, UiTable } from '@common/business_components/ui'; -import { Button, Input, Label } from '@common/components'; +import { Button, DatePicker, Input, Label } from '@common/components'; import { UiTable2 } from '@common/business_components/ui/table/index-2'; import { UITab2 } from '@common/business_components/ui/tab/index-2'; import { SelectBox2 } from '@common/business_components/ui/select/index-2'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox'; -import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, SewagePump2, stofcbrCol2 } from './components/common/table'; +import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, ExclnSewagePumpCol2, stofcbrCol2 } from './components/common/table'; import LoadingOverlay from '@/components/ui/LoadingBar'; const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`; @@ -122,6 +122,8 @@ const SearchModal: React.FC = ({ const [가동개시_종료_월, set가동개시_종료_월] = useState(''); const [가동개시_시작_일, set가동개시_시작_일] = useState(''); const [가동개시_종료_일, set가동개시_종료_일] = useState(''); + const [fromDate, setFromDate] = useState(() => { const date = new Date(); date.setDate(date.getDate() - 7); return date }) + const [toDate, setToDate] = useState(new Date()) // 로딩바 const [isLoading, setIsLoading] = useState(false); @@ -142,7 +144,7 @@ const SearchModal: React.FC = ({ else if (basicType === 'tb_il_swage_prcs_fclt') dynamicHeadlist = SwtrmtFcltCol2; // 하수처리시설 else if (basicType === 'tb_ms_swage_prcs_zone') dynamicHeadlist = SwtrmtPrcsZoneCol2; // 하수처리구역 else if (basicType === 'tb_ms_swage_mhl') dynamicHeadlist = MsSwageMhlCol2; // 하수맨홀 - else if (basicType === 'tb_ms_swage_pmstn') dynamicHeadlist = SewagePump2; // 하수펌프장 + else if (basicType === 'tb_ms_swage_pmstn') dynamicHeadlist = ExclnSewagePumpCol2; // 하수펌프장 else if (basicType === 'tb_ms_stofcbr') dynamicHeadlist = stofcbrCol2; // 우수토실 // 조회 버튼 클릭 시 1페이지로 이동하도록 수정 @@ -948,8 +950,8 @@ const SearchModal: React.FC = ({ value={workType} /> - {/* 설치년도 */} - @@ -959,8 +961,29 @@ const SearchModal: React.FC = ({ 종료: range.end, }) } - startLabel="설치년도" + startLabel="수행기간" endLabel="" + /> */} + { if (date) setFromDate(date) }} + modifiers={{ + disabled: { after: new Date() } + }} + zIndex={102} + /> + ~ + { if (date) setToDate(date) }} + modifiers={{ + disabled: { after: new Date() } + }} + zIndex={102} />
{/* 경과년도 */} diff --git a/apps/sn/app/(map-layout)/map/components/InputSection.tsx b/apps/sn/app/(map-layout)/map/components/InputSection.tsx index fe8897703..209361293 100644 --- a/apps/sn/app/(map-layout)/map/components/InputSection.tsx +++ b/apps/sn/app/(map-layout)/map/components/InputSection.tsx @@ -20,14 +20,14 @@ const InputSection: React.FC = ({ title, data, sectionKey, on
- 년도 - 구분 + 년도 + 구분 {data.map((row, index) => ( - + = ({ title, data, sectionKey, on className="w-full text-xl border-radius-0 px-3 py-2 text-base text-center leading-normal" /> - + {row.type} diff --git a/apps/sn/app/(map-layout)/map/components/common/table.ts b/apps/sn/app/(map-layout)/map/components/common/table.ts index 1747106cc..f114cf97b 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -1,65 +1,65 @@ // 하수관로 export const MsSwagePplCol = [ - { id: 'avg_grdn', title: '평균구배' }, - { id: 'clar_fvlc', title: '맑음유속' }, - { id: 'drtw_mltv_area', title: '오수배수면적' }, - { id: 'excln_mltv_area', title: '우수배수면적' }, { id: 'fclt_mng_no', title: '시설관리번호' }, - // { id: 'fclty_shp_cd', title: '시설물형태코드' }, - // { id: 'fid', title: 'FID' }, - // { id: 'ftre_smbol_cd', title: '지형지물부호코드' }, { id: 'inst_mng_no', title: '기관관리번호' }, { id: 'instl_ymd', title: '설치일자' }, { id: 'mapsht_no', title: '도엽번호' }, - // { id: 'mng_inst_cd', title: '관리기관코드' }, - // { id: 'mqlt_cd', title: '재질코드' }, - // { id: 'pbadms_emd_cd', title: '행정읍면동코드' }, - { id: 'pdmt', title: '관경' }, - { id: 'prlg', title: '연장' }, - { id: 'rnyssn_fvlc', title: '우기유속' }, - { id: 'scend_dpth', title: '종점깊이' }, - { id: 'scend_mhl_mng_no', title: '종점맨홀관리번호' }, - { id: 'tmpt_dpth', title: '시점깊이' }, + { id: 'pdmt', title: '관경(mm)' }, + { id: 'prlg', title: '연장(m)' }, + { id: 'usg_cd', title: '용도코드' }, + { id: 'mqlt_cd', title: '재질코드' }, + { id: 'avg_grdn', title: '평균구배(m/m)' }, + { id: 'drtw_mltv_area', title: '오수배수면적(m²)' }, + { id: 'excln_mltv_area', title: '우수배수면적(m²)' }, + { id: 'tmpt_dpth', title: '시점깊이(m)' }, { id: 'tmpt_mhl_mng_no', title: '시점맨홀관리번호' }, + { id: 'scend_dpth', title: '종점깊이(m)' }, + { id: 'scend_mhl_mng_no', title: '종점맨홀관리번호' }, { id: 'trfln_cnt', title: '차선수' }, - // { id: 'usg_cd', title: '용도코드' }, - { id: 'vrtc_len', title: '세로길이' }, - { id: 'wdth_len', title: '가로길이' }, + { id: 'vrtc_len', title: '세로길이(m)' }, + { id: 'wdth_len', title: '가로길이(m)' }, + // { id: 'rnyssn_fvlc', title: '우기 시 유속(m/s)' }, + // { id: 'clar_fvlc', title: '건기 시 유속(m/s)' }, + // { id: 'mng_inst_cd', title: '관리기관코드' }, + // { id: 'pbadms_emd_cd', title: '행정읍면동코드' }, + // { id: 'fclty_shp_cd', title: '시설물형태코드' }, + // { id: 'fid', title: 'FID' }, + // { id: 'ftre_smbol_cd', title: '지형지물부호코드' }, // { id: 'lyrTypeNm', title: '레이어타입명' }, ] export const MsSwagePplCol2 = [ - { id: 'avgGrdn', title: '평균구배' }, - { id: 'clarFvlc', title: '맑음유속' }, - { id: 'drtwMltvArea', title: '오수배수면적' }, - { id: 'exclnMltvArea', title: '우수배수면적' }, { id: 'fcltMngNo', title: '시설관리번호' }, - // { id: 'fcltyShpCd', title: '시설물형태코드' }, - // { id: 'fid', title: 'FID' }, - // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, { id: 'instMngNo', title: '기관관리번호' }, { id: 'instlYmd', title: '설치일자' }, { id: 'mapshtNo', title: '도엽번호' }, + { id: 'pdmt', title: '관경(mm)' }, + { id: 'prlg', title: '연장(m)' }, + { id: 'avgGrdn', title: '평균구배(m/m)' }, + { id: 'rnysnFvlc', title: '우기 시 유속(m/s)' }, + { id: 'clarFvlc', title: '건기 시 유속(m/s)' }, + { id: 'drtwMltvArea', title: '오수배수면적(m²)' }, + { id: 'exclnMltvArea', title: '우수배수면적(m²)' }, + { id: 'tmptDpth', title: '시점깊이(m)' }, + { id: 'tmptMhlMngNo', title: '시점맨홀관리번호' }, + { id: 'scendDpth', title: '종점깊이(m)' }, + { id: 'scendMhlMngNo', title: '종점맨홀관리번호' }, + { id: 'trflnCnt', title: '차선수' }, + { id: 'vrtcLen', title: '세로길이(m)' }, + { id: 'wdthLen', title: '가로길이(m)' }, + // { id: 'fcltyShpCd', title: '시설물형태코드' }, + // { id: 'fid', title: 'FID' }, + // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, // { id: 'mngInstCd', title: '관리기관코드' }, // { id: 'mqltCd', title: '재질코드' }, // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, - { id: 'pdmt', title: '관경' }, - { id: 'prlg', title: '연장' }, - // { id: 'rnysnFvlc', title: '우기유속' }, - { id: 'scendDpth', title: '종점깊이' }, - { id: 'scendMhlMngNo', title: '종점맨홀관리번호' }, - { id: 'tmptDpth', title: '시점깊이' }, - { id: 'tmptMhlMngNo', title: '시점맨홀관리번호' }, - { id: 'trflnCnt', title: '차선수' }, // { id: 'usgCd', title: '용도코드' }, - { id: 'vrtcLen', title: '세로길이' }, - { id: 'wdthLen', title: '가로길이' }, // { id: 'lyrTypeNm', title: '레이어타입명' }, ] // 하수처리시설 export const SwtrmtFcltCol = [ { id: 'swtrmt_fclt_nm', title: '하수처리시설명' }, - { id: 'fclt_cpct', title: '시설용량' }, + { id: 'fclt_cpct', title: '시설용량(㎥/d)' }, { id: 'rgn_expln', title: '지역설명' }, { id: 'cmcn_ymd', title: '준공일자' }, { id: 'oprtng_strt_ymd', title: '가동개시일자' }, @@ -78,26 +78,26 @@ export const SwtrmtFcltCol = [ { id: 'rdnm_addr', title: '도로명주소' }, { id: 'dtl_rdnm_addr', title: '상세도로명주소' }, { id: 'dschg_wtst_nm', title: '방류수계명' }, - { id: 'plln_area', title: '부지면적' }, + { id: 'plln_area', title: '부지면적(m²)' }, { id: 'mng_rprtv_bzenty_nm', title: '관리대행업제명' }, - { id: 'swtrmt_ppltn_cnt', title: '하수처리인구수' }, - { id: 'prcs_zone_area_sum', title: '처리구역면적합계' }, + { id: 'swtrmt_ppltn_cnt', title: '하수처리인구수(인)' }, + { id: 'prcs_zone_area_sum', title: '처리구역면적합계(m²)' }, { id: 'xcrd', title: 'X좌표' }, { id: 'ycrd', title: 'Y좌표' }, // { id: 'oprtngSttsCd', title: '가동상태코드' }, { id: 'rprs_msrc_cn', title: '대표공법내용' }, - { id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량' }, - { id: 'stty_crtr_toc', title: '법정기준TOC' }, - { id: 'stty_crtr_ss', title: '법정기준SS' }, - { id: 'stty_crtr_tn', title: '법정기준총질소' }, - { id: 'stty_crtr_tph', title: '법정기준총인' }, - { id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수' }, + { id: 'stty_crtr_bod', title: '법정기준생물화학적산소요구량(mg/L)' }, + { id: 'stty_crtr_toc', title: '법정기준TOC((mg/L))' }, + { id: 'stty_crtr_ss', title: '법정기준SS(mg/L)' }, + { id: 'stty_crtr_tn', title: '법정기준총질소(mg/L)' }, + { id: 'stty_crtr_tph', title: '법정기준총인(mg/L)' }, + { id: 'stty_crtr_clbcl_cnt', title: '법정기준대장균수(군수/100mL)' }, { id: 'bsn_nm', title: '유역명' }, // { id: 'obsrvnSptCd', title: '관측지점코드' }, ]; export const SwtrmtFcltCol2 = [ { id: 'swtrmtFcltNm', title: '하수처리시설명' }, - { id: 'fcltCpct', title: '시설용량' }, + { id: 'fcltCpct', title: '시설용량(㎥/d)' }, { id: 'rgnExpln', title: '지역설명' }, { id: 'cmcnYmd', title: '준공일자' }, { id: 'oprtngStrtYmd', title: '가동개시일자' }, @@ -116,20 +116,20 @@ export const SwtrmtFcltCol2 = [ { id: 'rdnmAddr', title: '도로명주소' }, { id: 'dtlRdnmAddr', title: '상세도로명주소' }, { id: 'dschgWtstNm', title: '방류수계명' }, - { id: 'pllnArea', title: '부지면적' }, + { id: 'pllnArea', title: '부지면적(m²)' }, { id: 'mngRprtvBzentyNm', title: '관리대행업제명' }, - { id: 'swtrmtPpltnCnt', title: '하수처리인구수' }, - { id: 'prcsZoneAreaSum', title: '처리구역면적합계' }, + { id: 'swtrmtPpltnCnt', title: '하수처리인구수(인)' }, + { id: 'prcsZoneAreaSum', title: '처리구역면적합계(m²)' }, { id: 'xcrd', title: 'X좌표' }, { id: 'ycrd', title: 'Y좌표' }, // { id: 'oprtngSttsCd', title: '가동상태코드' }, { id: 'rprsMsrcCn', title: '대표공법내용' }, - { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량' }, - { id: 'sttyCrtrToc', title: '법정기준TOC' }, - { id: 'sttyCrtrSs', title: '법정기준SS' }, - { id: 'sttyCrtrTn', title: '법정기준총질소' }, - { id: 'sttyCrtrTph', title: '법정기준총인' }, - { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수' }, + { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량(mg/L)' }, + { id: 'sttyCrtrToc', title: '법정기준TOC(mg/L)' }, + { id: 'sttyCrtrSs', title: '법정기준SS(mg/L)' }, + { id: 'sttyCrtrTn', title: '법정기준총질소(mg/L)' }, + { id: 'sttyCrtrTph', title: '법정기준총인(mg/L)' }, + { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수(군수/100mL)' }, { id: 'bsnNm', title: '유역명' }, // { id: 'obsrvnSptCd', title: '관측지점코드' }, ]; @@ -170,14 +170,14 @@ export const MsSwageMhlCol = [ // { id: 'usg_cd', title: '용도코드' }, // { id: 'fclty_shp_cd', title: '시설물형태코드' }, // { id: 'mhl_knd_cd', title: '맨홀종류코드' }, - { id: 'swage_mh_diam', title: '하수맨홀구경' }, - { id: 'wdth_len', title: '가로길이' }, - { id: 'vrtc_len', title: '세로길이' }, - // { id: 'mqltCd', title: '재질코드' }, + { id: 'swage_mh_diam', title: '하수맨홀구경(mm)' }, + { id: 'mqlt_cd', title: '재질코드' }, + { id: 'wdth_len', title: '가로길이(m)' }, + { id: 'vrtc_len', title: '세로길이(m)' }, // { id: 'ang_dir', title: '표고' }, - { id: 'altd_vl', title: '표고' }, - { id: 'dpthlVl', title: '심도' }, - // { id: 'instMngNo', title: '기관관리번호' } + { id: 'altd_vl', title: '표고(EL.m)' }, + { id: 'dpthlVl', title: '심도(m)' }, + // { id: 'inst_mng_no', title: '기관관리번호' } ]; export const MsSwageMhlCol2 = [ // { id: 'fid', title: 'FID' }, @@ -192,18 +192,81 @@ export const MsSwageMhlCol2 = [ // { id: 'usgCd', title: '용도코드' }, // { id: 'fcltyShpCd', title: '시설물형태코드' }, // { id: 'mhlKndCd', title: '맨홀종류코드' }, - { id: 'swageMhDiam', title: '하수맨홀구경' }, - { id: 'wdthLen', title: '가로길이' }, - { id: 'vrtcLen', title: '세로길이' }, - // { id: 'mqltCd', title: '재질코드' }, + { id: 'swageMhDiam', title: '하수맨홀구경(mm)' }, + { id: 'mqltCd', title: '재질코드' }, + { id: 'wdthLen', title: '가로길이(m)' }, + { id: 'vrtcLen', title: '세로길이(m)' }, // { id: 'angDir', title: '표고' }, - { id: 'altdVl', title: '표고' }, - { id: 'dpthlVl', title: '심도' }, + { id: 'altdVl', title: '표고(EL.m)' }, + { id: 'dpthlVl', title: '심도(m)' }, // { id: 'instMngNo', title: '기관관리번호' } ]; +// 하수맨홀 뚜껑재질 코드표 +export const MS_SWAGE_MHL_CODES = [ + { val: "SBC000", text: "미분류" }, + { val: "SBC001", text: "주철" }, + { val: "SBC002", text: "철판" }, + { val: "SBC003", text: "콘크리트" }, + { val: "SBC004", text: "그레이팅" }, + { val: "SBC091", text: "칼라" }, + { val: "SBC092", text: "S.G" }, + { val: "SBC999", text: "기타" }, + { val: "SBC900", text: "각주철" }, + { val: "SBC901", text: "강재" }, + { val: "SBC902", text: "나무" }, + { val: "SBC903", text: "나무,널판지,합판" }, + { val: "SBC904", text: "대리석" }, + { val: "SBC905", text: "뚜껑없음" }, + { val: "SBC906", text: "보도용콘크리트" }, + { val: "SBC907", text: "스틸(ST)" }, + { val: "SBC908", text: "신형 CON" }, + { val: "SBC909", text: "알루미늄" }, + { val: "SBC910", text: "염화비닐(PE)" }, + { val: "SBC911", text: "인조석" }, + { val: "SBC912", text: "인조석(주철)" }, + { val: "SBC913", text: "인조CONC" }, + { val: "SBC914", text: "철, 철근" }, + { val: "SBC915", text: "칼라콘크리트" }, + { val: "SBC916", text: "플라스틱" }, + { val: "SBC917", text: "PVC" }, + { val: "SBC918", text: "SP" }, + { val: "SBC919", text: "SS" }, + { val: "SBC920", text: "닥타일주철" }, + { val: "SBC921", text: "철근G" }, + { val: "SBC922", text: "폴리에틸렌(PE)" }, + { val: "SBC923", text: "회주철" } +]; +// 하수맨홀 용도 코드표 +export const MS_SWAGE_MHL_USE_CODES = [ + { val: "SMU000", text: "미분류" }, + { val: "SMU001", text: "우수" }, + { val: "SMU002", text: "오수" }, + { val: "SMU003", text: "집수" }, + { val: "SMU004", text: "합류" }, + { val: "SMU005", text: "차집" }, + { val: "SMU999", text: "기타" }, + { val: "SMU900", text: "1호" }, + { val: "SMU901", text: "2호" }, + { val: "SMU902", text: "3호" }, + { val: "SMU903", text: "4호" }, + { val: "SMU904", text: "5호" }, + { val: "SMU905", text: "6호" }, + { val: "SMU906", text: "7호" }, + { val: "SMU907", text: "8호" }, + { val: "SMU908", text: "구거용맨홀" }, + { val: "SMU909", text: "부관부착맨홀" }, + { val: "SMU910", text: "조립식맨홀" }, + { val: "SMU911", text: "특1호" }, + { val: "SMU912", text: "특2호" }, + { val: "SMU913", text: "특3호" }, + { val: "SMU914", text: "특4호" }, + { val: "SMU915", text: "특5호" }, + { val: "SMU916", text: "하수맨홀용도" }, + { val: "SMU917", text: "현장타설관거용" } +]; -// 하수펌프장 -export const SewagePump = [ +// 우수펌프장 +export const ExclnSewagePumpCol = [ // { id: 'fid', title: 'FID' }, // { id: 'geom', title: 'geometry' }, // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, @@ -213,17 +276,17 @@ export const SewagePump = [ // { id: 'mngInstCd', title: '관리기관코드' }, { id: 'instl_ymd', title: '설치일자' }, { id: 'swage_pmstn_nm', title: '하수펌프장명' }, - { id: 'plln_area', title: '부지면적' }, - // { id: 'opngSttsCd', title: '개통상태코드' }, + { id: 'plln_area', title: '부지면적(m²)' }, + // { id: 'opngSttsCd', title: '개통상태코드' }, // { id: 'usgCd', title: '용도코드' }, - { id: 'daily_prcs_cpct', title: '일일처리용량' }, - { id: 'max_impnd_cpct', title: '최대저수용량' }, - { id: 'altd_vl', title: '표고' }, - { id: 'wtlv_vl', title: '수위' }, - { id: 'excln_wpmp_ablt', title: '우수양수능력' }, + { id: 'daily_prcs_cpct', title: '일일처리용량(㎥)' }, + { id: 'max_impnd_cpct', title: '최대저수용량(㎥)' }, + { id: 'altd_vl', title: '표고(EL.m)' }, + { id: 'wtlv_vl', title: '수위(m)' }, + { id: 'excln_wpmp_ablt', title: '우수양수능력(m²/d)' }, // { id: 'instMngNo', title: '기관관리번호' }, ] -export const SewagePump2 = [ +export const ExclnSewagePumpCol2 = [ // { id: 'fid', title: 'FID' }, // { id: 'geom', title: 'geometry' }, // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, @@ -233,14 +296,56 @@ export const SewagePump2 = [ // { id: 'mngInstCd', title: '관리기관코드' }, { id: 'instlYmd', title: '설치일자' }, { id: 'swagePmstnNm', title: '하수펌프장명' }, - { id: 'pllnArea', title: '부지면적' }, + { id: 'pllnArea', title: '부지면적(m²)' }, // { id: 'opngSttsCd', title: '개통상태코드' }, // { id: 'usgCd', title: '용도코드' }, - { id: 'dailyPrcsCpct', title: '일일처리용량' }, - // { id: 'max_impndCpct', title: '최대저수용량' }, - { id: 'altdVl', title: '표고' }, - { id: 'wtlvVl', title: '수위' }, - { id: 'exclnWpmpAblt', title: '우수양수능력' }, + { id: 'dailyPrcsCpct', title: '일일처리용량(㎥)' }, + { id: 'max_impndCpct', title: '최대저수용량(㎥)' }, + { id: 'altdVl', title: '표고(EL.m)' }, + { id: 'wtlvVl', title: '수위(m)' }, + { id: 'exclnWpmpAblt', title: '우수양수능력(m²/d)' }, + // { id: 'instMngNo', title: '기관관리번호' }, +] + +// 오수펌프장 +export const DrtwSewagePumpCol1 = [ + // { id: 'fid', title: 'FID' }, + // { id: 'geom', title: 'geometry' }, + // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, + { id: 'fclt_mng_no', title: '시설관리번호' }, + // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, + { id: 'mapsht_no', title: '도엽번호' }, + // { id: 'mngInstCd', title: '관리기관코드' }, + { id: 'instl_ymd', title: '설치일자' }, + { id: 'swage_pmstn_nm', title: '하수펌프장명' }, + { id: 'plln_area', title: '부지면적(m²)' }, + // { id: 'opngSttsCd', title: '개통상태코드' }, + // { id: 'usgCd', title: '용도코드' }, + { id: 'daily_prcs_cpct', title: '일일처리용량(㎥)' }, + { id: 'max_impnd_cpct', title: '최대저수용량(㎥)' }, + { id: 'altd_vl', title: '표고(EL.m)' }, + { id: 'wtlv_vl', title: '수위(m)' }, + { id: 'excln_wpmp_ablt', title: '오수양수능력(m²/d)' }, + // { id: 'instMngNo', title: '기관관리번호' }, +] +export const DrtwSewagePumpCol2 = [ + // { id: 'fid', title: 'FID' }, + // { id: 'geom', title: 'geometry' }, + // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, + { id: 'fcltMngNo', title: '시설관리번호' }, + // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, + { id: 'mapshtNo', title: '도엽번호' }, + // { id: 'mngInstCd', title: '관리기관코드' }, + { id: 'instlYmd', title: '설치일자' }, + { id: 'swagePmstnNm', title: '하수펌프장명' }, + { id: 'pllnArea', title: '부지면적(m²)' }, + // { id: 'opngSttsCd', title: '개통상태코드' }, + // { id: 'usgCd', title: '용도코드' }, + { id: 'dailyPrcsCpct', title: '일일처리용량(㎥)' }, + { id: 'max_impndCpct', title: '최대저수용량(㎥)' }, + { id: 'altdVl', title: '표고(EL.m)' }, + { id: 'wtlvVl', title: '수위(m)' }, + { id: 'exclnWpmpAblt', title: '오수양수능력(m²/d)' }, // { id: 'instMngNo', title: '기관관리번호' }, ] @@ -253,11 +358,11 @@ export const stofcbrCol = [ // { id: 'mng_inst_cd', title: '관리기관코드' }, { id: 'instl_ymd', title: '설치일자' }, // { id: 'fclty_shp_cd', title: '시설물형태코드' }, - { id: 'worflw_wall_hgt', title: '월류벽높이' }, + { id: 'worflw_wall_hgt', title: '월류벽높이(m)' }, // { id: 'mhl_exst_yn_cd', title: '맨홀존재여부코드' }, // { id: 'swage_mhl_ftre_smbol_cd', title: '하수맨홀지형지물부호코드' }, { id: 'swage_mhl_mng_no', title: '하수맨홀관리번호' }, - { id: 'drtn_angl', title: '방향각도' }, + { id: 'drtn_angl', title: '방향각도(°)' }, ] export const stofcbrCol2 = [ // { id: 'ftre_smbol_cd', title: '지형지물부호코드' }, @@ -267,11 +372,11 @@ export const stofcbrCol2 = [ // { id: 'mng_inst_cd', title: '관리기관코드' }, { id: 'instlYmd', title: '설치일자' }, // { id: 'fclty_shp_cd', title: '시설물형태코드' }, - { id: 'worflwWallHgt', title: '월류벽높이' }, + { id: 'worflwWallHgt', title: '월류벽높이(m)' }, // { id: 'mhl_exst_yn_cd', title: '맨홀존재여부코드' }, // { id: 'swage_mhl_ftre_smbol_cd', title: '하수맨홀지형지물부호코드' }, { id: 'swageMhlMngNo', title: '하수맨홀관리번호' }, - { id: 'drtnAngl', title: '방향각도' }, + { id: 'drtnAngl', title: '방향각도(°)' }, ] // 중점우수토실 측정지점 @@ -287,7 +392,7 @@ export const untrtSwgRainCol1 = [ // 중점우수토실 측정지점 시설현황 export const untrtSwgRainCol2 = [ { id: 'flwmtr_mesure_tp_etc', title: '구분' }, - { id: 'discharge_pipe_spec', title: '방류관로 규격' }, + { id: 'discharge_pipe_spec', title: '방류관로 규격(m)' }, { id: 'swr_ppl_eqp_ar', title: '배수구역 면적(m²)' }, { id: 'swr_trt_popl', title: '하수처리 인구(인)' }, { id: 'screen_instl_at', title: '스크린설치 여부' }, diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx index 46537a7dd..26b3a60aa 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx @@ -7,7 +7,7 @@ import { handleInputChange } from '../common'; // 하수관로 const inputColumn = [ { id: "title", title: "설치주제", type: "select", options: ["BTL", "재정사업"] }, - { id: "swtrmt_zone_cd", title: "처리구역", type: "select", options: ["구역1", "구역2"] }, + { id: "swtrmt_zone_cd", title: "처리구역", type: "input" }, { id: "basu", title: "배수구역", type: "input" }, { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, { id: "wltjs", title: "지선/간선", type: "select", options: ["지선", "간선"] }, diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx index 7e22ea03b..31aef5172 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx @@ -3,12 +3,19 @@ import { UiModal, UiTable } from '@common/business_components/ui'; import { Button, TableHead, TableRow } from '@common/components/ui'; import React, { useState } from 'react'; import { untrtSwgRainCol3, untrtSwgRainCol4, untrtSwgRainCol5 } from '../common/table'; +import { VerticalTable } from '@/components/ui/verticalTable'; import LoadingOverlay from '@/components/ui/LoadingBar'; -const Ssc = ({ featureData, chkMainSsc, additionalData }: { +const inputColumn = [ + { id: "place", title: "중점여부", type: "select", options: ["중점우수토실", "우수토실"] }, + { id: "guyeok", title: "처리구역", type: "input" }, +]; + +const Ssc = ({ featureData, chkMainSsc, additionalData, onSaveClick }: { featureData: any, chkMainSsc?: boolean, - additionalData?: any + additionalData?: any, + onSaveClick?: () => void }) => { const [isModalOpen, setIsModalOpen] = useState(false); const [isDataLoaded, setIsDataLoaded] = useState(false); @@ -93,7 +100,7 @@ const Ssc = ({ featureData, chkMainSsc, additionalData }: { return (
- {/* */} + showSaveButton={true} + onSaveClick={onSaveClick} + /> {chkMainSsc && (
diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx index 4eaf1f18d..f0c4d21b3 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx @@ -1,17 +1,22 @@ import { VerticalTable } from '@/components/ui/verticalTable'; import React from 'react' -const inputColumn = [ - { id: "swtrmt_zone_cd", title: "처리구역", type: "select", options: ["구역1", "구역2"] }, +const exclnInputColumn = [ + { id: "swtrmt_zone_cd", title: "배수구역", type: "input" }, { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, - { id: "freq", title: "설계빈도", type: "input" }, + { id: "freq", title: "설계빈도(년)", type: "input" }, ] +const drtwInputColumn = [ + { id: "swtrmt_zone_cd", title: "배수구역", type: "input" }, + { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, +] + // 하수펌프장 const sewagePump = ({ featureData, onSaveClick }: { featureData: any, onSaveClick?: () => void }) => { return ( void }) => { return ( diff --git a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx index 16c4f99a8..72831902f 100644 --- a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx @@ -6,7 +6,7 @@ import { useGisContext } from "@common/business_components/ui/map/Gis"; import { Button } from "@common/components/ui"; import { useEffect, useRef, useState, useCallback, useMemo } from "react"; import { getLayerContentComponent } from "./components/common"; -import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, SewagePump, MsSwageMhlCol, stofcbrCol } from "./components/common/table"; +import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, ExclnSewagePumpCol, MsSwageMhlCol, stofcbrCol, MS_SWAGE_MHL_CODES } from "./components/common/table"; import InfilChart from './components/popupComponent/chart/infilChart'; import RdiiChart from './components/popupComponent/chart/rdiiChart'; import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore"; @@ -29,8 +29,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, const [isAdditionalDataLoading, setIsAdditionalDataLoading] = useState(false); const [additionalDataError, setAdditionalDataError] = useState(null); // 🎯 InfilChart 및 RdiiChart 관련 상태 추가 - const { setIsOpen:setIsModalInfil } = useInfilChartModalStore(); - const { setIsOpen:setIsModalRdii } = useRdiiChartModalStore(); + const { setIsOpen: setIsModalInfil } = useInfilChartModalStore(); + const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore(); // 🎯 관로관리번호 추출 const pplMngNo = featureData?.values_?.fclt_mng_no || ""; @@ -135,8 +135,27 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, console.log('gis data', featureData.values_); let data = featureData.values_; - setfetchData(data) - setTableData(data); + + // 하수맨홀인 경우 용도코드를 텍스트로 변환 + if (selectedLayerName === '하수맨홀' && data) { + const processedData = { ...data }; + + // mqlt_cd 값 변환 (재질코드) + if (processedData.mqlt_cd) { + const materialCodeItem = MS_SWAGE_MHL_CODES.find( + code => code.val === processedData.mqlt_cd.trim() + ); + if (materialCodeItem) { + processedData.mqlt_cd = `${materialCodeItem.text}`; + } + } + + setfetchData(processedData); + setTableData(processedData); + } else { + setfetchData(data); + setTableData(data); + } switch (selectedLayerName) { case '하수처리시설': @@ -173,6 +192,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, case '우수토실': setHeadlist(stofcbrCol) setButtonChk(false) + setChkMainSsc(false) break; case '하수관로': setHeadlist(MsSwagePplCol) @@ -185,7 +205,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // setButtonChk(true) // break; case '하수펌프장': - setHeadlist(SewagePump) + setHeadlist(ExclnSewagePumpCol) setButtonChk(true) break; case '하수맨홀': @@ -237,32 +257,41 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, setIsModalOpen(false); // 모달 닫기 }; + // 저장 버튼 이벤트 const btnClickEvent = async () => { const bodyData: Record = {} + if (buttonChk && contentRef.current) { const inputElements = contentRef.current.querySelectorAll('input'); const selectElements = contentRef.current.querySelectorAll('select'); + // 카멜케이스 변환 함수 const toCamelCase = (str: string) => str.replace(/_([a-z])/g, (_, char) => char.toUpperCase()); + // select 태그의 값 가져오기 selectElements.forEach((select) => { const camelCaseId = toCamelCase(select.id); bodyData[camelCaseId] = select.value; }); + // input 태그의 값 가져오기 inputElements.forEach((input) => { const camelCaseId = toCamelCase(input.id); bodyData[camelCaseId] = input.value; }); + if (layerNm === '하수관로') bodyData['lyrTypeNm'] = 'tb_ms_swage_ppl' else if (layerNm === '우수토실') bodyData['lyrTypeNm'] = 'tb_ms_stofcbr' else if (layerNm === '중점우수토실') bodyData['lyrTypeNm'] = 'om_dt_untrt_swg_rain' else if (layerNm === '오수펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn' else if (layerNm === '빗물펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn' else if (layerNm === '하수맨홀') bodyData['lyrTypeNm'] = 'tb_ms_swage_mnhl' + bodyData['fid'] = featureId + const data = await putData(`v1/fclts/${featureId}`, bodyData); + if (data.status == 200) { alert('저장되었습니다') setTableData(data) @@ -286,13 +315,13 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, {/* 🎯 하수관로일 때만 Infil/RDII 버튼 표시 */} {layerNm === '하수관로' && ( <> - -
) } diff --git a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx index 6ae0b3609..3578ff967 100644 --- a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx @@ -27,16 +27,16 @@ const Page = () => { const [curPage, setCurPage] = useState(1) //현재 페이지 const [totalData, setTotalData] = useState(0) //총 데이터 수 const [isLoading, setIsLoading] = useState(true) //로딩 상태 + + // 조회 const fetchData = async () => { setIsLoading(true) - searchCmmnCd('SITEKNDCD') + // searchCmmnCd('SITEKNDCD') try { const { data, total } = await searchData('v1/sbmrgPrevnt', { fromRegDt: formatDate(fromDate), - fromMngYr: manageYear, - toMngYr: mngQu, toRegDt: formatDate(toDate), - atflNm: pjNm, + sbmrgPrevntBizNm: pjNm, rgtrNm: usr, page: curPage - 1, size: '10' @@ -45,12 +45,18 @@ const Page = () => { setTotalData(total) } catch (error) { console.error('Error fetching data:', error) } - finally { setIsLoading(false); } + finally { + setFileNm(''); + setAtflId(''); + setSbmrgPrevntBizSn(''); + setIsLoading(false); + } } useEffect(() => { setCurPage(1) fetchData() }, []) + // 파일 다운로드 const isChckFile = () => { if (fileNm === '' || fileNm === undefined) { @@ -59,6 +65,7 @@ const Page = () => { } handleDownload(`/attach-service/api/v1/download/${atflId}`, fileNm) } + // 선택 파일 삭제 const isDeleteFile = async () => { if (sbmrgPrevntBizSn === '' || sbmrgPrevntBizSn === undefined) { @@ -96,11 +103,19 @@ const Page = () => { { if (date) setFromDate(date) }} /> + onSelect={(date: Date | undefined) => { if (date) setFromDate(date) }} + modifiers={{ + disabled: { after: new Date() } + }} + /> ~ { if (date) setToDate(date) }} /> + onSelect={(date: Date | undefined) => { if (date) setToDate(date) }} + modifiers={{ + disabled: { after: new Date() } + }} + />
@@ -132,7 +147,23 @@ const Page = () => {
- { if (index != null) { const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn); } }} onPageChange={async (page: number) => { setCurPage(page); await fetchData() }}> + { + if (index != null) { + const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; + const id = tableData[index]?.atflId ?? ''; + setFileNm(fileName); + setAtflId(id); + setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn); + } + }} + onPageChange={async (page: number) => { setCurPage(page); await fetchData() }} + /> { await registFile(file, year, quater, cd, id) }} /> diff --git a/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx b/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx index 307452e2d..c4bac35b7 100644 --- a/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/oldPp/page.tsx @@ -25,14 +25,13 @@ const Page = () => { const [curPage, setCurPage] = useState(1) const [totalData, setTotalData] = useState(0) //총 데이터 수 const [isLoading, setIsLoading] = useState(true) //로딩 상태 + // 데이터 조회 const fetchData = async () => { setIsLoading(true) try { const { data, total } = await searchData('v1/dcrpPpl', { fromRegDt: formatDate(fromDate), - fromMngYr: manageYear, - toMngYr: mngQu, toRegDt: formatDate(toDate), dcrpPplMtncBizNm: pjNm, rgtrNm: usr, @@ -44,12 +43,18 @@ const Page = () => { console.log(data, total) } catch (error) { console.error('Error fetching data:', error) - } finally { setIsLoading(false) } + } finally { + setFileNm(''); + setAtflId(''); + setDcrpPplMtncBizSn(''); + setIsLoading(false) + } } useEffect(() => { setCurPage(1) fetchData() }, []) + // 파일 다운로드 const isChckFile = () => { if (fileNm === '' || fileNm === undefined) { @@ -59,6 +64,7 @@ const Page = () => { handleDownload(`/attach-service/api/v1/download/${atflId}`, fileNm) return true } + // 파일 삭제 const isDeleteFile = async () => { if (dcrpPplMtncBizSn === '' || dcrpPplMtncBizSn === undefined) { @@ -76,6 +82,7 @@ const Page = () => { } } } + // 파일 등록 const registFile = async (fileNm: string, year: string, quater: string, cd: string, id: string) => { const data = await postData('v1/dcrpPpl', { @@ -88,6 +95,8 @@ const Page = () => { }) if (data) { alert('파일이 등록되었습니다.'); fetchData() } } + + return ( <> @@ -98,11 +107,17 @@ const Page = () => { { if (date) setFromDate(date) }} /> + onSelect={(date: Date | undefined) => { if (date) setFromDate(date) }} + modifiers={{ + disabled: { after: new Date() } + }} /> ~ { if (date) setToDate(date) }} /> + onSelect={(date: Date | undefined) => { if (date) setToDate(date) }} + modifiers={{ + disabled: { after: new Date() } + }} />
{
- { if (index != null) { const fileName = tableData[index]?.dcrpPplMtncBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setDcrpPplMtncBizSn(tableData[index]?.dcrpPplMtncBizSn) } }} onPageChange={async (page: number) => { setCurPage(page); await fetchData() }}> + { + if (index != null) { + const fileName = tableData[index]?.dcrpPplMtncBizNm ?? ""; + const id = tableData[index]?.atflId ?? ''; + setFileNm(fileName); + setAtflId(id); + setDcrpPplMtncBizSn(tableData[index]?.dcrpPplMtncBizSn); + } + }} + onPageChange={async (page: number) => { setCurPage(page); await fetchData() }} + />
{ await registFile(file, year, quater, cd, id) }} /> diff --git a/apps/sn/app/components/ui/fileUploadForm.tsx b/apps/sn/app/components/ui/fileUploadForm.tsx index 3cd663e01..fb626348e 100644 --- a/apps/sn/app/components/ui/fileUploadForm.tsx +++ b/apps/sn/app/components/ui/fileUploadForm.tsx @@ -29,6 +29,8 @@ const FileUploadForm = ({ const [files, setFiles] = useState(null); const [upload, setUpload] = useState(null); const uniqueId = useId(); // 각 FileUploadForm 인스턴스에 대한 고유 ID 생성 + // FileUploader 컴포넌트를 강제로 재마운트하기 위한 key 상태 추가 + const [uploaderKey, setUploaderKey] = useState(0); const quater = [{ text: '1분기', val: '1' }, { text: '2분기', val: '2' }, { text: '3분기', val: '3' }, { text: '4분기', val: '4' }]; // 현재 년도부터 10년 전까지의 년도 옵션 생성 @@ -64,6 +66,7 @@ const FileUploadForm = ({
{/* FileUploader와 Button을 정렬하는 메인 flex 컨테이너 */}
{/* FileUploader의 너비와 오른쪽 여백을 제어하는 컨테이너 */} prev + 1); } }} > diff --git a/apps/sn/app/components/ui/verticalTable.tsx b/apps/sn/app/components/ui/verticalTable.tsx index 1455c9e4a..19e302c30 100644 --- a/apps/sn/app/components/ui/verticalTable.tsx +++ b/apps/sn/app/components/ui/verticalTable.tsx @@ -141,7 +141,7 @@ export function VerticalTable({ handleInputChange(head.id, e.target.value)} className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1" /> diff --git a/packages/common/business_components/src/ui/chart/BarChart.tsx b/packages/common/business_components/src/ui/chart/BarChart.tsx index 0802a72e4..02d3a7c60 100644 --- a/packages/common/business_components/src/ui/chart/BarChart.tsx +++ b/packages/common/business_components/src/ui/chart/BarChart.tsx @@ -75,7 +75,7 @@ const CustomLegend = (props: any) => { }; export default function Chart({chartConfig=undefined, chartData=[], chartTitle='차트', chartClassName='w-full h-full', graphSize=40, yFieldText='', showLegend=false} : BarChartProps) { - const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEEAD", "#D4A5A5"]; + const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FED16A", "#FFEEAD", "#D4A5A5"]; const getMaxValue = (data: any[], keyPrefix: string) => { return Math.max(...data.map(item => Object.keys(item) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx index 2d7d2bf90..a42dea012 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx @@ -1,4 +1,5 @@ -import { FormField } from "../form"; +import React from 'react'; +import { FormField } from "../form"; import { SelectBox } from "../select"; import { Input } from "@common/components"; import { FormUi } from "../form_ui"; @@ -55,6 +56,7 @@ interface FormSchema { bznmTotNo?: string; rgtr?: string; dmdAplyPswd?: string; + dmdAplyPswdConfirm?: string; } interface SdmRegFormProps { @@ -85,12 +87,27 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun const formatter = new AsYouType("KR"); const formatted = formatter.input(input); - // 저장할 값 처리: 숫자만 추출 - const digitsOnly = input.replace(/\D/g, ""); - return formatted }; + // 사업자등록번호 포맷팅 함수 (3-2-5 형식) + const formatBusinessNumber = (value: string) => { + // 숫자만 추출 + const digitsOnly = value.replace(/\D/g, ""); + + // 10자리까지만 처리 + const limitedDigits = digitsOnly.slice(0, 10); + + // 3-2-5 형식으로 포맷팅 + if (limitedDigits.length <= 3) { + return limitedDigits; + } else if (limitedDigits.length <= 5) { + return `${limitedDigits.slice(0, 3)}-${limitedDigits.slice(3)}`; + } else { + return `${limitedDigits.slice(0, 3)}-${limitedDigits.slice(3, 5)}-${limitedDigits.slice(5)}`; + } + }; + const initializeSigunData = useCallback((sidoCd: string) => { if (sidoCd === '0') { @@ -179,12 +196,15 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun const value = e.target.value; if(noType === 'dmdInfoPk') { - if(orgBznmNo.substring(0,10) === value) { + // 숫자만 추출하여 저장 (포맷팅 제거) + const digitsOnly = value.replace(/\D/g, ""); + + if(orgBznmNo.substring(0,10) === digitsOnly) { setIsDuplicate(true); } else { setIsDuplicate(false); } - field?.onChange(value); + field?.onChange(digitsOnly); } else { if(orgBznmNo.substring(10,14) === value) { setIsDuplicate(true); @@ -296,7 +316,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun type="text" className="!text-xl text-gray-600" onChange={(e) => bznNoChange(e, 'dmdInfoPk', field)} - value={field.value} + value={formatBusinessNumber(field.value || '')} readOnly={!!updateList?.dmdInfoPk} /> ) @@ -368,32 +388,60 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun {...field} /> ) + }, + { + name: "dmdAplyPswdConfirm", + label: "패스워드확인", + component: (field) => ( + + ) } ] return ( <> - {formFields.filter((item)=> - {if(updateList?.dmdInfoPk){ - return item.name !== 'dmdAplyPswd' - }else{ - return item - } - }) - .map(({ name, label, component }) => ( - ( - name === 'bznmTotNo' ? component(field) : ( - - {component(field)} - - ) - )} - /> - ))} + {formFields + .filter(({ name }) => !(updateList?.dmdInfoPk && (name === "dmdAplyPswd" || name === "dmdAplyPswdConfirm"))) + .map(({ name, label, component }) => { + const error = form.formState.errors[name]; + const inputId = `${name}-input`; + const errorId = `${name}-error`; + const isRequired = ["ctpvCd", "sggCd", "dmdCoNm", "dmdInfoPk", "daddr", "telno", "dmdAplyPswd", "dmdAplyPswdConfirm"].includes(name); + + return ( + ( +
+ + + {React.cloneElement(component(field), { + id: inputId, + "aria-required": isRequired, + "aria-invalid": !!error, + "aria-describedby": error ? errorId : undefined + })} + + {error?.message && ( + + )} +
+ )} + /> + ); + })} ); } \ No newline at end of file diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index 4219602e6..c564b63dd 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -47,7 +47,17 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean ,up ? z.string().optional() // 패스워드는 선택 사항이며 길이 제한 없음 : z.string().optional() .refine((val) => !val || (val.length >= 8 && val.length <= 16), "패스워드는 8자 이상 16자 이내로 입력해주세요"), - + dmdAplyPswdConfirm: z.string() + .min(1, "패스워드확인을 입력해주세요"), +}).refine((data) => { + // 패스워드 확인 검증 + if (data.dmdAplyPswd && data.dmdAplyPswdConfirm) { + return data.dmdAplyPswd === data.dmdAplyPswdConfirm; + } + return true; +}, { + message: "패스워드가 일치하지 않습니다", + path: ["dmdAplyPswdConfirm"], // 에러를 패스워드 확인 필드에 표시 }); type FormSchema = z.infer>; @@ -62,6 +72,7 @@ const defaultValues: FormSchema = { telno: '', rgtr: '', dmdAplyPswd: '', + dmdAplyPswdConfirm: '', }; /** @@ -149,7 +160,7 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList console.log(' formData ', formData) /* await insertSdmData(formData); */ - rtnInputData(formData as DemandCompType); + rtnInputData(formData as unknown as DemandCompType); //router.push(`/pages/sdmMng/sdmInfoInsert?${queryParams.toString()}`); diff --git a/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx b/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx index 3c8fd7192..059d63d90 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/sdmNameBox.tsx @@ -1,14 +1,14 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import type { DemandCompType } from './form'; +import React, { useCallback, useEffect, useRef, useState } from "react"; +import type { DemandCompType } from "./form"; export type thisProps = { label: string | undefined; initValue: string | undefined; - dataList : DemandCompType[]; - rtnValue : (searchText: string, pageCnt: number) => void; - rtnData : (item: DemandCompType) => void; - rtnText : (text: string) => void; -} + dataList: DemandCompType[]; + rtnValue: (searchText: string, pageCnt: number) => void; + rtnData: (item: DemandCompType) => void; + rtnText: (text: string) => void; +}; /** * 수요처 검색 컴포넌트 @@ -18,88 +18,110 @@ export type thisProps = { * @param dataList 검색할 때 넘기는 데이터 리스트 * @param rtnData 검색 결과 반환 함수 */ -export const SdmSearchForm = ({label=undefined, initValue=undefined, rtnValue=()=>{}, dataList=[], rtnData=()=>{}, rtnText=()=>{} } :thisProps) => { - +export const SdmSearchForm = ({ + label = undefined, + initValue = undefined, + rtnValue = () => {}, + dataList = [], + rtnData = () => {}, + rtnText = () => {}, +}: thisProps) => { const [isOpen, setIsOpen] = useState(false); - const [textValue, setTextValue] = useState(initValue || ''); + const [textValue, setTextValue] = useState(initValue || ""); const wrapperRef = useRef(null); - const handleInputChange = useCallback((e: React.ChangeEvent) => { - const value = e.target.value; - setTextValue(value); - rtnValue(value, 10); - rtnText(value); - if (value) { - setIsOpen(true); - } else { - setIsOpen(false); - } - }, [rtnValue, rtnText]); + const handleInputChange = useCallback( + (e: React.ChangeEvent) => { + const value = e.target.value; + setTextValue(value); + rtnValue(value, 10); + rtnText(value); + if (value) { + setIsOpen(true); + } else { + setIsOpen(false); + } + }, + [rtnValue, rtnText], + ); - const handleSuggestionClick = useCallback((item: DemandCompType) => { - setTextValue(item.dmdCoNm); - rtnData(item); - setIsOpen(false); - }, [rtnData]); + const handleSuggestionClick = useCallback( + (item: DemandCompType) => { + setTextValue(item.dmdCoNm); + rtnData(item); + setIsOpen(false); + }, + [rtnData], + ); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { - if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) { + if ( + wrapperRef.current && + !wrapperRef.current.contains(event.target as Node) + ) { setIsOpen(false); } }; - document.addEventListener('mousedown', handleClickOutside); + document.addEventListener("mousedown", handleClickOutside); return () => { - document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener("mousedown", handleClickOutside); }; }, []); useEffect(() => { - if(initValue&& initValue?.length>0){ - setTextValue(initValue) + if (initValue && initValue?.length > 0) { + setTextValue(initValue); } - },[initValue]) - + }, [initValue]); + return ( -
+
setIsOpen(true)} */ - className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" + className="h-[3.2rem] w-full rounded-md border border-gray-300 pl-3 !text-xl text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder={`${label}을(를) 입력하세요`} /> {isOpen && ( -
+
- {dataList && dataList.length > 0 ? dataList.map((item : DemandCompType, index : number) => ( -
handleSuggestionClick(item)} - role="button" - tabIndex={0} - onKeyDown={(e) => { - if (e.key === 'Enter' || e.key === ' ') { - handleSuggestionClick(item); - } - }} - > - {item.dmdInfoPk.substring(10,14) !== '0000' ? ( - <> - 사업자번호 : {item.dmdInfoPk.substring(0,10)}  - 종사업자번호 : {item.dmdInfoPk.substring(10,14)}  - - ) : ( - <> - 사업자번호 : {item.dmdInfoPk.substring(0,10)}  - - )} - {item.dmdCoNm} -
- )) : ( -
+ {dataList && dataList.length > 0 ? ( + dataList.map((item: DemandCompType, index: number) => ( +
handleSuggestionClick(item)} + role="button" + tabIndex={0} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === " ") { + handleSuggestionClick(item); + } + }} + > + {item.dmdInfoPk.substring(10, 14) !== "0000" ? ( + <> + 사업자번호 : {" "} + {item.dmdInfoPk.substring(0, 10)}  + + 종사업자번호 :{" "} + {" "} + {item.dmdInfoPk.substring(10, 14)}  + + ) : ( + <> + 사업자번호 : {" "} + {item.dmdInfoPk.substring(0, 10)}  + + )} + {item.dmdCoNm} +
+ )) + ) : ( +
검색 결과가 없습니다.
)} @@ -107,5 +129,5 @@ export const SdmSearchForm = ({label=undefined, initValue=undefined, rtnValue=()
)}
- ) -} \ No newline at end of file + ); +}; diff --git a/packages/common/business_components/src/ui/search_form_left/index.tsx b/packages/common/business_components/src/ui/search_form_left/index.tsx index e7858df2a..4f36c078c 100644 --- a/packages/common/business_components/src/ui/search_form_left/index.tsx +++ b/packages/common/business_components/src/ui/search_form_left/index.tsx @@ -199,7 +199,7 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel setRtnSidoText(selectedSido?.text || ''); } initializeSigunData(val); - onSelectValue(selectSigunData[0]?.val || '0', 'sigun'); + onSelectValue('0', 'sigun'); break; case 'sigun': if (setRtnSigunValue) { diff --git a/packages/common/business_components/src/ui/table/index.tsx b/packages/common/business_components/src/ui/table/index.tsx index fe720abc0..01bb18ba2 100644 --- a/packages/common/business_components/src/ui/table/index.tsx +++ b/packages/common/business_components/src/ui/table/index.tsx @@ -49,6 +49,12 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr } }, [resetSelection]); + // 테이블 데이터가 변경될 때마다 선택된 행 초기화하는 useEffect 추가 + useEffect(() => { + // 새로운 데이터가 로드되면 선택 상태 초기화 + setIdx(-1); + }, [tableData]); + const handlePageChange = (page: number) => { setCur(page); onPageChange(page); @@ -83,7 +89,7 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr ? handleCellClick(index, head.id)} key={`cell-${head.id}-${index}`} @@ -97,7 +103,7 @@ export function UiTable({ tableData, headlist, pageSize, total, headName, childr : handleCellClick(index, head.id)} key={`cell-${head.id}-${index}`} diff --git a/packages/common/business_components/src/ui/table/uiPageNations.tsx b/packages/common/business_components/src/ui/table/uiPageNations.tsx index 891fc4c81..ca1f8e0c0 100644 --- a/packages/common/business_components/src/ui/table/uiPageNations.tsx +++ b/packages/common/business_components/src/ui/table/uiPageNations.tsx @@ -40,7 +40,8 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP { + onClick={(e) => { + e.preventDefault(); if (startPage > 1) handlePageChange(startPage - 1); }} /> @@ -53,7 +54,9 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP handlePageChange(pageNum)} + onClick={(e) => { + e.preventDefault(); + handlePageChange(pageNum)}} > {pageNum} @@ -65,7 +68,8 @@ export default function UiPageNations(commonPageNationsProps: CommonPageNationsP { + onClick={(e) => { + e.preventDefault(); if (endPage < totalPages) handlePageChange(endPage + 1); }} /> diff --git a/packages/common/components/src/ui/date-picker/index.tsx b/packages/common/components/src/ui/date-picker/index.tsx index 919e22435..85c584e5f 100644 --- a/packages/common/components/src/ui/date-picker/index.tsx +++ b/packages/common/components/src/ui/date-picker/index.tsx @@ -13,12 +13,14 @@ type DatePickerProps = { placeholder?: string; disabled?: boolean; selected?: Date; + zIndex?: number; // z-index prop 추가 } & React.ComponentProps; export function DatePicker({ className, placeholder = "날짜 선택", disabled, + zIndex, // zIndex prop 받기 ...props }: DatePickerProps) { return ( @@ -37,7 +39,10 @@ export function DatePicker({ )} - + From 90fda952ad0efb22e8c0018cb7d8291118f51d8c Mon Sep 17 00:00:00 2001 From: JIeunhuh Date: Wed, 9 Jul 2025 13:27:34 +0900 Subject: [PATCH 06/17] =?UTF-8?q?=EC=8B=9C=EC=84=A4=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=20=EC=8B=9C=20=ED=98=84=ED=99=A9=EB=AA=A9=EB=A1=9D=20=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=83=9D=EC=84=B1=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20props=EB=A1=9C=20=EB=84=98=EA=B8=B0=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/business_components/src/ui/map/Gis.js | 2 ++ .../common/business_components/src/ui/map/GisTree.js | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index 880c116cd..bad4d313c 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -30,6 +30,7 @@ function Gis({ setIsOpen, setFeatureData, featureData, + imgVisble = false, searchView: SearchView, detailView: DetailView, onFeatureSelect, @@ -386,6 +387,7 @@ function Gis({ }; onFeatureSelect(dummyFeature); }} + imageVisible={imgVisble} /> {/* */} diff --git a/packages/common/business_components/src/ui/map/GisTree.js b/packages/common/business_components/src/ui/map/GisTree.js index 5b30dc7f4..8a2db3ae2 100644 --- a/packages/common/business_components/src/ui/map/GisTree.js +++ b/packages/common/business_components/src/ui/map/GisTree.js @@ -10,7 +10,7 @@ import { DndProvider } from "react-dnd"; import { useGisContext } from './Gis'; import GisApp from './lib/gis.core'; -export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes = () => { }, visible, setVisible, onCheckedChange, onLayerIconClick }) { +export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes = () => { }, visible, setVisible, onCheckedChange, onLayerIconClick,imageVisible=false }) { const { gisCore, treeData } = useGisContext(); const [checked, setChecked] = useState([]); const [expanded, setExpanded] = useState([]); @@ -188,9 +188,9 @@ export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes image.src = canvas.toDataURL('image/png'); return image; }; - const handleLayerImgClick = (nodeNm) => { - console.log('click!', nodeNm) - onLayerIconClick(nodeNm) + const handleLayerImgClick = (nodeNm, nodeId) => { + if(!checked.includes(nodeId)) alert('시설을 선택해주세요') + else onLayerIconClick(nodeNm) } if (!treeData || treeData.length === 0) return null; @@ -224,7 +224,7 @@ export default React.memo(function GisTree({ checkedNodes = [], setCheckedNodes handleCheck(node.id)} className="cursor-pointer" /> {node.icon && {node.icon}} {node.text} - {depth > 0 && {handleLayerImgClick(node.text)}} alt={node.text}>} + {imageVisible ? depth > 0 && {handleLayerImgClick(node.text, node.id)}} alt={node.text}> : null}
)} sort={(a, b) => { From 17f6e640a6b06abec655af339d28fa7375d2f42b Mon Sep 17 00:00:00 2001 From: swcho Date: Wed, 9 Jul 2025 15:29:36 +0900 Subject: [PATCH 07/17] =?UTF-8?q?Revert=20"feat:=20DatePicker=20zIndex=20p?= =?UTF-8?q?rops=20=EB=8B=A4=EC=8B=9C=20=EC=A0=81=EC=9A=A9"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4224375b3a5aa1e3213b96ccfc3fff067a9ce06a. --- packages/common/components/src/ui/date-picker/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/common/components/src/ui/date-picker/index.tsx b/packages/common/components/src/ui/date-picker/index.tsx index 85c584e5f..67265df0e 100644 --- a/packages/common/components/src/ui/date-picker/index.tsx +++ b/packages/common/components/src/ui/date-picker/index.tsx @@ -40,8 +40,10 @@ export function DatePicker({ From b3a69bf2ef34331c10436669de505fa9e7caf4b6 Mon Sep 17 00:00:00 2001 From: swcho Date: Wed, 9 Jul 2025 15:29:57 +0900 Subject: [PATCH 08/17] =?UTF-8?q?Revert=20"feat:=20DatePicker=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20zIndex=20props=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 52a5650ca593c82790d8d34d5f38293797f41739. --- .../components/src/ui/date-picker/index.tsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/common/components/src/ui/date-picker/index.tsx b/packages/common/components/src/ui/date-picker/index.tsx index 67265df0e..ee5d37872 100644 --- a/packages/common/components/src/ui/date-picker/index.tsx +++ b/packages/common/components/src/ui/date-picker/index.tsx @@ -2,7 +2,7 @@ import "./date-picker.css"; import { format } from "date-fns"; import { CalendarIcon } from "lucide-react"; -import type { DayPicker } from "react-day-picker"; +import type { DayPickerSingleProps } from "react-day-picker"; import { cn } from "../../lib/utils"; import { Button } from "../button"; @@ -12,15 +12,12 @@ import { Popover, PopoverContent, PopoverTrigger } from "../popover"; type DatePickerProps = { placeholder?: string; disabled?: boolean; - selected?: Date; - zIndex?: number; // z-index prop 추가 -} & React.ComponentProps; +} & DayPickerSingleProps; export function DatePicker({ className, placeholder = "날짜 선택", disabled, - zIndex, // zIndex prop 받기 ...props }: DatePickerProps) { return ( @@ -39,13 +36,8 @@ export function DatePicker({ )} - - + + ); From f4d6b3415ba34f9e3dc245e462479c5400702618 Mon Sep 17 00:00:00 2001 From: JIeunhuh Date: Wed, 9 Jul 2025 17:41:15 +0900 Subject: [PATCH 09/17] =?UTF-8?q?=EC=A4=91=EC=88=98=EB=8F=84=EC=8B=9C?= =?UTF-8?q?=EC=84=A4=20=EC=A1=B0=EA=B1=B4=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/business_components/src/ui/map/Gis.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index bad4d313c..3a7bec1b8 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -89,11 +89,11 @@ function Gis({ const layerName = layerNmRef.current if (layerName === '하수재이용시설') { featureId = data.searchPk; - } else if (layerName === '빗물이용시설') { + } else if (layerName === '빗물이용시설'|| layerName == '중수도시설') { featureId = data.bdstInfoPk; } else if (layerName === '하수처리시설') { featureId = data.bscFctCd; - } else if (layerName === '중수도시설' || layerName == '온배수시설') { + } else if (layerName === '온배수시설' ) { featureId = data.bdstRuseFcltPk; } else { console.warn('해당 레이어에 대한 featureId 매핑 없음', layerNm); From e9ff6bbeb5a02657f5099ce69fcf51ce336fa420 Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Wed, 9 Jul 2025 18:26:15 +0900 Subject: [PATCH 10/17] =?UTF-8?q?=EB=B0=94=EC=B0=A8=ED=8A=B8=20=ED=81=AC?= =?UTF-8?q?=EA=B8=B0=EB=B9=84=EC=9C=A8=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/chart/BarChart.tsx | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/common/business_components/src/ui/chart/BarChart.tsx b/packages/common/business_components/src/ui/chart/BarChart.tsx index 02d3a7c60..ddd0ac272 100644 --- a/packages/common/business_components/src/ui/chart/BarChart.tsx +++ b/packages/common/business_components/src/ui/chart/BarChart.tsx @@ -74,17 +74,25 @@ const CustomLegend = (props: any) => { ); }; +// chartData의 모든 값 중 최대값 구하기 +const getGlobalMax = (data: Record[]) => { + if (!data || data.length === 0) return 0; + return Math.max( + ...data.flatMap(item => + Object.entries(item) + .filter(([key]) => key !== 'label') + .map(([, value]) => value as number) + ) + ); +}; + export default function Chart({chartConfig=undefined, chartData=[], chartTitle='차트', chartClassName='w-full h-full', graphSize=40, yFieldText='', showLegend=false} : BarChartProps) { const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FED16A", "#FFEEAD", "#D4A5A5"]; - const getMaxValue = (data: any[], keyPrefix: string) => { - return Math.max(...data.map(item => - Object.keys(item) - .filter(key => key.includes(keyPrefix)) - .map(key => item[key]) - ).flat()); - }; - - const barMaxValue = getMaxValue(chartData, 'barVal'); + const globalMax = getGlobalMax(chartData); + const tickCount = 5; + // interval을 globalMax / tickCount로 계산 + const interval = globalMax / tickCount; + const ticks = Array.from({ length: tickCount + 1 }, (_, i) => Math.round(interval * i)); return ( <> {chartTitle && chartTitle !== "" && chartTitle !== "undefined" ? ( @@ -93,8 +101,8 @@ export default function Chart({chartConfig=undefined, chartData=[], chartTitle='
): null}
- - + + }/> {chartData && chartData.length > 0 && ( From 58e0322bfeb9933313f37d14c71c97b76c74e4fb Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Wed, 9 Jul 2025 19:33:40 +0900 Subject: [PATCH 11/17] =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=EC=8B=9C=20?= =?UTF-8?q?=ED=96=89=EC=A0=95=EB=B3=84=20A=EB=A1=9C=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20(304=EB=9D=BC=EC=9D=B8)=20=EA=B1=B4=EB=93=A4=EC=A7=80?= =?UTF-8?q?=EB=A7=88=EC=84=B8=EC=9A=94=20...=E3=85=A0=E3=85=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/search_form_left/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/search_form_left/index.tsx b/packages/common/business_components/src/ui/search_form_left/index.tsx index 4f36c078c..a891ec207 100644 --- a/packages/common/business_components/src/ui/search_form_left/index.tsx +++ b/packages/common/business_components/src/ui/search_form_left/index.tsx @@ -301,7 +301,7 @@ function SearchFormLeft({ isShowPart = false, children, selectSidoData = [], sel resetAllValues(); // 리셋 후 트리거를 false로 설정 if (setRtnPartValue) { - setRtnPartValue('0'); + setRtnPartValue('A'); } } }, [resetTrigger]); From 3ec986dfbeb8a0a834fcdcd620815e3819e352df Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Wed, 9 Jul 2025 19:52:42 +0900 Subject: [PATCH 12/17] =?UTF-8?q?datepickerrange=20=EC=83=9D=EC=84=B1(?= =?UTF-8?q?=EC=86=90=EB=8C=80=EC=A7=80=EB=A7=88=EC=84=B8=EC=9A=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/date_picker_range/index.tsx | 46 +++++++++++++++++++ .../business_components/src/ui/index.ts | 3 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 packages/common/business_components/src/ui/date_picker_range/index.tsx diff --git a/packages/common/business_components/src/ui/date_picker_range/index.tsx b/packages/common/business_components/src/ui/date_picker_range/index.tsx new file mode 100644 index 000000000..3a6ab1ae0 --- /dev/null +++ b/packages/common/business_components/src/ui/date_picker_range/index.tsx @@ -0,0 +1,46 @@ +import "./date-picker.css"; + +import { format } from "date-fns"; +import { CalendarIcon } from "lucide-react"; +import type { DayPickerSingleProps } from "react-day-picker"; + +import { cn } from "../../lib/utils"; +import { Button } from "@common/components/ui"; +import { Calendar } from "@common/components/ui"; +import { Popover, PopoverContent, PopoverTrigger } from "@common/components/ui"; + +type DatePickerRangeProps = { + placeholder?: string; + disabled?: boolean | ((date: Date) => boolean); +} & DayPickerSingleProps; + +export function DatePickerRange({ + className, + placeholder = "날짜 선택", + disabled, + ...props +}: DatePickerRangeProps) { + return ( + + + + + + + + + ); +} diff --git a/packages/common/business_components/src/ui/index.ts b/packages/common/business_components/src/ui/index.ts index fd1e6fe9e..eab3a7eab 100644 --- a/packages/common/business_components/src/ui/index.ts +++ b/packages/common/business_components/src/ui/index.ts @@ -21,4 +21,5 @@ export * from "./table_div"; export * from "./title"; export * from "./sdmInsertForm"; export * from "./popover_ui"; -export * from "./date_month_picker"; \ No newline at end of file +export * from "./date_month_picker"; +export * from "./date_picker_range" \ No newline at end of file From 9ab0302e0893eab8bd3872a0b03d1981eba000e8 Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Wed, 9 Jul 2025 20:00:01 +0900 Subject: [PATCH 13/17] =?UTF-8?q?=EB=8B=AC=EB=A0=A5=20=EB=A7=8C=EB=93=A0?= =?UTF-8?q?=EA=B1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/date_picker_range/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/business_components/src/ui/date_picker_range/index.tsx b/packages/common/business_components/src/ui/date_picker_range/index.tsx index 3a6ab1ae0..70565230a 100644 --- a/packages/common/business_components/src/ui/date_picker_range/index.tsx +++ b/packages/common/business_components/src/ui/date_picker_range/index.tsx @@ -1,4 +1,4 @@ -import "./date-picker.css"; +import "../date_picker/date-picker.css"; import { format } from "date-fns"; import { CalendarIcon } from "lucide-react"; From cce216ad9bac561a711d8f40a98b130fbf672d48 Mon Sep 17 00:00:00 2001 From: leedj312 Date: Thu, 10 Jul 2025 11:20:58 +0900 Subject: [PATCH 14/17] =?UTF-8?q?readOnly=20disabled=20=EA=B0=80=20?= =?UTF-8?q?=EC=95=84=EB=8B=8C=20readOnly=EB=A1=9C=20=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/date_picker/index.tsx | 134 +++++++++++------- .../src/ui/select/index.tsx | 128 +++++++++++------ 2 files changed, 173 insertions(+), 89 deletions(-) diff --git a/packages/common/business_components/src/ui/date_picker/index.tsx b/packages/common/business_components/src/ui/date_picker/index.tsx index 9df32b3b5..722b82a3c 100644 --- a/packages/common/business_components/src/ui/date_picker/index.tsx +++ b/packages/common/business_components/src/ui/date_picker/index.tsx @@ -6,62 +6,100 @@ import { format } from "date-fns"; import { CalendarIcon } from "lucide-react"; import type { DayPickerSingleProps } from "react-day-picker"; -import { Button, Calendar, Popover, PopoverContent, PopoverTrigger } from "@common/components/ui"; +import { + Button, + Calendar, + Popover, + PopoverContent, + PopoverTrigger, +} from "@common/components/ui"; import { cn } from "../../lib/utils"; import { FormControl } from "../form"; import { ko } from "date-fns/locale"; import { useState } from "react"; -type DatePickerProps = DayPickerSingleProps & { field: { value: Date; onChange: (date: Date | undefined) => void }, selectClass: string | undefined, readOnly?: boolean }; +type DatePickerProps = DayPickerSingleProps & { + field: { value: Date; onChange: (date: Date | undefined) => void }; + selectClass: string | undefined; + readOnly?: boolean; +}; +export function DatePicker({ + field, + selectClass, + readOnly = false, + ...props +}: DatePickerProps) { + const [open, setOpen] = useState(false); -export function DatePicker({ field, selectClass, readOnly = false, ...props }: DatePickerProps) { - const [open, setOpen] = useState(false); + const handleSelect = (date: Date | undefined) => { + if (!readOnly) { + // readOnly가 아닐 때만 변경 허용 + field.onChange(date); // React Hook Form 업데이트 + setOpen(false); + } + }; - const handleSelect = (date: Date | undefined) => { - if (!readOnly) { // readOnly가 아닐 때만 변경 허용 - field.onChange(date); // React Hook Form 업데이트 - setOpen(false); - } - }; + return ( + + + + - - - - - - - ); + "PPP", + { locale: ko }, + ) + ) : ( + 날짜를 선택해주세요 + )} + + + + + + + + + ); } diff --git a/packages/common/business_components/src/ui/select/index.tsx b/packages/common/business_components/src/ui/select/index.tsx index 8843aa04e..d09e3023a 100644 --- a/packages/common/business_components/src/ui/select/index.tsx +++ b/packages/common/business_components/src/ui/select/index.tsx @@ -1,57 +1,103 @@ // selectBox import { Label } from "@common/components"; -import React from "react"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./lib/selectBox"; +import React, { useEffect, useState } from "react"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "./lib/selectBox"; /** 차트 기본 스타일 */ interface SelectBox1 { - text:string, - val:string|number, - hidden?: boolean + text: string; + val: string | number; + hidden?: boolean; } const SelectBox = React.forwardRef< HTMLDivElement, React.HTMLAttributes & { - label:string, - selectClass:string|undefined, - className:string, - selectArray:SelectBox1[], - onSelectValue:(val:string|number)=>void, - value?: string|number, - readOnly?: boolean // readOnly 속성 추가 + label: string; + selectClass: string | undefined; + className: string; + selectArray: SelectBox1[]; + onSelectValue: (val: string | number) => void; + value?: string | number; + readOnly?: boolean; // readOnly 속성 추가 } ->(({ label, className, selectClass, selectArray, onSelectValue, value, readOnly = false }, ref)=>{ - // hidden이 true인 첫 번째 항목을 placeholder로 사용 - const hiddenItem = selectArray.find(item => item.hidden); - const placeHolder = hiddenItem?.text ?? "선택"; - - // hidden이 true인 항목만 드롭다운에서 제외 - const visibleItems = selectArray.filter(item => !item.hidden); +>( + ( + { + label, + className, + selectClass, + selectArray, + onSelectValue, + value, + readOnly = false, + }, + ref, + ) => { + // hidden이 true인 첫 번째 항목을 placeholder로 사용 + const hiddenItem = selectArray.find((item) => item.hidden); + const placeHolder = hiddenItem?.text ?? "선택"; + const [isOpen, setIsOpen] = useState(false); + // hidden이 true인 항목만 드롭다운에서 제외 + const visibleItems = selectArray.filter((item) => !item.hidden); - // 현재 값이 hidden 항목이거나 빈 값인 경우 undefined로 설정하여 placeholder가 표시되도록 함 - const currentValue = value !== undefined && - hiddenItem && - (String(value) === String(hiddenItem.val) || value === "" || value === "0" || value === 0) - ? undefined - : (value !== undefined ? String(value) : undefined); + // 현재 값이 hidden 항목이거나 빈 값인 경우 undefined로 설정하여 placeholder가 표시되도록 함 + const currentValue = + value !== undefined && + hiddenItem && + (String(value) === String(hiddenItem.val) || + value === "" || + value === "0" || + value === 0) + ? undefined + : value !== undefined + ? String(value) + : undefined; - return ( -
- {label && } - -
- ) -}) + return ( +
+ {label && ( + + )} + +
+ ); + }, +); export { SelectBox }; From b75caf4f7baf01314fd3628e1b80cb30e06254c8 Mon Sep 17 00:00:00 2001 From: swcho Date: Thu, 10 Jul 2025 15:34:37 +0900 Subject: [PATCH 15/17] =?UTF-8?q?feat:=20DatePickerRange=EC=97=90=20z-inde?= =?UTF-8?q?x=20props=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/date_picker_range/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/common/business_components/src/ui/date_picker_range/index.tsx b/packages/common/business_components/src/ui/date_picker_range/index.tsx index 70565230a..91bbb84f1 100644 --- a/packages/common/business_components/src/ui/date_picker_range/index.tsx +++ b/packages/common/business_components/src/ui/date_picker_range/index.tsx @@ -12,12 +12,14 @@ import { Popover, PopoverContent, PopoverTrigger } from "@common/components/ui"; type DatePickerRangeProps = { placeholder?: string; disabled?: boolean | ((date: Date) => boolean); + zIndex?: number; // z-index prop 추가 } & DayPickerSingleProps; export function DatePickerRange({ className, placeholder = "날짜 선택", disabled, + zIndex, ...props }: DatePickerRangeProps) { return ( @@ -36,8 +38,8 @@ export function DatePickerRange({ )} - - + From c394fd4de2de3b3a7c0d2f2b07c8238fd0d13f4b Mon Sep 17 00:00:00 2001 From: swcho Date: Thu, 10 Jul 2025 15:47:36 +0900 Subject: [PATCH 16/17] =?UTF-8?q?Revert=20"feat:=20DatePickerRange?= =?UTF-8?q?=EC=97=90=20z-index=20props=20=EC=B6=94=EA=B0=80"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b75caf4f7baf01314fd3628e1b80cb30e06254c8. --- .../business_components/src/ui/date_picker_range/index.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/common/business_components/src/ui/date_picker_range/index.tsx b/packages/common/business_components/src/ui/date_picker_range/index.tsx index 91bbb84f1..70565230a 100644 --- a/packages/common/business_components/src/ui/date_picker_range/index.tsx +++ b/packages/common/business_components/src/ui/date_picker_range/index.tsx @@ -12,14 +12,12 @@ import { Popover, PopoverContent, PopoverTrigger } from "@common/components/ui"; type DatePickerRangeProps = { placeholder?: string; disabled?: boolean | ((date: Date) => boolean); - zIndex?: number; // z-index prop 추가 } & DayPickerSingleProps; export function DatePickerRange({ className, placeholder = "날짜 선택", disabled, - zIndex, ...props }: DatePickerRangeProps) { return ( @@ -38,8 +36,8 @@ export function DatePickerRange({ )} - - + From 757dc97bda6c86424a6102aadcca1c61b9a9fac7 Mon Sep 17 00:00:00 2001 From: swcho Date: Thu, 10 Jul 2025 21:11:01 +0900 Subject: [PATCH 17/17] =?UTF-8?q?feat:=20=ED=95=98=EC=88=98=ED=8E=8C?= =?UTF-8?q?=ED=94=84=EC=9E=A5,=20=ED=95=98=EC=88=98=EB=A7=A8=ED=99=80,=20?= =?UTF-8?q?=ED=95=98=EC=88=98=EA=B4=80=EB=A1=9C,=20=EC=9A=B0=EC=88=98?= =?UTF-8?q?=ED=86=A0=EC=8B=A4=20=EC=9E=90=EC=B2=B4=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=A0=80=EC=9E=A5=20=EB=B0=8F=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/.env.local | 2 +- apps/sn/app/(map-layout)/map/SearchModal.tsx | 69 +++--- .../map/components/common/index.ts | 4 +- .../map/components/common/table.ts | 219 +++++++++++++++++- .../components/popupComponent/MsSwagePpl.tsx | 46 ++-- .../map/components/popupComponent/Ssc.tsx | 72 +++--- .../components/popupComponent/sewagePump.tsx | 41 +++- .../map/components/popupComponent/smh.tsx | 37 ++- .../map/featureClickEventPopup.tsx | 156 ++++++++++--- apps/sn/app/components/lib/api/index.ts | 2 + apps/sn/app/components/ui/verticalTable.tsx | 30 ++- 11 files changed, 542 insertions(+), 136 deletions(-) diff --git a/apps/sn/.env.local b/apps/sn/.env.local index 35c1476f5..d0be4b904 100644 --- a/apps/sn/.env.local +++ b/apps/sn/.env.local @@ -12,4 +12,4 @@ NEXT_PUBLIC_REFRESH_TOKEN = refresh-token NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API #NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성 부장님 API -#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정 차장님 API +#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.222:8883/sewerage-service/api # 박이정 차장님 API diff --git a/apps/sn/app/(map-layout)/map/SearchModal.tsx b/apps/sn/app/(map-layout)/map/SearchModal.tsx index 73cc5fc8e..a549ece0b 100644 --- a/apps/sn/app/(map-layout)/map/SearchModal.tsx +++ b/apps/sn/app/(map-layout)/map/SearchModal.tsx @@ -1,8 +1,8 @@ import FeatureClickEventPopup from './featureClickEventPopup'; import React, { useEffect, useState } from 'react'; import axios from 'axios'; -import { UiModal, UiTable } from '@common/business_components/ui'; -import { Button, DatePicker, Input, Label } from '@common/components'; +import { UiModal, UiTable, DatePickerRange } from '@common/business_components/ui'; +import { Button, Input, Label } from '@common/components'; import { UiTable2 } from '@common/business_components/ui/table/index-2'; import { UITab2 } from '@common/business_components/ui/tab/index-2'; import { SelectBox2 } from '@common/business_components/ui/select/index-2'; @@ -136,6 +136,21 @@ const SearchModal: React.FC = ({ const todayMonth = (today.getMonth() + 1).toString().padStart(2, "0"); const todayDate = today.getDate().toString().padStart(2, "0"); + const isDateInRanges = (date: Date) => { + const standYear = parseInt(fromDate.getFullYear().toString()); + const dateRanges = []; + dateRanges.push({ + start: new Date(standYear, 0, 1), + end: new Date(standYear, 11, 31) + }); + + return dateRanges.some(range => { + const start = new Date(range.start); + const end = new Date(range.end); + return date >= start && date <= end; + }); + }; + // UiTable2에 넘길 headlist를 BASIC_TYPES 값에 따라 분기 처리 let dynamicHeadlist = MsSwagePplCol2; // default 값 if (activeTab === 'operation') dynamicHeadlist = operationTableHeadlist; // 운영정보 @@ -964,43 +979,23 @@ const SearchModal: React.FC = ({ startLabel="수행기간" endLabel="" /> */} - { if (date) setFromDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} - zIndex={102} + { if (date) setFromDate(date) }} // 선택했을 때 이벤트 (주로 set) + className="w-full p-1 border rounded bg-white" // 스타일 + disabled={(date) => !isDateInRanges(date)} // 선택못하게 하는 날짜 - 없으면 안넣어도 됨 + defaultMonth={fromDate} // 처음에 시작할 날짜 selected랑 같이 같은 날짜 넣으면 됨 /> - ~ - { if (date) setToDate(date) }} - modifiers={{ - disabled: { after: new Date() } - }} - zIndex={102} + ~ + { if (date) setFromDate(date) }} // 선택했을 때 이벤트 (주로 set) + className="w-full p-1 border rounded bg-white" // 스타일 + disabled={(date) => !isDateInRanges(date)} // 선택못하게 하는 날짜 - 없으면 안넣어도 됨 + defaultMonth={toDate} // 처음에 시작할 날짜 selected랑 같이 같은 날짜 넣으면 됨 /> -
- {/* 경과년도 */} - {/* - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ""); - setYearFilter({ ...yearFilter, 경과년도: val }); - }} - /> */} -
{/* 조회 버튼 중앙 정렬 */}
diff --git a/apps/sn/app/(map-layout)/map/components/common/index.ts b/apps/sn/app/(map-layout)/map/components/common/index.ts index 51dd450e7..e71e8ba3f 100644 --- a/apps/sn/app/(map-layout)/map/components/common/index.ts +++ b/apps/sn/app/(map-layout)/map/components/common/index.ts @@ -7,9 +7,11 @@ import SwtrmtFclt from "../popupComponent/SwtrmtFclt"; type LayerComponentProps = { featureData: any; - chkMainSsc?: boolean; + isMainSsc?: boolean; + isDrtwSewagePump?: boolean; additionalData?: any; onSaveClick?: () => void; + onFormDataChange?: (data: any) => void; // 추가 }; type LayerContentMap = { [key: string]: { diff --git a/apps/sn/app/(map-layout)/map/components/common/table.ts b/apps/sn/app/(map-layout)/map/components/common/table.ts index f114cf97b..87be5bf6e 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -55,6 +55,213 @@ export const MsSwagePplCol2 = [ // { id: 'usgCd', title: '용도코드' }, // { id: 'lyrTypeNm', title: '레이어타입명' }, ] +// 하수관로 용도 코드표 +export const MS_SWAGE_PPL_USE_CODES = [ + { val: "SBA000", text: "미분류" }, + { val: "SBA001", text: "합류관" }, + { val: "SBA002", text: "차집관" }, + { val: "SBA003", text: "우수관" }, + { val: "SBA004", text: "오수관" }, + { val: "SBA999", text: "기타" }, + { val: "그 외", text: "미분류" }, +]; +// 하수관로 재질 코드표 +export const MS_SWAGE_PPL_CODES = [ + { val: "MOP000", text: "미분류" }, + { val: "MOP001", text: "닥타일주철관(DCIP)" }, + { val: "MOP002", text: "강관(SP)" }, + { val: "MOP003", text: "아연도강관(GS)" }, + { val: "MOP004", text: "염화비닐관(PVC)" }, + { val: "MOP005", text: "폴리에틸렌관(PE)" }, + { val: "MOP006", text: "스테인레스관(SSP)" }, + { val: "MOP007", text: "동관(COP)" }, + { val: "MOP008", text: "P.S.콘크리트관(PC)" }, + { val: "MOP009", text: "석면시멘트관(AS)" }, + { val: "MOP010", text: "회주철관(CIP)" }, + { val: "MOP011", text: "연관(LP)" }, + { val: "MOP012", text: "흉관(HP)" }, + { val: "MOP013", text: "철근콘크리트관(RC)" }, + { val: "MOP014", text: "강관(ST)" }, + { val: "MOP015", text: "주철관(CI)" }, + { val: "MOP016", text: "화학제품류관(PV)" }, + { val: "MOP017", text: "도관(VC)" }, + { val: "MOP018", text: "석축(SE)" }, + { val: "MOP019", text: "도복장 강관(SP)" }, + { val: "MOP020", text: "흉관(EP)" }, + { val: "MOP021", text: "아연도강관(GP)" }, + { val: "MOP022", text: "청동관(BR)" }, + { val: "MOP023", text: "고무몰딩(RM)" }, + { val: "MOP024", text: "주강(CS)" }, + { val: "MOP025", text: "VR관" }, + { val: "MOP026", text: "HDPE관" }, + { val: "MOP027", text: "시멘트라이닝주철관(C)" }, + { val: "MOP028", text: "수도용 PE관(PE)" }, + { val: "MOP029", text: "석면시멘트관(AC)" }, + { val: "MOP030", text: "폴리에틸렌분체라이닝강관(PEP)" }, + { val: "MOP031", text: "에폭시코팅강관(EPS)" }, + { val: "MOP032", text: "HI-3P" }, + { val: "MOP033", text: "철근콘크리트박스(RCB)" }, + { val: "MOP034", text: "콘크리트중선함(CD)" }, + { val: "MOP035", text: "후랙시불전선함(FP)" }, + { val: "MOP036", text: "전선함(FD)" }, + { val: "MOP038", text: "이중보온관" }, + { val: "MOP039", text: "폴리에틸렌피복강관(PLP)" }, + { val: "MOP041", text: "FRP" }, + { val: "MOP042", text: "강재" }, + { val: "MOP999", text: "기타" }, + { val: "MOP800", text: "2중벽PE관" }, + { val: "MOP801", text: "3중벽PE관" }, + { val: "MOP802", text: "가스배관용 강관" }, + { val: "MOP803", text: "강관(피복 Double, 용접접합)" }, + { val: "MOP804", text: "강관(피복 Single, 용접접합)" }, + { val: "MOP805", text: "강관(CP)" }, + { val: "MOP806", text: "강철" }, + { val: "MOP807", text: "강화플라스틱복합관" }, + { val: "MOP808", text: "경질염화비닐관(HI-VP)" }, + { val: "MOP809", text: "고강성PVC이중벽관" }, + { val: "MOP810", text: "고광도PVC이중벽관" }, + { val: "MOP811", text: "고밀도폴리에틸렌관(THP)" }, + { val: "MOP812", text: "고밀도폴리에틸렌파상형이중벽관" }, + { val: "MOP813", text: "공장제 박스관거" }, + { val: "MOP814", text: "관로없음(알케이블)" }, + { val: "MOP815", text: "나선형강관" }, + { val: "MOP816", text: "내충격수도관" }, + { val: "MOP817", text: "내충격용하수도용경질염화비닐관(HI-VG)" }, + { val: "MOP818", text: "내충격HI-VG2관" }, + { val: "MOP819", text: "내충격PVC하수관" }, + { val: "MOP820", text: "녹석(돌산호과 일종)" }, + { val: "MOP821", text: "동관(구리관, 용접)" }, + { val: "MOP822", text: "둥근잔돌" }, + { val: "MOP823", text: "무근콘크리트" }, + { val: "MOP824", text: "백관" }, + { val: "MOP825", text: "복합철판파형관" }, + { val: "MOP826", text: "분체라이닝관" }, + { val: "MOP827", text: "석축박스" }, + { val: "MOP828", text: "석축철콘" }, + { val: "MOP829", text: "수도용경질염화비관" }, + { val: "MOP830", text: "수도용경질염화비닐이음관" }, + { val: "MOP831", text: "수도용엑포시수지분체내외면코팅강관" }, + { val: "MOP832", text: "수지파형강관(PCS)" }, + { val: "MOP833", text: "수지CSP" }, + { val: "MOP834", text: "스테인레스 주름관" }, + { val: "MOP835", text: "스테인레스관(STS)" }, + { val: "MOP836", text: "스테인레스스틸파이프관" }, + { val: "MOP837", text: "아스콘" }, + { val: "MOP838", text: "아스팔트" }, + { val: "MOP839", text: "아스팔트도복장강관(ASP)" }, + { val: "MOP840", text: "아연" }, + { val: "MOP841", text: "아연도금(백관)" }, + { val: "MOP842", text: "알루미늄" }, + { val: "MOP843", text: "알루미늄합금" }, + { val: "MOP844", text: "압력배관용 탄소강관" }, + { val: "MOP845", text: "양철관" }, + { val: "MOP846", text: "양철주름관(CSP)" }, + { val: "MOP847", text: "연합인슈강판" }, + { val: "MOP848", text: "와사관(GSP)" }, + { val: "MOP849", text: "원심력철근콘크리트" }, + { val: "MOP850", text: "유리섬유관(GRP)" }, + { val: "MOP851", text: "유리섬유복합관(GRP)" }, + { val: "MOP852", text: "이음매없는동및동합금관" }, + { val: "MOP853", text: "일반배관용스테인리스강관" }, + { val: "MOP854", text: "전압 콘크리트관" }, + { val: "MOP855", text: "주름관" }, + { val: "MOP856", text: "주름주철파형강관" }, + { val: "MOP857", text: "지중 저압케이블 입상관" }, + { val: "MOP858", text: "진동및전압철근콘크리트관" }, + { val: "MOP859", text: "철근콘크리트" }, + { val: "MOP860", text: "철근콘크리트 블록" }, + { val: "MOP861", text: "철근콘크리트조립흙막이" }, + { val: "MOP862", text: "철판매입관" }, + { val: "MOP863", text: "청동" }, + { val: "MOP864", text: "코아식프리스트레스트콘크리트관" }, + { val: "MOP865", text: "콘크리트" }, + { val: "MOP866", text: "콘크리트 폴륨관" }, + { val: "MOP867", text: "콘크리트블록" }, + { val: "MOP868", text: "탄소강" }, + { val: "MOP869", text: "탄소강(카본스틸)" }, + { val: "MOP870", text: "탄소주강" }, + { val: "MOP871", text: "트러후" }, + { val: "MOP872", text: "파선형강관(RCF)" }, + { val: "MOP873", text: "파형강관(CSP)" }, + { val: "MOP874", text: "파형관" }, + { val: "MOP875", text: "파형플라스틱관" }, + { val: "MOP876", text: "폴리머관" }, + { val: "MOP877", text: "폴리에스테르수지콘크리트관" }, + { val: "MOP878", text: "폴리에틸렌 전선관" }, + { val: "MOP879", text: "폴리에틸렌 피복강관" }, + { val: "MOP880", text: "폴리에틸렌관 1호관" }, + { val: "MOP881", text: "폴리에틸렌관 2호관" }, + { val: "MOP882", text: "폴리에틸렌관(2중벽)" }, + { val: "MOP883", text: "폴리에틸렌관(3중벽)" }, + { val: "MOP884", text: "폴리에틸렌분체라이닝" }, + { val: "MOP885", text: "폴리에틸렌이중벽하수관" }, + { val: "MOP886", text: "폴리탄산에스테르" }, + { val: "MOP887", text: "프리스트레스트콘크리트실린더관" }, + { val: "MOP888", text: "플라스틱" }, + { val: "MOP889", text: "플라스틱주름관" }, + { val: "MOP890", text: "하수도용고강성경질염화비닐이중벽주름관" }, + { val: "MOP891", text: "현장타설관" }, + { val: "MOP892", text: "현장타설철근콘크리트관" }, + { val: "MOP893", text: "흑관" }, + { val: "MOP894", text: "흙" }, + { val: "MOP895", text: "AP" }, + { val: "MOP896", text: "API관" }, + { val: "MOP897", text: "ASP" }, + { val: "MOP898", text: "CMCIP" }, + { val: "MOP899", text: "CSP" }, + { val: "MOP900", text: "DRP" }, + { val: "MOP901", text: "DSP" }, + { val: "MOP902", text: "DTC관" }, + { val: "MOP903", text: "ELP" }, + { val: "MOP904", text: "EPP" }, + { val: "MOP905", text: "FC관" }, + { val: "MOP906", text: "H" }, + { val: "MOP907", text: "H6" }, + { val: "MOP908", text: "HCP" }, + { val: "MOP909", text: "HI_2P관" }, + { val: "MOP910", text: "HI-KP" }, + { val: "MOP911", text: "HL" }, + { val: "MOP912", text: "IP" }, + { val: "MOP913", text: "KCGP" }, + { val: "MOP914", text: "KP관" }, + { val: "MOP915", text: "P2S관" }, + { val: "MOP916", text: "PC박스(PCB)" }, + { val: "MOP917", text: "PCS" }, + { val: "MOP918", text: "PDP" }, + { val: "MOP919", text: "PE이중벽관" }, + { val: "MOP920", text: "PE적측벽1종관" }, + { val: "MOP921", text: "PFP관" }, + { val: "MOP922", text: "PG관" }, + { val: "MOP923", text: "PIP관(이중보온관)" }, + { val: "MOP924", text: "PLCSP" }, + { val: "MOP925", text: "PS" }, + { val: "MOP926", text: "PUB" }, + { val: "MOP927", text: "PVB" }, + { val: "MOP928", text: "PVC이중벽관(PVC2)" }, + { val: "MOP929", text: "PVC-DC" }, + { val: "MOP930", text: "PVC-DV" }, + { val: "MOP931", text: "SBK" }, + { val: "MOP932", text: "SCP" }, + { val: "MOP933", text: "SEB" }, + { val: "MOP934", text: "SIS관(이중보온관)" }, + { val: "MOP935", text: "SMC" }, + { val: "MOP936", text: "STW" }, + { val: "MOP937", text: "SUS" }, + { val: "MOP938", text: "THP나선관" }, + { val: "MOP939", text: "U관" }, + { val: "MOP940", text: "VG2" }, + { val: "MOP941", text: "WSP(와사피)" }, + { val: "MOP942", text: "Steel Grating" }, + { val: "MOP943", text: "모래" }, + { val: "MOP944", text: "인조석" }, + { val: "MOP945", text: "SPOL" }, + { val: "MOP946", text: "PCF관(강판보강 PE 나선형관)" }, + { val: "MOP947", text: "PVC3(PVC3중벽관)" }, + { val: "MOP948", text: "PE다중벽관" }, + { val: "MOP977", text: "전주용입상관" }, + { val: "MOP978", text: "MD관" }, + { val: "그 외", text: "미분류" }, +]; // 하수처리시설 export const SwtrmtFcltCol = [ @@ -306,7 +513,6 @@ export const ExclnSewagePumpCol2 = [ { id: 'exclnWpmpAblt', title: '우수양수능력(m²/d)' }, // { id: 'instMngNo', title: '기관관리번호' }, ] - // 오수펌프장 export const DrtwSewagePumpCol1 = [ // { id: 'fid', title: 'FID' }, @@ -348,6 +554,17 @@ export const DrtwSewagePumpCol2 = [ { id: 'exclnWpmpAblt', title: '오수양수능력(m²/d)' }, // { id: 'instMngNo', title: '기관관리번호' }, ] +// 펌프장 용도 코드표 +export const DRTW_SEWAGE_PUMP_USE_CODES = [ + { val: "SBE000", text: "미분류" }, + { val: "SBE001", text: "빗물펌프장" }, + { val: "SBE002", text: "오수펌프장" }, + { val: "SBE003", text: "처리장내펌프장" }, + { val: "SBE900", text: "오수배제" }, + { val: "SBE901", text: "우수배제" }, + { val: "SBE999", text: "기타" }, + { val: "그 외", text: "미분류" }, +]; // 우수토실 export const stofcbrCol = [ diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx index 26b3a60aa..38b0c25d6 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx @@ -1,18 +1,18 @@ 'use client' import { VerticalTable } from '@/components/ui/verticalTable'; -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' import InputSection from '../InputSection'; import { handleInputChange } from '../common'; // 하수관로 const inputColumn = [ - { id: "title", title: "설치주제", type: "select", options: ["BTL", "재정사업"] }, - { id: "swtrmt_zone_cd", title: "처리구역", type: "input" }, - { id: "basu", title: "배수구역", type: "input" }, - { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, - { id: "wltjs", title: "지선/간선", type: "select", options: ["지선", "간선"] }, - { id: "flow", title: "흐름방식", type: "select", options: ["자연유하", "압송"] }, - { id: "place", title: "매설위치", type: "select", options: ["도로", "하상"] }, + { id: "instlMbdyCd", title: "설치주제", type: "select", options: ["BTL", "재정사업"] }, + { id: "swtrmtZoneCd", title: "처리구역", type: "input" }, + { id: "mltvZoneNm", title: "배수구역", type: "input" }, + { id: "mltvDtdvNm", title: "배수분구", type: "input" }, + { id: "lineCd", title: "지선/간선", type: "select", options: ["지선", "간선"] }, + { id: "floCd", title: "흐름방식", type: "select", options: ["자연유하", "압송"] }, + { id: "layCd", title: "매설위치", type: "select", options: ["도로", "하상"] }, ]; const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClick?: () => void }) => { @@ -20,29 +20,48 @@ const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClic { year: "2025", type: "개대체" }, { year: "2025", type: "보수" }, ]); - const [cleaningData, setCleaningData] = useState([ { year: "2025", type: "청소" }, { year: "2025", type: "준설" }, ]); - const [inspectionData, setInspectionData] = useState([ { year: "2025", type: "관로기술진단" }, { year: "2025", type: "관로기술진단" }, ]); - const dataMap = { repair: { data: repairData, setData: setRepairData }, cleaning: { data: cleaningData, setData: setCleaningData }, inspection: { data: inspectionData, setData: setInspectionData }, }; + const [formData, setFormData] = useState({}); + + // featureData가 변경될 때 formData 초기화 + useEffect(() => { + if (featureData) { + setFormData(featureData); + } + }, [featureData]); + + // 폼 데이터가 변경될 때 호출될 핸들러 + const handleFormDataChange = (newFormData: any) => { + setFormData(newFormData); + }; + + // 저장 버튼 클릭 시 최신 formData를 부모에게 전달 + const handleSaveClick = () => { + if (onSaveClick) { + // 저장 전에 formData를 부모 컴포넌트의 handleSaveClick에 전달 + onSaveClick(); + } + }; + return ( <> void }) => { const [isModalOpen, setIsModalOpen] = useState(false); const [isDataLoaded, setIsDataLoaded] = useState(false); + const [formData, setFormData] = useState({}); console.log('featureData data received:', featureData); // 추가 데이터 확인용 console.log('Additional data received:', additionalData); // 추가 데이터 확인용 + const openModal = () => { setIsModalOpen(true); }; + const closeModal = () => { setIsModalOpen(false); if (!isDataLoaded) { @@ -31,11 +34,25 @@ const Ssc = ({ featureData, chkMainSsc, additionalData, onSaveClick }: { } }; - // 데이터 전처리: 합쳐진 필드 추가 - // const preprocessedData = featureData ? [{ - // ...featureData, - // flwmtr_combined: `${featureData.flwmtr_mesure_tp_etc || '-'} / ${featureData.flwmtr_knd || '-'}` - // }] : []; + // featureData가 변경될 때 formData 초기화 + useEffect(() => { + if (featureData) { + setFormData(featureData); + } + }, [featureData]); + + // 폼 데이터가 변경될 때 호출될 핸들러 + const handleFormDataChange = (newFormData: any) => { + setFormData(newFormData); + }; + + // 저장 버튼 클릭 시 최신 formData를 부모에게 전달 + const handleSaveClick = () => { + if (onSaveClick) { + // 저장 전에 formData를 부모 컴포넌트의 handleSaveClick에 전달 + onSaveClick(); + } + }; const renderModalBody = () => (
@@ -100,23 +117,26 @@ const Ssc = ({ featureData, chkMainSsc, additionalData, onSaveClick }: { return (
- + {!isMainSsc && ( + + )} - {chkMainSsc && ( + {isMainSsc && (

중점우수토실 운영정보

diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx index f0c4d21b3..0da4ab31e 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx @@ -1,22 +1,46 @@ import { VerticalTable } from '@/components/ui/verticalTable'; -import React from 'react' +import React, { useState, useEffect } from 'react' +// 빗물펌프 자체 입력 정보 const exclnInputColumn = [ - { id: "swtrmt_zone_cd", title: "배수구역", type: "input" }, - { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, - { id: "freq", title: "설계빈도(년)", type: "input" }, + { id: "swtrmtZoneCd", title: "배수구역", type: "input" }, + { id: "mltvDtdvNm", title: "배수분구", type: "input" }, + { id: "dsgnFrqnc", title: "설계빈도(년)", type: "input" }, ] +// 오수펌프 자체 입력 정보 const drtwInputColumn = [ { id: "swtrmt_zone_cd", title: "배수구역", type: "input" }, { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, ] // 하수펌프장 -const sewagePump = ({ featureData, onSaveClick }: { featureData: any, onSaveClick?: () => void }) => { +const sewagePump = ({ featureData, isDrtwSewagePump, onSaveClick }: { featureData: any, isDrtwSewagePump: boolean, onSaveClick?: () => void }) => { + const [formData, setFormData] = useState({}); + + // featureData가 변경될 때 formData 초기화 + useEffect(() => { + if (featureData) { + setFormData(featureData); + } + }, [featureData]); + + // 폼 데이터가 변경될 때 호출될 핸들러 + const handleFormDataChange = (newFormData: any) => { + setFormData(newFormData); + }; + + // 저장 버튼 클릭 시 최신 formData를 부모에게 전달 + const handleSaveClick = () => { + if (onSaveClick) { + // 저장 전에 formData를 부모 컴포넌트의 handleSaveClick에 전달 + onSaveClick(); + } + }; + return ( ) } diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx index 7f2251063..e2a2cc747 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx @@ -1,17 +1,39 @@ // 하수맨홀 import { VerticalTable } from '@/components/ui/verticalTable'; -import React from 'react' +import React, { useState, useEffect } from 'react' const inputColumn = [ - { id: "guyeok", title: "처리구역", type: "input" }, - { id: "basu", title: "배수구역", type: "input" }, - { id: "bungu", title: "배수분구", type: "input" }, - { id: "place", title: "매설위치", type: "select", options: ["도로", "하상"] }, + { id: "swtrmtZoneCd", title: "처리구역", type: "input" }, + { id: "mltvZoneNm", title: "배수구역", type: "input" }, + { id: "mltvDtdvNm", title: "배수분구", type: "input" }, + { id: "layCd", title: "매설위치", type: "select", options: ["도로", "하상"] }, ]; const Smh = ({ featureData, onSaveClick }: { featureData: any, onSaveClick?: () => void }) => { + const [formData, setFormData] = useState({}); + + // featureData가 변경될 때 formData 초기화 + useEffect(() => { + if (featureData) { + setFormData(featureData); + } + }, [featureData]); + + // 폼 데이터가 변경될 때 호출될 핸들러 + const handleFormDataChange = (newFormData: any) => { + setFormData(newFormData); + }; + + // 저장 버튼 클릭 시 최신 formData를 부모에게 전달 + const handleSaveClick = () => { + if (onSaveClick) { + // 저장 전에 formData를 부모 컴포넌트의 handleSaveClick에 전달 + onSaveClick(); + } + }; + return ( ) } diff --git a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx index 72831902f..95cab06c7 100644 --- a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx @@ -1,15 +1,16 @@ 'use client' -import { getData, putData } from "@/components/lib/api"; +import { getData, postData } from "@/components/lib/api"; import Modal from "@/components/ui/modal"; import { VerticalTable } from "@/components/ui/verticalTable"; import { useGisContext } from "@common/business_components/ui/map/Gis"; import { Button } from "@common/components/ui"; import { useEffect, useRef, useState, useCallback, useMemo } from "react"; import { getLayerContentComponent } from "./components/common"; -import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, ExclnSewagePumpCol, MsSwageMhlCol, stofcbrCol, MS_SWAGE_MHL_CODES } from "./components/common/table"; +import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, ExclnSewagePumpCol, MsSwageMhlCol, stofcbrCol, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table"; import InfilChart from './components/popupComponent/chart/infilChart'; import RdiiChart from './components/popupComponent/chart/rdiiChart'; import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore"; +import { set } from "react-hook-form"; // TODO: const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, featureData: any }) => { @@ -23,7 +24,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, const [fetchData, setfetchData] = useState(); // api 호출여부 const contentRef = useRef(null); const [isModalOpen, setIsModalOpen] = useState(false); // 모달 열기 상태 - const [chkMainSsc, setChkMainSsc] = useState(false); // 중점우수토실 여부 + const [isMainSsc, setIsMainSsc] = useState(false); // 중점우수토실 여부 + const [isDrtwSewagePump, setIsDrtwSewagePump] = useState(false); // 오수펌프장 여부 const [isLoading, setIsLoading] = useState(false); // 🎯 추가 데이터 로딩 상태 분리 const [isAdditionalDataLoading, setIsAdditionalDataLoading] = useState(false); @@ -54,17 +56,10 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, try { console.log(`추가 데이터 API 호출 시작: v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs`); - // 🎯 타임아웃 설정 (10초) - const timeoutPromise = new Promise((_, reject) => - setTimeout(() => reject(new Error('API 타임아웃')), 10000) - ); + const result = getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs`); - const apiPromise = getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs`); - - const response = await Promise.race([apiPromise, timeoutPromise]) as any; - - console.log('추가 데이터 API 호출 성공:', response); - return response?.content || []; + console.log('추가 데이터 API 호출 성공:', result); + return result || []; } catch (error) { console.error('추가 데이터 로딩 실패:', error); setAdditionalDataError(error instanceof Error ? error.message : '알 수 없는 오류'); @@ -106,7 +101,16 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, else if (featureData.lyrTypeNm === 'tb_ms_stofcbr') result = '우수토실'; else if (featureData.lyrTypeNm === 'om_dt_untrt_swg_rain') result = '중점우수토실'; else if (featureData.lyrTypeNm === 'tb_ms_swage_ppl') result = '하수관로'; - else if (featureData.lyrTypeNm === 'tb_ms_swage_pmstn') result = '하수펌프장'; + else if (featureData.lyrTypeNm === 'tb_ms_swage_pmstn') { + const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); + console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val); + if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) { + setIsDrtwSewagePump(true); + } else { + setIsDrtwSewagePump(false); + } + result = '하수펌프장'; + } else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') result = '하수맨홀'; } else { @@ -116,7 +120,16 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, else if (lyrTyNm === 'tb_ms_stofcbr') result = '우수토실'; else if (lyrTyNm === 'om_dt_untrt_swg_rain') result = '중점우수토실'; else if (lyrTyNm === 'tb_ms_swage_ppl') result = '하수관로'; - else if (lyrTyNm === 'tb_ms_swage_pmstn') result = '하수펌프장'; + else if (lyrTyNm === 'tb_ms_swage_pmstn') { + const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); + console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val); + if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) { + setIsDrtwSewagePump(true); + } else { + setIsDrtwSewagePump(false); + } + result = '하수펌프장'; + } else if (lyrTyNm === 'tb_ms_swage_mhl') result = '하수맨홀'; else result = featureLayer.get('lyrNm'); } @@ -170,7 +183,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, setHeadlist(untrtSwgRainCol1) setHeadlist2(untrtSwgRainCol2) setButtonChk(false) - setChkMainSsc(true) + setIsMainSsc(true) setfetchData([processedData]) setTableData(processedData); @@ -188,11 +201,11 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, setMntrngsData(false); }); } - return; + break; case '우수토실': setHeadlist(stofcbrCol) - setButtonChk(false) - setChkMainSsc(false) + setButtonChk(true) + setIsMainSsc(false) break; case '하수관로': setHeadlist(MsSwagePplCol) @@ -215,6 +228,59 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, default: break; } + + // API 엔드포인트 선택 + let apiEndpoint = ''; + let getFeatureId = featureId.toString().split('.').pop() || null; + if (selectedLayerName === '하수관로') apiEndpoint = `v1/fcltppl/${getFeatureId}`; + else if (selectedLayerName === '우수토실') apiEndpoint = `v1/fcltstofcbr/${getFeatureId}`; + else if (selectedLayerName === '오수펌프' || selectedLayerName === '빗물펌프') apiEndpoint = `v1/fcltpump/${getFeatureId}`; + else if (selectedLayerName === '하수맨홀') apiEndpoint = `v1/fcltmhl/${getFeatureId}`; + + // API에서 상세 데이터 가져오기 + if (apiEndpoint) { + try { + console.log(`API 호출: ${apiEndpoint}`); + const result = await getData(apiEndpoint); + + if (result) { + console.log('API 데이터 로드 성공:', result); + + // 하수맨홀인 경우 용도코드를 텍스트로 변환 + if (selectedLayerName === '하수맨홀') { + const processedData = { ...result }; + + // mqlt_cd 값 변환 (재질코드) + if (processedData.mqlt_cd) { + const materialCodeItem = MS_SWAGE_MHL_CODES.find( + code => code.val === processedData.mqlt_cd.trim() + ); + if (materialCodeItem) { + processedData.mqlt_cd = `${materialCodeItem.text}`; + } + } + + setfetchData(processedData); + } // 🎯 우수토실인 경우 prrtymngYn 값 변환 + else if (selectedLayerName === '우수토실' && data) { + const processedData = { ...result, ...data }; + + // prrtymngYn 값 변환 + if (processedData.prrtymngYn === 'Y') processedData.prrtymngYn = '중점우수토실'; + else if (processedData.prrtymngYn === 'N') processedData.prrtymngYn = '우수토실'; + + console.log('processedData', processedData); + + setfetchData(processedData); + } else { + setfetchData(result); + } + } + } catch (apiError) { + console.error('API 데이터 로딩 중 오류:', apiError); + } + } + console.log('mntrngsData', mntrngsData); } catch (error) { console.error('데이터 로딩 중 오류:', error); } @@ -275,27 +341,50 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, bodyData[camelCaseId] = select.value; }); - // input 태그의 값 가져오기 + // // input 태그의 값 가져오기 inputElements.forEach((input) => { const camelCaseId = toCamelCase(input.id); bodyData[camelCaseId] = input.value; }); - if (layerNm === '하수관로') bodyData['lyrTypeNm'] = 'tb_ms_swage_ppl' - else if (layerNm === '우수토실') bodyData['lyrTypeNm'] = 'tb_ms_stofcbr' - else if (layerNm === '중점우수토실') bodyData['lyrTypeNm'] = 'om_dt_untrt_swg_rain' - else if (layerNm === '오수펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn' - else if (layerNm === '빗물펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn' - else if (layerNm === '하수맨홀') bodyData['lyrTypeNm'] = 'tb_ms_swage_mnhl' + // 레이어명에 따라 API 엔드포인트 분기처리 + let apiEndpoint = ''; + let result = null; - bodyData['fid'] = featureId + if (layerNm === '하수관로') apiEndpoint = 'v1/fcltppl'; + else if (layerNm === '우수토실') apiEndpoint = 'v1/fcltstofcbr'; + else if (layerNm === '하수펌프장') apiEndpoint = 'v1/fcltpump'; + else if (layerNm === '하수맨홀') apiEndpoint = 'v1/fcltmhl'; - const data = await putData(`v1/fclts/${featureId}`, bodyData); + bodyData['fid'] = featureId.toString().split('.').pop() || null; + // 빈 키 제거 + if (bodyData[""] !== undefined) delete bodyData[""]; - if (data.status == 200) { - alert('저장되었습니다') - setTableData(data) - setfetchData(data) + // 🎯 우수토실일 경우 prrtymngYn 값 변환 + if (layerNm === '우수토실' && bodyData.prrtymngYn) { + if (bodyData.prrtymngYn === '중점우수토실') { + bodyData.prrtymngYn = 'Y'; + } else if (bodyData.prrtymngYn === '우수토실') { + bodyData.prrtymngYn = 'N'; + } + } + console.log('bodyData', bodyData); + console.log('apiEndpoint', apiEndpoint); + + try { + result = await postData(apiEndpoint, bodyData); + console.log('result', result); + + if (result) { + alert('저장되었습니다'); + setfetchData(result.data || result); + } else { + alert('저장에 실패했습니다'); + console.error('API 응답 오류:', result); + } + } catch (error) { + alert('저장 중 오류가 발생했습니다'); + console.error('API 요청 오류:', error); } } } @@ -363,7 +452,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, {ContentComponent && diff --git a/apps/sn/app/components/lib/api/index.ts b/apps/sn/app/components/lib/api/index.ts index e4a750ff3..55d111074 100644 --- a/apps/sn/app/components/lib/api/index.ts +++ b/apps/sn/app/components/lib/api/index.ts @@ -9,6 +9,8 @@ export const postData = async (url: string, data: object): Promise => { body: JSON.stringify(data), }; const res = await fetch(`${BASE_URL}/${url}`, options); + console.log('res', res); + console.log('res.status', res.status); if (res.ok) { const resData = await res.json(); return resData; diff --git a/apps/sn/app/components/ui/verticalTable.tsx b/apps/sn/app/components/ui/verticalTable.tsx index 19e302c30..2f8143409 100644 --- a/apps/sn/app/components/ui/verticalTable.tsx +++ b/apps/sn/app/components/ui/verticalTable.tsx @@ -29,6 +29,7 @@ type UiTableProps = { showSecondTable?: boolean; showSaveButton?: boolean; onSaveClick?: () => void; + onFormDataChange?: (formData: { [key: string]: string | number | boolean }) => void; // 추가 }; type UiHeadProps = { @@ -66,6 +67,7 @@ export function VerticalTable({ showSecondTable = false, showSaveButton = false, onSaveClick, + onFormDataChange, }: UiTableProps) { const [cur, setCur] = useState(1); const [formData, setFormData] = useState<{ [key: string]: string | number | boolean }>({}); @@ -78,17 +80,27 @@ export function VerticalTable({ useEffect(() => { if (tableData.length > 0 && tableData[0]) { - setFormData(tableData[0] as { [key: string]: string | number | boolean }); + // 깊은 복사를 통해 새로운 객체 생성 + const newData = JSON.parse(JSON.stringify(tableData[0])); + setFormData(newData); + console.log("Form data initialized:", newData); // 디버깅용 } }, [tableData]); const handleInputChange = (id: string, value: string | number | boolean) => { - setFormData((prev) => ({ - ...prev, + console.log(`Input change: ${id} = ${value}`); // 디버깅용 + const newFormData = { + ...formData, [id]: value, - })); - }; + }; + console.log("New form data:", newFormData); // 디버깅용 + setFormData(newFormData); + // 폼 데이터가 변경될 때마다 부모에게 알림 + if (onFormDataChange) { + onFormDataChange(newFormData); + } + }; const handlePageChange = (page: number) => { setCur(page); onPageChange(page); @@ -100,8 +112,8 @@ export function VerticalTable({

{headName}

{showSaveButton && onSaveClick && ( -