From 05b4a4dae547541197c9b9162aab9c3e74ec63bf Mon Sep 17 00:00:00 2001 From: leedj312 Date: Tue, 2 Sep 2025 17:30:05 +0900 Subject: [PATCH] =?UTF-8?q?=EB=AC=BC=EC=9E=AC=EC=9D=B4=EC=9A=A9=20?= =?UTF-8?q?=EC=A7=80=EB=8F=84=20=EC=98=A4=EB=B2=84=EB=A0=88=EC=9D=B4=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EB=B9=BC=EA=B3=A0=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wr/app/(map-layout)/map/mainMap/page.tsx | 217 +++++++++++++++--- .../(popUp-layout)/mapFeaturePopup/page.tsx | 2 +- apps/wr/app/store/common/code/basicCode.tsx | 1 + apps/wr/app/store/map/pbnstMap/index.tsx | 9 +- apps/wr/app/store/map/ruseMap/index.tsx | 79 +++++-- .../ruseFcltMng/fcltReg/rswtReg/index.tsx | 4 +- apps/wr/components/lib/func/mapUtil.ts | 116 ++++++++-- .../wrOverLay/WrOverLayRuse/WrOverLayRuse.tsx | 88 +++++++ .../WrOverLayTable/WrOverLayTable.tsx | 33 +++ .../components/ui/map/wrOverLay/wrOverLay.tsx | 50 ++++ 10 files changed, 526 insertions(+), 73 deletions(-) create mode 100644 apps/wr/components/ui/map/wrOverLay/WrOverLayRuse/WrOverLayRuse.tsx create mode 100644 apps/wr/components/ui/map/wrOverLay/WrOverLayTable/WrOverLayTable.tsx create mode 100644 apps/wr/components/ui/map/wrOverLay/wrOverLay.tsx diff --git a/apps/wr/app/(map-layout)/map/mainMap/page.tsx b/apps/wr/app/(map-layout)/map/mainMap/page.tsx index f75604d86..f31263202 100644 --- a/apps/wr/app/(map-layout)/map/mainMap/page.tsx +++ b/apps/wr/app/(map-layout)/map/mainMap/page.tsx @@ -15,9 +15,14 @@ import { getWrLayerNm, } from "@/components/lib/func/mapUtil"; import toast, { Toaster } from "react-hot-toast"; +import createOverlayManager from "@common/business_components/ui/map/GisOverlay"; +import { createRoot } from "react-dom/client"; +import WrOverLay from "@/components/ui/map/wrOverLay/wrOverLay"; +import type { comCodeState } from "@/app/store/common/code"; const Map = () => { - const { comMap } = useWrStore((state) => state); + + const {code, comMap ,rainMapDetile ,rswtMapDetile,getRuseMaplListReturn,pbnMapDetaile,ldrmntMapDetile,htdfMapDetile,coSttnMapDetail} = useWrStore((state) => state); const { isFeatured } = comMap; const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정 const gisMaps = useRef(null); @@ -79,11 +84,10 @@ const Map = () => { // SearchModal, GisContent 등에서 호출 const onFeatureFocus = (data: any) => { - console.log('data',data) + console.log("data", data); }; - const onFeatureSelect = (data: any ,popUpClick?:boolean) => { - + const onFeatureSelect = (data: any, popUpClick?: boolean) => { const map = gisMaps.current; if (!map) { console.warn("지도가 초기화되지 않았습니다."); @@ -100,21 +104,22 @@ const Map = () => { // 2. data가 OpenLayers Feature 인스턴스인지 확인 let foundFeature: any = null; let featureId = data.fid; - - if(popUpClick){ + + if (popUpClick) { const layerName = getWrLayerNm(data); const featurePk = getWrFeaturePk(layerName ?? ""); // 재이용시설 if (featurePk) { - - const lastPk = layerName==='tb_wr_ruse_fclt_dmd_co'? data[featurePk].replaceAll("-", "") : data[featurePk] + const lastPk = + layerName === "tb_wr_ruse_fclt_dmd_co" + ? data[featurePk].replaceAll("-", "") + : data[featurePk]; featureId = `${layerName}.${lastPk}`; } else { console.warn("해당 피처는 선택된 레이어에서 찾을수 없습니다."); } - }else{ - featureId=getClickFeatureId(data) - + } else { + featureId = getClickFeatureId(data); } map .getLayers() @@ -143,9 +148,9 @@ const Map = () => { } select.selectFeature(foundFeature, true); } else { - // toast.error('위치정보를 찾을수 없습니다') + // toast.error('위치정보를 찾을수 없습니다') console.warn("OpenLayers Feature를 찾을 수 없습니다:"); - console.log("foundFeature :", foundFeature ); + console.log("foundFeature :", foundFeature); console.warn("featureId : ", featureId); console.warn("data : ", data); console.warn(": 끝"); @@ -157,14 +162,21 @@ const Map = () => { setIsOpen(true); setIsSearchModalOpen(false); - if (popUpClick && foundFeature&&!( - Object.keys(foundFeature?.getProperties()).length === 0 && - foundFeature.constructor === Object - )){ - const layerName = getWrLayerNm(data); - const isColumn = getFeatureCd(foundFeature.getProperties(), String(layerName)); - if(layerName&&isColumn) - featurePopUpOpen(layerName,isColumn,popupDetailRef) + if ( + popUpClick && + foundFeature && + !( + Object.keys(foundFeature?.getProperties()).length === 0 && + foundFeature.constructor === Object + ) + ) { + const layerName = getWrLayerNm(data); + const isColumn = getFeatureCd( + foundFeature.getProperties(), + String(layerName) + ); + if (layerName && isColumn) + featurePopUpOpen(layerName, isColumn, popupDetailRef); } }; @@ -178,14 +190,12 @@ const Map = () => { const bc = new BroadcastChannel("mapDetailPopUp"); bc.onmessage = (event) => { if (event.data.type === "SELECT_FEATURE") { - onFeatureSelect(event.data.feature,true); + onFeatureSelect(event.data.feature, true); closePopup(); } }; }, []); - - const renderDetailView = useCallback( (props: any) => { const map = gisMaps.current; @@ -202,11 +212,10 @@ const Map = () => { isFeature.constructor === Object ) ) { - const layerNm = getSelectedLayers(isFeature,gisMaps); - const safeProps = isFeature.getProperties(); + const layerNm = getSelectedLayers(isFeature, gisMaps); + const safeProps = isFeature.getProperties(); const featureCd = getFeatureCd(safeProps, String(layerNm)); - if(layerNm) - featurePopUpOpen(layerNm,featureCd,popupDetailRef) + if (layerNm) featurePopUpOpen(layerNm, featureCd, popupDetailRef); } } else { console.log(" data확인 필요"); @@ -239,6 +248,158 @@ const Map = () => { } }; + + const OVERLAY_MIN_ZOOM = 16; +const OVERLAY_COORD_PRECISION = 5; +const OVERLAY_MAX_PER_VIEW = 800; + +const overlayManagersRef = useRef([]); +const overlayActiveRef = useRef(false); +const moveEndDebounceRef = useRef(null); + +const overlayFormatter = (feature: any, props: any) => { + const propertise = props || {}; + const featureId = + feature.getId?.() ?? + propertise?.id ?? + propertise?.fid ?? + propertise?.ftrIdn ?? + ''; + if (!featureId) return null; + + const fcltTableId = featureId.split('.')[0]; + const fcltCd = getFeatureCd(props, fcltTableId); + + const div = document.createElement("div"); + const root = createRoot(div); + + // 비동기 처리만 따로 + (async () => { + let overLayData; + let title = ''; + + if (fcltTableId === 'tb_il_swage_prcs_fclt') { + overLayData = await pbnMapDetaile( fcltCd); + title = '하수처리시설'; + } else if (fcltTableId === 'tb_wr_bdst_ruse_fclt') { + overLayData = await getRuseMaplListReturn(fcltCd); + title = '하수재이용시설'; + + } else if (fcltTableId === 'tb_wr_rnwtr_utztn_fclt') { + overLayData = await rainMapDetile(fcltCd); + title = '빗물이용시설'; + } else if (fcltTableId === 'tb_wr_rswtr_fclt') { + overLayData = await rswtMapDetile(fcltCd); + title = '중수도시설'; + } else if (fcltTableId === 'tb_wr_htdfl_fclt') { + overLayData = await htdfMapDetile(fcltCd); + title = '온배수시설'; + } else if (fcltTableId === 'tb_wr_ruse_fclt_dmd_co') { + overLayData = await coSttnMapDetail(fcltCd); + title = '수요처'; + } else if (fcltTableId === 'tb_wr_tmpr_dmd_co') { + overLayData = await ldrmntMapDetile(fcltCd); + title = '잠재수요처'; + } + + root.render(} />); + })(); + + // 제거 시 React unmount + (div as any).__dispose = () => root.unmount(); + + return div; // <-- HTMLDivElement 동기 리턴 +}; + +const destroyAllManagers = () => { + overlayManagersRef.current.forEach(m => { try { m.destroy(); } catch {} }); + overlayManagersRef.current = []; + overlayActiveRef.current = false; +}; + +const mountOverlayManagers = () => { + const map = gisMaps.current; + if (!map) return; + + // 이전 것 정리 + destroyAllManagers(); + + // 체크된 벡터 레이어만 골라 매니저 생성 + const checkedSet = new Set(checkedLayers.map(String)); + const layers: any[] = map.getLayers().getArray(); + const targets = layers.filter((layer: any) => { + const src = layer.getSource?.(); + const isVector = src && typeof src.getFeatures === "function"; + const id = String(layer.get?.("lyrSn") ?? layer.get?.("id") ?? ""); + return isVector && layer.getVisible?.() && checkedSet.has(id); + }); + + targets.forEach((layer: any) => { + const mgr = createOverlayManager(map, layer, overlayFormatter, { + coordPrecision: OVERLAY_COORD_PRECISION, + maxOverlaysPerViewport: OVERLAY_MAX_PER_VIEW, + }); + mgr.mount(); // 리스너 1회 등록 + mgr.enable(); // 표시 + 1회 sync + overlayManagersRef.current.push(mgr); + }); + + overlayActiveRef.current = overlayManagersRef.current.length > 0; +}; + +useEffect(() => { + const map = gisMaps.current; + if (!map) return; + + const z = map.getView()?.getZoom?.() ?? 0; + if (z < OVERLAY_MIN_ZOOM) { + // 저줌에선 그냥 안 보이게만 + overlayManagersRef.current.forEach(m => { try { m.disable({ clear:true, delayed:true }); } catch {} }); + return; + } + mountOverlayManagers(); + + return () => { destroyAllManagers(); }; +}, [checkedLayers]); + + +useEffect(() => { + const map = gisMaps.current; + if (!map) return; + + const onMoveStart = () => { + // 숨기기만 (리스너/DOM 대량 제거 X) + overlayManagersRef.current.forEach(m => { try { m.disable({ clear:false }); } catch {} }); + if (moveEndDebounceRef.current) { clearTimeout(moveEndDebounceRef.current); moveEndDebounceRef.current = null; } + }; + + const onMoveEnd = () => { + const z = map.getView()?.getZoom?.() ?? 0; + const active = overlayActiveRef.current; + + if (moveEndDebounceRef.current) clearTimeout(moveEndDebounceRef.current); + moveEndDebounceRef.current = window.setTimeout(() => { + if (z < OVERLAY_MIN_ZOOM) { + if (active) overlayManagersRef.current.forEach(m => { try { m.disable({ clear:true, delayed:true }); } catch {} }); + return; + } + if (!active) { + mountOverlayManagers(); + } else { + // 다시 보이고 1회만 동기화 + overlayManagersRef.current.forEach(m => { try { m.enable(); m.syncOverlays(); } catch {} }); + } + }, 180) as unknown as number; + }; + + map.on("movestart", onMoveStart); + map.on("moveend", onMoveEnd); + return () => { + map.un("movestart", onMoveStart); + map.un("moveend", onMoveEnd); + if (moveEndDebounceRef.current) { clearTimeout(moveEndDebounceRef.current); moveEndDebounceRef.current = null; } + }; +}, [checkedLayers]); return (
{ + pbnMapDetaile(isFeatureCd).then((res) => { setIsDetail(res); }); } else if (layerNm === "tb_wr_rnwtr_utztn_fclt") { diff --git a/apps/wr/app/store/common/code/basicCode.tsx b/apps/wr/app/store/common/code/basicCode.tsx index 8af04c59f..5fc13c16d 100644 --- a/apps/wr/app/store/common/code/basicCode.tsx +++ b/apps/wr/app/store/common/code/basicCode.tsx @@ -211,6 +211,7 @@ export const rswtPrscCdMthdCd = [ }, { val: "소독(염소, UV 등)", text: "소독(염소, UV 등)" }, { val: "기타", text: "기타" }, + { val: "확인불가", text: "확인불가" }, ]; export const htdPowerMthdCd= [ diff --git a/apps/wr/app/store/map/pbnstMap/index.tsx b/apps/wr/app/store/map/pbnstMap/index.tsx index 4cd118caa..18f9abfe2 100644 --- a/apps/wr/app/store/map/pbnstMap/index.tsx +++ b/apps/wr/app/store/map/pbnstMap/index.tsx @@ -77,7 +77,6 @@ type pbnMapActions = { ) => void; pbnMapDetaile: ( featureCd: string, - data: string ) => Promise; }; @@ -117,11 +116,11 @@ export const pbnMapActionsExport: (set: any) => pbnMapActions = (set: any) => { console.log(e); } }, - pbnMapDetaile: async (featureCd: string, data: string) => { + pbnMapDetaile: async ( featureCd: string) => { try { const hasuRes = await postFectch( - `/prcsFclt/ruseInfo/1/20/A/0/0/1/SW/${featureCd}`, - [data], + `/prcsFclt/ruseInfo/1/1/A/0/0/1/SW/`, + [featureCd], fetchType.COMMON ); const filteredData = hasuRes.data.map((item: any) => { @@ -131,7 +130,7 @@ export const pbnMapActionsExport: (set: any) => pbnMapActions = (set: any) => { ruse: item.ruse === false ? "N" : "Y", }; }); - return filteredData; + return filteredData[0]; } catch (error) { console.log(error); throw error; // 호출부에서 catch 가능하도록 diff --git a/apps/wr/app/store/map/ruseMap/index.tsx b/apps/wr/app/store/map/ruseMap/index.tsx index 5e07a9b72..f68fb96b3 100644 --- a/apps/wr/app/store/map/ruseMap/index.tsx +++ b/apps/wr/app/store/map/ruseMap/index.tsx @@ -42,8 +42,8 @@ type ruseMapActions = { fclts: string[], fcltNm: string ) => void; - ruseMapDetail: (ruseFcltId: string) => Promise; getRuseMaplList: (bscFctCd: string) => void; + getRuseMaplListReturn: (bscFctCd: string) => Promise; }; export type ruseMapType = ruseMapState & ruseMapActions; @@ -106,21 +106,7 @@ export const ruseMapActionsExport: (set: any) => ruseMapActions = ( console.log(e); } }, - ruseMapDetail: async (ruseFcltId: string) => { - try { - let ruseDetail = await getFetch("wr", `/reuseFc/pubFc/${ruseFcltId}`); - if (ruseDetail.length >= 0) { - ruseDetail = ruseDetail.find( - (item: customPbnst) => item.pbnstRuseFcltId === ruseFcltId - ); - } - // 🔑 스토어 업데이트 대신 리턴 - return ruseDetail; - } catch (errorHasu) { - console.log(errorHasu); - throw errorHasu; // 호출부에서 catch 가능하도록 - } - }, + getRuseMaplList: async (bscFctCd: string) => { try { const ruseDetailList = await getFetch( @@ -204,5 +190,66 @@ export const ruseMapActionsExport: (set: any) => ruseMapActions = ( console.log(e); } }, + + getRuseMaplListReturn: async (bscFctCd: string) => { + try { + const ruseDetailList = await getFetch( + fetchType.WR, + `/reuseFc/pubFc/${bscFctCd}` + ); + const year = new Date().getFullYear(); + const data = [bscFctCd]; + const rusePrfList = await postFectch( + `/reuseFc/pubDetailList/${year}/0/1/10`, + data, + fetchType.WR + ); + const dataList = ruseDetailList.map((ruse) => { + const matchRuse = rusePrfList?.data.find( + (prf) => prf.pbnstRuseFcltId === ruse.pbnstRuseFcltId + ); + + + const usage = matchRuse.prfList.reduce( + (acc, cur) => { + acc.inUsage += + cur.wshwtr + + cur.coolUswtr + + cur.cleanUswtr + + cur.drwtUswtr + + cur.dltnUswtr + + cur.ithlRswtr + + cur.ithlEtcUswtr + + cur.cleanToilUswtr + + cur.resn; + acc.outUsage += + cur.lndwtr + + cur.hydUswtr + + cur.ugwtChr + + cur.farmUswtr + + cur.rvrKeepUswtr + + cur.indstUswtr; + acc.total = acc.inUsage + acc.outUsage; + + return acc; + }, + { total: 0, inUsage: 0, outUsage: 0 } + ); + + + return { + ...ruse, + prfList: matchRuse.prfList, + inUsage: usage?.inUsage, + outUsage: usage?.outUsage, + + }; + }); + return dataList + } catch (errorHasu) { + console.log(errorHasu); + throw errorHasu; // 호출부에서 catch 가능하도록 + } + } }; }; diff --git a/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx b/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx index 02ea00b19..42e771292 100644 --- a/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx +++ b/apps/wr/app/store/ruseFcltMng/fcltReg/rswtReg/index.tsx @@ -18,8 +18,8 @@ const rswtrObjSchema = z.object({ filtrTrtmfctProcs: z.string({ required_error: validationMessages.required("주요처리공정") }).min(1, { message: validationMessages.required("주요처리공정") }), filtrTrtmfctUsgCd: z.string().default("").nullish(), rswtrUsqty: z.number().default(0), - altUswtrUtztnYn: z.enum(["Y", "N"]).nullish(), //안쓰는값 - altUswtrKndCd: z.string().default("").nullish(), //안쓰는값 + //altUswtrUtztnYn: z.enum(["Y", "N"]).nullish(), //안쓰는값 +// altUswtrKndCd: z.string().default("").nullish(), //안쓰는값 altUswtrUtztnQnt: z.number().default(0), //안쓰는값 altUswtrIdntyMthdCd: z.string().default("").nullish(), //안쓰는값 rgtr: z.string().nullish().default(null), diff --git a/apps/wr/components/lib/func/mapUtil.ts b/apps/wr/components/lib/func/mapUtil.ts index a23b48484..283b53a75 100644 --- a/apps/wr/components/lib/func/mapUtil.ts +++ b/apps/wr/components/lib/func/mapUtil.ts @@ -1,3 +1,5 @@ +import type { comCodeState } from "@/app/store/common/code"; + const wrLayerList = [ { text: "tb_il_swage_prcs_fclt", val: "bscFctCd" }, { text: "tb_wr_bdst_ruse_fclt", val: "pbnstRuseFcltId" }, @@ -26,8 +28,7 @@ const wrFeaturePK = [ // { text: "잠재수요처", val: "tb_wr_tmpr_dmd_co" }, export const getFeatureCd = (featurePropertise: any, layerNm: string) => { - - console.log('featurePropertise ', featurePropertise) + console.log("featurePropertise ", featurePropertise); const featureCd = layerNm === "tb_wr_bdst_ruse_fclt" ? featurePropertise?.swtrmt_fclt_cd @@ -39,32 +40,30 @@ export const getFeatureCd = (featurePropertise: any, layerNm: string) => { ].includes(layerNm) ? featurePropertise?.bdst_nm : layerNm === "tb_il_swage_prcs_fclt" - ? featurePropertise?.swtrmt_fclt_nm - : layerNm === "tb_wr_ruse_fclt_dmd_co"? - featurePropertise?.bdst_info_sn - : null; + ? featurePropertise?.swtrmt_fclt_cd + : layerNm === "tb_wr_ruse_fclt_dmd_co" + ? featurePropertise?.bdst_info_sn + : null; return featureCd; }; export const getWrLayerNm = (featurePropertise: any) => { const result = wrLayerList - .filter(item => item.val in featurePropertise) // 키 존재 여부 체크 - .map(item => item.text); - + .filter((item) => item.val in featurePropertise) // 키 존재 여부 체크 + .map((item) => item.text); return result[0]; }; - -export const getWrFeaturePk = (layerName :string) => { +export const getWrFeaturePk = (layerName: string) => { const result = wrFeaturePK - .filter(item => item.val === layerName) // 키 존재 여부 체크 - .map(item => item.text); + .filter((item) => item.val === layerName) // 키 존재 여부 체크 + .map((item) => item.text); return result[0]; }; -export const getSelectedLayers = (isFeature: any, gisMaps:any) => { +export const getSelectedLayers = (isFeature: any, gisMaps: any) => { const map = gisMaps.current; if (!map) { console.warn("지도가 초기화되지 않았습니다."); @@ -97,11 +96,11 @@ export const getSelectedLayers = (isFeature: any, gisMaps:any) => { return result; }; -export const getClickFeatureId = (data: any) => { - let featureId ='' +export const getClickFeatureId = (data: any) => { + let featureId = ""; const layerName = data.layerNm; if (layerName === "하수재이용시설") { - // 재이용시설 + // 재이용시설 featureId = `${layerName}.${data.searchPk}`; } else if ( //빗물이용시설, 중수도시설 @@ -124,7 +123,11 @@ export const getClickFeatureId = (data: any) => { return featureId; }; -export function featurePopUpOpen(layerNm:string,featureCd:string,popupDetailRef){ +export function featurePopUpOpen( + layerNm: string, + featureCd: string, + popupDetailRef +) { const url = `/mapFeaturePopup?layerNm=${encodeURIComponent(String(layerNm))}&featureCd=${encodeURIComponent(featureCd)} `; const width = String(layerNm) === "tb_wr_bdst_ruse_fclt" @@ -134,8 +137,8 @@ export function featurePopUpOpen(layerNm:string,featureCd:string,popupDetailRef) String(layerNm) === "tb_wr_bdst_ruse_fclt" ? Math.floor(window.innerHeight - 100) : String(layerNm) === "tb_wr_ruse_fclt_dmd_co" - ?Math.floor(window.innerHeight - 430) - : Math.floor(window.innerHeight - 300); // 150px 여백 확보; // calc(100% - 70px) + ? Math.floor(window.innerHeight - 430) + : Math.floor(window.innerHeight - 300); // 150px 여백 확보; // calc(100% - 70px) const left = (window.screen.availWidth - width) / 2; const top = (window.screen.availHeight - height) / 2; const popupOptions = `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes `; @@ -145,4 +148,75 @@ export function featurePopUpOpen(layerNm:string,featureCd:string,popupDetailRef) "지도 시설 상세정보 팝업", popupOptions ); -} \ No newline at end of file +} + +export const getOverLayObj = (fclType: string, data: any,code?:Partial) => { + let newObj = {}; + let title = ""; + + + if (fclType === "하수재이용시설") { + newObj = { + "시설용량(톤/일)": data?.fcltCpct ??"", + "재이용률(%)": (data?.fcltCpct / data?.bscFctCpc)||0, + "장내용수(m³/년)": data?.inUsage ?? "", + "장외용수(m3/년)":data?.outUsage ?? "", + // 수요처: data?.reuseBuilding[0]?.rainyObj.pntfColArea ?? "", + }; + title = data?.bdstNm ?? ""; + } else if (fclType === "하수처리시설") { + newObj = { + "시설용량(톤/일)": data?.fctCpc ?? "", + 지역구분: data?.efflWqltStndrdNm ?? "", + 재이용여부: data?.rswtrYn ?? "", + "재이용시설 등록여부": data?.ruse ?? "", + }; + title = data?.bscFctNm ?? ""; + } else if (fclType === "빗물이용시설" ) { + newObj = { + 건물용도: code?.code?.bdstUsgCd.find((item) => item.val===data?.reuseBuilding[0].bdstUsgCd )?.text ?? "", + 설치완료일: data?.reuseBuilding[0]?.instlCmptnDt ?? "", + 처리시설유무: data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctYn ?? "", + "처리시설용량(m³/일)": + data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctCpct ?? "", + "저류조용량(m³)": data?.reuseBuilding[0]?.rainyObj.pntfColArea ?? "", + }; + title = data?.bdstNm ?? ""; + } else if (fclType === "중수도시설") { + newObj = { + 건물용도: code?.code?.bdstUsgCd.find((item) => item.val===data?.reuseBuilding[0].bdstUsgCd )?.text ?? "", + 설치완료일: data?.reuseBuilding[0]?.instlCmptnDt ?? "", + "주요 처리공정": code?.code?.rswtPrscCdMthdCd.find((item) => item.val===data?.reuseBuilding[0]?.rswtrObj.filtrTrtmfctProcs)?.text ?? "", + 원수종류: code?.code?.orgwtKndCd.find((item) => item.val === data?.reuseBuilding[0]?.rswtrObj.orgwtKndCd)?.text ?? "", + //이용용도: isCode.filtrTrtmfctUsgCd data?.reuseBuilding[0]?.rswtrObj.altUswtrKndCd ?? "", + }; + title = data?.bdstNm ?? ""; + } else if (fclType === "온배수시설") { + newObj = { + 미정: "", + // '설치완료일': data?.reuseBuilding[0]?.instlCmptnDt??'', + // '처리시설유무': data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctYn??'', + // '처리시설용량(m³/일)': data?.reuseBuilding[0]?.rainyObj.filtrTrtmfctCpct??'', + // '저류조용량(m³)': data?.reuseBuilding[0]?.rainyObj.pntfColArea??'', + }; + title = data?.bdstNm ?? ""; + } else if (fclType === "수요처") { + newObj = { + '사업자등록번호': data?.dmdInfoId??'', + '주소': data?.daddr??'', + '전화번호': data?.telno??'', + }; + title = data?.dmdCoNm ?? ""; + + } else if (fclType === "잠재수요처") { + newObj = { + 공장구분: data?.fctrySe ?? "", + 설립구분: data?.fndnSe ?? "", + 업종명: data?.tpbizNm ?? "", + 생산폼목: data?.prdctnItem ?? "", + }; + title = data?.dmdCoNm ?? ""; + } + + return { title, newObj }; +}; diff --git a/apps/wr/components/ui/map/wrOverLay/WrOverLayRuse/WrOverLayRuse.tsx b/apps/wr/components/ui/map/wrOverLay/WrOverLayRuse/WrOverLayRuse.tsx new file mode 100644 index 000000000..62369c348 --- /dev/null +++ b/apps/wr/components/ui/map/wrOverLay/WrOverLayRuse/WrOverLayRuse.tsx @@ -0,0 +1,88 @@ +"use client"; + +import { useEffect, useState } from "react"; +import WrOverLayTable from "../WrOverLayTable/WrOverLayTable"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@common/components/ui"; +import { getOverLayObj } from "@/components/lib/func/mapUtil"; + + +type RuseTabData = { + data: Record; + tabData:{ + pbnstRuseFcltId: string; + ruseUtztnFcltNm: string; + } +} + + +export default function WrOverLayRuse({ overLayData }: { overLayData: any }) { + const [fcltTab, setFcltTab] = useState(""); + const [ruseData, setRuseData] = useState([]as RuseTabData[]); + // useEffect(() => { + // const detail = overLayData.find((list) => list.pbnstRuseFcltId === fcltTab); + // if (detail) setIsDetail(detail); + // }, [fcltTab, overLayData]); + + useEffect(() => { + + if (overLayData && overLayData[0]) { + setFcltTab(overLayData[0].pbnstRuseFcltId); + + const newRuseData= overLayData.map((ruse) =>{ + const isData = getOverLayObj( '하수재이용시설',ruse); + return { + data: isData.newObj, + tabData:{ + pbnstRuseFcltId: ruse.pbnstRuseFcltId, + ruseUtztnFcltNm: ruse.ruseUtztnFcltNm + } + } + }) + + setRuseData(newRuseData); + } + }, [overLayData]); + + if (!(overLayData && overLayData[0])) return; + return ( + <> +
+
+
+ + + {ruseData?.map((item, index) => { + return ( + + {item.tabData.ruseUtztnFcltNm} + + ); + })} + + + {ruseData?.map((item) => ( + +
+ +
+
+ ))} +
+
+ + ); +} diff --git a/apps/wr/components/ui/map/wrOverLay/WrOverLayTable/WrOverLayTable.tsx b/apps/wr/components/ui/map/wrOverLay/WrOverLayTable/WrOverLayTable.tsx new file mode 100644 index 000000000..db992a507 --- /dev/null +++ b/apps/wr/components/ui/map/wrOverLay/WrOverLayTable/WrOverLayTable.tsx @@ -0,0 +1,33 @@ +import { Table, TableBody, TableCell, TableRow } from "@common/components/ui"; + +export default function WrOverLayTable({overLayData}:{overLayData:any,}){ + + + + return( + + <> + + + {Object.entries(overLayData).map(([key, value]) => ( + + + {" "} + {key}{" "} + + + + {" "} + {String(value)}{" "} + + + ))} + +
+ + ) +} \ No newline at end of file diff --git a/apps/wr/components/ui/map/wrOverLay/wrOverLay.tsx b/apps/wr/components/ui/map/wrOverLay/wrOverLay.tsx new file mode 100644 index 000000000..bc8394a9a --- /dev/null +++ b/apps/wr/components/ui/map/wrOverLay/wrOverLay.tsx @@ -0,0 +1,50 @@ +"use client"; +import type { comCodeState } from "@/app/store/common/code"; +import { getOverLayObj } from "@/components/lib/func/mapUtil"; +import { Card } from "@common/business_components/ui/chart/lib/card"; +import { useEffect, useState } from "react"; +import WrOverLayTable from "./WrOverLayTable/WrOverLayTable"; +import WrOverLayRuse from "./WrOverLayRuse/WrOverLayRuse"; + +export default function WrOverLay({ + title, + data, + code, +}: { + title: string; + data: any; + code: Partial; +}) { + const [newOverLayData, setNewOverLayData] = useState>( + {} + ); + const [typeTitle, setTypeTitle] = useState(""); + + useEffect(() => { + if (title !== "하수재이용시설" && data) { + const overRayData = getOverLayObj(title, data, code); + setTypeTitle(overRayData?.title ?? ""); + setNewOverLayData(overRayData.newObj ?? {}); + } + }, [title, data]); + + return ( + <> + + {/* 파란 제목 바 */} + {title !== "하수재이용시설" ? ( +
+ {typeTitle + "(" + title + ")"} +
+ ) : ( + <> + )} + {title === "하수재이용시설" ? ( + + ) : ( + + )} +
+ + ); +}