diff --git a/package-lock.json b/package-lock.json index 2db3c75d..f8115741 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,10 +20,14 @@ "aos": "^2.3.4", "axios": "^1.7.2", "cors": "^2.8.5", + "docx": "^8.5.0", "dotenv": "^16.4.5", "emoji-picker-react": "^4.11.1", + "file-saver": "^2.0.5", "formik": "^2.4.6", "html-webpack-plugin": "^5.6.0", + "jspdf": "^2.5.1", + "jspdf-autotable": "^3.8.2", "jwt-decode": "^4.0.0", "mini-css-extract-plugin": "^2.9.0", "papaparse": "^5.4.1", @@ -8114,6 +8118,13 @@ "dev": true, "license": "MIT" }, + "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==", + "license": "MIT", + "optional": true + }, "node_modules/@types/range-parser": { "version": "1.2.7", "dev": true, @@ -9429,6 +9440,18 @@ "version": "0.4.0", "license": "MIT" }, + "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==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "dev": true, @@ -9738,6 +9761,16 @@ "devOptional": true, "license": "MIT" }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "dev": true, @@ -10610,6 +10643,18 @@ "node-int64": "^0.4.0" } }, + "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==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/buffer": { "version": "5.7.1", "dev": true, @@ -10821,6 +10866,33 @@ "node": ">=6" } }, + "node_modules/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "license": "MIT", + "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==", + "license": "MIT", + "optional": true + }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "dev": true, @@ -11492,6 +11564,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/core-js": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-compat": { "version": "3.37.1", "dev": true, @@ -11506,7 +11590,6 @@ }, "node_modules/core-util-is": { "version": "1.0.3", - "dev": true, "license": "MIT" }, "node_modules/cors": { @@ -11731,6 +11814,16 @@ "node": ">=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==", + "license": "MIT", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "7.1.2", "dev": true, @@ -12790,6 +12883,40 @@ "node": ">=6.0.0" } }, + "node_modules/docx": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/docx/-/docx-8.5.0.tgz", + "integrity": "sha512-4SbcbedPXTciySXiSnNNLuJXpvxFe5nqivbiEHXyL8P/w0wx2uW7YXNjnYgjW0e2e6vy+L/tMISU/oAiXCl57Q==", + "license": "MIT", + "dependencies": { + "@types/node": "^20.3.1", + "jszip": "^3.10.1", + "nanoid": "^5.0.4", + "xml": "^1.0.1", + "xml-js": "^1.6.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/docx/node_modules/nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "dev": true, @@ -12856,6 +12983,13 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.6.tgz", + "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true + }, "node_modules/domutils": { "version": "2.8.0", "license": "BSD-2-Clause", @@ -15035,6 +15169,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "dev": true, @@ -15085,6 +15225,12 @@ "url": "https://opencollective.com/webpack" } }, + "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-system-cache": { "version": "2.3.0", "dev": true, @@ -16440,6 +16586,20 @@ } } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "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", "funding": [ @@ -17016,6 +17176,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/immer": { "version": "10.1.1", "license": "MIT", @@ -17156,7 +17322,6 @@ }, "node_modules/inherits": { "version": "2.0.4", - "devOptional": true, "license": "ISC" }, "node_modules/ini": { @@ -17877,7 +18042,6 @@ }, "node_modules/isarray": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "node_modules/isexe": { @@ -20263,6 +20427,33 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jspdf": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", + "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.14.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.4.8" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.2.0", + "html2canvas": "^1.0.0-rc.5" + } + }, + "node_modules/jspdf-autotable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-3.8.2.tgz", + "integrity": "sha512-zW1ix99/mtR4MbIni7IqvrpfHmuTaICl6iv6wqjRN86Nxtwaw/QtOeDbpXqYSzHIJK9JvgtLM283sc5x+ipkJg==", + "license": "MIT", + "peerDependencies": { + "jspdf": "^2.5.1" + } + }, "node_modules/jsprim": { "version": "1.4.2", "dev": true, @@ -20291,6 +20482,54 @@ "node": ">=4.0" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/junk": { "version": "3.1.0", "dev": true, @@ -20399,6 +20638,15 @@ "node": ">= 0.8.0" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "license": "MIT" @@ -22100,7 +22348,7 @@ }, "node_modules/performance-now": { "version": "2.1.0", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/picocolors": { @@ -22525,7 +22773,6 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", - "dev": true, "license": "MIT" }, "node_modules/prompts": { @@ -22696,6 +22943,16 @@ ], "license": "MIT" }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "license": "MIT", + "optional": true, + "dependencies": { + "performance-now": "^2.1.0" + } + }, "node_modules/ramda": { "version": "0.29.0", "dev": true, @@ -24294,6 +24551,16 @@ "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==", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "2.7.1", "dev": true, @@ -24492,6 +24759,12 @@ "node_modules/save-dev": { "version": "0.0.1-security" }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, "node_modules/saxes": { "version": "6.0.0", "dev": true, @@ -24805,6 +25078,12 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "dev": true, @@ -25167,6 +25446,16 @@ "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/statuses": { "version": "2.0.1", "dev": true, @@ -25584,6 +25873,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "2.8.0", "dev": true, @@ -25907,6 +26206,16 @@ "node": "*" } }, + "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==", + "license": "MIT", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "dev": true, @@ -26907,7 +27216,6 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "devOptional": true, "license": "MIT" }, "node_modules/utila": { @@ -26922,6 +27230,16 @@ "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==", + "license": "MIT", + "optional": true, + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "8.3.2", "dev": true, @@ -27906,6 +28224,24 @@ "node": ">=0.8" } }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "license": "MIT" + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, "node_modules/xml-name-validator": { "version": "4.0.0", "dev": true, diff --git a/package.json b/package.json index 5da1ee17..24f78d7e 100644 --- a/package.json +++ b/package.json @@ -22,14 +22,18 @@ "aos": "^2.3.4", "axios": "^1.7.2", "cors": "^2.8.5", + "docx": "^8.5.0", "dotenv": "^16.4.5", "emoji-picker-react": "^4.11.1", + "file-saver": "^2.0.5", "formik": "^2.4.6", "html-webpack-plugin": "^5.6.0", + "jspdf": "^2.5.1", + "jspdf-autotable": "^3.8.2", "jwt-decode": "^4.0.0", "mini-css-extract-plugin": "^2.9.0", - "pdfjs-dist": "^4.5.136", "papaparse": "^5.4.1", + "pdfjs-dist": "^4.5.136", "react": "^18.3.1", "react-dom": "^18.3.1", "react-fast-marquee": "^1.6.5", diff --git a/src/assets/styles/SellerLayout.scss b/src/assets/styles/SellerLayout.scss index 7074f724..b9a9c9fe 100644 --- a/src/assets/styles/SellerLayout.scss +++ b/src/assets/styles/SellerLayout.scss @@ -73,20 +73,20 @@ gap: 3rem; .text_content { - color: $text-color; - font-size: 1.8rem; - text-decoration: none; - padding: 1rem; - border-radius: .5rem; - transition: background-color 0.3s, color 0.3s; - display: block; - - - &:hover { - background-color: $menu-hover; - color: $white !important; - width: 15rem !important ; - } + color: $text-color; + font-size: 1.8rem; + text-decoration: none; + padding: 1rem; + border-radius: .5rem; + transition: background-color 0.3s, color 0.3s; + display: block; + + + &:hover { + background-color: $menu-hover; + color: $white !important; + width: 15rem !important; + } } } @@ -96,20 +96,20 @@ margin-bottom: 3rem; .text_content { - color: $text-color; - font-size: 1.9rem; - text-decoration: none; - padding: 1rem; - border-radius: .5rem; - transition: background-color 0.3s, color 0.3s; - display: block; - - &:hover { - background-color: $menu-hover; - color: $white !important; - width: 15rem; - } + color: $text-color; + font-size: 1.9rem; + text-decoration: none; + padding: 1rem; + border-radius: .5rem; + transition: background-color 0.3s, color 0.3s; + display: block; + + &:hover { + background-color: $menu-hover; + color: $white !important; + width: 15rem; } + } } } @@ -125,151 +125,161 @@ } .main__seller__content__dashboard { - display: flex; - flex-direction: column; - flex: 1; - max-height: 100vh; + display: flex; + flex-direction: column; + flex: 1; + max-height: 100vh; } .main__seller__dashboard { + display: flex; + flex: 1; + width: 100%; + min-height: calc(100vh - 120px); + max-height: calc(100vh - 120px); + background-color: $container-color; + padding: 20px; + + .outlet { + background-color: white; + flex: 0 0 60%; + border-radius: 20px; + min-height: 95%; + max-height: 95%; + min-width: 70%; + max-width: 70%; + box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); + padding: 2rem; + overflow-y: scroll; + scroll-behavior: smooth; + + &::-webkit-scrollbar { + display: none; + } + } + + .right__side { + flex: 0 0 20%; + min-width: 20%; + max-width: 20%; + min-height: 100%; + max-height: 100%; display: flex; - flex: 1; - width: 100%; - min-height: calc(100vh - 120px); - max-height: calc(100vh - 120px); - background-color: $container-color; - padding: 20px; + flex-direction: column; + gap: 25px; + padding: 0 20px; - .outlet { - background-color: white; - flex: 0 0 60%; - border-radius: 20px; - min-height: 95%; - max-height: 95%; - min-width: 70%; - max-width: 70%; - box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); - padding: 2rem; - overflow-y: scroll; - scroll-behavior: smooth; - - &::-webkit-scrollbar { - display: none; + .right-profile { + background-color: $white-color; + height: 40%; + border-radius: 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); + padding: 2rem; + + .profile-image { + border-radius: 50%; + height: 6rem; + border: 0.2rem solid #FF6D18; + width: 6rem; + object-fit: cover; + margin-bottom: 1rem; + } + + .profile-name { + font-size: 1.8rem; + font-weight: 600; + color: $text-color; + margin: 0; + } + + .profile-edit { + font-size: 1.4rem; + color: $text-color; + background-color: #ffede2; + margin: 0; + cursor: pointer; + border: none; + color: $primary-color; + border-radius: 2rem; + padding: 0.5rem 1.8rem; + margin-top: 1rem; + font-size: 1.4rem; + + .icon-edit { + color: $primary-color; + margin-left: 1rem; + } + } + + .progress-bar-container { + display: flex; + align-items: center; + font-size: 1.4rem; + margin-top: 1rem; + color: $text-color; + + .order-progress { + color: $primary-color; + margin-left: 0.5rem; + margin-right: 0.5rem; } + } + + .progress-bar { + width: 3rem; + height: 1rem; + background-color: #e0e0e0; + border-radius: 0.5rem; + overflow: hidden; + } + + .progress-bar-fill { + height: 100%; + transition: width 0.3s ease; + } } - .right__side { - flex: 0 0 20%; - min-width: 20%; - max-width: 20%; - min-height: 100%; - max-height: 100%; + .right-products { + .loader { display: flex; - flex-direction: column; - gap: 25px; - padding: 0 20px; + justify-content: center; + align-items: center; + height: 50vh; + } - .right-profile { - background-color: $white-color; - height: 40%; - border-radius: 20px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); - padding: 2rem; - .profile-image { - border-radius: 50%; - height: 6rem; - border: 0.2rem solid #FF6D18; - width: 6rem; - object-fit: cover; - margin-bottom: 1rem; - } - .profile-name { - font-size: 1.8rem; - font-weight: 600; - color: $text-color; - margin: 0; - } - .profile-edit { - font-size: 1.4rem; - color: $text-color; - background-color: #ffede2; - margin: 0; - cursor: pointer; - border: none; - color: $primary-color; - border-radius: 2rem; - padding: 0.5rem 1.8rem; - margin-top: 1rem; - font-size: 1.4rem; - .icon-edit { - color: $primary-color; - margin-left: 1rem; - } - } - .progress-bar-container { - display: flex; - align-items: center; - font-size: 1.4rem; - margin-top: 1rem; - color: $text-color; - .order-progress { - color: $primary-color; - margin-left: 0.5rem; - margin-right: 0.5rem; - } - } - - .progress-bar { - width: 3rem; - height: 1rem; - background-color: #e0e0e0; - border-radius: 0.5rem; - overflow: hidden; - } - - .progress-bar-fill { - height: 100%; - transition: width 0.3s ease; - } - } + background-color: $white-color; + height: 60%; + overflow-y: scroll; + scroll-behavior: smooth; + border-radius: 20px; + box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); + padding: 1rem; - .right-products { - .loader { - display: flex; - justify-content: center; - align-items: center; - height: 50vh; - } - background-color: $white-color; - height: 60%; - overflow-y: scroll; - scroll-behavior: smooth; - border-radius: 20px; - box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1); - padding: 1rem; - &::-webkit-scrollbar { - display: none; - } - .right-header { - font-size: 1.4rem; - color: #000; - } - .product-header{ - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.3rem 0.9rem; - border-radius: 2rem; - margin-top: 1rem; - background-color: #d9d9d9; - color: #FF6D18; - } - } + &::-webkit-scrollbar { + display: none; + } + + .right-header { + font-size: 1.4rem; + color: #000; + } + + .product-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.3rem 0.9rem; + border-radius: 2rem; + margin-top: 1rem; + background-color: #d9d9d9; + color: #FF6D18; + } } + } } } @@ -282,128 +292,192 @@ width: 100%; gap: 30px; - .statisticCards { + .statisticCards { + display: flex; + justify-content: center; + align-items: center; + flex-wrap: wrap; + + .card { + transition: margin-top 0.3s ease; + } + + .card:hover { + margin-top: -20px; + } + } + + .chart-container { + width: 95%; + height: auto; + border-radius: 30px; + background-color: #fff; + overflow: hidden; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); + + + .chart-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 20px; + background-color: #fff; + border-bottom: 1px solid #e0e0e0; + + .sub-header { display: flex; - justify-content: center; - align-items: center; - flex-wrap: wrap; + flex-direction: column; + gap: 10px; - .card { - transition: margin-top 0.3s ease; + h1 { + margin-left: 2%; } - .card:hover { - margin-top: -20px; + .legend { + display: flex; + align-items: center; + flex-direction: row; + gap: 20px; + + .dot { + height: 10px; + width: 10px; + border-radius: 50%; + + &.completed { + background-color: #ff7300; + } + + &.cancelled { + background-color: #bfbfbf; + } + } } } - .chart-container { - width: 95%; - height: auto; - border-radius: 30px; - background-color: #fff; - overflow: hidden; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); - .chart-header { + .export-section { display: flex; - justify-content: space-between; - align-items: center; - padding: 10px 20px; - background-color: #fff; - border-bottom: 1px solid #e0e0e0; - .sub-header { - display: flex; - flex-direction: column; - gap: 10px; - h1 { - margin-left: 2%; + gap: 10px; + + .monthDropDown { + .dropdown-button { + background-color: #ff7300; + color: #fff; + border: none; + padding: 5px 10px; + border-radius: 5px; + cursor: pointer; + font-size: 14px; + + .arrow-down { + margin-left: 5px; + } } - .legend { - display: flex; - align-items: center; - flex-direction: row; - gap: 20px; + } - .dot { - height: 10px; - width: 10px; - border-radius: 50%; + .export-dropdown { + position: relative; - &.completed { - background-color: #ff7300; - } + .export-btn { + background-color: #0f8615; + color: #fff; + border: none; + padding: 5px 10px; + border-radius: 5px; + cursor: pointer; + font-size: 14px; + display: flex; + align-items: center; + gap: 4px; - &.cancelled { - background-color: #bfbfbf; - } + .arrow-down { + margin-left: 5px; } } - } - .export-section{ - display: flex; - gap: 10px; - .monthDropDown { - .dropdown-button { - background-color: #ff7300; - color: #fff; - border: none; - padding: 5px 10px; - border-radius: 5px; + .export-menu { + position: absolute; + top: 100%; + right: 0; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 5px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + list-style-type: none; + padding: 0; + margin: 5px 0 0; + z-index: 1000; + + li { + padding: 8px 15px; cursor: pointer; + display: flex; + align-items: center; + gap: 8px; font-size: 14px; - - .arrow-down { - margin-left: 5px; + color: #333; + + &:hover { + background-color: #f5f5f5; + } + + svg { + font-size: 16px; + } + + &:nth-child(1) svg { + color: #217346; // Excel green + } + + &:nth-child(2) svg { + color: #888888; // CSV gray + } + + &:nth-child(3) svg { + color: #F40F02; // PDF red + } + + &:nth-child(4) svg { + color: #2B579A; // Word blue } } } - .export-btn{ - background-color: #0f8615; - color: #fff; - border: none; - padding: 5px 10px; - border-radius: 5px; - cursor: pointer; - font-size: 14px; - display: flex; - gap: 4px; - } } - } + } + } } @media (max-width: 1024px) { .seller__wrapper { - .left__side { - width: 6.5rem; + .left__side { + width: 6.5rem; - .dashboard__items { - display: none; - } + .dashboard__items { + display: none; } + } - .main__seller__content__dashboard { - flex: 1; - padding: auto; - padding-left: 0px; - } + .main__seller__content__dashboard { + flex: 1; + padding: auto; + padding-left: 0px; + } - .main__seller__dashboard { - padding: 12px; + .main__seller__dashboard { + padding: 12px; - .outlet { - max-width: calc(100vw - 3.5rem); - overflow-y: scroll; - } + .outlet { + max-width: calc(100vw - 3.5rem); + overflow-y: scroll; + } - .right__side { - display: none; - } + .right__side { + display: none; } + } } } diff --git a/src/assets/styles/adminDashboard.scss b/src/assets/styles/adminDashboard.scss index e240b457..68b3f5dc 100644 --- a/src/assets/styles/adminDashboard.scss +++ b/src/assets/styles/adminDashboard.scss @@ -156,21 +156,112 @@ } } - .monthDropDown { - .dropdown-button { - background-color: #ff7300; - color: #fff; - border: none; - padding: 5px 10px; - border-radius: 5px; - cursor: pointer; - font-size: 14px; - - .arrow-down { - margin-left: 5px; + // .monthDropDown { + // .dropdown-button { + // background-color: #ff7300; + // color: #fff; + // border: none; + // padding: 5px 10px; + // border-radius: 5px; + // cursor: pointer; + // font-size: 14px; + + // .arrow-down { + // margin-left: 5px; + // } + // } + // } + + .export-section { + display: flex; + gap: 10px; + + .monthDropDown { + .dropdown-button { + background-color: #ff7300; + color: #fff; + border: none; + padding: 5px 10px; + border-radius: 5px; + cursor: pointer; + font-size: 14px; + + .arrow-down { + margin-left: 5px; + } + } + } + + .export-dropdown { + position: relative; + + .export-btn { + background-color: #0f8615; + color: #fff; + border: none; + padding: 5px 10px; + border-radius: 5px; + cursor: pointer; + font-size: 14px; + display: flex; + align-items: center; + gap: 4px; + + .arrow-down { + margin-left: 5px; + } + } + + .export-menu { + position: absolute; + top: 100%; + right: 0; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 5px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + list-style-type: none; + padding: 0; + margin: 5px 0 0; + z-index: 1000; + + li { + padding: 8px 15px; + cursor: pointer; + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + color: #333; + + &:hover { + background-color: #f5f5f5; + } + + svg { + font-size: 16px; + } + + &:nth-child(1) svg { + color: #217346; // Excel green + } + + &:nth-child(2) svg { + color: #888888; // CSV gray + } + + &:nth-child(3) svg { + color: #F40F02; // PDF red + } + + &:nth-child(4) svg { + color: #2B579A; // Word blue + } + } } } } + } } } diff --git a/src/pages/admin/OverView.tsx b/src/pages/admin/OverView.tsx index 8c653236..0a46fd6e 100644 --- a/src/pages/admin/OverView.tsx +++ b/src/pages/admin/OverView.tsx @@ -18,6 +18,12 @@ import { } from "../../store/features/admin/adminSlice"; import { useAppDispatch, useAppSelector } from "../../store/store"; import { useNavigate } from 'react-router-dom'; +import { FaFileExcel, FaFileCsv, FaFilePdf, FaFileWord } from "react-icons/fa"; +import exportToExcel from "../../utils/export/exportToExcel"; +import exportToCSV from "../../utils/export/exportToCSV"; +import exportToPDF from "../../utils/export/exportToPDF"; +import exportToWord from "../../utils/export/exportToWord"; + export const OverViewDashboard = () => { const getMonthName = (dateString) => { const date = new Date(dateString); @@ -44,6 +50,7 @@ export const OverViewDashboard = () => { const [numberOfSellers, setNumberOfSellers] = useState(null); const [numberOfShops, setNumberOfShops] = useState(null); const [selectedMonth, setSelectedMonth] = useState("All"); + const [orderHistory, setOrderHistory] = useState({ order: [] }) const dispatch = useAppDispatch(); const navigate = useNavigate(); @@ -78,6 +85,7 @@ export const OverViewDashboard = () => { const fetchData = async () => { try { const response = await dispatch(getOrderHistory()).unwrap(); + setOrderHistory({ order: response.data.OrderHistory }) const aggregatedData = response.data.OrderHistory.reduce( (acc, order) => { const monthName = getMonthName(order.orderDate); @@ -101,6 +109,34 @@ export const OverViewDashboard = () => { fetchData(); }, [dispatch]); + const [isExportOpen, setIsExportOpen] = useState(false); + + const toggleExportDropdown = () => { + setIsExportOpen(!isExportOpen); + }; + + const handleExport = (exportType) => { + console.dir(orderHistory) + switch (exportType) { + case 'excel': + exportToExcel(orderHistory, "admin_orders_report"); + break; + case 'csv': + exportToCSV(orderHistory, "admin_orders_report"); + break; + case 'pdf': + exportToPDF(orderHistory, "admin_orders_report"); + break; + case 'word': + exportToWord(orderHistory, "admin_orders_report"); + break; + default: + console.error('Invalid export type'); + } + setIsExportOpen(false); + }; + + const MonthDropDown = () => { const [isOpen, setIsOpen] = useState(false); const months = [ @@ -154,8 +190,8 @@ export const OverViewDashboard = () => { selectedMonth === "All" ? orderStats : orderStats.filter( - (stat) => stat.name === selectedMonth.substring(0, 3) - ); + (stat) => stat.name === selectedMonth.substring(0, 3) + ); return ( <> @@ -201,7 +237,22 @@ export const OverViewDashboard = () => { - +
+ +
+ + {isExportOpen && ( +
    +
  • handleExport('excel')}> Excel
  • +
  • handleExport('csv')}> CSV
  • +
  • handleExport('pdf')}> PDF
  • +
  • handleExport('word')}> Word
  • +
