Files
frontend/apps/sn/app/(with-base-layout)/oper/floodPre/tableModal.tsx
T

248 lines
8.4 KiB
TypeScript

'use client'
import { useState, useEffect } from 'react'
import LoadingOverlay from '@/components/ui/LoadingBar'
import { UITab, UiTable } from '@common/business_components/ui'
import * as XLSX from 'xlsx';
const TABS = [
{ val: "management", text: "관리SHEET" },
{ val: "Inspection results", text: "운영관리현황 점검결과" },
];
interface TableModalProps {
fileNm: string;
atflId: string;
}
const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
const [activeTab, setActiveTab] = useState(TABS[0]?.val ?? "management");
const [managementTableHeader, setManagementTableHeader] = useState<{ id: string; title: string }[]>([]) //테이블 헤더
const [managementTableData, setManagementTableData] = useState<any>([{}]) //테이블 데이터
const [resultTableHeader, setResultTableHeader] = useState<{ id: string; title: string }[]>([]) //테이블 헤더
const [resultTableData, setResultTableData] = useState<any>([{}]) //테이블 데이터
const [isLoading, setIsLoading] = useState(false) //로딩 상태
useEffect(() => {
isChckFile();
}, []);
// 파일 다운로드
const isChckFile = async () => {
setIsLoading(true);
try {
if (fileNm === '' || fileNm === undefined) {
alert('파일을 선택해주세요')
setIsLoading(false);
return false
}
const response = await fetch(`/attach-service/api/v1/download/${atflId}`);
if (!response.ok) {
throw new Error('파일을 가져오는 중 오류가 발생했습니다.');
}
const blob = await response.blob();
const file = new File([blob], fileNm, {
type: blob.type || 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
const targetSheets = ['관리SHEET', '운영관리현황 점검결과'];
const jsonDataBySheet = await filePickedSelectedSheets(file, 0, targetSheets);
// 관리 SHEET
const managementHeader = jsonDataBySheet['관리SHEET']?.[7] || [];
// 1번째~47번째, 74번째~80번째 데이터만 필터링
const filteredManagementHeader = Object.entries(managementHeader)
.filter(([key, value]) => {
const match = key.match(/^__EMPTY_(\d+)$/);
if (match) {
const index = parseInt(match[1] ?? '', 10);
return (index > 0 && index < 47) || (index > 73);
}
return false;
})
.map(([key, value]) => ({
id: key,
title: String(value).replace(/\r\n/g, '\n')
}));
setManagementTableHeader(filteredManagementHeader);
console.log('managementTableHeader', filteredManagementHeader);
const managementData = Array.isArray(jsonDataBySheet['관리SHEET'])
? jsonDataBySheet['관리SHEET'].slice(8)
: [];
// console.log('변환 후:', excelToManagementData(managementData));
const filteredManagementData = filterEmptyRows(managementData);
setManagementTableData(filteredManagementData);
console.log('managementTableData', filteredManagementData);
// 운영관리현황 점검결과
const resultHeader = jsonDataBySheet['운영관리현황 점검결과']?.[2] || [];
const dynamicInspectionHeader = Object.entries(resultHeader)
.map(([key, value]) => ({
id: key,
title: String(value).replace(/\r\n/g, '\n')
}));
dynamicInspectionHeader.splice(1, 0, {
id: "__EMPTY_2",
title: ''
});
setResultTableHeader(dynamicInspectionHeader);
console.log('resultTableHeader', dynamicInspectionHeader);
const resultData = Array.isArray(jsonDataBySheet['운영관리현황 점검결과'])
? jsonDataBySheet['운영관리현황 점검결과'].slice(3)
: [];
const filteredResultData = filterEmptyRows(resultData);
setResultTableData(filteredResultData);
console.log('resultTableData', filteredResultData);
} catch (error) {
console.error('파일 처리 중 오류 발생:', error);
alert('파일 처리 중 오류가 발생했습니다.');
} finally {
setIsLoading(false);
}
}
function filterEmptyRows(data: any[]) {
return data
.filter(row => {
return Object.entries(row).some(([key, value]) => {
const match = key.match(/^__EMPTY_(\d+)$/);
if (!match || parseInt(match[1] ?? '', 10) < 2) return false;
return value !== undefined &&
value !== null &&
value !== '' &&
value !== '-' &&
String(value).trim() !== '';
});
})
.map((row) => {
const processedRow = { ...row };
const keys = Object.keys(processedRow);
keys.forEach((key, keyIndex) => {
// 마지막 속성(비고)이 아닌 경우에만 빈 값을 '-'으로 변경
if (keyIndex !== keys.length - 1) {
const value = processedRow[key];
if (value === undefined ||
value === null ||
value === '' ||
String(value).trim() === '') {
processedRow[key] = '-';
}
}
});
return processedRow;
});
};
// 특정 시트만 선택적으로 JSON으로 변환하는 함수
function filePickedSelectedSheets(file: File, headerNum: number = 0, sheetNames: string[]): Promise<Record<string, any[]>> {
const reader = new FileReader();
return new Promise((resolve, reject) => {
reader.onload = function (e) {
const data = e.target?.result;
if (!data) {
console.error("Failed to read file: e.target.result is null");
reject(new Error("Failed to read file"));
return;
}
// Excel 파일 읽기
const wb = XLSX.read(data, { type: 'binary', cellDates: true });
const result: Record<string, any[]> = {};
// 지정된 시트 이름만 찾아서 처리
sheetNames.forEach(targetSheetName => {
// 대소문자 구분 없이 시트 이름 찾기
const sheetName = wb.SheetNames.find(name =>
name.toLowerCase() === targetSheetName.toLowerCase()
);
if (sheetName) {
const sheet = wb.Sheets[sheetName];
if (sheet) {
console.log(`Found sheet: "${sheetName}"`);
const jsonData = XLSX.utils.sheet_to_json(sheet, { range: headerNum, raw: false });
result[targetSheetName] = jsonData;
}
} else {
console.warn(`Sheet "${targetSheetName}" not found in workbook`);
result[targetSheetName] = [];
}
});
resolve(result);
};
reader.onerror = function () {
console.error("Error reading file");
reject(new Error("Error reading file"));
};
// 파일 읽기 시작
reader.readAsBinaryString(file);
});
};
return (
<>
{/* 탭 영역 */}
<UITab
defaultValue={activeTab}
tabList={TABS.map((tab) => ({
value: tab.val,
label: tab.text
}))}
onValueChange={(value: string) => setActiveTab(value)}
/>
{/* 관리SHEET 탭 */}
{activeTab === 'management' && (
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<div className="w-[1000%]">
<UiTable
headName={'관리SHEET'}
tableData={managementTableData}
headlist={managementTableHeader}
pageSize={10}
total={0}
cellClick={undefined}
onPageChange={() => { }}
/>
</div>
</div>
</div>
)}
{/* 운영관리현황 점검결과 탭 */}
{activeTab === 'Inspection results' && (
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={'운영관리현황 점검결과'}
tableData={resultTableData}
headlist={resultTableHeader}
pageSize={10}
total={0}
className={"overflow-x-auto overflow-y-auto"}
cellClick={undefined}
onPageChange={() => { }}
/>
</div>
</div>
)}
</>
)
};
export default TableModal;