diff --git a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx index 4634eec80..702c5beb2 100644 --- a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx +++ b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx @@ -68,6 +68,7 @@ type BaseLayout = { setSggCd: (sgg: string) => void; setSggName?: (sggName: string) => void; setSwtrmtFcltNm?: (swtrmtFcltNm: string) => void; + defaultSwtrmtFcltNm?: string; setIsLoading?: (isLoading: boolean) => void; onExcelDownload?: () => void; onDeleteFile?: () => void; @@ -103,6 +104,7 @@ const BaseLayout = ({ setSggCd, setSggName, setSwtrmtFcltNm, + defaultSwtrmtFcltNm, setIsLoading, onExcelDownload, onDeleteFile, @@ -212,6 +214,7 @@ const BaseLayout = ({ selectedSwagePrcsFclt={selectedSwagePrcsFclt} onSwagePrcsFcltChange={onSwagePrcsFcltChange} setSwtrmtFcltNm={setSwtrmtFcltNm} + defaultSwtrmtFcltNm={defaultSwtrmtFcltNm} setIsLoading={setIsLoading} /> )} 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 8b4276ca9..80b4b58cd 100644 --- a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx @@ -59,6 +59,10 @@ interface UploadedFileInfo { } // 초기 파일 정보 상태 const initialFileInfo: UploadedFileInfo = { file: null, atflCd: null, atflId: null }; +const DEFAULT_CTPV_CD = '41'; +const DEFAULT_SGG_CD = '41830'; +const DEFAULT_SGG_NAME = '\uC591\uD3C9\uAD70'; +const DEFAULT_SWTRMT_FCLT_NM = '\uC591\uD3C9'; const IrSetting = () => { const [input1, setInput1] = useState('0.8'); // 오수전환율 초기값 @@ -66,10 +70,10 @@ const IrSetting = () => { const [selectedSwagePrcsFclt, setSelectedSwagePrcsFclt] = useState('0'); // ?????? ?? ?? const [formResetKey, setFormResetKey] = useState(0); // FileUploadForm 리셋을 위한 key 상태 const [isLoadingResult, setIsLoadingResult] = useState(false); // 로딩 상태 - const [ctpvCd, setCtpvCd] = useState('0'); // 시도 코드 상태 - const [sggCd, setSggCd] = useState('0'); // 시군구 코드 상태 - const [sggName, setSggName] = useState(''); // 시군구 이름 상태 - const [swtrmtFcltNm, setSwtrmtFcltNm] = useState(''); // 하수처리시설명 상태 + const [ctpvCd, setCtpvCd] = useState(DEFAULT_CTPV_CD); // 시도 코드 상태 + const [sggCd, setSggCd] = useState(DEFAULT_SGG_CD); // 시군구 코드 상태 + const [sggName, setSggName] = useState(DEFAULT_SGG_NAME); // 시군구 이름 상태 + const [swtrmtFcltNm, setSwtrmtFcltNm] = useState(DEFAULT_SWTRMT_FCLT_NM); // 하수처리시설명 상태 const [uploadedFilesData, setUploadedFilesData] = useState([ initialFileInfo, // 0: 오수관망도 initialFileInfo, // 1: 수용가-맨홀 매칭결과 @@ -128,7 +132,10 @@ const IrSetting = () => { setInput1(''); // 입력 필드 초기화 setInput2(''); // 입력 필드 초기화 setSelectedSwagePrcsFclt('0'); - setSwtrmtFcltNm(''); + setCtpvCd(DEFAULT_CTPV_CD); + setSggCd(DEFAULT_SGG_CD); + setSggName(DEFAULT_SGG_NAME); + setSwtrmtFcltNm(DEFAULT_SWTRMT_FCLT_NM); setFormResetKey(prevKey => prevKey + 1); // FileUploadForm 재마운트를 위해 key 변경 }; @@ -390,6 +397,7 @@ const IrSetting = () => { setSggCd={setSggCd} setSggName={setSggName} setSwtrmtFcltNm={setSwtrmtFcltNm} + defaultSwtrmtFcltNm={swtrmtFcltNm} setIsLoading={setIsLoadingResult} onResultView={() => openAnalysisResultMapView('inftwtResultPopup')} onAnalysis={handleAnalysisClick} 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 30da5f7cb..b1c273be3 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx @@ -75,9 +75,9 @@ const formSchema = z.object({ type FormSchemaType = z.infer; // 기본 폼 값 정의 (테스트 편의를 위해 초기값 설정, 추후 삭제 필요) const defaultFormValues: FormSchemaType = { - ctpvCd: "", - sggCd: "", - swtrmtFcltNm: "", + ctpvCd: "41", + sggCd: "41830", + swtrmtFcltNm: "\uC591\uD3C9", rtkSource: "", rdiiArea: "", // 문자열로 기본값 설정 unitFactors: [ @@ -113,6 +113,10 @@ interface UploadedFileInfo { // 초기 파일 정보 상태 const initialFileInfo: UploadedFileInfo = { file: null, atflCd: null, atflId: null }; +const DEFAULT_CTPV_CD = '41'; +const DEFAULT_SGG_CD = '41830'; +const DEFAULT_SGG_NAME = '\uC591\uD3C9\uAD70'; +const DEFAULT_SWTRMT_FCLT_NM = '\uC591\uD3C9'; export default function RTKForm() { const [formResetKey, setFormResetKey] = useState(0); // FileUploadForm 리셋을 위한 key 상태 @@ -127,10 +131,10 @@ export default function RTKForm() { ]); const [select1, setSelect1] = useState('0'); // 하수처리장 (swtrmtFcltCd) - const [ctpvCd, setCtpvCd] = useState('0'); // 시도 코드 상태 - const [sggCd, setSggCd] = useState('0'); // 시군구 코드 상태 - const [sggName, setSggName] = useState(''); // 시군구 이름 상태 - const [swtrmtFcltNm, setSwtrmtFcltNm] = useState(''); // 하수처리시설명 상태 + const [ctpvCd, setCtpvCd] = useState(DEFAULT_CTPV_CD); // 시도 코드 상태 + const [sggCd, setSggCd] = useState(DEFAULT_SGG_CD); // 시군구 코드 상태 + const [sggName, setSggName] = useState(DEFAULT_SGG_NAME); // 시군구 이름 상태 + const [swtrmtFcltNm, setSwtrmtFcltNm] = useState(DEFAULT_SWTRMT_FCLT_NM); // 하수처리시설명 상태 const { data: userInfo } = useQuery({ queryKey: [ENDPOINT.USER_SERVICE.USERS], @@ -154,6 +158,10 @@ export default function RTKForm() { ]); setFormResetKey(prevKey => prevKey + 1); // FileUploadForm 재마운트를 위해 key 변경 setSelect1('0'); + setCtpvCd(DEFAULT_CTPV_CD); + setSggCd(DEFAULT_SGG_CD); + setSggName(DEFAULT_SGG_NAME); + setSwtrmtFcltNm(DEFAULT_SWTRMT_FCLT_NM); }; // FileUploadForm의 onFileSelect prop으로 전달될 콜백 함수 @@ -425,6 +433,7 @@ export default function RTKForm() { setSggCd={setSggCd} setSggName={setSggName} setSwtrmtFcltNm={setSwtrmtFcltNm} + defaultSwtrmtFcltNm={swtrmtFcltNm} setIsLoading={setIsLoadingResult} onResultView={() => openAnalysisResultMapView('rdiiResultPopup')} onAnalysis={handleAnalysisClick} diff --git a/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx b/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx index 25eb0a9d1..51eb5a166 100644 --- a/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx +++ b/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx @@ -35,10 +35,15 @@ interface CtpvSggPrcsFcltSelectBoxProps { selectedSwagePrcsFclt?: string; onSwagePrcsFcltChange?: (value: string) => void; setSwtrmtFcltNm?: (name: string) => void; + defaultSwtrmtFcltNm?: string; setIsLoading?: (isLoading: boolean) => void; } const defaultOption: ApiSelectOption = { val: '0', text: '전체' }; +const buildFacilityDefaultOption = (facilityName: string): ApiSelectOption => ({ + val: '0', + text: facilityName || defaultOption.text, +}); export function CtpvSggPrcsFcltSelectBox({ sido, @@ -52,6 +57,7 @@ export function CtpvSggPrcsFcltSelectBox({ selectedSwagePrcsFclt, onSwagePrcsFcltChange, setSwtrmtFcltNm, + defaultSwtrmtFcltNm, setIsLoading, }: CtpvSggPrcsFcltSelectBoxProps) { @@ -59,18 +65,7 @@ export function CtpvSggPrcsFcltSelectBox({ const { ctpv, sgg } = useStore(); const sidoStr = String(sido ?? ''); const sidoPrefix = sidoStr.slice(0, 2); - - useEffect(() => { - (async () => { - onSidoChange("0"); - onSigunguChange("0"); - if (setCtpvName && setSggName) { - setCtpvName(""); - setSggName(""); - } - if (setSwtrmtFcltNm) setSwtrmtFcltNm(""); - })(); - }, []); + const normalizedDefaultFacilityName = String(defaultSwtrmtFcltNm ?? '').trim(); useEffect(() => { onSwagePrcsFcltChange?.('0'); @@ -115,6 +110,25 @@ export function CtpvSggPrcsFcltSelectBox({ fetchData(); }, [sggName]); + useEffect(() => { + if (!normalizedDefaultFacilityName) return; + if (!selectedSwagePrcsFclt || selectedSwagePrcsFclt !== "0") return; + if (prcsFcltOptions.length === 0) return; + + const matchedDefaultFacility = prcsFcltOptions.find((option) => + String(option.text ?? "").trim() === normalizedDefaultFacilityName, + ); + if (!matchedDefaultFacility) return; + + onSwagePrcsFcltChange?.(String(matchedDefaultFacility.val)); + setSwtrmtFcltNm?.(matchedDefaultFacility.text); + }, [ + normalizedDefaultFacilityName, + onSwagePrcsFcltChange, + prcsFcltOptions, + selectedSwagePrcsFclt, + setSwtrmtFcltNm, + ]); return (
@@ -153,7 +167,7 @@ export function CtpvSggPrcsFcltSelectBox({ className="w-[160px]" selectClass="rounded-lg bg-white truncate" label="" - selectArray={[defaultOption, ...prcsFcltOptions]} + selectArray={[buildFacilityDefaultOption(normalizedDefaultFacilityName), ...prcsFcltOptions]} value={selectedSwagePrcsFclt} onSelectValue={(val) => { onSwagePrcsFcltChange?.(String(val)) @@ -165,4 +179,4 @@ export function CtpvSggPrcsFcltSelectBox({ )}
); -} \ No newline at end of file +} diff --git a/apps/sn/docs/작업내용/SN-침입수분석결과-지도연계유지보수/001-fe-SN-침입수분석결과-지도연계유지보수-통합구현기록.md b/apps/sn/docs/작업내용/SN-침입수분석결과-지도연계유지보수/001-fe-SN-침입수분석결과-지도연계유지보수-통합구현기록.md index 2f18e01e1..5067d4fcc 100644 --- a/apps/sn/docs/작업내용/SN-침입수분석결과-지도연계유지보수/001-fe-SN-침입수분석결과-지도연계유지보수-통합구현기록.md +++ b/apps/sn/docs/작업내용/SN-침입수분석결과-지도연계유지보수/001-fe-SN-침입수분석결과-지도연계유지보수-통합구현기록.md @@ -124,3 +124,9 @@ - `useInftwtResultMap`은 row click 직후 mapView를 먼저 확보한 뒤, `oilqPipeCount > 0`이면 검색바 동기화 이벤트에 `suppressMapMove`를 내려 지역 중심 이동을 건너뛰도록 보정했다. - `procSearchBar`는 `suppressMapMove`가 내려오면 시도/시군구/시설 상태만 갱신하고 `moveMapToCenter`는 호출하지 않는다. - 이 보정으로 실측하수량 관로가 있는 케이스는 처음부터 해당 관로 extent로 바로 확대된다. + +## 19. 2026-07-09 분석 대상지역 기본값 보정 + +- `ii/irsetting`, `ii/rdii`의 기본 선택값을 `경기도 / 양평군 / 양평`으로 맞췄다. +- 공통 `CtpvSggPrcsFcltSelectBox`는 mount 시 부모 값을 강제로 `0`으로 되돌리던 초기화 흐름을 제거하고, 시설 목록 로딩 후 `defaultSwtrmtFcltNm` 이름 기준으로 기본 시설을 자동 선택하게 보강했다. +- 이 보정으로 두 분석 화면 진입 직후 `하수처리시설명` select도 `양평` 기준으로 바로 보이도록 정리했다.