update menu report

This commit is contained in:
Athif
2025-12-18 15:03:39 +07:00
parent dc78add71d
commit 6b75f6f4b9

View File

@@ -16,9 +16,10 @@ const ListReport = memo(function ListReport(props) {
const dateNow = dayjs(); const dateNow = dayjs();
const dateNowFormated = dateNow.format('YYYY-MM-DD'); const dateNowFormated = dateNow.format('YYYY-MM-DD');
const [isLoadingModal, setIsLoadingModal] = useState(false); // Modal loading const [isLoadingModal, setIsLoadingModal] = useState(false);
const [isLoadingTable, setIsLoadingTable] = useState(false); // Table loading const [isLoadingTable, setIsLoadingTable] = useState(false);
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
const [columns, setColumns] = useState([]);
const [pivotData, setPivotData] = useState([]); const [pivotData, setPivotData] = useState([]);
const [valueReportData, setValueReportData] = useState([]); const [valueReportData, setValueReportData] = useState([]);
const [pagination, setPagination] = useState({ const [pagination, setPagination] = useState({
@@ -33,46 +34,6 @@ const ListReport = memo(function ListReport(props) {
const [endDate, setEndDate] = useState(dateNow); const [endDate, setEndDate] = useState(dateNow);
const [periode, setPeriode] = useState(30); const [periode, setPeriode] = useState(30);
const columns = [
{
title: 'No',
key: 'no',
width: 60,
align: 'center',
fixed: 'left',
render: (_, __, index) => {
return (pagination.current - 1) * pagination.pageSize + index + 1;
},
},
{
title: 'Datetime',
dataIndex: 'datetime',
key: 'datetime',
width: 180,
sorter: (a, b) => new Date(a.datetime) - new Date(b.datetime),
},
{
title: 'Tag Name',
dataIndex: 'tagName',
key: 'tagName',
width: 200,
},
{
title: 'Value',
dataIndex: 'value',
key: 'value',
width: 120,
align: 'left', // Aligned kanan (seperti angka pada umumnya)
render: (value) => {
if (value === null || value === undefined) {
return '-';
}
return Number(value).toFixed(2); // Format 2 desimal
},
}
];
// Fungsi helper untuk generate semua waktu dalam sehari berdasarkan periode
const generateFullDayTimes = (dateString, intervalMinutes) => { const generateFullDayTimes = (dateString, intervalMinutes) => {
const times = []; const times = [];
const startOfDay = dayjs(dateString).startOf('day'); const startOfDay = dayjs(dateString).startOf('day');
@@ -84,7 +45,6 @@ const ListReport = memo(function ListReport(props) {
times.push(currentTime.format('YYYY-MM-DD HH:mm:ss')); times.push(currentTime.format('YYYY-MM-DD HH:mm:ss'));
currentTime = currentTime.add(intervalMinutes, 'minute'); currentTime = currentTime.add(intervalMinutes, 'minute');
// Jika waktu berikutnya melebihi akhir hari, break
if (currentTime.isAfter(endOfDay)) { if (currentTime.isAfter(endOfDay)) {
break; break;
} }
@@ -99,9 +59,9 @@ const ListReport = memo(function ListReport(props) {
} }
if (showModal) { if (showModal) {
setIsLoadingModal(true); // Modal untuk fetch pertama setIsLoadingModal(true);
} else { } else {
setIsLoadingTable(true); // Spin untuk pagination setIsLoadingTable(true);
} }
try { try {
const formattedDateStart = startDate.format('YYYY-MM-DD'); const formattedDateStart = startDate.format('YYYY-MM-DD');
@@ -121,8 +81,6 @@ const ListReport = memo(function ListReport(props) {
if (pivotResponse && pivotResponse.data) { if (pivotResponse && pivotResponse.data) {
console.log('API Pivot Response:', pivotResponse); console.log('API Pivot Response:', pivotResponse);
console.log('First row pivot data:', pivotResponse.data[0]);
setPivotData(pivotResponse.data); setPivotData(pivotResponse.data);
if (valueReportResponse && valueReportResponse.data) { if (valueReportResponse && valueReportResponse.data) {
@@ -130,42 +88,90 @@ const ListReport = memo(function ListReport(props) {
setValueReportData(valueReportResponse.data); setValueReportData(valueReportResponse.data);
} }
const unpivotedData = []; // Buat struktur pivot: waktu sebagai baris, tag sebagai kolom
const timeMap = new Map();
const tagSet = new Set();
// Kumpulkan semua waktu unik dan tag unik
pivotResponse.data.forEach((row) => { pivotResponse.data.forEach((row) => {
const tagName = row.id; const tagName = row.id;
const dataPoints = row.data || []; tagSet.add(tagName);
const dataPoints = row.data || [];
dataPoints.forEach((item) => { dataPoints.forEach((item) => {
if (item && typeof item === 'object' && 'x' in item && 'y' in item) { if (item && typeof item === 'object' && 'x' in item && 'y' in item) {
unpivotedData.push({ const datetime = item.x;
datetime: item.x, if (!timeMap.has(datetime)) {
tagName: tagName, timeMap.set(datetime, {});
value: item.y, }
}); timeMap.get(datetime)[tagName] = item.y;
} }
}); });
}); });
console.log('Unpivoted data sample:', unpivotedData.slice(0, 10)); // Konversi ke array dan sort berdasarkan waktu
console.log('Total unpivoted rows:', unpivotedData.length); const sortedTimes = Array.from(timeMap.keys()).sort();
const sortedTags = Array.from(tagSet).sort();
unpivotedData.sort((a, b) => { // Buat data untuk table
if (a.tagName !== b.tagName) { const pivotTableData = sortedTimes.map((datetime, index) => {
return a.tagName.localeCompare(b.tagName); const rowData = {
} key: index,
return new Date(a.datetime) - new Date(b.datetime); datetime: datetime,
};
sortedTags.forEach((tagName) => {
rowData[tagName] = timeMap.get(datetime)[tagName];
});
return rowData;
}); });
const transformedData = unpivotedData.map((item, index) => ({ console.log('Pivot table data sample:', pivotTableData.slice(0, 5));
key: index, console.log('Total pivot rows:', pivotTableData.length);
...item,
}));
const total = transformedData.length; // Buat kolom dinamis
const dynamicColumns = [
{
title: 'No',
key: 'no',
width: 60,
align: 'center',
fixed: 'left',
render: (_, __, index) => {
return (page - 1) * pageSize + index + 1;
},
},
{
title: 'Datetime',
dataIndex: 'datetime',
key: 'datetime',
width: 180,
fixed: 'left',
sorter: (a, b) => new Date(a.datetime) - new Date(b.datetime),
},
...sortedTags.map((tagName) => ({
title: tagName,
dataIndex: tagName,
key: tagName,
width: 120,
align: 'center',
render: (value) => {
if (value === null || value === undefined) {
return '-';
}
return Number(value).toFixed(2);
},
})),
];
setColumns(dynamicColumns);
// Pagination
const total = pivotTableData.length;
const startIndex = (page - 1) * pageSize; const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize; const endIndex = startIndex + pageSize;
const paginatedData = transformedData.slice(startIndex, endIndex); const paginatedData = pivotTableData.slice(startIndex, endIndex);
setTableData(paginatedData); setTableData(paginatedData);
setPagination({ setPagination({
@@ -199,6 +205,7 @@ const ListReport = memo(function ListReport(props) {
setEndDate(dateNow); setEndDate(dateNow);
setPeriode(30); setPeriode(30);
setTableData([]); setTableData([]);
setColumns([]);
setPivotData([]); setPivotData([]);
setValueReportData([]); setValueReportData([]);
setPagination({ setPagination({
@@ -256,47 +263,43 @@ const ListReport = memo(function ListReport(props) {
const selectedSection = plantSubSectionList.find(item => item.plant_sub_section_id === plantSubSection); const selectedSection = plantSubSectionList.find(item => item.plant_sub_section_id === plantSubSection);
const sectionName = selectedSection ? selectedSection.plant_sub_section_name : 'Unknown'; const sectionName = selectedSection ? selectedSection.plant_sub_section_name : 'Unknown';
// Generate data lengkap untuk setiap tanggal dengan semua interval waktu // Buat struktur pivot yang sama seperti di tabel
const dataByDate = {}; const timeMap = new Map();
const tagSet = new Set();
// Pertama, kumpulkan semua tanggal yang ada pivotData.forEach((row) => {
const allDates = new Set(); const tagName = row.id;
pivotData.forEach(series => { tagSet.add(tagName);
series.data.forEach(item => {
const date = dayjs(item.x).format('YYYY-MM-DD');
allDates.add(date);
});
});
// Untuk setiap tanggal, generate semua waktu dan isi dengan data yang ada const dataPoints = row.data || [];
Array.from(allDates).forEach(date => { dataPoints.forEach((item) => {
const fullDayTimes = generateFullDayTimes(date, periode); if (item && typeof item === 'object' && 'x' in item && 'y' in item) {
dataByDate[date] = {}; const datetime = item.x;
if (!timeMap.has(datetime)) {
// Initialize dengan semua waktu timeMap.set(datetime, {});
pivotData.forEach(series => {
dataByDate[date][series.id] = fullDayTimes.map(time => ({
x: time,
y: null // Default null, akan diisi jika ada data
}));
});
// Isi dengan data aktual yang ada
pivotData.forEach(series => {
series.data.forEach(item => {
const itemDate = dayjs(item.x).format('YYYY-MM-DD');
if (itemDate === date) {
const itemTime = dayjs(item.x).format('YYYY-MM-DD HH:mm:ss');
const timeIndex = fullDayTimes.indexOf(itemTime);
if (timeIndex !== -1 && dataByDate[date][series.id][timeIndex]) {
dataByDate[date][series.id][timeIndex].y = item.y;
}
} }
}); timeMap.get(datetime)[tagName] = item.y;
}
}); });
}); });
const sortedDates = Object.keys(dataByDate).sort(); const sortedTimes = Array.from(timeMap.keys()).sort();
const sortedTags = Array.from(tagSet).sort();
const pivotTableData = sortedTimes.map((datetime) => {
const rowData = {
datetime: datetime,
};
sortedTags.forEach((tagName) => {
rowData[tagName] = timeMap.get(datetime)[tagName];
});
return rowData;
});
console.log('PDF Pivot data:', pivotTableData.slice(0, 5));
console.log('Total rows for PDF:', pivotTableData.length);
const loadImage = (src) => { const loadImage = (src) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -322,21 +325,17 @@ const ListReport = memo(function ListReport(props) {
const marginRight = 10; const marginRight = 10;
const tableWidth = pageWidth - marginLeft - marginRight; const tableWidth = pageWidth - marginLeft - marginRight;
// Konstanta untuk mengatur lebar kolom const DATETIME_COLUMN_WIDTH = 25;
const IO_TAG_COLUMN_WIDTH = 17; // Lebar kolom IO Soft Tag di TABEL (mm) const HEADER_LEFT_COLUMN_WIDTH = 40;
const HEADER_LEFT_COLUMN_WIDTH = 40; // Lebar kolom KIRI di HEADER (untuk logo1) (mm) const MAX_TAG_COLUMNS_PER_PAGE = 15;
const MAX_TIME_COLUMNS_PER_PAGE = 24;
let globalPageNumber = 1; const drawFullHeader = (doc) => {
// FUNGSI HEADER LENGKAP - Untuk Halaman Pertama
const drawFullHeader = (doc, date) => {
doc.setLineWidth(0.5); doc.setLineWidth(0.5);
doc.line(marginLeft, 10, marginLeft + tableWidth, 10); doc.line(marginLeft, 10, marginLeft + tableWidth, 10);
doc.line(marginLeft, 10, marginLeft, 50); doc.line(marginLeft, 10, marginLeft, 50);
doc.line(marginLeft + tableWidth, 10, marginLeft + tableWidth, 50); doc.line(marginLeft + tableWidth, 10, marginLeft + tableWidth, 50);
const col1Width = HEADER_LEFT_COLUMN_WIDTH; // Gunakan konstanta HEADER const col1Width = HEADER_LEFT_COLUMN_WIDTH;
const col3Width = tableWidth * 0.20; const col3Width = tableWidth * 0.20;
const col2Width = tableWidth - col1Width - col3Width; const col2Width = tableWidth - col1Width - col3Width;
@@ -391,194 +390,199 @@ const ListReport = memo(function ListReport(props) {
doc.addImage(logo2, 'PNG', logoX, logoY, logoWidth, logoHeight); doc.addImage(logo2, 'PNG', logoX, logoY, logoWidth, logoHeight);
} }
doc.line(marginLeft + tableWidth - col3Width, 30, marginLeft + tableWidth - col3Width, 50);
const formattedDate = dayjs(date).format('DD-MM-YYYY');
doc.setFontSize(9); doc.setFontSize(9);
doc.setFont('helvetica', 'bold');
doc.text('Laporan Periode :', marginLeft + tableWidth - col3Width / 2, 35, { align: 'center' });
doc.setFont('helvetica', 'normal');
doc.text(formattedDate, marginLeft + tableWidth - col3Width / 2, 40, { align: 'center' });
// Hitung waktu akhir berdasarkan periode
const minutesInDay = 24 * 60;
const lastTimeMinutes = Math.floor((minutesInDay - periode) / periode) * periode;
const lastHour = Math.floor(lastTimeMinutes / 60);
const lastMinute = lastTimeMinutes % 60;
const endTime = `${String(lastHour).padStart(2, '0')}:${String(lastMinute).padStart(2, '0')}`;
doc.setFontSize(9);
doc.text(`00:00 - ${endTime}`, marginLeft + tableWidth - col3Width / 2, 45, { align: 'center' });
doc.setFont('helvetica', 'bold'); doc.setFont('helvetica', 'bold');
doc.setFontSize(10); doc.setFontSize(10);
doc.text(`Plant Section : ${sectionName}`, marginLeft + col1Width + col2Width / 2, 41, { align: 'center' }); doc.text(`Plant Section : ${sectionName}`, marginLeft + col1Width + col2Width / 2, 41, { align: 'center' });
}; };
// FUNGSI HEADER SEDERHANA - Untuk Halaman Selanjutnya // Hitung total kolom tag chunks
const drawSimpleHeader = (doc, date) => { const totalTagColumns = sortedTags.length;
const formattedDate = dayjs(date).format('DD-MM-YYYY'); const totalTagChunks = Math.ceil(totalTagColumns / MAX_TAG_COLUMNS_PER_PAGE);
// Gunakan struktur kolom yang SAMA seperti header lengkap // PERBAIKAN: Variabel untuk tracking total halaman yang sebenarnya
const col1Width = HEADER_LEFT_COLUMN_WIDTH; // Gunakan konstanta HEADER let actualTotalPages = 0;
const col3Width = tableWidth * 0.20; const pageInfoArray = []; // Array untuk menyimpan info setiap page
const col2Width = tableWidth - col1Width - col3Width;
// Border luar // Loop pertama: hitung dulu total halaman yang akan dibuat
doc.setLineWidth(0.5); for (let pageChunk = 0; pageChunk < totalTagChunks; pageChunk++) {
doc.line(marginLeft, 10, marginLeft + tableWidth, 10); const startTagIndex = pageChunk * MAX_TAG_COLUMNS_PER_PAGE;
doc.line(marginLeft, 10, marginLeft, 30); const endTagIndex = Math.min(startTagIndex + MAX_TAG_COLUMNS_PER_PAGE, totalTagColumns);
doc.line(marginLeft + tableWidth, 10, marginLeft + tableWidth, 30); const pageTagColumns = sortedTags.slice(startTagIndex, endTagIndex);
doc.line(marginLeft, 30, marginLeft + tableWidth, 30); const isFirstPage = (pageChunk === 0);
// Garis vertikal pemisah kolom // Simulasi autoTable untuk menghitung jumlah halaman
doc.line(marginLeft + tableWidth - col3Width, 10, marginLeft + tableWidth - col3Width, 30); const tempDoc = new jsPDF({ orientation: 'landscape' });
const headerRow = ['Datetime', ...pageTagColumns.map(tag => tagMapping[tag] || tag)];
// Kolom Kiri (KOSONG - tidak ada isi) const pdfRows = pivotTableData.map((rowData) => {
const row = [dayjs(rowData.datetime).format('DD-MM-YYYY HH:mm')];
// Kolom Tengah - Plant Section pageTagColumns.forEach((tagName) => {
doc.setFontSize(10); const value = rowData[tagName];
doc.setFont('helvetica', 'bold'); row.push(value !== undefined && value !== null ? Number(value).toFixed(2) : '-');
doc.text(`Plant Section : ${sectionName}`, marginLeft + col1Width + col2Width / 2, 20, { align: 'center' }); });
return row;
// Kolom Kanan - Laporan Periode + Time Range
doc.setFontSize(9);
doc.setFont('helvetica', 'bold');
doc.text('Laporan Periode :', marginLeft + tableWidth - col3Width / 2, 14, { align: 'center' });
doc.setFont('helvetica', 'normal');
doc.text(formattedDate, marginLeft + tableWidth - col3Width / 2, 19, { align: 'center' });
// Hitung waktu akhir berdasarkan periode
const minutesInDay = 24 * 60;
const lastTimeMinutes = Math.floor((minutesInDay - periode) / periode) * periode;
const lastHour = Math.floor(lastTimeMinutes / 60);
const lastMinute = lastTimeMinutes % 60;
const endTime = `${String(lastHour).padStart(2, '0')}:${String(lastMinute).padStart(2, '0')}`;
doc.text(`00:00 - ${endTime}`, marginLeft + tableWidth - col3Width / 2, 24, { align: 'center' });
};
sortedDates.forEach((date, dateIndex) => {
const dateData = dataByDate[date];
// Ambil semua waktu yang sudah di-generate lengkap
const allTimes = dateData[Object.keys(dateData)[0]].map(item => item.x);
const formattedTimes = allTimes.map(time => dayjs(time).format('HH:mm'));
const sortedTags = Object.keys(dateData).sort();
const totalTimeColumns = formattedTimes.length;
const totalPages = Math.ceil(totalTimeColumns / MAX_TIME_COLUMNS_PER_PAGE);
let totalPagesCount = 0;
sortedDates.forEach((date) => {
const dateData = dataByDate[date];
const totalTimeColumns = dateData[Object.keys(dateData)[0]].length;
const pagesForThisDate = Math.ceil(totalTimeColumns / MAX_TIME_COLUMNS_PER_PAGE);
totalPagesCount += pagesForThisDate;
}); });
for (let pageChunk = 0; pageChunk < totalPages; pageChunk++) { const availableWidthForTags = tableWidth - DATETIME_COLUMN_WIDTH;
if (dateIndex > 0 || pageChunk > 0) { const TAG_COLUMN_WIDTH = availableWidthForTags / pageTagColumns.length;
doc.addPage();
}
const startColIndex = pageChunk * MAX_TIME_COLUMNS_PER_PAGE; const tagColumnStyles = {};
const endColIndex = Math.min(startColIndex + MAX_TIME_COLUMNS_PER_PAGE, totalTimeColumns); for (let i = 0; i < pageTagColumns.length; i++) {
const pageTimeColumns = formattedTimes.slice(startColIndex, endColIndex); tagColumnStyles[i + 1] = {
const pageRawTimes = allTimes.slice(startColIndex, endColIndex); cellWidth: TAG_COLUMN_WIDTH,
halign: 'center'
};
}
const isFirstPage = (dateIndex === 0 && pageChunk === 0); let pagesForThisChunk = 0;
// Gunakan header yang sesuai autoTable(tempDoc, {
if (isFirstPage) { head: [headerRow],
drawFullHeader(doc, date); body: pdfRows,
} else { startY: isFirstPage ? 50 : 15,
drawSimpleHeader(doc, date); theme: 'grid',
} rowPageBreak: 'avoid',
styles: {
const availableWidthForTime = tableWidth - IO_TAG_COLUMN_WIDTH; fontSize: 7,
const TIME_COLUMN_WIDTH = availableWidthForTime / pageTimeColumns.length; cellPadding: 1.5,
minCellHeight: 8,
const headerRow = ['IO Soft Tag', ...pageTimeColumns]; lineColor: [0, 0, 0],
lineWidth: 0.1,
const pdfRows = sortedTags.map(tagName => { halign: 'center',
const tagIdentifier = tagMapping[tagName] || tagName; valign: 'middle',
const row = [tagIdentifier]; overflow: 'linebreak',
},
const tagData = dateData[tagName]; headStyles: {
fillColor: [220, 220, 220],
for (let i = startColIndex; i < endColIndex; i++) { textColor: [0, 0, 0],
const dataPoint = tagData[i]; fontStyle: 'bold',
const val = dataPoint && dataPoint.y; halign: 'center',
row.push(val !== undefined && val !== null ? Number(val).toFixed(2) : '-'); valign: 'middle',
} lineColor: [0, 0, 0],
lineWidth: 0.3,
return row; },
}); columnStyles: {
0: {
const timeColumnStyles = {}; cellWidth: DATETIME_COLUMN_WIDTH,
for (let i = 0; i < pageTimeColumns.length; i++) {
timeColumnStyles[i + 1] = {
cellWidth: TIME_COLUMN_WIDTH,
minCellWidht: 10,
halign: 'center'
};
}
autoTable(doc, {
head: [headerRow],
body: pdfRows,
startY: isFirstPage ? 50 : 30, // Sesuaikan startY untuk header sederhana (sama tinggi dengan header lengkap)
theme: 'grid',
styles: {
fontSize: 5,
cellPadding: 1,
minCellHeight: 10,
lineColor: [0, 0, 0],
lineWidth: 0.1,
halign: 'center',
valign: 'middle',
overflow: 'linebreak',
},
headStyles: {
fillColor: [255, 255, 255],
textColor: [0, 0, 0],
fontStyle: 'bold', fontStyle: 'bold',
halign: 'center', halign: 'center',
valign: 'middle', valign: 'middle'
lineColor: [0, 0, 0],
lineWidth: 0.3,
}, },
columnStyles: { ...tagColumnStyles
0: { },
cellWidth: IO_TAG_COLUMN_WIDTH, margin: { left: marginLeft, right: marginRight, top: 15 },
fontStyle: 'bold', tableWidth: tableWidth,
halign: 'center', pageBreak: 'auto',
valign: 'middle' didDrawPage: () => {
}, pagesForThisChunk++;
...timeColumnStyles }
}, });
margin: { left: marginLeft, right: marginRight },
tableWidth: tableWidth,
pageBreak: 'auto',
didDrawPage: (data) => {
doc.setFontSize(8);
doc.setFont('helvetica', 'normal');
doc.text(
`Page ${globalPageNumber} of ${totalPagesCount}`,
doc.internal.pageSize.width / 2,
doc.internal.pageSize.height - 10,
{ align: 'center' }
);
globalPageNumber++;
},
});
}
});
doc.save(`Report_${startDate.format('DD-MM-YYYY')}_to_${endDate.format('DD-MM-YYYY')}_ByDate.pdf`); pageInfoArray.push({
chunkIndex: pageChunk,
pagesCount: pagesForThisChunk,
startPage: actualTotalPages + 1
});
actualTotalPages += pagesForThisChunk;
}
console.log('Total pages akan dibuat:', actualTotalPages);
// Loop kedua: buat PDF yang sebenarnya dengan nomor halaman yang benar
let globalPageNumber = 1;
for (let pageChunk = 0; pageChunk < totalTagChunks; pageChunk++) {
if (pageChunk > 0) {
doc.addPage();
}
const startTagIndex = pageChunk * MAX_TAG_COLUMNS_PER_PAGE;
const endTagIndex = Math.min(startTagIndex + MAX_TAG_COLUMNS_PER_PAGE, totalTagColumns);
const pageTagColumns = sortedTags.slice(startTagIndex, endTagIndex);
const isFirstPage = (pageChunk === 0);
if (isFirstPage) {
drawFullHeader(doc);
}
const headerRow = ['Datetime', ...pageTagColumns.map(tag => tagMapping[tag] || tag)];
const pdfRows = pivotTableData.map((rowData) => {
const row = [dayjs(rowData.datetime).format('DD-MM-YYYY HH:mm')];
pageTagColumns.forEach((tagName) => {
const value = rowData[tagName];
row.push(value !== undefined && value !== null ? Number(value).toFixed(2) : '-');
});
return row;
});
const availableWidthForTags = tableWidth - DATETIME_COLUMN_WIDTH;
const TAG_COLUMN_WIDTH = availableWidthForTags / pageTagColumns.length;
const tagColumnStyles = {};
for (let i = 0; i < pageTagColumns.length; i++) {
tagColumnStyles[i + 1] = {
cellWidth: TAG_COLUMN_WIDTH,
halign: 'center'
};
}
autoTable(doc, {
head: [headerRow],
body: pdfRows,
startY: isFirstPage ? 50 : 15,
theme: 'grid',
rowPageBreak: 'avoid',
styles: {
fontSize: 7,
cellPadding: 1.5,
minCellHeight: 8,
lineColor: [0, 0, 0],
lineWidth: 0.1,
halign: 'center',
valign: 'middle',
overflow: 'linebreak',
},
headStyles: {
fillColor: [220, 220, 220],
textColor: [0, 0, 0],
fontStyle: 'bold',
halign: 'center',
valign: 'middle',
lineColor: [0, 0, 0],
lineWidth: 0.3,
},
columnStyles: {
0: {
cellWidth: DATETIME_COLUMN_WIDTH,
fontStyle: 'bold',
halign: 'center',
valign: 'middle'
},
...tagColumnStyles
},
margin: { left: marginLeft, right: marginRight, top: 15 },
tableWidth: tableWidth,
pageBreak: 'auto',
didDrawPage: (data) => {
doc.setFontSize(8);
doc.setFont('helvetica', 'normal');
doc.text(
`Page ${globalPageNumber} of ${actualTotalPages}`,
doc.internal.pageSize.width / 2,
doc.internal.pageSize.height - 10,
{ align: 'center' }
);
globalPageNumber++;
},
});
}
doc.save(`Report_Pivot_${startDate.format('DD-MM-YYYY')}_to_${endDate.format('DD-MM-YYYY')}.pdf`);
}; };
return ( return (
@@ -707,20 +711,23 @@ const ListReport = memo(function ListReport(props) {
</Col> </Col>
<Col xs={24} style={{ marginTop: '16px' }}> <Col xs={24} style={{ marginTop: '16px' }}>
<Spin spinning={isLoadingTable}> <Spin spinning={isLoadingTable}>
<Table <div style={{ overflowX: 'auto', width: '100%' }}>
columns={columns} <Table
dataSource={tableData} columns={columns}
pagination={{ dataSource={tableData}
...pagination, pagination={{
showSizeChanger: true, ...pagination,
showTotal: (total) => `Total ${total} data`, showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'], showTotal: (total) => `Total ${total} data`,
}} pageSizeOptions: ['10', '20', '50', '100'],
onChange={handleTableChange} }}
scroll={{ x: 'max-content', y: 500 }} onChange={handleTableChange}
bordered scroll={{ x: 'max-content', y: 500 }}
size="small" bordered
/> size="small"
sticky
/>
</div>
</Spin> </Spin>
</Col> </Col>
</Row> </Row>