258 lines
9.2 KiB
TypeScript
258 lines
9.2 KiB
TypeScript
'use client'
|
|
import { deleteData, postData, useCookieAuth } from '@/components/lib/api'
|
|
import { searchData } from '@/components/lib/common/apiHelpers'
|
|
import { formatDate, handleDownload } from '@/components/lib/utils'
|
|
import LoadingOverlay from '@/components/ui/LoadingBar'
|
|
import { SearchDiv, SearchFormLeft, SearchFormRight, UiTable, UiModal } from '@common/business_components/ui'
|
|
import ListDiv from '@common/business_components/ui/list_div'
|
|
import { Button, DatePicker, Input, Label } from '@common/components/ui'
|
|
import { useEffect, useState } from 'react'
|
|
import { tableHeadlist } from '..'
|
|
import OperFileUploadForm from '../../../components/ui/operFileUploadForm'
|
|
import { tokenManager } from '@/entities/auth/lib/token-manager';
|
|
import { AUTH_USER_ID } from "@/shared/config";
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { ENDPOINT } from "@common/components/config";
|
|
import { getUserInfo } from "@common/components/api";
|
|
|
|
|
|
const Page = () => {
|
|
const AUTH = useCookieAuth();
|
|
|
|
// 조회조건
|
|
const [fromDate, setFromDate] = useState(() => { const date = new Date(); date.setDate(date.getDate() - 7); return date })
|
|
const [toDate, setToDate] = useState(new Date())
|
|
const [usr, setUsr] = useState('')
|
|
const [pjNm, setpjNm] = useState('')
|
|
// 파일업로드 관련 상태
|
|
const [fileNm, setFileNm] = useState('') //파일명
|
|
const [atflId, setAtflId] = useState('') //파일 ID
|
|
const [sbmrgPrevntBizSn, setSbmrgPrevntBizSn] = useState('') //파일 일련번호
|
|
const [tableData, setTableData] = useState<any>([{}]) //테이블 데이터
|
|
const [curPage, setCurPage] = useState(1) //현재 페이지
|
|
const [totalData, setTotalData] = useState(0) //총 데이터 수
|
|
const [isLoading, setIsLoading] = useState(true) //로딩 상태
|
|
const [isModalOpen, setIsModalOpen] = useState(false) // 모달 상태
|
|
const [resetSelection, setResetSelection] = useState<boolean>(false); // 선택 초기화 상태
|
|
const [isResetPage, setIsResetPage] = useState<boolean>(false);
|
|
|
|
const { data: userInfo } = useQuery({
|
|
queryKey: [ENDPOINT.USER_SERVICE.USERS],
|
|
queryFn: () => getUserInfo(),
|
|
enabled: true,
|
|
});
|
|
|
|
useEffect(() => {
|
|
setCurPage(1)
|
|
fetchData()
|
|
}, [])
|
|
|
|
// 페이지 변경 시마다 데이터 fetch
|
|
useEffect(() => {
|
|
setIsResetPage(false);
|
|
fetchData();
|
|
}, [curPage]);
|
|
|
|
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
|
|
const handleSearch: () => Promise<void> = async () => {
|
|
setCurPage(1); // 페이지를 1로 초기화
|
|
setIsResetPage(true); // 페이지를 초기화
|
|
await fetchData();
|
|
};
|
|
|
|
// 조회
|
|
const fetchData = async () => {
|
|
setIsLoading(true)
|
|
setResetSelection(true);
|
|
// searchCmmnCd('SITEKNDCD')
|
|
try {
|
|
const { data, total } = await searchData('v1/sbmrgPrevnt', {
|
|
fromRegDt: formatDate(fromDate),
|
|
toRegDt: formatDate(toDate),
|
|
sbmrgPrevntBizNm: pjNm,
|
|
auth: AUTH,
|
|
page: curPage - 1,
|
|
size: '10'
|
|
})
|
|
// 일련번호를 추가한 데이터로 변환 (전체 데이터 기준으로 일련번호 계산)
|
|
const dataWithRowNumber = (data || []).map((item: any, index: number) => ({
|
|
...item,
|
|
rowNumber: (curPage - 1) * 10 + index + 1, // 페이지 기준 일련번호 계산
|
|
}));
|
|
setTableData(dataWithRowNumber)
|
|
setTotalData(total)
|
|
}
|
|
catch (error) { console.error('Error fetching data:', error) }
|
|
finally {
|
|
setFileNm('');
|
|
setAtflId('');
|
|
setSbmrgPrevntBizSn('');
|
|
setIsLoading(false);
|
|
setResetSelection(false);
|
|
}
|
|
}
|
|
|
|
// 파일 다운로드
|
|
const isChckFile = () => {
|
|
if (fileNm === '' || fileNm === undefined) {
|
|
alert('파일을 선택해주세요')
|
|
return false
|
|
}
|
|
handleDownload(`/attach-service/api/v1/download/${atflId}`, fileNm)
|
|
}
|
|
|
|
// 선택 파일 삭제
|
|
const isDeleteFile = async () => {
|
|
if (sbmrgPrevntBizSn === '' || sbmrgPrevntBizSn === undefined) {
|
|
alert('삭제할 파일을 선택해주세요')
|
|
return false
|
|
}
|
|
const data = await deleteData(`/attach-service/api/v1/atfl/attachments/${atflId}`)
|
|
if (data) {
|
|
const delData = await deleteData(`v1/sbmrgPrevnt/${sbmrgPrevntBizSn}`)
|
|
if (delData.status === 200) {
|
|
alert('삭제되었습니다.')
|
|
fetchData()
|
|
}
|
|
}
|
|
else {
|
|
alert('삭제에 실패했습니다.')
|
|
}
|
|
}
|
|
|
|
// 현황 등록
|
|
const registFile = async (fileName: string, year: string, quater: string, cd: string, id: string) => {
|
|
const json = {
|
|
atflNm: fileName,
|
|
mngYr: year,
|
|
mngQu: quater,
|
|
atflCd: cd,
|
|
atflId: id,
|
|
sbmrgPrevntBizNm: fileName,
|
|
rgtr: tokenManager.getToken(AUTH_USER_ID) || null
|
|
}
|
|
console.log('request DTO', json);
|
|
const data = await postData('v1/sbmrgPrevnt', json)
|
|
if (data) {
|
|
alert('파일이 등록되었습니다.');
|
|
setIsModalOpen(false);
|
|
handleSearch();
|
|
}
|
|
}
|
|
|
|
// 등록 버튼 클릭 핸들러
|
|
const handleRegisterClick = () => {
|
|
setIsModalOpen(true);
|
|
}
|
|
|
|
|
|
return (
|
|
<>
|
|
<LoadingOverlay isLoading={isLoading ?? false} />
|
|
<SearchDiv>
|
|
<SearchFormLeft>
|
|
<div className='flex items-center gap-5'>
|
|
<div className='flex items-center gap-2'>
|
|
<Label className="w-20 text-xl text-gray-600">등록기간</Label>
|
|
<DatePicker mode={'single'}
|
|
selected={fromDate}
|
|
onSelect={(date: Date | undefined) => { if (date) setFromDate(date) }}
|
|
modifiers={{
|
|
disabled: { after: new Date() }
|
|
}}
|
|
/>
|
|
<span>~</span>
|
|
<DatePicker mode={'single'}
|
|
selected={toDate}
|
|
onSelect={(date: Date | undefined) => { if (date) setToDate(date) }}
|
|
modifiers={{
|
|
disabled: { after: new Date() }
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className='flex items-center'>
|
|
<Label className="w-20 text-xl text-gray-600">등록자</Label>
|
|
<Input
|
|
className='w-[100px]'
|
|
value={usr}
|
|
onChange={(e) => setUsr(e.target.value)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault(); // Enter 키 기본 동작 방지
|
|
handleSearch();
|
|
}
|
|
}}
|
|
/>
|
|
</div>
|
|
<div className='flex items-center'>
|
|
<Label className="w-20 text-xl text-gray-600">파일명</Label>
|
|
<Input
|
|
className='w-[100px]'
|
|
value={pjNm}
|
|
onChange={(e) => setpjNm(e.target.value)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault(); // Enter 키 기본 동작 방지
|
|
handleSearch();
|
|
}
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</SearchFormLeft>
|
|
<SearchFormRight>
|
|
<div className='flex items-center gap-5'>
|
|
<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 handleSearch()} >조회</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={handleRegisterClick} >등록</Button>
|
|
</div>
|
|
</SearchFormRight>
|
|
</SearchDiv>
|
|
<ListDiv className="mt-4">
|
|
<div className="card-header flex items-center justify-between">
|
|
<h3 className="text-2xl font-medium">사업정보 등록현황</h3>
|
|
<div>
|
|
<Button className="px-4 py-2 !mr-[1.2rem] bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" onClick={isChckFile} >파일 다운로드</Button>
|
|
<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 ?? "";
|
|
const id = tableData[index]?.atflId ?? '';
|
|
setFileNm(fileName);
|
|
setAtflId(id);
|
|
setSbmrgPrevntBizSn(tableData[index]?.sbmrgPrevntBizSn);
|
|
}
|
|
}}
|
|
onPageChange={setCurPage}
|
|
resetSelection={resetSelection}
|
|
resetPageNo={isResetPage}
|
|
/>
|
|
</ListDiv>
|
|
{/* 파일 업로드 모달 */}
|
|
<UiModal
|
|
open={isModalOpen}
|
|
onOpenChange={setIsModalOpen}
|
|
bodyClass="w-auto max-w-[90vw] min-w-[600px] h-auto"
|
|
noHeaderYn="N"
|
|
noFooterYn="Y"
|
|
body={
|
|
<OperFileUploadForm
|
|
title='도시침수 예방사업 추진현황 등록'
|
|
onSubmit={async (file, year, quater, cd, id) => {
|
|
await registFile(file, year, quater, cd, id)
|
|
}}
|
|
/>
|
|
}
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default Page |