From 792e38c0c5db037f9dfa7945088da6dea40a8eb5 Mon Sep 17 00:00:00 2001 From: swcho Date: Mon, 11 Aug 2025 17:39:59 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20-=20=EC=9A=B4=EC=98=81=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EA=B2=80=EC=83=89=EC=97=90=20=ED=95=98=EC=88=98?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=EA=B5=AC=EC=97=AD=20=EC=BB=AC=EB=9F=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=EA=B8=B0=EB=B3=B8=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=20=ED=95=98=EC=88=98=EA=B4=80=EB=A1=9C=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=EC=97=90=20=EC=8B=9C=EB=8F=84,=20=EC=8B=9C=EA=B5=B0=EA=B5=AC,?= =?UTF-8?q?=20=EC=9A=A9=EB=8F=84=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20-=20=EA=B3=B5=ED=86=B5=20=EC=BD=94=EB=93=9C=20=EC=8B=9C?= =?UTF-8?q?=EB=8F=84,=20=EC=8B=9C=EA=B5=B0=EA=B5=AC=20API=20=EC=9B=90?= =?UTF-8?q?=EC=95=A4=EC=98=AC=20->=20=EC=95=8C=EC=95=A0=EC=8A=A4=EC=9B=90?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/app/(map-layout)/layout.tsx | 5 +- .../map/components/common/table.ts | 9 ++-- .../(map-layout)/map/searchModal/basicTab.tsx | 14 ++++-- .../map/searchModal/operationTab.tsx | 15 +++++- .../map/searchModal/searchModal.tsx | 49 +++++++++++++------ .../(map-layout)/map/searchModal/swagePpl.tsx | 26 ++++++++-- .../map/searchModal/swagePrcsFclt.tsx | 10 ++-- .../map/searchModal/swagePrcsZone.tsx | 12 ++--- .../app/(with-base-layout)/ii/BaseLayout.tsx | 12 ++--- apps/sn/app/(with-base-layout)/layout.tsx | 5 +- .../ui/ctpvSggPrcsFcltSelectBox.tsx | 39 ++++++--------- apps/sn/app/store/index.ts | 48 +++++++++--------- apps/sn/app/store/useStore.ts | 16 +++--- .../src/ui/map/searchBar/procSearchBar.tsx | 30 +++++++----- 14 files changed, 174 insertions(+), 116 deletions(-) diff --git a/apps/sn/app/(map-layout)/layout.tsx b/apps/sn/app/(map-layout)/layout.tsx index 2077e5756..2ea6758b3 100644 --- a/apps/sn/app/(map-layout)/layout.tsx +++ b/apps/sn/app/(map-layout)/layout.tsx @@ -19,10 +19,11 @@ export default function MapLayout({ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); - const { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); + const { fetchCtpv, fetchSgg, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); useEffect(() => { - fetchCtpvSggData(); + fetchCtpv(); + fetchSgg(); fetchBIZ_SE_CD(); fetchBIZ_TY_CD(); }, []); 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 1e34f5475..238ba7599 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -31,17 +31,20 @@ export const MsSwagePplCol2 = [ { id: 'rowNumber', title: '일련\n번호' }, { id: 'fcltMngNo', title: '시설\n관리번호' }, { id: 'instMngNo', title: '기관\n관리번호' }, + { id: 'ctpvNm', title: '시도' }, + { id: 'sggNm', title: '시군구' }, { id: 'instlYmd', title: '설치일자' }, // { id: 'mapshtNo', title: '도엽번호' }, + { id: 'usgCd', title: '용도' }, { id: 'pdmtVl', title: '관경\n(mm)' }, { id: 'prlgVl', title: '연장\n(m)' }, - { id: 'avgGrdn', title: '평균구배\n(m/m)' }, + // { id: 'avgGrdn', title: '평균구배\n(m/m)' }, { id: 'tmptDpth', title: '시점깊이\n(m)' }, { id: 'tmptMhlMngNo', title: '시점맨홀\n관리번호' }, { id: 'scendDpth', title: '종점깊이\n(m)' }, { id: 'scendMhlMngNo', title: '종점맨홀\n관리번호' }, - { id: 'vrtcLen', title: '세로길이\n(m)' }, - { id: 'wdthLen', title: '가로길이\n(m)' }, + // { id: 'vrtcLen', title: '세로길이\n(m)' }, + // { id: 'wdthLen', title: '가로길이\n(m)' }, // { id: 'fcltyShpCd', title: '시설물형태코드' }, // { id: 'fid', title: 'FID' }, // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, diff --git a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx index 018f67883..7a783f139 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { SelectBox } from '@common/business_components/ui'; -import { Button, Input, Label } from '@common/components'; +import { Button, Label } from '@common/components'; import SwagePpl from './swagePpl'; import SwagePrcsFclt from './swagePrcsFclt'; import SwagePrcsZone from './swagePrcsZone'; @@ -20,8 +20,8 @@ export const BASIC_TYPES = [ interface BasicTabProps { basicType: string; - city: number; - sgg: number; + city: string; + sgg: string; start1: string; start2: string; end1: string; @@ -31,9 +31,9 @@ interface BasicTabProps { yearFilter: { start: string; end: string; }; handleSearch: () => void; setBasicType: (type: string) => void; - setCity: (city: number) => void; + setCity: (city: string) => void; setCtpvName: (name: string) => void; - setSgg: (sgg: number) => void; + setSgg: (sgg: string) => void; setSggName: (name: string) => void; setYearFilter: (filter: { start: string; end: string }) => void; setStart1: (value: string) => void; @@ -97,6 +97,8 @@ const BasicTab: React.FC = ({ start2={start2} end1={end1} end2={end2} + city={city} + sgg={sgg} yearFilter={yearFilter} setVar1={setVar1} setVar2={setVar2} @@ -104,6 +106,8 @@ const BasicTab: React.FC = ({ setStart2={setStart2} setEnd1={setEnd1} setEnd2={setEnd2} + setCity={setCity} + setSgg={setSgg} setYearFilter={setYearFilter} handleSearch={handleSearch} /> diff --git a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx index 155a17215..446632965 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx @@ -24,7 +24,10 @@ export const operationTableHeadlist = [ export const operationMaintenanceTableHeadlist = [ { id: 'rowNumber', title: '일련번호' }, { id: "fcltMngNo", title: "관리번호" }, + { id: "swtrmt_zone_nm", title: "처리구역" }, { id: "usgCd", title: "용도" }, + // { id: "lgalDrblyr", title: "내용연수" }, + // { id: "acqsPrmpc", title: "취득금액" }, { id: "mqltCd", title: "재질" }, { id: "pdmtVl", title: "관경(mm)" }, { id: "prlgVl", title: "연장(m)" }, @@ -35,7 +38,10 @@ export const operationMaintenanceTableHeadlist = [ export const operationCleaningTableHeadlist = [ { id: 'rowNumber', title: '일련번호' }, { id: "fcltMngNo", title: "관리번호" }, + { id: "swtrmt_zone_nm", title: "처리구역" }, { id: "usgCd", title: "용도" }, + // { id: "lgalDrblyr", title: "내용연수" }, + // { id: "acqsPrmpc", title: "취득금액" }, { id: "mqltCd", title: "재질" }, { id: "pdmtVl", title: "관경(mm)" }, { id: "prlgVl", title: "연장(m)" }, @@ -45,13 +51,18 @@ export const operationCleaningTableHeadlist = [ export const operationInspectionTableHeadlist = [ { id: 'rowNumber', title: '일련번호' }, { id: "fcltMngNo", title: "관리번호" }, + { id: "swtrmt_zone_nm", title: "처리구역" }, { id: "usgCd", title: "용도" }, + // { id: "riskEval", title: "위험평가" }, + // { id: "acqsPrmpc", title: "취득금액" }, + // { id: "lgalDrblyr", title: "내용연수" }, + // { id: "remLife", title: "잔존수명" }, { id: "mqltCd", title: "재질" }, { id: "pdmtVl", title: "관경(mm)" }, { id: "prlgVl", title: "연장(m)" }, { id: "instlYmd", title: "설치일자" }, - { id: "strct_stat_grd", title: "구조적 상태등급" }, - { id: "oper_stat_grd", title: "운영적 상태등급" }, + { id: "strc_stts_grd", title: "구조적 상태등급" }, + { id: "oper_stts_grd", title: "운영적 상태등급" }, ]; interface OperationTabProps { diff --git a/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx index 71e7c8855..ccce61561 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx @@ -61,9 +61,9 @@ const SearchModal: React.FC = ({ const [isResetSelection, setIsResetSelection] = useState(false); const [isResetDetailSelection, setIsResetDetailSelection] = useState(false); const [detailBizId, setDetailBizId] = useState(0); - const [city, setCity] = useState(0); + const [ctpvCd, setCtpvCd] = useState("0"); const [ctpvName, setCtpvName] = useState(''); - const [sgg, setSgg] = useState(0); + const [sggCd, setSggCd] = useState("0"); const [sggName, setSggName] = useState(''); const [start1, setStart1] = useState(""); const [start2, setStart2] = useState(""); @@ -76,7 +76,7 @@ const SearchModal: React.FC = ({ // 시작, 종료 const [yearFilter, setYearFilter] = useState({ start: "", end: "" }); - const { BIZ_TY_CD } = useStore(); + const { ctpv, sgg, BIZ_TY_CD, BIZ_SE_CD } = useStore(); // 오늘 날짜 구하기 @@ -104,8 +104,8 @@ const SearchModal: React.FC = ({ const dynamicHeadlist2: { id: string, title: string }[] = useMemo(() => { if (activeTab === 'operation') { if (workType === WORK_TYPES[0]?.val) return operationMaintenanceTableHeadlist; - if (workType === WORK_TYPES[1]?.val) return operationCleaningTableHeadlist; - if (workType === WORK_TYPES[2]?.val) return operationInspectionTableHeadlist; + if (workType === WORK_TYPES[1]?.val) return operationInspectionTableHeadlist; + if (workType === WORK_TYPES[2]?.val) return operationCleaningTableHeadlist; } return []; @@ -121,8 +121,8 @@ const SearchModal: React.FC = ({ setVar2(""); setVar3(""); setVar4(""); - setCity(0); - setSgg(0); + setCtpvCd("0"); + setSggCd("0"); setYearFilter({ start: "", end: "", @@ -204,14 +204,30 @@ const SearchModal: React.FC = ({ const dataWithRowNumber = (res.data.data || []).map((item: any, index: number) => { // 🎯 먼저 각 아이템을 포맷팅 const formattedItem = formatDisplayData(item); - const matched = MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim()); + + let ctpvCd = item?.ctpvNm ?? formattedItem?.ctpvNm ?? ''; + let sggCd = item?.sggNm ?? formattedItem?.sggNm ?? ''; + + if (!ctpvCd || !sggCd) { + const code = String(item?.pbadmsEmdCd ?? formattedItem?.pbadmsEmdCd ?? '').trim(); + if (!ctpvCd && code) ctpvCd = code.slice(0, 2); + if (!sggCd && code) sggCd = code.slice(0, 5); + } + + const matchedMhlCode = MS_SWAGE_MHL_CODES.find(code => code.val === item?.mqltCd?.trim()); + const ctpvNm = ctpv.find(code => code.val.trim() === ctpvCd)?.text || ctpvCd; + const sggNm = sgg.find(code => code.val.trim() === sggCd)?.text || '-'; + const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item?.usgCd?.trim()); // 추가 처리 및 일련번호 추가 return { ...formattedItem, rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가 scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item.scsYn, // scsYn이 null이면 'N'으로 변경 - mqltCd: matched ? matched.text : item.mqltCd, + mqltCd: matchedMhlCode ? matchedMhlCode.text : item.mqltCd, + usgCd: usgCdObj ? usgCdObj.text : item.usgCd, + ctpvNm, + sggNm, }; }); @@ -286,7 +302,8 @@ const SearchModal: React.FC = ({ // 추후 작성 예정 if (var1) cqlFilters.push(`usg_cd='${var1}'`); if (var2) cqlFilters.push(`mqlt_cd='${var2}'`); - if (var3) cqlFilters.push(`pbadms_emd_cd='${var3}'`); + if (ctpvCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${ctpvCd.trim()}%'`); + if (ctpvCd !== '0' && sggCd !== '0') cqlFilters.push(`pbadms_emd_cd LIKE '${sggCd}%'`); // 설치년도 범위 const startDate = getDateString( yearFilter.start, @@ -354,8 +371,8 @@ const SearchModal: React.FC = ({ // 하수처리구역용 CQL 필터 생성 const zoneCqlFilters = () => { const cqlFilters: string[] = []; - if (city) cqlFilters.push(`ctpv_cd='${city}'`); - if (sgg) cqlFilters.push(`sgg_cd='${sgg}'`); + if (ctpvCd !== '' && ctpvCd !== '0') cqlFilters.push(`ctpv_cd='${ctpvCd.trim()}'`); + if (sggCd !== '' && sggCd !== '0') cqlFilters.push(`sgg_cd='${sggCd.trim()}'`); if (var1) cqlFilters.push(`swtrmt_zone_nm ILIKE '%${var1}%'`); if (var2) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var2}%'`); return cqlFilters; @@ -563,8 +580,8 @@ const SearchModal: React.FC = ({ {activeTab === 'basic' && ( = ({ yearFilter={yearFilter} handleSearch={handleSearch} setBasicType={setBasicType} - setCity={setCity} + setCity={setCtpvCd} setCtpvName={setCtpvName} - setSgg={setSgg} + setSgg={setSggCd} setSggName={setSggName} setYearFilter={setYearFilter} setStart1={setStart1} diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx index f729ab6eb..1676b469a 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx @@ -5,6 +5,7 @@ import { SelectBox } from '@common/business_components/ui'; import { Button, Input, Label } from '@common/components'; import React from 'react'; import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES } from '../components/common/table'; +import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox'; interface SwagePplProps { var1: string; @@ -13,6 +14,8 @@ interface SwagePplProps { start2: string; end1: string; end2: string; + city: string; + sgg: string; yearFilter: { start: string; end: string }; setVar1: (value: string) => void; setVar2: (value: string) => void; @@ -20,6 +23,8 @@ interface SwagePplProps { setStart2: (value: string) => void; setEnd1: (value: string) => void; setEnd2: (value: string) => void; + setCity: (value: string) => void; + setSgg: (value: string) => void; setYearFilter: (filter: { start: string; end: string }) => void; handleSearch: () => void; } @@ -31,6 +36,8 @@ const SwagePpl: React.FC = ({ start2, end1, end2, + city, + sgg, yearFilter, setVar1, setVar2, @@ -38,6 +45,8 @@ const SwagePpl: React.FC = ({ setStart2, setEnd1, setEnd2, + setCity, + setSgg, setYearFilter, handleSearch, }) => { @@ -45,6 +54,15 @@ const SwagePpl: React.FC = ({ return (
+ { + setCity(sidoId); + setSgg("0"); + }} + onSigunguChange={setSgg} + /> {/* 설치년도 */} = ({ selectContentClass="z-[101]" /> {/* 재질 */} - + {/* = ({ setVar2(String(val)); }} selectContentClass="z-[101]" - /> + /> */} {/* 관경 */} = ({ }} /> {/* 연장 */} - + {/* = ({ handleSearch(); } }} - /> + /> */} {/* 조회 버튼 */}
diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx index 8779f0fa5..a3db595a5 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx @@ -12,17 +12,17 @@ interface SwagePrcsFcltProps { start2: string; end1: string; end2: string; - city: number; - sgg: number; + city: string; + sgg: string; yearFilter: { start: string; end: string }; setVar1: (value: string) => void; setStart1: (value: string) => void; setStart2: (value: string) => void; setEnd1: (value: string) => void; setEnd2: (value: string) => void; - setCity: (value: number) => void; + setCity: (value: string) => void; setCtpvName: (name: string) => void; - setSgg: (value: number) => void; + setSgg: (value: string) => void; setSggName: (name: string) => void; setYearFilter: (filter: { start: string; end: string }) => void; handleSearch: () => void; @@ -52,7 +52,7 @@ const SwagePrcsFclt: React.FC = ({ sigungu={sgg} onSidoChange={(sidoId) => { setCity(sidoId); - setSgg(0); + setSgg("0"); }} onSigunguChange={setSgg} setCtpvName={setCtpvName} diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx index 8cb304d2a..9f8e8a181 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx @@ -7,12 +7,12 @@ import React from 'react'; interface swagePrcsZoneProps { var1: string; var2: string; - city: number; - sgg: number; + city: string; + sgg: string; setVar1: (value: string) => void; setVar2: (value: string) => void; - setCity: (value: number) => void; - setSgg: (value: number) => void; + setCity: (value: string) => void; + setSgg: (value: string) => void; handleSearch: () => void; } @@ -34,9 +34,9 @@ const swagePrcsZone: React.FC = ({ { + onSidoChange={(sidoId: string) => { setCity(sidoId); - setSgg(0); + setSgg("0"); }} onSigunguChange={setSgg} /> diff --git a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx index 275126474..68f5ec068 100644 --- a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx +++ b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx @@ -39,8 +39,8 @@ type BaseLayout = { firstDivBtn?: boolean selectBox?: SelectBox showDatePicker?: boolean; - ctpvCd: number; - sggCd: number; + ctpvCd: string; + sggCd: string; sggName?: string; sigungu?: ApiSelectOption selectedSwagePrcsFclt?: string | number; @@ -49,8 +49,8 @@ type BaseLayout = { setAplcnYmFrom?: (aplcnYmFrom: string) => void; aplcnYmTo?: string setAplcnYmTo?: (aplcnYmTo: string) => void; - setCtpvCd: (ctpv: number) => void; - setSggCd: (sgg: number) => void; + setCtpvCd: (ctpv: string) => void; + setSggCd: (sgg: string) => void; setSggName?: (sggName: string) => void; setSwtrmtFcltNm?: (swtrmtFcltNm: string) => void; setIsLoading?: (isLoading: boolean) => void; @@ -178,9 +178,9 @@ const BaseLayout = ({ sido={ctpvCd} sigungu={sggCd} sggName={sggName} - onSidoChange={(sidoId: number) => { + onSidoChange={(sidoId: string) => { setCtpvCd(sidoId); - setSggCd(0); + setSggCd('0'); }} onSigunguChange={setSggCd} setSggName={setSggName} diff --git a/apps/sn/app/(with-base-layout)/layout.tsx b/apps/sn/app/(with-base-layout)/layout.tsx index f8e046717..229415e53 100644 --- a/apps/sn/app/(with-base-layout)/layout.tsx +++ b/apps/sn/app/(with-base-layout)/layout.tsx @@ -20,10 +20,11 @@ export default function WithBaseLayout({ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); - const { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); + const { fetchCtpv, fetchSgg, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); useEffect(() => { - fetchCtpvSggData(); + fetchCtpv(); + fetchSgg(); fetchBIZ_SE_CD(); fetchBIZ_TY_CD(); }, []); diff --git a/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx b/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx index a7472d4c0..9b9df0724 100644 --- a/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx +++ b/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo, useEffect } from "react"; +import React, { useState, useEffect } from "react"; import { SelectBox } from '@common/business_components/ui' import { Label } from '@common/components'; import useStore from '../../store/useStore'; @@ -10,11 +10,11 @@ interface ApiSelectOption { val: string; } interface CtpvSggPrcsFcltSelectBoxProps { - sido: number; - sigungu: number; + sido: string; + sigungu: string; sggName?: string; - onSidoChange: (id: number) => void; - onSigunguChange: (id: number) => void; + onSidoChange: (id: string) => void; + onSigunguChange: (id: string) => void; setCtpvName?: (name: string) => void; setSggName?: (name: string) => void; className?: string; @@ -46,14 +46,17 @@ export function CtpvSggPrcsFcltSelectBox({ useEffect(() => { (async () => { - onSidoChange(0); - onSigunguChange(0); + onSidoChange("0"); + onSigunguChange("0"); if (setCtpvName && setSggName) { setCtpvName(""); setSggName(""); } if (setSwtrmtFcltNm) setSwtrmtFcltNm(""); })(); + + console.log("ctpv", ctpv); + console.log("sgg", sgg); }, []); useEffect(() => { @@ -112,15 +115,11 @@ export function CtpvSggPrcsFcltSelectBox({ className="w-60 mr-8" selectClass="rounded-lg bg-white" label="" - selectArray={ - [defaultOption, - ...ctpv.map(opt => ({ val: opt.id, text: opt.name })) - ] - } + selectArray={[defaultOption, ...ctpv]} value={sido} onSelectValue={val => { - onSidoChange(Number(val)); - if (setCtpvName) setCtpvName(ctpv.find(opt => Number(opt.id) === Number(val))?.name || ""); + onSidoChange(String(val)); + if (setCtpvName) setCtpvName(ctpv.find(opt => String(opt.val) === String(val))?.text || ""); if (setSwtrmtFcltNm) setSwtrmtFcltNm(""); }} selectContentClass="z-[101]" @@ -130,17 +129,11 @@ export function CtpvSggPrcsFcltSelectBox({ className="w-48" selectClass="w-48 rounded-lg bg-white truncate" label="" - selectArray={ - [defaultOption, - ...sgg - .filter(opt => String(opt.id).slice(0, 2) === String(sido)) - .map(opt => ({ val: opt.id, text: opt.name })) - ] - } + selectArray={[defaultOption, ...sgg.filter(opt => opt.val.startsWith(sido.slice(0, 2)))]} value={sigungu} onSelectValue={val => { - onSigunguChange(Number(val)) - if (setSggName) setSggName(sgg.find(opt => Number(opt.id) === Number(val))?.name || ""); + onSigunguChange(String(val)) + if (setSggName) setSggName(sgg.find(opt => String(opt.val) === String(val))?.text || ""); if (setSwtrmtFcltNm) setSwtrmtFcltNm("") }} selectContentClass="z-[101]" diff --git a/apps/sn/app/store/index.ts b/apps/sn/app/store/index.ts index 40e094480..de827c9a1 100644 --- a/apps/sn/app/store/index.ts +++ b/apps/sn/app/store/index.ts @@ -1,8 +1,6 @@ import { getCmsData } from "@/components/lib/api"; -export interface Option { id: number, name: string } - export type BIZ_CD_TYPE = { lwpoCd: string, upCd: string, @@ -11,28 +9,34 @@ export type BIZ_CD_TYPE = { prntLwpoCd: null }; -export const fetchCtpvSggData = async (set: (state: any) => void) => { - try { - const ctpvData = await getCmsData('/api/v1/code/cache/ADSTDSTRCD/Y'); - const ctpvList: Option[] = ctpvData - .filter((item: any) => typeof item.lwpoCd === 'string' && item.lwpoCd.length === 2) - .map((feature: any) => ({ - id: feature.lwpoCd, - name: feature.lwpoCdNm - })); +export const fetchCtpv = async (set: (state: any) => void) => { + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`; + const res = await fetch(url).then(res => res.json()); - const sggList: Option[] = ctpvData - .filter((item: any) => typeof item.lwpoCd === 'string' && item.lwpoCd.length !== 2) - .map((item: any) => ({ - id: item.lwpoCd, - name: item.lwpoCdNm - })); + const list = res.features + .map((f: any) => ({ + text: f.properties.mctpv_korn_nm, + val: f.properties.mctpv_cd, + })) + .sort((a, b) => a.text.localeCompare(b.text, 'ko')); - set({ ctpv: ctpvList, sgg: sggList }); - } catch (e: any) { - // alert("시도, 시군구 데이터 로드 실패: " + e.message); - console.error("CTPV 데이터 로드 실패:", e); - } + console.log('시도 데이터', list); + set({ ctpv: list}); +}; + +export const fetchSgg = async (set: (state: any) => void) => { + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`; + const res = await fetch(url).then(res => res.json()); + + const list = res.features + .map((f: any) => ({ + text: f.properties.sgg_korn_nm, + val: f.properties.sgg_cd, + })) + .sort((a, b) => a.text.localeCompare(b.text, 'ko')); + + console.log('시군구 데이터', list); + set({ sgg: list }); }; export const fetchBIZ_SE_CD = async (set: (state: any) => void) => { diff --git a/apps/sn/app/store/useStore.ts b/apps/sn/app/store/useStore.ts index b2ae014fa..678090ed7 100644 --- a/apps/sn/app/store/useStore.ts +++ b/apps/sn/app/store/useStore.ts @@ -1,8 +1,6 @@ import { create } from "zustand"; -import { getGeoData, getCmsData } from "@/components/lib/api"; -import { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } from "./index"; - -interface Option { id: number, name: string } +import { fetchCtpv, fetchSgg, fetchBIZ_SE_CD, fetchBIZ_TY_CD } from "./index"; +import { type SelectDataType } from "@common/business_components"; export type BIZ_CD_TYPE = { lwpoCd: string, @@ -13,11 +11,12 @@ export type BIZ_CD_TYPE = { }; interface SnStoreState { - ctpv: Option[]; - sgg: Option[]; + ctpv: SelectDataType[]; + sgg: SelectDataType[]; BIZ_SE_CD: BIZ_CD_TYPE[]; BIZ_TY_CD: BIZ_CD_TYPE[]; - fetchCtpvSggData: () => Promise; + fetchCtpv: () => Promise; + fetchSgg: () => Promise; fetchBIZ_SE_CD: () => Promise; fetchBIZ_TY_CD: () => Promise; } @@ -27,7 +26,8 @@ const useStore = create((set) => ({ sgg: [], BIZ_SE_CD: [], BIZ_TY_CD: [], - fetchCtpvSggData: () => fetchCtpvSggData(set), + fetchCtpv: () => fetchCtpv(set), + fetchSgg: () => fetchSgg(set), fetchBIZ_SE_CD: () => fetchBIZ_SE_CD(set), fetchBIZ_TY_CD: () => fetchBIZ_TY_CD(set), })); diff --git a/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx b/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx index 21239bd7b..2f0eb2be9 100644 --- a/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx +++ b/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx @@ -43,10 +43,12 @@ export const ProcSearchBar = ({ gisMaps, facilityTypes }: SearchBarProps) => { const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`; const res = await fetch(url).then(res => res.json()); - const list = res.features.map((f: any) => ({ - text: f.properties.mctpv_korn_nm, - val: f.properties.mctpv_cd, - })); + const list = res.features + .map((f: any) => ({ + text: f.properties.mctpv_korn_nm, + val: f.properties.mctpv_cd, + })) + .sort((a, b) => a.text.localeCompare(b.text, 'ko')); setSidoData([{ text: "시도", val: "0" }, ...list]); }; @@ -54,10 +56,12 @@ export const ProcSearchBar = ({ gisMaps, facilityTypes }: SearchBarProps) => { const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`; const res = await fetch(url).then(res => res.json()); - const list = res.features.map((f: any) => ({ - text: f.properties.sgg_korn_nm, - val: f.properties.sgg_cd, - })); + const list = res.features + .map((f: any) => ({ + text: f.properties.sgg_korn_nm, + val: f.properties.sgg_cd, + })) + .sort((a, b) => a.text.localeCompare(b.text, 'ko')); setSigunData(list); }; @@ -90,10 +94,12 @@ export const ProcSearchBar = ({ gisMaps, facilityTypes }: SearchBarProps) => { url = `${url}&typeName=hasudo:${type}&cql_filter=${cqlFilter}`; const res = await fetch(url); const json = await res.json(); - list = json.features.map((f: any) => ({ - text: f.properties.swtrmt_fclt_nm ?? "(이름없음)", - val: f.id, - })); + list = json.features + .map((f: any) => ({ + text: f.properties.swtrmt_fclt_nm ?? "(이름없음)", + val: f.id, + })) + .sort((a, b) => a.text.localeCompare(b.text, 'ko')); } else if ( type === "tb_wr_bdst_ruse_fclt" // 재이용시설 ) {