diff --git a/apps/sn/app/components/lib/utils/excelToJson.ts b/apps/sn/app/components/lib/utils/excelToJson.ts new file mode 100644 index 000000000..c4a3a226d --- /dev/null +++ b/apps/sn/app/components/lib/utils/excelToJson.ts @@ -0,0 +1,63 @@ +export const TEST_UUID= '2d4b151d-1828-41e0-91d9-4cd28ea1cc7e' +import { z } from "zod"; + +// 수용가-맨홀 매칭결과 (아직 안함) +export const MatchingResultZod = z.object({ + anls_sn: z.number(), + mhl_mng_no: z.string(), // 일련번호 0 포함인지? number? string? + rcptr_no: z.string(), +}); + +export type MatchingResultZodType = z.infer; + +export const excelToMatchingResultData = (excelData: any) => { + const MatchingResultData: MatchingResultZodType[] = excelData.map((item: any) => { + + return { + anls_sn: Number(item["NO"]), + mhl_mng_no: String(item["FTR_IDN"]), // 임시값이라 추후 수정 필요 + rcptr_no: String(item["수용가"]), + }; + }).filter((el: any) => el !== undefined); + return MatchingResultData; +}; + +// 시간패턴 +export const timePatternZod = z.object({ + hr_id: z.number(), + rt: z.number().nullish(), +}); + +export type timePatternZodType = z.infer; + +export const excelToTimePatternData = (excelData: any) => { + const timePatternData: timePatternZodType[] = excelData.map((item: any) => { + + return { + hr_id: Number(item["시간"]), + rt: Number(item["비율"]), + }; + }).filter((el: any) => el !== undefined); + return timePatternData; +}; + +// 유량자료 +export const flowRateZod = z.object({ + ppl_mng_no: z.string(), + mtrng_dt: z.number(), // type 뭘로 해야할지 Date? timeStamp임 + oilq: z.number().nullish(), +}); + +export type flowRateZodType = z.infer; + +export const excelToflowRateData = (excelData: any) => { + const flowRateData: flowRateZodType[] = excelData.map((item: any) => { + + return { + ppl_mng_no: String(item["관로번호"]), + mtrng_dt: new Date(item["시간"]).toISOString(), // type 뭘로 해야할지 Date? timeStamp임 + oilq: Number(item["유량(㎥/h)"]), + }; + }).filter((el: any) => el !== undefined); + return flowRateData; +}; \ No newline at end of file diff --git a/apps/sn/app/ii/BaseLayout.tsx b/apps/sn/app/ii/BaseLayout.tsx index 42697c00f..129063ba7 100644 --- a/apps/sn/app/ii/BaseLayout.tsx +++ b/apps/sn/app/ii/BaseLayout.tsx @@ -4,6 +4,8 @@ import { SearchDiv, SearchFormLeft, SelectBox, SearchFormRight, Form, UiTable } import ListDiv from '@common/business_components/ui/list_div' import { Button } from '@common/components/ui' import React, { type ReactNode } from 'react' +import { SelectBox2 } from '@common/business_components/ui/select/index-2' + type TitleName = { mainTitle: string firstCardTitle: string @@ -12,6 +14,7 @@ type TitleName = { type SelectBox = { labelNm?: Label searchChk?: boolean + title?: string // SearchDiv의 제목 (선택 사항) } type Label = { first: string @@ -41,15 +44,30 @@ type BaseLayout = { const BaseLayout = ({ children, titleName, form, onSubmitEvent, graphBtn = false, searchBox }: BaseLayout) => { return ( - - - { }} selectClass={undefined} /> - { }} selectClass='' /> - { }} selectClass='' /> - { }} selectClass='' /> - - {searchBox?.searchChk ? : null} - + + {/* searchBox.title이 있으면 h3 태그로 제목을 표시합니다. */} + {searchBox?.title && ( +
+

{searchBox.title}

+
+ {graphBtn ? : null} + {/* 그래프 있을 시 */} + {graphBtn ? : null} +
+
+ )} +
+
+ + { }} selectClass={undefined} /> + { }} selectClass='' /> + { }} selectClass='' /> + { }} selectClass='' /> + +
+ {searchBox?.searchChk ? : null} +
+

{titleName.firstCardTitle}

