diff --git a/package.json b/package.json index 0ae293b..2afaf2d 100755 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "axios": "^1.7.2", + "flutterwave-react-v3": "^1.3.2", "framer-motion": "^11.2.10", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d6a026..ed27c3c 100755 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: axios: specifier: ^1.7.2 version: 1.7.2 + flutterwave-react-v3: + specifier: ^1.3.2 + version: 1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) framer-motion: specifier: ^11.2.10 version: 11.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -44,7 +47,7 @@ importers: version: 18.3.0 '@vitejs/plugin-react': specifier: ^4.2.1 - version: 4.3.0(vite@5.2.12(sass@1.77.5)) + version: 4.3.0(vite@5.2.12(@types/node@22.2.0)(sass@1.77.5)) autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.38) @@ -68,7 +71,7 @@ importers: version: 3.4.3 vite: specifier: ^5.2.0 - version: 5.2.12(sass@1.77.5) + version: 5.2.12(@types/node@22.2.0)(sass@1.77.5) packages: @@ -354,6 +357,22 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -472,6 +491,19 @@ packages: cpu: [x64] os: [win32] + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -487,6 +519,21 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jsdom@20.0.1': + resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} + + '@types/node@22.2.0': + resolution: {integrity: sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==} + '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -496,6 +543,18 @@ packages: '@types/react@18.3.3': resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -505,16 +564,31 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + + acorn-globals@7.0.1: + resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.3: + resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} + engines: {node: '>=0.4.0'} + acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -534,6 +608,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -596,6 +674,9 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axios@0.21.4: + resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} + axios@1.7.2: resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} @@ -648,6 +729,10 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -687,9 +772,23 @@ packages: engines: {node: '>=4'} hasBin: true + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + data-urls@3.0.2: + resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} + engines: {node: '>=12'} + data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} @@ -711,6 +810,9 @@ packages: supports-color: optional: true + decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -740,6 +842,11 @@ packages: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} + domexception@4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + deprecated: Use your platform's native DOMException instead + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -752,6 +859,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + es-abstract@1.23.3: resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} engines: {node: '>= 0.4'} @@ -796,10 +907,19 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-plugin-react-hooks@4.6.2: resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} engines: {node: '>=10'} @@ -834,6 +954,11 @@ packages: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} @@ -885,6 +1010,12 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + flutterwave-react-v3@1.3.2: + resolution: {integrity: sha512-kFDNUQddrLsV1V4NkjP7qJ8byPWrAawHnagsYjW9dBGy3GyLzxgMUgZHW4/zYAK2DzMBrAmvT7jIKSTes8lx/g==} + peerDependencies: + react: ^15.0.0 || ^18.0.0 + react-dom: ^15.0.0 || ^18.0.0 + follow-redirects@1.15.6: resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} @@ -984,6 +1115,9 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -1017,6 +1151,22 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -1116,6 +1266,9 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -1164,6 +1317,27 @@ packages: resolution: {integrity: sha512-glPiBfKguqA7v8JsXO3iLjJWZ9FV1vNpoI0I9hI9Mnk5yetO9uPLSpiCEmiVijAssv2f54HpvtzvAHfhPieiDQ==} engines: {node: '>=14'} + jest-environment-jsdom@29.7.0: + resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jiti@1.21.1: resolution: {integrity: sha512-KMXpzEJMsOFyRj6ZpDTnnlJrdr9umUY+eut5vlRvjVixohitnRFIRTFw9MEu9zPlBxTHZo6xD5ftKYiQZuJYQw==} hasBin: true @@ -1175,6 +1349,15 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsdom@20.0.3: + resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} @@ -1286,6 +1469,9 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} + nwsapi@2.2.12: + resolution: {integrity: sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1340,6 +1526,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1423,16 +1612,26 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1464,6 +1663,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -1500,6 +1702,9 @@ packages: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1537,11 +1742,18 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sass@1.77.5: resolution: {integrity: sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==} engines: {node: '>=14.0.0'} hasBin: true + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -1573,10 +1785,22 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1633,6 +1857,9 @@ packages: resolution: {integrity: sha512-JJQWFXdxiMGC2j6ZGTYat5Z7NN9JORJBgHp0/joX9uPod+cRj0wr5H5VnWSNIz9JeAamQvYKaG7aFrGHIF9OEg==} engines: {node: '>= 4.7.0'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwindcss@3.4.3: resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} engines: {node: '>=14.0.0'} @@ -1656,6 +1883,14 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@3.0.0: + resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} + engines: {node: '>=12'} + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -1666,6 +1901,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -1689,6 +1928,13 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + undici-types@6.13.0: + resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + update-browserslist-db@1.0.16: resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true @@ -1698,6 +1944,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1729,6 +1978,26 @@ packages: terser: optional: true + w3c-xmlserializer@4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-url@11.0.0: + resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} + engines: {node: '>=12'} + which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -1764,6 +2033,25 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -2033,6 +2321,35 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.2.0 + jest-mock: 29.7.0 + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 22.2.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.2.0 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -2115,6 +2432,18 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true + '@sinclair/typebox@0.27.8': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@tootallnate/once@2.0.0': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.24.6 @@ -2138,6 +2467,26 @@ snapshots: '@types/estree@1.0.5': {} + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jsdom@20.0.1': + dependencies: + '@types/node': 22.2.0 + '@types/tough-cookie': 4.0.5 + parse5: 7.1.2 + + '@types/node@22.2.0': + dependencies: + undici-types: 6.13.0 + '@types/prop-types@15.7.12': {} '@types/react-dom@18.3.0': @@ -2149,25 +2498,52 @@ snapshots: '@types/prop-types': 15.7.12 csstype: 3.1.3 + '@types/stack-utils@2.0.3': {} + + '@types/tough-cookie@4.0.5': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react@4.3.0(vite@5.2.12(sass@1.77.5))': + '@vitejs/plugin-react@4.3.0(vite@5.2.12(@types/node@22.2.0)(sass@1.77.5))': dependencies: '@babel/core': 7.24.6 '@babel/plugin-transform-react-jsx-self': 7.24.6(@babel/core@7.24.6) '@babel/plugin-transform-react-jsx-source': 7.24.6(@babel/core@7.24.6) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.2.12(sass@1.77.5) + vite: 5.2.12(@types/node@22.2.0)(sass@1.77.5) transitivePeerDependencies: - supports-color + abab@2.0.6: {} + + acorn-globals@7.0.1: + dependencies: + acorn: 8.11.3 + acorn-walk: 8.3.3 + acorn-jsx@5.3.2(acorn@8.11.3): dependencies: acorn: 8.11.3 + acorn-walk@8.3.3: + dependencies: + acorn: 8.11.3 + acorn@8.11.3: {} + agent-base@6.0.2: + dependencies: + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -2187,6 +2563,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} any-promise@1.3.0: {} @@ -2279,6 +2657,12 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 + axios@0.21.4: + dependencies: + follow-redirects: 1.15.6 + transitivePeerDependencies: + - debug + axios@1.7.2: dependencies: follow-redirects: 1.15.6 @@ -2348,6 +2732,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + ci-info@3.9.0: {} + classnames@2.5.1: {} color-convert@1.9.3: @@ -2380,8 +2766,22 @@ snapshots: cssesc@3.0.0: {} + cssom@0.3.8: {} + + cssom@0.5.0: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + csstype@3.1.3: {} + data-urls@3.0.2: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 @@ -2404,6 +2804,8 @@ snapshots: dependencies: ms: 2.1.2 + decimal.js@10.4.3: {} + deep-is@0.1.4: {} define-data-property@1.1.4: @@ -2432,6 +2834,10 @@ snapshots: dependencies: esutils: 2.0.3 + domexception@4.0.0: + dependencies: + webidl-conversions: 7.0.0 + eastasianwidth@0.2.0: {} electron-to-chromium@1.4.789: {} @@ -2440,6 +2846,8 @@ snapshots: emoji-regex@9.2.2: {} + entities@4.5.0: {} + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 @@ -2562,8 +2970,18 @@ snapshots: escape-string-regexp@1.0.5: {} + escape-string-regexp@2.0.0: {} + escape-string-regexp@4.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -2650,6 +3068,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.11.3) eslint-visitor-keys: 3.4.3 + esprima@4.0.1: {} + esquery@1.5.0: dependencies: estraverse: 5.3.0 @@ -2701,6 +3121,19 @@ snapshots: flatted@3.3.1: {} + flutterwave-react-v3@1.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + axios: 0.21.4 + jest-environment-jsdom: 29.7.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - bufferutil + - canvas + - debug + - supports-color + - utf-8-validate + follow-redirects@1.15.6: {} for-each@0.3.3: @@ -2799,6 +3232,8 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + graceful-fs@4.2.11: {} + graphemer@1.4.0: {} has-bigints@1.0.2: {} @@ -2823,6 +3258,29 @@ snapshots: dependencies: function-bind: 1.1.2 + html-encoding-sniffer@3.0.0: + dependencies: + whatwg-encoding: 2.0.0 + + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + ignore@5.3.1: {} immutable@4.3.6: {} @@ -2911,6 +3369,8 @@ snapshots: is-path-inside@3.0.3: {} + is-potential-custom-element-name@1.0.1: {} + is-regex@1.1.4: dependencies: call-bind: 1.0.7 @@ -2963,6 +3423,48 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jest-environment-jsdom@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/jsdom': 20.0.1 + '@types/node': 22.2.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + jsdom: 20.0.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.24.6 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.7 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.2.0 + jest-util: 29.7.0 + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.2.0 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + jiti@1.21.1: {} js-tokens@4.0.0: {} @@ -2971,6 +3473,39 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@20.0.3: + dependencies: + abab: 2.0.6 + acorn: 8.11.3 + acorn-globals: 7.0.1 + cssom: 0.5.0 + cssstyle: 2.3.0 + data-urls: 3.0.2 + decimal.js: 10.4.3 + domexception: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.0 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.12 + parse5: 7.1.2 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + ws: 8.18.0 + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@2.5.2: {} json-buffer@3.0.1: {} @@ -3060,6 +3595,8 @@ snapshots: normalize-range@0.1.2: {} + nwsapi@2.2.12: {} + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -3125,6 +3662,10 @@ snapshots: dependencies: callsites: 3.1.0 + parse5@7.1.2: + dependencies: + entities: 4.5.0 + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -3187,6 +3728,12 @@ snapshots: prelude-ls@1.2.1: {} + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -3195,8 +3742,12 @@ snapshots: proxy-from-env@1.1.0: {} + psl@1.9.0: {} + punycode@2.3.1: {} + querystringify@2.2.0: {} + queue-microtask@1.2.3: {} react-dom@18.3.1(react@18.3.1): @@ -3224,6 +3775,8 @@ snapshots: react-is@16.13.1: {} + react-is@18.3.1: {} + react-refresh@0.14.2: {} react-router-dom@6.23.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -3267,6 +3820,8 @@ snapshots: es-errors: 1.3.0 set-function-name: 2.0.2 + requires-port@1.0.0: {} + resolve-from@4.0.0: {} resolve@1.22.8: @@ -3326,12 +3881,18 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 + safer-buffer@2.1.2: {} + sass@1.77.5: dependencies: chokidar: 3.6.0 immutable: 4.3.6 source-map-js: 1.2.0 + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -3369,8 +3930,17 @@ snapshots: signal-exit@4.1.0: {} + slash@3.0.0: {} + source-map-js@1.2.0: {} + source-map@0.6.1: + optional: true + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -3449,6 +4019,8 @@ snapshots: swiper@11.1.5: {} + symbol-tree@3.2.4: {} + tailwindcss@3.4.3: dependencies: '@alloc/quick-lru': 5.2.0 @@ -3492,6 +4064,17 @@ snapshots: dependencies: is-number: 7.0.0 + tough-cookie@4.1.4: + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@3.0.0: + dependencies: + punycode: 2.3.1 + ts-interface-checker@0.1.13: {} tslib@2.6.3: {} @@ -3500,6 +4083,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-detect@4.0.8: {} + type-fest@0.20.2: {} typed-array-buffer@1.0.2: @@ -3541,6 +4126,10 @@ snapshots: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + undici-types@6.13.0: {} + + universalify@0.2.0: {} + update-browserslist-db@1.0.16(browserslist@4.23.0): dependencies: browserslist: 4.23.0 @@ -3551,17 +4140,40 @@ snapshots: dependencies: punycode: 2.3.1 + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + util-deprecate@1.0.2: {} - vite@5.2.12(sass@1.77.5): + vite@5.2.12(@types/node@22.2.0)(sass@1.77.5): dependencies: esbuild: 0.20.2 postcss: 8.4.38 rollup: 4.18.0 optionalDependencies: + '@types/node': 22.2.0 fsevents: 2.3.3 sass: 1.77.5 + w3c-xmlserializer@4.0.0: + dependencies: + xml-name-validator: 4.0.0 + + webidl-conversions@7.0.0: {} + + whatwg-encoding@2.0.0: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@3.0.0: {} + + whatwg-url@11.0.0: + dependencies: + tr46: 3.0.0 + webidl-conversions: 7.0.0 + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 @@ -3620,6 +4232,12 @@ snapshots: wrappy@1.0.2: {} + ws@8.18.0: {} + + xml-name-validator@4.0.0: {} + + xmlchars@2.2.0: {} + yallist@3.1.1: {} yaml@2.4.3: {} diff --git a/src/App.jsx b/src/App.jsx index c05c95b..62836a6 100755 --- a/src/App.jsx +++ b/src/App.jsx @@ -5,6 +5,7 @@ import { Route, // Navigate, } from "react-router-dom"; +import { CardProvider } from "./context/CardContext"; // Updated import name import { SignupContextProvider } from "./context/SignupContext"; import Landing from "./components/landingPage/landingPage"; import EnrollPage from "./components/onboarding/Enroll"; @@ -19,6 +20,7 @@ import Dashboard from "./components/dashboard/dashbord/DashboardHome" import Eservice from "./components/E-service/Services"; import Tuition from "./components/dashboard/PayTuition/Tuition"; import Wallet from "./components/dashboard/wallet/Wallets"; +import TargetSavings from "./components/dashboard/TargetSavings/Target"; import "./index.css"; @@ -27,6 +29,7 @@ function App() { return ( + } /> @@ -55,6 +58,10 @@ function App() { path="/dashboard/wallet" element={isLoggedIn ? : } /> + : } + /> {/* } /> } /> @@ -62,6 +69,7 @@ function App() { } /> */} + ); } diff --git a/src/assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 1.png b/src/assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 1.png new file mode 100644 index 0000000..a089df6 Binary files /dev/null and b/src/assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 1.png differ diff --git a/src/assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 2.png b/src/assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 2.png new file mode 100644 index 0000000..50a8e4d Binary files /dev/null and b/src/assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 2.png differ diff --git a/src/assets/images/2151266604 (1) 1.png b/src/assets/images/2151266604 (1) 1.png new file mode 100644 index 0000000..7200fd1 Binary files /dev/null and b/src/assets/images/2151266604 (1) 1.png differ diff --git a/src/assets/images/Banner how to pay.png b/src/assets/images/Banner how to pay.png new file mode 100644 index 0000000..98d902f Binary files /dev/null and b/src/assets/images/Banner how to pay.png differ diff --git a/src/assets/images/Card 10.png b/src/assets/images/Card 10.png new file mode 100644 index 0000000..96a98be Binary files /dev/null and b/src/assets/images/Card 10.png differ diff --git a/src/assets/images/Card 7.png b/src/assets/images/Card 7.png new file mode 100644 index 0000000..0579a6f Binary files /dev/null and b/src/assets/images/Card 7.png differ diff --git a/src/assets/images/Cards.png b/src/assets/images/Cards.png new file mode 100644 index 0000000..3968fee Binary files /dev/null and b/src/assets/images/Cards.png differ diff --git a/src/assets/images/Group 56.png b/src/assets/images/Group 56.png new file mode 100644 index 0000000..c4e4fd5 Binary files /dev/null and b/src/assets/images/Group 56.png differ diff --git a/src/assets/images/Spinning wheel.png b/src/assets/images/Spinning wheel.png new file mode 100644 index 0000000..adea92f Binary files /dev/null and b/src/assets/images/Spinning wheel.png differ diff --git a/src/assets/images/Success checkmark.png b/src/assets/images/Success checkmark.png new file mode 100644 index 0000000..a10dc8c Binary files /dev/null and b/src/assets/images/Success checkmark.png differ diff --git a/src/assets/images/VectorX.png b/src/assets/images/VectorX.png new file mode 100644 index 0000000..d70f309 Binary files /dev/null and b/src/assets/images/VectorX.png differ diff --git a/src/components/dashboard/wallet/button.jsx b/src/components/dashboard/TargetSavings/Button.jsx similarity index 100% rename from src/components/dashboard/wallet/button.jsx rename to src/components/dashboard/TargetSavings/Button.jsx diff --git a/src/components/dashboard/TargetSavings/Completed.jsx b/src/components/dashboard/TargetSavings/Completed.jsx new file mode 100644 index 0000000..adae576 --- /dev/null +++ b/src/components/dashboard/TargetSavings/Completed.jsx @@ -0,0 +1,46 @@ +import Vector from "../../../assets/images/VectorX.png" +export default function Completed() { + return( +
+
+ +
+ +
+
+
+

