diff --git a/package-lock.json b/package-lock.json index 194979d..855be43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,12 @@ "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", + "@fontsource/plus-jakarta-sans": "^5.0.20", "@ionic/react": "^7.8.1", "@mui/icons-material": "^5.15.6", "@mui/material": "^5.15.6", + "@react-pdf/renderer": "^3.4.4", + "@reduxjs/toolkit": "^2.2.5", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -25,8 +28,12 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-inlinesvg": "^4.1.1", + "react-loader-spinner": "^6.1.6", + "react-redux": "^9.1.2", "react-router-dom": "^6.21.3", - "recharts": "^2.12.3" + "recharts": "^2.12.3", + "redux": "^5.0.1", + "redux-persist": "^6.0.0" }, "devDependencies": { "@babel/cli": "^7.23.9", @@ -2035,9 +2042,10 @@ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "license": "MIT", "dependencies": { "@emotion/memoize": "^0.8.1" } @@ -2635,6 +2643,12 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, + "node_modules/@fontsource/plus-jakarta-sans": { + "version": "5.0.20", + "resolved": "https://registry.npmjs.org/@fontsource/plus-jakarta-sans/-/plus-jakarta-sans-5.0.20.tgz", + "integrity": "sha512-a887FrG31RWqliRg1jXZM8tjzqee2NlO3Vuc5uGdws2EFvOg46P9VMaeS5eM3jihFq8Kj0zUQD0GYQqcxdkfCA==", + "license": "OFL-1.1" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -3118,6 +3132,199 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@react-pdf/fns": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.2.1.tgz", + "integrity": "sha512-s78aDg0vDYaijU5lLOCsUD+qinQbfOvcNeaoX9AiE7+kZzzCo6B/nX+l48cmt9OosJmvZvE9DWR9cLhrhOi2pA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13" + } + }, + "node_modules/@react-pdf/font": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-2.5.1.tgz", + "integrity": "sha512-Hyb2zBb92Glc3lvhmJfy4dO2Mj29KB26Uk12Ua9EhKAdiuCTLBqgP8Oe1cGwrvDI7xA4OOcwvBMdYh0vhOUHzA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/types": "^2.5.0", + "cross-fetch": "^3.1.5", + "fontkit": "^2.0.2", + "is-url": "^1.2.4" + } + }, + "node_modules/@react-pdf/image": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-2.3.6.tgz", + "integrity": "sha512-7iZDYZrZlJqNzS6huNl2XdMcLFUo68e6mOdzQeJ63d5eApdthhSHBnkGzHfLhH5t8DCpZNtClmklzuLL63ADfw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^2.3.1", + "cross-fetch": "^3.1.5", + "jay-peg": "^1.0.2" + } + }, + "node_modules/@react-pdf/layout": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-3.12.1.tgz", + "integrity": "sha512-BxSeykDxvADlpe4OGtQ7NH46QXq3uImAYsTHOPLCwbXMniQ1O3uCBx7H+HthxkCNshgYVPp9qS3KyvQv/oIZwg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.2.1", + "@react-pdf/image": "^2.3.6", + "@react-pdf/pdfkit": "^3.1.10", + "@react-pdf/primitives": "^3.1.1", + "@react-pdf/stylesheet": "^4.2.5", + "@react-pdf/textkit": "^4.4.1", + "@react-pdf/types": "^2.5.0", + "cross-fetch": "^3.1.5", + "emoji-regex": "^10.3.0", + "queue": "^6.0.1", + "yoga-layout": "^2.0.1" + } + }, + "node_modules/@react-pdf/pdfkit": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-3.1.10.tgz", + "integrity": "sha512-P/qPBtCFo2HDJD0i6NfbmoBRrsOVO8CIogYsefwG4fklTo50zNgnMM5U1WLckTuX8Qt1ThiQuokmTG5arheblA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^2.3.1", + "browserify-zlib": "^0.2.0", + "crypto-js": "^4.2.0", + "fontkit": "^2.0.2", + "jay-peg": "^1.0.2", + "vite-compatible-readable-stream": "^3.6.1" + } + }, + "node_modules/@react-pdf/png-js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-2.3.1.tgz", + "integrity": "sha512-pEZ18I4t1vAUS4lmhvXPmXYP4PHeblpWP/pAlMMRkEyP7tdAeHUN7taQl9sf9OPq7YITMY3lWpYpJU6t4CZgZg==", + "license": "MIT", + "dependencies": { + "browserify-zlib": "^0.2.0" + } + }, + "node_modules/@react-pdf/primitives": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-3.1.1.tgz", + "integrity": "sha512-miwjxLwTnO3IjoqkTVeTI+9CdyDggwekmSLhVCw+a/7FoQc+gF3J2dSKwsHvAcVFM0gvU8mzCeTofgw0zPDq0w==", + "license": "MIT" + }, + "node_modules/@react-pdf/render": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-3.4.4.tgz", + "integrity": "sha512-CfGxWmVgrY3JgmB1iMnz2W6Ck+8pisZeFt8vGlxP+JfT+0onr208pQvGSV5KwA9LGhAdABxqc/+y17V3vtKdFA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.2.1", + "@react-pdf/primitives": "^3.1.1", + "@react-pdf/textkit": "^4.4.1", + "@react-pdf/types": "^2.5.0", + "abs-svg-path": "^0.1.1", + "color-string": "^1.9.1", + "normalize-svg-path": "^1.1.0", + "parse-svg-path": "^0.1.2", + "svg-arc-to-cubic-bezier": "^3.2.0" + } + }, + "node_modules/@react-pdf/renderer": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-3.4.4.tgz", + "integrity": "sha512-j1TWMHHXDeHdoQE3xjhBh0MZ2rn7wHIlP/uglr/EJZXqnPbfg6bfLzRJCM6bs+XJV3d8+zLQjHf6sF/fWcBDfg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/font": "^2.5.1", + "@react-pdf/layout": "^3.12.1", + "@react-pdf/pdfkit": "^3.1.10", + "@react-pdf/primitives": "^3.1.1", + "@react-pdf/render": "^3.4.4", + "@react-pdf/types": "^2.5.0", + "events": "^3.3.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "queue": "^6.0.1", + "scheduler": "^0.17.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-pdf/renderer/node_modules/scheduler": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz", + "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/@react-pdf/stylesheet": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-4.2.5.tgz", + "integrity": "sha512-XnmapeCW+hDuNdVwpuvO04WKv71wAs8aH+saIq29Bo2fp1SxznHTcQArTZtK6Wgr/E9BHXeB2iAPpUZuI6G+xA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.2.1", + "@react-pdf/types": "^2.5.0", + "color-string": "^1.9.1", + "hsl-to-hex": "^1.0.0", + "media-engine": "^1.0.3", + "postcss-value-parser": "^4.1.0" + } + }, + "node_modules/@react-pdf/textkit": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-4.4.1.tgz", + "integrity": "sha512-Jl9wdTqIvJ5pX+vAGz0EOhP7ut5Two9H6CzTKo/YYPeD79cM2yTXF3JzTERBC28y7LR0Waq9D2LHQjI+b/EYUQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "2.2.1", + "bidi-js": "^1.0.2", + "hyphen": "^1.6.4", + "unicode-properties": "^1.4.1" + } + }, + "node_modules/@react-pdf/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.5.0.tgz", + "integrity": "sha512-XsVRkt0hQ60I4e3leAVt+aZR3KJCaJd179BfJHAv4F4x6Vq3yqkry8lcbUWKGKDw1j3/8sW4FsgGR41SFvsG9A==", + "license": "MIT" + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.5.tgz", + "integrity": "sha512-aeFA/s5NCG7NoJe/MhmwREJxRkDs0ZaSqt0MxhWUrwCf1UQXpwR87RROJEql0uAkLI6U7snBOYOcKw83ew3FPg==", + "license": "MIT", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@remix-run/router": { "version": "1.14.2", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz", @@ -3138,6 +3345,16 @@ "npm": ">=7.10.0" } }, + "node_modules/@swc/helpers": { + "version": "0.4.36", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.36.tgz", + "integrity": "sha512-5lxnyLEYFskErRPenYItLRSge5DjrJngYKdVjRSrWfza9G6KkgHEXi0vUZiyUeMU5JfXH1YnvXZzSp8ul88o2Q==", + "license": "Apache-2.0", + "dependencies": { + "legacy-swc-helpers": "npm:@swc/helpers@=0.4.14", + "tslib": "^2.4.0" + } + }, "node_modules/@testing-library/dom": { "version": "9.3.4", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", @@ -4005,6 +4222,12 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", + "license": "MIT" + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.9", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", @@ -4013,6 +4236,12 @@ "@types/jest": "*" } }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -4340,6 +4569,12 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==", + "license": "MIT" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -4942,12 +5177,41 @@ "node": ">= 0.6.0" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -5062,6 +5326,24 @@ "node": ">=8" } }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, "node_modules/browserslist": { "version": "4.22.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", @@ -5154,6 +5436,15 @@ "tslib": "^2.0.3" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001581", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", @@ -5324,6 +5615,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -5359,6 +5659,16 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -5532,6 +5842,15 @@ "node": ">=10" } }, + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5546,6 +5865,21 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "license": "ISC", + "engines": { + "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", @@ -5752,6 +6086,17 @@ "fastparse": "^1.1.2" } }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -6039,6 +6384,12 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", + "license": "MIT" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -6183,8 +6534,7 @@ "node_modules/emoji-regex": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" }, "node_modules/emojis-list": { "version": "3.0.0", @@ -7328,6 +7678,23 @@ } } }, + "node_modules/fontkit": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.2.tgz", + "integrity": "sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==", + "license": "MIT", + "dependencies": { + "@swc/helpers": "^0.4.2", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -7790,6 +8157,21 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/hsl-to-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz", + "integrity": "sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==", + "license": "MIT", + "dependencies": { + "hsl-to-rgb-for-reals": "^1.1.0" + } + }, + "node_modules/hsl-to-rgb-for-reals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz", + "integrity": "sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==", + "license": "ISC" + }, "node_modules/html-entities": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", @@ -7980,6 +8362,12 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyphen": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.4.tgz", + "integrity": "sha512-SejXzIpv9gOVdDWXd4suM1fdF1k2dxZGvuTdkOVLoazYfK7O4DykIQbdrvuyG+EaTNlXAGhMndtKrhykgbt0gg==", + "license": "ISC" + }, "node_modules/icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", @@ -8006,6 +8394,16 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -8078,8 +8476,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/internal-slot": { "version": "1.0.7", @@ -8491,6 +8888,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, "node_modules/is-weakmap": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", @@ -8568,6 +8971,15 @@ "set-function-name": "^2.0.1" } }, + "node_modules/jay-peg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jay-peg/-/jay-peg-1.0.2.tgz", + "integrity": "sha512-fyV3NVvv6pTys/3BTapBUGAWAuU9rM2gRcgijZHzptd5KKL+s+S7hESFN+wOsbDH1MzFwdlRAXi0aGxS6uiMKg==", + "license": "MIT", + "dependencies": { + "restructure": "^3.0.0" + } + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -8717,6 +9129,16 @@ "shell-quote": "^1.8.1" } }, + "node_modules/legacy-swc-helpers": { + "name": "@swc/helpers", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -9195,6 +9617,12 @@ "lz-string": "bin/bin.js" } }, + "node_modules/media-engine": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz", + "integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==", + "license": "MIT" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -9358,7 +9786,6 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -9402,6 +9829,26 @@ "tslib": "^2.0.3" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -9425,6 +9872,15 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-svg-path": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz", + "integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==", + "license": "MIT", + "dependencies": { + "svg-arc-to-cubic-bezier": "^3.0.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -9703,6 +10159,12 @@ "node": ">=6" } }, + "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/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -9741,6 +10203,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==", + "license": "MIT" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -9905,10 +10373,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", - "dev": true, + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "funding": [ { "type": "opencollective", @@ -9923,10 +10390,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -10152,8 +10620,7 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -10291,6 +10758,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -10420,6 +10896,52 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-loader-spinner": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/react-loader-spinner/-/react-loader-spinner-6.1.6.tgz", + "integrity": "sha512-x5h1Jcit7Qn03MuKlrWcMG9o12cp9SNDVHVJTNRi9TgtGPKcjKiXkou4NRfLAtXaFB3+Z8yZsVzONmPzhv2ErA==", + "license": "MIT", + "dependencies": { + "react-is": "^18.2.0", + "styled-components": "^6.1.2" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-loader-spinner/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-redux": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", + "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.3", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25", + "react": "^18.0", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-router": { "version": "6.21.3", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz", @@ -10564,6 +11086,30 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-persist": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", + "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", + "license": "MIT", + "peerDependencies": { + "redux": ">4.0.0" + } + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", @@ -10698,7 +11244,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -10709,6 +11254,12 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/reselect": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.0.tgz", + "integrity": "sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -10762,6 +11313,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restructure": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.1.tgz", + "integrity": "sha512-6neDpI/yE9eogQo22qmWwKIA9wFPRyYjQleDEh6zaNAf2ZPqLJYUvNBJBWEWNoBlCeQMQkvIOe2YI/K2GOag+g==", + "license": "MIT" + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -11164,6 +11721,12 @@ "node": ">=8" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -11213,6 +11776,21 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -11261,10 +11839,10 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -11368,7 +11946,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -11556,6 +12133,40 @@ "webpack": "^5.0.0" } }, + "node_modules/styled-components": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.11.tgz", + "integrity": "sha512-Ui0jXPzbp1phYij90h12ksljKGqF8ncGx+pjrNPsSPhbUUjWT2tD1FwGo2LF6USCnbrsIhNngDfodhxbegfEOA==", + "license": "MIT", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.38", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", + "license": "MIT" + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -11583,6 +12194,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-arc-to-cubic-bezier": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", + "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==", + "license": "ISC" + }, "node_modules/svg-pathdata": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", @@ -11691,6 +12308,12 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -11724,6 +12347,12 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -11905,6 +12534,16 @@ "node": ">=4" } }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", @@ -11914,6 +12553,22 @@ "node": ">=4" } }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "license": "MIT" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -11987,11 +12642,19 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utila": { "version": "0.4.0", @@ -12055,6 +12718,20 @@ "d3-timer": "^3.0.1" } }, + "node_modules/vite-compatible-readable-stream": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz", + "integrity": "sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -12076,6 +12753,12 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, "node_modules/webpack": { "version": "5.90.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz", @@ -12450,6 +13133,16 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -12630,6 +13323,12 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoga-layout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-2.0.1.tgz", + "integrity": "sha512-tT/oChyDXelLo2A+UVnlW9GU7CsvFMaEnd9kVFsaiCQonFAXd3xrHhkLYu+suwwosrAEQ746xBU+HvYtm1Zs2Q==", + "license": "MIT" } } } diff --git a/package.json b/package.json index c449c6a..a322d86 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,12 @@ "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", + "@fontsource/plus-jakarta-sans": "^5.0.20", "@ionic/react": "^7.8.1", "@mui/icons-material": "^5.15.6", "@mui/material": "^5.15.6", + "@react-pdf/renderer": "^3.4.4", + "@reduxjs/toolkit": "^2.2.5", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -20,8 +23,12 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-inlinesvg": "^4.1.1", + "react-loader-spinner": "^6.1.6", + "react-redux": "^9.1.2", "react-router-dom": "^6.21.3", - "recharts": "^2.12.3" + "recharts": "^2.12.3", + "redux": "^5.0.1", + "redux-persist": "^6.0.0" }, "scripts": { "start": "webpack serve --mode development", @@ -68,4 +75,4 @@ "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" } -} +} \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index 9dec11e..0b5ce28 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -4,17 +4,24 @@ import { BrowserRouter as Router } from 'react-router-dom'; import { FormDataProvider } from './context/FormDataContext'; import MainRoutes from './routes/routes'; import theme from './context/theme'; +import { Provider } from 'react-redux'; +import {store , persistor} from './store'; +import { PersistGate } from 'redux-persist/integration/react'; const App = () => { return ( - + + - + + ); }; + + export default App; diff --git a/src/actions/actions.js b/src/actions/actions.js new file mode 100644 index 0000000..36ba9fb --- /dev/null +++ b/src/actions/actions.js @@ -0,0 +1,13 @@ + +export const UPDATE = 'UPDATE'; + + +const update = payload => { + return{ + type: UPDATE, + payload, + }; + +} + +export {update}; \ No newline at end of file diff --git a/src/components/Counter.js b/src/components/Counter.js new file mode 100644 index 0000000..c4d450b --- /dev/null +++ b/src/components/Counter.js @@ -0,0 +1,26 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { increment, decrement } from '../actions/actions'; + +const Counter = ({ count, increment, decrement }) => { + return ( +
+

