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) }} />