From 85e836210080cf459b1fcac2fa9ce10782395d8e Mon Sep 17 00:00:00 2001 From: swcho Date: Tue, 10 Jun 2025 11:06:03 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20-=20I/I=20=EB=B6=84=EC=84=9D=20LoadingB?= =?UTF-8?q?ar=20=EC=A0=81=EC=9A=A9=20-=20rdii=20=EB=B6=84=EC=84=9D=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=9A=A9=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=EA=B0=92=20=EC=9E=85=EB=A0=A5=20(=EC=B6=94?= =?UTF-8?q?=ED=9B=84=20=EC=82=AD=EC=A0=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/app/ii/BaseLayout.tsx | 4 +++- apps/sn/app/ii/irsetting/page.tsx | 11 +++++++-- apps/sn/app/ii/rdii/page.tsx | 35 ++++++++++++++++------------- apps/sn/app/ii/rdii_result/page.tsx | 13 ++++++++--- apps/sn/app/ii/result/page.tsx | 15 ++++++++++--- 5 files changed, 54 insertions(+), 24 deletions(-) diff --git a/apps/sn/app/ii/BaseLayout.tsx b/apps/sn/app/ii/BaseLayout.tsx index 18d9f9bf0..b08fdcbe4 100644 --- a/apps/sn/app/ii/BaseLayout.tsx +++ b/apps/sn/app/ii/BaseLayout.tsx @@ -51,6 +51,7 @@ type BaseLayout = { onSwageProcessingZoneChange?: (value: string | number) => void; aplcnYm?: Date setAplcnYm?: (aplcnYm: Date | undefined) => void; + isLoading?: boolean; // Excel 다운로드 관련 props 추가 onExcelDownload?: () => void; onDeleteFile?: () => void; @@ -86,6 +87,7 @@ const BaseLayout = ({ onSwageProcessingZoneChange, aplcnYm, setAplcnYm, + isLoading, // Excel 다운로드 관련 props 추가 onExcelDownload, onDeleteFile, @@ -196,7 +198,7 @@ const BaseLayout = ({ return (
- + {/* searchBox.title이 있으면 h3 태그로 제목을 표시합니다. */} {selectBox?.title && ( diff --git a/apps/sn/app/ii/irsetting/page.tsx b/apps/sn/app/ii/irsetting/page.tsx index 8cb36c2bf..162cb9e3f 100644 --- a/apps/sn/app/ii/irsetting/page.tsx +++ b/apps/sn/app/ii/irsetting/page.tsx @@ -67,6 +67,7 @@ const IrSetting = () => { const [select4, setSelect4] = useState('0'); // 하수처리장코드 const [select5, setSelect5] = useState('0'); // 하수처리구역코드 const [formResetKey, setFormResetKey] = useState(0); // FileUploadForm 리셋을 위한 key 상태 + const [isLoadingResult, setIsLoadingResult] = useState(false); // 로딩 상태 // 폼 초기화 함수 const resetAllForms = () => { @@ -117,6 +118,7 @@ const IrSetting = () => { const registFile = async (analysisData: any) => { + setIsLoadingResult(true); // 로딩 상태 시작 console.log("Submitting combined analysis data to backend:", analysisData); // 추후 API 엔드포인트에 맞게 URL 수정 필요 const data = await postData('v1/inftwtAnls', analysisData); @@ -125,10 +127,12 @@ const IrSetting = () => { alert("분석 데이터가 성공적으로 제출되었습니다."); resetAllForms(); // 성공 시 폼 초기화 함수 호출 } else alert("분석 데이터 제출 중 오류가 발생했습니다."); + setIsLoadingResult(false); // 로딩 상태 시작 }; // 침입수 분석 실행 버튼 클릭 핸들러 const handleAnalysisClick = async () => { + setIsLoadingResult(true); // 로딩 상태 시작 console.log(uploadedFilesData); const file1 = uploadedFilesData[0]; // 오수관망도 const file2 = uploadedFilesData[1]; // 수용가-맨홀 매칭결과 @@ -224,8 +228,9 @@ const IrSetting = () => { // 수정된 registFile 함수를 호출하여 combinedAnalysisData를 전송합니다. await registFile(combinedAnalysisData); - + setIsLoadingResult(false); } catch (error) { + setIsLoadingResult(false); console.error("파일 파싱 중 오류 발생:", error); alert("파일 처리 중 오류가 발생했습니다."); return; @@ -249,7 +254,9 @@ const IrSetting = () => { selectedSwageTreatmentPlant={select4} onSwageTreatmentPlantChange={setSelect4} selectedSwageProcessingZone={select5} - onSwageProcessingZoneChange={setSelect5}> + onSwageProcessingZoneChange={setSelect5} + isLoading={isLoadingResult} + >
; -// 기본 폼 값 정의 +// 기본 폼 값 정의 (테스트 편의를 위해 초기값 설정, 추후 삭제 필요) const defaultFormValues: FormSchemaType = { enoCd: "", ctpvCd: "", sggCd: "", swageTmplntCd: "", swtrmtZoneCd: "", - rtkSource: "", - rdiiArea: "", // 문자열로 기본값 설정 + rtkSource: "출처", + rdiiArea: "123", // 문자열로 기본값 설정 unitFactors: [ - { response: "Short-Term", R: "", T: "", K: "" }, // 문자열로 기본값 설정 - { response: "Medium-Term", R: "", T: "", K: "" }, - { response: "Long-Term", R: "", T: "", K: "" }, + { response: "Short-Term", R: "0.040", T: "0.5", K: "1" }, // 문자열로 기본값 설정 + { response: "Medium-Term", R: "0.005", T: "1", K: "2" }, + { response: "Long-Term", R: "0.005", T: "2", K: "3" }, ], initialDepths: [ - { response: "Short-Term", Dmax: "", Drec: "", Do: "" }, // 문자열로 기본값 설정 - { response: "Medium-Term", Dmax: "", Drec: "", Do: "" }, - { response: "Long-Term", Dmax: "", Drec: "", Do: "" }, + { response: "Short-Term", Dmax: "0", Drec: "0", Do: "0" }, // 문자열로 기본값 설정 + { response: "Medium-Term", Dmax: "0", Drec: "0", Do: "0" }, + { response: "Long-Term", Dmax: "0", Drec: "0", Do: "0" }, ], // osumap: undefined, // matchingResultFile: undefined, aplcnYm: "", - rate: "", // 문자열로 기본값 설정 + rate: "0.8", // 문자열로 기본값 설정 // rainFile: undefined, - analysisInfo: "", + analysisInfo: "test 분석정보", date: new Date(), }; @@ -92,6 +92,7 @@ interface ApiSelectOption { export default function RTKForm() { const [formResetKey, setFormResetKey] = useState(0); // FileUploadForm 리셋을 위한 key 상태 + const [isLoadingResult, setIsLoadingResult] = useState(false); // 로딩 상태 // FileUploadForm에서 전달받은 파일 정보를 저장할 상태 배열 // 각 인덱스는 FileUploadForm의 fileIdx와 매칭됨 @@ -107,6 +108,7 @@ export default function RTKForm() { const [select4, setSelect4] = useState('0'); // 하수처리장 (swageTmplntCd) const [select5, setSelect5] = useState('0'); // 하수처리구역 (swtrmtZoneCd) + // form 인스턴스 생성 const form = useForm({ resolver: zodResolver(formSchema), @@ -160,6 +162,7 @@ export default function RTKForm() { // 침입수 분석 실행 버튼 클릭 핸들러 const handleAnalysisClick = async () => { + setIsLoadingResult(true); // 로딩 상태 시작 const formData = form.getValues(); console.log(uploadedFilesData); const file1 = uploadedFilesData[0]; // 오수관망도 @@ -256,7 +259,7 @@ export default function RTKForm() { longTermRcvryRt: parseFloat(formData.initialDepths[2]?.Drec !== undefined ? formData.initialDepths[2]?.Drec : "0") || null, // 장기간회복비율 longTermBgngDpth: parseFloat(formData.initialDepths[2]?.Do !== undefined ? formData.initialDepths[2]?.Do : "0") || null, // 장기간시작깊이 - dtrwSwtcRt: parseFloat(formData.rate !== undefined ? formData.rate : "0") || null, // 오수전환율 + drtwSwtcRt: parseFloat(formData.rate !== undefined ? formData.rate : "0") || null, // 오수전환율 anlsInfo: formData.analysisInfo, // 분석정보 tbSnRcptrMhlMpng: matchingResultData, // 수용가-맨홀 매칭결과 @@ -267,8 +270,9 @@ export default function RTKForm() { // 수정된 registFile 함수를 호출하여 combinedAnalysisData를 전송합니다. await registFile(combinedAnalysisData); - + setIsLoadingResult(false); } catch (error) { + setIsLoadingResult(false); console.error("파일 파싱 중 오류 발생:", error); alert("파일 처리 중 오류가 발생했습니다."); return; @@ -329,6 +333,7 @@ export default function RTKForm() { onSwageTreatmentPlantChange={setSelect4} selectedSwageProcessingZone={select5} onSwageProcessingZoneChange={setSelect5} + isLoading={isLoadingResult} > {[
@@ -414,7 +419,7 @@ export default function RTKForm() { }} // className을 직접 사용하거나, DatePicker 내부에서 selectClass를 처리하도록 수정 필요 // 여기서는 DatePicker의 selectClass prop을 사용하고, date-picker.css의 스타일을 적용 - selectClass="ml-5 date-picker-trigger" + selectClass="ml-5 date-picker-trigger" /> diff --git a/apps/sn/app/ii/rdii_result/page.tsx b/apps/sn/app/ii/rdii_result/page.tsx index ada7f4c56..dba3a1232 100644 --- a/apps/sn/app/ii/rdii_result/page.tsx +++ b/apps/sn/app/ii/rdii_result/page.tsx @@ -1,5 +1,5 @@ 'use client' -import { getData, deleteData } from '@/components/lib/api' +import { deleteData, getData } from '@/components/lib/api' import { UiTable, downloadExcel } from '@common/business_components/ui' import { zodResolver } from '@hookform/resolvers/zod' import { useState } from 'react' @@ -101,13 +101,13 @@ const Result = () => { setTotalData(tableData.length); console.log("response:", data); console.log("response data:", data.content || []); + setIsLoadingResult(false); } catch (error) { + setIsLoadingResult(false); console.error("Error fetching analysis result data:", error); alert("분석결과 조회 중 오류가 발생했습니다."); setTableData([]); setTotalData(0); - } finally { - setIsLoadingResult(false); } }; @@ -122,8 +122,10 @@ const Result = () => { // Excel 다운로드 핸들러 추가 const handleExcelDownload = async () => { + setIsLoadingResult(true); console.log("Selected row data for download:", selectedRowData); if (!selectedRowData || selectedRowData.rainInfwtAnlsSn === undefined) { + setIsLoadingResult(false); alert('다운로드할 데이터를 선택해주세요.'); return; } @@ -143,7 +145,9 @@ const Result = () => { sheetNameArray: ["RDII 분석결과"], headerRange: "A1:D1" // 테이블 컬럼 수에 맞춰 조정 }); + setIsLoadingResult(false); } catch (error) { + setIsLoadingResult(false); console.error("Excel 다운로드 중 오류 발생:", error); alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요."); } @@ -151,6 +155,7 @@ const Result = () => { // 파일 삭제 핸들러 추가 const handleFileDelete = async () => { + setIsLoadingResult(true); console.log("Selected row data for deletion:", selectedRowData); if (!selectedRowData || selectedRowData.rainInfwtAnlsSn === undefined) { alert('삭제할 파일을 선택해주세요.'); @@ -188,6 +193,7 @@ const Result = () => { console.error("분석결과 파일 삭제 중 오류 발생:", error); alert("분석결과 파일 삭제 중 오류가 발생했습니다. 다시 시도해주세요."); } + setIsLoadingResult(false); }; return ( @@ -216,6 +222,7 @@ const Result = () => { form.setValue("aplcnYm", new Date(val)) } }} + isLoading={isLoadingResult} // Excel 다운로드 핸들러 추가 onExcelDownload={handleExcelDownload} onDeleteFile={handleFileDelete} diff --git a/apps/sn/app/ii/result/page.tsx b/apps/sn/app/ii/result/page.tsx index 552504e0b..99f0f902a 100644 --- a/apps/sn/app/ii/result/page.tsx +++ b/apps/sn/app/ii/result/page.tsx @@ -1,5 +1,5 @@ 'use client' -import { getData, deleteData } from '@/components/lib/api' +import { deleteData, getData } from '@/components/lib/api' import { UiTable, downloadExcel } from '@common/business_components/ui' import { zodResolver } from '@hookform/resolvers/zod' import { useState } from 'react' @@ -100,13 +100,13 @@ const Result = () => { setTotalData(tableData.length); console.log("response:", data); console.log("response data:", data.content || []); + setIsLoadingResult(false); } catch (error) { + setIsLoadingResult(false); console.error("Error fetching analysis result data:", error); alert("분석결과 조회 중 오류가 발생했습니다."); setTableData([]); setTotalData(0); - } finally { - setIsLoadingResult(false); } }; @@ -121,8 +121,10 @@ const Result = () => { // Excel 다운로드 핸들러 추가 const handleExcelDownload = async () => { + setIsLoadingResult(true); console.log("Selected row data for download:", selectedRowData); if (!selectedRowData || selectedRowData.inftwtAnlsSn === undefined) { + setIsLoadingResult(false); alert('다운로드할 데이터를 선택해주세요.'); return; } @@ -142,7 +144,9 @@ const Result = () => { sheetNameArray: ["침입수 분석결과"], headerRange: "A1:D1" // 테이블 컬럼 수에 맞춰 조정 }); + setIsLoadingResult(false); } catch (error) { + setIsLoadingResult(false); console.error("Excel 다운로드 중 오류 발생:", error); alert("Excel 다운로드 중 오류가 발생했습니다. 다시 시도해주세요."); } @@ -150,8 +154,10 @@ const Result = () => { // 파일 삭제 핸들러 추가 const handleFileDelete = async () => { + setIsLoadingResult(true); console.log("Selected row data for deletion:", selectedRowData); if (!selectedRowData || selectedRowData.inftwtAnlsSn === undefined) { + setIsLoadingResult(false); alert('삭제할 파일을 선택해주세요.'); return; } @@ -181,9 +187,11 @@ const Result = () => { // 선택된 행 초기화 setSelectedRowData(null); setSelectedRowIndex(undefined); + setIsLoadingResult(false); alert('삭제가 완료되었습니다.'); } catch (error) { + setIsLoadingResult(false); console.error("분석결과 파일 삭제 중 오류 발생:", error); alert("분석결과 파일 삭제 중 오류가 발생했습니다. 다시 시도해주세요."); } @@ -215,6 +223,7 @@ const Result = () => { form.setValue("aplcnYm", new Date(val)) } }} + isLoading={isLoadingResult} // 로딩 상태 전달 // Excel 다운로드 핸들러 추가 onExcelDownload={handleExcelDownload} onDeleteFile={handleFileDelete}