import * as React from "react"; import { useParams } from "next/navigation"; import { useTranslation } from "@/i18n/client"; import { Button } from "@/components/ui/button"; import { FileDown, Loader } from "lucide-react"; import { toast } from "sonner"; import * as ExcelJS from 'exceljs'; interface ExcelDownloadProps { comparisonResults: Array<{ tagNo: string; tagDesc: string; isMatching: boolean; attributes: Array<{ key: string; label: string; localValue: any; sedpValue: any; isMatching: boolean; uom?: string; }>; }>; missingTags: { localOnly: Array<{ tagNo: string; tagDesc: string }>; sedpOnly: Array<{ tagNo: string; tagDesc: string }>; }; formCode: string; disabled: boolean; } export function ExcelDownload({ comparisonResults, missingTags, formCode, disabled }: ExcelDownloadProps) { const [isExporting, setIsExporting] = React.useState(false); const params = useParams(); const lng = (params?.lng as string) || "ko"; const { t } = useTranslation(lng, "engineering"); // Function to generate and download Excel file with differences const handleExportDifferences = async () => { try { setIsExporting(true); // Get only items with differences const itemsWithDifferences = comparisonResults.filter(item => !item.isMatching); const hasMissingTags = missingTags.localOnly.length > 0 || missingTags.sedpOnly.length > 0; if (itemsWithDifferences.length === 0 && !hasMissingTags) { toast.info(t("excelDownload.noDifferencesToDownload")); return; } // Create a new workbook const workbook = new ExcelJS.Workbook(); workbook.creator = 'SEDP Compare Tool'; workbook.created = new Date(); // Add a worksheet for attribute differences if (itemsWithDifferences.length > 0) { const worksheet = workbook.addWorksheet(t("excelDownload.attributeDifferencesSheet")); // Add headers worksheet.columns = [ { header: t("excelDownload.tagNumber"), key: 'tagNo', width: 20 }, { header: t("excelDownload.tagDescription"), key: 'tagDesc', width: 30 }, { header: t("excelDownload.attribute"), key: 'attribute', width: 25 }, { header: t("excelDownload.localValue"), key: 'localValue', width: 20 }, { header: t("excelDownload.sedpValue"), key: 'sedpValue', width: 20 } ]; // Style the header row const headerRow = worksheet.getRow(1); headerRow.eachCell((cell) => { cell.font = { bold: true }; cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFE0E0E0' } }; cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' } }; }); // Add data rows let rowIndex = 2; itemsWithDifferences.forEach(item => { const differences = item.attributes.filter(attr => !attr.isMatching); if (differences.length === 0) return; differences.forEach(diff => { const row = worksheet.getRow(rowIndex++); // Format local value with UOM const localDisplay = diff.localValue === null || diff.localValue === undefined || diff.localValue === '' ? t("excelDownload.emptyValue") : diff.uom ? `${diff.localValue} ${diff.uom}` : diff.localValue; // SEDP value is displayed as-is const sedpDisplay = diff.sedpValue === null || diff.sedpValue === undefined || diff.sedpValue === '' ? t("excelDownload.emptyValue") : diff.sedpValue; // Set cell values row.getCell('tagNo').value = item.tagNo; row.getCell('tagDesc').value = item.tagDesc; row.getCell('attribute').value = diff.label; row.getCell('localValue').value = localDisplay; row.getCell('sedpValue').value = sedpDisplay; // Style the row row.getCell('localValue').font = { color: { argb: 'FFFF0000' } }; // Red for local value row.getCell('sedpValue').font = { color: { argb: 'FF008000' } }; // Green for SEDP value // Add borders row.eachCell((cell) => { cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' } }; }); }); // Add a blank row after each tag for better readability rowIndex++; }); } // Add a worksheet for missing tags if there are any if (hasMissingTags) { const missingWorksheet = workbook.addWorksheet(t("excelDownload.missingTagsSheet")); // Add headers missingWorksheet.columns = [ { header: t("excelDownload.tagNumber"), key: 'tagNo', width: 20 }, { header: t("excelDownload.tagDescription"), key: 'tagDesc', width: 30 }, { header: t("excelDownload.status"), key: 'status', width: 20 } ]; // Style the header row const headerRow = missingWorksheet.getRow(1); headerRow.eachCell((cell) => { cell.font = { bold: true }; cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFE0E0E0' } }; cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' } }; }); // Add local-only tags let rowIndex = 2; missingTags.localOnly.forEach(tag => { const row = missingWorksheet.getRow(rowIndex++); row.getCell('tagNo').value = tag.tagNo; row.getCell('tagDesc').value = tag.tagDesc; row.getCell('status').value = t("excelDownload.localOnlyStatus"); // Style the status cell row.getCell('status').font = { color: { argb: 'FFFF8C00' } }; // Orange for local-only // Add borders row.eachCell((cell) => { cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' } }; }); }); // Add a blank row if (missingTags.localOnly.length > 0 && missingTags.sedpOnly.length > 0) { rowIndex++; } // Add SEDP-only tags missingTags.sedpOnly.forEach(tag => { const row = missingWorksheet.getRow(rowIndex++); row.getCell('tagNo').value = tag.tagNo; row.getCell('tagDesc').value = tag.tagDesc; row.getCell('status').value = t("excelDownload.sedpOnlyStatus"); // Style the status cell row.getCell('status').font = { color: { argb: 'FF0000FF' } }; // Blue for SEDP-only // Add borders row.eachCell((cell) => { cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' } }; }); }); } // Generate Excel file const buffer = await workbook.xlsx.writeBuffer(); // Create a Blob from the buffer const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); // Create a download link and trigger the download const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${t("excelDownload.fileNamePrefix")}_${formCode}_${new Date().toISOString().slice(0, 10)}.xlsx`; document.body.appendChild(a); a.click(); // Clean up window.URL.revokeObjectURL(url); document.body.removeChild(a); toast.success(t("excelDownload.downloadComplete")); } catch (error) { console.error("Error exporting to Excel:", error); toast.error(t("excelDownload.downloadFailed")); } finally { setIsExporting(false); } }; // Determine if there are any differences or missing tags const hasDifferences = comparisonResults.some(item => !item.isMatching); const hasMissingTags = missingTags && (missingTags.localOnly.length > 0 || missingTags.sedpOnly.length > 0); const hasExportableContent = hasDifferences || hasMissingTags; return ( ); }