$0.00

+

+ Balance left to Maturity +

+
+
+
+

Institution

+

Algonquin College

+
+
+

Description

+

First Semester Tuition

+
+
+

Maturity Amount

+

$760.00

+
+
+
+ ) +} \ No newline at end of file diff --git a/src/components/dashboard/TargetSavings/CreatePlan.jsx b/src/components/dashboard/TargetSavings/CreatePlan.jsx new file mode 100644 index 0000000..bbce423 --- /dev/null +++ b/src/components/dashboard/TargetSavings/CreatePlan.jsx @@ -0,0 +1,58 @@ +import React, { useState } from "react"; +import Coin from "../../../assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 1.png"; +import Coin1 from "../../../assets/images/151055041_b058e357-f1d4-48f6-8977-25b8bead6dcc-removebg-preview 2.png"; +import Image from "../../../assets/images/2151266604 (1) 1.png"; +import Ongoing from "./Ongoing"; +import Completed from "./Completed"; +import Tuition from "./PlanCreate"; +import Terminated from "./Terminated"; +import Button from "./Button"; + +export default function CreatePlan() { + const [showTuition, setTuition] = useState(false); + + const handleClick = () => { + console.log("Button clicked"); + setTuition(true); // Show Tuition component + }; + + return ( + <> + {!showTuition ? ( + <> +
+
+
+

+ Hedge Your Funds With
+ Target Savings +

+ +
+
+ coin + coin + coin +
+
+
+
+
+
+ +
+
+
+ + + + ) : ( +
+ +
+ )} + + ); +} diff --git a/src/components/dashboard/TargetSavings/Ongoing.jsx b/src/components/dashboard/TargetSavings/Ongoing.jsx new file mode 100644 index 0000000..487815a --- /dev/null +++ b/src/components/dashboard/TargetSavings/Ongoing.jsx @@ -0,0 +1,53 @@ +import Vector from "../../../assets/images/VectorX.png"; +import { React , useState } from "react"; +export default function Ongoing() { + + // const items = [ + // { instituition: "Institution", + + // } + // ] + return ( +
+
+ +
+ +
+
+
+

$760.00

+

+ Balance left to Maturity +

+
+
+
+

Institution

+

Algonquin College

+
+
+

Description

+

Accommodation

+
+
+

Maturity Amount

+

$760.00

+
+
+
+ ); +} diff --git a/src/components/dashboard/TargetSavings/PlanCreate.jsx b/src/components/dashboard/TargetSavings/PlanCreate.jsx new file mode 100644 index 0000000..197d18a --- /dev/null +++ b/src/components/dashboard/TargetSavings/PlanCreate.jsx @@ -0,0 +1,59 @@ +import InstituteInfor from "../PayTuition/InstituteInfor"; +import PaymentInformation from "../PayTuition/PaymentInformation"; +import TuitionStatus from "../PayTuition/TuitionStatus"; +import StudentInfor from "../PayTuition/StudentInfor"; +import TransactionSummary from "../PayTuition/TransactionSummary"; +import CompletePayment from "../PayTuition/CompletePayment"; +import { useState } from "react"; +import { Steps } from "../../../constants/SidebarData"; +const Plan = () => { + const [currentForm, setCurrentForm] = useState(1); + + const handleNext = () => { + setCurrentForm((prevForm) => Math.min(prevForm + 1, 5)); // Ensure it doesn't exceed the number of steps + }; + const handleThreeBack = () => { + setCurrentForm((prevForm) => Math.max(prevForm - 3, 1)); // Ensure it doesn't go below the first step + }; + const handleTwoBack = () => { + setCurrentForm((prevForm) => Math.max(prevForm - 2, 1)); // Ensure it doesn't go below the first step + }; + const handleOneBack = () => { + setCurrentForm((prevForm) => Math.max(prevForm - 1, 1)); // Ensure it doesn't go below the first step + }; + const renderForm = () => { + switch (currentForm) { + case 1: + return ; + case 2: + return ; + case 3: + return ; + case 4: + return ( + + ); + case 5: + return ; + default: + return; + } + }; + return ( + +
+
{renderForm()}
+
+ +
+
+ + ); +}; + +export default Plan; diff --git a/src/components/dashboard/TargetSavings/Target.jsx b/src/components/dashboard/TargetSavings/Target.jsx new file mode 100644 index 0000000..404c5de --- /dev/null +++ b/src/components/dashboard/TargetSavings/Target.jsx @@ -0,0 +1,11 @@ +import Dashboard from "../../views/dashboard"; +import CreatePlan from "./CreatePlan"; +const Target = () => { + return ( + + + + ); +}; + +export default Target; diff --git a/src/components/dashboard/TargetSavings/Terminated.jsx b/src/components/dashboard/TargetSavings/Terminated.jsx new file mode 100644 index 0000000..b5d3bb3 --- /dev/null +++ b/src/components/dashboard/TargetSavings/Terminated.jsx @@ -0,0 +1,49 @@ +import Vector from "../../../assets/images/VectorX.png"; +import { React , useState } from "react"; +export default function Ongoing() { + + + return ( +
+
+ +
+ +
+
+
+

$760.00

+

+ Balance left to Maturity +

+
+
+
+

Institution

+

Algonquin College

+
+
+

Description

+

Accommodation

+
+
+

Maturity Amount

+

$760.00

+
+
+
+ ); +} diff --git a/src/components/dashboard/wallet/Animation.css b/src/components/dashboard/wallet/Animation.css new file mode 100644 index 0000000..1c2920f --- /dev/null +++ b/src/components/dashboard/wallet/Animation.css @@ -0,0 +1,9 @@ +@keyframes slow-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } + + .slow-spin { + animation: slow-spin 2s linear infinite; /* Adjust the duration here */ + } + \ No newline at end of file diff --git a/src/components/dashboard/wallet/CardDesign.jsx b/src/components/dashboard/wallet/CardDesign.jsx new file mode 100644 index 0000000..1d36bcd --- /dev/null +++ b/src/components/dashboard/wallet/CardDesign.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import Card1 from "../../../assets/images/Card 7.png"; + +export default function CardOne() { + return ( +
+
+ +
+
+ ); +} diff --git a/src/components/dashboard/wallet/CardDesign3.jsx b/src/components/dashboard/wallet/CardDesign3.jsx new file mode 100644 index 0000000..8fce3a5 --- /dev/null +++ b/src/components/dashboard/wallet/CardDesign3.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import Card3 from "../../../assets/images/Group 56.png"; +export default function CardThree() { + return ( +
+
+ +
+
+ ); +} diff --git a/src/components/dashboard/wallet/CardDesign4.jsx b/src/components/dashboard/wallet/CardDesign4.jsx new file mode 100644 index 0000000..b007c79 --- /dev/null +++ b/src/components/dashboard/wallet/CardDesign4.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import Card4 from "../../../assets/images/Card 10.png"; + +export default function CardFour() { + return ( +
+
+ +
+
+ ); +} diff --git a/src/components/dashboard/wallet/EnterCardDetails.jsx b/src/components/dashboard/wallet/EnterCardDetails.jsx index aa4d6cc..f8a800d 100644 --- a/src/components/dashboard/wallet/EnterCardDetails.jsx +++ b/src/components/dashboard/wallet/EnterCardDetails.jsx @@ -1,33 +1,31 @@ -import React, { useState } from "react"; -import Arrow from "../../../assets/images/Icons Right.png"; +import React from 'react'; +import { useCardContext } from '../../../context/CardContext'; +import TopUpCard from './TopupCard'; import Close from "../../../assets/images/close.png"; -import TopUpCard from "./topupCard"; +import Arrow from "../../../assets/images/Icons Right.png"; export default function EnterCardDetails({ onClose }) { - const [isOpen, setIsOpen] = useState(false); - const [selectedOption, setSelectedOption] = useState(""); - const [showTopUpCard, setShowTopUpCard] = useState(false); + const { setEnteredDetails } = useCardContext(); + const [isOpen, setIsOpen] = React.useState(false); + const [selectedOption, setSelectedOption] = React.useState(""); + const [showTopUpCard, setShowTopUpCard] = React.useState(false); const handleProceedClick = (event) => { - event.preventDefault(); // Prevent form from submitting if using manual handling + event.preventDefault(); + setEnteredDetails({ description: event.target.description.value, cardType: selectedOption }); setShowTopUpCard(true); }; const options = ["Single-use virtual card", "Multi-use virtual card"]; - const handleOptionClick = (option) => { setSelectedOption(option); setIsOpen(false); }; - const toggleDropdown = () => { - setIsOpen(!isOpen); - }; - return ( <> {showTopUpCard ? ( -
+
setShowTopUpCard(false)} />
@@ -66,27 +64,26 @@ export default function EnterCardDetails({ onClose }) { name="cardType" placeholder="Select card type" value={selectedOption} - className="px-12 py-2 w-[100%] rounded border border-[#CCCCCC] mt-[8px]" - style={{ minWidth: "200px" }} - readOnly + className="px-12 py-2 rounded border border-[#CCCCCC] mt-[8px] w-full text-[#A1A4A8]" + + onClick={() => setIsOpen(!isOpen)} required /> Arrow setIsOpen(!isOpen)} />
{isOpen && ( -
- {options.map((option) => ( +
+ {options.map((option, index) => (
handleOptionClick(option)} - required > {option}
@@ -94,10 +91,9 @@ export default function EnterCardDetails({ onClose }) {
)}
- diff --git a/src/components/dashboard/wallet/PrepingCard.jsx b/src/components/dashboard/wallet/PrepingCard.jsx new file mode 100644 index 0000000..807e712 --- /dev/null +++ b/src/components/dashboard/wallet/PrepingCard.jsx @@ -0,0 +1,55 @@ +import React, { useState, useEffect } from 'react'; +import Close from "../../../assets/images/close.png"; +import SpinningWheel from "../../../assets/images/Spinning wheel.png"; +import "./Animation.css"; +import CardSuccessful from "./Successful"; + +export default function PrepingCard({ onClose }) { + const [isSpinning, setIsSpinning] = useState(true); + const [isSuccessful, setIsSuccessful] = useState(false); + + useEffect(() => { + const timer = setTimeout(() => { + setIsSpinning(false); + setIsSuccessful(true); + }, 3000); + + return () => clearTimeout(timer); + }, []); + + return ( + <> +
+
+ {isSuccessful ? '' : 'Please Wait'} +
+ +
+ + {isSpinning ? ( +
+ Loading +
+
+ Please Wait +
+

+ We are preparing your virtual card +

+
+
+ ) : ( + + )} + + ); +} diff --git a/src/components/dashboard/wallet/Prev.css b/src/components/dashboard/wallet/Prev.css new file mode 100644 index 0000000..05e0a20 --- /dev/null +++ b/src/components/dashboard/wallet/Prev.css @@ -0,0 +1,23 @@ +.swiper { + width: 344px; + height: 202px; + } + + .swiper-slide { + text-align: center; + font-size: 18px; + background: #fff; + + /* Center slide text vertically */ + display: flex; + justify-content: center; + align-items: center; + } + + .swiper-slide img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + } + \ No newline at end of file diff --git a/src/components/dashboard/wallet/SeeCardDetails.jsx b/src/components/dashboard/wallet/SeeCardDetails.jsx new file mode 100644 index 0000000..1131fb4 --- /dev/null +++ b/src/components/dashboard/wallet/SeeCardDetails.jsx @@ -0,0 +1,88 @@ +import React, { useEffect } from "react"; +import { useCardContext } from "../../../context/CardContext"; +import barner from "../../../assets/images/Banner how to pay.png"; +import { useNavigate } from "react-router-dom"; + +export default function SeeCardDetails() { + const navigate = useNavigate(); + const { cardDetails, enteredDetails } = useCardContext(); + const Exp = "12/23"; + const Cvv = "123"; + + // const handleClick = () => { + // navigate("/dashboard/wallet"); + // }; + + useEffect(() => { + // Retrieve existing card data from local storage + const savedCardData = localStorage.getItem("cardData"); + + // Parse the saved card data + let cardData = []; + try { + cardData = savedCardData ? JSON.parse(savedCardData) : []; + + } catch (error) { + // console.error("Error parsing cardData:", error); + cardData = []; + } + + const now = new Date(); + const creationDate = now.toLocaleDateString(); // Format as desired + const creationTime = now.toLocaleTimeString(); + const newCard = { + cardDetails, + enteredDetails: { + ...enteredDetails, + Exp, + Cvv, + creationDate, + creationTime + } + }; + + // Save updated card data back to local storage + const updatedCardData = [...cardData, newCard]; + localStorage.setItem("cardData", JSON.stringify(updatedCardData)); }, + [cardDetails, enteredDetails]); + + return ( +
+ +
+
+ {cardDetails ?
{cardDetails}
:

No card selected.

} +
+
+ +
+
+

Card Name

+

{enteredDetails.cardType || "N/A"}

+
+
+

Card Number

+

1234 5678 9101 1213

+
+
+
+
+
+

Exp Date

+

{Exp}

+
+
+

CVV

+

{Cvv}

+
+
+
+

Card Type

+

{enteredDetails.description || "N/A"}

+
+
+
+ ); +} diff --git a/src/components/dashboard/wallet/Successful.jsx b/src/components/dashboard/wallet/Successful.jsx new file mode 100644 index 0000000..3fff447 --- /dev/null +++ b/src/components/dashboard/wallet/Successful.jsx @@ -0,0 +1,54 @@ +import React from "react"; +import SuccessfulImage from "../../../assets/images/Success checkmark.png"; +import CardDetails from "./SeeCardDetails"; +import Close from "../../../assets/images/close.png"; + +export default function Successful() { + const [showCardDetails, setShowCardDetails] = React.useState(false); + + const handleShowCardDetails = () => { + setShowCardDetails(true); + }; + + return ( +
+ {showCardDetails && ( +
+
+ + setShowCardDetails(false)} /> +
+
+ )} +
+
+ Success +
+
+
+ Successful +
+

+ Your virtual card is ready to go +

+
+ +
+
+ ); +} diff --git a/src/components/dashboard/wallet/Wallets.jsx b/src/components/dashboard/wallet/Wallets.jsx index d38aad2..16f30af 100644 --- a/src/components/dashboard/wallet/Wallets.jsx +++ b/src/components/dashboard/wallet/Wallets.jsx @@ -1,6 +1,5 @@ import Dashboard from "../../views/dashboard"; import Card from "./cardComponent"; -import HeaderMessage from "../../views/messageDashboard"; const Wallets = () => { return ( diff --git a/src/components/dashboard/wallet/addCardComponent.jsx b/src/components/dashboard/wallet/addCardComponent.jsx index 92958b9..302463b 100644 --- a/src/components/dashboard/wallet/addCardComponent.jsx +++ b/src/components/dashboard/wallet/addCardComponent.jsx @@ -1,8 +1,9 @@ -import React, { useState } from "react"; -import Details from "./detailsComponent"; -import RoundedCircleButton from "./dotted"; -import Search from "./searchFilter"; // Make sure the correct import path is used +import React, { useState, useEffect } from "react"; +import Details from "./DetailsComponent"; +import RoundedCircleButton from "./Dotted"; +import Search from "./SearchFilter"; +// Sample cards data const Cards = [ { bank: "Monobank Card", @@ -24,47 +25,94 @@ const Cards = [ const AddWallet = () => { const [cards, setCards] = useState(Cards); const [searchTerm, setSearchTerm] = useState(""); + const [selectedCardIndex, setSelectedCardIndex] = useState(null); + const [savedCardDetails, setSavedCardDetails] = useState([]); + const [showRedDot, setShowRedDot] = useState(false); - const toggleCircle = (index) => { - const updatedCards = cards.map((card, i) => ({ - ...card, - showCircle: i === index ? !card.showCircle : false, // Ensure only one showCircle is true - })); - setCards(updatedCards); - }; + // Retrieve card details from local storage + useEffect(() => { + const savedCardData = localStorage.getItem("cardData"); + try { + const parsedData = savedCardData ? JSON.parse(savedCardData) : []; + if (Array.isArray(parsedData)) { + // Sort cards by creation date in descending order + const sortedCards = parsedData.sort((a, b) => new Date(b.enteredDetails.creationDate) - new Date(a.enteredDetails.creationDate)); + setSavedCardDetails(sortedCards); + } else { + setSavedCardDetails([]); + } + } catch (error) { + setSavedCardDetails([]); + } + }, []); + // Handle search input const handleSearch = (term) => { setSearchTerm(term); }; - // Filter cards based on search term - const filteredCards = cards.filter((card) => - card.bank.toLowerCase().includes(searchTerm.toLowerCase()) + // Filter saved cards based on search term + const filteredSavedCards = savedCardDetails.filter((card) => + card.enteredDetails?.description.toLowerCase().includes(searchTerm.toLowerCase()) ); + // Function to handle selecting a card + const handleSelectCard = (index) => { + setSelectedCardIndex(index); + setShowRedDot(!showRedDot); // Toggle the red dot + }; + + // Function to handle clicking the Details button + const handleDetailsClick = (index) => { + setShowRedDot(!showRedDot); // Toggle the red dot + setSelectedCardIndex(index); // Update selected card index + }; + return ( -
+
- {filteredCards.map((card, index) => ( -
- toggleCircle(index)} - showCircle={card.showCircle} - /> -
-

- {card.bank} -

-

- Created: {card.date} -

+ + {/* Render saved card details if available and filtered */} + {filteredSavedCards.length > 0 ? ( + filteredSavedCards.map((card, index) => ( +
+ +
+

+ {card.enteredDetails?.description || "N/A"} +

+

+ Created: {card.enteredDetails?.creationDate || "N/A"} +

+
+
handleDetailsClick(index)}>Details
-
toggleCircle(index)}>Details
-
- ))} + )) + ) : ( + // Render "No cards found" message if no saved card details + filteredSavedCards.length === 0 && searchTerm ? ( +

No cards found

+ ) : ( + // Render static cards if no saved card details and no search term + cards.map((card, index) => ( +
+ handleSelectCard(index)} + showCircle={index === selectedCardIndex && showRedDot} + /> +
+

+ {card.bank} +

+

+ Created: {card.date} +

+
+
handleSelectCard(index)}>Details
+
+ )) + ) + )}
); }; diff --git a/src/components/dashboard/wallet/addWallet.jsx b/src/components/dashboard/wallet/addWallet.jsx index f24915a..e89037a 100644 --- a/src/components/dashboard/wallet/addWallet.jsx +++ b/src/components/dashboard/wallet/addWallet.jsx @@ -1,55 +1,91 @@ -import React, { useState } from 'react'; -import AddWallet from './addCardComponent'; -import Pop from './popUp'; // Import the Modal component +import React, { useRef, useState } from "react"; +import AddWallet from "./addCardComponent"; +import Pop from "./PopUp"; +import Card1 from "./CardDesign"; +import Card2 from "./CardDesign1"; +import Card3 from "./CardDesign3"; +import card1 from "../../../assets/images/Card 7.png"; +import card2 from "../../../assets/images/Cards.png"; +import card3 from "../../../assets/images/Group 56.png"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/pagination"; +import "./Prev.css"; +// import "../../../../src/swipper.css" + +import { Pagination } from "swiper/modules"; +import { useCardContext } from "../../../context/CardContext"; export default function AddWalletPage() { - const [isModalOpen, setIsModalOpen] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); - const handleOpenModal = () => { - setIsModalOpen(true); - }; + const handleOpenModal = () => { + setIsModalOpen(true); + }; - const handleCloseModal = () => { - setIsModalOpen(false); - }; + const handleCloseModal = () => { + setIsModalOpen(false); + }; - return ( - <> -
-
- - Create New Card -
-
-
-

