From 7fd95ba6f9a17c5b8937bea5f7fafcbf3b051601 Mon Sep 17 00:00:00 2001 From: ljpark Date: Fri, 4 Sep 2026 10:32:36 +0900 Subject: [PATCH 01/13] =?UTF-8?q?sn:=20src/shared/util/util.ts=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/fldngHstry/fldngHstryTypes.ts | 20 +++++++--------- .../floodDngrMap/floodDngrMapTypes.ts | 17 ++++++------- .../sbmrgDngrMap/sbmrgDngrMapTypes.ts | 13 +++++----- .../map/components/sinkhole/sinkholeTypes.ts | 20 +++++++--------- .../ui/CtyFldngPrvtnBizListPage.tsx | 24 ++++++++++--------- .../features/obsltPpl/ui/ObsltPplListPage.tsx | 24 ++++++++++--------- 6 files changed, 57 insertions(+), 61 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts b/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts index bca73fc0e..3d5649b7f 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts @@ -1,6 +1,7 @@ "use client"; import type { UiHeadProps } from "@common/business_components/ui"; +import { appendApiSearchParams } from "@/shared/util/util"; export const FLOOD_HISTORY_POPUP_KEY = "fldngHstryPopup"; export const FLDNG_HSTRY_ROW_SELECT_MESSAGE = "SN_FLOOD_HISTORY_ROW_SELECT"; @@ -419,17 +420,14 @@ export const buildFldngHstryListQueryString = ( size: String(size), }); - if (normalized.ctpvCd !== "0") - params.set("ctpvCd", normalized.ctpvCd.slice(0, 2)); - if (normalized.sggCd !== "0") - params.set("sggCd", normalized.sggCd.slice(0, 5)); - if (normalized.floodYear) params.set("fldngYr", normalized.floodYear); - if (normalized.disasterName) - params.set("fldngDstrNm", normalized.disasterName); - if (normalized.rainStartDate) - params.set("rainBgngTm", normalized.rainStartDate); - if (normalized.districtName) - params.set("fldngDstrctNm", normalized.districtName); + appendApiSearchParams(params, { + ctpvCd: normalized.ctpvCd === "0" ? "0" : normalized.ctpvCd.slice(0, 2), + sggCd: normalized.sggCd === "0" ? "0" : normalized.sggCd.slice(0, 5), + fldngYr: normalized.floodYear, + fldngDstrNm: normalized.disasterName, + rainBgngTm: normalized.rainStartDate, + fldngDstrctNm: normalized.districtName, + }); return params.toString(); }; diff --git a/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts b/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts index ab03f132d..1d4d2df65 100644 --- a/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts @@ -1,6 +1,7 @@ "use client"; import type { UiHeadProps } from "@common/business_components/ui"; +import { appendApiSearchParams } from "@/shared/util/util"; export const FLOOD_DNGR_MAP_POPUP_KEY = "floodDngrMapPopup"; export const FLOOD_DNGR_MAP_LAYER_TYPE = "tb_ms_flood_dngr_map"; @@ -89,16 +90,12 @@ export const buildFloodDngrMapListQueryString = ( page: String(page), size: String(size), }); - if (filters.ctpvCd && filters.ctpvCd !== "0") - params.set("ctpvCd", filters.ctpvCd.slice(0, 2)); - if (filters.sggCd && filters.sggCd !== "0") - params.set("sggCd", filters.sggCd.slice(0, 5)); - if (filters.sbmrgDpthlCd && filters.sbmrgDpthlCd !== "0") { - params.set("sbmrgDpthlCd", filters.sbmrgDpthlCd); - } - if (filters.sbmrgFrqExpln && filters.sbmrgFrqExpln !== "0") { - params.set("sbmrgFrqExpln", filters.sbmrgFrqExpln); - } + appendApiSearchParams(params, { + ctpvCd: filters.ctpvCd === "0" ? "0" : filters.ctpvCd.slice(0, 2), + sggCd: filters.sggCd === "0" ? "0" : filters.sggCd.slice(0, 5), + sbmrgDpthlCd: filters.sbmrgDpthlCd, + sbmrgFrqExpln: filters.sbmrgFrqExpln, + }); return params.toString(); }; diff --git a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts index bf225784e..3d27a82c9 100644 --- a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts @@ -1,6 +1,7 @@ "use client"; import type { UiHeadProps } from "@common/business_components/ui"; +import { appendApiSearchParams } from "@/shared/util/util"; export const SBMRG_DNGR_MAP_POPUP_KEY = "sbmrgDngrMapPopup"; export const SBMRG_DNGR_MAP_LAYER_TYPE = "tb_ms_sbmrg_dngr_map"; @@ -74,13 +75,11 @@ export const buildSbmrgDngrMapListQueryString = ( page: String(page), size: String(size), }); - if (filters.ctpvCd && filters.ctpvCd !== "0") - params.set("ctpvCd", filters.ctpvCd.slice(0, 2)); - if (filters.sggCd && filters.sggCd !== "0") - params.set("sggCd", filters.sggCd.slice(0, 5)); - if (filters.floodWtlvFrqVl && filters.floodWtlvFrqVl !== "0") { - params.set("floodWtlvFrqVl", filters.floodWtlvFrqVl); - } + appendApiSearchParams(params, { + ctpvCd: filters.ctpvCd === "0" ? "0" : filters.ctpvCd.slice(0, 2), + sggCd: filters.sggCd === "0" ? "0" : filters.sggCd.slice(0, 5), + floodWtlvFrqVl: filters.floodWtlvFrqVl, + }); return params.toString(); }; diff --git a/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts b/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts index 401029745..e526ec992 100644 --- a/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts @@ -2,6 +2,7 @@ import type { SelectDataType } from "@common/business_components"; import type { IUserInfo } from "@/shared/store"; +import { appendApiSearchParams } from "@/shared/util/util"; export const SINKHOLE_CONTROL_NODE_ID = "SN_SINKHOLE"; export const SINKHOLE_LAYER_TYPE = "tb_sn_sinkhole_info"; @@ -284,19 +285,16 @@ export const buildSinkholeListQueryString = ( size: String(size), }); - if (filters.startYmd) params.set("startYmd", filters.startYmd); - if (filters.endYmd) params.set("endYmd", filters.endYmd); - const ctpvNm = resolveRegionNameByCode(filters.ctpvCd, ctpvOptions, 2); const sggNm = resolveRegionNameByCode(filters.sggCd, sggOptions, 5); - if (ctpvNm) params.set("ctpvNm", ctpvNm); - if (sggNm) params.set("sggNm", sggNm); - if (filters.restoreStatus && filters.restoreStatus !== "0") { - params.set("restoreStatus", filters.restoreStatus); - } - if (filters.coordStatus && filters.coordStatus !== "0") { - params.set("coordStatus", filters.coordStatus); - } + appendApiSearchParams(params, { + startYmd: filters.startYmd, + endYmd: filters.endYmd, + ctpvNm, + sggNm, + restoreStatus: filters.restoreStatus, + coordStatus: filters.coordStatus, + }); if (options?.includeCoordStatus === false) { params.set("includeCoordStatus", "false"); } diff --git a/apps/sn/src/features/ctyFldngPrvtnBiz/ui/CtyFldngPrvtnBizListPage.tsx b/apps/sn/src/features/ctyFldngPrvtnBiz/ui/CtyFldngPrvtnBizListPage.tsx index 12666c3be..031511650 100644 --- a/apps/sn/src/features/ctyFldngPrvtnBiz/ui/CtyFldngPrvtnBizListPage.tsx +++ b/apps/sn/src/features/ctyFldngPrvtnBiz/ui/CtyFldngPrvtnBizListPage.tsx @@ -717,17 +717,19 @@ export function CtyFldngPrvtnBizListPage() { /> - - +
+ + +
{notice && ( diff --git a/apps/sn/src/features/obsltPpl/ui/ObsltPplListPage.tsx b/apps/sn/src/features/obsltPpl/ui/ObsltPplListPage.tsx index 214eca881..d27f76b49 100644 --- a/apps/sn/src/features/obsltPpl/ui/ObsltPplListPage.tsx +++ b/apps/sn/src/features/obsltPpl/ui/ObsltPplListPage.tsx @@ -619,17 +619,19 @@ export function ObsltPplListPage() { /> - - +
+ + +
From 10d3fc096a298a0068c9822a254143d302f82d69 Mon Sep 17 00:00:00 2001 From: ljpark Date: Fri, 4 Sep 2026 11:00:38 +0900 Subject: [PATCH 02/13] =?UTF-8?q?sn:=20=EC=8B=9C=EB=8F=84=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EC=9D=BC=20=EB=95=8C,=20=EC=8B=9C=EA=B5=B0=EA=B5=AC?= =?UTF-8?q?=20=EB=AA=A9=EB=A1=9D=20=EB=B9=84=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../map/components/agedPipe/AgedPipePopupPage.tsx | 2 +- .../map/components/fldngHstry/FldngHstryPopupPage.tsx | 2 +- .../map/components/floodDngrMap/FloodDngrMapPopupPage.tsx | 2 +- .../map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx | 2 +- .../map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx | 2 +- .../map/components/sinkhole/SinkholePopupPage.tsx | 2 +- .../map/components/waterRisk/WaterRiskPopupPage.tsx | 4 ++-- apps/sn/app/(with-base-layout)/oper/dredging/page.tsx | 2 +- .../sn/app/html/(map-layout)/aged-pipe/AgedPipeListModal.tsx | 2 +- .../fldngPredcPrst/ui/FldngPredcPrstPopupContent.tsx | 2 +- apps/sn/src/features/obsltPpl/lib/obslt-ppl-region.ts | 5 ++++- 11 files changed, 15 insertions(+), 12 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx b/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx index 5a8caf2d9..b2a12c783 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx @@ -57,7 +57,7 @@ export default function AgedPipePopupPage() { const sggOptions = useMemo( () => filters.ctpvCd === "0" - ? sgg + ? [] : sgg.filter((item) => String(item.val).startsWith(filters.ctpvCd.slice(0, 2)), ), diff --git a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx index 9191a4be5..42750f87d 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx @@ -126,7 +126,7 @@ export default function FldngHstryPopupPage() { const sggOptions = useMemo( () => filters.ctpvCd === "0" - ? sgg + ? [] : sgg.filter((item) => String(item.val).startsWith(filters.ctpvCd.slice(0, 2)), ), diff --git a/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx index b65c7b38f..62821229f 100644 --- a/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx @@ -101,7 +101,7 @@ export default function FloodDngrMapPopupPage() { availableSggCodes.has(String(item.val).trim().slice(0, 5)), ); return filters.ctpvCd === "0" - ? scopedOptions + ? [] : scopedOptions.filter((item) => String(item.val).startsWith(filters.ctpvCd.slice(0, 2)), ); diff --git a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx index 725921045..e657c6f2d 100644 --- a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx @@ -388,7 +388,7 @@ export default function PipeAnalysisPopupPage() { const sggOptions = useMemo( () => draftFilters.ctpvCd === "0" - ? sgg + ? [] : sgg.filter((item) => String(item.val).startsWith(draftFilters.ctpvCd.slice(0, 2)), ), diff --git a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx index 4cb3987fe..a6e2190e4 100644 --- a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx @@ -85,7 +85,7 @@ export default function SbmrgDngrMapPopupPage() { availableSggCodes.has(String(item.val).trim().slice(0, 5)), ); return filters.ctpvCd === "0" - ? scopedOptions + ? [] : scopedOptions.filter((item) => String(item.val).startsWith(filters.ctpvCd.slice(0, 2)), ); diff --git a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx index c837cefdf..c5268b167 100644 --- a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx @@ -197,7 +197,7 @@ export default function SinkholePopupPage() { const sggOptions = useMemo( () => filters.ctpvCd === "0" - ? sgg + ? [] : sgg.filter((item) => String(item.val).startsWith(filters.ctpvCd.slice(0, 2)), ), diff --git a/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx index 2077532aa..6758738f5 100644 --- a/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx @@ -366,7 +366,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) { areaOptions .filter( (option) => - draftResultFilters.ctpvCd === "ALL" || + draftResultFilters.ctpvCd !== "ALL" && option.ctpvCd === draftResultFilters.ctpvCd, ) .forEach((option) => { @@ -382,7 +382,7 @@ export default function WaterRiskPopupPage(_props: WindowPopupContentProps) { () => areaOptions.filter( (option) => - (draftResultFilters.ctpvCd === "ALL" || + (draftResultFilters.ctpvCd !== "ALL" && option.ctpvCd === draftResultFilters.ctpvCd) && (draftResultFilters.sggCd === "ALL" || option.sggCd === draftResultFilters.sggCd), diff --git a/apps/sn/app/(with-base-layout)/oper/dredging/page.tsx b/apps/sn/app/(with-base-layout)/oper/dredging/page.tsx index aa9e18396..7e041a273 100644 --- a/apps/sn/app/(with-base-layout)/oper/dredging/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/dredging/page.tsx @@ -361,7 +361,7 @@ const Page = () => { /** 선택한 시도 코드와 앞 두 자리가 같은 시군구만 후보로 제공한다. */ const availableSggOptions = useMemo(() => { - if (ctpvCd === "0") return sggRegionOptions; + if (ctpvCd === "0") return []; const ctpvPrefix = ctpvCd.slice(0, 2); return sggRegionOptions.filter((option) => String(option.val).startsWith(ctpvPrefix), diff --git a/apps/sn/app/html/(map-layout)/aged-pipe/AgedPipeListModal.tsx b/apps/sn/app/html/(map-layout)/aged-pipe/AgedPipeListModal.tsx index a5c90e184..45a04331b 100644 --- a/apps/sn/app/html/(map-layout)/aged-pipe/AgedPipeListModal.tsx +++ b/apps/sn/app/html/(map-layout)/aged-pipe/AgedPipeListModal.tsx @@ -41,7 +41,7 @@ export default function AgedPipeListModal({ const { ctpv, sgg } = useStore(); const lastClickRef = useRef<{ index: number; clickedAt: number } | null>(null); const sggOptions = filters.ctpvCd === "0" - ? sgg + ? [] : sgg.filter((item) => String(item.val).startsWith(filters.ctpvCd.slice(0, 2))); const handleRowClick = (index?: number) => { diff --git a/apps/sn/src/features/fldngPredcPrst/ui/FldngPredcPrstPopupContent.tsx b/apps/sn/src/features/fldngPredcPrst/ui/FldngPredcPrstPopupContent.tsx index b16991eb1..38abae35b 100644 --- a/apps/sn/src/features/fldngPredcPrst/ui/FldngPredcPrstPopupContent.tsx +++ b/apps/sn/src/features/fldngPredcPrst/ui/FldngPredcPrstPopupContent.tsx @@ -240,7 +240,7 @@ export default function FldngPredcPrstPopupContent() { const sggOptions = useMemo( () => filters.ctpvCd === "0" - ? sgg + ? [] : sgg.filter((item) => String(item.val).startsWith(filters.ctpvCd.slice(0, 2)), ), diff --git a/apps/sn/src/features/obsltPpl/lib/obslt-ppl-region.ts b/apps/sn/src/features/obsltPpl/lib/obslt-ppl-region.ts index 2fc38854e..46547c757 100644 --- a/apps/sn/src/features/obsltPpl/lib/obslt-ppl-region.ts +++ b/apps/sn/src/features/obsltPpl/lib/obslt-ppl-region.ts @@ -40,12 +40,15 @@ export const buildObsltPplRepresentativeSggOptions = ( sggOptions: RegionOption[], ctpvCd: string, ) => { + // 시도가 전체(0)이면 시군구를 선택할 수 없도록 목록을 비운다. + if (ctpvCd === "0") return []; + const representativeMap = new Map(); sggOptions .filter((option) => { const optionCode = String(option.val ?? "").trim(); - return ctpvCd === "0" || optionCode.startsWith(ctpvCd.slice(0, 2)); + return optionCode.startsWith(ctpvCd.slice(0, 2)); }) .forEach((option) => { const representativeName = normalizeObsltPplSigunName(option.text); From 9067e645b30d1f11951f019fa4f92d3988512ba0 Mon Sep 17 00:00:00 2001 From: ljpark Date: Fri, 4 Sep 2026 14:33:25 +0900 Subject: [PATCH 03/13] =?UTF-8?q?sn:=20=EC=A0=95=EB=B3=B4=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EA=B8=B0=EB=B3=B8=EC=A0=95=EB=B3=B4=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84=EB=9E=80=20=ED=99=94=EB=A9=B4=EC=9D=B4=20=EC=A4=84?= =?UTF-8?q?=EC=97=88=EC=9D=84=20=EB=95=8C,=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=20=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx | 2 +- apps/sn/app/(map-layout)/map/searchModal/fldngWtlvMap.tsx | 4 ++-- apps/sn/app/(map-layout)/map/searchModal/stofcbr.tsx | 4 ++-- apps/sn/app/(map-layout)/map/searchModal/swageMhl.tsx | 4 ++-- apps/sn/app/(map-layout)/map/searchModal/swagePmstn.tsx | 4 ++-- apps/sn/app/(map-layout)/map/searchModal/swagePpl.tsx | 4 ++-- .../sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx | 4 ++-- .../sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx | 4 ++-- .../sn/app/html/(map-layout)/map/searchModal/basicTab.tsx | 8 ++++---- .../src/ui/standard_data_table/index.tsx | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx index 769c33036..0d1ebe18d 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/basicTab.tsx @@ -55,7 +55,7 @@ const BasicTab: React.FC = () => { selectContentClass="z-[101]" /> -
+
{basicType === "tb_ms_swage_ppl" && } {/* 하수관로 */} {basicType === "tb_il_swage_prcs_fclt" && }{" "} {/** 하수처리시설 */} diff --git a/apps/sn/app/(map-layout)/map/searchModal/fldngWtlvMap.tsx b/apps/sn/app/(map-layout)/map/searchModal/fldngWtlvMap.tsx index 35d08b98f..47248ab07 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/fldngWtlvMap.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/fldngWtlvMap.tsx @@ -23,8 +23,8 @@ const FldngWtlvMap: React.FC = () => { const { handleSearch, handleResetSearch } = useSearchModal(); return ( -
-
+
+
{ const { handleSearch, handleResetSearch } = useSearchModal(); return ( -
-
+
+
{/* 시도, 시군구 */} { const { handleSearch, handleResetSearch } = useSearchModal(); return ( -
-
+
+
{ const { handleSearch, handleResetSearch } = useSearchModal(); return ( -
-
+
+
{/* 시도, 시군구 */} { const { handleSearch, handleResetSearch } = useSearchModal(); return ( -
-
+
+
{ const { handleSearch, handleResetSearch } = useSearchModal(); return ( -
-
+
+
{ const { handleSearch, handleResetSearch } = useSearchModal(); return ( -
-
+
+
{ const { basicType, setBasicType } = useSearchModalStore(); return ( -
+
{/* 구분 */} -
+
{ />
- {/* 조회 조건 */} + {/* 조회 조건: 구분 선택과 같은 행에 배치 */} {basicType === "tb_ms_swage_ppl" && ()} {/* 하수관로 */} {basicType === "tb_il_swage_prcs_fclt" && ()} {/* 하수처리시설 */} {basicType === "tb_ms_swage_prcs_zone" && ()} {/* 하수처리구역 */} @@ -63,4 +63,4 @@ const BasicTab: React.FC = () => { ); }; -export default React.memo(BasicTab); \ No newline at end of file +export default React.memo(BasicTab); diff --git a/packages/common/business_components/src/ui/standard_data_table/index.tsx b/packages/common/business_components/src/ui/standard_data_table/index.tsx index 0753d8f23..f044b851c 100644 --- a/packages/common/business_components/src/ui/standard_data_table/index.tsx +++ b/packages/common/business_components/src/ui/standard_data_table/index.tsx @@ -277,7 +277,7 @@ function StandardDataTable({
From aa5a71ae6818ea240dc3147b1c6c76eb271cc79a Mon Sep 17 00:00:00 2001 From: ljpark Date: Fri, 4 Sep 2026 14:52:11 +0900 Subject: [PATCH 04/13] =?UTF-8?q?sn:=20=EC=B9=A8=EC=9E=85=EC=88=98,=20RDII?= =?UTF-8?q?=20=EC=A0=9C=EB=AA=A9=EB=9E=80=20=EC=A1=B0=EA=B8=88=20=EB=84=93?= =?UTF-8?q?=EA=B2=8C=20=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/infilChart.tsx | 2 +- .../popupComponent/chart/rdiiChart.tsx | 2 +- .../(with-base-layout)/ii/irsetting/page.tsx | 1 + .../app/(with-base-layout)/ii/rdii/page.tsx | 1 + apps/sn/app/components/ui/fileUploadForm.tsx | 8 +++---- .../src/ui/standard_form/index.tsx | 24 ++++++++++++------- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index c75fcdb5e..515d6ad8a 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -244,7 +244,7 @@ const InfilChart = ({ const renderResultPanel = () => (
- +
{selectedAplcnYm diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx index 5c9b09683..0a5abc436 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -218,7 +218,7 @@ const RdiiChart = ({ const renderResultPanel = () => (
- +
{selectedAplcnYm diff --git a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx index 927e9581a..4e7f7a237 100644 --- a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx @@ -485,6 +485,7 @@ const IrSetting = () => { key="irsetting-layout-key" title="분석 조건 및 자료" columns={2} + wideLabels > {/* 연월 선택 라이브러리로 수정 필요 */} diff --git a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx index d0b72ef21..e5757f572 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx @@ -518,6 +518,7 @@ export default function RTKForm() { key="form-section" title="분석 조건 및 자료" columns={2} + wideLabels > diff --git a/apps/sn/app/components/ui/fileUploadForm.tsx b/apps/sn/app/components/ui/fileUploadForm.tsx index 8af347679..0277bc836 100644 --- a/apps/sn/app/components/ui/fileUploadForm.tsx +++ b/apps/sn/app/components/ui/fileUploadForm.tsx @@ -168,16 +168,16 @@ const FileUploadForm = ({ } return ( -
+
{" "} {/* 컴포넌트 루트 div */} -
+
{" "} {/* 카드 스타일링 */} -
+
{" "} {/* FileUploader와 Button을 정렬하는 메인 flex 컨테이너 */} -
+
{" "} {/* FileUploader의 너비와 오른쪽 여백을 제어하는 컨테이너 */} {title} -
- {children} -
+ +
+ {children} +
+
); } @@ -78,9 +84,11 @@ function StandardFormField({ children, className = "", }: StandardFormFieldProps) { + const wideLabels = useContext(StandardFormWideLabelsContext); + return (
-
+
{children} {error ? (

From 34ba09ce1b694d58e2dc01abe9b9618203887c4b Mon Sep 17 00:00:00 2001 From: mind-one001 Date: Fri, 4 Sep 2026 15:24:17 +0900 Subject: [PATCH 05/13] =?UTF-8?q?=EC=A4=80=EC=84=A4=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/DredgingDetailPopupPage.tsx | 87 +++++++++++++++---- .../components/DredgingRegisterModal.tsx | 38 +++++--- .../001-qa-SFR-010-012-준설관리-검증결과.md | 42 +++++++++ .../001-fe-SFR-010-012-준설관리-구현기록.md | 22 +++++ 4 files changed, 159 insertions(+), 30 deletions(-) diff --git a/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx b/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx index 5f0909de1..200e9203c 100644 --- a/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx +++ b/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingDetailPopupPage.tsx @@ -14,6 +14,7 @@ import { TableRow, } from "@common/components"; import { MS_SWAGE_PPL_CODES } from "@/app/(map-layout)/map/components/common/table"; +import { fileDownload } from "@/components/lib/utils/fileDownload"; import { useAlertStore } from "@/shared/lib"; import { useEffect, useMemo, useRef, useState } from "react"; @@ -119,6 +120,8 @@ const DredgingDetailPopupPage = ({ const [matchError, setMatchError] = useState(null); const [isMatching, setIsMatching] = useState(false); const [isSaving, setIsSaving] = useState(false); + // 원본 다운로드 중 연속 클릭을 막고 선택한 사진의 다운로드 진행 상태를 표시한다. + const [isDownloadingPhoto, setIsDownloadingPhoto] = useState(false); const [statusMessage, setStatusMessage] = useState(""); const uploadedAttachmentsRef = useRef(new Map()); @@ -221,6 +224,31 @@ const DredgingDetailPopupPage = ({ null) : null; + /** 저장된 사진은 공통 첨부 원본을 받고, 아직 저장하지 않은 신규 사진은 로컬 File을 내려받는다. */ + const handlePhotoDownload = async () => { + // 다운로드 중 선택을 바꾸더라도 클릭한 시점의 파일과 파일명을 함께 유지한다. + const existingPhoto = selectedExistingPhoto; + const newPhoto = selectedNewPhoto; + if (isDownloadingPhoto || (!existingPhoto && !newPhoto)) return; + + setIsDownloadingPhoto(true); + try { + if (newPhoto) { + fileDownload(newPhoto.file, newPhoto.file.name); + } else if (existingPhoto) { + const original = await fetchDredgingPhotoBlob(existingPhoto.atflId); + fileDownload( + original, + existingPhoto.originalFileName || `준설사진_${existingPhoto.photoSn}`, + ); + } + } catch { + alert("사진을 다운로드하지 못했습니다. 잠시 후 다시 시도해주세요."); + } finally { + setIsDownloadingPhoto(false); + } + }; + const pipeInfo = [ ["시도", record.ctpv || "확인불가"], ["시군구", record.sgg || "확인불가"], @@ -481,10 +509,10 @@ const DredgingDetailPopupPage = ({

} - bodyClassName="sn-dredging-register block overflow-y-auto" + bodyClassName="sn-dredging-register !overflow-hidden" > -
-