diff --git a/apps/sn/app/components/fileUploadForm.tsx b/apps/sn/app/components/fileUploadForm.tsx new file mode 100644 index 000000000..dd3575302 --- /dev/null +++ b/apps/sn/app/components/fileUploadForm.tsx @@ -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(null); + const [selectedYear, setSelectedYear] = useState(''); + + // 현재 년도부터 10년 전까지의 년도 옵션 생성 + const yearOptions = Array.from({ length: 10 }, (_, i) => { + const year = new Date().getFullYear() - i; + return { text: `${year}년`, val: year.toString() }; + }); + + return ( +
+
+

{title}

+
+
+
+
+ +
+ setSelectedYear(String(value))} + /> + +
+
+
+ ) +} + +export default FileUploadForm \ No newline at end of file diff --git a/apps/sn/app/oper/floodPre/page.tsx b/apps/sn/app/oper/floodPre/page.tsx new file mode 100644 index 000000000..79ef43f76 --- /dev/null +++ b/apps/sn/app/oper/floodPre/page.tsx @@ -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 ( + + + <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 \ No newline at end of file diff --git a/apps/sn/app/oper/oldPp/excelDown/excelDown.tsx b/apps/sn/app/oper/oldPp/excelDown/excelDown.tsx new file mode 100644 index 000000000..d1bd5cc70 --- /dev/null +++ b/apps/sn/app/oper/oldPp/excelDown/excelDown.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +const ExcelDown = () => { + return ( + <div>excelDown</div> + ) +} + +export default ExcelDown \ No newline at end of file diff --git a/apps/sn/app/oper/oldPp/page.tsx b/apps/sn/app/oper/oldPp/page.tsx new file mode 100644 index 000000000..cc0e00aeb --- /dev/null +++ b/apps/sn/app/oper/oldPp/page.tsx @@ -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 \ No newline at end of file diff --git a/apps/sn/app/page.tsx b/apps/sn/app/page.tsx index dd54ce3f9..e6811fb42 100644 --- a/apps/sn/app/page.tsx +++ b/apps/sn/app/page.tsx @@ -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> ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 82f59a6cd..baa723e45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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