+ )} +
+
diff --git a/src/pages/seller/SellerDashboard.tsx b/src/pages/seller/SellerDashboard.tsx index 2854d26e..571d4252 100644 --- a/src/pages/seller/SellerDashboard.tsx +++ b/src/pages/seller/SellerDashboard.tsx @@ -17,10 +17,11 @@ import { sellerGetOrderHistory, } from "../../store/features/product/sellerCollectionProductsSlice"; import { useNavigate } from "react-router-dom"; -import productSlice from "../../store/features/product/productSlice"; -import { FaFileExcel } from "react-icons/fa"; -import exportToCSV from "../../utils/excel/exportToCSV"; -import exportToExcel from "../../utils/excel/exportToExcel"; +import { FaFileExcel, FaFileCsv, FaFilePdf, FaFileWord } from "react-icons/fa"; +import exportToExcel from "../../utils/export/exportToExcel"; +import exportToCSV from "../../utils/export/exportToCSV"; +import exportToPDF from "../../utils/export/exportToPDF"; +import exportToWord from "../../utils/export/exportToWord"; const SellerDashboard = () => { const { OrderHistory, message, data, isError } = useAppSelector( @@ -60,6 +61,7 @@ const SellerDashboard = () => { useEffect(() => { dispatch(sellerGetOrderHistory()); dispatch(fetchSellerCollectionProduct()); + dispatch(sellerGetAllProducts()); }, [dispatch]); useEffect(() => { try { @@ -108,6 +110,32 @@ const SellerDashboard = () => { } }, [OrderHistory, isError, message]); + const [isExportOpen, setIsExportOpen] = useState(false); + + const toggleExportDropdown = () => { + setIsExportOpen(!isExportOpen); + }; + + const handleExport = (exportType) => { + switch (exportType) { + case 'excel': + exportToExcel(OrderHistory); + break; + case 'csv': + exportToCSV(OrderHistory); + break; + case 'pdf': + exportToPDF(OrderHistory); + break; + case 'word': + exportToWord(OrderHistory); + break; + default: + console.error('Invalid export type'); + } + setIsExportOpen(false); + }; + const MonthDropDown = () => { const [isOpen, setIsOpen] = useState(false); const months = [ @@ -164,10 +192,6 @@ const SellerDashboard = () => { (stat) => stat.name === selectedMonth.substring(0, 3) ); - const exportStats = () => { - exportToExcel(OrderHistory) - } - return ( <>
@@ -203,7 +227,19 @@ const SellerDashboard = () => {
- +
+ + {isExportOpen && ( +
    +
  • handleExport('excel')}> Excel
  • +
  • handleExport('csv')}> CSV
  • +
  • handleExport('pdf')}> PDF
  • +
  • handleExport('word')}> Word
  • +
+ )} +
diff --git a/src/utils/excel/exportToCSV.ts b/src/utils/excel/exportToCSV.ts deleted file mode 100644 index bfdca6d1..00000000 --- a/src/utils/excel/exportToCSV.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable */ -import Papa from 'papaparse' - -const exportToCSV = (orderHistory) => { - const orders = orderHistory.order; - const rows = []; - rows.push([ - 'Order ID', - 'Order Date', - 'Expected Delivery Date', - 'Order Status', - 'Payment Method', - 'Products', - 'Total Order Revenue (RWF)', - 'Shipping Status' - ]); - orders.forEach(order => { - const products = JSON.parse(order.products); - const productSummary = products.map(p => `${p.name} (${p.quantity})`).join(', '); - const totalRevenue = products.reduce((sum, p) => sum + parseFloat(p.totalPrice), 0).toFixed(2); - - rows.push([ - order.id, - new Date(order.orderDate).toLocaleString(), - new Date(order.expectedDeliveryDate).toLocaleString(), - order.status, - order.paymentMethodId, - productSummary, - totalRevenue, - order.shippingProcess - ]); - }); - - const csv = Papa.unparse(rows); - const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); - const link = document.createElement('a'); - if (link.download !== undefined) { - const url = URL.createObjectURL(blob); - link.setAttribute('href', url); - link.setAttribute('download', 'seller_orders.csv'); - link.style.visibility = 'hidden'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - - } -}; - -export default exportToCSV; \ No newline at end of file diff --git a/src/utils/export/exportToCSV.ts b/src/utils/export/exportToCSV.ts new file mode 100644 index 00000000..c0d0143f --- /dev/null +++ b/src/utils/export/exportToCSV.ts @@ -0,0 +1,56 @@ +/* eslint-disable */ +/* eslint-disable */ +import Papa from 'papaparse'; + +const exportToCSV = (orderHistory, docName = 'seller_orders') => { + const orders = orderHistory.order; + const rows = [ + [ + 'Order ID', + 'Order Date', + 'Expected Delivery Date', + 'Order Status', + 'Payment Method', + 'Products', + 'Shipping Status' + ] + ]; + + orders.forEach(order => { + let productsInfo = ''; + + if (Array.isArray(order.products)) { + productsInfo = order.products.map(p => `${p.productId}(${p.status})`).join(', '); + } + + rows.push([ + order.id, + new Date(order.orderDate).toLocaleString(), + new Date(order.expectedDeliveryDate).toLocaleString(), + order.status, + order.paymentMethodId, + productsInfo, + order.shippingProcess + ]); + }); + + // Convert the data to CSV + const csv = Papa.unparse(rows); + + // Create a Blob with the CSV data + const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); + + // Create a download link and trigger the download + const link = document.createElement('a'); + if (link.download !== undefined) { + const url = URL.createObjectURL(blob); + link.setAttribute('href', url); + link.setAttribute('download', `${docName}.csv`); + link.style.visibility = 'hidden'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } +}; + +export default exportToCSV; \ No newline at end of file diff --git a/src/utils/excel/exportToExcel.ts b/src/utils/export/exportToExcel.ts similarity index 90% rename from src/utils/excel/exportToExcel.ts rename to src/utils/export/exportToExcel.ts index 4d6f267f..ec4b5928 100644 --- a/src/utils/excel/exportToExcel.ts +++ b/src/utils/export/exportToExcel.ts @@ -1,7 +1,7 @@ /* eslint-disable */ import * as XLSX from 'xlsx'; -const exportToExcel = (orderHistory) => { +const exportToExcel = (orderHistory, docName = 'seller_orders') => { const orders = orderHistory.order; const rows = [ [ @@ -41,7 +41,7 @@ const exportToExcel = (orderHistory) => { XLSX.utils.book_append_sheet(workbook, worksheet, 'OrderHistory'); // Export the workbook to an Excel file - XLSX.writeFile(workbook, 'seller_orders.xlsx'); + XLSX.writeFile(workbook, `${docName}.xlsx`); }; export default exportToExcel; \ No newline at end of file diff --git a/src/utils/export/exportToPDF.ts b/src/utils/export/exportToPDF.ts new file mode 100644 index 00000000..82dc869e --- /dev/null +++ b/src/utils/export/exportToPDF.ts @@ -0,0 +1,52 @@ +/* eslint-disable */ +import jsPDF from 'jspdf'; +import 'jspdf-autotable'; + +const exportToPDF = (orderHistory, docName = 'seller_orders') => { + const doc = new jsPDF(); + const orders = orderHistory.order; + + // Add title + doc.text('Order History', 14, 15); + + // Prepare data for the table + const tableRows = orders.map(order => [ + order.id, + new Date(order.orderDate).toLocaleString(), + new Date(order.expectedDeliveryDate).toLocaleString(), + order.status, + order.paymentMethodId, + Array.isArray(order.products) ? order.products.map(p => `${p.productId}(${p.status})`).join(', ') : '', + order.shippingProcess + ]); + + const columnCount = 7; // Number of columns + const pageWidth = doc.internal.pageSize.width; + const tableWidth = pageWidth - 20; // 10mm margin on each side + const columnWidth = tableWidth / columnCount; + + // Add table to the PDF + // @ts-ignore + doc.autoTable({ + head: [['Order ID', 'Order Date', 'Expected Delivery Date', 'Order Status', 'Payment Method', 'Products', 'Shipping Status']], + body: tableRows, + startY: 20, + margin: { left: 10, right: 10 }, + columnStyles: { + 0: { cellWidth: columnWidth }, + 1: { cellWidth: columnWidth }, + 2: { cellWidth: columnWidth }, + 3: { cellWidth: columnWidth }, + 4: { cellWidth: columnWidth }, + 5: { cellWidth: columnWidth }, + 6: { cellWidth: columnWidth }, + }, + styles: { overflow: 'linebreak', cellPadding: 2 }, + headStyles: { fillColor: [41, 128, 185], textColor: 255 }, + }); + + // Save the PDF + doc.save(`${docName}.pdf`); +}; + +export default exportToPDF; \ No newline at end of file diff --git a/src/utils/export/exportToWord.ts b/src/utils/export/exportToWord.ts new file mode 100644 index 00000000..679af0b7 --- /dev/null +++ b/src/utils/export/exportToWord.ts @@ -0,0 +1,58 @@ +/* eslint-disable */ +import { Document, Packer, Paragraph, Table, TableRow, TableCell, WidthType } from 'docx'; +import { saveAs } from 'file-saver'; + +const exportToWord = (orderHistory, docName = 'seller_orders') => { + const orders = orderHistory.order; + + // Define equal width for each column + const columnWidth = 100 / 7; // 7 columns, so each gets 1/7 of the total width + + // Create table rows + const rows = orders.map(order => + new TableRow({ + children: [ + new TableCell({ children: [new Paragraph(order.id)], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph(new Date(order.orderDate).toLocaleString())], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph(new Date(order.expectedDeliveryDate).toLocaleString())], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph(order.status)], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph(order.paymentMethodId)], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph(Array.isArray(order.products) ? order.products.map(p => `${p.productId}(${p.status})`).join(', ') : '')], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph(order.shippingProcess)], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + ], + }) + ); + + // Create the document + const doc = new Document({ + sections: [{ + children: [ + new Paragraph("Order History"), + new Table({ + rows: [ + new TableRow({ + children: [ + new TableCell({ children: [new Paragraph("Order ID")], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph("Order Date")], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph("Expected Delivery Date")], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph("Order Status")], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph("Payment Method")], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph("Products")], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + new TableCell({ children: [new Paragraph("Shipping Status")], width: { size: columnWidth, type: WidthType.PERCENTAGE } }), + ], + }), + ...rows, + ], + width: { size: 100, type: WidthType.PERCENTAGE }, + }), + ], + }], + }); + + // Generate and save the document + Packer.toBlob(doc).then(blob => { + saveAs(blob, `${docName}.docx`); + }); +}; + +export default exportToWord; \ No newline at end of file