From eb802a23a557f90fddee8ad93564583b6cf0e3db Mon Sep 17 00:00:00 2001 From: Harshitha Shetty <141444342+HarshithaShetty27@users.noreply.github.com> Date: Sun, 26 Jan 2025 18:25:54 +0530 Subject: [PATCH] appointment report generation --- client/package-lock.json | 167 ++++++++++++++++++++++++ client/package.json | 2 + client/src/Pages/courseConsolidated.jsx | 108 ++++++++++++--- 3 files changed, 262 insertions(+), 15 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 2c28366..fade6f1 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -13,6 +13,8 @@ "@testing-library/user-event": "^13.5.0", "axios": "^1.6.8", "bootstrap": "^5.3.3", + "jspdf": "^2.5.2", + "jspdf-autotable": "^3.8.4", "md5": "^2.3.0", "mongoose": "^8.3.1", "react": "^18.2.0", @@ -4502,6 +4504,12 @@ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==" }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "optional": true + }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", @@ -5443,6 +5451,17 @@ "node": ">= 4.0.0" } }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.19", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", @@ -5848,6 +5867,15 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "optional": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -6051,6 +6079,17 @@ "node": ">=16.20.1" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -6159,6 +6198,31 @@ } ] }, + "node_modules/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/canvg/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "optional": true + }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", @@ -6671,6 +6735,15 @@ "postcss": "^8.4" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -7403,6 +7476,12 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.8.tgz", + "integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==", + "optional": true + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -9596,6 +9675,19 @@ } } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "optional": true, + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -12592,6 +12684,36 @@ "node": ">=0.10.0" } }, + "node_modules/jspdf": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz", + "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.5.4", + "html2canvas": "^1.0.0-rc.5" + } + }, + "node_modules/jspdf-autotable": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-3.8.4.tgz", + "integrity": "sha512-rSffGoBsJYX83iTRv8Ft7FhqfgEL2nLpGAIiqruEQQ3e4r0qdLFbPUB7N9HAle0I3XgpisvyW751VHCqKUVOgQ==", + "peerDependencies": { + "jspdf": "^2.5.1" + } + }, + "node_modules/jspdf/node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -16066,6 +16188,15 @@ "node": ">=0.10.0" } }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -16775,6 +16906,15 @@ "node": ">=8" } }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -17267,6 +17407,15 @@ "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", @@ -17515,6 +17664,15 @@ "node": ">=8" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -18010,6 +18168,15 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "optional": true, + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", diff --git a/client/package.json b/client/package.json index b67e3ac..44fd21f 100644 --- a/client/package.json +++ b/client/package.json @@ -8,6 +8,8 @@ "@testing-library/user-event": "^13.5.0", "axios": "^1.6.8", "bootstrap": "^5.3.3", + "jspdf": "^2.5.2", + "jspdf-autotable": "^3.8.4", "md5": "^2.3.0", "mongoose": "^8.3.1", "react": "^18.2.0", diff --git a/client/src/Pages/courseConsolidated.jsx b/client/src/Pages/courseConsolidated.jsx index 97da622..fe03333 100644 --- a/client/src/Pages/courseConsolidated.jsx +++ b/client/src/Pages/courseConsolidated.jsx @@ -1,6 +1,9 @@ import React, { useState, useEffect } from "react"; import axios from "axios"; import * as XLSX from "xlsx-js-style"; +import { jsPDF } from "jspdf"; +import autoTable from "jspdf-autotable"; + const CourseConsolidated = () => { const [data, setData] = useState([]); @@ -51,12 +54,87 @@ const CourseConsolidated = () => { if (currentPage > 1) setCurrentPage((prevPage) => prevPage - 1); }; - const createExcelFile = (courseData, courseName) => { - const workbook = XLSX.utils.book_new(); - const worksheet = XLSX.utils.json_to_sheet(courseData); - XLSX.utils.book_append_sheet(workbook, worksheet, courseName); - XLSX.writeFile(workbook, `${courseName.replace(/\s+/g, "_")}_Table.xlsx`); - }; + const generateAppointmentPDF = (courseData, courseName) => { + console.log(courseData); + const doc = new jsPDF(); + + // Add Title + doc.setFontSize(16); + doc.text(`${courseName} - Appointment Order`, 105, 10, { align: "center" }); + + // Add the table for names and roles (Using courseData for this) + const table1Data = [ + ...(courseData.oralPracticalTeachers?.map((teacher) => [ + teacher, + "K. J. Somaiya Institute of Technology", + "Assessment Role", + "Contact Number", + ]) || []), + ...(courseData.reassessmentTeachers?.map((teacher) => [ + teacher, + "K. J. Somaiya Institute of Technology", + "Reassessment Role", + "Contact Number", + ]) || []), + ...(courseData.paperSettingTeachers?.map((teacher) => [ + teacher, + "K. J. Somaiya Institute of Technology", + "Paper Setter", + "Contact Number", + ]) || []), + ...(courseData.moderationTeachers?.map((teacher) => [ + teacher, + "K. J. Somaiya Institute of Technology", + "Moderator", + "Contact Number", + ]) || []), + ...(courseData.pwdPaperSettingTeachers?.map((teacher) => [ + teacher, + "K. J. Somaiya Institute of Technology", + "PwD Paper Setter", + "Contact Number", + ]) || []), + ]; + + + autoTable(doc, { + head: [["Name", "Affiliation", "Appointment Role", "Contact No."]], + body: table1Data, + startY: 20, + theme: "grid", + }); + + // Add the descriptive paragraph + const text = `Dear all,\n\nYou have been appointed to jointly act as Paper Setters as mentioned against your name for the following Examination to be held at K. J. Somaiya Institute of Technology, Sion, Mumbai:`; + doc.setFontSize(12); + doc.text(text, 10, doc.previousAutoTable.finalY + 10); + + // Add the exam details table using `courseData` + const table2Data = [ + ["Programme:", courseData.courseName], + ["Exam Category:", "Regular Examination"], + ["Exam Type:", courseData.examType], + ["Exam Season:", "Second Half - Winter Examination 2023"], + ["Number of Sets Required:", courseData.paperSettingTeachers.length], + ["Year:", courseData.year], + ["Semester:", courseData.semester], + ["Course Name:", courseName], + ["Course Code:", courseData.courseCode], + ]; + + + + autoTable(doc, { + body: table2Data, + startY: doc.previousAutoTable.finalY + 30, + theme: "plain", + styles: { lineColor: [0, 0, 0], lineWidth: 0.1 }, + }); + + // Save the PDF + doc.save(`${courseName} - AppointmentOrder.pdf`); +}; + return (