diff options
Diffstat (limited to 'components/form-data-plant/sedp-excel-download.tsx')
| -rw-r--r-- | components/form-data-plant/sedp-excel-download.tsx | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/components/form-data-plant/sedp-excel-download.tsx b/components/form-data-plant/sedp-excel-download.tsx new file mode 100644 index 00000000..36be4847 --- /dev/null +++ b/components/form-data-plant/sedp-excel-download.tsx @@ -0,0 +1,259 @@ +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 ( + <Button + variant="secondary" + onClick={handleExportDifferences} + disabled={disabled || isExporting || !hasExportableContent} + className="flex items-center gap-2" + > + {isExporting ? ( + <Loader className="h-4 w-4 animate-spin" /> + ) : ( + <FileDown className="h-4 w-4" /> + )} + {t("excelDownload.downloadButtonText")} + </Button> + ); +}
\ No newline at end of file |
