사업이력 - 노후하수관로 / 도시침수 예방사업 페이지 구현(이벤트 처리 및 로직필요)

This commit is contained in:
JIeunhuh
2025-04-16 17:35:59 +09:00
parent 969a0eab29
commit f9cd3c579d
6 changed files with 312 additions and 5 deletions
+58
View File
@@ -0,0 +1,58 @@
"use client"
import { FileUpload, SelectBox } from '@common/business_components/ui';
import { Button } from '@common/components/ui';
import React, { useState } from 'react'
const FileUploadForm = ({title}:{title:string}) => {
const [files, setFiles] = useState<File[] | null>(null);
const [selectedYear, setSelectedYear] = useState<string>('');
// 현재 년도부터 10년 전까지의 년도 옵션 생성
const yearOptions = Array.from({ length: 10 }, (_, i) => {
const year = new Date().getFullYear() - i;
return { text: `${year}년`, val: year.toString() };
});
return (
<div>
<div className='card-header'>
<h3 className="text-2xl font-medium">{title}</h3>
</div>
<div className="card p-6">
<div className="flex items-center space-x-4">
<div className="w-[400px]">
<FileUpload
files={files}
setFiles={setFiles}
fileTypes=".xlsx,.xls"
/>
</div>
<SelectBox
className="w-50"
selectClass="w-50 rounded-lg bg-white"
label="관리년도"
selectArray={yearOptions}
onSelectValue={(value: string | number) => setSelectedYear(String(value))}
/>
<Button
className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700"
size="sm"
onClick={() => {
if (!files?.[0] || !selectedYear) {
alert('파일과 등록년도를 선택해주세요.');
return;
}
// TODO: 파일 업로드 처리
console.log('Upload file:', files[0], 'Year:', selectedYear);
}}
>
등록
</Button>
</div>
</div>
</div>
)
}
export default FileUploadForm
+80
View File
@@ -0,0 +1,80 @@
'use client'
import { ContentsDiv, MainDiv, SearchDiv, SearchFormLeft, SearchFormRight, SearchInput, Title, UiTable } from '@common/business_components/ui'
import { Button, DatePicker, Input } from '@common/components/ui'
import React, { useRef, useState } from 'react'
import FileUploadForm from '../../components/fileUploadForm'
import ListDiv from '@common/business_components/ui/list_div'
const tableHeadlist = [
{ id: 'no', title: 'NO' },
{ id: 'fileNm', title: '파일명' },
{ id: 'manageYear', title: '기준년도' },
{ id: 'registDt', title: '등록 일자' },
{ id: 'registUsr', title: '등록자' }
]
const tableData = [
{ 'no': '1', 'fileNm': '파일명', 'manageYear': '2023', 'registDt': '2025-04-16', 'registUsr': 'me' },
{ 'no': '2', 'fileNm': '파일명', 'manageYear': '2024', 'registDt': '2025-04-16', 'registUsr': 'me2' },
{ 'no': '3', 'fileNm': '파일명', 'manageYear': '2025', 'registDt': '2025-04-16', 'registUsr': 'me3' }
]
const Page = () => {
const [selectedDate, setSelectedDate] = useState(new Date())
const [company, setCompany] = useState('')
const [pjNm, setpjNm] = useState('')
return (
<MainDiv>
<Title title='도시침수 예방사업' />
<ContentsDiv>
<SearchDiv>
<SearchFormLeft>
<div className='flex items-center space-x-4'>
<div className='flex items-center gap-2'>
<span className='whitespace-nowrap'>수행기간</span>
<DatePicker mode={'single'}
selected={selectedDate}
onSelect={(date: Date | undefined) => { if (date) setSelectedDate(date) }} />
<span>~</span>
<DatePicker mode={'single'}
selected={selectedDate}
onSelect={(date: Date | undefined) => { if (date) setSelectedDate(date) }} />
</div>
</div>
</SearchFormLeft>
<SearchFormRight>
<div className='flex mx-4'>
<div className='flex items-center mx-2'>
<span className='whitespace-nowrap'>수행사</span>
<Input
className='w-[70px] ml-2'
value={company}
onChange={(e) => setCompany(e.target.value)}
/>
</div>
<div className='flex items-center'>
<span className='whitespace-nowrap'>사업명</span>
<Input
className='w-[70px] ml-2'
value={pjNm}
onChange={(e) => setpjNm(e.target.value)}
/>
</div>
</div>
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" >조회</Button>
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" >파일 다운로드</Button>
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" >삭제</Button>
</SearchFormRight>
</SearchDiv>
<ListDiv className="mt-4">
<UiTable headName='사업정보 등록 현황' tableData={tableData} headlist={tableHeadlist} pageSize={20} total={20} children={undefined} cellClick={() => { }} onPageChange={function (page: number): void {
throw new Error('Function not implemented.')
}}></UiTable>
</ListDiv>
<ListDiv className="mt-4">
<FileUploadForm title='도시침수 예방사업 사업추진현황 등록' />
</ListDiv>
</ContentsDiv>
</MainDiv>
)
}
export default Page
@@ -0,0 +1,9 @@
import React from 'react'
const ExcelDown = () => {
return (
<div>excelDown</div>
)
}
export default ExcelDown
+59
View File
@@ -0,0 +1,59 @@
'use client'
import { ContentsDiv, MainDiv, SearchDiv, SearchFormLeft, SearchFormRight, SelectBox, Title, UiTable } from '@common/business_components/ui'
import { Button, DatePicker } from '@common/components/ui'
import React, { useState } from 'react'
import FileUploadForm from '../../components/fileUploadForm'
import ListDiv from '@common/business_components/ui/list_div'
// TODO: 임시 id
const tableHeadlist = [
{ id: 'no', title: 'NO' },
{ id: 'fileNm', title: '파일명' },
{ id: 'manageYear', title: '관리년도' },
{ id: 'registDt', title: '등록 일자' },
{ id: 'registUsr', title: '등록자' }
]
const tableData = [
{ 'no': '1', 'fileNm': '파일명', 'manageYear': '2023', 'registDt': '2025-04-16', 'registUsr': 'me' },
{ 'no': '2', 'fileNm': '파일명', 'manageYear': '2024', 'registDt': '2025-04-16', 'registUsr': 'me2' },
{ 'no': '3', 'fileNm': '파일명', 'manageYear': '2025', 'registDt': '2025-04-16', 'registUsr': 'me3' }
]
const Page = () => {
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
return (
<MainDiv>
<Title title='노후 하수관로 정비사업'/>
<ContentsDiv>
<SearchDiv>
<SearchFormLeft>
<div className='flex items-center space-x-2'>
<span className='w-20 whitespace-nowrap'>등록기간</span>
<DatePicker mode={'single'}
selected={selectedDate}
onSelect={(date: Date | undefined) => { if (date) setSelectedDate(date) }} />
<span>~</span>
<DatePicker mode={'single'}
selected={selectedDate}
onSelect={(date: Date | undefined) => { if (date) setSelectedDate(date) }} />
</div>
</SearchFormLeft>
<SearchFormRight>
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 mr-2" size="sm" >조회</Button>
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 mr-2" size="sm" >파일 다운로드</Button>
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" >삭제</Button>
</SearchFormRight>
</SearchDiv>
<ListDiv className="mt-4">
<UiTable headName='사업정보 등록 현황' tableData={tableData} headlist={tableHeadlist} pageSize={20} total={20} children={undefined} cellClick={() => { }} onPageChange={function (page: number): void {
throw new Error('Function not implemented.')
}}></UiTable>
</ListDiv>
<ListDiv className="mt-4">
<FileUploadForm title='노후 하수관로 정비사업 주진현황 등록'/>
</ListDiv>
</ContentsDiv>
</MainDiv>
)
}
export default Page
+4 -4
View File
@@ -4,10 +4,10 @@ import { Button } from "@common/components/ui";
export default function Home() {
return (
<div className="grid grid-cols-12 gap-2">
<div className="col-span-2">
<Link href={"/oper/pplines"}><Button>관로시설</Button></Link>
</div>
<div className="flex flex-row gap-4 p-4">
<Link href={"/oper/pplines"}><Button>관로시설</Button></Link>
<Link href={"/oper/floodPre"}><Button>도시침수 예방사업</Button></Link>
<Link href={"/oper/oldPp"}><Button>노후 하수관로 정비사업</Button></Link>
</div>
);
}
+102 -1
View File
@@ -140,6 +140,106 @@ importers:
specifier: ^5
version: 5.6.3
apps/sn:
dependencies:
'@common/assets':
specifier: workspace:*
version: link:../../packages/common/assets
'@common/business_components':
specifier: workspace:*
version: link:../../packages/common/business_components
'@common/components':
specifier: workspace:*
version: link:../../packages/common/components
'@frontend-opensource/use-react-hooks':
specifier: ^1.1.4
version: 1.1.4
'@hookform/resolvers':
specifier: ^4.1.3
version: 4.1.3(react-hook-form@7.54.2)
'@radix-ui/react-label':
specifier: ^2.1.2
version: 2.1.2(@types/react-dom@18.3.5)(@types/react@18.3.18)(react-dom@18.3.1)(react@18.3.1)
'@radix-ui/react-slot':
specifier: ^1.1.2
version: 1.1.2(@types/react@18.3.18)(react@18.3.1)
'@tanstack/react-query':
specifier: ^5.67.1
version: 5.67.1(react@18.3.1)
'@tanstack/react-table':
specifier: ^8.21.2
version: 8.21.2(react-dom@18.3.1)(react@18.3.1)
axios:
specifier: ^1.8.1
version: 1.8.1
chart.js:
specifier: ^4.4.8
version: 4.4.8
dayjs:
specifier: ^1.11.13
version: 1.11.13
js-cookie:
specifier: ^3.0.5
version: 3.0.5
next:
specifier: 15.1.7
version: 15.1.7(react-dom@18.3.1)(react@18.3.1)
react-chartjs-2:
specifier: ^5.3.0
version: 5.3.0(chart.js@4.4.8)(react@18.3.1)
react-hook-form:
specifier: ^7.54.2
version: 7.54.2(react@18.3.1)
tailwindcss-animate:
specifier: ^1.0.7
version: 1.0.7(tailwindcss@3.4.17)
zod:
specifier: ^3.24.2
version: 3.24.2
zustand:
specifier: ^5.0.3
version: 5.0.3(@types/react@18.3.18)(react@18.3.1)
devDependencies:
'@eslint/eslintrc':
specifier: ^3
version: 3.3.0
'@faker-js/faker':
specifier: ^9.5.0
version: 9.5.0
'@types/js-cookie':
specifier: ^3.0.6
version: 3.0.6
'@types/node':
specifier: ^22.13.1
version: 22.13.9
'@types/webpack':
specifier: ^5.28.5
version: 5.28.5
eslint:
specifier: ^9
version: 9.21.0
eslint-config-next:
specifier: 15.1.7
version: 15.1.7(eslint@9.21.0)(typescript@5.6.3)
postcss:
specifier: ^8
version: 8.5.3
prettier:
specifier: ^3.4.2
version: 3.5.2
prettier-plugin-tailwindcss:
specifier: ^0.6.11
version: 0.6.11(prettier@3.5.2)
steiger:
specifier: ^0.5.5
version: 0.5.5(typescript@5.6.3)
tailwindcss:
specifier: ^3.4.1
version: 3.4.17
typescript:
specifier: ^5
version: 5.6.3
apps/wr:
dependencies:
'@common/business_components':
@@ -1320,6 +1420,7 @@ packages:
/@faker-js/faker@9.5.0:
resolution: {integrity: sha512-3qbjLv+fzuuCg3umxc9/7YjrEXNaKwHgmig949nfyaTx8eL4FAsvFbu+1JcFUj1YAXofhaDn6JdEUBTYuk0Ssw==}
engines: {node: '>=18.0.0', npm: '>=9.0.0'}
deprecated: Please update to a newer version
dev: true
/@feature-sliced/filesystem@2.4.0:
@@ -6083,7 +6184,7 @@ packages:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/node': 22.13.5
'@types/node': 22.13.9
merge-stream: 2.0.0
supports-color: 8.1.1
dev: true