diff --git a/apps/sn/app/(map-layout)/layout.tsx b/apps/sn/app/(map-layout)/layout.tsx index e245cfdf1..4337ee048 100644 --- a/apps/sn/app/(map-layout)/layout.tsx +++ b/apps/sn/app/(map-layout)/layout.tsx @@ -1,10 +1,12 @@ "use client"; +import React, { useEffect } from 'react'; import { usePathname, useRouter } from "next/navigation"; import { useQueryClient } from "@tanstack/react-query"; import { BaseLayout } from "@common/components"; import type { MenuItem } from "@/entities/menu"; import { useMenuStore } from "@/shared/lib"; +import useStore from '../store/useStore'; export default function MapLayout({ children, @@ -17,6 +19,17 @@ export default function MapLayout({ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); + const { fetchCtpvData, fetchSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); + + + // 시도, 시군구 호출 + useEffect(() => { + fetchCtpvData(); + fetchSggData(); + fetchBIZ_SE_CD(); + fetchBIZ_TY_CD(); + }, []); + const handleMenuClick = (item: MenuItem) => { setCurrentMenuInfo(item); router.push(item.urlPath); diff --git a/apps/sn/app/(map-layout)/map/commonStore.ts b/apps/sn/app/(map-layout)/map/commonStore.ts deleted file mode 100644 index ff903e1e7..000000000 --- a/apps/sn/app/(map-layout)/map/commonStore.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { create } from 'zustand'; - -export type SelectDataType = { - text: string; - val: string; - sido?: string; // 시도 코드 (선택 사항) -} - -interface CityCdStore { - cityCd: string; - setCityCd: (cityCd: string) => void; - sidos: SelectDataType[]; - setSidos: (sidos: SelectDataType[]) => void; - siguns : SelectDataType[]; - setSiguns: (siguns: SelectDataType[]) => void; -} - -export const useCityCdStore = create((set) => ({ - cityCd: '', - setCityCd: (cityCd: string) => set({ cityCd }), - sidos: [], - setSidos: (sidos: SelectDataType[]) => set({ sidos }), - siguns: [], - setSiguns: (siguns: SelectDataType[]) => set({ siguns }), -})); 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 08443c73f..ad067383a 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx @@ -4,7 +4,7 @@ import React, { useState, useEffect } from 'react' import InputSection from '../InputSection'; import { handleInputChange } from '../common'; import { getData } from "@/components/lib/api"; -// import { useBizByFcltStore } from "../../../../store/StoreProvider"; +import useStore from '../../../../store/useStore'; // 하수관로 const inputColumn = [ @@ -30,21 +30,7 @@ const MsSwagePpl = ({ featureData, onSaveClick }: { featureData: any, onSaveClic inspection: { data: inspectionData, setData: setInspectionData }, }; - - // const BIZ_SE_CD = useBizByFcltStore(state => state.BIZ_SE_CD); - const BIZ_SE_CD = [ - { lwpoCd: "100", lwpoCdNm: "관로기술진단" }, - { lwpoCd: "200", lwpoCdNm: "개대체" }, - { lwpoCd: "201", lwpoCdNm: "유지보수" }, - { lwpoCd: "203", lwpoCdNm: "청소, 준설" }, - { lwpoCd: "204", lwpoCdNm: "단순보수" }, - ]; - // const BIZ_TY_CD = useBizByFcltStore(state => state.BIZ_TY_CD); - const BIZ_TY_CD = [ - { lwpoCd: "SV", lwpoCdNm: "용역" }, - { lwpoCd: "SF", lwpoCdNm: "자체" }, - { lwpoCd: "SC", lwpoCdNm: "공사" }, - ]; + const { BIZ_SE_CD, BIZ_TY_CD } = useStore(); // 마운트 및 업데이트 시 API 호출 diff --git a/apps/sn/app/(map-layout)/map/page.tsx b/apps/sn/app/(map-layout)/map/page.tsx index 15c6586eb..77b89cfd0 100644 --- a/apps/sn/app/(map-layout)/map/page.tsx +++ b/apps/sn/app/(map-layout)/map/page.tsx @@ -6,7 +6,6 @@ import { useCallback, useEffect, useRef, useState } from "react"; import GisApp from "@common/business_components/ui/map/lib/gis.core"; import SearchModal from "./searchModal/searchModal"; import FeatureClickEventPopup from "./components/popupComponent/featureClickEventPopup"; -import useStore from "../../store/useStore"; // 타입 정의 추가 export type LyrStngProps = { @@ -39,13 +38,11 @@ const Map = () => { const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태 const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태 const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터 - const { fetchCtpvData, fetchSggData } = useStore(); - // 시도, 시군구 호출 + useEffect(() => { - fetchCtpvData(); - fetchSggData(); - }, [fetchCtpvData, fetchSggData]); + fetchData(); + }, []); const fetchData = async () => { try { @@ -56,9 +53,6 @@ const Map = () => { } }; - useEffect(() => { - fetchData(); - }, []); // SearchModal, GisContent 등에서 호출 const onFeatureSelect = (data: any) => { let map = gisMaps.current; diff --git a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx index 9a46e2bf8..dfd71a39d 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx @@ -1,40 +1,15 @@ +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 React from 'react'; -//import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi'; -// import { useBizByFcltStore } from "../../../store/StoreProvider"; +import useStore from '../../../store/useStore'; // 운영정보 '구분' 선택 목록 -// const WORK_TYPES = [ -// { val: "maintenance", text: "보수 및 갱신" }, -// { val: "cleaning", text: "청소 및 준설" }, -// { val: "inspection", text: "점검 및 진단" }, -// ]; export const WORK_TYPES = [ { val: "['200', '201', '204']", text: "보수 및 갱신" }, { val: "['100']", text: "점검 및 진단" }, { val: "['203']", text: "청소 및 준설" }, ]; -// const BIZ_SE_CD = useBizByFcltStore(state => state.BIZ_SE_CD); -export const BIZ_SE_CD = [ - { lwpoCd: "100", lwpoCdNm: "관로기술진단" }, - { lwpoCd: "200", lwpoCdNm: "개대체" }, - { lwpoCd: "201", lwpoCdNm: "유지보수" }, - { lwpoCd: "203", lwpoCdNm: "청소, 준설" }, - { lwpoCd: "204", lwpoCdNm: "단순보수" }, -]; -// const BIZ_TY_CD = useBizByFcltStore(state => state.BIZ_TY_CD); -export const BIZ_TY_CD = [ - { lwpoCd: "0", lwpoCdNm: "전체" }, - { lwpoCd: "SV", lwpoCdNm: "용역" }, - { lwpoCd: "SF", lwpoCdNm: "자체" }, - { lwpoCd: "SC", lwpoCdNm: "공사" }, -]; -export const BIZ_TY_CD_SELECT_ARRAY = BIZ_TY_CD.map(item => ({ - val: item.lwpoCd, - text: item.lwpoCdNm, -})); // 운영정보 - 사업 현황 export const operationTableHeadlist = [ { id: 'rowNumber', title: '일련번호' }, @@ -110,6 +85,14 @@ const OperationTab: React.FC = ({ setVar2, setYearFilter, }) => { + + const { BIZ_TY_CD } = useStore(); + + const BIZ_TY_CD_SELECT_ARRAY = BIZ_TY_CD.map(item => ({ + val: item.lwpoCd, + text: item.lwpoCdNm, + })); + return (
diff --git a/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx index b453ba20f..7076b621c 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx @@ -3,24 +3,22 @@ import { UiModal, UITab, UiTable } from '@common/business_components/ui'; import axios from 'axios'; import React, { useEffect, useMemo, useState } from 'react'; import { ExclnSewagePumpCol2, MsSwageMhlCol2, MsSwagePplCol2, stofcbrCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2 } from '../components/common/table'; -import { type SelectDataType } from '../commonStore'; import { MS_SWAGE_PPL_CODES, MS_SWAGE_PPL_USE_CODES, MS_SWAGE_MHL_CODES } from '../components/common/table'; import { getData } from "@/components/lib/api"; import BasicTab, { BASIC_TYPES } from './basicTab'; -import OperationTab, { BIZ_TY_CD, operationCleaningTableHeadlist, operationInspectionTableHeadlist, operationMaintenanceTableHeadlist, operationTableHeadlist, WORK_TYPES } from './operationTab'; -import ReportTab, { reportTableHeadlist } from './reportTab'; +import OperationTab, { operationCleaningTableHeadlist, operationInspectionTableHeadlist, operationMaintenanceTableHeadlist, operationTableHeadlist, WORK_TYPES } from './operationTab'; +import ReportTab from './reportTab'; import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; +import useStore from '../../../store/useStore'; const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`; -// 탭 const TABS = [ { val: "basic", text: "기본정보" }, { val: "operation", text: "운영정보" }, { val: "report", text: "하수도정비기본계획보고서" }, ]; - // 날짜 조합 함수 const getDateString = ( year: string, @@ -67,10 +65,6 @@ const SearchModal: React.FC = ({ const [ctpvName, setCtpvName] = useState(''); const [sgg, setSgg] = useState(0); const [sggName, setSggName] = useState(''); - const [ctpvCd, setCtpvCd] = useState('0'); // 하수정비기본계획 report - const [sigungu, setSigungu] = useState('0'); // 하수정비기본계획 report - const [gubun, setGubun] = useState(""); // 하수정비기본계획 report - const [reportGubun, setReportGubun] = useState("0"); // 하수정비기본계획 report const [start1, setStart1] = useState(""); const [start2, setStart2] = useState(""); const [end1, setEnd1] = useState(""); @@ -81,7 +75,8 @@ const SearchModal: React.FC = ({ const [var4, setVar4] = useState(""); // 시작, 종료 const [yearFilter, setYearFilter] = useState({ start: "", end: "" }); - const [filteredSiguns, setFilteredSiguns] = useState([{ val: '0', text: '전체', sido: '0' }]); + + const { BIZ_TY_CD } = useStore(); // 오늘 날짜 구하기 diff --git a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx index d825b34fa..9eab30712 100644 --- a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx +++ b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx @@ -1,12 +1,12 @@ 'use client' import { getData } from '@/components/lib/api' -import ContentLayout from '@/components/ui/contentLayout' import { GovSidoSigunguSearchForm } from '@/components/ui/govSidoSigunguSearchForm' -import { DatePicker, DateMonthPicker, Form, SearchFormRight, SelectBox } from '@common/business_components/ui' +import { DateMonthPicker, Form, SelectBox } from '@common/business_components/ui' import ListDiv from '@common/business_components/ui/list_div' import { Button, Label } from '@common/components/ui' import { useEffect, useState, type ReactNode } from 'react' import LoadingOverlay from '@/components/ui/LoadingBar' +import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox' type TitleName = { mainTitle: string @@ -40,12 +40,10 @@ type BaseLayout = { firstDivBtn?: boolean selectBox?: SelectBox showDatePicker?: boolean; - enoCd?: string | number - setEnoCd?: (enoCd: string) => void - ctpvCd?: string | number - setCtpvCd?: (ctpvCd: string) => void + ctpvCd: number; + sggCd: number; + sggName?: string; sigungu?: ApiSelectOption - setSigungu?: (sigungu: ApiSelectOption) => void selectedSwageTreatmentPlant?: string | number; onSwageTreatmentPlantChange?: (value: string | number) => void; selectedSwageProcessingZone?: string | number; @@ -54,23 +52,16 @@ type BaseLayout = { setAplcnYmFrom?: (aplcnYmFrom: string) => void; aplcnYmTo?: string setAplcnYmTo?: (aplcnYmTo: string) => void; + setCtpvCd: (ctpv: number) => void; + setSggCd: (sgg: number) => void; + setSggName?: (sggName: string) => void; isLoading?: boolean; - // Excel 다운로드 관련 props 추가 onExcelDownload?: () => void; onDeleteFile?: () => void; onAnalysis?: () => void; selectedRowData?: any; } -// TODO: 나중에 이벤트 추가되면 파라미터 추가 필요 ? -/** - * - * @param children - * @param titleName : 메인 타이틀, 첫번째 요소 타이틀, 두번째 요소 타이틀 - * @param form : zod 스키마 - * @param onSubmitEvent : 폼 이벤트 처리 - * @param graphBtn : 하단에 그래프 버튼 유무 처리 - * @returns - */ + const BaseLayout = ({ children, titleName, @@ -80,42 +71,36 @@ const BaseLayout = ({ analysisBtn, selectBox, showDatePicker = false, - enoCd, - setEnoCd, ctpvCd, - setCtpvCd, + sggCd, + sggName, sigungu, - setSigungu, selectedSwageTreatmentPlant, onSwageTreatmentPlantChange, - selectedSwageProcessingZone, - onSwageProcessingZoneChange, aplcnYmFrom, setAplcnYmFrom, aplcnYmTo, setAplcnYmTo, + setCtpvCd, + setSggCd, + setSggName, isLoading, - // Excel 다운로드 관련 props 추가 onExcelDownload, onDeleteFile, onAnalysis, - selectedRowData }: BaseLayout) => { const defaultOption: ApiSelectOption = { val: '0', text: '전체' }; - const [processingZoneOptions, setProcessingZoneOptions] = useState([]); const [treatmentFacilityOptions, setTreatmentFacilityOptions] = useState([]); const [isLoadingAreaData, setIsLoadingAreaData] = useState(isLoading || false); - const [atflId, setAtflId] = useState('') - const [fileNm, setFileNm] = useState('') - const [dcrpPplMtncBizSn, setDcrpPplMtncBizSn] = useState('') useEffect(() => { + onSwageTreatmentPlantChange?.(0); + const fetchData = async () => { - if (!sigungu || sigungu.val === '0' || !sigungu.val) { + if (!sggName) { console.log("BaseLayout: Skipping fetchData because sigungu.val is:", sigungu?.val); - setProcessingZoneOptions([defaultOption]); setTreatmentFacilityOptions([defaultOption]); setIsLoadingAreaData(false); return; @@ -123,20 +108,6 @@ const BaseLayout = ({ setIsLoadingAreaData(true); try { - // const queryParamsZone = new URLSearchParams({ - // lyrTypeNm: 'tb_ms_swage_prcs_zone', - // page: '0', - // size: '100000', - // sort: 'string', - // }); - // const cqlFiltersZone: string[] = []; - // if (sigungu.val && sigungu.val !== '0') { - // // console.log("시군구 코드", sigungu.val); - // cqlFiltersZone.push(`sgg_cd='${sigungu.val}'`); - // } - // if (cqlFiltersZone.length > 0) { - // queryParamsZone.append('cqlFiter', cqlFiltersZone.join(' and ')); - // } const queryParamsFacility = new URLSearchParams({ lyrTypeNm: 'tb_il_swage_prcs_fclt', @@ -145,39 +116,26 @@ const BaseLayout = ({ sort: 'string', }); const cqlFiltersFacility: string[] = []; - if (sigungu.text && sigungu.val !== '0') { - cqlFiltersFacility.push(`sgg_nm ILIKE '%${sigungu.text}%'`); - } - if (cqlFiltersFacility.length > 0) { - queryParamsFacility.append('cqlFiter', cqlFiltersFacility.join(' and ')); // API 명세에 따라 cqlFilter 또는 cqlFiter - } + if (sggName) cqlFiltersFacility.push(`sgg_nm ILIKE '%${sggName}%'`); + if (cqlFiltersFacility.length > 0) queryParamsFacility.append('cqlFiter', cqlFiltersFacility.join(' and ')); - // console.log("BaseLayout API URL for Zones:", `v1/fclts?${queryParamsZone.toString()}`); console.log("BaseLayout API URL for Facilities:", `v1/fclts?${queryParamsFacility.toString()}`); - // const [zoneRes, facilityRes] = await Promise.all([ - // getData(`v1/fclts?${queryParamsZone.toString()}`), - // getData(`v1/fclts?${queryParamsFacility.toString()}`) - // ]); const facilityRes = await getData(`v1/fclts?${queryParamsFacility.toString()}`); - // const zones = (zoneRes.data || []).map((item: any) => ({ - // text: item.swtrmtZoneNm || item.name || `구역 ${item.id || item.gid || item.objectid}`, - // val: item.fid || item.id || item.gid || item.objectid - // })); - // setProcessingZoneOptions([defaultOption, ...zones]); - // console.log("BaseLayout Fetched Processing Zones:", [defaultOption, ...zones]); + console.log('facilityRes.data', facilityRes.data); - const facilities = (facilityRes.data || []).map((item: any) => ({ - text: item.swtrmtFcltNm || item.name || `시설 ${item.id || item.gid || item.objectid}`, - val: item.fid || item.id || item.gid || item.objectid - })); + const facilities = (facilityRes.data || []) + .map((item: any) => ({ + text: item.swtrmtFcltNm, + val: item.fid + })) + .sort((a: ApiSelectOption, b: ApiSelectOption) => a.text.localeCompare(b.text, 'ko')); setTreatmentFacilityOptions([defaultOption, ...facilities]); console.log("BaseLayout Fetched Treatment Facilities:", [defaultOption, ...facilities]); } catch (error) { console.error("BaseLayout: 지역/시설 데이터 조회 중 오류 발생:", error); - setProcessingZoneOptions([defaultOption]); setTreatmentFacilityOptions([defaultOption]); } finally { setIsLoadingAreaData(false); @@ -185,7 +143,7 @@ const BaseLayout = ({ }; fetchData(); - }, [sigungu]); // sigungu 상태가 변경될 때마다 실행 + }, [sggName]); // sgg 상태가 변경될 때마다 실행 // 파일 다운로드 const isChckFile = () => { @@ -215,10 +173,10 @@ const BaseLayout = ({

{selectBox.title}

)} -
+
{showDatePicker && ( // showDatePicker 값에 따라 DatePicker 렌더링 <> - + { // aplcnYm이 없으면 현재 연월을 기본값으로 설정 @@ -253,24 +211,26 @@ const BaseLayout = ({ /> )} - setEnoCd?.(val)} - setRtnEnvPartSidoValue={(val) => setCtpvCd?.(val)} - setRtnEnvPartSigunValue={setSigungu} // 선택된 시군구 값을 받을 콜백 함수 전달 - > - - onSwageTreatmentPlantChange?.(val)} - selectContentClass="z-[101]" - /> - {/* onSwageProcessingZoneChange?.(val)} selectContentClass="z-[101]" /> */} - + { + setCtpvCd(sidoId); + setSggCd(0); + }} + onSigunguChange={setSggCd} + setSggName={setSggName} + /> + + onSwageTreatmentPlantChange?.(val)} + selectContentClass="z-[101]" + /> {selectBox?.searchChk && (
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 99542f5bf..e2a51676e 100644 --- a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx @@ -49,13 +49,12 @@ interface ApiSelectOption { const IrSetting = () => { const [input1, setInput1] = useState('0.8'); // 오수전환율 초기값 const [input2, setInput2] = useState(''); - const [select1, setSelect1] = useState('0'); // 환경청코드 - const [select2, setSelect2] = useState('0'); // 시도코드 - const [select3, setSelect3] = useState({ val: '0', text: '전체' }); // 시군구 상태를 객체로 변경 - const [select4, setSelect4] = useState('0'); // 하수처리장코드 - const [select5, setSelect5] = useState('0'); // 하수처리구역코드 + const [select1, setSelect1] = 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 { data: userInfo } = useQuery({ queryKey: [ENDPOINT.USER_SERVICE.USERS], @@ -115,11 +114,7 @@ const IrSetting = () => { setSelectedDate(`${year}${month}`); setInput1(''); // 입력 필드 초기화 setInput2(''); // 입력 필드 초기화 - setSelect1('0'); // 선택 필드 초기화 - setSelect2('0'); - setSelect3({ val: '0', text: '전체' }); - setSelect4(0); - setSelect5(0); + setSelect1(0); setFormResetKey(prevKey => prevKey + 1); // FileUploadForm 재마운트를 위해 key 변경 }; @@ -164,7 +159,7 @@ const IrSetting = () => { setIsLoadingResult(true); // 로딩 상태 시작 // 기본 선택 항목들 검증 (환경청, 시도, 시군구, 하수처리장) - if (!validateBasicSelectionsWithAlert(select1, select2, select3, select4, { + if (!validateBasicSelectionsWithAlert(select1, { requireEnv: true, requireSido: true, requireSigungu: true, @@ -299,15 +294,11 @@ const IrSetting = () => { // 새로운 JSON 데이터 생성 const combinedAnalysisData = { - enoCd: (select1 && select1 !== '0') ? select1.toString() : null, // 환경청코드 (선택값) - ctpvCd: (select2 && select2 !== '0') ? select2.toString() : null, // 시도코드 (선택값) - sggCd: (select3.val && select3.val !== '0') ? select3.val.toString() : null, // 시군구코드 (선택값) - swageTmplntCd: (select4 && select4 !== '0' && select4 !== 0) - ? select4.toString().split('.').pop() || null // '.'으로 split해서 마지막 부분만 사용 + ctpvCd: (ctpvCd ? String(ctpvCd) : null), + sggCd: (sggCd ? String(sggCd) : null), // 시군구코드 (선택값) + swageTmplntCd: (select1 && select1 !== '0' && select1 !== 0) + ? select1.toString().split('.').pop() || null // '.'으로 split해서 마지막 부분만 사용 : null, // 하수처리장코드 (선택값) - swtrmtZoneCd: (select5 && select5 !== '0' && select5 !== 0) - ? select5.toString().split('.').pop() || null // '.'으로 split해서 마지막 부분만 사용 - : null, // 하수처리구역코드 (선택값) aplcnYm: selectedDate, // 적용연월 drtwSwtcRt: parseFloat(input1) || null, // 오수전환율 (숫자로 변환) anlsInfo: input2, // 분석정보 @@ -346,16 +337,14 @@ const IrSetting = () => { graphBtn={false} analysisBtn={'침입수분석 실행'} selectBox={{ title: '분석 대상지역 선택' }} - enoCd={select1} - setEnoCd={setSelect1} - ctpvCd={select2} - setCtpvCd={setSelect2} - sigungu={select3} - setSigungu={setSelect3} - selectedSwageTreatmentPlant={select4} - onSwageTreatmentPlantChange={setSelect4} - selectedSwageProcessingZone={select5} - onSwageProcessingZoneChange={setSelect5} + ctpvCd={ctpvCd} + sggCd={sggCd} + sggName={sggName} + selectedSwageTreatmentPlant={select1} + onSwageTreatmentPlantChange={setSelect1} + setCtpvCd={setCtpvCd} + setSggCd={setSggCd} + setSggName={setSggName} isLoading={isLoadingResult} 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 9bf381b97..491d2ae9d 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx @@ -114,11 +114,10 @@ export default function RTKForm() { initialFileInfo, // 2: 강우자료 ]); - const [select1, setSelect1] = useState('0'); // 환경청코드 (enoCd) - const [select2, setSelect2] = useState('0'); // 시도코드 (ctpvCd) - const [select3, setSelect3] = useState({ val: '0', text: '전체' }); // 시군구 (sggCd) - const [select4, setSelect4] = useState('0'); // 하수처리장 (swageTmplntCd) - const [select5, setSelect5] = useState('0'); // 하수처리구역 (swtrmtZoneCd) + const [select1, setSelect1] = useState('0'); // 하수처리장 (swageTmplntCd) + const [ctpvCd, setCtpvCd] = useState(0); // 시도 코드 상태 + const [sggCd, setSggCd] = useState(0); // 시군구 코드 상태 + const [sggName, setSggName] = useState(''); // 시군구 이름 상태 const { data: userInfo } = useQuery({ queryKey: [ENDPOINT.USER_SERVICE.USERS], @@ -142,10 +141,6 @@ export default function RTKForm() { ]); setFormResetKey(prevKey => prevKey + 1); // FileUploadForm 재마운트를 위해 key 변경 setSelect1('0'); - setSelect2('0'); - setSelect3({ val: '0', text: '전체' }); - setSelect4('0'); - setSelect5('0'); }; // FileUploadForm의 onFileSelect prop으로 전달될 콜백 함수 @@ -182,7 +177,7 @@ export default function RTKForm() { setIsLoadingResult(true); // 로딩 상태 시작 // 기본 선택 항목들 검증 (환경청, 시도, 시군구, 하수처리장) - if (!validateBasicSelectionsWithAlert(select1, select2, select3, select4, { + if (!validateBasicSelectionsWithAlert(select1, { requireEnv: true, requireSido: true, requireSigungu: true, @@ -295,16 +290,12 @@ export default function RTKForm() { // 새로운 JSON 데이터 생성 const combinedAnalysisData = { - enoCd: (select1 && select1 !== '0') ? select1.toString() : null, // 환경청코드 (선택값) aplcnYm: formData.date, // 적용연월 (YYYYMM 형식) - ctpvCd: (select2 && select2 !== '0') ? select2.toString() : null, // 시도코드 (선택값) - sggCd: (select3.val && select3.val !== '0') ? select3.val.toString() : null, // 시군구코드 (선택값) - swageTmplntCd: (select4 && select4 !== '0' && select4 !== 0) - ? select4.toString().split('.').pop() || null // '.'으로 split해서 마지막 부분만 사용 + ctpvCd: ctpvCd ? String(ctpvCd) : null, // 시도코드 (선택값) + sggCd: sggCd ? String(sggCd) : null, // 시군구코드 (선택값) + swageTmplntCd: (select1 && select1 !== '0' && select1 !== 0) + ? select1.toString().split('.').pop() || null // '.'으로 split해서 마지막 부분만 사용 : null, // 하수처리장코드 (선택값) - swtrmtZoneCd: (select5 && select5 !== '0' && select5 !== 0) - ? select5.toString().split('.').pop() || null // '.'으로 split해서 마지막 부분만 사용 - : null, // 하수처리구역코드 (선택값) atflCd: file1?.atflCd, // 첨부파일CD (오수관망도) atflId: file1?.atflId, // 첨부파일ID (오수관망도) atflInpNm: file1?.file?.name || "", // 오수관망도 파일명 @@ -395,7 +386,6 @@ export default function RTKForm() { } return ( - // { }} graphBtn={false} > { }} // BaseLayout의 form 태그에 연결될 onSubmit graphBtn={false} analysisBtn={'RDII분석 실행'} - enoCd={select1} - setEnoCd={setSelect1} - ctpvCd={select2} - setCtpvCd={setSelect2} - sigungu={select3} - setSigungu={setSelect3} - selectedSwageTreatmentPlant={select4} - onSwageTreatmentPlantChange={setSelect4} - selectedSwageProcessingZone={select5} - onSwageProcessingZoneChange={setSelect5} + ctpvCd={ctpvCd} + sggCd={sggCd} + sggName={sggName} + selectedSwageTreatmentPlant={select1} + onSwageTreatmentPlantChange={setSelect1} + setCtpvCd={setCtpvCd} + setSggCd={setSggCd} + setSggName={setSggName} isLoading={isLoadingResult} onAnalysis={handleAnalysisClick} > diff --git a/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx b/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx index 08c7a8146..d705728c5 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx @@ -1,5 +1,5 @@ 'use client' -import { deleteData, getData, useCookieAuth } from '@/components/lib/api' +import { deleteData, getData } from '@/components/lib/api' import { UiTable, downloadExcelWithKoreanHeaders } from '@common/business_components/ui' import { zodResolver } from '@hookform/resolvers/zod' import { useState, useEffect } from 'react' @@ -11,12 +11,6 @@ import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; const formSchema = z.object({ - enoCd: z.string().default('0'), // 환경청코드 - ctpvCd: z.string().default('0'), // 시도코드 - sggCd: z.object({ // 시군구 - val: z.string().default('0'), - text: z.string().default('전체'), - }).default({ val: '0', text: '전체' }), swageTmplntCd: z.string().default('0'), // 하수처리장 swtrmtZoneCd: z.string().default('0'), // 하수처리구역 aplcnYmFrom: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경 @@ -54,14 +48,10 @@ const tableColumn = [ ] const Result = () => { - const AUTH = useCookieAuth(); const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { - enoCd: '0', - ctpvCd: '0', - sggCd: { val: '0', text: '전체' }, swageTmplntCd: '0', swtrmtZoneCd: '0', aplcnYmFrom: (() => { // 현재 연월을 yyyyMM 형식으로 설정 @@ -88,6 +78,9 @@ const Result = () => { const [resetSelection, setResetSelection] = useState(false); const [isResetPage, setIsResetPage] = useState(false); const [curPage, setCurPage] = useState(1); // 현재 페이지 + const [ctpvCd, setCtpvCd] = useState(0); // 시도 코드 상태 + const [sggCd, setSggCd] = useState(0); // 시군구 코드 상태 + const [sggName, setSggName] = useState(''); // 시군구 이름 상태 useEffect(() => { // setCurPage(1); @@ -127,11 +120,9 @@ const Result = () => { let inftwtAnlsSearchDto = { "aplcnYmFrom": formValues.aplcnYmFrom && formValues.aplcnYmFrom !== '' ? formValues.aplcnYmFrom : null, "aplcnYmTo": formValues.aplcnYmTo && formValues.aplcnYmTo !== '' ? formValues.aplcnYmTo : null, - "enoCd": formValues.enoCd === '0' ? null : formValues.enoCd, - "ctpvCd": formValues.ctpvCd === '0' ? null : formValues.ctpvCd, - "sggCd": formValues.sggCd?.val === '0' ? null : formValues.sggCd?.val, + "ctpvCd": ctpvCd === 0 ? null : ctpvCd, + "sggCd": sggCd === 0 ? null : sggCd, "swageTmplntCd": processedSwageTmplntCd, - "auth": AUTH, }; console.log("Search DTO:", inftwtAnlsSearchDto); @@ -163,7 +154,8 @@ const Result = () => { rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가 scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item.scsYn // scsYn이 null이면 'N'으로 변경 }; - }); + }) + .filter((item: any) => item.scsYn === 'Y'); // 선택된 행 초기화 setSelectedRowData(null); @@ -289,20 +281,18 @@ const Result = () => { onSubmitEvent={() => { }} // BaseLayout의 form 태그에 연결될 onSubmit graphBtn={true} showDatePicker={true} - enoCd={form.watch("enoCd")} - setEnoCd={(val) => form.setValue("enoCd", val)} - ctpvCd={form.watch("ctpvCd")} - setCtpvCd={(val) => form.setValue("ctpvCd", val)} - sigungu={form.watch("sggCd")} - setSigungu={(val) => form.setValue("sggCd", val)} + ctpvCd={ctpvCd} + sggCd={sggCd} + sggName={sggName} selectedSwageTreatmentPlant={form.watch("swageTmplntCd")} onSwageTreatmentPlantChange={(val) => form.setValue("swageTmplntCd", String(val))} - selectedSwageProcessingZone={form.watch("swtrmtZoneCd")} - onSwageProcessingZoneChange={(val) => form.setValue("swtrmtZoneCd", String(val))} aplcnYmFrom={form.watch("aplcnYmFrom")} setAplcnYmFrom={(val: string) => { form.setValue("aplcnYmFrom", val) }} aplcnYmTo={form.watch("aplcnYmTo")} setAplcnYmTo={(val: string) => { form.setValue("aplcnYmTo", val) }} + setCtpvCd={setCtpvCd} + setSggCd={setSggCd} + setSggName={setSggName} isLoading={isLoadingResult} // Excel 다운로드 핸들러 추가 onExcelDownload={handleExcelDownload} diff --git a/apps/sn/app/(with-base-layout)/ii/result/page.tsx b/apps/sn/app/(with-base-layout)/ii/result/page.tsx index 974f6fa5f..c27110223 100644 --- a/apps/sn/app/(with-base-layout)/ii/result/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/result/page.tsx @@ -1,6 +1,6 @@ 'use client' -import { deleteData, getData, useCookieAuth } from '@/components/lib/api' -import { UiTable, downloadExcel, downloadExcelWithKoreanHeaders } from '@common/business_components/ui' +import { deleteData, getData } from '@/components/lib/api' +import { UiTable, downloadExcelWithKoreanHeaders } from '@common/business_components/ui' import { zodResolver } from '@hookform/resolvers/zod' import { useState, useEffect } from 'react' import { useForm } from 'react-hook-form' @@ -11,12 +11,6 @@ import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; const formSchema = z.object({ - enoCd: z.string().default('0'), // 환경청코드 - ctpvCd: z.string().default('0'), // 시도코드 - sggCd: z.object({ // 시군구 - val: z.string().default('0'), - text: z.string().default('전체'), - }).default({ val: '0', text: '전체' }), swageTmplntCd: z.string().default('0'), // 하수처리장 swtrmtZoneCd: z.string().default('0'), // 하수처리구역 aplcnYmFrom: z.string().default(() => { // Date에서 string(yyyyMM 형식)으로 변경 @@ -55,9 +49,6 @@ const Result = () => { const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { - enoCd: '0', - ctpvCd: '0', - sggCd: { val: '0', text: '전체' }, swageTmplntCd: '0', swtrmtZoneCd: '0', aplcnYmFrom: (() => { // 현재 연월을 yyyyMM 형식으로 설정 @@ -76,8 +67,6 @@ const Result = () => { } }) - const AUTH = useCookieAuth(); - const [tableData, setTableData] = useState([]); // API 조회 결과 저장 상태 const [totalData, setTotalData] = useState(0) //총 데이터 수l const [isLoadingResult, setIsLoadingResult] = useState(false); // 로딩 상태 @@ -85,6 +74,9 @@ const Result = () => { const [resetSelection, setResetSelection] = useState(false); const [isResetPage, setIsResetPage] = useState(false); const [curPage, setCurPage] = useState(1); // 현재 페이지 + const [ctpvCd, setCtpvCd] = useState(0); // 시도 코드 상태 + const [sggCd, setSggCd] = useState(0); // 시군구 코드 상태 + const [sggName, setSggName] = useState(''); // 시군구 이름 상태 useEffect(() => { // setCurPage(1); @@ -124,12 +116,9 @@ const Result = () => { let inftwtAnlsSearchDto = { "aplcnYmFrom": formValues.aplcnYmFrom && formValues.aplcnYmFrom !== '' ? formValues.aplcnYmFrom : null, "aplcnYmTo": formValues.aplcnYmTo && formValues.aplcnYmTo !== '' ? formValues.aplcnYmTo : null, - "enoCd": formValues.enoCd === '0' ? null : formValues.enoCd, - "ctpvCd": formValues.ctpvCd === '0' ? null : formValues.ctpvCd, - "sggCd": formValues.sggCd?.val === '0' ? null : formValues.sggCd?.val, + "ctpvCd": ctpvCd === 0 ? null : ctpvCd, + "sggCd": sggCd === 0 ? null : sggCd, "swageTmplntCd": processedSwageTmplntCd, - // "swtrmtZoneCd": formValues.swtrmtZoneCd === '0' ? null : formValues.swtrmtZoneCd, - "auth": AUTH, }; console.log("Search DTO:", inftwtAnlsSearchDto); @@ -162,7 +151,8 @@ const Result = () => { rowNumber: (curPage - 1) * 10 + index + 1, // 1부터 시작하는 일련번호 추가 scsYn: item.scsYn === null || item.scsYn === undefined ? 'N' : item.scsYn // scsYn이 null이면 'N'으로 변경 }; - }); + }) + .filter((item: any) => item.scsYn === 'Y'); // 선택된 행 초기화 setSelectedRowData(null); @@ -289,20 +279,18 @@ const Result = () => { onSubmitEvent={() => { }} // BaseLayout의 form 태그에 연결될 onSubmit graphBtn={true} showDatePicker={true} - enoCd={form.watch("enoCd")} - setEnoCd={(val) => form.setValue("enoCd", val)} - ctpvCd={form.watch("ctpvCd")} - setCtpvCd={(val) => form.setValue("ctpvCd", val)} - sigungu={form.watch("sggCd")} - setSigungu={(val) => form.setValue("sggCd", val)} + ctpvCd={ctpvCd} + sggCd={sggCd} + sggName={sggName} selectedSwageTreatmentPlant={form.watch("swageTmplntCd")} onSwageTreatmentPlantChange={(val) => form.setValue("swageTmplntCd", String(val))} - selectedSwageProcessingZone={form.watch("swtrmtZoneCd")} - onSwageProcessingZoneChange={(val) => form.setValue("swtrmtZoneCd", String(val))} aplcnYmFrom={form.watch("aplcnYmFrom")} setAplcnYmFrom={(val: string) => { form.setValue("aplcnYmFrom", val) }} aplcnYmTo={form.watch("aplcnYmTo")} setAplcnYmTo={(val: string) => { form.setValue("aplcnYmTo", val) }} + setCtpvCd={setCtpvCd} + setSggCd={setSggCd} + setSggName={setSggName} isLoading={isLoadingResult} // 로딩 상태 전달 // Excel 다운로드 핸들러 추가 onExcelDownload={handleExcelDownload} diff --git a/apps/sn/app/(with-base-layout)/layout.tsx b/apps/sn/app/(with-base-layout)/layout.tsx index 3c1a527d7..8c72ecb0c 100644 --- a/apps/sn/app/(with-base-layout)/layout.tsx +++ b/apps/sn/app/(with-base-layout)/layout.tsx @@ -1,11 +1,13 @@ "use client"; +import React, { useEffect} from 'react'; import { usePathname, useRouter } from "next/navigation"; import { useQueryClient } from "@tanstack/react-query"; import { BaseLayout } from "@common/components"; import type { MenuItem } from "@/entities/menu"; import { useMenuStore } from "@/shared/lib"; import { PageLayout } from "@/shared/ui/page-layout"; +import useStore from '../store/useStore'; export default function WithBaseLayout({ children, @@ -18,6 +20,15 @@ export default function WithBaseLayout({ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); + const { fetchCtpvData, fetchSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); + + useEffect(() => { + fetchCtpvData(); + fetchSggData(); + fetchBIZ_SE_CD(); + fetchBIZ_TY_CD(); + }, []); + const handleMenuClick = (item: MenuItem) => { setCurrentMenuInfo(item); router.push(item.urlPath); diff --git a/apps/sn/app/(with-base-layout)/selectionValidation.tsx b/apps/sn/app/(with-base-layout)/selectionValidation.tsx index 8cc506d0e..e5cdb77ad 100644 --- a/apps/sn/app/(with-base-layout)/selectionValidation.tsx +++ b/apps/sn/app/(with-base-layout)/selectionValidation.tsx @@ -87,10 +87,7 @@ export const validateMultipleSelectionsWithAlert = ( * @returns 검증 결과 */ export const validateBasicSelections = ( - select1: string, - select2: string, - select3: ApiSelectOption, - select4: string | number, + select1: string | number, options: { requireEnv?: boolean; requireSido?: boolean; @@ -108,21 +105,6 @@ export const validateBasicSelections = ( const validationConfigs: SelectionValidationConfig[] = [ { value: select1, - description: '환경청', - required: requireEnv - }, - { - value: select2, - description: '시도', - required: requireSido - }, - { - value: select3, - description: '시군구', - required: requireSigungu - }, - { - value: select4, description: '하수처리장', required: requireTreatmentPlant } @@ -133,18 +115,12 @@ export const validateBasicSelections = ( /** * 기본 선택 항목들 검증 및 alert 표시 - * @param select1 환경청코드 - * @param select2 시도코드 - * @param select3 시군구 객체 - * @param select4 하수처리장코드 + * @param select1 하수처리장코드 * @param options 각 항목의 필수 여부 설정 * @returns 검증 결과 */ export const validateBasicSelectionsWithAlert = ( - select1: string, - select2: string, - select3: ApiSelectOption, - select4: string | number, + select1: string | number, options: { requireEnv?: boolean; requireSido?: boolean; @@ -152,7 +128,7 @@ export const validateBasicSelectionsWithAlert = ( requireTreatmentPlant?: boolean; } = {} ): boolean => { - const result = validateBasicSelections(select1, select2, select3, select4, options); + const result = validateBasicSelections(select1, options); if (!result.isValid && result.errorMessage) { alert(result.errorMessage); return false; diff --git a/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx b/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx index a3a138259..fc9962e75 100644 --- a/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx +++ b/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx @@ -3,10 +3,6 @@ import { SelectBox } from '@common/business_components/ui' import { Label } from '@common/components'; import useStore from '../../store/useStore'; -interface Option { - id: number; - name: string; -} interface SidoSigunguSelectBoxProps { sido: number; diff --git a/apps/sn/app/store/index.ts b/apps/sn/app/store/index.ts new file mode 100644 index 000000000..b20466d77 --- /dev/null +++ b/apps/sn/app/store/index.ts @@ -0,0 +1,64 @@ +import { getGeoData, getCmsData } from "@/components/lib/api"; + + +export interface Option { id: number, name: string } + +export type BIZ_CD_TYPE = { + lwpoCd: string, + upCd: string, + lwpoCdNm: string, + unit: string, + prntLwpoCd: null +}; + +export const fetchCtpvData = async (set: (state: any) => void) => { + try { + const ctpvData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_ctpv&outputFormat=application%2Fjson'); + const ctpvList: Option[] = ctpvData.features + .map((feature: any) => ({ + id: feature.properties.mctpv_cd.trim(), + name: feature.properties.mctpv_korn_nm + })) + .sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko')); + set({ ctpv: ctpvList }); + } catch (e: any) { + alert("시도 데이터 로드 실패: " + e.message); + console.error("CTPV 데이터 로드 실패:", e); + } +}; + +export const fetchSggData = async (set: (state: any) => void) => { + try { + const sggData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_sgg&outputFormat=application%2Fjson'); + const sggList: Option[] = sggData.features + .map((feature: any) => ({ + id: feature.properties.sgg_cd, + name: feature.properties.sgg_korn_nm + })) + .sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko')); + set({ sgg: sggList }); + } catch (e: any) { + alert("시군구 데이터 로드 실패: " + e.message); + console.error("SGG 데이터 로드 실패:", e); + } +}; + +export const fetchBIZ_SE_CD = async (set: (state: any) => void) => { + try { + const res = await getCmsData(`/api/v1/code/cache/BIZSECD`); + set({ BIZ_SE_CD: res }); + } catch (e: any) { + alert("BIZ_SE_CD 데이터 로드 실패: " + e.message); + console.error("BIZ_SE_CD 데이터 로드 실패:", e); + } +}; + +export const fetchBIZ_TY_CD = async (set: (state: any) => void) => { + try { + const res = await getCmsData(`/api/v1/code/cache/BIZTYCD`); + set({ BIZ_TY_CD: res }); + } catch (e: any) { + alert("BIZ_TY_CD 데이터 로드 실패: " + e.message); + console.error("BIZ_TY_CD 데이터 로드 실패:", e); + } +}; \ No newline at end of file diff --git a/apps/sn/app/store/useStore.ts b/apps/sn/app/store/useStore.ts index 518cce66b..7775ca61e 100644 --- a/apps/sn/app/store/useStore.ts +++ b/apps/sn/app/store/useStore.ts @@ -1,41 +1,37 @@ -import { useMemo } from "react"; import { create } from "zustand"; -import { getGeoData } from "@/components/lib/api"; -import { get } from "http"; +import { getGeoData, getCmsData } from "@/components/lib/api"; +import { fetchCtpvData, fetchSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } from "./index"; interface Option { id: number, name: string } +export type BIZ_CD_TYPE = { + lwpoCd: string, + upCd: string, + lwpoCdNm: string, + unit: string, + prntLwpoCd: null +}; + interface SnStoreState { ctpv: Option[]; sgg: Option[]; + BIZ_SE_CD: BIZ_CD_TYPE[]; + BIZ_TY_CD: BIZ_CD_TYPE[]; fetchCtpvData: () => Promise; fetchSggData: () => Promise; + fetchBIZ_SE_CD: () => Promise; + fetchBIZ_TY_CD: () => Promise; } const useStore = create((set) => ({ - // Define your store state and actions here ctpv: [], sgg: [], - fetchCtpvData: async () => { - const ctpvData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_ctpv&outputFormat=application%2Fjson'); - const ctpvList: Option[] = ctpvData.features - .map((feature: any) => ({ - id: feature.properties.mctpv_cd.trim(), - name: feature.properties.mctpv_korn_nm - })) - .sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko')); - set({ ctpv: ctpvList }); - }, - fetchSggData: async () => { - const sggData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_sgg&outputFormat=application%2Fjson'); - const sggList: Option[] = sggData.features - .map((feature: any) => ({ - id: feature.properties.sgg_cd, - name: feature.properties.sgg_korn_nm - })) - .sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko')); - set({ sgg: sggList }); - } + BIZ_SE_CD: [], + BIZ_TY_CD: [], + fetchCtpvData: () => fetchCtpvData(set), + fetchSggData: () => fetchSggData(set), + fetchBIZ_SE_CD: () => fetchBIZ_SE_CD(set), + fetchBIZ_TY_CD: () => fetchBIZ_TY_CD(set), })); export default useStore; \ No newline at end of file