Count: {count}

+ + +
+ ); +}; + +// Map state to props +const mapStateToProps = state => ({ + count: state.counter.count +}); + +// Map dispatch to props +const mapDispatchToProps = { + increment, + decrement +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Counter); diff --git a/src/components/CounterItem/counteritem.jsx b/src/components/CounterItem/counteritem.jsx index e6a28ad..e3c906f 100644 --- a/src/components/CounterItem/counteritem.jsx +++ b/src/components/CounterItem/counteritem.jsx @@ -29,7 +29,7 @@ const CounterItem = ({ label, count, incrementValue, decrementValue, setCount }) }} style={{ margin: '0 10px', - width: '100px' + width: '122px' }} /> diff --git a/src/components/CounterQuestion/counterquestion.jsx b/src/components/CounterQuestion/counterquestion.jsx index 734a068..7047c14 100644 --- a/src/components/CounterQuestion/counterquestion.jsx +++ b/src/components/CounterQuestion/counterquestion.jsx @@ -7,7 +7,7 @@ const CounterQuestion = ({ question, label = null, popup = null, content, state, return (
- {question} + {question} {popup && }
{label && {label}} diff --git a/src/components/Heating/HeatComponent/heat.jsx b/src/components/Heating/HeatComponent/heat.jsx index 77882af..e8114c2 100644 --- a/src/components/Heating/HeatComponent/heat.jsx +++ b/src/components/Heating/HeatComponent/heat.jsx @@ -235,9 +235,7 @@ const Heat = (props) => { { values: 'Wood Fireplace', label: 'Fireplace', icon: Fireplace }, ] - useEffect(() => { - setHeat(''); - }, [source]); + return ( <> diff --git a/src/components/HomeType/OwnerTypeComponent/ownerType.jsx b/src/components/HomeType/OwnerTypeComponent/ownerType.jsx index 937fce7..64850f1 100644 --- a/src/components/HomeType/OwnerTypeComponent/ownerType.jsx +++ b/src/components/HomeType/OwnerTypeComponent/ownerType.jsx @@ -12,5 +12,6 @@ const OwnerType = ({ owner, setOwner }) => { /> ); }; - + export default OwnerType; + \ No newline at end of file diff --git a/src/components/Navbar/navbar.css b/src/components/Navbar/navbar.css index 704a47e..c201755 100644 --- a/src/components/Navbar/navbar.css +++ b/src/components/Navbar/navbar.css @@ -78,18 +78,22 @@ user-select: none; border-radius: 20px; border-width: 2px; + color: lightgray; } .list-item-text { user-select: none; + } .list-item.clickable { /* Add your styles for clickable list items here */ cursor: pointer; + color: black; } .list-item.clickable:hover { border-color: teal; - border-style: solid; /* Add this line */ + background-color: lightblue; + } diff --git a/src/components/Navbar/navbar.jsx b/src/components/Navbar/navbar.jsx index bc4cf92..ad9cdd3 100644 --- a/src/components/Navbar/navbar.jsx +++ b/src/components/Navbar/navbar.jsx @@ -54,7 +54,7 @@ const Navbar = ({ index, handleClick }) => { primary={step.text} primaryTypographyProps={{ style: { - color: i === index ? 'black' : 'lightgray', + color: i === index ? 'black' : 'inherit', fontWeight: i === index ? 'bold' : 'normal' } }} diff --git a/src/components/PopupHint/popup.jsx b/src/components/PopupHint/popup.jsx index 32ae46b..d89acea 100644 --- a/src/components/PopupHint/popup.jsx +++ b/src/components/PopupHint/popup.jsx @@ -24,7 +24,7 @@ const PopupHint = ({ content }) => { variant="contained" color="primary" onClick={handleClick} - style={{ minWidth: 'auto', width: '40px', height: '40px', borderRadius: '50%' }} + style={{ minWidth: 'auto', width: '20px', height: '20px', borderRadius: '50%', backgroundColor:'inherit',boxShadow:'none', marginBottom:'30px'}} > diff --git a/src/components/Results/EnergyScore/calcbutton.jsx b/src/components/Results/EnergyScore/calcbutton.jsx index 98fe072..fec676a 100644 --- a/src/components/Results/EnergyScore/calcbutton.jsx +++ b/src/components/Results/EnergyScore/calcbutton.jsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { Button, Dialog, DialogTitle, DialogContent, Card, CardContent, Typography, Box, Grid } from '@mui/material'; import { IonIcon } from '@ionic/react'; import { star } from 'ionicons/icons'; - +import './energyScore.css'; const getScoreColor = (score) => { if (score < 50) { return 'darkred'; @@ -14,8 +14,8 @@ const getScoreColor = (score) => { }; const ScoreBlock = ({ score }) => ( - - Your Home's Clean Energy Score: + + Your Home's Clean Energy Score: {score} out of 100 Your score is based on the estimated CO2 emissions of your home. @@ -51,7 +51,7 @@ const ScoreDetailsCard = (props) => { return ( - + The Science Behind Your Score @@ -62,11 +62,11 @@ const ScoreDetailsCard = (props) => { - What we estimate: + What we estimate: - Your Location + Your Location - Zip Code: {zipCode} - State: {state} - Annual Heating Degree Days: {heatingDegreeDays} @@ -74,7 +74,7 @@ const ScoreDetailsCard = (props) => { - Average Ground Water Temp: {groundWaterTemp}° F - Your Home + Your Home - Home Volume: {homeVolume} ft³ - Air Changes per Hour (ACH): {airChangesPerHour} - Insulated Wall R Value: {wallRValue} @@ -101,13 +101,20 @@ const CalcButton = (props) => { setOpen(false); }; + const dialogStyle = { + // Add your custom styles here + borderRadius: '8px', + boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.2)', + }; + + return (
- + Calculation Guide: diff --git a/src/components/Results/EnergyScore/comparebutton.jsx b/src/components/Results/EnergyScore/comparebutton.jsx index 1d4441e..31901f6 100644 --- a/src/components/Results/EnergyScore/comparebutton.jsx +++ b/src/components/Results/EnergyScore/comparebutton.jsx @@ -3,7 +3,9 @@ import { DialogContent, Typography, Button, LinearProgress, Box, Dialog, DialogT import { home } from 'ionicons/icons'; import { IonIcon } from '@ionic/react'; -const ProgressBar = ({ label, value }) => ( +const ProgressBar = ({ label, value }) => { + const color1 = 'red'; + return(
{label} @@ -13,9 +15,10 @@ const ProgressBar = ({ label, value }) => ( variant="determinate" value={((value / 16000) * 100)} sx={{ width: '60%' }} + style={{color:'red', backgroundColor:color1}} /> -); +);} const CompareButton = (props) => { const [open, setOpen] = useState(false); @@ -39,16 +42,17 @@ const CompareButton = (props) => { onClose={handleClose} PaperProps={{ sx: { - width: '33vw', - maxWidth: '33vw', + width: '40vw', + maxWidth: '40vw', overflowX: 'hidden' } }} > - - See How You Compare! + + +
See How You Compare!
- +
diff --git a/src/components/Results/EnergyScore/energyScore.css b/src/components/Results/EnergyScore/energyScore.css new file mode 100644 index 0000000..0c7b2d1 --- /dev/null +++ b/src/components/Results/EnergyScore/energyScore.css @@ -0,0 +1,15 @@ +.viewEditBtn{ + text-decoration: none; + font: 18px; + font-weight: bold; + color: #2d2828; +} +.title{ + font-size: 30px!important; + text-align: center; + font-weight: bold!important; +} + +.type_bold{ + font-weight: bold!important; +} \ No newline at end of file diff --git a/src/components/Results/EnergyScore/energyscore.jsx b/src/components/Results/EnergyScore/energyscore.jsx index 285ab40..95141d2 100644 --- a/src/components/Results/EnergyScore/energyscore.jsx +++ b/src/components/Results/EnergyScore/energyscore.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Box, Typography, Grid, Card, CardContent } from '@mui/material'; import CalcButton from './calcbutton'; import CompareButton from './comparebutton'; @@ -6,16 +6,24 @@ import ViewEditButton from './vieweditbutton'; import ScoreRing from './scorering'; const EnergyScore = (props) => { - const score = Math.floor(100 * (props.avgHomeUS / (props.avgHomeUS + props.yourHomeValue))); - + let score = Math.floor(100 * (props.avgHomeUS / (props.avgHomeUS + props.yourHomeValue))); + const [scoretext, setScoretext] = useState(''); + useEffect(() => { + if (score<25)setScoretext('Bad'); + else if (score<50) setScoretext('OK'); + else if (score<75) setScoretext('Good'); + else scoretext = setScoretext ('Awesome'); + }, [score]); + + return ( - + Results - + Your Home's Clean Energy Score:
{ }} >
- +
Score is based on the estimated CO2 emissions of your home
diff --git a/src/components/Results/EnergyScore/vieweditbutton.jsx b/src/components/Results/EnergyScore/vieweditbutton.jsx index 0a3cdb8..83fda52 100644 --- a/src/components/Results/EnergyScore/vieweditbutton.jsx +++ b/src/components/Results/EnergyScore/vieweditbutton.jsx @@ -3,6 +3,7 @@ import { Button, Dialog, DialogTitle, DialogContent, Typography, Box, Grid } fro import { FormDataContext } from '../../../context/FormDataContext'; import { pencil } from 'ionicons/icons'; import { IonIcon } from '@ionic/react'; +import './energyScore.css'; const ViewEditButton = () => { const { formData } = useContext(FormDataContext); @@ -23,12 +24,12 @@ const ViewEditButton = () => { View/Edit Answers - Your Survey Answers: + Your Survey Answers: - Home Type: + Home Type: Owner: {formData.owner} @@ -37,7 +38,7 @@ const ViewEditButton = () => { - Location: + Location: Zipcode: {formData.zipcode} @@ -45,7 +46,7 @@ const ViewEditButton = () => { - Home Size: + Home Size: Size: {formData.homeSize} @@ -57,7 +58,7 @@ const ViewEditButton = () => { - Windows: + Windows: Windows: {formData.windows} @@ -67,7 +68,7 @@ const ViewEditButton = () => { - Insulation: + Insulation: Insulation: {formData.insulation.join(' ')} @@ -76,7 +77,7 @@ const ViewEditButton = () => { - Heating: + Heating: Heating: {formData.primaryHeat} @@ -85,7 +86,7 @@ const ViewEditButton = () => { - Secondary Heating: + Secondary Heating: {formData.secondaryHeating ? ( @@ -100,7 +101,7 @@ const ViewEditButton = () => { - Cooling: + Cooling: {formData.hasAirCond ? ( @@ -114,7 +115,7 @@ const ViewEditButton = () => { - Water Heater: + Water Heater: Water Heater: {formData.waterHeater} @@ -123,7 +124,7 @@ const ViewEditButton = () => { - Lighting + Lighting Lighting: {formData.efficiency} @@ -131,7 +132,7 @@ const ViewEditButton = () => { - Appliances: + Appliances: {Object.keys(formData.kitchen).map((appliance, index) => ( @@ -148,7 +149,7 @@ const ViewEditButton = () => { - Energy: + Energy: Energy: {formData.energy} diff --git a/src/components/Results/Header/header.jsx b/src/components/Results/Header/header.jsx index 6996d25..07c8ec9 100644 --- a/src/components/Results/Header/header.jsx +++ b/src/components/Results/Header/header.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import logo from './logo.png' import { AppBar, Toolbar, IconButton } from '@mui/material'; @@ -6,10 +7,13 @@ const Header = () => { return ( - - - logo - + +
+ + logo + +
Zwell
+
diff --git a/src/components/Results/Header/logo.png b/src/components/Results/Header/logo.png new file mode 100644 index 0000000..8f9ad0b Binary files /dev/null and b/src/components/Results/Header/logo.png differ diff --git a/src/components/Results/IndividualScore/IndividualScore.css b/src/components/Results/IndividualScore/IndividualScore.css new file mode 100644 index 0000000..96d1410 --- /dev/null +++ b/src/components/Results/IndividualScore/IndividualScore.css @@ -0,0 +1,3 @@ +.Card{ + min-height: "177.4px"; +} \ No newline at end of file diff --git a/src/components/Results/PdfGenerator/Awesome.png b/src/components/Results/PdfGenerator/Awesome.png new file mode 100644 index 0000000..78f7f42 Binary files /dev/null and b/src/components/Results/PdfGenerator/Awesome.png differ diff --git a/src/components/Results/PdfGenerator/No.png b/src/components/Results/PdfGenerator/No.png new file mode 100644 index 0000000..dceb503 Binary files /dev/null and b/src/components/Results/PdfGenerator/No.png differ diff --git a/src/components/Results/PdfGenerator/SurveyAnswer.js b/src/components/Results/PdfGenerator/SurveyAnswer.js new file mode 100644 index 0000000..aa708b0 --- /dev/null +++ b/src/components/Results/PdfGenerator/SurveyAnswer.js @@ -0,0 +1,104 @@ +import React, { useState, useContext } from 'react'; +import { Page,Text, Document, PDFDownloadLink,StyleSheet} from "@react-pdf/renderer" +import { fontSize } from '@mui/system'; + +// Define stylesheet +const styles = StyleSheet.create({ + page: { + flexDirection: 'column', + backgroundColor: '#E4E4E4', + padding: 10, + }, + title: { + fontSize: 20, + marginBottom: 10, + padding: 10 + }, + text: { + marginBottom: 5, + fontSize: 15, + //padding: 20, + marginLeft: 30 + }, +}); + +const SurveyAnswer = (props) => { + const formData = props.formData; + const MyDocument = () => ( + + + Your Survey Answers + + Home Type: + Owner: {formData.owner} + Built: {formData.homeBuilt} + + Location: + Zipcode: {formData.zipcode} + + Home Size: + Size: {formData.homeSize} + Bedrooms: {formData.rooms.Bedrooms} + Bathrooms: {formData.rooms.Bathrooms} + Kitchens: {formData.rooms.Kitchens} + Basements: {formData.layout.basements} + + Windows: + Windows: {formData.windows} + Panes: {formData.panes} + Treatments: {formData.treatments} + + Insulation: + Windows: {formData.windows} + Panes: {formData.panes} + Treatments: {formData.treatments} + + Heating: + Heating: {formData.primaryHeat} + Heating Source: {formData.primarySource} + + Secondary Heating: + {formData.secondaryHeating ? ( + <> + Secondary Heating: {formData.secondaryHeating} + Heating Type: {formData.secondaryHeatingType} + + ) : ( + No Secondary Heating + )} + + Cooling: + {formData.hasAirCond ? ( + Cooling: {formData.coolingSystem} + ) : ( + No Cooling + )} + + Water Heater: + Water Heater: {formData.waterHeater} + Heating Type: {formData.fuelSource} + + Lighting: + Lighting: {formData.efficiency} + + Appliances: + {Object.keys(formData.kitchen).map((appliance, index) => ( + + {appliance}: {formData.kitchen[appliance]} + + ))} + + Energy: + Energy: {formData.energy} + + + + ); + console.log(formData); + + return ( + + ); +}; + +export default SurveyAnswer; \ No newline at end of file diff --git a/src/components/Results/PdfGenerator/Yes.png b/src/components/Results/PdfGenerator/Yes.png new file mode 100644 index 0000000..ec9f5c5 Binary files /dev/null and b/src/components/Results/PdfGenerator/Yes.png differ diff --git a/src/components/Results/PdfGenerator/caclulationguide.js b/src/components/Results/PdfGenerator/caclulationguide.js new file mode 100644 index 0000000..9e23dc7 --- /dev/null +++ b/src/components/Results/PdfGenerator/caclulationguide.js @@ -0,0 +1,96 @@ +import React, { useState } from 'react'; +import { Page, Text, StyleSheet } from "@react-pdf/renderer" + +// Define stylesheet +const styles = StyleSheet.create({ + page: { + flexDirection: 'column', + backgroundColor: '#E4E4E4', + padding: 10, + }, + title: { + fontSize: 24, + marginBottom: 10, + padding: 10 + }, + mtitle: { + fontSize: 20, + marginBottom: 10, + marginLeft: 20 + }, + text: { + marginBottom: 5, + fontSize: 15, + //padding: 20, + marginLeft: 30 + }, +}); + + +const CalculationGuide = (props) => { + + const score = props.score; + const { + zipCode, + state, + solarIndex, + heatingDegreeDays, + coolingDegreeDays, + groundWaterTemp, + homeVolume, + airChangesPerHour, + wallRValue, + atticRValue, + glazingPercentage, + heatLoss, + heatGain + } = props.data.details; + + let color = 'red'; + if(score < 50) color ='red'; + else if(score<100) color ='yellow'; + else scorecolor = color ='green'; + + const MyDocument = () => ( + + + Calculation Guide + + {score} out of 100 + Your score is based on the estimated CO2 emissions of your home + 0 = the highest possible emissions + 50 = an average home + 100 = a zero-emissions home + The Science Behind Your Score: + Many things go into estimating the CO₂ emissions of a home - the size of your home, the outside temperature through the year, the materials and insulation in your home, and much more! Here's a look at what we estimated some of those factors to be based on your answers. + + What we estimate + + Your location + - Zipcode: {zipCode} + - State: {state} + - Annual Heating Degree Days: {heatingDegreeDays} + - Annual Cooling Degree Days: {coolingDegreeDays} + - Average Ground Water Temp: {groundWaterTemp} + + Your Home + - Home Volume: {homeVolume} + - Air Changes per Hour (ACH): {airChangesPerHour} + - Insulated Wall R Value: {wallRValue} + - Insulated Attic/Roof R Value: {atticRValue} + - Glazing Percentage: {glazingPercentage} + - Annual BTUs of Heat Loss: {heatLoss} + - Annual BTUs of Solar Heat Gain: {heatGain} + + + + + ); + console.log(props.data); + + return ( + + ); +}; + +export default CalculationGuide; \ No newline at end of file diff --git a/src/components/Results/PdfGenerator/content.js b/src/components/Results/PdfGenerator/content.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Results/PdfGenerator/pdfgenerator.js b/src/components/Results/PdfGenerator/pdfgenerator.js new file mode 100644 index 0000000..377d267 --- /dev/null +++ b/src/components/Results/PdfGenerator/pdfgenerator.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { Page,Text, Document, PDFDownloadLink,Image} from "@react-pdf/renderer" +import SurveyAnswer from './SurveyAnswer'; +import SaveResultsBox from '../SaveComponent/save'; +import ResultPage from './resultpage'; +import CalculationGuide from './caclulationguide'; + +const PDFGenerator = (props) => { + const imageData =props.imageData; + const MyDocument = () => ( + + + + + + ); + + return ( +
+ } fileName="myDocument.pdf"> + + +
+ ); +}; + +export default PDFGenerator; \ No newline at end of file diff --git a/src/components/Results/PdfGenerator/resultpage.js b/src/components/Results/PdfGenerator/resultpage.js new file mode 100644 index 0000000..9e7a67f --- /dev/null +++ b/src/components/Results/PdfGenerator/resultpage.js @@ -0,0 +1,77 @@ +import React, { useState, useContext } from 'react'; +import { Page,Text, Document, PDFDownloadLink,StyleSheet, Image} from "@react-pdf/renderer" +import { fontSize } from '@mui/system'; +import { Science } from '@mui/icons-material'; +import { IonIcon } from '@ionic/react'; +// Define stylesheet +const styles = StyleSheet.create({ + page: { + flexDirection: 'column', + backgroundColor: '#E4E4E4', + padding: 10, + }, + title: { + fontSize: 20, + marginBottom: 20, + padding: 10 + }, + text: { + marginBottom: 10, + fontSize: 15, + //padding: 20, + marginLeft: 30 + }, +}); + + +const ResultPage = (props) => { + + const data = props.data; + + const gradeColors = { + 'A+': 'green', + 'A-': 'green', + 'B+': 'gold', + 'B-': 'gold', + 'C+': 'red', + 'C-': 'red', + 'D+': 'red', + 'D-': 'red', + 'F': 'black' + }; + const MyDocument = () => ( + + + Results + + + Your Home's Clean Energy Score: + Score: {props.score} + + {data.grades && data.grades.map((score) => ( + <> + + {score.title} + Grade: {score.grade} + + {/* {score.content.map((item) => { + ( + <> + {item.title} + + )})} */} + + + ))} + + + + + ); + + return ( + + ); +}; + +export default ResultPage; \ No newline at end of file diff --git a/src/components/Submit/submit.jsx b/src/components/Submit/submit.jsx index cfa4f1e..10a7a84 100644 --- a/src/components/Submit/submit.jsx +++ b/src/components/Submit/submit.jsx @@ -1,16 +1,19 @@ import React, { useContext } from 'react'; import Button from '@mui/material/Button'; import { FormDataContext } from '../../context/FormDataContext'; - +import { useSelector, useDispatch } from 'react-redux'; +import { update } from '../../actions/actions'; const SubmitButton = (props) => { - const { updateFormData } = useContext(FormDataContext); + + const dispatch = useDispatch(); const { handleNext } = props; const handleSubmit = () => { const validatedData = handleNext(); if (validatedData) { - updateFormData(validatedData); + dispatch(update(validatedData)); } + }; return ( @@ -19,7 +22,8 @@ const SubmitButton = (props) => { style={{ marginTop: '40px', width: '100px', - height: '50px' + height: '50px', + marginBottom: '50px' }} > Next diff --git a/src/components/TextQuestion/textquestion.jsx b/src/components/TextQuestion/textquestion.jsx index 16597fe..59e1f3d 100644 --- a/src/components/TextQuestion/textquestion.jsx +++ b/src/components/TextQuestion/textquestion.jsx @@ -14,9 +14,9 @@ const TextQuestion = ({ question, subtext = null, popup = null, label, value, se }; return ( -
-
- {question} +
+
+ {question} {popup && }
{subtext && {subtext}} diff --git a/src/context/FormDataContext.jsx b/src/context/FormDataContext.jsx index af5c4f1..e0fb8af 100644 --- a/src/context/FormDataContext.jsx +++ b/src/context/FormDataContext.jsx @@ -1,5 +1,4 @@ import React, { createContext, useState, useEffect } from 'react'; - export const FormDataContext = createContext(); export const FormDataProvider = ({ children }) => { diff --git a/src/pages/Appliances.jsx b/src/pages/Appliances.jsx index 065101c..0502740 100644 --- a/src/pages/Appliances.jsx +++ b/src/pages/Appliances.jsx @@ -3,9 +3,9 @@ import { Kitchen, Laundry } from '../components/Appliances'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; import { FormDataContext } from '../context/FormDataContext'; - +import { useSelector } from 'react-redux'; const Appliances = (props) => { - const { formData } = useContext(FormDataContext); + const formData = useSelector(state=>state.formdatacontext); const [kitchen, setKitchen] = useState( formData.kitchen || { diff --git a/src/pages/Cooling.jsx b/src/pages/Cooling.jsx index bb98543..f82ff5b 100644 --- a/src/pages/Cooling.jsx +++ b/src/pages/Cooling.jsx @@ -2,14 +2,13 @@ import React, { useContext, useState } from 'react'; import { CoolingSystem, HasAirCond, InstallationYear } from '../components/Cooling'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; const Cooling = (props) => { - const { formData } = useContext(FormDataContext); - + const formData = useSelector(state=>state.formdatacontext); const [hasAirCond, setHasAirCond] = useState(formData.hasAirCond || 'No'); const [coolingInstallYear, setCoolingInstallYear] = useState(formData.coolingInstallYear || ''); - const [coolingSystem, setCoolingSystem] = useState(formData.airCondSystem || ''); + const [coolingSystem, setCoolingSystem] = useState(formData.coolingSystem || ''); const [error, setError] = useState(null); const validateAndProceed = () => { diff --git a/src/pages/Energy.jsx b/src/pages/Energy.jsx index 5b79064..fb9e9ba 100644 --- a/src/pages/Energy.jsx +++ b/src/pages/Energy.jsx @@ -2,10 +2,10 @@ import React, { useState, useContext } from 'react'; import { GreenEnergy, Slider } from '../components/Energy'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; const Energy = (props) => { - const { formData } = useContext(FormDataContext); + const formData = useSelector(state=>state.formdatacontext); const [energy, setEnergy] = useState(formData.energy || []); const [slider, setSlider] = useState(formData.slider || 0); const [error, setError] = useState(null); diff --git a/src/pages/Heating.jsx b/src/pages/Heating.jsx index b7ee8a6..cd19081 100644 --- a/src/pages/Heating.jsx +++ b/src/pages/Heating.jsx @@ -2,11 +2,10 @@ import React, { useContext, useState } from 'react'; import { HasSecondary, Heat, HeatedFloors, InstallationYear, Source } from '../components/Heating'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; const Heating = (props) => { - const { formData } = useContext(FormDataContext); - + const formData = useSelector(state=>state.formdatacontext); const [primaryHeat, setPrimaryHeat] = useState(formData.primaryHeat || ''); const [primarySource, setPrimarySource] = useState(formData.primarySource || ''); const [heatInstallYear, setHeatInstallYear] = useState(formData.heatInstallYear || ''); @@ -23,6 +22,7 @@ const Heating = (props) => { } else { setError(null); props.handleNext(); + console.log(primaryHeat); return { primaryHeat, primarySource, diff --git a/src/pages/HomeSize.jsx b/src/pages/HomeSize.jsx index 15aacc4..6cadd6a 100644 --- a/src/pages/HomeSize.jsx +++ b/src/pages/HomeSize.jsx @@ -3,11 +3,9 @@ import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; import '../styles/page.css'; import { SqrFeet, Rooms, Layout, CrawlSpace } from '../components/HomeSize'; -import { FormDataContext } from '../context/FormDataContext'; - +import { useSelector } from 'react-redux'; const HomeSize = (props) => { - const { formData } = useContext(FormDataContext); - + const formData = useSelector(state=>state.formdatacontext); const [sqrfeet, setSqrfeet] = useState(formData.sqrfeet || ''); const [rooms, setRooms] = useState( formData.rooms || { diff --git a/src/pages/HomeType.jsx b/src/pages/HomeType.jsx index 8896159..14c540c 100644 --- a/src/pages/HomeType.jsx +++ b/src/pages/HomeType.jsx @@ -3,10 +3,10 @@ import { OwnerType, HomeSize, HomeBuilt } from '../components/HomeType'; import SubmitButton from '../components/Submit'; import '../styles/page.css'; import { FormDataContext } from '../context/FormDataContext'; - +import { useDispatch, useSelector } from 'react-redux'; const HomeType = (props) => { - const { formData } = useContext(FormDataContext); - + const formData = useSelector(state=>state.formdatacontext); + console.log(formData); const [owner, setOwner] = useState(formData.owner || ''); const [homeSize, setHomeSize] = useState(formData.homeSize || ''); const [homeBuilt, setHomeBuilt] = useState(formData.homeBuilt || ''); diff --git a/src/pages/Insulation.jsx b/src/pages/Insulation.jsx index 68be38c..60d0b0d 100644 --- a/src/pages/Insulation.jsx +++ b/src/pages/Insulation.jsx @@ -2,11 +2,10 @@ import React, { useState, useContext } from 'react'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; import { Siding, HomeInsulation } from '../components/Insulation'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; const Insulation = (props) => { - const { formData } = useContext(FormDataContext); - + const formData = useSelector(state=>state.formdatacontext); const [siding, setSiding] = useState(formData.siding || ''); const [insulation, setInsulation] = useState(formData.insulation || ''); const [error, setError] = useState(null); diff --git a/src/pages/Lighting.jsx b/src/pages/Lighting.jsx index ea77852..644e460 100644 --- a/src/pages/Lighting.jsx +++ b/src/pages/Lighting.jsx @@ -2,10 +2,10 @@ import React, { useState, useContext } from 'react'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; import Efficiency from '../components/Lighting'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; const Lighting = (props) => { - const { formData } = useContext(FormDataContext); + const formData = useSelector(state=>state.formdatacontext); const [efficiency, setEfficiency] = useState(formData.efficiency || ''); const [error, setError] = useState(null); diff --git a/src/pages/Location.jsx b/src/pages/Location.jsx index 5d6f99a..610b168 100644 --- a/src/pages/Location.jsx +++ b/src/pages/Location.jsx @@ -1,37 +1,49 @@ -import React, { useState, useContext } from 'react'; -import axios from 'axios'; +import React, { useEffect, useState } from 'react'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; import Button from '@mui/material/Button'; import { CircularProgress } from '@mui/material'; import { Zipcode, ZipData } from '../components/Location'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; import { validateZipCode } from '../helpers/api'; -import '../styles/page.css'; const Location = (props) => { - const { formData } = useContext(FormDataContext); + const formData = useSelector(state => state.formdatacontext); const [zipcode, setZipcode] = useState(formData.zipcode || ''); const [hidden, hide] = useState(true); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); - const validateAndProceed = async () => { + + useEffect(() => { + + const handleZipcodeValidation = async () => { + if (zipcode) { + console.log("starting"); + setLoading(true); + if ((await validateZipCode(zipcode))) { // if valid + setLoading(false); + setError(null); + } else { + await findValidZipCode(zipcode) + } + } + }; + + handleZipcodeValidation() + }, [zipcode]); + + const validateAndProceed = () => { + if (!zipcode) { setError('All fields must be filled out'); return null; - } else { - const result = await validateZipCode(zipcode); - if (result) { - setLoading(false); - setError(null); - setZipcode(zipcode); - props.handleNext(); - return { zipcode }; - } else { - findValidZipCode(zipcode); - } + } else if (!loading && !error) { + props.handleNext(); + console.log(`RESULT = ${zipcode}`); + return { zipcode }; } + }; const findValidZipCode = async (originalZip) => { @@ -67,10 +79,10 @@ const Location = (props) => { {loading && } {error &&
{error}
} - {hidden ? null : } - {hidden ? null : } + {!hidden && } + {!hidden && }
); }; -export default Location; +export default Location; \ No newline at end of file diff --git a/src/pages/Results.jsx b/src/pages/Results.jsx index a50ae29..d0d2c43 100644 --- a/src/pages/Results.jsx +++ b/src/pages/Results.jsx @@ -5,13 +5,13 @@ import { FormDataContext } from '../context/FormDataContext'; import handleCalculation from '../helpers/calculation.js'; import '../styles/page.css'; import Header from '../components/Results/Header'; -import { jsPDF } from 'jspdf' -import html2canvas from 'html2canvas'; - +import { Oval } from 'react-loader-spinner'; +import PDFGenerator from '../components/Results/PdfGenerator/pdfgenerator.js'; +import { useSelector } from 'react-redux'; const Results = () => { - const { formData } = useContext(FormDataContext); + const formData = useSelector(state=>state.formdatacontext); const [ data, setData ] = useState(null); - const inputRef = useRef(null) + const inputRef = useRef(null); useEffect(() => { const calculate = async () => { @@ -21,24 +21,30 @@ const Results = () => { calculate(); }, [formData]); + - const saveToPdf = () => { - console.log("saving"); - html2canvas(inputRef.current).then((canvas) => { - const imgData = canvas.toDataURL("image/png"); - const pdf = new jsPDF("landscape", "mm", "a4") - const width = pdf.internal.pageSize.getWidth(); - const height = pdf.internal.pageSize.getHeight(); - pdf.addImage(imgData, "JPEG", 0, 0, width, height); - pdf.save("download.pdf"); - }) - } - if (data === null) { - return
Loading...
; + if (!data) { + return( +
+ +
Loading...
+
+ ) } + const score = Math.floor(100 * (16000 / (data.co2_total + data.avgHome))); return ( -
+
@@ -47,13 +53,14 @@ const Results = () => { avgHomeState={data.avgHome} avgHomeUS={16000} details={data.details} + score = {score} /> - + {data.grades && data.grades.map((score, index) => ( - - + { rows={score.rows} current={score.current} recommended={score.recommended} + minHeight = {"300px"} /> ))} - - + + diff --git a/src/pages/WaterHeating.jsx b/src/pages/WaterHeating.jsx index e75c7fe..72bed8e 100644 --- a/src/pages/WaterHeating.jsx +++ b/src/pages/WaterHeating.jsx @@ -2,10 +2,10 @@ import React, { useContext, useEffect, useState } from 'react'; import { InstallationYear, Source, WaterHeater } from '../components/WaterHeater'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; const WaterHeating = (props) => { - const { formData } = useContext(FormDataContext); + const formData = useSelector(state=>state.formdatacontext); const [waterHeating, setWaterHeating] = useState(formData.waterHeating || ''); const [fuelSource, setFuelSource] = useState(formData.fuelSource || ''); diff --git a/src/pages/Windows.jsx b/src/pages/Windows.jsx index 5403495..a6dba1e 100644 --- a/src/pages/Windows.jsx +++ b/src/pages/Windows.jsx @@ -2,10 +2,10 @@ import React, { useState, useContext } from 'react'; import BackButton from '../components/BackButton'; import SubmitButton from '../components/Submit'; import { WindowConverage, Panes, Sun, Treatments } from '../components/Windows'; -import { FormDataContext } from '../context/FormDataContext'; +import { useSelector } from 'react-redux'; const Windows = (props) => { - const { formData } = useContext(FormDataContext); + const formData = useSelector(state=>state.formdatacontext); const [windows, setWindows] = useState(formData.windows || ''); const [panes, setPanes] = useState(formData.panes || ''); diff --git a/src/reducers/formdatareducer.js b/src/reducers/formdatareducer.js new file mode 100644 index 0000000..3d6cc5d --- /dev/null +++ b/src/reducers/formdatareducer.js @@ -0,0 +1,16 @@ +import { UPDATE } from '../actions/actions.js'; + +// Reducer function +const formdataReducer = (state = [], action) => { + + switch (action.type) { + case UPDATE: + return { ...state, ...action.payload }; + default: + return state; + } +}; + +export default formdataReducer; + + diff --git a/src/reducers/index.js b/src/reducers/index.js new file mode 100644 index 0000000..84ba6c7 --- /dev/null +++ b/src/reducers/index.js @@ -0,0 +1,8 @@ +import { combineReducers } from 'redux'; +import formdataReducer from './formdatareducer'; + +const rootReducer = combineReducers({ + formdatacontext: formdataReducer +}); + +export default rootReducer; diff --git a/src/store.js b/src/store.js new file mode 100644 index 0000000..9d70ac1 --- /dev/null +++ b/src/store.js @@ -0,0 +1,22 @@ +import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit"; +import rootReducer from "./reducers/index"; +import { persistStore, persistReducer } from 'redux-persist'; +import storage from 'redux-persist/lib/storage'; + +const persistConfig = { + key: 'root', + storage, +}; + +const persistedReducer = persistReducer(persistConfig, rootReducer); + +const store = configureStore({ + reducer: persistedReducer, + middleware: (getDefaultMiddleware) => getDefaultMiddleware({ + serializableCheck: false + }), +}); + +const persistor = persistStore(store); + +export { store, persistor }; \ No newline at end of file diff --git a/src/styles/page.css b/src/styles/page.css index b53e2e3..7d070b4 100644 --- a/src/styles/page.css +++ b/src/styles/page.css @@ -3,7 +3,7 @@ display: flex; flex-direction: column; align-items: center; - padding-bottom: 1.5%; + background-color: lightgray!important; } .component { @@ -19,4 +19,22 @@ color: red; font-size: 1.5rem; margin-top: 1rem; +} + +.spinner { + border: 4px solid rgba(0, 0, 0, 0.1); + border-left-color: #7983ff; + border-radius: 50%; + width: 50px; + height: 50px; + animation: spin 1s linear infinite; +} +.spinner-container { + position: relative; + width: 100%; + height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; } \ No newline at end of file diff --git a/src/styles/resultcard.css b/src/styles/resultcard.css new file mode 100644 index 0000000..0cd56b8 --- /dev/null +++ b/src/styles/resultcard.css @@ -0,0 +1,3 @@ +.Card { + min-height: 177.4px; +} \ No newline at end of file