@@ -68,18 +86,20 @@ const BaseLayout = ({ children, titleName, form, onSubmitEvent, graphBtn = false - {children?.[1] != null ? -
-

{titleName?.secondCardTitle}

-
- {graphBtn ? : null} - {/* 그래프 있을 시 */} - {graphBtn ? : null} -
-
-
{children?.[1]}
-
: null} - + { + children?.[1] != null ? +
+

{titleName?.secondCardTitle}

+
+ {graphBtn ? : null} + {/* 그래프 있을 시 */} + {graphBtn ? : null} +
+
+
{children?.[1]}
+
: null + } + ) } diff --git a/apps/sn/app/ii/irsetting/page.tsx b/apps/sn/app/ii/irsetting/page.tsx index 34b1d2f00..17410e3cd 100644 --- a/apps/sn/app/ii/irsetting/page.tsx +++ b/apps/sn/app/ii/irsetting/page.tsx @@ -1,12 +1,15 @@ 'use client' -import React, { useState } from 'react' -import { FormField, SelectBox } from '@common/business_components/ui' +import React, { useRef, useState } from 'react' import { Button, DatePicker, Input } from '@common/components/ui' import { z } from 'zod' import { zodResolver } from '@hookform/resolvers/zod' import { useForm } from 'react-hook-form' import FormSection from '@/components/ui/formSection' import BaseLayout from '../BaseLayout' +import { filePicked, FileUpload } from '@common/business_components/ui' +import { excelToflowRateData, excelToMatchingResultData, excelToTimePatternData } from '../../components/lib/utils/excelToJson' +import { postData } from '@/components/lib/api' + const formSchema = z.object({ managenm: z.string(), region: z.string(), @@ -14,7 +17,7 @@ const formSchema = z.object({ inputdate: z.coerce.date(), rtkSource: z.string(), suyeongaPlace: z.string(), - pattern : z.string() + pattern: z.string() }) const region: { text: string, val: number }[] = [{ text: '양평', val: 1 }, { text: '강남', val: 2 }, { text: 'test', val: 3 }] const IrSetting = () => { @@ -30,35 +33,106 @@ const IrSetting = () => { pattern: "" } }) + const [file1, setFile1] = useState(null); + const [file2, setFile2] = useState(null); + const [file3, setFile3] = useState(null); + const [file4, setFile4] = useState(null); const [selectedDate, setSelectedDate] = useState(new Date()) + const fileInputRef1 = useRef(null) + const fileInputRef2 = useRef(null) + const fileInputRef3 = useRef(null) + const fileInputRef4 = useRef(null) + + // 버튼 클릭 핸들러 + const handleAnalysisClick = async () => { + const file1 = fileInputRef1.current?.files?.[0] + const file2 = fileInputRef2.current?.files?.[0] + const file3 = fileInputRef3.current?.files?.[0] + + if (!file1 || !file2 || !file3) { + alert('모든 파일을 선택해주세요.') + return + } + + let json2: any = null; + let json3: any = null; + + await filePicked(file2, 0).then((res) => { + if (res !== undefined) json2 = excelToMatchingResultData(res); + }); + await filePicked(file3, 0).then((res) => { + if (res !== undefined) json3 = excelToTimePatternData(res); + }); + + + console.log(file1) + console.log(json2) + console.log(json3) + } + + + // 버튼 클릭 핸들러 + const handleUploadClick = async () => { + const file4 = fileInputRef4.current?.files?.[0]; + + if (!file4) { + alert('파일을 선택해주세요.') + return + } + let json4: any = null; + await filePicked(file4, 0).then((res) => { + console.log(res); + if (res !== undefined) json4 = excelToflowRateData(res); + }); + console.log(json4); + + // json4가 존재하면 postData로 백엔드에 전송 + if (json4) { + try { + const response = await postData('your-backend-endpoint', json4); // 'your-backend-endpoint'를 실제 API 경로로 변경 + console.log('업로드 결과:', response); + alert('업로드가 완료되었습니다.'); + } catch (error) { + console.error('업로드 실패:', error); + alert('업로드에 실패했습니다.'); + } + } + } + return ( - { }} graphBtn={false}> -
-
- -
-
- -
-
- -
- - { if (date) setSelectedDate(date) }} mode={"single"} /> - - -
- -
-
-
- -
- + <> + { }} graphBtn={false} searchBox={{ title: '분석 대장지역 선택' }} > +
+
+ +
+
+ +
+
+ +
+ + { if (date) setSelectedDate(date) }} mode={"single"} /> + + + +
+
- -
-
+
+
+ +
+ +
+
+
+ +
+
+ + ) } diff --git a/apps/sn/app/ii/rdii/page.tsx b/apps/sn/app/ii/rdii/page.tsx index 7db1bfe56..94cb94f40 100644 --- a/apps/sn/app/ii/rdii/page.tsx +++ b/apps/sn/app/ii/rdii/page.tsx @@ -88,17 +88,17 @@ export default function RTKForm() { } const [selectedDate, setSelectedDate] = useState(new Date()) return ( - { }} graphBtn={false}> + { }} graphBtn={false} > {[
- -
+ +
○ 단위도 계수
@@ -132,23 +132,24 @@ export default function RTKForm() {
-
- -
-
- -
- - { if (date) setSelectedDate(date) }} mode={"single"} /> - - -
- -
+
+ +
+
+ +
+ + { if (date) setSelectedDate(date) }} mode={"single"} /> + + +
+ +
+ +
+
+
-
- -
]}
diff --git a/apps/sn/app/ii/result/page.tsx b/apps/sn/app/ii/result/page.tsx index a3a036518..6e1d1b067 100644 --- a/apps/sn/app/ii/result/page.tsx +++ b/apps/sn/app/ii/result/page.tsx @@ -57,7 +57,7 @@ const Result = () => { } }) return ( - { }} graphBtn={true}> + { }} graphBtn={true}> {[
○ 침입수 산정결과 현황