diff --git a/apps/dm/app/page.tsx b/apps/dm/app/page.tsx index fdb323086..a5f49f0bc 100644 --- a/apps/dm/app/page.tsx +++ b/apps/dm/app/page.tsx @@ -30,6 +30,9 @@ export default function Home() { + ); diff --git a/apps/dm/app/pages/map/mainMap/page.tsx b/apps/dm/app/pages/map/mainMap/page.tsx index f1def0310..ca33e5142 100644 --- a/apps/dm/app/pages/map/mainMap/page.tsx +++ b/apps/dm/app/pages/map/mainMap/page.tsx @@ -1,13 +1,27 @@ "use client"; -const Map = () => { - +import { SearchBar } from "@/components/ui/map/searchBar/searchBar"; +import { useEffect, useState } from "react"; + +const Map = () => { + + const [selectDataPk, setSelectDataPk] = useState ('') + + // 삭제요망 데이터 선ㅌ + useEffect(() =>{ + console.log("Selected Data Pk: ", selectDataPk); + },[selectDataPk]) return ( <> - - + { + console.log("Selected HasuPk: ", hasuPk); + if(hasuPk !==""){ + setSelectDataPk(hasuPk); + } + }} + /> - ); }; diff --git a/apps/dm/app/store/map/index.tsx b/apps/dm/app/store/map/index.tsx new file mode 100644 index 000000000..8ed8fce40 --- /dev/null +++ b/apps/dm/app/store/map/index.tsx @@ -0,0 +1,85 @@ +import { getFetch } from "@/components/ui/api"; +import { DEV_URL_FO } from "@/components/ui/config"; +import type { FacilityInfo } from "./type"; + +const checkWrRegList = async () => { + const wrRegList = await getFetch("wr", `/reuseFc/pubFc`); + return wrRegList; +}; + +const getRuseFclt = async ( + page: string, + sggOrCity: string, + searchTxt?: string +) => { + const checkWrRegListRes = await checkWrRegList(); + + let url = `/prcsFclt/ruseInfo/${page ? page : 1}/11/A/${sggOrCity ? sggOrCity : "11"}/0/1/SW`; + + console.log(' checkWrRegListRes ', checkWrRegListRes) + const ruseList = checkWrRegListRes.data.filter((item: string) => item !== ""); + + if (searchTxt) { + url = url + `/${searchTxt}`; + } + + const response = await fetch(DEV_URL_FO + url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(ruseList), + }); + + const hasuList = await response.json().then((res: any) => { + + const data =res.data + .map((item: any) => { + return { + ...item, + fctCpc: Number(item.fctCpc) || 0, + searchNm: item.fctNm, + searchPk: item.bscFctNm, + + }; + }) + .filter((hasu) => + ruseList.find((ruse) => hasu.bscFctCd === ruse) + ); + return{ data: data, count: res.count }; + + }); + return hasuList +}; + +export type DmMapActions = { + findRuseFclt(sggOrCity:string, searchTxt: string): void; +}; + +export type DmMapType = { + map: { + ruseFcltList: FacilityInfo[]; + }; +}; + +export const dmMapState: DmMapType = { + map: { + ruseFcltList: [], + }, +}; +export type DmMapStore = DmMapType & DmMapActions; + +export const DmMapReducer = (set: any): DmMapActions => { + return { + findRuseFclt: async (sggOrCity:string, searchTxt: string) => { + const ruseFcltList = await getRuseFclt('1', sggOrCity,searchTxt); + + set((state: DmMapType) => ({ + map: { + ...state.map, + ruseFcltList :ruseFcltList.data + }, + })); + }, + }; +}; diff --git a/apps/dm/app/store/map/type.tsx b/apps/dm/app/store/map/type.tsx new file mode 100644 index 000000000..4d6cea0ac --- /dev/null +++ b/apps/dm/app/store/map/type.tsx @@ -0,0 +1,34 @@ +export type FacilityInfo= { + bscFctCd: string; // 기본시설 코드 + bscFctNm: string; // 기본시설명 + rvbsnCd: string; // 유역 코드 + rvbsn: string; // 유역명 + lgbsn: string; // 대권역명 + mdmbsn: string; // 중권역명 + rgnCd: string; // 관할청 코드 + rgnNm: string; // 관할청 명칭 + adstDstrCd: string; // 행정구역 코드 + sido: string; // 시도 + gugun: string; // 구군 + addr: string; // 주소 + fctCpc: string; // 시설용량 + efflWqltStndrdCd: string; // 방류수 수질기준 코드 + efflWqltStndrdNm: string; // 방류수 수질기준명 + trtFrfNm: string; // 처리공법명 + trtDstr: string; // 처리구역 + rnDt: string; // 사용개시일 (예: YYYYMMDD) + cmplDt: string; // 준공일자 (예: YYYYMMDD) + trstOprEtpNm: string; // 위탁운영기관명 + bscFctClsNm: string; // 기본시설 구분명 + sitArea: string; // 부지면적 + trtDstrArea: string; // 처리구역 면적 + swrTrtPopl: string; // 하수처리 인구 + mnstr: string; // 총괄 유역 + efflWtrrgn: string; // 방류수역 + rvNm: string; // 하천명 + bscFctClsCd: string; // 기본시설 구분 코드 + rvbsnNm: string; // 유역명 + tel: string; // 전화번호 + rswtrYn: string; // 재이용수 여부 ("Y" 또는 "N") + ruse: boolean; // 재이용 여부 (boolean) + } \ No newline at end of file diff --git a/apps/dm/app/store/sdmMng/index.tsx b/apps/dm/app/store/sdmMng/index.tsx index e51c6b56a..8e487543f 100644 --- a/apps/dm/app/store/sdmMng/index.tsx +++ b/apps/dm/app/store/sdmMng/index.tsx @@ -387,11 +387,9 @@ export const SdmState: SdmType = { similarCaseList: similarCaseList, upHeadMoneyDetailList : moneyDetailModalHeader, moneyDetailList: moneyDetailList, - // 수요정보 신청현황 sdmInfoStatusList: [], upHeadSdmInfoStatus: upHeadSdmInfoStatus, - // 로그인관련 successNextPage : false, successLogin: false, diff --git a/apps/dm/app/store/store.tsx b/apps/dm/app/store/store.tsx index 66b626aa3..7107012d9 100644 --- a/apps/dm/app/store/store.tsx +++ b/apps/dm/app/store/store.tsx @@ -1,19 +1,23 @@ import { createStore } from 'zustand/vanilla'; import { CommonReducer, CommonState, type CommonStore, type CommonType } from './common'; import { SdmReducer, SdmState, type SdmStore, type SdmType } from './sdmMng'; +import { dmMapState, type DmMapType, type DmMapStore, DmMapReducer } from './map'; -export type DmStore = CommonStore & SdmStore; -export type DmState = CommonType & SdmType; +export type DmStore = CommonStore & SdmStore &DmMapStore ; +export type DmState = CommonType & SdmType &DmMapType; export const StoreZus = (initState: DmState= { ...CommonState, ...SdmState, + ...dmMapState, }) => { return createStore()((set) => { + return { ...initState, ...CommonReducer(set), - ...SdmReducer(set) + ...SdmReducer(set), + ...DmMapReducer(set) } }) } \ No newline at end of file diff --git a/apps/dm/components/ui/map/SearchInputText/SearchInputText.tsx b/apps/dm/components/ui/map/SearchInputText/SearchInputText.tsx new file mode 100644 index 000000000..3660891f1 --- /dev/null +++ b/apps/dm/components/ui/map/SearchInputText/SearchInputText.tsx @@ -0,0 +1,108 @@ +import React, { useCallback, useEffect, useRef, useState } from "react"; + +type SearchType = { + searchNm: string; + searchPk: string; +}; +type thisProps = { + label: string | undefined; + initValue: string | undefined; + setValue: (searchNm?: string) => void; + setRtnData: (rtnData: any) => void; + searchList?: any[]; +}; +export default function SearchInputText({ + label = undefined, + initValue = undefined, + setValue = () => {}, + setRtnData = () => {}, + searchList = undefined, +}: thisProps) { + + const [isOpen, setIsOpen] = useState(false); + const [textValue, setTextValue] = useState(initValue || ""); + + const wrapperRef = useRef(null); + const handleInputChange = useCallback( + (e: React.ChangeEvent) => { + const value = e.target.value; + + setTextValue(value); + setValue(value); + if (value && value!=='') { + setIsOpen(true); + } else { + setIsOpen(false); + } + }, + [setValue] + ); + + const handleSuggestionClick = useCallback( + (searchNm: string) => { + // Do not update textValue to keep input unchanged on suggestion click + setValue(searchNm); + setIsOpen(false); + setRtnData(searchList?.find((item) => item.searchNm === searchNm) || {}); + }, + [searchList, setRtnData, setValue] + ); + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + wrapperRef.current && + !wrapperRef.current.contains(event.target as Node) + ) { + setIsOpen(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, []); + + return ( +
+ setIsOpen(true)} */ + className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" + placeholder={`${label}을(를) 입력하세요`} + /> + {isOpen && ( +
+
+ {searchList && searchList.length > 0 ? ( + searchList.map((item: SearchType, index: number) => ( +
handleSuggestionClick(item.searchNm)} + role="button" + tabIndex={0} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === " ") { + handleSuggestionClick(item.searchNm); + } + }} + > + {item.searchPk?.substring(0, 10)}  + {item.searchNm} +
+ )) + ) : ( +
+ 검색 결과가 없습니다. +
+ )} +
+
+ )} +
+ ); +} diff --git a/apps/dm/components/ui/map/searchBar/searchBar.tsx b/apps/dm/components/ui/map/searchBar/searchBar.tsx index f6af413ef..61c9fb6d6 100644 --- a/apps/dm/components/ui/map/searchBar/searchBar.tsx +++ b/apps/dm/components/ui/map/searchBar/searchBar.tsx @@ -1,6 +1,134 @@ -export function SearchBar() { - return ( - <> - +"use client"; +import { useDmStore } from "@/app/store"; +import { + SearchDiv, + SearchFormLeft, + SearchFormRight, + SelectBox, + type SelectDataType, +} from "@common/business_components/ui"; +import { Label } from "@common/components/ui"; +import { useCallback, useEffect, useState } from "react"; +import SearchInputText from "../SearchInputText/SearchInputText"; + +export function SearchBar({ + + setHasuPk +}:{ + setHasuPk: (hasuPk: string) => void, +} + +) { + const {map, Common, initializeCommonData ,findRuseFclt} = useDmStore((state) => state); + const [sidoValue, setSidoValue] = useState(""); + const [sigunValue, setSigunValue] = useState(""); + const [filteredSigunData, setFilteredSigunData] = useState([ + { text: "전체", val: "0" }, + ]); + useEffect(() => { + initializeCommonData(); + }, [initializeCommonData]); + + const initializeSigunData = useCallback( + (sidoCd: string) => { + if (sidoCd === "0") { + setSigunValue("0"); + setFilteredSigunData([{ text: "전체", val: "0" }]); + } else { + const newFilteredData = [ + { text: "전체", val: "0" }, + ...Common.selectSigunData.filter( + (item: SelectDataType) => item.val.substring(0, 2) === sidoCd + ), + ]; + setSigunValue("0"); + setFilteredSigunData(newFilteredData); + } + }, + [Common.selectSigunData] ); -} \ No newline at end of file + const onSelectValue = useCallback( + (val: string, type: string) => { + switch (type) { + case "ctpvCd": + initializeSigunData(val); + setSidoValue(val); + break; + case "sggCd": + setSigunValue(val); + } + }, + [initializeSigunData] + ); + + +useEffect(()=>{ + console.log('map.ruseFcltList ', map.ruseFcltList) +},[map.ruseFcltList]) + + return ( + <> +
+
+ + +
+ + onSelectValue(val.toString(), "ctpvCd") + } + value={sidoValue|| Common.selectSidoData[0]?.val || ""} + /> + + onSelectValue(val.toString(), "sggCd") + } + value={sigunValue} + /> +
+ + { + let sggOrCity='' + if(searchNm){ + if(sigunValue === "0" || sigunValue === "") { + sggOrCity = sidoValue; + }else{ + sggOrCity = sigunValue; + } + findRuseFclt(sggOrCity, searchNm); + } + }} + setRtnData={(rtnData: any)=> { + setHasuPk(rtnData.bscFctCd || ""); + }} + searchList={map.ruseFcltList || []} + /> +
+
+
+ +
+ {/* */} +
+
+
+
+
+ + ); +}