sn:노후 하수관로 정비 세로스크롤
This commit is contained in:
@@ -276,6 +276,7 @@ const Page = () => {
|
||||
max-h-[100dvh]
|
||||
overflow-hidden
|
||||
z-[101]
|
||||
flex flex-col gap-[10px]
|
||||
`}
|
||||
body={<TableModal fileNm={fileNm} atflId={atflId} />}
|
||||
useDirectRender={true}
|
||||
|
||||
@@ -177,303 +177,303 @@ const TableModal: React.FC<TableModalProps> = ({ fileNm, atflId }) => {
|
||||
rowNumber: index + 1
|
||||
};
|
||||
});
|
||||
setTableData3(filteredData3);
|
||||
setTableData3(filteredData3);
|
||||
|
||||
// 3.정비사업
|
||||
const allEntries4 = Object.entries(header4);
|
||||
const filteredHeader4 = allEntries4.filter((e): e is [string, any] => Boolean(e))
|
||||
.map(([key, value]) => ({
|
||||
id: key,
|
||||
title: String(value).replace(/\r\n/g, '\n')
|
||||
}));
|
||||
// 3.정비사업
|
||||
const allEntries4 = Object.entries(header4);
|
||||
const filteredHeader4 = allEntries4.filter((e): e is [string, any] => Boolean(e))
|
||||
.map(([key, value]) => ({
|
||||
id: key,
|
||||
title: String(value).replace(/\r\n/g, '\n')
|
||||
}));
|
||||
|
||||
filteredHeader4.splice(0, 0, {
|
||||
id: "rowNumber",
|
||||
title: '일련번호'
|
||||
});
|
||||
setTableHeader4(filteredHeader4);
|
||||
filteredHeader4.splice(0, 0, {
|
||||
id: "rowNumber",
|
||||
title: '일련번호'
|
||||
});
|
||||
setTableHeader4(filteredHeader4);
|
||||
|
||||
const data4 = Array.isArray(jsonDataBySheet[' 3.정비사업'])
|
||||
? jsonDataBySheet[' 3.정비사업'].slice(2)
|
||||
: [];
|
||||
const filteredData4 = filterEmptyRows(data4).map((item: any, index: number) => ({
|
||||
...item,
|
||||
rowNumber: index + 1,
|
||||
__EMPTY_2: item?.__EMPTY_2 || '-',
|
||||
__EMPTY_11: item?.__EMPTY_11 || '-',
|
||||
}));
|
||||
setTableData4(filteredData4);
|
||||
|
||||
// 4.정비사업요약
|
||||
const allEntries5 = Object.entries(header5);
|
||||
const excludeKeys5 = [
|
||||
": \"정비사업\"sheet에서 사업코드 ctrl+c, Ctrl+v 한 다음 중복된 데이터 제거실시",
|
||||
"__EMPTY",
|
||||
"__EMPTY_8",
|
||||
"__EMPTY_15"
|
||||
];
|
||||
const filteredHeader5 = allEntries5
|
||||
.filter(([key]) => !excludeKeys5.includes(key))
|
||||
.filter((e): e is [string, any] => Boolean(e))
|
||||
.map(([key, value]) => ({
|
||||
id: key,
|
||||
title: String(value).replace(/\r\n/g, '\n'),
|
||||
}));
|
||||
filteredHeader5.splice(0, 0, {
|
||||
id: "rowNumber",
|
||||
title: '일련번호'
|
||||
});
|
||||
setTableHeader5(filteredHeader5);
|
||||
|
||||
const data5 = Array.isArray(jsonDataBySheet['4.정비사업요약'])
|
||||
? jsonDataBySheet['4.정비사업요약'].slice(3)
|
||||
: [];
|
||||
const filteredData5 =
|
||||
filterEmptyRows(data5).map((item: any, index: number) => ({
|
||||
const data4 = Array.isArray(jsonDataBySheet[' 3.정비사업'])
|
||||
? jsonDataBySheet[' 3.정비사업'].slice(2)
|
||||
: [];
|
||||
const filteredData4 = filterEmptyRows(data4).map((item: any, index: number) => ({
|
||||
...item,
|
||||
rowNumber: index + 1,
|
||||
__EMPTY_2: item?.__EMPTY_2 || '-',
|
||||
__EMPTY_11: item?.__EMPTY_11 || '-',
|
||||
}));
|
||||
setTableData5(filteredData5);
|
||||
setTableData4(filteredData4);
|
||||
|
||||
// 4.정비사업최종 (헤더는 import)
|
||||
const data6 = Array.isArray(jsonDataBySheet['4.정비사업최종'])
|
||||
? jsonDataBySheet['4.정비사업최종'].slice(6)
|
||||
: [];
|
||||
const filteredData6 =
|
||||
filterEmptyRows(data6).map((item: any, index: number) => ({
|
||||
...item,
|
||||
rowNumber: index + 1,
|
||||
}));
|
||||
setTableData6(filteredData6);
|
||||
} catch (error) {
|
||||
console.error('파일 처리 중 오류 발생:', error);
|
||||
alert('파일 처리 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
// 4.정비사업요약
|
||||
const allEntries5 = Object.entries(header5);
|
||||
const excludeKeys5 = [
|
||||
": \"정비사업\"sheet에서 사업코드 ctrl+c, Ctrl+v 한 다음 중복된 데이터 제거실시",
|
||||
"__EMPTY",
|
||||
"__EMPTY_8",
|
||||
"__EMPTY_15"
|
||||
];
|
||||
const filteredHeader5 = allEntries5
|
||||
.filter(([key]) => !excludeKeys5.includes(key))
|
||||
.filter((e): e is [string, any] => Boolean(e))
|
||||
.map(([key, value]) => ({
|
||||
id: key,
|
||||
title: String(value).replace(/\r\n/g, '\n'),
|
||||
}));
|
||||
filteredHeader5.splice(0, 0, {
|
||||
id: "rowNumber",
|
||||
title: '일련번호'
|
||||
});
|
||||
setTableHeader5(filteredHeader5);
|
||||
|
||||
const data5 = Array.isArray(jsonDataBySheet['4.정비사업요약'])
|
||||
? jsonDataBySheet['4.정비사업요약'].slice(3)
|
||||
: [];
|
||||
const filteredData5 =
|
||||
filterEmptyRows(data5).map((item: any, index: number) => ({
|
||||
...item,
|
||||
rowNumber: index + 1,
|
||||
}));
|
||||
setTableData5(filteredData5);
|
||||
|
||||
// 4.정비사업최종 (헤더는 import)
|
||||
const data6 = Array.isArray(jsonDataBySheet['4.정비사업최종'])
|
||||
? jsonDataBySheet['4.정비사업최종'].slice(6)
|
||||
: [];
|
||||
const filteredData6 =
|
||||
filterEmptyRows(data6).map((item: any, index: number) => ({
|
||||
...item,
|
||||
rowNumber: index + 1,
|
||||
}));
|
||||
setTableData6(filteredData6);
|
||||
} 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;
|
||||
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 &&
|
||||
String(value).trim() !== '' &&
|
||||
String(value).trim() !== '-' &&
|
||||
String(value).trim() !== '';
|
||||
});
|
||||
})
|
||||
.map((row) => {
|
||||
const processedRow = { ...row };
|
||||
const keys = Object.keys(processedRow);
|
||||
return value !== undefined &&
|
||||
value !== null &&
|
||||
String(value).trim() !== '' &&
|
||||
String(value).trim() !== '-' &&
|
||||
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] = '-';
|
||||
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;
|
||||
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) {
|
||||
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);
|
||||
});
|
||||
};
|
||||
|
||||
// 특정 시트만 선택적으로 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) {
|
||||
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)}
|
||||
/>
|
||||
{/* row data 탭 */}
|
||||
{activeTab === '1' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[150%]">
|
||||
<UiTable
|
||||
headName={'row data'}
|
||||
tableData={tableData1}
|
||||
headlist={tableHeader1}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
return (
|
||||
<>
|
||||
{/* 탭 영역 */}
|
||||
<UITab
|
||||
defaultValue={activeTab}
|
||||
tabList={TABS.map((tab) => ({
|
||||
value: tab.val,
|
||||
label: tab.text
|
||||
}))}
|
||||
onValueChange={(value: string) => setActiveTab(value)}
|
||||
/>
|
||||
{/* row data 탭 */}
|
||||
{activeTab === '1' && (
|
||||
<div className="h-[79vh] rounded-lg border flex flex-col">
|
||||
<div className="flex-1 min-w-[50vw] max-w-[100vw] overflow-auto">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-max">
|
||||
<UiTable
|
||||
headName={'row data'}
|
||||
tableData={tableData1}
|
||||
headlist={tableHeader1}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* 1.정밀조사 탭 */}
|
||||
{activeTab === '2' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[150%]">
|
||||
<UiTable
|
||||
headName={'1.정밀조사'}
|
||||
tableData={tableData2}
|
||||
headlist={tableHeader2}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
)}
|
||||
{/* 1.정밀조사 탭 */}
|
||||
{activeTab === '2' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[150%]">
|
||||
<UiTable
|
||||
headName={'1.정밀조사'}
|
||||
tableData={tableData2}
|
||||
headlist={tableHeader2}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* 2.정밀조사_정비사업연계 탭 */}
|
||||
{activeTab === '3' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[550%]">
|
||||
<UiTable
|
||||
headName={'2.정밀조사_정비사업연계'}
|
||||
tableData={tableData3}
|
||||
headlist={oldPpTable2HeadList}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={oldPpTable2NodeList} />
|
||||
</UiTable>
|
||||
)}
|
||||
{/* 2.정밀조사_정비사업연계 탭 */}
|
||||
{activeTab === '3' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[550%]">
|
||||
<UiTable
|
||||
headName={'2.정밀조사_정비사업연계'}
|
||||
tableData={tableData3}
|
||||
headlist={oldPpTable2HeadList}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={oldPpTable2NodeList} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* 3.정비사업 탭 */}
|
||||
{activeTab === '4' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[160%]">
|
||||
<UiTable
|
||||
headName={'3.정비사업'}
|
||||
tableData={tableData4}
|
||||
headlist={tableHeader4}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
)}
|
||||
{/* 3.정비사업 탭 */}
|
||||
{activeTab === '4' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[160%]">
|
||||
<UiTable
|
||||
headName={'3.정비사업'}
|
||||
tableData={tableData4}
|
||||
headlist={tableHeader4}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* 4.정비사업요약 탭 */}
|
||||
{activeTab === '5' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[130%]">
|
||||
<UiTable
|
||||
headName={'4.정비사업요약'}
|
||||
tableData={tableData5}
|
||||
headlist={tableHeader5}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
)}
|
||||
{/* 4.정비사업요약 탭 */}
|
||||
{activeTab === '5' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[130%]">
|
||||
<UiTable
|
||||
headName={'4.정비사업요약'}
|
||||
tableData={tableData5}
|
||||
headlist={tableHeader5}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* 4.정비사업최종 탭 */}
|
||||
{activeTab === '6' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[200%]">
|
||||
<UiTable
|
||||
headName={'4.정비사업최종'}
|
||||
tableData={tableData6}
|
||||
headlist={oldPpTable6HeadList}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={oldPpTable6NodeList} />
|
||||
</UiTable>
|
||||
)}
|
||||
{/* 4.정비사업최종 탭 */}
|
||||
{activeTab === '6' && (
|
||||
<div className="h-[79vh] w-full overflow-auto rounded-lg border">
|
||||
<div className="flex-1 px-2 pb-2">
|
||||
<LoadingOverlay isLoading={isLoading} />
|
||||
<div className="min-w-[200%]">
|
||||
<UiTable
|
||||
headName={'4.정비사업최종'}
|
||||
tableData={tableData6}
|
||||
headlist={oldPpTable6HeadList}
|
||||
pageSize={10}
|
||||
total={0}
|
||||
className={"overflow-x-auto overflow-y-auto"}
|
||||
cellClick={undefined}
|
||||
onPageChange={() => { }}
|
||||
>
|
||||
<HeadMakeColSpan upHeadList={oldPpTable6NodeList} />
|
||||
</UiTable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
export default TableModal;
|
||||
Reference in New Issue
Block a user