From 83845d686029d87a67df3ecc86fc4420036ec9c9 Mon Sep 17 00:00:00 2001 From: JIeunhuh Date: Tue, 27 May 2025 13:18:55 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=EB=85=B8=ED=9B=84=20=ED=95=98=EC=88=98?= =?UTF-8?q?=EA=B4=80=EB=A1=9C=20=EA=B5=AC=ED=98=84=20=EC=9E=91=EC=97=85=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/app/components/lib/api/index.ts | 9 +++++++-- apps/sn/app/oper/floodPre/page.tsx | 2 +- apps/sn/app/oper/oldPp/page.tsx | 26 ++++++++++++------------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/sn/app/components/lib/api/index.ts b/apps/sn/app/components/lib/api/index.ts index e2f5cbf95..0045047e1 100644 --- a/apps/sn/app/components/lib/api/index.ts +++ b/apps/sn/app/components/lib/api/index.ts @@ -9,8 +9,13 @@ export const postData = async (url: string, data: object): Promise => { body: JSON.stringify(data), }; const res = await fetch(`${BASE_URL}/${url}`, options); - const resData = await res.json(); - return resData; + if (res.ok) { + const text = await res.text(); + if (text) { + return JSON.parse(text); // JSON 데이터가 있으면 파싱하여 반환 + } + return true; // 응답 본문이 비어 있으면 true 반환 + } }; export const postMutiPart = async (url: string, data: FormData): Promise => { diff --git a/apps/sn/app/oper/floodPre/page.tsx b/apps/sn/app/oper/floodPre/page.tsx index ec0608fd7..0a619b2bb 100644 --- a/apps/sn/app/oper/floodPre/page.tsx +++ b/apps/sn/app/oper/floodPre/page.tsx @@ -13,7 +13,7 @@ import { deleteData, getData, postData } from '@/components/lib/api' const Page = () => { // 조회조건 - const [fromDate, setFromDate] = useState(new Date()) + const [fromDate, setFromDate] = useState(()=>{const date = new Date(); date.setDate(date.getDate()-7); return date}) const [toDate, setToDate] = useState(new Date()) const [manageYear, setManageYear] = useState('') const [mngQu, setMngQu] = useState('') diff --git a/apps/sn/app/oper/oldPp/page.tsx b/apps/sn/app/oper/oldPp/page.tsx index f7ca87ca5..8f241621a 100644 --- a/apps/sn/app/oper/oldPp/page.tsx +++ b/apps/sn/app/oper/oldPp/page.tsx @@ -5,13 +5,13 @@ import React, { useEffect, useState } from 'react' import OperFileUploadForm from '../../components/ui/operFileUploadForm' import ListDiv from '@common/business_components/ui/list_div' import ContentLayout from '@/components/ui/contentLayout' -import { tableHeadlist } from '..' +import { tableHeadlistOldPp } from '..' import { handleDownload } from '@/components/lib/utils/fileDownload' import { searchData } from '@/components/lib/common/apiHelpers' import { formatDate } from '@/components/lib/utils/date' import { deleteData, getData, postData } from '@/components/lib/api' const Page = () => { - const [fromDate, setFromDate] = useState(new Date()); + const [fromDate, setFromDate] = useState(()=>{const date = new Date(); date.setDate(date.getDate()-7); return date}); const [toDate, setToDate] = useState(new Date()); const [manageYear, setManageYear] = useState('') const [mngQu, setMngQu] = useState('') @@ -19,8 +19,7 @@ const Page = () => { const [pjNm, setpjNm] = useState('') const [fileNm, setFileNm] = useState('') const [atflId, setAtflId] = useState('') - const [atflCd, setAtflCd] = useState('') - const [sbmrgPrevntBizSn, setSbmrgPrevntBizSn] = useState('') + const [dcrpPplMtncBizSn, setDcrpPplMtncBizSn] = useState('') const [tableData, setTableData] = useState([{}]) const [curPage, setCurPage] = useState(1) // 데이터 조회 @@ -30,7 +29,7 @@ const Page = () => { fromMngYr: manageYear, toMngYr: mngQu, toRegDt: formatDate(toDate), - atflNm: pjNm, + dcrpPplMtncBizNm: pjNm, rgtrNm: usr, page: curPage - 1, size: '10' @@ -52,14 +51,14 @@ const Page = () => { } // 파일 삭제 const isDeleteFile = async () => { - if (fileNm === '' || fileNm === undefined) { + if (dcrpPplMtncBizSn === '' || dcrpPplMtncBizSn === undefined) { alert('삭제할 파일을 선택해주세요') return false } - const data = await getData(`/attach-service/api/v1/atfl/attachments/${atflId}`) + const data = await deleteData(`/attach-service/api/v1/atfl/attachments/${atflId}`) if (data) { - const delData = await deleteData(`v1/sbmrgPrevnt/${sbmrgPrevntBizSn}`) - if (delData) { + const delData = await deleteData(`v1/dcrpPpl/${dcrpPplMtncBizSn}`) + if (delData.status == 200) { alert('삭제되었습니다.') fetchData() } else { @@ -74,9 +73,10 @@ const Page = () => { mngYr: year, mngQu: quater, atflCd: cd, - atflId: id + atflId: id, + dcrpPplMtncBizNm: fileNm }) - if (data.ok) { setAtflId(data.atflId); setAtflCd(data.atflCd) } + if (data) {alert('파일이 등록되었습니다.');fetchData() } } return ( @@ -119,7 +119,7 @@ const Page = () => { setpjNm(e.target.value)} + onChange={(e) => {setpjNm(e.target.value)}} /> @@ -137,7 +137,7 @@ const Page = () => { - { if (index != null) { const fileName = tableData[index]?.fileNm ?? ""; setFileNm(fileName); setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn) } }} onPageChange={async (page:number)=>{setCurPage(page); await fetchData()}}> + { if (index != null) { const fileName = tableData[index]?.dcrpPplMtncBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setDcrpPplMtncBizSn(tableData[index]?.dcrpPplMtncBizSn) } }} onPageChange={async (page:number)=>{setCurPage(page); await fetchData()}}> { await registFile(file, year, quater, cd, id) }} /> From 5395969952627f9a7381522a8d322584a6e22add Mon Sep 17 00:00:00 2001 From: JIeunhuh Date: Tue, 27 May 2025 13:41:07 +0900 Subject: [PATCH 2/6] =?UTF-8?q?url=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/app/oper/oldPp/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sn/app/oper/oldPp/page.tsx b/apps/sn/app/oper/oldPp/page.tsx index 8f241621a..4eea3049e 100644 --- a/apps/sn/app/oper/oldPp/page.tsx +++ b/apps/sn/app/oper/oldPp/page.tsx @@ -46,7 +46,7 @@ const Page = () => { alert('파일을 선택해주세요') return false } - handleDownload(`/attach-service/api/v1/download/${atflId}}`, fileNm) + handleDownload(`/attach-service/api/v1/download/${atflId}`, fileNm) return true } // 파일 삭제 From 2fe86d591333a7a700c6177f5fb6f7d86cbefc10 Mon Sep 17 00:00:00 2001 From: JIeunhuh Date: Tue, 27 May 2025 14:06:26 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=95=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EA=B0=AF=EC=88=98=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/app/components/lib/common/apiHelpers.ts | 2 +- apps/sn/app/oper/floodPre/page.tsx | 8 +++++--- apps/sn/app/oper/oldPp/page.tsx | 7 +++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/sn/app/components/lib/common/apiHelpers.ts b/apps/sn/app/components/lib/common/apiHelpers.ts index 508556571..6f205c875 100644 --- a/apps/sn/app/components/lib/common/apiHelpers.ts +++ b/apps/sn/app/components/lib/common/apiHelpers.ts @@ -10,5 +10,5 @@ export const searchData = async>(url: string, para }, {} as Record) ); const data = await getData(`${url}?${params.toString()}`); - return data && data.content + return data && {data : data.content, total : data.totalElements} } diff --git a/apps/sn/app/oper/floodPre/page.tsx b/apps/sn/app/oper/floodPre/page.tsx index 0a619b2bb..a260d530b 100644 --- a/apps/sn/app/oper/floodPre/page.tsx +++ b/apps/sn/app/oper/floodPre/page.tsx @@ -9,7 +9,7 @@ import { searchData } from '@/components/lib/common/apiHelpers' import { tableHeadlist } from '..' import { handleDownload } from '@/components/lib/utils/fileDownload' import { formatDate } from '@/components/lib/utils/date' -import { deleteData, getData, postData } from '@/components/lib/api' +import { deleteData, postData } from '@/components/lib/api' const Page = () => { // 조회조건 @@ -25,8 +25,9 @@ const Page = () => { const [sbmrgPrevntBizSn, setSbmrgPrevntBizSn] = useState('') //파일 일련번호 const [tableData, setTableData] = useState([{}]) //테이블 데이터 const [curPage, setCurPage] = useState(1) //현재 페이지 + const [totalData, setTotalData] = useState(0) //총 데이터 수 const fetchData = async () => { - const data = await searchData('v1/sbmrgPrevnt', { + const {data, total} = await searchData('v1/sbmrgPrevnt', { fromRegDt: formatDate(fromDate), fromMngYr: manageYear, toMngYr: mngQu, @@ -37,6 +38,7 @@ const Page = () => { size: '10' }) setTableData(data) + setTotalData(total) } useEffect(() => { setCurPage(1) @@ -133,7 +135,7 @@ const Page = () => { - { if (index != null) {const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn) } }} onPageChange={async (page:number)=>{setCurPage(page); await fetchData()}}> + { if (index != null) {const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn);} }} onPageChange={async (page:number)=>{setCurPage(page); await fetchData()}}> { await registFile(file, year, quater, cd, id) }} /> diff --git a/apps/sn/app/oper/oldPp/page.tsx b/apps/sn/app/oper/oldPp/page.tsx index 4eea3049e..cf49a1f18 100644 --- a/apps/sn/app/oper/oldPp/page.tsx +++ b/apps/sn/app/oper/oldPp/page.tsx @@ -22,9 +22,10 @@ const Page = () => { const [dcrpPplMtncBizSn, setDcrpPplMtncBizSn] = useState('') const [tableData, setTableData] = useState([{}]) const [curPage, setCurPage] = useState(1) + const [totalData, setTotalData] = useState(0) //총 데이터 수 // 데이터 조회 const fetchData = async () => { - const data = await searchData('v1/dcrpPpl', { + const {data, total} = await searchData('v1/dcrpPpl', { fromRegDt: formatDate(fromDate), fromMngYr: manageYear, toMngYr: mngQu, @@ -35,6 +36,8 @@ const Page = () => { size: '10' }) setTableData(data) + setTotalData(total) + console.log(data, total) } useEffect(() => { setCurPage(1) @@ -137,7 +140,7 @@ const Page = () => { - { if (index != null) { const fileName = tableData[index]?.dcrpPplMtncBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setDcrpPplMtncBizSn(tableData[index]?.dcrpPplMtncBizSn) } }} onPageChange={async (page:number)=>{setCurPage(page); await fetchData()}}> + { if (index != null) { const fileName = tableData[index]?.dcrpPplMtncBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setDcrpPplMtncBizSn(tableData[index]?.dcrpPplMtncBizSn) } }} onPageChange={async (page:number)=>{setCurPage(page); await fetchData()}}> { await registFile(file, year, quater, cd, id) }} /> From e0041cbde4b034d3edbcd39a6b612ca2f58796ea Mon Sep 17 00:00:00 2001 From: JIeunhuh Date: Tue, 27 May 2025 15:54:55 +0900 Subject: [PATCH 4/6] =?UTF-8?q?ngii=20=EC=84=A4=EC=A0=95=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/map/lib/gis.core.js | 70 ++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/packages/common/business_components/src/ui/map/lib/gis.core.js b/packages/common/business_components/src/ui/map/lib/gis.core.js index 4085e2907..1869b766a 100644 --- a/packages/common/business_components/src/ui/map/lib/gis.core.js +++ b/packages/common/business_components/src/ui/map/lib/gis.core.js @@ -14,6 +14,9 @@ import CircleStyle from 'ol/style/Circle'; import VectorLayer from 'ol/layer/Vector'; import { Point } from 'ol/geom'; import { boundingExtent } from 'ol/extent'; +import TileWMTS from 'ol/source/WMTS'; +import WMTS from 'ol/tilegrid/WMTS'; +import { get as getProjection } from 'ol/proj'; import olSourceImageWMS from 'ol/source/ImageWMS'; import { GeoJSON } from 'ol/format'; import GisOlEditLayer from './gis.edit'; @@ -32,20 +35,26 @@ GisApp.GEOSERVER_URL = '/geoserver/hasudo/ows'; GisApp.GEOSERVER_WMS_URL = '/geoserver/hasudo/wms'; //맵 정보 -GisApp.EMAP_URL = '/emap/'; -GisApp.EMAP_SATELLITE_URL = '/emap/satellite/'; -GisApp.VWORLD_URL = 'https://xdworld.vworld.kr/2d/Base/service/{z}/{x}/{y}.png'; -GisApp.VWORLD_SATELLITE_URL = 'https://xdworld.vworld.kr/2d/Satellite/service/{z}/{x}/{y}.jpeg'; GisApp.GOOGLE_API_KEY = 'AIzaSyCf1sgeELFalfPuqlykRKBMj6X9u_DQH6M'; GisApp.GOOGLE_ROADMAP_URL = `https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&key=${GisApp.GOOGLE_API_KEY}`; GisApp.GOOGLE_SATELLITE_URL = `https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}&key=${GisApp.GOOGLE_API_KEY}`; GisApp.GOOGLE_HYBRID_URL = `https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}&key=${GisApp.GOOGLE_API_KEY}`; GisApp.GOOGLE_3D_URL = `https://tile.googleapis.com/v1/3dtiles/root.json?key=${GisApp.GOOGLE_API_KEY}`; + +// TODO: NGII 정보 +GisApp.NGII_API_KEY = '305CC242F2920F46BB93BCC13A52DD8A'; // NGII에서 발급받은 API 키 +GisApp.NGII_WMTS_URL = `http://map.ngii.go.kr/openapi/wmts_ngiiMap.js?apikey=${GisApp.NGII_API_KEY}`; + +GisApp.EMAP_URL = '/emap/'; +GisApp.EMAP_SATELLITE_URL = '/emap/satellite/'; +GisApp.VWORLD_URL = 'https://xdworld.vworld.kr/2d/Base/service/{z}/{x}/{y}.png'; +GisApp.VWORLD_SATELLITE_URL = 'https://xdworld.vworld.kr/2d/Satellite/service/{z}/{x}/{y}.jpeg'; GisApp.OPENSTREET_URL = '//tile.openstreetmap.org/{z}/{x}/{y}.png'; GisApp.BASE_MAP_TYPES = []; GisApp.FROM_PROJ = 'EPSG:4326'; -GisApp.TO_PROJ = 'EPSG:3857'; +// GisApp.TO_PROJ = 'EPSG:3857'; +GisApp.TO_PROJ = 'EPSG:5179'; //ngii 좌표계 GisApp.TO_DATA_PROJ = 'EPSG:4326'; GisApp.CONTEXT_LAYER_PATH = '/images/map/layericon/'; GisApp.layerCode = {}; @@ -86,6 +95,7 @@ GisApp.core.prototype = { minZoom: 5, maxZoom: 22, }, + options: { /*1: { zoom: 16, minZoom: 10, maxZoom: 22, centerX: 35.3227711, centerY: 129.1836202, dataProj: 'EPSG:5186' }, 4: { zoom: 16, minZoom: 10, maxZoom: 22, centerX: 35.0140499, centerY: 126.7110757, dataProj: 'EPSG:5186' }, @@ -109,11 +119,15 @@ GisApp.core.prototype = { GisApp.Module.core = this; GisApp.Module.layer = new GisOlLayer(this.defaults); GisApp.Module.edit = new GisOlEditLayer(this.defaults); - + // TODO: vworld layer 정보 (getNGIIbaseMap)활성화 하면 ngii base map으로 변경됨 this.baseMiniMapLayers['base'] = this.getBaseMap('minimap-base'); this.baseLayers['base'] = this.getBaseMap('base'); this.baseLayers['satellite'] = this.getBaseMap('satellite'); this.baseLayers['3d'] = this.getBaseMap('3d'); + // this.baseLayers['3d'] = this.getNGIIBaseMap('3d'); + // this.baseMiniMapLayers['base'] = this.getNGIIBaseMap('minimap-base'); + // this.baseLayers['base'] = this.getNGIIBaseMap('base'); + // this.baseLayers['satellite'] = this.getNGIIBaseMap('satellite'); }, layerType: { point: 'POINT', @@ -126,6 +140,46 @@ GisApp.core.prototype = { this.setCenter(Number(this.defaults.centerX), Number(this.defaults.centerY)); this.setZoom(15); }, + // NGII Base Map + getNGIIBaseMap: function (_id) { + const layers = { + base: 'korean_map', // 일반지도 + satellite: 'satellite_map', // 위성지도 + night: 'night_map', // 야간지도 + }; + // 선택된 레이어 + const layerName = layers[_id] || layers.base; + // EPSG:5179 좌표계 설정 + const projection = getProjection('EPSG:5179'); + const extent = [705680.0000, 1349270.0000,1388291.0000, 2581448.0000]; // NGII 좌표계 범위 + const resolutions = [ + 2088.96, 1044.48, 522.24, 261.12, 130.56, 65.28, 32.64, 16.32, 8.16, 4.08, 2.04, 1.02, 0.51, 0.255, + ]; + const tileGrid = new WMTS({ + extent: extent, + resolutions: resolutions, + matrixIds: resolutions.map((_, index) => index.toString()), // WMTS matrix IDs + }); + + // WMTS 소스 생성 + const wmtsSource = new TileWMTS({ + url: GisApp.NGII_WMTS_URL, + layer: layerName, + matrixSet: 'EPSG:5179', + format: 'image/png', + projection: projection, + tileGrid: tileGrid, + style: 'default', + crossOrigin: 'anonymous', + }); + + // TileLayer 생성 + return new TileLayer({ + source: wmtsSource, + visible: true, + zIndex: 0, + }); + }, getBaseMap: function (_id) { let url = GisApp.VWORLD_URL; if (_id === 'satellite') { @@ -182,7 +236,7 @@ GisApp.core.prototype = { setCenter: function (x, y, transYn) { if (!x || !y) return; let view = this.map.getView(); - + if (!transYn) { // 값이 없으면 let center = olProj.transform([Number(y), Number(x)], GisApp.FROM_PROJ, GisApp.TO_PROJ); @@ -553,7 +607,7 @@ GisApp.core.prototype = { */ convertLayerInfosToLayerCode: function (array, key, parentName) { let initialValue = {}; - + for (let i = 0; i < array.length; i++) { let item = {}; Object.assign(item, array[i]); From 3f6026065a5da213826614a108d10b467ef646b7 Mon Sep 17 00:00:00 2001 From: yschoi Date: Tue, 27 May 2025 16:37:21 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=ED=8C=8C=EB=B9=84=EC=BD=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/components/lib/auth/lib/auth-wrapper.tsx | 3 +++ apps/sn/public/favicon.ico | Bin 0 -> 4286 bytes 2 files changed, 3 insertions(+) create mode 100644 apps/sn/public/favicon.ico diff --git a/apps/sn/app/components/lib/auth/lib/auth-wrapper.tsx b/apps/sn/app/components/lib/auth/lib/auth-wrapper.tsx index 0b72cc768..5b5e18143 100644 --- a/apps/sn/app/components/lib/auth/lib/auth-wrapper.tsx +++ b/apps/sn/app/components/lib/auth/lib/auth-wrapper.tsx @@ -43,6 +43,9 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => { const accessToken = tokenManager.getToken(CLAIM_NAME); const tokenId = tokenManager.getToken(AUTH_USER_ID); + //TODO 삭제 + console.log(accessToken) + const response = await axios.get( `${ENDPOINT.USER_SERVICE.USERS}/info/me`, { diff --git a/apps/sn/public/favicon.ico b/apps/sn/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d304b69814b2d79060a24f36f667a7f53b768103 GIT binary patch literal 4286 zcmb`K3s6*59LCQ|ikK6XsZsfun##0v95pR15s|b|G%-a`$DE!vmSyIHWMNFiN+Xg- zJ|hw%MPPwl7SPpQ9=pp!V|wiw5)a-aYr6|L^?2bA>?& z4ZjBt6!KrO`(7dX2q6X$4he4}#~ok2?iNDQ*{|$R#ginMY$Exjid2&tQcm`gRm6up z(AoOV=Cjs|WDBV!aDmI5Q$#)@4?C-St8uRFOQK05amA}Pr;=+I+{$(1bFLXn%I?6c z+)F#_Y$iQ!^r(I2yeZ@qQP%iB?o(LvJ~gLfjL%1tKW^cc{m5MRk*y?=7|0oNt9>SO zPEUtVdF8klskljvb9}ag$oH`q=|(ifjdUji$wFc#H`_;)(kt&dzYCG?xU+ROKJ&hD zo!V#4^B^CR2BKE4jpGxQYx&umv^be>HONgkiwBkS-g^GhOXdoAR6 zr`?YIaqUc^)|dPlG2@zlFz?m&+060h9kp)v${L>&wcftxcvpR>c-zVI_}g_V*Rl2^ zqhaYAxvD%y5^VH z{VN65eLFgGPh{WUl>O^CUY78Xp<(|Rx6Yf?SNxtLM&w0^OPPvuKJbaa%0$0}#OR^5 z#ueB5&!GRv_Wpmil}wzhUafPZ^{GO0Iz?=u9}d6FJC|p^CcYo1gaVobmeXy1ilu{c*Ls#1-ZbzE>R{Bi-p*56m(wUc00yp;#Bz z6CG!;MnK1Brl_7cXBmr@!e`NJ9%5}i*gx`|$zw{>e(_XOp6GoxSGb?e5&xV|W47qp zkSTi9>qNi$3^A%cO)RKO6FcZX)tDx5Y%AT0>`m-9=IcT5E{Iq>_veDGUnR{%{>K6` z7r95tZ@Oo2(K-grhX#Xw(Ek_xjr1R*-$uWM=o|GSm;Pe=n=?? z_QDy17p|BzXw7Hl%)gQOH!^=o1M_cS{`Jhif%#vgyM^apwcP_hL_UP|@nf(^_a-J5 zM&SjzCtB9R#~hJLzq`XPuOT&t^}*Fym|LyGtfK}@KbD8U$~4R~e}iQQ!;oAYSoDj@ zYvZL{5qHTb_O=>C8p*hrO|nGVUpkT8k|8!07@pd;EFv?F#0QG|4RR> zhm$d*d>3YveUIs7-(h;`PE0G^j%g)ZG1dMp{B3b~*%pf_*3HiR->`p|{sx#`mGLWU>9;ZeHW&P7c>d`;{~-EZ%G;S+IZl5c`d_5~ zedZq@P`Wdl`R6kKT;{)*`LAdG^O^rp`nxOF-s~Pt0|2cX+J(SnA;z}~F`!8Z&tE;8 z+)d*zyPLw=-L!yPIG`cnZdW Date: Tue, 27 May 2025 18:10:51 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=EB=A1=9C=EB=94=A9=EB=B0=94=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sn/app/components/ui/LoadingBar/index.tsx | 20 +++++++++ apps/sn/app/components/ui/contentLayout.tsx | 5 ++- apps/sn/app/oper/floodPre/page.tsx | 45 +++++++++++-------- 3 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 apps/sn/app/components/ui/LoadingBar/index.tsx diff --git a/apps/sn/app/components/ui/LoadingBar/index.tsx b/apps/sn/app/components/ui/LoadingBar/index.tsx new file mode 100644 index 000000000..37991d1d2 --- /dev/null +++ b/apps/sn/app/components/ui/LoadingBar/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { LoadingWithAnimation } from '@common/components/ui/loading'; + +interface LoadingOverlayProps { + isLoading: boolean; +} + +const LoadingOverlay: React.FC = ({ isLoading }) => { + if (!isLoading) return null; + + return ( +
+
+ +
+
+ ); +}; + +export default LoadingOverlay; \ No newline at end of file diff --git a/apps/sn/app/components/ui/contentLayout.tsx b/apps/sn/app/components/ui/contentLayout.tsx index 738e26b16..75d61235f 100644 --- a/apps/sn/app/components/ui/contentLayout.tsx +++ b/apps/sn/app/components/ui/contentLayout.tsx @@ -1,14 +1,17 @@ import { ContentsDiv, MainDiv, Title } from '@common/business_components/ui' import React, { type ReactNode } from 'react' +import LoadingOverlay from './LoadingBar' type LayoutNode = { children : ReactNode title : string + isLoading?: boolean } -const ContentLayout = ({children, title} : LayoutNode) => { +const ContentLayout = ({children, title, isLoading} : LayoutNode) => { return ( <ContentsDiv> + <LoadingOverlay isLoading={isLoading ?? false}/> {children} </ContentsDiv> </MainDiv> diff --git a/apps/sn/app/oper/floodPre/page.tsx b/apps/sn/app/oper/floodPre/page.tsx index a260d530b..e8aacad26 100644 --- a/apps/sn/app/oper/floodPre/page.tsx +++ b/apps/sn/app/oper/floodPre/page.tsx @@ -1,6 +1,6 @@ 'use client' import { SearchDiv, SearchFormLeft, SearchFormRight, UiTable } from '@common/business_components/ui' -import { Button, DatePicker, Input, Label } from '@common/components/ui' +import { Button, DatePicker, Input, Label, LoadingWithAnimation } from '@common/components/ui' import React, { useEffect, useState } from 'react' import OperFileUploadForm from '../../components/ui/operFileUploadForm' import ListDiv from '@common/business_components/ui/list_div' @@ -10,10 +10,11 @@ import { tableHeadlist } from '..' import { handleDownload } from '@/components/lib/utils/fileDownload' import { formatDate } from '@/components/lib/utils/date' import { deleteData, postData } from '@/components/lib/api' +import LoadingOverlay from '@/components/ui/LoadingBar' const Page = () => { // 조회조건 - const [fromDate, setFromDate] = useState(()=>{const date = new Date(); date.setDate(date.getDate()-7); return date}) + const [fromDate, setFromDate] = useState(() => { const date = new Date(); date.setDate(date.getDate() - 7); return date }) const [toDate, setToDate] = useState(new Date()) const [manageYear, setManageYear] = useState('') const [mngQu, setMngQu] = useState('') @@ -26,19 +27,25 @@ const Page = () => { const [tableData, setTableData] = useState<any>([{}]) //테이블 데이터 const [curPage, setCurPage] = useState(1) //현재 페이지 const [totalData, setTotalData] = useState(0) //총 데이터 수 + const [isLoading, setIsLoading] = useState(true) //로딩 상태 const fetchData = async () => { - const {data, total} = await searchData('v1/sbmrgPrevnt', { - fromRegDt: formatDate(fromDate), - fromMngYr: manageYear, - toMngYr: mngQu, - toRegDt: formatDate(toDate), - atflNm: pjNm, - rgtrNm: usr, - page: curPage - 1, - size: '10' - }) - setTableData(data) - setTotalData(total) + setIsLoading(true) + try { + const { data, total } = await searchData('v1/sbmrgPrevnt', { + fromRegDt: formatDate(fromDate), + fromMngYr: manageYear, + toMngYr: mngQu, + toRegDt: formatDate(toDate), + atflNm: pjNm, + rgtrNm: usr, + page: curPage - 1, + size: '10' + }) + setTableData(data) + setTotalData(total) + } + catch (error) { console.error('Error fetching data:', error) } + finally {setIsLoading(false); } } useEffect(() => { setCurPage(1) @@ -72,12 +79,12 @@ const Page = () => { mngQu: quater, atflCd: cd, atflId: id, - sbmrgPrevntBizNm:fileName + sbmrgPrevntBizNm: fileName }) - if (data) {alert('파일이 등록되었습니다.'); fetchData() } + if (data) { alert('파일이 등록되었습니다.'); fetchData() } } return ( - <ContentLayout title='도시침수 예방사업'> + <ContentLayout title='도시침수 예방사업' isLoading={isLoading}> <SearchDiv> <SearchFormLeft> <div className='flex items-center gap-4'> @@ -124,7 +131,7 @@ const Page = () => { </div> </SearchFormLeft> <SearchFormRight> - <Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={async () => await fetchData() } >조회</Button> + <Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={async () => await fetchData()} >조회</Button> </SearchFormRight> </SearchDiv> <ListDiv className="mt-4"> @@ -135,7 +142,7 @@ const Page = () => { <Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm" onClick={isDeleteFile} >삭제</Button> </div> </div> - <UiTable headName='' tableData={tableData} headlist={tableHeadlist} pageSize={10} total={totalData} cellClick={(index) => { if (index != null) {const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn);} }} onPageChange={async (page:number)=>{setCurPage(page); await fetchData()}}></UiTable> + (<UiTable headName='' tableData={tableData} headlist={tableHeadlist} pageSize={10} total={totalData} cellClick={(index) => { if (index != null) { const fileName = tableData[index]?.sbmrgPrevntBizNm ?? ""; setFileNm(fileName); const id = tableData[index]?.atflId ?? ''; setAtflId(id); setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn); } }} onPageChange={async (page: number) => { setCurPage(page); await fetchData() }}></UiTable>) </ListDiv> <ListDiv className="mt-4"> <OperFileUploadForm title='도시침수 예방사업 사업추진현황 등록' onSubmit={async (file, year, quater, cd, id) => { await registFile(file, year, quater, cd, id) }} />