From 747bdad3c61de4f9f2ea302d0a70db261bc3d4bf Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Wed, 8 Jan 2025 10:13:46 +0200 Subject: [PATCH] client side xlsx export :) --- package-lock.json | 7 +++ package.json | 1 + pages/cart/publishers/index.tsx | 96 +++++++++++++++++++++++++++------ 3 files changed, 89 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 421c62d..f34a8af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "express": "^4.18.2", "express-jwt": "^8.4.1", "fastest-levenshtein": "^1.0.16", + "file-saver": "^2.0.5", "fs": "^0.0.1-security", "gapi": "^0.0.3", "gapi-script": "^1.2.0", @@ -7906,6 +7907,12 @@ "node": ">=16.0.0" } }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, "node_modules/file-stream-rotator": { "version": "0.6.1", "license": "MIT", diff --git a/package.json b/package.json index c86025c..191d986 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "express": "^4.18.2", "express-jwt": "^8.4.1", "fastest-levenshtein": "^1.0.16", + "file-saver": "^2.0.5", "fs": "^0.0.1-security", "gapi": "^0.0.3", "gapi-script": "^1.2.0", diff --git a/pages/cart/publishers/index.tsx b/pages/cart/publishers/index.tsx index 10e5bc4..c48e139 100644 --- a/pages/cart/publishers/index.tsx +++ b/pages/cart/publishers/index.tsx @@ -23,6 +23,10 @@ import ConfirmationModal from '../../../components/ConfirmationModal'; import { relative } from "path"; import { set } from "lodash"; +import { utils, write } from 'xlsx'; +import { saveAs } from 'file-saver'; + + interface IProps { initialItems: Publisher[]; } @@ -38,20 +42,6 @@ function PublishersPage({ publishers = [] }: IProps) { indeterminate: true, }); - // const cbRefFilterTraining = useRef(null); - - // const getCheckboxState = (currentState: boolean | null) => { - // if (currentState === true) return 'unchecked'; - // if (currentState === false) return 'checked'; - // return 'indeterminate'; - // }; - // const cbRefFilterTraining = useRef(null); - // const [cbFilterTrainingState, setcbFilterTrainingState] = useState(null); - // useEffect(() => { - // if (cbRefFilterTraining.current) { - // cbRefFilterTraining.current.indeterminate = cbFilterTrainingState === null; - // } - // }, [cbFilterTrainingState]); const [flterNoTraining, setFilterNoTraining] = useState(false); const [isDeleting, setIsDeleting] = useState(false); @@ -225,6 +215,69 @@ function PublishersPage({ publishers = [] }: IProps) { toast.error("Грешка при експорт на данни"); } } + + + // Add this function to your component + const exportFilteredPublishers = () => { + try { + // Format the data for Excel + const excelData = shownPubs.map(publisher => ({ + 'First Name': publisher.firstName, + 'Last Name': publisher.lastName, + 'Email': publisher.email, + 'Phone': publisher.phone, + 'Active': publisher.isActive ? 'Yes' : 'No', + 'Trained': publisher.isTrained ? 'Yes' : 'No', + 'Imported': publisher.isImported ? 'Yes' : 'No', + 'Last Assignment': publisher.assignments.length > 0 + ? new Date(Math.max(...publisher.assignments.map(a => new Date(a.shift.startTime)))).toLocaleDateString() + : 'Never', + 'Number of Assignments': publisher.assignments.length, + 'Number of Availabilities': publisher.availabilities.length + })); + + // Create worksheet + const ws = utils.json_to_sheet(excelData); + + // Set column widths + const colWidths = [ + { wch: 15 }, // First Name + { wch: 15 }, // Last Name + { wch: 30 }, // Email + { wch: 10 }, // Active + { wch: 10 }, // Trained + { wch: 10 }, // Imported + { wch: 15 }, // Last Assignment + { wch: 20 }, // Number of Assignments + { wch: 20 }, // Number of Availabilities + ]; + ws['!cols'] = colWidths; + + // Create workbook and add worksheet + const wb = utils.book_new(); + utils.book_append_sheet(wb, ws, 'Publishers'); + + // Generate buffer + const excelBuffer = write(wb, { bookType: 'xlsx', type: 'array' }); + + // Create blob and save file + const blob = new Blob([excelBuffer], { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + }); + + // Generate filename with current date + const date = new Date().toISOString().split('T')[0]; + const filename = `publishers-${date}.xlsx`; + + saveAs(blob, filename); + + toast.success("Експортът е успешен"); + } catch (error) { + console.error('Export error:', error); + toast.error("Грешка при експорт на данни"); + } + }; + return ( @@ -258,8 +311,16 @@ function PublishersPage({ publishers = [] }: IProps) { Import publishers {/* export by calling excel helper .ExportPublishersToExcel() */} -
+ {/*
+
*/} +
+ +
@@ -350,6 +411,11 @@ export const getServerSideProps = async (context) => { isActive: true, isTrained: true, isImported: true, + lastLogin: true, + phone: true, + isSubscribedToReminders: true, + isSubscribedToCoverMe: true, + familyHeadId: true, assignments: { select: { shift: {