- Manage Cards -

-

View all

-
- -
-
- {/* Render Modal */} - - ); + return ( + <> +
+ +
+ + {Card1} + + + {Card2} + + + {Card3} + + {/* + {" "} + */} +
+
+
+ + Create New Card +
+
+
+

+ Manage Cards +

+

View all

+
+ +
+
+ + + ); } diff --git a/src/components/dashboard/wallet/cardComponent.jsx b/src/components/dashboard/wallet/cardComponent.jsx index e7ad6ae..8b96094 100644 --- a/src/components/dashboard/wallet/cardComponent.jsx +++ b/src/components/dashboard/wallet/cardComponent.jsx @@ -1,34 +1,102 @@ -import React from "react"; +import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { useFlutterwave, closePaymentModal } from 'flutterwave-react-v3'; import Looper from "../../../assets/images/Looper-1.png"; import ReactFlagsSelect from "react-flags-select"; import Framer from "../../../assets/images/Frame.png"; import Framer2 from "../../../assets/images/Frame (1).png"; import { BsEye, BsEyeSlash } from "react-icons/bs"; import History from "./history"; -import Button from "./button"; -import AddWallet from "./addWallet"; +import Button from "../TargetSavings/Button"; +import AddWallet from "./AddWallet"; -import { useState } from "react"; export default function Card() { const [selected, setSelected] = useState("US"); const [showAmount, setShowAmount] = useState(true); + const [amount, setAmount] = useState(() => { + const savedAmount = localStorage.getItem("amount"); + const numericAmount = savedAmount ? parseFloat(savedAmount) : 0; + return isNaN(numericAmount) ? 0 : numericAmount; + }); + const [inputAmount, setInputAmount] = useState(""); + const [showModal, setShowModal] = useState(false); + const navigate = useNavigate(); + + const handlePayment = () => { + const numericAmount = parseFloat(inputAmount.replace(/[^0-9.]/g, "")); + if (isNaN(numericAmount) || numericAmount <= 0) { + alert("Invalid amount"); + return; + } + + const config = { + public_key: "FLWPUBK_TEST-02b9b5fc6406bd4a41c3ff141cc45e93-X", + tx_ref: Date.now(), // Use unique tx_ref + amount: numericAmount, + currency: 'NGN', + customer: { + email: 'user@gmail.com', + phone_number: '070********', + name: 'john doe', + }, + customizations: { + title: 'my Payment Title', + description: 'Funding my wallet', + logo: 'https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg', + }, + }; + + const handleFlutterPayment = useFlutterwave(config); + + handleFlutterPayment({ + callback: function (data) { + const newBalance = amount + numericAmount; + setAmount(newBalance); + localStorage.setItem("amount", newBalance); + // Save transaction details in localStorage + const transaction = { + id: data.tx_ref, + amount: numericAmount, + date: new Date().toISOString(), + payment_options + }; + + let transactions = JSON.parse(localStorage.getItem("transactions")) || []; + transactions.push(transaction); + localStorage.setItem("transactions", JSON.stringify(transactions)); + + navigate("/dashboard/wallet"); + closePaymentModal(); + setShowModal(false); + }, + onClose: function () { + setShowModal(false); + } + }).catch(error => { + console.error('Payment error:', error); + closePaymentModal(); + setShowModal(false); + }); + }; + const toggleVisibility = () => { setShowAmount(!showAmount); }; const renderAmount = () => { - return showAmount ? "$18,000" : "******"; + return showAmount ? `₦${amount.toFixed(2)}` : "******"; }; - const topUp = () => { - alert("top-up"); + + const handleInputChange = (event) => { + setInputAmount(event.target.value); }; - const render = "123 4567 890"; + return ( <>
-
+

Wallet Balance

setSelected(code)} /> - {/* */}
-
+

{renderAmount()}

@@ -72,40 +130,67 @@ export default function Card() { className="text-white w-24 absolute top-2 right-2" onClick={toggleVisibility} > - {" "} {showAmount ? : }
-
-

Unique Id: {render}

+

Unique Id:

-
- {" "} +
+ + {showModal && ( +
+
+

Enter Amount

+ + + +
+
+ )} ); } diff --git a/src/components/dashboard/wallet/cardDesign1.jsx b/src/components/dashboard/wallet/cardDesign1.jsx index b14e0d1..c74cd41 100644 --- a/src/components/dashboard/wallet/cardDesign1.jsx +++ b/src/components/dashboard/wallet/cardDesign1.jsx @@ -1,11 +1,20 @@ import React from "react"; - -export default function Card1() { - return( - <> -
- -
- - ) -} \ No newline at end of file +import Card2 from "../../../assets/images/Cards.png"; +export default function CardTwo() { + return ( +
+
+ +
+
+ ); +} diff --git a/src/components/dashboard/wallet/creatComponent.jsx b/src/components/dashboard/wallet/creatComponent.jsx deleted file mode 100644 index 408d9bf..0000000 --- a/src/components/dashboard/wallet/creatComponent.jsx +++ /dev/null @@ -1,4 +0,0 @@ -import React from "react"; -export default function Card({ children, className }) { - return
; -} diff --git a/src/components/dashboard/wallet/history.jsx b/src/components/dashboard/wallet/history.jsx index 28f6bc1..2bb8f40 100644 --- a/src/components/dashboard/wallet/history.jsx +++ b/src/components/dashboard/wallet/history.jsx @@ -1,5 +1,5 @@ import React from "react"; -import HistoryComponent from "./historyComponent"; +import HistoryComponent from "./HistoryComponent"; const history = () => { return ( <> diff --git a/src/components/dashboard/wallet/popUp.jsx b/src/components/dashboard/wallet/popUp.jsx index d5eed9d..4c7bfca 100644 --- a/src/components/dashboard/wallet/popUp.jsx +++ b/src/components/dashboard/wallet/popUp.jsx @@ -1,10 +1,9 @@ -import React, { useState } from "react"; -import Close from "../../../assets/images/close.png"; -import Atm from "../../../assets/images/ATM Illustration.png"; -import Swip from "./swippedCard"; - -const Modal = ({ isOpen, onClose }) => { - const [showSwip, setShowSwip] = useState(false); +import React from "react"; +import Close from "../../../assets/images/close.png"; // Update the path as necessary +import Swip from "./SwippedCard"; // Ensure Swip component is correctly imported +import Atm from "../../../assets/images/ATM Illustration.png"; // Update the path as necessary +const Pop = ({ isOpen, onClose }) => { + const [showSwip, setShowSwip] = React.useState(false); const handleProceedClick = () => { setShowSwip(true); @@ -14,20 +13,18 @@ const Modal = ({ isOpen, onClose }) => { return (
-
-
- -
+
+ {showSwip ? ( - + // Display Swip component when showSwip is true ) : ( <> -
+
ATM illustration
@@ -38,7 +35,7 @@ const Modal = ({ isOpen, onClose }) => { from your Tuition wallet for seamless transactions

diff --git a/src/components/dashboard/wallet/topupCard.jsx b/src/components/dashboard/wallet/topupCard.jsx index 35ca3c1..d34533a 100644 --- a/src/components/dashboard/wallet/topupCard.jsx +++ b/src/components/dashboard/wallet/topupCard.jsx @@ -2,9 +2,18 @@ import React, { useState } from "react"; import Close from "../../../assets/images/close.png"; import USFlag from "../../../assets/images/Frame 373.png"; import Arrow from "../../../assets/images/Icons Right.png"; +import PrepingCard from "./PrepingCard"; +import { useCardContext } from "../../../context/CardContext"; // Adjust path as necessary + export default function TopUpCard({ onClose }) { const [selectedCurrency, setSelectedCurrency] = useState("USD"); + const [showPrepingCard, setShowPrepingCard] = useState(false); + + const handleProceedClick = (event) => { + event.preventDefault(); + setShowPrepingCard(true); + } const handleCurrencyChange = (event) => { setSelectedCurrency(event.target.value); @@ -38,57 +47,113 @@ export default function TopUpCard({ onClose }) { return (
-
-
- Top-Up Card -
- -
-

- To avoid topping up failures, please make sure your wallet balance is - enough to cover the desired top-up amount. -

-
-
- -
- {getFlag(selectedCurrency)} - {getDisplayValue(selectedCurrency)} -
- Arrow +
+ setShowPrepingCard(false)} /> +
+
+ ) : ( +
+
+
+ Top-Up Card +
+ +
+

+ To avoid topping up failures, please make sure your wallet balance is + enough to cover the desired top-up amount. +

+
+
+ +
+ {getFlag(selectedCurrency)} + {getDisplayValue(selectedCurrency)} +
+ Arrow +
+
+
+
+
+ +
-
- -
-
- - + )}
); } + +// import React, { useState } from "react"; +// import { useCardContext } from "../../../context/CardContext"; // Adjust path as necessary +// import USFlag from "../../../assets/images/Frame 373.png"; +// import Arrow from "../../../assets/images/Icons Right.png"; + +// export default function TopUpCard({ onClose }) { +// const [selectedCurrency, setSelectedCurrency] = useState("USD"); +// const [amount, setAmount] = useState(""); +// const { setTopUpDetails } = useCardContext(); + +// const handleProceedClick = (event) => { +// event.preventDefault(); +// setTopUpDetails({ amount, currency: selectedCurrency }); +// // Show the PrepingCard component +// }; + +// return ( +//
+//
+//
+// Top-Up Card +//
+//
+// +// setAmount(e.target.value)} +// /> +//
+// +//
+// ); +// } diff --git a/src/components/onboarding/Enroll.jsx b/src/components/onboarding/Enroll.jsx index 908e5c4..085ea85 100644 --- a/src/components/onboarding/Enroll.jsx +++ b/src/components/onboarding/Enroll.jsx @@ -29,6 +29,7 @@ export default function Enroll() { !formData.contactEmail ) { alert("Please fill in all fields"); + setIsLoading(false); return; } @@ -41,7 +42,7 @@ export default function Enroll() { }, body: JSON.stringify(formData), }); - // console.log("sending data", formData); + if (response.ok) { navigate("/enrollsuccess"); } @@ -64,23 +65,23 @@ export default function Enroll() { transition={{ duration: 1 }} >
-
-
-

- {" "} +
+
+

Enroll your institution

-

+

With Tuition, no matter your location in the world, your students - can easily pay their education fees without hassle

+ can easily pay their education fees without hassle. +

Please complete the form to connect with a member of our team.

-
+
-
+
-
+
{ setSelected(code); - setFormData({ ...formData, countryName: code }); // Update formData with selected country code + setFormData({ ...formData, countryName: code }); }} searchable - id="countryName" - className="ml-28 text-gray-700 w-96" + className="text-gray-700 w-full md:w-96" + /> +
+
+ +
+
+ +
+
+
- - - -
- diff --git a/src/components/onboarding/contactUs/contactus.jsx b/src/components/onboarding/contactUs/contactus.jsx index 3afee28..25bc4dd 100644 --- a/src/components/onboarding/contactUs/contactus.jsx +++ b/src/components/onboarding/contactUs/contactus.jsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import { motion } from "framer-motion"; import Header from "../../views/header"; import { NavLink } from "react-router-dom"; @@ -9,9 +9,9 @@ import Phone from "../../../assets/images/Phone container.png"; import X from "../../../assets/images/X socials container.png"; import Faq from "../../../assets/images/FAQs container.png"; import Bob from "../../../assets/images/Blob 1 (1).png"; -import { useState } from "react"; -import { useNavigate } from "react-router-dom"; import Small from "../../../assets/images/3d_small_people_-_global_manager-removebg-preview 1 (1).png"; +import { useNavigate } from "react-router-dom"; + export default function ContactUs() { const [isLoading, setIsLoading] = useState(false); const navigate = useNavigate(); @@ -19,22 +19,22 @@ export default function ContactUs() { first_name: "", last_name: "", email: "", - message:"", + message: "", }); const handleSubmit = async (event) => { event.preventDefault(); try { - setIsLoading(true); + setIsLoading(true); if ( !formData.first_name || !formData.last_name || !formData.email || !formData.message - ) - { + ) { alert("Please fill in all fields"); - return setIsLoading(false); + setIsLoading(false); + return; } const endpoint = @@ -49,7 +49,7 @@ export default function ContactUs() { console.log("sending data", formData); if (response.ok) { navigate("/enrollsuccess"); - } + } } catch (error) { alert(error.message); setIsLoading(false); @@ -68,149 +68,125 @@ export default function ContactUs() { transition={{ duration: 1 }} >
-
-
- -

Let’s sort you out

+
+
+ Vector Icon +

Let’s sort you out

-

- +

Need help with something? Our 24/7 support team is ready to assist you - on
your preferred channel + on
your preferred channel.

-
- -
-
- -
+
+ +
+
+
-
- -
+
+
-
-
- -
+
+
-
- -
-
-