diff --git a/.gitignore b/.gitignore
index 44300dc1f..77ec94cd7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,7 +17,7 @@ dist
build
# environment variables
-.env
+.env.*
.env.local
.env.development.local
.env.test.local
diff --git a/apphosting.yaml b/apphosting.yaml
new file mode 100644
index 000000000..2325bef5d
--- /dev/null
+++ b/apphosting.yaml
@@ -0,0 +1,23 @@
+# Settings for Backend (on Cloud Run).
+# See https://firebase.google.com/docs/app-hosting/configure#cloud-run
+runConfig:
+ minInstances: 0
+ # maxInstances: 100
+ # concurrency: 80
+ # cpu: 1
+ # memoryMiB: 512
+
+# Environment variables and secrets.
+# env:
+ # Configure environment variables.
+ # See https://firebase.google.com/docs/app-hosting/configure#user-defined-environment
+ # - variable: MESSAGE
+ # value: Hello world!
+ # availability:
+ # - BUILD
+ # - RUNTIME
+
+ # Grant access to secrets in Cloud Secret Manager.
+ # See https://firebase.google.com/docs/app-hosting/configure#secret-parameters
+ # - variable: MY_SECRET
+ # secret: mySecretRef
diff --git a/index.html b/index.html
index efb687cbc..0870fcfa9 100644
--- a/index.html
+++ b/index.html
@@ -5,7 +5,7 @@
-
Minimal UI Kit
+ PABGM Portal
diff --git a/package-lock.json b/package-lock.json
index bcd1a82ae..0066b5add 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@minimal/material-kit-react",
- "version": "2.0.0",
+ "version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@minimal/material-kit-react",
- "version": "2.0.0",
+ "version": "1.0.0",
"dependencies": {
"@emotion/cache": "^11.13.1",
"@emotion/react": "^11.13.3",
@@ -16,9 +16,14 @@
"@iconify/react": "^5.0.2",
"@mui/lab": "^5.0.0-alpha.173",
"@mui/material": "^5.16.7",
+ "@paystack/inline-js": "^2.22.1",
"apexcharts": "^3.52.0",
+ "bcryptjs": "^2.4.3",
+ "crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
+ "firebase": "^11.0.1",
"history": "^5.3.0",
+ "jwt-decode": "^4.0.0",
"react": "^18.3.1",
"react-apexcharts": "^1.4.1",
"react-dom": "^18.3.1",
@@ -27,7 +32,10 @@
"simplebar-react": "^3.2.6"
},
"devDependencies": {
+ "@types/bcryptjs": "^2.4.6",
+ "@types/crypto-js": "^4.2.2",
"@types/node": "^22.5.0",
+ "@types/paystack__inline-js": "^1.0.0",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
@@ -65,12 +73,13 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
- "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"license": "MIT",
"dependencies": {
- "@babel/highlight": "^7.24.7",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
@@ -78,73 +87,59 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.4.tgz",
- "integrity": "sha512-NFtZmZsyzDPJnk9Zg3BbTfKKc9UlHYzD0E//p2Z3B9nCwwtJW9T0gVbCz8+fBngnn4zf1Dr3IK8PHQQHq0lDQw==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz",
+ "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.4",
+ "@babel/parser": "^7.26.2",
+ "@babel/types": "^7.26.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^2.5.1"
+ "jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
- "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
- "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
- "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
- "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.24.7",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
- },
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz",
- "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
+ "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.4"
+ "@babel/types": "^7.26.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -154,9 +149,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz",
- "integrity": "sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
+ "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
@@ -166,30 +161,30 @@
}
},
"node_modules/@babel/template": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz",
- "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/parser": "^7.25.0",
- "@babel/types": "^7.25.0"
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz",
- "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
+ "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/generator": "^7.25.4",
- "@babel/parser": "^7.25.4",
- "@babel/template": "^7.25.0",
- "@babel/types": "^7.25.4",
+ "@babel/code-frame": "^7.25.9",
+ "@babel/generator": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -198,14 +193,13 @@
}
},
"node_modules/@babel/types": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz",
- "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
+ "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.24.8",
- "@babel/helper-validator-identifier": "^7.24.7",
- "to-fast-properties": "^2.0.0"
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -289,15 +283,15 @@
}
},
"node_modules/@emotion/serialize": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz",
- "integrity": "sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz",
+ "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==",
"license": "MIT",
"dependencies": {
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/unitless": "^0.10.0",
- "@emotion/utils": "^1.4.0",
+ "@emotion/utils": "^1.4.1",
"csstype": "^3.0.2"
}
},
@@ -346,9 +340,9 @@
}
},
"node_modules/@emotion/utils": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz",
- "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==",
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz",
+ "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==",
"license": "MIT"
},
"node_modules/@emotion/weak-memoize": {
@@ -861,6 +855,612 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@firebase/analytics": {
+ "version": "0.10.9",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.9.tgz",
+ "integrity": "sha512-FrvW6u6xDBKXUGYUy1WIUh0J9tvbppMsk90mig0JhHST8iLveKu/dIBVeVE/ZYZhmXy4fkI7SPSWvD1V0O4tXw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-compat": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.15.tgz",
+ "integrity": "sha512-C5to422Sr8FkL0MPwXcIecbMnF4o2Ll7MtoWvIm4Q/LPJvvM+tWa1DiU+LzsCdsd1/CYE9EIW9Ma3ko9XnAAYw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/analytics": "0.10.9",
+ "@firebase/analytics-types": "0.8.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-types": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz",
+ "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app": {
+ "version": "0.10.15",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.15.tgz",
+ "integrity": "sha512-he6qlG3pmwL+LHdG/BrSMBQeJzzutciq4fpXN3lGa1uSwYSijJ24VtakS/bP2X9SiDf8jGywJ4u+OgXAenJsNg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-check": {
+ "version": "0.8.9",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.9.tgz",
+ "integrity": "sha512-YzVn1mMLzD2JboMPVVO0Pe20YOgWzrF+aXoAmmd0v3xec051n83YpxSUZbacL69uYvk0dHrEsbea44QtQ5WPDA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-compat": {
+ "version": "0.3.16",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.16.tgz",
+ "integrity": "sha512-AxIGzLRXrTFNL+H6V+4BO0w/gERloROfRbWI/FoJUnQd0qPZIzyfdHZBbThFzFGLfDt/mVs2kdjYFx/l9I8NhQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check": "0.8.9",
+ "@firebase/app-check-types": "0.5.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-interop-types": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz",
+ "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app-check-types": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz",
+ "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app-compat": {
+ "version": "0.2.45",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.45.tgz",
+ "integrity": "sha512-5rYbXq1ndtMTg+07oH4WrkYuP+NZq61uzVwW1hlmybp/gr4cXq2SfaP9fc6/9IzTKmu3dh3H0fjj++HG7Z7o/w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app": "0.10.15",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-types": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz",
+ "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/auth": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.0.tgz",
+ "integrity": "sha512-/O7UDWE5S5ux456fzNHSLx/0YN/Kykw/WyAzgDQ6wvkddZhSEmPX19EzxgsFldzhuFjsl5uOZTz8kzlosCiJjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@react-native-async-storage/async-storage": "^1.18.1"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/auth-compat": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.15.tgz",
+ "integrity": "sha512-jz6k1ridPiecKI8CBRiqCM6IMOhwYp2MD+YvoxnMiK8nQLSTm57GvHETlPNX3WlbyQnCjMCOvrAhe27whyxAEg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/auth": "1.8.0",
+ "@firebase/auth-types": "0.12.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/auth-interop-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz",
+ "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/auth-types": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz",
+ "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/component": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.10.tgz",
+ "integrity": "sha512-OsNbEKyz9iLZSmMUhsl6+kCADzte00iisJIRUspnUqvDCX+RSGZOBIqekukv/jN177ovjApBQNFaxSYIDc/SyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/data-connect": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.1.tgz",
+ "integrity": "sha512-RBJ7XE/a3oXFv31Jlw8cbMRdsxQoI8F3L7xm4n93ab+bIr1NQUiYGgW9L7TTw7obdNev91ZnW0xfqJtXcPA5yA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/database": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.9.tgz",
+ "integrity": "sha512-EkiPSKSu2TJJGtOjyISASf3UFpFJDil1lMbfqnxilfbmIsilvC8DzgjuLoYD+eOitcug4wtU9Fh1tt2vgBhskA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-compat": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.0.tgz",
+ "integrity": "sha512-2xlODKWwf/vNAxCmou0GFhymx2pqZKkhXMN9B5aiTjZ6+81sOxGim53ELY2lj+qKG2IvgiCYFc4X+ZJA2Ad5vg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/database": "1.0.9",
+ "@firebase/database-types": "1.0.6",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-types": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.6.tgz",
+ "integrity": "sha512-sMI7IynSZBsyGbUugc8PKE1jwKbnvaieAz/RxuM57PZQNCi6Rteiviwcw/jqZOX6igqYJwXWZ3UzKOZo2nUDRA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-types": "0.9.2",
+ "@firebase/util": "1.10.1"
+ }
+ },
+ "node_modules/@firebase/firestore": {
+ "version": "4.7.4",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.4.tgz",
+ "integrity": "sha512-K2nq4w+NF8J1waGawY5OHLawP/Aw5CYxyDstVv1NZemGPcM3U+LZ9EPaXr1PatYIrPA7fS4DxZoWcbB0aGJ8Zg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "@firebase/webchannel-wrapper": "1.0.2",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-compat": {
+ "version": "0.3.39",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.39.tgz",
+ "integrity": "sha512-CsK8g34jNeHx95LISDRTcArJLonW+zJCqHI1Ez9WNiLAK2X8FeQ4UiD+RwOwxAIR+t2a6xED/5Fe6ZIqx7MuoQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/firestore": "4.7.4",
+ "@firebase/firestore-types": "3.0.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz",
+ "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/functions": {
+ "version": "0.11.9",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.9.tgz",
+ "integrity": "sha512-dhO5IUfQRCsrc20YD20nSOX+QCT+cH6N86HlZOLz2XgyEFgzOdBQnUot4EabBJQRkMBI7fZWUrbYfRcnov53ug==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.10",
+ "@firebase/messaging-interop-types": "0.2.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-compat": {
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.15.tgz",
+ "integrity": "sha512-eiHpc6Sd9Y/SNhBsGi944SapiFbfTPKsiSUQ74QxNSs0yoxvABeIRolVMFk4TokP57NGmstGYpYte02XGNPcYw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/functions": "0.11.9",
+ "@firebase/functions-types": "0.6.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-types": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz",
+ "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/installations": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.10.tgz",
+ "integrity": "sha512-TuGSOMqkFrllxa0X/8VZIqBCRH4POndU/iWKWkRmkh12+/xKSpdp+y/kWaVbsySrelltan6LeYlcYPmLibWbwg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-compat": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.10.tgz",
+ "integrity": "sha512-YTonkcVz3AK7RF8xFhvs5CwDuJ0xbzzCJIwXoV14gnzdYbMgy6vWlUUbzkvbtEDXzPRHB0n7aGZl56oy9dLOFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/installations-types": "0.5.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-types": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz",
+ "integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/logger": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.3.tgz",
+ "integrity": "sha512-Th42bWJg18EF5bJwhRosn2M/eYxmbWCwXZr4hHX7ltO0SE3QLrpgiMKeRBR/NW7vJke7i0n3i8esbCW2s93qBw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/messaging": {
+ "version": "0.12.13",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.13.tgz",
+ "integrity": "sha512-YLa8PWl+BgiOVR5WOyzl21fVJFJeBRfniNuN25d9DBrQzppSAahuN6yS+vt1OIjvZNPN4pZ/lcRLYupbGu4W0w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/messaging-interop-types": "0.2.2",
+ "@firebase/util": "1.10.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-compat": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.13.tgz",
+ "integrity": "sha512-9ootPClS6m2c2KIzo7AqSHaWzAw28zWcjQPjVv7WeQDu6wjufpbOg+7tuVzb+gqpF9Issa3lDoYOwlO0ZudO3g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/messaging": "0.12.13",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-interop-types": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz",
+ "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/performance": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.10.tgz",
+ "integrity": "sha512-x/mNYKGxq7A+QV0EiEZeD2S+E+kw+UcZ8FXuE7qDJyGGt/0Wd+bIIL7RakG/VrFt7/UYc//nKygDc7/Ig7sOmQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-compat": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.10.tgz",
+ "integrity": "sha512-0h1qYkF6I79DSSpHfTQFvb91fo8shmmwiPzWFYAPdPK02bSWpKwVssNYlZX2iUnumxerDMbl7dWN+Im/W3bnXA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/performance": "0.6.10",
+ "@firebase/performance-types": "0.2.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-types": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz",
+ "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/remote-config": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.10.tgz",
+ "integrity": "sha512-jTRjy3TdqzVna19m5a1HEHE5BG4Z3BQTxBgvQRTmMKlHacx4QS0CToAas7R9M9UkxpgFcVuAE7FpWIOWQGCEWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-compat": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.10.tgz",
+ "integrity": "sha512-fIi5OB2zk0zpChMV/tTd0oEZcZI8TlwQDlLlcrDpMOV5l5dqd0JNlWKh6Fwmh4izmytk+rZIAIpnak/NjGVesQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/remote-config": "0.4.10",
+ "@firebase/remote-config-types": "0.3.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-types": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz",
+ "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/storage": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.3.tgz",
+ "integrity": "sha512-B5HiJ7isYKaT4dOEV43f2ySdhQxzq+SQEm7lqXebJ8AYCsebdHrgGzrPR0LR962xGjPzJHFKx63gA8Be/P2MCw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-compat": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.13.tgz",
+ "integrity": "sha512-15kje7JALswRCBKsCSvKg5FbqUYykaIMqMbZRD7I6uVRWwdyTvez5MBQfMhBia2JcEmPiDpXhJTXH4PAWFiA8g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/storage": "0.13.3",
+ "@firebase/storage-types": "0.8.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-types": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz",
+ "integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/util": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.1.tgz",
+ "integrity": "sha512-AIhFnCCjM8FmCqSNlNPTuOk3+gpHC1RkeNUBLtPbcqGYpN5MxI5q7Yby+rxycweOZOCboDzfIj8WyaY4tpQG/g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/vertexai": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.0.tgz",
+ "integrity": "sha512-48N3Lp/9GgiCCRfrSdHS+Y1IiMdYXvnHFO/f+HL1PgUtBq7WQ/fWmYOX3mzAN36zvytq13nb68ImF+GALopp+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/webchannel-wrapper": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.2.tgz",
+ "integrity": "sha512-3F4iA2E+NtdMbOU0XC1cHE8q6MqpGIKRj62oGOF38S6AAx5VHR9cXmoDUSj7ejvTAT7m6jxuEeQkHeq0F+mU2w==",
+ "license": "Apache-2.0"
+ },
"node_modules/@floating-ui/core": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz",
@@ -911,6 +1511,37 @@
"integrity": "sha512-4F+rbfklgWHatFheB3ZQgTFjkqzMiWfHomy69TWSGc0qU+w+QhX9dGz7IVQRksvKciJoXAhxijCxwAJw418g4Q==",
"license": "OFL-1.1"
},
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
+ "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.8",
+ "@types/node": ">=12.12.47"
+ },
+ "engines": {
+ "node": "^8.13.0 || >=10.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.13",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz",
+ "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -1270,12 +1901,12 @@
}
},
"node_modules/@mui/types": {
- "version": "7.2.15",
- "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz",
- "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==",
+ "version": "7.2.19",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz",
+ "integrity": "sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA==",
"license": "MIT",
"peerDependencies": {
- "@types/react": "^17.0.0 || ^18.0.0"
+ "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -1351,6 +1982,16 @@
"node": ">= 8"
}
},
+ "node_modules/@paystack/inline-js": {
+ "version": "2.22.1",
+ "resolved": "https://registry.npmjs.org/@paystack/inline-js/-/inline-js-2.22.1.tgz",
+ "integrity": "sha512-h9cf+3UbFY/+/GRA5XeWj769KaSHuedqIcuYDdV6voKGnwF9qcmJ3BorpIST45Y3qVXljOXsexL2tS6GZXJbmg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 18.0.0",
+ "npm": ">= 10.0.0"
+ }
+ },
"node_modules/@pkgr/core": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
@@ -1364,15 +2005,79 @@
"url": "https://opencollective.com/unts"
}
},
- "node_modules/@popperjs/core": {
- "version": "2.11.8",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
- "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/popperjs"
- }
+ "node_modules/@popperjs/core": {
+ "version": "2.11.8",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
+ "license": "BSD-3-Clause"
},
"node_modules/@remix-run/router": {
"version": "1.19.1",
@@ -1833,6 +2538,20 @@
"@swc/counter": "^0.1.3"
}
},
+ "node_modules/@types/bcryptjs": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz",
+ "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/crypto-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
+ "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
@@ -1866,7 +2585,6 @@
"version": "22.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.0.tgz",
"integrity": "sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
@@ -1878,10 +2596,17 @@
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
"license": "MIT"
},
+ "node_modules/@types/paystack__inline-js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/paystack__inline-js/-/paystack__inline-js-1.0.0.tgz",
+ "integrity": "sha512-LCU5rSBs3FAG8tkn1hgV9FHTTRk+Kj2s/DupNlJRem5NaVabj6AASjWJ9tBtJX6dt7bcKhkf8c5MzgJUkpOG2g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/prop-types": {
- "version": "15.7.12",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
- "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
+ "version": "15.7.13",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
+ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
"license": "MIT"
},
"node_modules/@types/react": {
@@ -2192,24 +2917,11 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
- "node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
@@ -2488,6 +3200,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
+ "license": "MIT"
+ },
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@@ -2550,29 +3268,6 @@
"node": ">=6"
}
},
- "node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/chalk/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -2614,6 +3309,20 @@
"node": ">= 6"
}
},
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -2623,21 +3332,6 @@
"node": ">=6"
}
},
- "node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "license": "MIT"
- },
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
@@ -2699,6 +3393,12 @@
"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/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
@@ -3153,6 +3853,15 @@
"@esbuild/win32-x64": "0.21.5"
}
},
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -4019,6 +4728,18 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -4068,6 +4789,42 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/firebase": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.0.1.tgz",
+ "integrity": "sha512-qsFb8dMcQINEDhJteG7RP+GqwgSRvfyiexQqHd5JToDdm87i9I2rGC4XQsGawKGxzKwZ/ISdgwNWxXAFYdCC6A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/analytics": "0.10.9",
+ "@firebase/analytics-compat": "0.2.15",
+ "@firebase/app": "0.10.15",
+ "@firebase/app-check": "0.8.9",
+ "@firebase/app-check-compat": "0.3.16",
+ "@firebase/app-compat": "0.2.45",
+ "@firebase/app-types": "0.9.2",
+ "@firebase/auth": "1.8.0",
+ "@firebase/auth-compat": "0.5.15",
+ "@firebase/data-connect": "0.1.1",
+ "@firebase/database": "1.0.9",
+ "@firebase/database-compat": "2.0.0",
+ "@firebase/firestore": "4.7.4",
+ "@firebase/firestore-compat": "0.3.39",
+ "@firebase/functions": "0.11.9",
+ "@firebase/functions-compat": "0.3.15",
+ "@firebase/installations": "0.6.10",
+ "@firebase/installations-compat": "0.2.10",
+ "@firebase/messaging": "0.12.13",
+ "@firebase/messaging-compat": "0.2.13",
+ "@firebase/performance": "0.6.10",
+ "@firebase/performance-compat": "0.2.10",
+ "@firebase/remote-config": "0.4.10",
+ "@firebase/remote-config-compat": "0.2.10",
+ "@firebase/storage": "0.13.3",
+ "@firebase/storage-compat": "0.3.13",
+ "@firebase/util": "1.10.1",
+ "@firebase/vertexai": "1.0.0"
+ }
+ },
"node_modules/flat-cache": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@@ -4174,6 +4931,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
@@ -4367,15 +5133,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
@@ -4467,6 +5224,18 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
+ "node_modules/http-parser-js": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
+ "license": "MIT"
+ },
+ "node_modules/idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
+ "license": "ISC"
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -4728,6 +5497,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
@@ -5004,15 +5782,15 @@
}
},
"node_modules/jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
- "node": ">=4"
+ "node": ">=6"
}
},
"node_modules/json-parse-even-better-errors": {
@@ -5077,6 +5855,15 @@
"node": ">=4.0"
}
},
+ "node_modules/jwt-decode": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
+ "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/language-subtag-registry": {
"version": "0.3.23",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
@@ -5145,6 +5932,12 @@
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"license": "MIT"
},
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "license": "MIT"
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -5152,6 +5945,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==",
+ "license": "Apache-2.0"
+ },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -5545,9 +6344,9 @@
}
},
"node_modules/picocolors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
- "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"license": "ISC"
},
"node_modules/picomatch": {
@@ -5658,6 +6457,30 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
+ "node_modules/protobufjs": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
+ "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -5861,6 +6684,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -6004,6 +6836,26 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "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/safe-regex-test": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
@@ -6191,6 +7043,26 @@
"node": ">= 0.4"
}
},
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
"node_modules/string.prototype.includes": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz",
@@ -6296,7 +7168,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@@ -6334,18 +7205,6 @@
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
"license": "MIT"
},
- "node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
@@ -6490,15 +7349,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -6542,7 +7392,6 @@
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
- "dev": true,
"license": "0BSD"
},
"node_modules/type-check": {
@@ -6682,7 +7531,6 @@
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
- "dev": true,
"license": "MIT"
},
"node_modules/universalify": {
@@ -7002,6 +7850,29 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -7101,6 +7972,56 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -7108,6 +8029,15 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
@@ -7117,6 +8047,33 @@
"node": ">= 6"
}
},
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index 8842c7bea..969ea8861 100644
--- a/package.json
+++ b/package.json
@@ -2,13 +2,14 @@
"name": "@minimal/material-kit-react",
"author": "minimals.cc",
"licence": "MIT",
- "version": "2.0.0",
+ "version": "1.0.0",
"private": false,
"type": "module",
"scripts": {
"dev": "vite",
"start": "vite preview",
"build": "tsc && vite build",
+ "host": "firebase deploy --only hosting",
"lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"",
"fm:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\"",
@@ -32,9 +33,14 @@
"@iconify/react": "^5.0.2",
"@mui/lab": "^5.0.0-alpha.173",
"@mui/material": "^5.16.7",
+ "@paystack/inline-js": "^2.22.1",
"apexcharts": "^3.52.0",
+ "bcryptjs": "^2.4.3",
+ "crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
+ "firebase": "^11.0.1",
"history": "^5.3.0",
+ "jwt-decode": "^4.0.0",
"react": "^18.3.1",
"react-apexcharts": "^1.4.1",
"react-dom": "^18.3.1",
@@ -43,7 +49,10 @@
"simplebar-react": "^3.2.6"
},
"devDependencies": {
+ "@types/bcryptjs": "^2.4.6",
+ "@types/crypto-js": "^4.2.2",
"@types/node": "^22.5.0",
+ "@types/paystack__inline-js": "^1.0.0",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 000000000..829eda8fd
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+ Page Not Found
+
+
+
+
+
+
404
+
Page Not Found
+
The specified file was not found on this website. Please check the URL for mistakes and try again.
+
Why am I seeing this?
+
This page was generated by the Firebase Command-Line Interface. To modify it, edit the 404.html
file in your project's configured public
directory.
+
+
+
diff --git a/public/assets/icons/glass/ic-donate.svg b/public/assets/icons/glass/ic-donate.svg
new file mode 100644
index 000000000..b4d273e5c
--- /dev/null
+++ b/public/assets/icons/glass/ic-donate.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/icons/glass/ic-glass-bag.svg b/public/assets/icons/glass/ic-glass-bag.svg
deleted file mode 100644
index 5875b6f39..000000000
--- a/public/assets/icons/glass/ic-glass-bag.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-
diff --git a/public/assets/icons/glass/ic-wallet.svg b/public/assets/icons/glass/ic-wallet.svg
new file mode 100644
index 000000000..3b30bbf91
--- /dev/null
+++ b/public/assets/icons/glass/ic-wallet.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/icons/navbar/ic-donate.svg b/public/assets/icons/navbar/ic-donate.svg
new file mode 100644
index 000000000..80a633dc6
--- /dev/null
+++ b/public/assets/icons/navbar/ic-donate.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/icons/navbar/ic-exit.svg b/public/assets/icons/navbar/ic-exit.svg
new file mode 100644
index 000000000..4e637896c
--- /dev/null
+++ b/public/assets/icons/navbar/ic-exit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/icons/status/ic-failed.svg b/public/assets/icons/status/ic-failed.svg
new file mode 100644
index 000000000..0bda5ac56
--- /dev/null
+++ b/public/assets/icons/status/ic-failed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/icons/status/ic-pending.svg b/public/assets/icons/status/ic-pending.svg
new file mode 100644
index 000000000..b3df1c3da
--- /dev/null
+++ b/public/assets/icons/status/ic-pending.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/icons/status/ic-success.svg b/public/assets/icons/status/ic-success.svg
new file mode 100644
index 000000000..cdfff398c
--- /dev/null
+++ b/public/assets/icons/status/ic-success.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/images/logo.png b/public/assets/images/logo.png
new file mode 100644
index 000000000..8a5addbd3
Binary files /dev/null and b/public/assets/images/logo.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
index 5c435e6bb..26fe61f5b 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 000000000..0ebc2eb15
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+ Welcome to Firebase Hosting
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome
+
Firebase Hosting Setup Complete
+
You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!
+
Open Hosting Documentation
+
+ Firebase SDK Loading…
+
+
+
+
diff --git a/src/_mock/_countries.ts b/src/_mock/_countries.ts
new file mode 100644
index 000000000..1875f2c86
--- /dev/null
+++ b/src/_mock/_countries.ts
@@ -0,0 +1,1247 @@
+export default [
+ {
+ code: 'af',
+ label: 'Afghanistan',
+ icon: 'twemoji:flag-afghanistan',
+ },
+ {
+ code: 'ax',
+ label: 'Aland Islands',
+ icon: 'twemoji:flag-aland-islands',
+ },
+ {
+ code: 'al',
+ label: 'Albania',
+ icon: 'twemoji:flag-albania',
+ },
+ {
+ code: 'dz',
+ label: 'Algeria',
+ icon: 'twemoji:flag-algeria',
+ },
+ {
+ code: 'as',
+ label: 'American Samoa',
+ icon: 'twemoji:flag-american-samoa',
+ },
+ {
+ code: 'ad',
+ label: 'Andorra',
+ icon: 'twemoji:flag-andorra',
+ },
+ {
+ code: 'ao',
+ label: 'Angola',
+ icon: 'twemoji:flag-angola',
+ },
+ {
+ code: 'ai',
+ label: 'Anguilla',
+ icon: 'twemoji:flag-anguilla',
+ },
+ {
+ code: 'aq',
+ label: 'Antarctica',
+ icon: 'twemoji:flag-antarctica',
+ },
+ {
+ code: 'ag',
+ label: 'Antigua and Barbuda',
+ icon: 'twemoji:flag-antigua-and-barbuda',
+ },
+ {
+ code: 'ar',
+ label: 'Argentina',
+ icon: 'twemoji:flag-argentina',
+ },
+ {
+ code: 'am',
+ label: 'Armenia',
+ icon: 'twemoji:flag-armenia',
+ },
+ {
+ code: 'aw',
+ label: 'Aruba',
+ icon: 'twemoji:flag-aruba',
+ },
+ {
+ code: 'au',
+ label: 'Australia',
+ icon: 'twemoji:flag-australia',
+ },
+ {
+ code: 'at',
+ label: 'Austria',
+ icon: 'twemoji:flag-austria',
+ },
+ {
+ code: 'az',
+ label: 'Azerbaijan',
+ icon: 'twemoji:flag-azerbaijan',
+ },
+ {
+ code: 'bs',
+ label: 'Bahamas',
+ icon: 'twemoji:flag-bahamas',
+ },
+ {
+ code: 'bh',
+ label: 'Bahrain',
+ icon: 'twemoji:flag-bahrain',
+ },
+ {
+ code: 'bd',
+ label: 'Bangladesh',
+ icon: 'twemoji:flag-bangladesh',
+ },
+ {
+ code: 'bb',
+ label: 'Barbados',
+ icon: 'twemoji:flag-barbados',
+ },
+ {
+ code: 'by',
+ label: 'Belarus',
+ icon: 'twemoji:flag-belarus',
+ },
+ {
+ code: 'be',
+ label: 'Belgium',
+ icon: 'twemoji:flag-belgium',
+ },
+ {
+ code: 'bz',
+ label: 'Belize',
+ icon: 'twemoji:flag-belize',
+ },
+ {
+ code: 'bj',
+ label: 'Benin',
+ icon: 'twemoji:flag-benin',
+ },
+ {
+ code: 'bm',
+ label: 'Bermuda',
+ icon: 'twemoji:flag-bermuda',
+ },
+ {
+ code: 'bt',
+ label: 'Bhutan',
+ icon: 'twemoji:flag-bhutan',
+ },
+ {
+ code: 'bo',
+ label: 'Bolivia',
+ icon: 'twemoji:flag-bolivia',
+ },
+ {
+ code: 'ba',
+ label: 'Bosnia and Herzegovina',
+ icon: 'twemoji:flag-bosnia-and-herzegovina',
+ },
+ {
+ code: 'bw',
+ label: 'Botswana',
+ icon: 'twemoji:flag-botswana',
+ },
+ {
+ code: 'bv',
+ label: 'Bouvet Island',
+ icon: 'twemoji:flag-bouvet-island',
+ },
+ {
+ code: 'br',
+ label: 'Brazil',
+ icon: 'twemoji:flag-brazil',
+ },
+ {
+ code: 'io',
+ label: 'British Indian Ocean Territory',
+ icon: 'twemoji:flag-british-indian-ocean-territory',
+ },
+ {
+ code: 'vg',
+ label: 'British Virgin Islands',
+ icon: 'twemoji:flag-british-virgin-islands',
+ },
+ {
+ code: 'bn',
+ label: 'Brunei',
+ icon: 'twemoji:flag-brunei',
+ },
+ {
+ code: 'bg',
+ label: 'Bulgaria',
+ icon: 'twemoji:flag-bulgaria',
+ },
+ {
+ code: 'bf',
+ label: 'Burkina Faso',
+ icon: 'twemoji:flag-burkina-faso',
+ },
+ {
+ code: 'bi',
+ label: 'Burundi',
+ icon: 'twemoji:flag-burundi',
+ },
+ {
+ code: 'kh',
+ label: 'Cambodia',
+ icon: 'twemoji:flag-cambodia',
+ },
+ {
+ code: 'cm',
+ label: 'Cameroon',
+ icon: 'twemoji:flag-cameroon',
+ },
+ {
+ code: 'ca',
+ label: 'Canada',
+ icon: 'twemoji:flag-canada',
+ },
+ {
+ code: 'cv',
+ label: 'Cape Verde',
+ icon: 'twemoji:flag-cape-verde',
+ },
+ {
+ code: 'ky',
+ label: 'Cayman Islands',
+ icon: 'twemoji:flag-cayman-islands',
+ },
+ {
+ code: 'cf',
+ label: 'Central African Republic',
+ icon: 'twemoji:flag-central-african-republic',
+ },
+ {
+ code: 'td',
+ label: 'Chad',
+ icon: 'twemoji:flag-chad',
+ },
+ {
+ code: 'cl',
+ label: 'Chile',
+ icon: 'twemoji:flag-chile',
+ },
+ {
+ code: 'cn',
+ label: 'China',
+ icon: 'twemoji:flag-china',
+ },
+ {
+ code: 'cx',
+ label: 'Christmas Island',
+ icon: 'twemoji:flag-christmas-island',
+ },
+ {
+ code: 'cc',
+ label: 'Cocos Islands',
+ icon: 'twemoji:flag-cocos-keeling-islands',
+ },
+ {
+ code: 'co',
+ label: 'Colombia',
+ icon: 'twemoji:flag-colombia',
+ },
+ {
+ code: 'km',
+ label: 'Comoros',
+ icon: 'twemoji:flag-comoros',
+ },
+ {
+ code: 'ck',
+ label: 'Cook Islands',
+ icon: 'twemoji:flag-cook-islands',
+ },
+ {
+ code: 'cr',
+ label: 'Costa Rica',
+ icon: 'twemoji:flag-costa-rica',
+ },
+ {
+ code: 'hr',
+ label: 'Croatia',
+ icon: 'twemoji:flag-croatia',
+ },
+ {
+ code: 'cu',
+ label: 'Cuba',
+ icon: 'twemoji:flag-cuba',
+ },
+ {
+ code: 'cw',
+ label: 'Curacao',
+ icon: 'twemoji:flag-curacao',
+ },
+ {
+ code: 'cy',
+ label: 'Cyprus',
+ icon: 'twemoji:flag-cyprus',
+ },
+ {
+ code: 'cz',
+ label: 'Czech Republic',
+ icon: 'twemoji:flag-czechia',
+ },
+ {
+ code: 'cd',
+ label: 'Democratic Republic of the Congo',
+ icon: 'twemoji:flag-congo-kinshasa',
+ },
+ {
+ code: 'dk',
+ label: 'Denmark',
+ icon: 'twemoji:flag-denmark',
+ },
+ {
+ code: 'dj',
+ label: 'Djibouti',
+ icon: 'twemoji:flag-djibouti',
+ },
+ {
+ code: 'dm',
+ label: 'Dominica',
+ icon: 'twemoji:flag-dominica',
+ },
+ {
+ code: 'do',
+ label: 'Dominican Republic',
+ icon: 'twemoji:flag-dominican-republic',
+ },
+ {
+ code: 'tl',
+ label: 'East Timor',
+ icon: 'twemoji:flag-timor-leste',
+ },
+ {
+ code: 'ec',
+ label: 'Ecuador',
+ icon: 'twemoji:flag-ecuador',
+ },
+ {
+ code: 'eg',
+ label: 'Egypt',
+ icon: 'twemoji:flag-egypt',
+ },
+ {
+ code: 'sv',
+ label: 'El Salvador',
+ icon: 'twemoji:flag-el-salvador',
+ },
+ {
+ code: 'gq',
+ label: 'Equatorial Guinea',
+ icon: 'twemoji:flag-equatorial-guinea',
+ },
+ {
+ code: 'er',
+ label: 'Eritrea',
+ icon: 'twemoji:flag-eritrea',
+ },
+ {
+ code: 'ee',
+ label: 'Estonia',
+ icon: 'twemoji:flag-estonia',
+ },
+ {
+ code: 'et',
+ label: 'Ethiopia',
+ icon: 'twemoji:flag-ethiopia',
+ },
+ {
+ code: 'fk',
+ label: 'Falkland Islands',
+ icon: 'twemoji:flag-falkland-islands',
+ },
+ {
+ code: 'fo',
+ label: 'Faroe Islands',
+ icon: 'twemoji:flag-faroe-islands',
+ },
+ {
+ code: 'fj',
+ label: 'Fiji',
+ icon: 'twemoji:flag-fiji',
+ },
+ {
+ code: 'fi',
+ label: 'Finland',
+ icon: 'twemoji:flag-finland',
+ },
+ {
+ code: 'fr',
+ label: 'France',
+ icon: 'twemoji:flag-france',
+ },
+ {
+ code: 'gf',
+ label: 'French Guiana',
+ icon: 'twemoji:flag-french-guiana',
+ },
+ {
+ code: 'pf',
+ label: 'French Polynesia',
+ icon: 'twemoji:flag-french-polynesia',
+ },
+ {
+ code: 'tf',
+ label: 'French Southern Territories',
+ icon: 'twemoji:flag-french-southern-territories',
+ },
+ {
+ code: 'ga',
+ label: 'Gabon',
+ icon: 'twemoji:flag-gabon',
+ },
+ {
+ code: 'gm',
+ label: 'Gambia',
+ icon: 'twemoji:flag-gambia',
+ },
+ {
+ code: 'ge',
+ label: 'Georgia',
+ icon: 'twemoji:flag-georgia',
+ },
+ {
+ code: 'de',
+ label: 'Germany',
+ icon: 'twemoji:flag-germany',
+ },
+ {
+ code: 'gh',
+ label: 'Ghana',
+ icon: 'twemoji:flag-ghana',
+ },
+ {
+ code: 'gi',
+ label: 'Gibraltar',
+ icon: 'twemoji:flag-gibraltar',
+ },
+ {
+ code: 'gr',
+ label: 'Greece',
+ icon: 'twemoji:flag-greece',
+ },
+ {
+ code: 'gl',
+ label: 'Greenland',
+ icon: 'twemoji:flag-greenland',
+ },
+ {
+ code: 'gd',
+ label: 'Grenada',
+ icon: 'twemoji:flag-grenada',
+ },
+ {
+ code: 'gp',
+ label: 'Guadeloupe',
+ icon: 'twemoji:flag-guadeloupe',
+ },
+ {
+ code: 'gu',
+ label: 'Guam',
+ icon: 'twemoji:flag-guam',
+ },
+ {
+ code: 'gt',
+ label: 'Guatemala',
+ icon: 'twemoji:flag-guatemala',
+ },
+ {
+ code: 'gg',
+ label: 'Guernsey',
+ icon: 'twemoji:flag-guernsey',
+ },
+ {
+ code: 'gn',
+ label: 'Guinea',
+ icon: 'twemoji:flag-guinea',
+ },
+ {
+ code: 'gw',
+ label: 'Guinea-Bissau',
+ icon: 'twemoji:flag-guinea-bissau',
+ },
+ {
+ code: 'gy',
+ label: 'Guyana',
+ icon: 'twemoji:flag-guyana',
+ },
+ {
+ code: 'ht',
+ label: 'Haiti',
+ icon: 'twemoji:flag-haiti',
+ },
+ {
+ code: 'hm',
+ label: 'Heard Island and McDonald Islands',
+ icon: 'twemoji:flag-heard-and-mcdonald-islands',
+ },
+ {
+ code: 'hn',
+ label: 'Honduras',
+ icon: 'twemoji:flag-honduras',
+ },
+ {
+ code: 'hk',
+ label: 'Hong Kong',
+ icon: 'twemoji:flag-hong-kong-sar-china',
+ },
+ {
+ code: 'hu',
+ label: 'Hungary',
+ icon: 'twemoji:flag-hungary',
+ },
+ {
+ code: 'is',
+ label: 'Iceland',
+ icon: 'twemoji:flag-iceland',
+ },
+ {
+ code: 'in',
+ label: 'India',
+ icon: 'twemoji:flag-india',
+ },
+ {
+ code: 'id',
+ label: 'Indonesia',
+ icon: 'twemoji:flag-indonesia',
+ },
+ {
+ code: 'ir',
+ label: 'Iran',
+ icon: 'twemoji:flag-iran',
+ },
+ {
+ code: 'iq',
+ label: 'Iraq',
+ icon: 'twemoji:flag-iraq',
+ },
+ {
+ code: 'ie',
+ label: 'Ireland',
+ icon: 'twemoji:flag-ireland',
+ },
+ {
+ code: 'im',
+ label: 'Isle of Man',
+ icon: 'twemoji:flag-isle-of-man',
+ },
+ {
+ code: 'il',
+ label: 'Israel',
+ icon: 'twemoji:flag-israel',
+ },
+ {
+ code: 'it',
+ label: 'Italy',
+ icon: 'twemoji:flag-italy',
+ },
+ {
+ code: 'ci',
+ label: 'Ivory Coast',
+ icon: 'twemoji:flag-cote-divoire',
+ },
+ {
+ code: 'jm',
+ label: 'Jamaica',
+ icon: 'twemoji:flag-jamaica',
+ },
+ {
+ code: 'jp',
+ label: 'Japan',
+ icon: 'twemoji:flag-japan',
+ },
+ {
+ code: 'je',
+ label: 'Jersey',
+ icon: 'twemoji:flag-jersey',
+ },
+ {
+ code: 'jo',
+ label: 'Jordan',
+ icon: 'twemoji:flag-jordan',
+ },
+ {
+ code: 'kz',
+ label: 'Kazakhstan',
+ icon: 'twemoji:flag-kazakhstan',
+ },
+ {
+ code: 'ke',
+ label: 'Kenya',
+ icon: 'twemoji:flag-kenya',
+ },
+ {
+ code: 'ki',
+ label: 'Kiribati',
+ icon: 'twemoji:flag-kiribati',
+ },
+ {
+ code: 'xk',
+ label: 'Kosovo',
+ icon: 'twemoji:flag-kosovo',
+ },
+ {
+ code: 'kw',
+ label: 'Kuwait',
+ icon: 'twemoji:flag-kuwait',
+ },
+ {
+ code: 'kg',
+ label: 'Kyrgyzstan',
+ icon: 'twemoji:flag-kyrgyzstan',
+ },
+ {
+ code: 'la',
+ label: 'Laos',
+ icon: 'twemoji:flag-laos',
+ },
+ {
+ code: 'lv',
+ label: 'Latvia',
+ icon: 'twemoji:flag-latvia',
+ },
+ {
+ code: 'lb',
+ label: 'Lebanon',
+ icon: 'twemoji:flag-lebanon',
+ },
+ {
+ code: 'ls',
+ label: 'Lesotho',
+ icon: 'twemoji:flag-lesotho',
+ },
+ {
+ code: 'lr',
+ label: 'Liberia',
+ icon: 'twemoji:flag-liberia',
+ },
+ {
+ code: 'ly',
+ label: 'Libya',
+ icon: 'twemoji:flag-libya',
+ },
+ {
+ code: 'li',
+ label: 'Liechtenstein',
+ icon: 'twemoji:flag-liechtenstein',
+ },
+ {
+ code: 'lt',
+ label: 'Lithuania',
+ icon: 'twemoji:flag-lithuania',
+ },
+ {
+ code: 'lu',
+ label: 'Luxembourg',
+ icon: 'twemoji:flag-luxembourg',
+ },
+ {
+ code: 'mo',
+ label: 'Macao',
+ icon: 'twemoji:flag-macao-sar-china',
+ },
+ {
+ code: 'mk',
+ label: 'Macedonia',
+ icon: 'twemoji:flag-north-macedonia',
+ },
+ {
+ code: 'mg',
+ label: 'Madagascar',
+ icon: 'twemoji:flag-madagascar',
+ },
+ {
+ code: 'mw',
+ label: 'Malawi',
+ icon: 'twemoji:flag-malawi',
+ },
+ {
+ code: 'my',
+ label: 'Malaysia',
+ icon: 'twemoji:flag-malaysia',
+ },
+ {
+ code: 'mv',
+ label: 'Maldives',
+ icon: 'twemoji:flag-maldives',
+ },
+ {
+ code: 'ml',
+ label: 'Mali',
+ icon: 'twemoji:flag-mali',
+ },
+ {
+ code: 'mt',
+ label: 'Malta',
+ icon: 'twemoji:flag-malta',
+ },
+ {
+ code: 'mh',
+ label: 'Marshall Islands',
+ icon: 'twemoji:flag-marshall-islands',
+ },
+ {
+ code: 'mq',
+ label: 'Martinique',
+ icon: 'twemoji:flag-martinique',
+ },
+ {
+ code: 'mr',
+ label: 'Mauritania',
+ icon: 'twemoji:flag-mauritania',
+ },
+ {
+ code: 'mu',
+ label: 'Mauritius',
+ icon: 'twemoji:flag-mauritius',
+ },
+ {
+ code: 'yt',
+ label: 'Mayotte',
+ icon: 'twemoji:flag-mayotte',
+ },
+ {
+ code: 'mx',
+ label: 'Mexico',
+ icon: 'twemoji:flag-mexico',
+ },
+ {
+ code: 'fm',
+ label: 'Micronesia',
+ icon: 'twemoji:flag-micronesia',
+ },
+ {
+ code: 'md',
+ label: 'Moldova',
+ icon: 'twemoji:flag-moldova',
+ },
+ {
+ code: 'mc',
+ label: 'Monaco',
+ icon: 'twemoji:flag-monaco',
+ },
+ {
+ code: 'mn',
+ label: 'Mongolia',
+ icon: 'twemoji:flag-mongolia',
+ },
+ {
+ code: 'me',
+ label: 'Montenegro',
+ icon: 'twemoji:flag-montenegro',
+ },
+ {
+ code: 'ms',
+ label: 'Montserrat',
+ icon: 'twemoji:flag-montserrat',
+ },
+ {
+ code: 'ma',
+ label: 'Morocco',
+ icon: 'twemoji:flag-morocco',
+ },
+ {
+ code: 'mz',
+ label: 'Mozambique',
+ icon: 'twemoji:flag-mozambique',
+ },
+ {
+ code: 'mm',
+ label: 'Myanmar',
+ icon: 'twemoji:flag-myanmar-burma',
+ },
+ {
+ code: 'na',
+ label: 'Namibia',
+ icon: 'twemoji:flag-namibia',
+ },
+ {
+ code: 'nr',
+ label: 'Nauru',
+ icon: 'twemoji:flag-nauru',
+ },
+ {
+ code: 'np',
+ label: 'Nepal',
+ icon: 'twemoji:flag-nepal',
+ },
+ {
+ code: 'nl',
+ label: 'Netherlands',
+ icon: 'twemoji:flag-netherlands',
+ },
+ {
+ code: 'nc',
+ label: 'New Caledonia',
+ icon: 'twemoji:flag-new-caledonia',
+ },
+ {
+ code: 'nz',
+ label: 'New Zealand',
+ icon: 'twemoji:flag-new-zealand',
+ },
+ {
+ code: 'ni',
+ label: 'Nicaragua',
+ icon: 'twemoji:flag-nicaragua',
+ },
+ {
+ code: 'ne',
+ label: 'Niger',
+ icon: 'twemoji:flag-niger',
+ },
+ {
+ code: 'ng',
+ label: 'Nigeria',
+ icon: 'twemoji:flag-nigeria',
+ },
+ {
+ code: 'nu',
+ label: 'Niue',
+ icon: 'twemoji:flag-niue',
+ },
+ {
+ code: 'nf',
+ label: 'Norfolk Island',
+ icon: 'twemoji:flag-norfolk-island',
+ },
+ {
+ code: 'kp',
+ label: 'North Korea',
+ icon: 'twemoji:flag-north-korea',
+ },
+ {
+ code: 'mp',
+ label: 'Northern Mariana Islands',
+ icon: 'twemoji:flag-northern-mariana-islands',
+ },
+ {
+ code: 'no',
+ label: 'Norway',
+ icon: 'twemoji:flag-norway',
+ },
+ {
+ code: 'om',
+ label: 'Oman',
+ icon: 'twemoji:flag-oman',
+ },
+ {
+ code: 'pk',
+ label: 'Pakistan',
+ icon: 'twemoji:flag-pakistan',
+ },
+ {
+ code: 'pw',
+ label: 'Palau',
+ icon: 'twemoji:flag-palau',
+ },
+ {
+ code: 'ps',
+ label: 'Palestinian Territory',
+ icon: 'twemoji:flag-palestinian-territories',
+ },
+ {
+ code: 'pa',
+ label: 'Panama',
+ icon: 'twemoji:flag-panama',
+ },
+ {
+ code: 'pg',
+ label: 'Papua New Guinea',
+ icon: 'twemoji:flag-papua-new-guinea',
+ },
+ {
+ code: 'py',
+ label: 'Paraguay',
+ icon: 'twemoji:flag-paraguay',
+ },
+ {
+ code: 'pe',
+ label: 'Peru',
+ icon: 'twemoji:flag-peru',
+ },
+ {
+ code: 'ph',
+ label: 'Philippines',
+ icon: 'twemoji:flag-philippines',
+ },
+ {
+ code: 'pn',
+ label: 'Pitcairn',
+ icon: 'twemoji:flag-pitcairn-islands',
+ },
+ {
+ code: 'pl',
+ label: 'Poland',
+ icon: 'twemoji:flag-poland',
+ },
+ {
+ code: 'pt',
+ label: 'Portugal',
+ icon: 'twemoji:flag-portugal',
+ },
+ {
+ code: 'pr',
+ label: 'Puerto Rico',
+ icon: 'twemoji:flag-puerto-rico',
+ },
+ {
+ code: 'qa',
+ label: 'Qatar',
+ icon: 'twemoji:flag-qatar',
+ },
+ {
+ code: 'cg',
+ label: 'Republic of the Congo',
+ icon: 'twemoji:flag-congo-brazzaville',
+ },
+ {
+ code: 're',
+ label: 'Reunion',
+ icon: 'twemoji:flag-reunion',
+ },
+ {
+ code: 'ro',
+ label: 'Romania',
+ icon: 'twemoji:flag-romania',
+ },
+ {
+ code: 'ru',
+ label: 'Russia',
+ icon: 'twemoji:flag-russia',
+ },
+ {
+ code: 'rw',
+ label: 'Rwanda',
+ icon: 'twemoji:flag-rwanda',
+ },
+ {
+ code: 'bl',
+ label: 'Saint Barthelemy',
+ icon: 'twemoji:flag-st-barthelemy',
+ },
+ {
+ code: 'sh',
+ label: 'Saint Helena',
+ icon: 'twemoji:flag-st-helena',
+ },
+ {
+ code: 'kn',
+ label: 'Saint Kitts and Nevis',
+ icon: 'twemoji:flag-st-kitts-and-nevis',
+ },
+ {
+ code: 'lc',
+ label: 'Saint Lucia',
+ icon: 'twemoji:flag-st-lucia',
+ },
+ {
+ code: 'mf',
+ label: 'Saint Martin',
+ icon: 'twemoji:flag-st-martin',
+ },
+ {
+ code: 'pm',
+ label: 'Saint Pierre and Miquelon',
+ icon: 'twemoji:flag-st-pierre-and-miquelon',
+ },
+ {
+ code: 'vc',
+ label: 'Saint Vincent and the Grenadines',
+ icon: 'twemoji:flag-st-vincent-and-grenadines',
+ },
+ {
+ code: 'ws',
+ label: 'Samoa',
+ icon: 'twemoji:flag-samoa',
+ },
+ {
+ code: 'sm',
+ label: 'San Marino',
+ icon: 'twemoji:flag-san-marino',
+ },
+ {
+ code: 'st',
+ label: 'Sao Tome and Principe',
+ icon: 'twemoji:flag-sao-tome-and-principe',
+ },
+ {
+ code: 'sa',
+ label: 'Saudi Arabia',
+ icon: 'twemoji:flag-saudi-arabia',
+ },
+ {
+ code: 'sn',
+ label: 'Senegal',
+ icon: 'twemoji:flag-senegal',
+ },
+ {
+ code: 'rs',
+ label: 'Serbia',
+ icon: 'twemoji:flag-serbia',
+ },
+ {
+ code: 'sc',
+ label: 'Seychelles',
+ icon: 'twemoji:flag-seychelles',
+ },
+ {
+ code: 'sl',
+ label: 'Sierra Leone',
+ icon: 'twemoji:flag-sierra-leone',
+ },
+ {
+ code: 'sg',
+ label: 'Singapore',
+ icon: 'twemoji:flag-singapore',
+ },
+ {
+ code: 'sx',
+ label: 'Sint Maarten',
+ icon: 'twemoji:flag-sint-maarten',
+ },
+ {
+ code: 'sk',
+ label: 'Slovakia',
+ icon: 'twemoji:flag-slovakia',
+ },
+ {
+ code: 'si',
+ label: 'Slovenia',
+ icon: 'twemoji:flag-slovenia',
+ },
+ {
+ code: 'sb',
+ label: 'Solomon Islands',
+ icon: 'twemoji:flag-solomon-islands',
+ },
+ {
+ code: 'so',
+ label: 'Somalia',
+ icon: 'twemoji:flag-somalia',
+ },
+ {
+ code: 'za',
+ label: 'South Africa',
+ icon: 'twemoji:flag-south-africa',
+ },
+ {
+ code: 'gs',
+ label: 'South Georgia and the South Sandwich Islands',
+ icon: 'twemoji:flag-south-georgia-and-south-sandwich-islands',
+ },
+ {
+ code: 'kr',
+ label: 'South Korea',
+ icon: 'twemoji:flag-south-korea',
+ },
+ {
+ code: 'ss',
+ label: 'South Sudan',
+ icon: 'twemoji:flag-south-sudan',
+ },
+ {
+ code: 'es',
+ label: 'Spain',
+ icon: 'twemoji:flag-spain',
+ },
+ {
+ code: 'lk',
+ label: 'Sri Lanka',
+ icon: 'twemoji:flag-sri-lanka',
+ },
+ {
+ code: 'sd',
+ label: 'Sudan',
+ icon: 'twemoji:flag-sudan',
+ },
+ {
+ code: 'sr',
+ label: 'Suriname',
+ icon: 'twemoji:flag-suriname',
+ },
+ {
+ code: 'sj',
+ label: 'Svalbard and Jan Mayen',
+ icon: 'twemoji:flag-svalbard-and-jan-mayen',
+ },
+ {
+ code: 'sz',
+ label: 'Swaziland',
+ icon: 'emojione-v1:flag-for-swaziland',
+ },
+ {
+ code: 'se',
+ label: 'Sweden',
+ icon: 'twemoji:flag-sweden',
+ },
+ {
+ code: 'ch',
+ label: 'Switzerland',
+ icon: 'twemoji:flag-switzerland',
+ },
+ {
+ code: 'sy',
+ label: 'Syria',
+ icon: 'twemoji:flag-syria',
+ },
+ {
+ code: 'tw',
+ label: 'Taiwan',
+ icon: 'twemoji:flag-taiwan',
+ },
+ {
+ code: 'tj',
+ label: 'Tajikistan',
+ icon: 'twemoji:flag-tajikistan',
+ },
+ {
+ code: 'tz',
+ label: 'Tanzania',
+ icon: 'twemoji:flag-tanzania',
+ },
+ {
+ code: 'th',
+ label: 'Thailand',
+ icon: 'twemoji:flag-thailand',
+ },
+ {
+ code: 'tg',
+ label: 'Togo',
+ icon: 'twemoji:flag-togo',
+ },
+ {
+ code: 'tk',
+ label: 'Tokelau',
+ icon: 'twemoji:flag-tokelau',
+ },
+ {
+ code: 'to',
+ label: 'Tonga',
+ icon: 'twemoji:flag-tonga',
+ },
+ {
+ code: 'tt',
+ label: 'Trinidad and Tobago',
+ icon: 'twemoji:flag-trinidad-and-tobago',
+ },
+ {
+ code: 'tn',
+ label: 'Tunisia',
+ icon: 'twemoji:flag-tunisia',
+ },
+ {
+ code: 'tr',
+ label: 'Turkey',
+ icon: 'twemoji:flag-for-flag-turkey',
+ },
+ {
+ code: 'tm',
+ label: 'Turkmenistan',
+ icon: 'twemoji:flag-turkmenistan',
+ },
+ {
+ code: 'tc',
+ label: 'Turks and Caicos Islands',
+ icon: 'twemoji:flag-turks-and-caicos-islands',
+ },
+ {
+ code: 'tv',
+ label: 'Tuvalu',
+ icon: 'twemoji:flag-tuvalu',
+ },
+ {
+ code: 'vi',
+ label: 'U.S. Virgin Islands',
+ icon: 'twemoji:flag-us-virgin-islands',
+ },
+ {
+ code: 'ug',
+ label: 'Uganda',
+ icon: 'twemoji:flag-uganda',
+ },
+ {
+ code: 'ua',
+ label: 'Ukraine',
+ icon: 'twemoji:flag-ukraine',
+ },
+ {
+ code: 'ae',
+ label: 'United Arab Emirates',
+ icon: 'twemoji:flag-united-arab-emirates',
+ },
+ {
+ code: 'gb',
+ label: 'United Kingdom',
+ icon: 'twemoji:flag-united-kingdom',
+ },
+ {
+ code: 'us',
+ label: 'United States',
+ icon: 'twemoji:flag-united-states',
+ },
+ {
+ code: 'um',
+ label: 'United States Minor Outlying Islands',
+ icon: 'twemoji:flag-us-outlying-islands',
+ },
+ {
+ code: 'uy',
+ label: 'Uruguay',
+ icon: 'twemoji:flag-uruguay',
+ },
+ {
+ code: 'uz',
+ label: 'Uzbekistan',
+ icon: 'twemoji:flag-uzbekistan',
+ },
+ {
+ code: 'vu',
+ label: 'Vanuatu',
+ icon: 'twemoji:flag-vanuatu',
+ },
+ {
+ code: 'va',
+ label: 'Vatican',
+ icon: 'twemoji:flag-vatican-city',
+ },
+ {
+ code: 've',
+ label: 'Venezuela',
+ icon: 'twemoji:flag-venezuela',
+ },
+ {
+ code: 'vn',
+ label: 'Vietnam',
+ icon: 'twemoji:flag-vietnam',
+ },
+ {
+ code: 'wf',
+ label: 'Wallis and Futuna',
+ icon: 'twemoji:flag-wallis-and-futuna',
+ },
+ {
+ code: 'eh',
+ label: 'Western Sahara',
+ icon: 'twemoji:flag-western-sahara',
+ },
+ {
+ code: 'ye',
+ label: 'Yemen',
+ icon: 'twemoji:flag-yemen',
+ },
+ {
+ code: 'zm',
+ label: 'Zambia',
+ icon: 'twemoji:flag-zambia',
+ },
+ {
+ code: 'zw',
+ label: 'Zimbabwe',
+ icon: 'twemoji:flag-zimbabwe',
+ },
+];
diff --git a/src/_mock/_data.ts b/src/_mock/_data.ts
index d6dadc0eb..4455c52c2 100644
--- a/src/_mock/_data.ts
+++ b/src/_mock/_data.ts
@@ -1,7 +1,12 @@
+
+import type { ContributionProps } from 'src/sections/contributions/contributions-table-row';
+
import {
_id,
_price,
_times,
+ _months,
+ _amount,
_company,
_boolean,
_fullName,
@@ -63,6 +68,18 @@ export const _posts = [...Array(23)].map((_, index) => ({
// ----------------------------------------------------------------------
+export const _contributions: ContributionProps[] = [...Array(24)].map((_, index) => ({
+ id: _id(index),
+ sender: { id: `${_id(index)}'2'`, name: _fullName(index) },
+ months: _months(Math.ceil(Math.random() * 3)),
+ status: index % 4 ? 'success' : 'failed',
+ timestamp: new Date(),
+ amount: _amount(),
+ code: 's',
+}));
+
+// ----------------------------------------------------------------------
+
const COLORS = [
'#00AB55',
'#000000',
@@ -116,6 +133,272 @@ export const _langs = [
},
];
+export const _countries = [
+ {
+ value: 'GH',
+ icon: 'twemoji:flag-ghana',
+ label: 'Ghana',
+ },
+ {
+ value: 'ng',
+ icon: 'twemoji:flag-nigeria',
+ label: 'Nigeria',
+ },
+];
+
+export const COUNTRIES = {
+ BD: 'Bangladesh',
+ BE: 'Belgium',
+ BF: 'Burkina Faso',
+ BG: 'Bulgaria',
+ BA: 'Bosnia and Herzegovina',
+ BB: 'Barbados',
+ WF: 'Wallis and Futuna',
+ BL: 'Saint Barthelemy',
+ BM: 'Bermuda',
+ BN: 'Brunei',
+ BO: 'Bolivia',
+ BH: 'Bahrain',
+ BI: 'Burundi',
+ BJ: 'Benin',
+ BT: 'Bhutan',
+ JM: 'Jamaica',
+ BV: 'Bouvet Island',
+ BW: 'Botswana',
+ WS: 'Samoa',
+ BQ: 'Bonaire, Saint Eustatius and Saba ',
+ BR: 'Brazil',
+ BS: 'Bahamas',
+ JE: 'Jersey',
+ BY: 'Belarus',
+ BZ: 'Belize',
+ RU: 'Russia',
+ RW: 'Rwanda',
+ RS: 'Serbia',
+ TL: 'East Timor',
+ RE: 'Reunion',
+ TM: 'Turkmenistan',
+ TJ: 'Tajikistan',
+ RO: 'Romania',
+ TK: 'Tokelau',
+ GW: 'Guinea-Bissau',
+ GU: 'Guam',
+ GT: 'Guatemala',
+ GS: 'South Georgia and the South Sandwich Islands',
+ GR: 'Greece',
+ GQ: 'Equatorial Guinea',
+ GP: 'Guadeloupe',
+ JP: 'Japan',
+ GY: 'Guyana',
+ GG: 'Guernsey',
+ GF: 'French Guiana',
+ GE: 'Georgia',
+ GD: 'Grenada',
+ GB: 'United Kingdom',
+ GA: 'Gabon',
+ SV: 'El Salvador',
+ GN: 'Guinea',
+ GM: 'Gambia',
+ GL: 'Greenland',
+ GI: 'Gibraltar',
+ GH: 'Ghana',
+ OM: 'Oman',
+ TN: 'Tunisia',
+ JO: 'Jordan',
+ HR: 'Croatia',
+ HT: 'Haiti',
+ HU: 'Hungary',
+ HK: 'Hong Kong',
+ HN: 'Honduras',
+ HM: 'Heard Island and McDonald Islands',
+ VE: 'Venezuela',
+ PR: 'Puerto Rico',
+ PS: 'Palestinian Territory',
+ PW: 'Palau',
+ PT: 'Portugal',
+ SJ: 'Svalbard and Jan Mayen',
+ PY: 'Paraguay',
+ IQ: 'Iraq',
+ PA: 'Panama',
+ PF: 'French Polynesia',
+ PG: 'Papua New Guinea',
+ PE: 'Peru',
+ PK: 'Pakistan',
+ PH: 'Philippines',
+ PN: 'Pitcairn',
+ PL: 'Poland',
+ PM: 'Saint Pierre and Miquelon',
+ ZM: 'Zambia',
+ EH: 'Western Sahara',
+ EE: 'Estonia',
+ EG: 'Egypt',
+ ZA: 'South Africa',
+ EC: 'Ecuador',
+ IT: 'Italy',
+ VN: 'Vietnam',
+ SB: 'Solomon Islands',
+ ET: 'Ethiopia',
+ SO: 'Somalia',
+ ZW: 'Zimbabwe',
+ SA: 'Saudi Arabia',
+ ES: 'Spain',
+ ER: 'Eritrea',
+ ME: 'Montenegro',
+ MD: 'Moldova',
+ MG: 'Madagascar',
+ MF: 'Saint Martin',
+ MA: 'Morocco',
+ MC: 'Monaco',
+ UZ: 'Uzbekistan',
+ MM: 'Myanmar',
+ ML: 'Mali',
+ MO: 'Macao',
+ MN: 'Mongolia',
+ MH: 'Marshall Islands',
+ MK: 'Macedonia',
+ MU: 'Mauritius',
+ MT: 'Malta',
+ MW: 'Malawi',
+ MV: 'Maldives',
+ MQ: 'Martinique',
+ MP: 'Northern Mariana Islands',
+ MS: 'Montserrat',
+ MR: 'Mauritania',
+ IM: 'Isle of Man',
+ UG: 'Uganda',
+ TZ: 'Tanzania',
+ MY: 'Malaysia',
+ MX: 'Mexico',
+ IL: 'Israel',
+ FR: 'France',
+ IO: 'British Indian Ocean Territory',
+ SH: 'Saint Helena',
+ FI: 'Finland',
+ FJ: 'Fiji',
+ FK: 'Falkland Islands',
+ FM: 'Micronesia',
+ FO: 'Faroe Islands',
+ NI: 'Nicaragua',
+ NL: 'Netherlands',
+ NO: 'Norway',
+ NA: 'Namibia',
+ VU: 'Vanuatu',
+ NC: 'New Caledonia',
+ NE: 'Niger',
+ NF: 'Norfolk Island',
+ NG: 'Nigeria',
+ NZ: 'New Zealand',
+ NP: 'Nepal',
+ NR: 'Nauru',
+ NU: 'Niue',
+ CK: 'Cook Islands',
+ XK: 'Kosovo',
+ CI: 'Ivory Coast',
+ CH: 'Switzerland',
+ CO: 'Colombia',
+ CN: 'China',
+ CM: 'Cameroon',
+ CL: 'Chile',
+ CC: 'Cocos Islands',
+ CA: 'Canada',
+ CG: 'Republic of the Congo',
+ CF: 'Central African Republic',
+ CD: 'Democratic Republic of the Congo',
+ CZ: 'Czech Republic',
+ CY: 'Cyprus',
+ CX: 'Christmas Island',
+ CR: 'Costa Rica',
+ CW: 'Curacao',
+ CV: 'Cape Verde',
+ CU: 'Cuba',
+ SZ: 'Swaziland',
+ SY: 'Syria',
+ SX: 'Sint Maarten',
+ KG: 'Kyrgyzstan',
+ KE: 'Kenya',
+ SS: 'South Sudan',
+ SR: 'Suriname',
+ KI: 'Kiribati',
+ KH: 'Cambodia',
+ KN: 'Saint Kitts and Nevis',
+ KM: 'Comoros',
+ ST: 'Sao Tome and Principe',
+ SK: 'Slovakia',
+ KR: 'South Korea',
+ SI: 'Slovenia',
+ KP: 'North Korea',
+ KW: 'Kuwait',
+ SN: 'Senegal',
+ SM: 'San Marino',
+ SL: 'Sierra Leone',
+ SC: 'Seychelles',
+ KZ: 'Kazakhstan',
+ KY: 'Cayman Islands',
+ SG: 'Singapore',
+ SE: 'Sweden',
+ SD: 'Sudan',
+ DO: 'Dominican Republic',
+ DM: 'Dominica',
+ DJ: 'Djibouti',
+ DK: 'Denmark',
+ VG: 'British Virgin Islands',
+ DE: 'Germany',
+ YE: 'Yemen',
+ DZ: 'Algeria',
+ US: 'United States',
+ UY: 'Uruguay',
+ YT: 'Mayotte',
+ UM: 'United States Minor Outlying Islands',
+ LB: 'Lebanon',
+ LC: 'Saint Lucia',
+ LA: 'Laos',
+ TV: 'Tuvalu',
+ TW: 'Taiwan',
+ TT: 'Trinidad and Tobago',
+ TR: 'Turkey',
+ LK: 'Sri Lanka',
+ LI: 'Liechtenstein',
+ LV: 'Latvia',
+ TO: 'Tonga',
+ LT: 'Lithuania',
+ LU: 'Luxembourg',
+ LR: 'Liberia',
+ LS: 'Lesotho',
+ TH: 'Thailand',
+ TF: 'French Southern Territories',
+ TG: 'Togo',
+ TD: 'Chad',
+ TC: 'Turks and Caicos Islands',
+ LY: 'Libya',
+ VA: 'Vatican',
+ VC: 'Saint Vincent and the Grenadines',
+ AE: 'United Arab Emirates',
+ AD: 'Andorra',
+ AG: 'Antigua and Barbuda',
+ AF: 'Afghanistan',
+ AI: 'Anguilla',
+ VI: 'U.S. Virgin Islands',
+ IS: 'Iceland',
+ IR: 'Iran',
+ AM: 'Armenia',
+ AL: 'Albania',
+ AO: 'Angola',
+ AQ: 'Antarctica',
+ AS: 'American Samoa',
+ AR: 'Argentina',
+ AU: 'Australia',
+ AT: 'Austria',
+ AW: 'Aruba',
+ IN: 'India',
+ AX: 'Aland Islands',
+ AZ: 'Azerbaijan',
+ IE: 'Ireland',
+ ID: 'Indonesia',
+ UA: 'Ukraine',
+ QA: 'Qatar',
+ MZ: 'Mozambique',
+};
+
// ----------------------------------------------------------------------
export const _timeline = [...Array(5)].map((_, index) => ({
diff --git a/src/_mock/_mock.ts b/src/_mock/_mock.ts
index 46f120bb1..70bce3624 100644
--- a/src/_mock/_mock.ts
+++ b/src/_mock/_mock.ts
@@ -1,5 +1,12 @@
+import { fShortenNumber } from 'src/utils/format-number';
+
+const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
export const _id = (index: number) => `e99f09a7-dd88-49d5-b1c8-1daf80c2d7b${index}`;
+export const _amount = () =>
+ fShortenNumber(Math.ceil(Math.max(Math.random() * 500, Math.random() * 5000))).toString();
+
export const _times = (index: number) =>
// 'MM/DD/YYYY'
[
@@ -91,6 +98,9 @@ export const _company = (index: number) =>
'Streich Group',
][index];
+export const _months = (length: number) =>
+ new Array(length).fill(0).map(() => MONTHS[Math.ceil(Math.random() * 11)]);
+
export const _boolean = (index: number) =>
[
true,
diff --git a/src/app.tsx b/src/app.tsx
index 68bbf1784..97ac7f115 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -1,44 +1,27 @@
import 'src/global.css';
-import Fab from '@mui/material/Fab';
-
import { Router } from 'src/routes/sections';
import { useScrollToTop } from 'src/hooks/use-scroll-to-top';
import { ThemeProvider } from 'src/theme/theme-provider';
-import { Iconify } from 'src/components/iconify';
+import { AlertUtil } from './utils';
+import AppAlert from './components/shared/alert';
// ----------------------------------------------------------------------
export default function App() {
useScrollToTop();
- const githubButton = (
-
-
-
- );
+ const setAlert = (ref: any) => {
+ AlertUtil.setRef(ref);
+ };
return (
- {githubButton}
+ setAlert(ref)} />
);
}
diff --git a/src/components/country-select/index.tsx b/src/components/country-select/index.tsx
new file mode 100644
index 000000000..5cf8d7148
--- /dev/null
+++ b/src/components/country-select/index.tsx
@@ -0,0 +1,38 @@
+import type { SelectProps } from '@mui/material';
+
+import { Select, MenuItem, InputLabel, FormControl } from '@mui/material';
+
+import _countries from 'src/_mock/_countries';
+
+import { Iconify } from '../iconify';
+
+function CountrySelect({ label = 'Country', ...props }: SelectProps) {
+ return (
+
+ {label}
+
+
+ );
+}
+
+export default CountrySelect;
diff --git a/src/components/loader/index.tsx b/src/components/loader/index.tsx
new file mode 100644
index 000000000..6582b4be8
--- /dev/null
+++ b/src/components/loader/index.tsx
@@ -0,0 +1,23 @@
+import type { FC } from 'react';
+import type { BoxProps } from '@mui/material/Box';
+
+import { Box, LinearProgress, linearProgressClasses } from '@mui/material';
+
+import { varAlpha } from 'src/theme/styles';
+
+interface LoaderProps extends BoxProps {}
+
+const Loader: FC = (props) => (
+
+ varAlpha(theme.vars.palette.text.primaryChannel, 0.16),
+ [`& .${linearProgressClasses.bar}`]: { bgcolor: 'text.primary' },
+ }}
+ />
+
+);
+
+export default Loader;
diff --git a/src/components/logo/logo.tsx b/src/components/logo/logo.tsx
index fae19d7ce..405e21ee4 100644
--- a/src/components/logo/logo.tsx
+++ b/src/components/logo/logo.tsx
@@ -212,7 +212,8 @@ export const Logo = forwardRef(
}}
{...other}
>
- {isSingle ? singleLogo : fullLogo}
+ {/* {isSingle ? singleLogo : fullLogo} */}
+
);
}
diff --git a/src/components/provider/index.tsx b/src/components/provider/index.tsx
new file mode 100644
index 000000000..7cdeaf3cd
--- /dev/null
+++ b/src/components/provider/index.tsx
@@ -0,0 +1,72 @@
+import type { ReactNode} from 'react';
+import type { User } from 'src/services/user/user.dto';
+
+import React, { useMemo, useState, useEffect, useCallback } from 'react';
+
+import { useRouter } from 'src/routes/hooks';
+
+import UserService from 'src/services/user';
+import { Cache, CacheKeys } from 'src/utils';
+
+const IS_ADMIN_MODE = !!Cache.get(CacheKeys.AdminMode);
+
+interface IUserContext {
+ user?: User;
+ isAdminMode: boolean;
+ pay: () => void;
+ reFetchUser: () => void;
+ setIsAdmin: (val: boolean) => void;
+}
+
+export const UserContext = React.createContext({
+ isAdminMode: IS_ADMIN_MODE,
+ user: undefined,
+ pay: () => {},
+ reFetchUser: () => {},
+ setIsAdmin: () => {},
+});
+
+const AppProvider = ({ children, pay }: { children: ReactNode; pay: () => void }) => {
+ const [user, setUser] = useState();
+ const { replace } = useRouter();
+
+ const fetchUser = useCallback(async () => {
+ try {
+ const res = await UserService.me();
+ if (res) {
+ setUser(res);
+ }
+ } catch (error) {
+ console.error(error);
+ }
+ }, []);
+
+ const updateAdminMode = useCallback(
+ async (val: boolean) => {
+ replace('/');
+ Cache.set(CacheKeys.AdminMode, val);
+ },
+ [replace]
+ );
+
+ useEffect(() => {
+ fetchUser();
+ }, [fetchUser]);
+
+ const contextValues: IUserContext = useMemo(
+ () => ({
+ user,
+ isAdminMode: IS_ADMIN_MODE,
+ pay,
+ setIsAdmin: updateAdminMode,
+ reFetchUser: fetchUser,
+ }),
+ [user, updateAdminMode, fetchUser, pay]
+ );
+
+ return {children};
+};
+
+export default AppProvider;
+
+// { user: User | undefined; isAdminMode: boolean; setAdminMode: (val: boolean) => void; reFetchUser: () => Promise; }
diff --git a/src/components/shared/alert/index.tsx b/src/components/shared/alert/index.tsx
new file mode 100644
index 000000000..26f2aa353
--- /dev/null
+++ b/src/components/shared/alert/index.tsx
@@ -0,0 +1,100 @@
+import type { AlertProps } from '@mui/material';
+import type { IconifyProps } from 'src/components/iconify';
+
+import { useRef, useState, forwardRef, useCallback, useImperativeHandle } from 'react';
+
+import { Box, Alert, Slide, Portal, IconButton } from '@mui/material';
+
+import { Iconify } from 'src/components/iconify';
+
+export interface AppAlertProps {
+ id?: string;
+ label: string;
+ icon?: IconifyProps['icon'];
+ type: AlertProps['severity'];
+ duration?: number;
+}
+
+export interface AppAlertMethods {
+ show: (data: AppAlertProps, cb?: () => void) => void;
+ close: (data: AppAlertProps, cb?: () => void) => void;
+}
+
+const AppAlert = forwardRef((_, ref) => {
+ const [visible, setVisible] = useState(false);
+ const [show, setShow] = useState(visible);
+ const dataRef = useRef(null);
+ const [value, setValue] = useState(null);
+
+ const container = useRef();
+
+ const clearData = () => {
+ setValue(null);
+ };
+
+ const handleOpenClose = useCallback((open: boolean, data?: AppAlertProps | null) => {
+ if (open) {
+ setValue(data ?? null);
+ setVisible(open);
+ setShow(open);
+ setTimeout(
+ () => {
+ setVisible(false);
+ },
+ (data?.duration ?? 5) * 1000
+ );
+ } else {
+ setVisible(open);
+ clearData();
+ }
+ }, []);
+
+ const onClose = () => {
+ setVisible(false);
+ };
+
+ const onExited = () => {
+ setShow(false);
+ };
+
+ useImperativeHandle(
+ ref,
+ () => ({
+ show(data) {
+ handleOpenClose(true, data);
+ },
+ close() {
+ handleOpenClose(false);
+ },
+ }),
+ [handleOpenClose]
+ );
+
+ return show ? (
+
+
+
+ }
+ action={
+
+
+
+ }
+ >
+ {value?.label}
+
+
+
+
+ ) : null;
+});
+
+export default AppAlert;
diff --git a/src/components/shared/modals/contributeForm.tsx b/src/components/shared/modals/contributeForm.tsx
new file mode 100644
index 000000000..562bfa4c3
--- /dev/null
+++ b/src/components/shared/modals/contributeForm.tsx
@@ -0,0 +1,171 @@
+import type { FormEvent, ChangeEvent } from 'react';
+
+import React, { useState, useEffect } from 'react';
+
+import { LoadingButton } from '@mui/lab';
+import {
+ Box,
+ Chip,
+ Link,
+ Modal,
+ TextField,
+ IconButton,
+ Typography,
+ Autocomplete,
+} from '@mui/material';
+
+import { useRouter } from 'src/routes/hooks';
+
+import useUser from 'src/hooks/useUser';
+
+import { errCb } from 'src/utils';
+import PayService from 'src/services/pay';
+
+import { Iconify } from 'src/components/iconify';
+
+const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+interface PaymentFormModalProps {
+ open: boolean;
+ amount?: string | number;
+ handleClose: () => void;
+}
+
+const PaymentFormModal: React.FC = ({
+ open,
+ amount: pledge,
+ handleClose,
+}) => {
+ const { user } = useUser();
+ const { refresh } = useRouter();
+
+ const [amount, setAmount] = useState(user?.pledgeAmount ?? pledge ?? '');
+ const [selectedMonths, setSelectedMonths] = useState([]);
+ const [loading, setLoading] = useState(false);
+
+ const handleAmountChange = (event: ChangeEvent) => {
+ setAmount(event.target.value);
+ };
+
+ const handleSubmit = async (event: FormEvent) => {
+ try {
+ setLoading(true);
+ event.preventDefault();
+ await PayService.init(Number(amount), selectedMonths);
+ closeModal();
+ setLoading(false);
+ } catch (error) {
+ errCb(error.message);
+ }
+ };
+
+ const closeModal = () => {
+ setAmount('');
+ setSelectedMonths([]);
+ handleClose();
+ };
+
+ useEffect(() => {
+ setAmount(user?.pledgeAmount ?? '');
+ }, [user?.pledgeAmount]);
+
+ useEffect(() => {
+ if (open) {
+ setAmount(user?.pledgeAmount ?? '');
+ }
+ }, [open, user?.pledgeAmount]);
+
+ const hasValues = !!amount && !!selectedMonths.length;
+
+ return (
+
+
+
+
+
+
+ Contribute
+
+ {!!selectedMonths.length && amount && (
+
+ You are making a contribution of{' '}
+
+ GHS{amount}
+ {' '}
+ for{' '}
+
+ {selectedMonths.join(', ')}
+
+
+ )}
+
+
+
+ );
+};
+
+export default PaymentFormModal;
diff --git a/src/components/shared/switch/toggle/index.tsx b/src/components/shared/switch/toggle/index.tsx
new file mode 100644
index 000000000..57221a0ee
--- /dev/null
+++ b/src/components/shared/switch/toggle/index.tsx
@@ -0,0 +1,19 @@
+import type { FC } from 'react'
+import type { SwitchProps} from '@mui/material';
+
+import { Box, Switch, Typography } from '@mui/material'
+
+export interface ToggleSwitchProps extends SwitchProps {
+ label:string
+}
+
+const ToggleSwitch:FC = ({label, checked, ...props}) => (
+
+
+ {label}
+
+
+
+)
+
+export default ToggleSwitch
\ No newline at end of file
diff --git a/src/config-global.ts b/src/config-global.ts
index 49eefa7f0..1ef641acb 100644
--- a/src/config-global.ts
+++ b/src/config-global.ts
@@ -10,6 +10,6 @@ export type ConfigValue = {
// ----------------------------------------------------------------------
export const CONFIG: ConfigValue = {
- appName: 'Minimal UI',
+ appName: 'PABGM Partnership',
appVersion: packageJson.version,
};
diff --git a/src/configs/firebase.ts b/src/configs/firebase.ts
new file mode 100644
index 000000000..c2c1f5b49
--- /dev/null
+++ b/src/configs/firebase.ts
@@ -0,0 +1,80 @@
+// Import the functions you need from the SDKs you need
+import type { User } from 'firebase/auth';
+
+import { initializeApp } from 'firebase/app';
+import { getFirestore, connectFirestoreEmulator } from 'firebase/firestore';
+import { getFunctions, httpsCallable, connectFunctionsEmulator } from 'firebase/functions';
+import {
+ getAuth,
+ signOut,
+ onAuthStateChanged,
+ connectAuthEmulator,
+ confirmPasswordReset,
+ sendPasswordResetEmail,
+ signInWithEmailAndPassword,
+ createUserWithEmailAndPassword,
+} from 'firebase/auth';
+
+import type { ApiRoute } from '../constants/fxns';
+
+const USE_EMULATORS = false;
+
+const firebaseConfig = {
+ apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
+ authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
+ projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
+ storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
+ messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGE_SENDER_ID,
+ appId: import.meta.env.VITE_FIREBASE_APP_ID,
+ measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
+};
+
+// Initialize Firebase
+const app = initializeApp(firebaseConfig);
+
+const appAuth = getAuth();
+
+const auth = {
+ createUser(email: string, password: string) {
+ return createUserWithEmailAndPassword(appAuth, email, password);
+ },
+ signIn(email: string, password: string) {
+ return signInWithEmailAndPassword(appAuth, email, password);
+ },
+ resetPassword(email: string) {
+ return sendPasswordResetEmail(appAuth, email);
+ },
+ confirmPassReset(code: string, newPass: string) {
+ return confirmPasswordReset(appAuth, code, newPass);
+ },
+ logout() {
+ return signOut(appAuth);
+ },
+ listen(cb: (val: User | null) => void) {
+ onAuthStateChanged(appAuth, cb);
+ },
+};
+
+const db = getFirestore(app);
+const fxns = getFunctions(app);
+
+const fx = {
+ async call(path: ApiRoute, data?: T) {
+ const callable = httpsCallable(fxns, path);
+ const result = await callable(data ?? null);
+ return result.data;
+ },
+};
+
+const runEmulators = (val: boolean = USE_EMULATORS) => {
+ const local = '127.0.0.1';
+ if (val) {
+ connectFirestoreEmulator(db, local, 8080);
+ connectAuthEmulator(appAuth, `http://${local}:9099`);
+ connectFunctionsEmulator(fxns, local, 5001);
+ }
+};
+
+runEmulators();
+
+export { db, fx, app, auth };
diff --git a/src/configs/index.tsx b/src/configs/index.tsx
new file mode 100644
index 000000000..5588511bf
--- /dev/null
+++ b/src/configs/index.tsx
@@ -0,0 +1 @@
+export * from './firebase';
diff --git a/src/constants/factory.ts b/src/constants/factory.ts
new file mode 100644
index 000000000..5fd2ddae9
--- /dev/null
+++ b/src/constants/factory.ts
@@ -0,0 +1,8 @@
+export enum Collection {
+ Users = 'USERS',
+ Contributions = 'CONTRIBUTIONS',
+ Transactions = 'TRXS',
+ AdminStats = 'ADMIN_STATS',
+ PartnerStats = 'PARTNER_STATS',
+ Secret = 'SECRET',
+}
diff --git a/src/constants/fxns.ts b/src/constants/fxns.ts
new file mode 100644
index 000000000..41c7335e9
--- /dev/null
+++ b/src/constants/fxns.ts
@@ -0,0 +1,9 @@
+export enum ApiRoute {
+ Donate = 'contribute',
+ InitPayment = 'initPay',
+ PaymentHook = 'payHook',
+ GetUser = 'getUser',
+ GetStats = 'getStats',
+ GetUserStats = 'getUserStats',
+ GetContributions = 'getContributions',
+}
diff --git a/src/constants/index.ts b/src/constants/index.ts
new file mode 100644
index 000000000..cc0202961
--- /dev/null
+++ b/src/constants/index.ts
@@ -0,0 +1,2 @@
+export * from './urls';
+export * from './factory';
diff --git a/src/constants/urls.ts b/src/constants/urls.ts
new file mode 100644
index 000000000..7995183aa
--- /dev/null
+++ b/src/constants/urls.ts
@@ -0,0 +1 @@
+export const API_URL = '';
diff --git a/src/hooks/useAdmin.ts b/src/hooks/useAdmin.ts
new file mode 100644
index 000000000..989e73e48
--- /dev/null
+++ b/src/hooks/useAdmin.ts
@@ -0,0 +1,16 @@
+import { useContext } from 'react';
+
+import { Cache, CacheKeys } from 'src/utils';
+
+import { UserContext } from 'src/components/provider';
+
+const useAdmin = () => {
+ const { setIsAdmin } = useContext(UserContext);
+ const isAdminMode = Cache.get(CacheKeys.AdminMode) ?? false;
+ return {
+ isAdminMode,
+ setIsAdmin,
+ };
+};
+
+export default useAdmin;
diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts
new file mode 100644
index 000000000..601730401
--- /dev/null
+++ b/src/hooks/useAuth.ts
@@ -0,0 +1,32 @@
+import type { User } from 'firebase/auth';
+
+import { useState, useEffect } from 'react';
+
+import AuthService from 'src/services/auth';
+
+const useAuth = () => {
+ const [data, setData] = useState<{ userExists: boolean; user: User | null }>({
+ userExists: false,
+ user: null,
+ });
+
+ const checkCurrentUser = (user: User | null) => {
+ if (user) {
+ setData({ userExists: true, user });
+ } else {
+ AuthService.setToken(null);
+ setData({
+ userExists: false,
+ user: null,
+ });
+ }
+ };
+
+ useEffect(() => {
+ AuthService.listen(checkCurrentUser);
+ }, []);
+
+ return data;
+};
+
+export default useAuth;
diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts
new file mode 100644
index 000000000..0e65640ba
--- /dev/null
+++ b/src/hooks/useUser.ts
@@ -0,0 +1,16 @@
+import { useState, useEffect, useContext } from 'react';
+
+import { UserContext } from 'src/components/provider';
+
+const useUser = () => {
+ const data = useContext(UserContext);
+ const [userContext, setUserContext] = useState(data);
+
+ useEffect(() => {
+ setUserContext(data);
+ }, [data]);
+
+ return userContext;
+};
+
+export default useUser;
diff --git a/src/layouts/components/account-popover.tsx b/src/layouts/components/account-popover.tsx
index 995efce0a..559b13816 100644
--- a/src/layouts/components/account-popover.tsx
+++ b/src/layouts/components/account-popover.tsx
@@ -3,7 +3,6 @@ import type { IconButtonProps } from '@mui/material/IconButton';
import { useState, useCallback } from 'react';
import Box from '@mui/material/Box';
-import Button from '@mui/material/Button';
import Avatar from '@mui/material/Avatar';
import Popover from '@mui/material/Popover';
import Divider from '@mui/material/Divider';
@@ -14,7 +13,8 @@ import MenuItem, { menuItemClasses } from '@mui/material/MenuItem';
import { useRouter, usePathname } from 'src/routes/hooks';
-import { _myAccount } from 'src/_mock';
+import useUser from 'src/hooks/useUser';
+
// ----------------------------------------------------------------------
@@ -31,6 +31,7 @@ export function AccountPopover({ data = [], sx, ...other }: AccountPopoverProps)
const router = useRouter();
const pathname = usePathname();
+ const { user } = useUser();
const [openPopover, setOpenPopover] = useState(null);
@@ -64,8 +65,8 @@ export function AccountPopover({ data = [], sx, ...other }: AccountPopoverProps)
}}
{...other}
>
-
- {_myAccount.displayName.charAt(0).toUpperCase()}
+
+ {user?.fname.charAt(0).toUpperCase()}
@@ -83,11 +84,11 @@ export function AccountPopover({ data = [], sx, ...other }: AccountPopoverProps)
>
- {_myAccount?.displayName}
+ {`${user?.fname} ${user?.lname}`}
- {_myAccount?.email}
+ {user?.email}
@@ -125,14 +126,6 @@ export function AccountPopover({ data = [], sx, ...other }: AccountPopoverProps)
))}
-
-
-
-
-
-
>
);
diff --git a/src/layouts/config-nav-dashboard.tsx b/src/layouts/config-nav-dashboard.tsx
index 2acb80796..c4b3bf2db 100644
--- a/src/layouts/config-nav-dashboard.tsx
+++ b/src/layouts/config-nav-dashboard.tsx
@@ -1,4 +1,3 @@
-import { Label } from 'src/components/label';
import { SvgColor } from 'src/components/svg-color';
// ----------------------------------------------------------------------
@@ -14,33 +13,43 @@ export const navData = [
icon: icon('ic-analytics'),
},
{
- title: 'User',
- path: '/user',
- icon: icon('ic-user'),
- },
- {
- title: 'Product',
- path: '/products',
- icon: icon('ic-cart'),
- info: (
-
- ),
+ title: 'Contributions',
+ path: '/contributions',
+ icon: icon('ic-donate'),
},
{
- title: 'Blog',
- path: '/blog',
- icon: icon('ic-blog'),
- },
- {
- title: 'Sign in',
- path: '/sign-in',
- icon: icon('ic-lock'),
+ title: 'Partners',
+ path: '/user',
+ icon: icon('ic-user'),
},
{
- title: 'Not found',
- path: '/404',
- icon: icon('ic-disabled'),
+ title: 'Logout',
+ path: '/logout',
+ icon: icon('ic-exit'),
},
+ // {
+ // title: 'Product',
+ // path: '/products',
+ // icon: icon('ic-cart'),
+ // info: (
+ //
+ // ),
+ // },
+ // {
+ // title: 'Blog',
+ // path: '/blog',
+ // icon: icon('ic-blog'),
+ // },
+ // {
+ // title: 'Sign in',
+ // path: '/sign-in',
+ // icon: icon('ic-lock'),
+ // },
+ // {
+ // title: 'Not found',
+ // path: '/404',
+ // icon: icon('ic-disabled'),
+ // },
];
diff --git a/src/layouts/dashboard/layout.tsx b/src/layouts/dashboard/layout.tsx
index 281305821..dce538642 100644
--- a/src/layouts/dashboard/layout.tsx
+++ b/src/layouts/dashboard/layout.tsx
@@ -1,27 +1,31 @@
import type { Theme, SxProps, Breakpoint } from '@mui/material/styles';
-import { useState } from 'react';
+import { useState, useEffect } from 'react';
import Box from '@mui/material/Box';
import Alert from '@mui/material/Alert';
import { useTheme } from '@mui/material/styles';
-import { _langs, _notifications } from 'src/_mock';
+import { useRouter } from 'src/routes/hooks';
-import { Iconify } from 'src/components/iconify';
+import useAuth from 'src/hooks/useAuth';
+import useUser from 'src/hooks/useUser';
+import useAdmin from 'src/hooks/useAdmin';
+
+import AuthService from 'src/services/auth';
+import { UserRole } from 'src/services/user/user.dto';
+
+import ToggleSwitch from 'src/components/shared/switch/toggle';
import { Main } from './main';
import { layoutClasses } from '../classes';
import { NavMobile, NavDesktop } from './nav';
import { navData } from '../config-nav-dashboard';
-import { Searchbar } from '../components/searchbar';
import { _workspaces } from '../config-nav-workspace';
import { MenuButton } from '../components/menu-button';
-import { LayoutSection } from '../core/layout-section';
import { HeaderSection } from '../core/header-section';
+import { LayoutSection } from '../core/layout-section';
import { AccountPopover } from '../components/account-popover';
-import { LanguagePopover } from '../components/language-popover';
-import { NotificationsPopover } from '../components/notifications-popover';
// ----------------------------------------------------------------------
@@ -35,11 +39,28 @@ export type DashboardLayoutProps = {
export function DashboardLayout({ sx, children, header }: DashboardLayoutProps) {
const theme = useTheme();
+ const { userExists } = useAuth();
+ const router = useRouter();
+ const { user } = useUser();
+ const { isAdminMode, setIsAdmin } = useAdmin();
+
+ const isAdmin = !!user?.role.includes(UserRole.Admin);
const [navOpen, setNavOpen] = useState(false);
const layoutQuery: Breakpoint = 'lg';
+ const onToggleAdmin = (event: React.ChangeEvent) => {
+ setIsAdmin(event.target.checked);
+ };
+
+ useEffect(() => {
+ if (!AuthService.hasToken()) {
+ router.replace('/signin');
+ }
+ }, [userExists, router]);
+
+ const navOptions = isAdminMode ? navData : navData.filter((nav) => nav.title !== 'Partners');
return (
-
-
-
+ {isAdmin && (
+
+ )}
+ {/* */}
,
- },
- {
- label: 'Profile',
- href: '#',
- icon: ,
- },
- {
- label: 'Settings',
- href: '#',
- icon: ,
- },
- ]}
+ data={
+ [
+ // {
+ // label: 'Profile',
+ // href: '#',
+ // icon: ,
+ // },
+ // {
+ // label: 'Settings',
+ // href: '#',
+ // icon: ,
+ // },
+ ]
+ }
/>
),
@@ -111,7 +130,7 @@ export function DashboardLayout({ sx, children, header }: DashboardLayoutProps)
* Sidebar
*************************************** */
sidebarSection={
-
+
}
/** **************************************
* Footer
diff --git a/src/layouts/dashboard/nav.tsx b/src/layouts/dashboard/nav.tsx
index 3b19cb940..cc905ed15 100644
--- a/src/layouts/dashboard/nav.tsx
+++ b/src/layouts/dashboard/nav.tsx
@@ -16,9 +16,6 @@ import { varAlpha } from 'src/theme/styles';
import { Logo } from 'src/components/logo';
import { Scrollbar } from 'src/components/scrollbar';
-import { NavUpgrade } from '../components/nav-upgrade';
-import { WorkspacesPopover } from '../components/workspaces-popover';
-
import type { WorkspacesPopoverProps } from '../components/workspaces-popover';
// ----------------------------------------------------------------------
@@ -120,16 +117,20 @@ export function NavContent({ data, slots, workspaces, sx }: NavContentProps) {
return (
<>
-
{slots?.topArea}
-
-
-
-
+
{data.map((item) => {
const isActived = item.path === pathname;
+ if (item.path === '/logout') return null;
return (
@@ -173,10 +174,32 @@ export function NavContent({ data, slots, workspaces, sx }: NavContentProps) {
-
{slots?.bottomArea}
+
+
+ {data[data.length - 1].icon}
+
-
+
+ {data[data.length - 1].title}
+
+
>
);
}
diff --git a/src/pages/contributions.tsx b/src/pages/contributions.tsx
new file mode 100644
index 000000000..98bb80ec0
--- /dev/null
+++ b/src/pages/contributions.tsx
@@ -0,0 +1,18 @@
+import { Helmet } from 'react-helmet-async';
+
+import { CONFIG } from 'src/config-global';
+
+import ContributionsList from 'src/sections/contributions/view/contributions-list';
+
+function Contributions() {
+ return (
+ <>
+
+ {`Contributions - ${CONFIG.appName}`}
+
+
+ >
+ );
+}
+
+export default Contributions;
diff --git a/src/pages/home.tsx b/src/pages/home.tsx
index 53838c922..ff5a3ebfd 100644
--- a/src/pages/home.tsx
+++ b/src/pages/home.tsx
@@ -11,11 +11,8 @@ export default function Page() {
<>
{`Dashboard - ${CONFIG.appName}`}
-
-
+
+
diff --git a/src/pages/logout.tsx b/src/pages/logout.tsx
new file mode 100644
index 000000000..0cbb0e428
--- /dev/null
+++ b/src/pages/logout.tsx
@@ -0,0 +1,22 @@
+import { useEffect, useCallback } from 'react';
+
+import { useRouter } from 'src/routes/hooks';
+
+import AuthService from 'src/services/auth';
+
+function Logout() {
+ const { replace } = useRouter();
+
+ const logout = useCallback(async () => {
+ await AuthService.logout();
+ replace('/signin');
+ }, [replace]);
+
+ useEffect(() => {
+ logout();
+ }, [logout]);
+
+ return null;
+}
+
+export default Logout;
diff --git a/src/pages/user.tsx b/src/pages/user.tsx
index f9b41608a..76d587a9d 100644
--- a/src/pages/user.tsx
+++ b/src/pages/user.tsx
@@ -2,7 +2,7 @@ import { Helmet } from 'react-helmet-async';
import { CONFIG } from 'src/config-global';
-import { UserView } from 'src/sections/user/view';
+import PartnersView from 'src/sections/user/view/partners-view';
// ----------------------------------------------------------------------
@@ -10,10 +10,10 @@ export default function Page() {
return (
<>
- {`Users - ${CONFIG.appName}`}
+ {`Partners - ${CONFIG.appName}`}
-
+
>
);
}
diff --git a/src/routes/sections.tsx b/src/routes/sections.tsx
index 34a673b10..70429663b 100644
--- a/src/routes/sections.tsx
+++ b/src/routes/sections.tsx
@@ -1,13 +1,22 @@
-import { lazy, Suspense } from 'react';
+import { lazy, Suspense, useState } from 'react';
import { Outlet, Navigate, useRoutes } from 'react-router-dom';
import Box from '@mui/material/Box';
+import { Fab } from '@mui/material';
import LinearProgress, { linearProgressClasses } from '@mui/material/LinearProgress';
+import useUser from 'src/hooks/useUser';
+import useAdmin from 'src/hooks/useAdmin';
+
import { varAlpha } from 'src/theme/styles';
import { AuthLayout } from 'src/layouts/auth';
import { DashboardLayout } from 'src/layouts/dashboard';
+import { Iconify } from 'src/components/iconify';
+import PaymentFormModal from 'src/components/shared/modals/contributeForm';
+
+const AppProvider = lazy(() => import('src/components/provider'));
+
// ----------------------------------------------------------------------
export const HomePage = lazy(() => import('src/pages/home'));
@@ -15,6 +24,8 @@ export const BlogPage = lazy(() => import('src/pages/blog'));
export const UserPage = lazy(() => import('src/pages/user'));
export const SignInPage = lazy(() => import('src/pages/sign-in'));
export const ProductsPage = lazy(() => import('src/pages/products'));
+export const ContributionsPage = lazy(() => import('src/pages/contributions'));
+export const LogoutPage = lazy(() => import('src/pages/logout'));
export const Page404 = lazy(() => import('src/pages/page-not-found'));
// ----------------------------------------------------------------------
@@ -33,30 +44,79 @@ const renderFallback = (
);
export function Router() {
+ const { user } = useUser();
+ const [open, setOpen] = useState(false);
+ const { isAdminMode } = useAdmin();
+
+ const onOpen = () => {
+ setOpen(true);
+ };
+
+ const onClose = () => {
+ setOpen(false);
+ };
+
+ const contributeBtn = (
+
+
+
+ );
+
+ const dashRoutes = [
+ { element: , index: true },
+ { path: 'user', element: },
+ { path: 'products', element: },
+ { path: 'blog', element: },
+ { path: 'contributions', element: },
+ ];
+
+ const routes = !isAdminMode ? dashRoutes.filter((route) => route.path !== 'user') : dashRoutes;
+
return useRoutes([
{
element: (
-
-
-
-
-
+
+
+
+
+
+
+ {contributeBtn}
+
+
+
+
),
- children: [
- { element: , index: true },
- { path: 'user', element: },
- { path: 'products', element: },
- { path: 'blog', element: },
- ],
+ children: routes,
},
{
- path: 'sign-in',
+ path: 'signin',
element: (
),
},
+ {
+ path: 'logout',
+ element: ,
+ },
{
path: '404',
element: ,
diff --git a/src/sections/auth/sign-in-view.tsx b/src/sections/auth/sign-in-view.tsx
index 52f619215..6682ee0b5 100644
--- a/src/sections/auth/sign-in-view.tsx
+++ b/src/sections/auth/sign-in-view.tsx
@@ -1,7 +1,10 @@
-import { useState, useCallback } from 'react';
+import type { CreateUserBody } from 'src/services/auth/auth.dto';
+
+import { useState, useEffect, useCallback } from 'react';
import Box from '@mui/material/Box';
import Link from '@mui/material/Link';
+import { Button } from '@mui/material';
import Divider from '@mui/material/Divider';
import TextField from '@mui/material/TextField';
import IconButton from '@mui/material/IconButton';
@@ -11,45 +14,194 @@ import InputAdornment from '@mui/material/InputAdornment';
import { useRouter } from 'src/routes/hooks';
+import { errCb } from 'src/utils';
+import AuthService from 'src/services/auth';
+
import { Iconify } from 'src/components/iconify';
+import CountrySelect from 'src/components/country-select';
// ----------------------------------------------------------------------
+const SIGN_IN = {
+ email: '',
+ password: '',
+};
+
+const SIGN_UP = {
+ fname: '',
+ lname: '',
+ country: '',
+ email: '',
+ password: '',
+ pledgeAmount: 0,
+ secret: '',
+};
+
export function SignInView() {
const router = useRouter();
const [showPassword, setShowPassword] = useState(false);
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false);
+ const [isSignin, setIsSignin] = useState(true);
+ const [authenticating, setAuthenticating] = useState(false);
+ const [confirmPass, setConfirmPass] = useState('');
+ const [data, setData] = useState>(SIGN_IN);
+
+ const onGetStarted = () => {
+ setIsSignin((val) => !val);
+ };
+
+ const onAuthenticate = async () => {
+ try {
+ setAuthenticating(true);
+ if (isSignin) {
+ if (!data.email || !data.password) {
+ throw new Error('Email and password is required');
+ } else {
+ await AuthService.login({
+ email: data.email!,
+ password: data.password!,
+ });
+ }
+ } else {
+ await AuthService.register(data as CreateUserBody);
+ }
+ router.replace('/');
+ } catch (error) {
+ errCb(error.message);
+ } finally {
+ setAuthenticating(false);
+ }
+ };
+
+ const updateField = (field: keyof CreateUserBody, val: string) => {
+ setData((value) => ({ ...value, [field]: val }));
+ };
- const handleSignIn = useCallback(() => {
- router.push('/');
- }, [router]);
+ const checkPass = useCallback(() => {
+ if (data.password !== confirmPass && !isSignin) {
+ return 'Passwords do not match';
+ }
+ return null;
+ }, [data.password, confirmPass, isSignin]);
+
+ const checkEmptyForm = useCallback(
+ () => [...Object.values(data), !isSignin ? confirmPass : 'true'].some((val) => val === ''),
+ [data, confirmPass, isSignin]
+ );
+
+ useEffect(() => {
+ if (isSignin) {
+ setData(SIGN_IN);
+ } else {
+ setData(SIGN_UP);
+ }
+ }, [isSignin]);
+
+ const passErr = checkPass();
+ const emptyForm = checkEmptyForm();
const renderForm = (
+ {!isSignin && (
+ updateField('secret', e.target.value)}
+ InputLabelProps={{ shrink: true }}
+ sx={{ mb: 3 }}
+ helperText={
+
+ Enter the secret code provided in your invite message.
+
+ }
+ />
+ )}
+ {!isSignin && (
+
+ updateField('fname', e.target.value)}
+ value={data.fname}
+ InputLabelProps={{ shrink: true }}
+ sx={{ mb: 3 }}
+ />
+ updateField('lname', e.target.value)}
+ InputLabelProps={{ shrink: true }}
+ value={data.lname}
+ sx={{ mb: 3 }}
+ />
+
+ )}
updateField('email', e.target.value)}
InputLabelProps={{ shrink: true }}
sx={{ mb: 3 }}
/>
+ {!isSignin && (
+ <>
+ updateField('pledgeAmount', e.target.value)}
+ InputLabelProps={{ shrink: true }}
+ sx={{ mb: 3 }}
+ />
+
+ updateField('country', e.target.value as string)}
+ required
+ />
+
+ >
+ )}
-
- Forgot password?
-
+ {isSignin && (
+
+ Forgot password?
+
+ )}
updateField('password', e.target.value)}
InputProps={{
endAdornment: (
- setShowPassword(!showPassword)} edge="end">
+ setShowPassword((val) => !val)} edge="end">
@@ -57,16 +209,45 @@ export function SignInView() {
}}
sx={{ mb: 3 }}
/>
+ {!isSignin && (
+ setConfirmPass(e.target.value)}
+ InputProps={{
+ endAdornment: (
+
+ setShowConfirmPassword((val) => !val)} edge="end">
+
+
+
+ ),
+ }}
+ sx={{ mb: 3 }}
+ />
+ )}
- Sign in
+ {isSignin ? 'Sign in' : 'Sign up'}
);
@@ -74,37 +255,34 @@ export function SignInView() {
return (
<>
- Sign in
+ {!isSignin ? 'Sign up' : 'Sign in'}
Don’t have an account?
-
- Get started
-
+
+
- {renderForm}
+ {/* {isSignin && (
+ <>
+
+
+ OR
+
+
-
-
- OR
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ >
+ )} */}
>
);
}
diff --git a/src/sections/contributions/contributions-table-head.tsx b/src/sections/contributions/contributions-table-head.tsx
new file mode 100644
index 000000000..23c2c05fb
--- /dev/null
+++ b/src/sections/contributions/contributions-table-head.tsx
@@ -0,0 +1,73 @@
+import Box from '@mui/material/Box';
+import TableRow from '@mui/material/TableRow';
+import Checkbox from '@mui/material/Checkbox';
+import TableHead from '@mui/material/TableHead';
+import TableCell from '@mui/material/TableCell';
+import TableSortLabel from '@mui/material/TableSortLabel';
+
+import { visuallyHidden } from './utils';
+
+// ----------------------------------------------------------------------
+
+type ContributionTableHeadProps = {
+ orderBy: string;
+ rowCount: number;
+ numSelected: number;
+ noMultiSelect?: boolean;
+ order: 'asc' | 'desc';
+ onSort: (id: string) => void;
+ headLabel: Record[];
+ onSelectAllRows: (checked: boolean) => void;
+};
+
+export function ContributionTableHead({
+ order,
+ onSort,
+ orderBy,
+ rowCount,
+ headLabel,
+ numSelected,
+ noMultiSelect = false,
+ onSelectAllRows,
+}: ContributionTableHeadProps) {
+ return (
+
+
+ {!noMultiSelect && (
+
+ 0 && numSelected < rowCount}
+ checked={rowCount > 0 && numSelected === rowCount}
+ onChange={(event: React.ChangeEvent) =>
+ onSelectAllRows(event.target.checked)
+ }
+ />
+
+ )}
+
+ {headLabel.map((headCell) => (
+
+ onSort(headCell.id)}
+ >
+ {headCell.label}
+ {orderBy === headCell.id ? (
+
+ {order === 'desc' ? 'sorted descending' : 'sorted ascending'}
+
+ ) : null}
+
+
+ ))}
+
+
+ );
+}
diff --git a/src/sections/contributions/contributions-table-row.tsx b/src/sections/contributions/contributions-table-row.tsx
new file mode 100644
index 000000000..a4154153d
--- /dev/null
+++ b/src/sections/contributions/contributions-table-row.tsx
@@ -0,0 +1,165 @@
+import type { LabelColor } from 'src/components/label';
+
+import { useState, useCallback } from 'react';
+
+import Box from '@mui/material/Box';
+import { Button } from '@mui/material';
+import Popover from '@mui/material/Popover';
+import Checkbox from '@mui/material/Checkbox';
+import MenuList from '@mui/material/MenuList';
+import TableRow from '@mui/material/TableRow';
+import TableCell from '@mui/material/TableCell';
+import MenuItem, { menuItemClasses } from '@mui/material/MenuItem';
+
+import useUser from 'src/hooks/useUser';
+
+import { fDateTime } from 'src/utils/format-time';
+
+import PayService from 'src/services/pay';
+
+import { Label } from 'src/components/label';
+import { Iconify } from 'src/components/iconify';
+import ContributionService from 'src/services/cont';
+import { LoadingButton } from '@mui/lab';
+
+// ----------------------------------------------------------------------
+
+export type ContributionProps = {
+ id: string;
+ sender: {
+ id: string;
+ name: string;
+ };
+ amount: string;
+ timestamp: Date;
+ status: 'pending' | 'success' | 'failed';
+ months: string[];
+ code: string;
+};
+
+type ContributionsTableRowProps = {
+ row: ContributionProps;
+ selected: boolean;
+ noSelection?: boolean;
+ onSelectRow: () => void;
+};
+
+export function ContributionsTableRow({
+ row,
+ selected,
+ noSelection,
+ onSelectRow,
+}: ContributionsTableRowProps) {
+ const [openPopover, setOpenPopover] = useState(null);
+ const [cancelling, setCancelling] = useState(false);
+ const { user } = useUser();
+
+ const handleOpenPopover = useCallback((event: React.MouseEvent) => {
+ setOpenPopover(event.currentTarget);
+ }, []);
+
+ const handleClosePopover = useCallback(() => {
+ setOpenPopover(null);
+ }, []);
+
+ const getStatus = (val: ContributionProps['status']): LabelColor => {
+ if (val === 'failed') return 'error';
+ if (val === 'pending') return 'info';
+ return 'success';
+ };
+
+ const onResume = (code: string) => {
+ PayService.resume(code);
+ };
+
+ const onCancel = async (id: string) => {
+ setCancelling(true);
+ await ContributionService.cancel(id);
+ setCancelling(false);
+ };
+
+ return (
+ <>
+
+ {!noSelection && (
+
+
+
+ )}
+
+
+
+ {row.sender.name}
+
+
+
+ {row.months.join(', ')}
+
+ {`GHS ${row.amount}`}
+
+ {fDateTime(row.timestamp)}
+
+
+
+
+
+
+
+ {row.status === 'pending' && row.sender.id === user?.id ? (
+
+
+ onCancel(row.id)}
+ >
+ Cancel
+
+
+ ) : (
+ ''
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/sections/contributions/contributions-table-toolbar.tsx b/src/sections/contributions/contributions-table-toolbar.tsx
new file mode 100644
index 000000000..34766ae5e
--- /dev/null
+++ b/src/sections/contributions/contributions-table-toolbar.tsx
@@ -0,0 +1,67 @@
+import Toolbar from '@mui/material/Toolbar';
+import OutlinedInput from '@mui/material/OutlinedInput';
+import InputAdornment from '@mui/material/InputAdornment';
+
+import { Iconify } from 'src/components/iconify';
+
+// ----------------------------------------------------------------------
+
+type ContributionsTableToolbarProps = {
+ numSelected: number;
+ filterName: string;
+ onFilterName: (event: React.ChangeEvent) => void;
+};
+
+export function ContributionsTableToolbar({
+ numSelected,
+ filterName,
+ onFilterName,
+}: ContributionsTableToolbarProps) {
+ return (
+ theme.spacing(0, 1, 0, 3),
+ ...(numSelected > 0 && {
+ color: 'primary.main',
+ bgcolor: 'primary.lighter',
+ }),
+ }}
+ >
+ {/* {numSelected > 0 ? (
+
+ {numSelected} selected
+
+ ) : ( */}
+
+
+
+ }
+ sx={{ maxWidth: 320 }}
+ />
+ {/* )} */}
+
+ {/* {numSelected > 0 ? (
+
+
+
+
+
+ ) : (
+
+
+
+
+
+ )} */}
+
+ );
+}
diff --git a/src/sections/contributions/table-empty-rows.tsx b/src/sections/contributions/table-empty-rows.tsx
new file mode 100644
index 000000000..4127993fb
--- /dev/null
+++ b/src/sections/contributions/table-empty-rows.tsx
@@ -0,0 +1,31 @@
+import type { TableRowProps } from '@mui/material/TableRow';
+
+import TableRow from '@mui/material/TableRow';
+import TableCell from '@mui/material/TableCell';
+
+// ----------------------------------------------------------------------
+
+type TableEmptyRowsProps = TableRowProps & {
+ emptyRows: number;
+ height?: number;
+};
+
+export function TableEmptyRows({ emptyRows, height, sx, ...other }: TableEmptyRowsProps) {
+ if (!emptyRows) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/src/sections/contributions/table-no-data.tsx b/src/sections/contributions/table-no-data.tsx
new file mode 100644
index 000000000..2d9051369
--- /dev/null
+++ b/src/sections/contributions/table-no-data.tsx
@@ -0,0 +1,35 @@
+import type { TableRowProps } from '@mui/material/TableRow';
+
+import Box from '@mui/material/Box';
+import TableRow from '@mui/material/TableRow';
+import TableCell from '@mui/material/TableCell';
+import Typography from '@mui/material/Typography';
+
+// ----------------------------------------------------------------------
+
+type TableNoDataProps = TableRowProps & {
+ searchQuery?: string;
+ label?: string;
+};
+
+export function TableNoData({ searchQuery, label, ...other }: TableNoDataProps) {
+ return (
+
+
+
+
+ {label}
+
+
+ {false && (
+
+ No results found for
+ "{searchQuery}".
+
Try checking for typos or using complete words.
+
+ )}
+
+
+
+ );
+}
diff --git a/src/sections/contributions/utils.ts b/src/sections/contributions/utils.ts
new file mode 100644
index 000000000..0a275e8eb
--- /dev/null
+++ b/src/sections/contributions/utils.ts
@@ -0,0 +1,80 @@
+import type { ContributionProps } from './contributions-table-row';
+
+// ----------------------------------------------------------------------
+
+export const visuallyHidden = {
+ border: 0,
+ margin: -1,
+ padding: 0,
+ width: '1px',
+ height: '1px',
+ overflow: 'hidden',
+ position: 'absolute',
+ whiteSpace: 'nowrap',
+ clip: 'rect(0 0 0 0)',
+} as const;
+
+// ----------------------------------------------------------------------
+
+export function emptyRows(page: number, rowsPerPage: number, arrayLength: number) {
+ return page ? Math.max(0, (1 + page) * rowsPerPage - arrayLength) : 0;
+}
+
+// ----------------------------------------------------------------------
+
+function descendingComparator(a: T, b: T, orderBy: keyof T) {
+ if (b[orderBy] < a[orderBy]) {
+ return -1;
+ }
+ if (b[orderBy] > a[orderBy]) {
+ return 1;
+ }
+ return 0;
+}
+
+// ----------------------------------------------------------------------
+
+export function getComparator(
+ order: 'asc' | 'desc',
+ orderBy: Key
+): (
+ a: {
+ [key in Key]: number | string;
+ },
+ b: {
+ [key in Key]: number | string;
+ }
+) => number {
+ return order === 'desc'
+ ? (a, b) => descendingComparator(a, b, orderBy)
+ : (a, b) => -descendingComparator(a, b, orderBy);
+}
+
+// ----------------------------------------------------------------------
+
+type ApplyFilterProps = {
+ inputData: ContributionProps[];
+ filterName: string;
+ comparator: (a: any, b: any) => number;
+};
+
+export function applyFilter({ inputData, comparator, filterName }: ApplyFilterProps) {
+ const stabilizedThis = inputData.map((el, index) => [el, index] as const);
+
+ stabilizedThis.sort((a, b) => {
+ const order = comparator(a[0], b[0]);
+ if (order !== 0) return order;
+ return a[1] - b[1];
+ });
+
+ inputData = stabilizedThis.map((el) => el[0]);
+
+ if (filterName) {
+ inputData = inputData.filter(
+ (contribution) =>
+ contribution.sender.name.toLowerCase().indexOf(filterName.toLowerCase()) !== -1
+ );
+ }
+
+ return inputData;
+}
diff --git a/src/sections/contributions/view/contributions-list.tsx b/src/sections/contributions/view/contributions-list.tsx
new file mode 100644
index 000000000..edeef025b
--- /dev/null
+++ b/src/sections/contributions/view/contributions-list.tsx
@@ -0,0 +1,63 @@
+import type { Contribution} from 'src/services/cont/contribute.dto';
+
+import { useState, useEffect, useCallback } from 'react';
+
+import useUser from 'src/hooks/useUser';
+import useAdmin from 'src/hooks/useAdmin';
+
+import ContributionService from 'src/services/cont';
+import { ContributionStatus } from 'src/services/cont/contribute.dto';
+
+import { ContributionsView } from './contributions-view';
+
+import type { ContributionProps } from '../contributions-table-row';
+
+const ContributionsList = () => {
+ const [data, setData] = useState();
+ const [loading, setLoading] = useState(true);
+ const { isAdminMode } = useAdmin();
+ const { user } = useUser();
+
+ const getStatus = (status: ContributionStatus): ContributionProps['status'] => {
+ if (status === ContributionStatus.Failed) return 'failed';
+ if (status === ContributionStatus.Pending) return 'pending';
+ return 'success';
+ };
+
+ const getContributions = useCallback(
+ (result: Contribution[]): ContributionProps[] =>
+ result.map((item) => ({
+ amount: item.amount,
+ id: item.id,
+ months: item.months,
+ sender: item.donor,
+ status: getStatus(item.status),
+ timestamp: (item.completedAt || item.createdAt).toDate(),
+ code: item?.trxCode,
+ })),
+ []
+ );
+
+ const init = useCallback(async () => {
+ const promise = isAdminMode
+ ? ContributionService.getList({ count: 20, page: 1 })
+ : ContributionService.getByUserId(user?.id!, 20);
+ const res = await promise;
+
+ // TODO: Implement pagination
+ // pageRef.current.set(res.metadata.page, res.data[res.data.length - 1].id);
+
+ const result = 'metadata' in res ? res.data : res;
+ const contributions = getContributions(result);
+ setData(contributions);
+ setLoading(false);
+ }, [getContributions, isAdminMode, user?.id]);
+
+ useEffect(() => {
+ init();
+ }, [init]);
+
+ return ;
+};
+
+export default ContributionsList;
diff --git a/src/sections/contributions/view/contributions-view.tsx b/src/sections/contributions/view/contributions-view.tsx
new file mode 100644
index 000000000..ae4755178
--- /dev/null
+++ b/src/sections/contributions/view/contributions-view.tsx
@@ -0,0 +1,255 @@
+import { useMemo, useState, useContext, useCallback } from 'react';
+
+import Box from '@mui/material/Box';
+import Card from '@mui/material/Card';
+import Table from '@mui/material/Table';
+import Button from '@mui/material/Button';
+import TableBody from '@mui/material/TableBody';
+import Typography from '@mui/material/Typography';
+import TableContainer from '@mui/material/TableContainer';
+import TablePagination from '@mui/material/TablePagination';
+
+import { useRouter } from 'src/routes/hooks';
+
+import { _users } from 'src/_mock';
+import { DashboardContent } from 'src/layouts/dashboard';
+
+import Loader from 'src/components/loader';
+import { Iconify } from 'src/components/iconify';
+import { Scrollbar } from 'src/components/scrollbar';
+import { UserContext } from 'src/components/provider';
+
+import { TableNoData } from '../table-no-data';
+import { TableEmptyRows } from '../table-empty-rows';
+import { emptyRows, applyFilter, getComparator } from '../utils';
+import { ContributionTableHead } from '../contributions-table-head';
+import { ContributionsTableToolbar } from '../contributions-table-toolbar';
+import { ContributionsTableRow, type ContributionProps } from '../contributions-table-row';
+
+// ----------------------------------------------------------------------
+
+interface ContributionsViewProps {
+ ignoreDashContent?: boolean;
+ noMultiSelect?: boolean;
+ noToolbar?: boolean;
+ hideBtn?: boolean;
+ title?: string;
+ noPagination?: boolean;
+ data?: ContributionProps[];
+ loading?: boolean;
+ viewMore?: boolean;
+}
+
+export function ContributionsView({
+ ignoreDashContent,
+ noMultiSelect,
+ noToolbar,
+ hideBtn,
+ noPagination,
+ title = 'Contributions',
+ loading,
+ viewMore,
+ data = [],
+}: ContributionsViewProps) {
+ const table = useTable();
+
+ const [filterName, setFilterName] = useState('');
+ const { pay } = useContext(UserContext);
+ const { push } = useRouter();
+
+ const onViewMore = () => {
+ push('/contributions');
+ };
+
+ const dataFiltered: ContributionProps[] = useMemo(
+ () =>
+ applyFilter({
+ inputData: data,
+ comparator: getComparator(table.order, table.orderBy),
+ filterName,
+ }),
+ [filterName, data, table.order, table.orderBy]
+ );
+
+ const notFound = (!dataFiltered.length && !!filterName) || (!dataFiltered.length && !filterName);
+
+ const content = (
+ <>
+
+
+ {title}
+
+ {!hideBtn && (
+ }
+ >
+ Contribute
+
+ )}
+ {viewMore && (
+
+ )}
+
+
+ {loading ? (
+
+ ) : (
+ <>
+ {!noToolbar && (
+ ) => {
+ setFilterName(event.target.value);
+ table.onResetPage();
+ }}
+ />
+ )}
+
+
+
+
+
+ table.onSelectAllRows(
+ checked,
+ _users.map((user) => user.id)
+ )
+ }
+ headLabel={[
+ { id: 'name', label: 'Name' },
+ { id: 'months', label: 'Month(s)' },
+ { id: 'amount', label: 'Amount' },
+ { id: 'date', label: 'Date' },
+ { id: 'status', label: 'Status' },
+ { id: 'resume', label: '' },
+ ]}
+ />
+
+ <>
+ {dataFiltered
+ .slice(
+ table.page * table.rowsPerPage,
+ table.page * table.rowsPerPage + table.rowsPerPage
+ )
+ .map((row) => (
+ table.onSelectRow(row.id)}
+ />
+ ))}
+
+
+ {notFound && (
+
+ )}
+ >
+
+
+
+
+
+ {!noPagination && (
+
+ )}
+ >
+ )}
+
+ >
+ );
+
+ return ignoreDashContent ? content : {content};
+}
+
+// ----------------------------------------------------------------------
+
+export function useTable() {
+ const [page, setPage] = useState(0);
+ const [orderBy, setOrderBy] = useState('name');
+ const [rowsPerPage, setRowsPerPage] = useState(10);
+ const [selected, setSelected] = useState([]);
+ const [order, setOrder] = useState<'asc' | 'desc'>('asc');
+
+ const onSort = useCallback(
+ (id: string) => {
+ const isAsc = orderBy === id && order === 'asc';
+ setOrder(isAsc ? 'desc' : 'asc');
+ setOrderBy(id);
+ },
+ [order, orderBy]
+ );
+
+ const onSelectAllRows = useCallback((checked: boolean, newSelecteds: string[]) => {
+ if (checked) {
+ setSelected(newSelecteds);
+ return;
+ }
+ setSelected([]);
+ }, []);
+
+ const onSelectRow = useCallback(
+ (inputValue: string) => {
+ const newSelected = selected.includes(inputValue)
+ ? selected.filter((value) => value !== inputValue)
+ : [...selected, inputValue];
+
+ setSelected(newSelected);
+ },
+ [selected]
+ );
+
+ const onResetPage = useCallback(() => {
+ setPage(0);
+ }, []);
+
+ const onChangePage = useCallback((event: unknown, newPage: number) => {
+ setPage(newPage);
+ }, []);
+
+ const onChangeRowsPerPage = useCallback(
+ (event: React.ChangeEvent) => {
+ setRowsPerPage(parseInt(event.target.value, 10));
+ onResetPage();
+ },
+ [onResetPage]
+ );
+
+ return {
+ page,
+ order,
+ onSort,
+ orderBy,
+ selected,
+ rowsPerPage,
+ onSelectRow,
+ onResetPage,
+ onChangePage,
+ onSelectAllRows,
+ onChangeRowsPerPage,
+ };
+}
diff --git a/src/sections/contributions/view/index.ts b/src/sections/contributions/view/index.ts
new file mode 100644
index 000000000..0902724a1
--- /dev/null
+++ b/src/sections/contributions/view/index.ts
@@ -0,0 +1 @@
+export * from './contributions-view';
diff --git a/src/sections/overview/analytics-widget-summary.tsx b/src/sections/overview/analytics-widget-summary.tsx
index 79694c0aa..6f271f27c 100644
--- a/src/sections/overview/analytics-widget-summary.tsx
+++ b/src/sections/overview/analytics-widget-summary.tsx
@@ -6,20 +6,18 @@ import Box from '@mui/material/Box';
import Card from '@mui/material/Card';
import { useTheme } from '@mui/material/styles';
-import { fNumber, fPercent, fShortenNumber } from 'src/utils/format-number';
+import { fShortenNumber } from 'src/utils/format-number';
import { varAlpha, bgGradient } from 'src/theme/styles';
-import { Iconify } from 'src/components/iconify';
import { SvgColor } from 'src/components/svg-color';
-import { Chart, useChart } from 'src/components/chart';
// ----------------------------------------------------------------------
type Props = CardProps & {
title: string;
- total: number;
- percent: number;
+ total: number|string;
+ percent?: number;
color?: ColorType;
icon: React.ReactNode;
chart: {
@@ -43,42 +41,23 @@ export function AnalyticsWidgetSummary({
const chartColors = [theme.palette[color].dark];
- const chartOptions = useChart({
- chart: { sparkline: { enabled: true } },
- colors: chartColors,
- xaxis: { categories: chart.categories },
- grid: {
- padding: {
- top: 6,
- left: 6,
- right: 6,
- bottom: 6,
- },
- },
- tooltip: {
- y: { formatter: (value: number) => fNumber(value), title: { formatter: () => '' } },
- },
- ...chart.options,
- });
-
- const renderTrending = (
-
-
-
- {percent > 0 && '+'}
- {fPercent(percent)}
-
-
- );
+ // const chartOptions = useChart({
+ // chart: { sparkline: { enabled: true } },
+ // colors: chartColors,
+ // xaxis: { categories: chart.categories },
+ // grid: {
+ // padding: {
+ // top: 6,
+ // left: 6,
+ // right: 6,
+ // bottom: 6,
+ // },
+ // },
+ // tooltip: {
+ // y: { formatter: (value: number) => fNumber(value), title: { formatter: () => '' } },
+ // },
+ // ...chart.options,
+ // });
return (
{icon}
- {renderTrending}
-
{fShortenNumber(total)}
-
+ /> */}
();
+
+ const getStatus = (status: ContributionStatus): ContributionProps['status'] => {
+ if (status === ContributionStatus.Failed) return 'failed';
+ if (status === ContributionStatus.Pending) return 'pending';
+ return 'success';
+ };
+
+ const getContributions = useCallback(
+ (result: Contribution[]): ContributionProps[] =>
+ result.map((item) => ({
+ amount: item.amount,
+ id: item.id,
+ months: item.months,
+ sender: item.donor,
+ status: getStatus(item.status),
+ timestamp: (item.completedAt || item.createdAt).toDate(),
+ code: item?.trxCode,
+ })),
+ []
+ );
+
+ const getStats = useCallback(async () => {
+ const stats = isAdminMode ? await StatsService.get() : await StatsService.getByUser();
+ setData((val) => (val ? { ...val, stats } : { stats }));
+ }, [isAdminMode]);
+
+ const onLatestContribution = useCallback(
+ (value: Contribution[]) => {
+ const cons = getContributions(value);
+ setData((val) => (val ? { ...val, cons } : { cons }));
+ getStats();
+ },
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [getContributions, getStats]
+ );
+
+ const init = useCallback(async () => {
+ if (!user?.id) return;
+ try {
+ ContributionService.listenLatest(onLatestContribution, isAdminMode ? undefined : user.id);
+ await getStats();
+ } catch (error) {
+ errCb(error.message);
+ } finally {
+ setLoading(false);
+ }
+ }, [user?.id, onLatestContribution, isAdminMode, getStats]);
+
+ useEffect(() => {
+ init();
+ }, [init]);
+
+ if (loading) {
+ return (
+
+ varAlpha(theme.vars.palette.text.primaryChannel, 0.16),
+ [`& .${linearProgressClasses.bar}`]: { bgcolor: 'text.primary' },
+ }}
+ />
+
+ );
+ }
+
+ const mdQuery = isAdminMode ? 3 : 4;
+
return (
- Hi, Welcome back 👋
+ Hi, {user?.fname} 👋
-
+
}
+ title="No. of contributions"
+ total={data?.stats?.contributionCount || 0}
+ icon={
}
chart={{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
- series: [22, 8, 35, 50, 82, 84, 77, 12],
+ series: [],
}}
/>
-
+
}
chart={{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
- series: [56, 47, 40, 62, 73, 30, 23, 54],
+ series: [],
}}
/>
-
+ {isAdminMode ? (
+
+ }
+ chart={{
+ categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
+ series: [10, 6, 9],
+ }}
+ />
+
+ ) : null}
+
+
}
+ icon={
}
chart={{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
- series: [40, 70, 50, 28, 70, 75, 7, 64],
+ series: [10, 6, 9],
}}
/>
-
+ {/*
}
chart={{
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
- series: [56, 30, 23, 54, 47, 40, 62, 73],
+ series: [],
}}
/>
-
-
-
+ */}
+ {/*
-
-
-
+ */}
+ {/*
-
-
-
+ */}
+ {/*
+ */}
+
+
-
-
-
-
-
-
+ {/*
-
-
-
+ */}
+ {/*
-
+ */}
);
diff --git a/src/sections/user/table-no-data.tsx b/src/sections/user/table-no-data.tsx
index 914e23f38..689d3062b 100644
--- a/src/sections/user/table-no-data.tsx
+++ b/src/sections/user/table-no-data.tsx
@@ -17,14 +17,16 @@ export function TableNoData({ searchQuery, ...other }: TableNoDataProps) {
- Not found
+ No users available
-
- No results found for
- "{searchQuery}".
-
Try checking for typos or using complete words.
-
+ {false && (
+
+ No results found for
+ "{searchQuery}".
+
Try checking for typos or using complete words.
+
+ )}
diff --git a/src/sections/user/user-table-head.tsx b/src/sections/user/user-table-head.tsx
index 3888ee712..204efeedb 100644
--- a/src/sections/user/user-table-head.tsx
+++ b/src/sections/user/user-table-head.tsx
@@ -1,6 +1,5 @@
import Box from '@mui/material/Box';
import TableRow from '@mui/material/TableRow';
-import Checkbox from '@mui/material/Checkbox';
import TableHead from '@mui/material/TableHead';
import TableCell from '@mui/material/TableCell';
import TableSortLabel from '@mui/material/TableSortLabel';
@@ -31,7 +30,7 @@ export function UserTableHead({
return (
-
+ {/*
0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount}
@@ -39,7 +38,7 @@ export function UserTableHead({
onSelectAllRows(event.target.checked)
}
/>
-
+ */}
{headLabel.map((headCell) => (
(null);
+ const [updating, setUpdating] = useState(false);
+ const { refresh } = useRouter();
+
+ const user = useUser();
const handleOpenPopover = useCallback((event: React.MouseEvent) => {
setOpenPopover(event.currentTarget);
@@ -42,25 +52,44 @@ export function UserTableRow({ row, selected, onSelectRow }: UserTableRowProps)
setOpenPopover(null);
}, []);
+ const onClick = useCallback(
+ async (val: 'makeAdmin' | 'delete') => {
+ setOpenPopover(null);
+ if (val === 'makeAdmin') {
+ setUpdating(true);
+ const userData = await UserService.get(row.id);
+ if (userData) {
+ const { role } = userData;
+ if (!role.includes(UserRole.Admin)) {
+ await UserService.update(row.id, { role: [...role, UserRole.Admin] });
+ }
+ }
+ }
+ refresh();
+ setUpdating(false);
+ },
+ [row.id, refresh]
+ );
+
return (
<>
-
-
+
+ {/*
-
+ */}
-
+
-
- {row.name}
+
+ {row.name} {row.email === user.user?.email ? '(You)' : ''}
- {row.company}
-
{row.role}
+ {row.email}
+ {`${fCurrency(row.pledge)}`}
-
+ {/*
{row.isVerified ? (
) : (
@@ -70,12 +99,18 @@ export function UserTableRow({ row, selected, onSelectRow }: UserTableRowProps)
-
+ */}
-
-
-
+ {updating ? (
+
+ ) : (
+ !row.role.includes(UserRole.Admin) && (
+
+
+
+ )
+ )}
@@ -102,15 +137,18 @@ export function UserTableRow({ row, selected, onSelectRow }: UserTableRowProps)
},
}}
>
-
+ {!row.role.includes(UserRole.Admin) && (
+
+ )}
- */}
>
diff --git a/src/sections/user/view/partners-view.tsx b/src/sections/user/view/partners-view.tsx
new file mode 100644
index 000000000..574564a5c
--- /dev/null
+++ b/src/sections/user/view/partners-view.tsx
@@ -0,0 +1,26 @@
+import type { User } from 'src/services/user/user.dto';
+
+import { useState, useEffect } from 'react';
+
+import UserService from 'src/services/user';
+
+import { UserView } from './user-view';
+
+const PartnersView = () => {
+ const [data, setData] = useState();
+ const [loading, setLoading] = useState(true);
+
+ const init = async () => {
+ const list = await UserService.list();
+ setData(list);
+ setLoading(false);
+ };
+
+ useEffect(() => {
+ init();
+ }, []);
+
+ return ;
+};
+
+export default PartnersView;
diff --git a/src/sections/user/view/user-view.tsx b/src/sections/user/view/user-view.tsx
index 5c5e96a2f..eb0b62e6d 100644
--- a/src/sections/user/view/user-view.tsx
+++ b/src/sections/user/view/user-view.tsx
@@ -1,120 +1,130 @@
+import type { User } from 'src/services/user/user.dto';
+
import { useState, useCallback } from 'react';
import Box from '@mui/material/Box';
import Card from '@mui/material/Card';
import Table from '@mui/material/Table';
-import Button from '@mui/material/Button';
import TableBody from '@mui/material/TableBody';
import Typography from '@mui/material/Typography';
import TableContainer from '@mui/material/TableContainer';
-import TablePagination from '@mui/material/TablePagination';
import { _users } from 'src/_mock';
import { DashboardContent } from 'src/layouts/dashboard';
-import { Iconify } from 'src/components/iconify';
+import Loader from 'src/components/loader';
import { Scrollbar } from 'src/components/scrollbar';
import { TableNoData } from '../table-no-data';
import { UserTableRow } from '../user-table-row';
import { UserTableHead } from '../user-table-head';
import { TableEmptyRows } from '../table-empty-rows';
-import { UserTableToolbar } from '../user-table-toolbar';
import { emptyRows, applyFilter, getComparator } from '../utils';
-import type { UserProps } from '../user-table-row';
-
// ----------------------------------------------------------------------
-export function UserView() {
+interface PartnersViewProps {
+ data?: User[];
+ loading?: boolean;
+}
+
+export function UserView({ data = [], loading }: PartnersViewProps) {
const table = useTable();
const [filterName, setFilterName] = useState('');
- const dataFiltered: UserProps[] = applyFilter({
- inputData: _users,
+ const dataFiltered = applyFilter({
+ inputData: data.map((item) => ({
+ id: item.id,
+ name: `${item.fname} ${item.lname}`,
+ role: item.role.join(', '),
+ email: item.email,
+ pledge: item.pledgeAmount,
+ })),
comparator: getComparator(table.order, table.orderBy),
filterName,
});
-
const notFound = !dataFiltered.length && !!filterName;
return (
- Users
+ Partners
- }
>
- New user
-
+ Invite Partner
+ */}
- ) => {
setFilterName(event.target.value);
table.onResetPage();
}}
- />
-
-
-
-
-
- table.onSelectAllRows(
- checked,
- _users.map((user) => user.id)
- )
- }
- headLabel={[
- { id: 'name', label: 'Name' },
- { id: 'company', label: 'Company' },
- { id: 'role', label: 'Role' },
- { id: 'isVerified', label: 'Verified', align: 'center' },
- { id: 'status', label: 'Status' },
- { id: '' },
- ]}
- />
-
- {dataFiltered
- .slice(
- table.page * table.rowsPerPage,
- table.page * table.rowsPerPage + table.rowsPerPage
- )
- .map((row) => (
- table.onSelectRow(row.id)}
- />
- ))}
-
- */}
+
+ {loading ? (
+
+ ) : (
+
+
+
+
+ table.onSelectAllRows(
+ checked,
+ data.map((user) => user.id)
+ )
+ }
+ headLabel={[
+ { id: 'name', label: 'Name' },
+ { id: 'role', label: 'Role' },
+ { id: 'email', label: 'Email' },
+ { id: 'pledge', label: 'Pledge' },
+ { id: 'action', label: '' },
+ ]}
/>
-
- {notFound && }
-
-
-
-
-
-
+ {dataFiltered
+ .slice(
+ table.page * table.rowsPerPage,
+ table.page * table.rowsPerPage + table.rowsPerPage
+ )
+ .map((row) => (
+ table.onSelectRow(row.id)}
+ />
+ ))}
+
+
+
+ {notFound && }
+
+
+
+
+ )}
+
+ {/*
+ /> */}
);
diff --git a/src/services/auth/auth.dto.ts b/src/services/auth/auth.dto.ts
new file mode 100644
index 000000000..f181f2e46
--- /dev/null
+++ b/src/services/auth/auth.dto.ts
@@ -0,0 +1,14 @@
+export interface CreateUserBody {
+ fname: string;
+ lname: string;
+ email: string;
+ password?: string;
+ country: string;
+ pledgeAmount: number;
+ secret?: string;
+}
+
+export interface UserLoginBody {
+ email: string;
+ password: string;
+}
diff --git a/src/services/auth/index.ts b/src/services/auth/index.ts
new file mode 100644
index 000000000..78078867d
--- /dev/null
+++ b/src/services/auth/index.ts
@@ -0,0 +1,71 @@
+import type { User } from 'firebase/auth';
+
+import { jwtDecode } from 'jwt-decode';
+
+import { hash } from 'src/utils/encrypt';
+
+import { auth } from 'src/configs/firebase';
+import { Cache, CacheKeys } from 'src/utils';
+
+import UserService from '../user';
+import { UserRole } from '../user/user.dto';
+
+import type { UserLoginBody, CreateUserBody } from './auth.dto';
+
+export default class AuthService {
+ private static token: string | null = Cache.get(CacheKeys.Token);
+
+ static async register(data: CreateUserBody) {
+ const valid = await UserService.validateSecret(data.secret!);
+ delete data?.secret;
+ if (!valid) throw new Error('INVALID_SECRET_KEY');
+ const pass = hash(data.password!);
+ const user = await auth.createUser(data.email, pass);
+ const token = await user.user.getIdToken();
+ this.setToken(token);
+ delete data.password;
+ return UserService.create({
+ ...data,
+ pledgeAmount: Number(data.pledgeAmount),
+ id: user.user.uid,
+ role: [UserRole.Partner],
+ });
+ }
+
+ static async login(data: UserLoginBody) {
+ const pass = hash(data.password);
+ const user = await auth.signIn(data.email, pass);
+ const token = await user.user.getIdToken();
+ this.setToken(token);
+ return UserService.get(user.user.uid);
+ }
+
+ static async logout() {
+ await auth.logout();
+ Cache.clear();
+ }
+
+ static setToken(token: string | null) {
+ this.token = token;
+ Cache.set(CacheKeys.Token, token);
+ }
+
+ static getToken(): string | null {
+ return this.token || Cache.get(CacheKeys.Token);
+ }
+
+ static hasToken() {
+ return !!this.getToken();
+ }
+
+ static decodeToken(token = this.getToken()) {
+ if (!token) return null;
+ const decoded = jwtDecode(token);
+ console.log(decoded);
+ return decoded;
+ }
+
+ static listen(cb: (val: User | null) => void) {
+ auth.listen(cb);
+ }
+}
diff --git a/src/services/cont/contribute.dto.ts b/src/services/cont/contribute.dto.ts
new file mode 100644
index 000000000..b78a40cdb
--- /dev/null
+++ b/src/services/cont/contribute.dto.ts
@@ -0,0 +1,36 @@
+import type { Timestamp } from 'firebase/firestore';
+
+export enum ContributionStatus {
+ Pending = 'PENDING',
+ Failed = 'FAILED',
+ Success = 'COMPLETED',
+}
+
+export interface Contribution {
+ id: string;
+ months: string[];
+ amount: string;
+ status: ContributionStatus;
+ trxRef: string;
+ trxCode: string;
+ createdAt: Timestamp;
+ modifiedAt: Timestamp | null;
+ completedAt: Timestamp | null;
+ donor: {
+ name: string;
+ id: string;
+ };
+}
+
+export interface ContributionResponse
+ extends Omit {
+ createdAt: { _seconds: number; _nanoseconds: number };
+ modifiedAt: { _seconds: number; _nanoseconds: number } | null;
+ completedAt: { _seconds: number; _nanoseconds: number } | null;
+}
+
+export interface CreateContributionParams {
+ amount: string;
+ months: string[];
+ donor: Contribution['donor'];
+}
diff --git a/src/services/cont/index.ts b/src/services/cont/index.ts
new file mode 100644
index 000000000..e04b073a3
--- /dev/null
+++ b/src/services/cont/index.ts
@@ -0,0 +1,97 @@
+import {
+ limit,
+ query,
+ where,
+ getDoc,
+ getDocs,
+ orderBy,
+ Timestamp,
+ onSnapshot,
+ deleteDoc,
+} from 'firebase/firestore';
+
+import { db, fx } from 'src/configs';
+import { Collection } from 'src/constants';
+import { colRef, docRef } from 'src/utils';
+import { ApiRoute } from 'src/constants/fxns';
+
+import { ContributionStatus } from './contribute.dto';
+
+import type { Contribution, ContributionResponse } from './contribute.dto';
+
+export default class ContributionService {
+ private static ref = colRef(Collection.Contributions);
+
+ static async getByUserId(id: string, count = 15) {
+ const q = query(
+ this.ref,
+ where('donor.id', '==', id),
+ limit(count),
+ orderBy('createdAt', 'desc')
+ );
+ const docs = await getDocs(q);
+ const data: Contribution[] = [];
+ docs.forEach((doc) => {
+ data.push(doc.data() as Contribution);
+ });
+ return data;
+ }
+
+ static async listenLatest(cb: (val: Contribution[]) => void, id?: string, count = 15) {
+ const q = query(
+ this.ref,
+ id ? where('donor.id', '==', id) : where('status', '==', ContributionStatus.Success),
+ orderBy('createdAt', 'desc'),
+ limit(count)
+ );
+
+ return onSnapshot(q, ({ docs }) => {
+ const data: Contribution[] = docs.map((doc) => doc.data() as Contribution);
+ cb(data);
+ });
+ }
+
+ static async get(id: string): Promise {
+ const ref = docRef(id, Collection.Contributions);
+ const docRes = await getDoc(ref);
+ return docRes.data() as Contribution;
+ }
+
+ static async getAllLatest() {
+ const q = query(this.ref, limit(15));
+ const docs = await getDocs(q);
+ const data: Contribution[] = [];
+ docs.forEach((doc) => {
+ data.push(doc.data() as Contribution);
+ });
+ return data;
+ }
+
+ static async getList(data?: { page: number; count: number }) {
+ const res = await fx.call<
+ typeof data,
+ {
+ data: ContributionResponse[];
+ metadata: { page: number; next: boolean; prev: boolean; pages: number; rows: number };
+ }
+ >(ApiRoute.GetContributions, data);
+ return {
+ metadata: res.metadata,
+ data: res.data.map(({ createdAt, completedAt, ...item }) => ({
+ ...item,
+ createdAt: new Timestamp(createdAt._seconds, createdAt._nanoseconds),
+ completedAt: completedAt
+ ? new Timestamp(completedAt._seconds, completedAt._nanoseconds)
+ : completedAt,
+ })) as Contribution[],
+ };
+ }
+
+ static async cancel(id: string) {
+ const data = await this.get(id);
+ if (data && data.status === ContributionStatus.Pending) {
+ const doc = docRef(id, Collection.Contributions);
+ await deleteDoc(doc);
+ }
+ }
+}
diff --git a/src/services/pay/index.ts b/src/services/pay/index.ts
new file mode 100644
index 000000000..f6098d654
--- /dev/null
+++ b/src/services/pay/index.ts
@@ -0,0 +1,38 @@
+import PaystackPop from '@paystack/inline-js';
+
+import { fx } from 'src/configs';
+import { errCb } from 'src/utils';
+import { ApiRoute } from 'src/constants/fxns';
+
+import type { ContributeInit } from './pay.dto';
+
+export default class PayService {
+ static async init(amount: number, months: string[]) {
+ try {
+ const res = await fx.call(ApiRoute.InitPayment, {
+ amount,
+ months,
+ callbackUrl: window.location.href,
+ });
+ const popup = new PaystackPop();
+ popup.resumeTransaction(res.code as any);
+ return popup;
+ } catch (error) {
+ const err = error as Error;
+ errCb(err.message);
+ return null;
+ }
+ }
+
+ static async resume(code: string) {
+ try {
+ const popup = new PaystackPop();
+ popup.resumeTransaction(code as any);
+ return popup;
+ } catch (error) {
+ const err = error as Error;
+ errCb(err.message);
+ return null;
+ }
+ }
+}
diff --git a/src/services/pay/pay.dto.ts b/src/services/pay/pay.dto.ts
new file mode 100644
index 000000000..b0d1087c1
--- /dev/null
+++ b/src/services/pay/pay.dto.ts
@@ -0,0 +1,5 @@
+export interface ContributeInit {
+ amount: number | null;
+ months: string[];
+ callbackUrl?: string;
+}
diff --git a/src/services/stats/index.ts b/src/services/stats/index.ts
new file mode 100644
index 000000000..aac377837
--- /dev/null
+++ b/src/services/stats/index.ts
@@ -0,0 +1,14 @@
+import { fx } from 'src/configs';
+import { ApiRoute } from 'src/constants/fxns';
+
+import type { Stats, UserStats } from './stats.dto';
+
+export default class StatsService {
+ static async get() {
+ return fx.call<{}, Stats>(ApiRoute.GetStats);
+ }
+
+ static async getByUser() {
+ return fx.call<{}, UserStats>(ApiRoute.GetUserStats);
+ }
+}
diff --git a/src/services/stats/stats.dto.ts b/src/services/stats/stats.dto.ts
new file mode 100644
index 000000000..c37799cc9
--- /dev/null
+++ b/src/services/stats/stats.dto.ts
@@ -0,0 +1,12 @@
+export interface Stats {
+ partnersCount: number;
+ contributionCount: number;
+ totalAmount: number;
+ expectedMonthly: number;
+}
+
+export interface UserStats {
+ contributionCount: number;
+ totalContribution: number;
+ pledge: number;
+}
diff --git a/src/services/trxn/trx.dto.ts b/src/services/trxn/trx.dto.ts
new file mode 100644
index 000000000..c7f12165b
--- /dev/null
+++ b/src/services/trxn/trx.dto.ts
@@ -0,0 +1,30 @@
+import type { Timestamp } from 'firebase/firestore';
+
+export enum TrxStatus {
+ Initiated = 'INITIATED',
+ Pending = 'PENDING',
+ Completed = 'COMPLETED',
+ Cancelled = 'CANCELLED',
+}
+
+export interface InitTransactionPayload {
+ email: string;
+ amount: string;
+}
+
+export interface Trxn {
+ id: string;
+ status: TrxStatus;
+ initiateAt: Timestamp;
+ completeAt: Timestamp | null;
+ modifiedAt: Timestamp | null;
+ trxRef: string;
+ trxCode: string;
+ trxUrl: string;
+ amount: string;
+ initiator: {
+ name: string;
+ id: string;
+ email: string;
+ };
+}
diff --git a/src/services/user/index.ts b/src/services/user/index.ts
new file mode 100644
index 000000000..eb61f860b
--- /dev/null
+++ b/src/services/user/index.ts
@@ -0,0 +1,46 @@
+import { getDoc, setDoc, getDocs, updateDoc } from 'firebase/firestore';
+
+import { fx } from 'src/configs';
+import { colRef, docRef } from 'src/utils';
+import { ApiRoute } from 'src/constants/fxns';
+import { Collection } from 'src/constants/factory';
+
+import type { User} from './user.dto';
+
+export default class UserService {
+ static async get(id: string): Promise {
+ const ref = docRef(id, Collection.Users);
+ const docRes = await getDoc(ref);
+ return docRes.data() as User;
+ }
+
+ static async me() {
+ return fx.call<{}, User>(ApiRoute.GetUser, {});
+ }
+
+ static async create(data: User) {
+ const ref = docRef(data.id, Collection.Users);
+ await setDoc(ref, data);
+ return data;
+ }
+
+ static async validateSecret(val: string) {
+ const ref = docRef(val, Collection.Secret);
+ const secretDoc = await getDoc(ref);
+ return secretDoc.exists();
+ }
+
+ static async update(id: string, data: Partial) {
+ const ref = docRef(id, Collection.Users);
+ await updateDoc(ref, data);
+ }
+
+ static async list() {
+ const ref = colRef(Collection.Users);
+ const { docs, empty } = await getDocs(ref);
+ if (!empty) {
+ return docs.map((document) => document.data() as User);
+ }
+ return [];
+ }
+}
diff --git a/src/services/user/user.dto.ts b/src/services/user/user.dto.ts
new file mode 100644
index 000000000..d14f7fcbd
--- /dev/null
+++ b/src/services/user/user.dto.ts
@@ -0,0 +1,16 @@
+export enum UserRole {
+ Admin = 'ADMIN',
+ Partner = 'PARTNER',
+}
+
+export interface User {
+ id: string;
+ fname: string;
+ lname: string;
+ email: string;
+ country: string;
+ pledgeAmount: number;
+ role: UserRole[];
+}
+
+export interface UserUpdateBody extends Omit {}
diff --git a/src/utils/alert.ts b/src/utils/alert.ts
new file mode 100644
index 000000000..29c4dbf7b
--- /dev/null
+++ b/src/utils/alert.ts
@@ -0,0 +1,13 @@
+import type { AppAlertMethods } from 'src/components/shared/alert';
+
+export class AlertUtil {
+ private static ref: AppAlertMethods | null;
+
+ public static setRef(_ref: AppAlertMethods | null) {
+ this.ref = _ref;
+ }
+
+ public static getRef(): AppAlertMethods | null {
+ return this.ref;
+ }
+}
diff --git a/src/utils/cache.ts b/src/utils/cache.ts
new file mode 100644
index 000000000..96f9b9c57
--- /dev/null
+++ b/src/utils/cache.ts
@@ -0,0 +1,39 @@
+import { payloadHash, payloadDeHash } from './encrypt';
+
+export enum CacheKeys {
+ Token = 'my.auth.id.t',
+ Admin = 'dash.admin.mode',
+ AdminMode = 'dash.is.admin.mode',
+}
+
+export class Cache {
+ static set(id: CacheKeys, data: T) {
+ return localStorage.setItem(id as any, this.parse(data));
+ }
+
+ static get(id: CacheKeys) {
+ const hash = localStorage.getItem(id);
+ if (!hash) return null;
+ return this.unparse(hash) as T;
+ }
+
+ private static parse(data: T) {
+ if (!data) return '';
+ const payloadString = JSON.stringify(data);
+ return payloadHash(payloadString);
+ }
+
+ private static unparse(hash: string) {
+ if (!hash) return null;
+ const payloadString = payloadDeHash(hash);
+ return JSON.parse(payloadString);
+ }
+
+ static delete(id: CacheKeys) {
+ localStorage.removeItem(id);
+ }
+
+ static clear() {
+ localStorage.clear();
+ }
+}
diff --git a/src/utils/encrypt.ts b/src/utils/encrypt.ts
new file mode 100644
index 000000000..149694c1a
--- /dev/null
+++ b/src/utils/encrypt.ts
@@ -0,0 +1,15 @@
+import crypto from 'crypto-js';
+
+const KEY = '1NF1U3N51NG11V35';
+
+export function hash(plainText: string) {
+ return crypto.SHA256(KEY + plainText).toString(crypto.enc.Hex);
+}
+
+export function payloadHash(plainText: string) {
+ return crypto.AES.encrypt(plainText, KEY).toString();
+}
+
+export function payloadDeHash(hashVal: string) {
+ return crypto.AES.decrypt(hashVal, KEY).toString(crypto.enc.Utf8);
+}
diff --git a/src/utils/errors.ts b/src/utils/errors.ts
new file mode 100644
index 000000000..b5574ef09
--- /dev/null
+++ b/src/utils/errors.ts
@@ -0,0 +1,5 @@
+import { AlertUtil } from './alert';
+
+export const errCb = (val: string) => {
+ AlertUtil.getRef()?.show({ label: val, type: 'error' });
+};
diff --git a/src/utils/format-number.ts b/src/utils/format-number.ts
index e0c5198b9..ecc799396 100644
--- a/src/utils/format-number.ts
+++ b/src/utils/format-number.ts
@@ -7,7 +7,7 @@ export type InputNumberValue = string | number | null | undefined;
type Options = Intl.NumberFormatOptions | undefined;
-const DEFAULT_LOCALE = { code: 'en-US', currency: 'USD' };
+const DEFAULT_LOCALE = { code: 'en-US', currency: 'GHS' };
function processInput(inputValue: InputNumberValue): number | null {
if (inputValue == null || Number.isNaN(inputValue)) return null;
diff --git a/src/utils/fstore.ts b/src/utils/fstore.ts
new file mode 100644
index 000000000..2da02bc03
--- /dev/null
+++ b/src/utils/fstore.ts
@@ -0,0 +1,13 @@
+import type { Collection } from 'src/constants/factory';
+
+import { doc, collection } from 'firebase/firestore';
+
+import { db } from 'src/configs';
+
+export function docRef(id: string, col: Collection) {
+ return doc(db, col, id);
+}
+
+export function colRef(col:Collection){
+ return collection(db,col)
+}
diff --git a/src/utils/index.ts b/src/utils/index.ts
new file mode 100644
index 000000000..5d9b03c6b
--- /dev/null
+++ b/src/utils/index.ts
@@ -0,0 +1,5 @@
+export * from './alert';
+export * from './cache';
+export * from './fstore';
+export * from './errors';
+export * from './encrypt';
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
index 11f02fe2a..d5066fece 100644
--- a/src/vite-env.d.ts
+++ b/src/vite-env.d.ts
@@ -1 +1,16 @@
///
+///
+
+interface ImportMetaEnv {
+ readonly VITE_FIREBASE_API_KEY: string;
+ readonly VITE_FIREBASE_AUTH_DOMAIN: string;
+ readonly VITE_FIREBASE_PROJECT_ID: string;
+ readonly VITE_FIREBASE_STORAGE_BUCKET: string;
+ readonly VITE_FIREBASE_MESSAGE_SENDER_ID: string;
+ readonly VITE_FIREBASE_APP_ID: string;
+ readonly VITE_FIREBASE_MEASUREMENT_ID: string;
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
diff --git a/tsconfig.json b/tsconfig.json
index 9bce082b7..a8aa76b30 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -21,7 +21,7 @@
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true
},
- "include": ["src"],
+ "include": ["src", "env.d.ts"],
"exclude": ["node_modules"],
"references": [
{
diff --git a/yarn.lock b/yarn.lock
index eb21c020b..b9e7ce203 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7,96 +7,87 @@
resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz"
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.7":
- version "7.24.7"
- resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz"
- integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.25.9":
+ version "7.26.2"
+ resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz"
+ integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
dependencies:
- "@babel/highlight" "^7.24.7"
+ "@babel/helper-validator-identifier" "^7.25.9"
+ js-tokens "^4.0.0"
picocolors "^1.0.0"
-"@babel/generator@^7.25.4":
- version "7.25.4"
- resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.25.4.tgz"
- integrity sha512-NFtZmZsyzDPJnk9Zg3BbTfKKc9UlHYzD0E//p2Z3B9nCwwtJW9T0gVbCz8+fBngnn4zf1Dr3IK8PHQQHq0lDQw==
+"@babel/generator@^7.25.9":
+ version "7.26.2"
+ resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz"
+ integrity sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==
dependencies:
- "@babel/types" "^7.25.4"
+ "@babel/parser" "^7.26.2"
+ "@babel/types" "^7.26.0"
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.25"
- jsesc "^2.5.1"
+ jsesc "^3.0.2"
"@babel/helper-module-imports@^7.16.7":
- version "7.24.7"
- resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz"
- integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==
- dependencies:
- "@babel/traverse" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/helper-string-parser@^7.24.8":
- version "7.24.8"
- resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz"
- integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==
-
-"@babel/helper-validator-identifier@^7.24.7":
- version "7.24.7"
- resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz"
- integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
-
-"@babel/highlight@^7.24.7":
- version "7.24.7"
- resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz"
- integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==
- dependencies:
- "@babel/helper-validator-identifier" "^7.24.7"
- chalk "^2.4.2"
- js-tokens "^4.0.0"
- picocolors "^1.0.0"
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz"
+ integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==
+ dependencies:
+ "@babel/traverse" "^7.25.9"
+ "@babel/types" "^7.25.9"
-"@babel/parser@^7.25.0", "@babel/parser@^7.25.4":
- version "7.25.4"
- resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz"
- integrity sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==
+"@babel/helper-string-parser@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz"
+ integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
+
+"@babel/helper-validator-identifier@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz"
+ integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
+
+"@babel/parser@^7.25.9", "@babel/parser@^7.26.2":
+ version "7.26.2"
+ resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz"
+ integrity sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==
dependencies:
- "@babel/types" "^7.25.4"
+ "@babel/types" "^7.26.0"
"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.7":
- version "7.25.4"
- resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz"
- integrity sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==
+ version "7.26.0"
+ resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz"
+ integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
dependencies:
regenerator-runtime "^0.14.0"
-"@babel/template@^7.25.0":
- version "7.25.0"
- resolved "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz"
- integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==
- dependencies:
- "@babel/code-frame" "^7.24.7"
- "@babel/parser" "^7.25.0"
- "@babel/types" "^7.25.0"
-
-"@babel/traverse@^7.24.7":
- version "7.25.4"
- resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz"
- integrity sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==
- dependencies:
- "@babel/code-frame" "^7.24.7"
- "@babel/generator" "^7.25.4"
- "@babel/parser" "^7.25.4"
- "@babel/template" "^7.25.0"
- "@babel/types" "^7.25.4"
+"@babel/template@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz"
+ integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==
+ dependencies:
+ "@babel/code-frame" "^7.25.9"
+ "@babel/parser" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/traverse@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz"
+ integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==
+ dependencies:
+ "@babel/code-frame" "^7.25.9"
+ "@babel/generator" "^7.25.9"
+ "@babel/parser" "^7.25.9"
+ "@babel/template" "^7.25.9"
+ "@babel/types" "^7.25.9"
debug "^4.3.1"
globals "^11.1.0"
-"@babel/types@^7.24.7", "@babel/types@^7.25.0", "@babel/types@^7.25.4":
- version "7.25.4"
- resolved "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz"
- integrity sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==
+"@babel/types@^7.25.9", "@babel/types@^7.26.0":
+ version "7.26.0"
+ resolved "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz"
+ integrity sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==
dependencies:
- "@babel/helper-string-parser" "^7.24.8"
- "@babel/helper-validator-identifier" "^7.24.7"
- to-fast-properties "^2.0.0"
+ "@babel/helper-string-parser" "^7.25.9"
+ "@babel/helper-validator-identifier" "^7.25.9"
"@emotion/babel-plugin@^11.12.0":
version "11.12.0"
@@ -158,14 +149,14 @@
hoist-non-react-statics "^3.3.1"
"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0", "@emotion/serialize@^1.3.1":
- version "1.3.1"
- resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.1.tgz"
- integrity sha512-dEPNKzBPU+vFPGa+z3axPRn8XVDetYORmDC0wAiej+TNcOZE70ZMJa0X7JdeoM6q/nWTMZeLpN/fTnD9o8MQBA==
+ version "1.3.2"
+ resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz"
+ integrity sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==
dependencies:
"@emotion/hash" "^0.9.2"
"@emotion/memoize" "^0.9.0"
"@emotion/unitless" "^0.10.0"
- "@emotion/utils" "^1.4.0"
+ "@emotion/utils" "^1.4.1"
csstype "^3.0.2"
"@emotion/sheet@^1.4.0":
@@ -195,20 +186,20 @@
resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz"
integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==
-"@emotion/utils@^1.4.0":
- version "1.4.0"
- resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz"
- integrity sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==
+"@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz"
+ integrity sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==
"@emotion/weak-memoize@^0.4.0":
version "0.4.0"
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
-"@esbuild/darwin-arm64@0.21.5":
+"@esbuild/win32-x64@0.21.5":
version "0.21.5"
- resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz"
- integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
+ resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz"
+ integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
@@ -242,6 +233,396 @@
resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz"
integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==
+"@firebase/analytics-compat@0.2.15":
+ version "0.2.15"
+ resolved "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.15.tgz"
+ integrity sha512-C5to422Sr8FkL0MPwXcIecbMnF4o2Ll7MtoWvIm4Q/LPJvvM+tWa1DiU+LzsCdsd1/CYE9EIW9Ma3ko9XnAAYw==
+ dependencies:
+ "@firebase/analytics" "0.10.9"
+ "@firebase/analytics-types" "0.8.2"
+ "@firebase/component" "0.6.10"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/analytics-types@0.8.2":
+ version "0.8.2"
+ resolved "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz"
+ integrity sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==
+
+"@firebase/analytics@0.10.9":
+ version "0.10.9"
+ resolved "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.9.tgz"
+ integrity sha512-FrvW6u6xDBKXUGYUy1WIUh0J9tvbppMsk90mig0JhHST8iLveKu/dIBVeVE/ZYZhmXy4fkI7SPSWvD1V0O4tXw==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/installations" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/app-check-compat@0.3.16":
+ version "0.3.16"
+ resolved "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.16.tgz"
+ integrity sha512-AxIGzLRXrTFNL+H6V+4BO0w/gERloROfRbWI/FoJUnQd0qPZIzyfdHZBbThFzFGLfDt/mVs2kdjYFx/l9I8NhQ==
+ dependencies:
+ "@firebase/app-check" "0.8.9"
+ "@firebase/app-check-types" "0.5.2"
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/app-check-interop-types@0.3.2":
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz"
+ integrity sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==
+
+"@firebase/app-check-types@0.5.2":
+ version "0.5.2"
+ resolved "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz"
+ integrity sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==
+
+"@firebase/app-check@0.8.9":
+ version "0.8.9"
+ resolved "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.9.tgz"
+ integrity sha512-YzVn1mMLzD2JboMPVVO0Pe20YOgWzrF+aXoAmmd0v3xec051n83YpxSUZbacL69uYvk0dHrEsbea44QtQ5WPDA==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/app-compat@0.2.45", "@firebase/app-compat@0.x":
+ version "0.2.45"
+ resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.45.tgz"
+ integrity sha512-5rYbXq1ndtMTg+07oH4WrkYuP+NZq61uzVwW1hlmybp/gr4cXq2SfaP9fc6/9IzTKmu3dh3H0fjj++HG7Z7o/w==
+ dependencies:
+ "@firebase/app" "0.10.15"
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/app-types@0.9.2", "@firebase/app-types@0.x":
+ version "0.9.2"
+ resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz"
+ integrity sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==
+
+"@firebase/app@0.10.15", "@firebase/app@0.x":
+ version "0.10.15"
+ resolved "https://registry.npmjs.org/@firebase/app/-/app-0.10.15.tgz"
+ integrity sha512-he6qlG3pmwL+LHdG/BrSMBQeJzzutciq4fpXN3lGa1uSwYSijJ24VtakS/bP2X9SiDf8jGywJ4u+OgXAenJsNg==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ idb "7.1.1"
+ tslib "^2.1.0"
+
+"@firebase/auth-compat@0.5.15":
+ version "0.5.15"
+ resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.15.tgz"
+ integrity sha512-jz6k1ridPiecKI8CBRiqCM6IMOhwYp2MD+YvoxnMiK8nQLSTm57GvHETlPNX3WlbyQnCjMCOvrAhe27whyxAEg==
+ dependencies:
+ "@firebase/auth" "1.8.0"
+ "@firebase/auth-types" "0.12.2"
+ "@firebase/component" "0.6.10"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/auth-interop-types@0.2.3":
+ version "0.2.3"
+ resolved "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz"
+ integrity sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==
+
+"@firebase/auth-types@0.12.2":
+ version "0.12.2"
+ resolved "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz"
+ integrity sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==
+
+"@firebase/auth@1.8.0":
+ version "1.8.0"
+ resolved "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.0.tgz"
+ integrity sha512-/O7UDWE5S5ux456fzNHSLx/0YN/Kykw/WyAzgDQ6wvkddZhSEmPX19EzxgsFldzhuFjsl5uOZTz8kzlosCiJjg==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/component@0.6.10":
+ version "0.6.10"
+ resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.10.tgz"
+ integrity sha512-OsNbEKyz9iLZSmMUhsl6+kCADzte00iisJIRUspnUqvDCX+RSGZOBIqekukv/jN177ovjApBQNFaxSYIDc/SyQ==
+ dependencies:
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/data-connect@0.1.1":
+ version "0.1.1"
+ resolved "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.1.tgz"
+ integrity sha512-RBJ7XE/a3oXFv31Jlw8cbMRdsxQoI8F3L7xm4n93ab+bIr1NQUiYGgW9L7TTw7obdNev91ZnW0xfqJtXcPA5yA==
+ dependencies:
+ "@firebase/auth-interop-types" "0.2.3"
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/database-compat@2.0.0":
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.0.tgz"
+ integrity sha512-2xlODKWwf/vNAxCmou0GFhymx2pqZKkhXMN9B5aiTjZ6+81sOxGim53ELY2lj+qKG2IvgiCYFc4X+ZJA2Ad5vg==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/database" "1.0.9"
+ "@firebase/database-types" "1.0.6"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/database-types@1.0.6":
+ version "1.0.6"
+ resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.6.tgz"
+ integrity sha512-sMI7IynSZBsyGbUugc8PKE1jwKbnvaieAz/RxuM57PZQNCi6Rteiviwcw/jqZOX6igqYJwXWZ3UzKOZo2nUDRA==
+ dependencies:
+ "@firebase/app-types" "0.9.2"
+ "@firebase/util" "1.10.1"
+
+"@firebase/database@1.0.9":
+ version "1.0.9"
+ resolved "https://registry.npmjs.org/@firebase/database/-/database-1.0.9.tgz"
+ integrity sha512-EkiPSKSu2TJJGtOjyISASf3UFpFJDil1lMbfqnxilfbmIsilvC8DzgjuLoYD+eOitcug4wtU9Fh1tt2vgBhskA==
+ dependencies:
+ "@firebase/app-check-interop-types" "0.3.2"
+ "@firebase/auth-interop-types" "0.2.3"
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ faye-websocket "0.11.4"
+ tslib "^2.1.0"
+
+"@firebase/firestore-compat@0.3.39":
+ version "0.3.39"
+ resolved "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.39.tgz"
+ integrity sha512-CsK8g34jNeHx95LISDRTcArJLonW+zJCqHI1Ez9WNiLAK2X8FeQ4UiD+RwOwxAIR+t2a6xED/5Fe6ZIqx7MuoQ==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/firestore" "4.7.4"
+ "@firebase/firestore-types" "3.0.2"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/firestore-types@3.0.2":
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz"
+ integrity sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==
+
+"@firebase/firestore@4.7.4":
+ version "4.7.4"
+ resolved "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.4.tgz"
+ integrity sha512-K2nq4w+NF8J1waGawY5OHLawP/Aw5CYxyDstVv1NZemGPcM3U+LZ9EPaXr1PatYIrPA7fS4DxZoWcbB0aGJ8Zg==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ "@firebase/webchannel-wrapper" "1.0.2"
+ "@grpc/grpc-js" "~1.9.0"
+ "@grpc/proto-loader" "^0.7.8"
+ tslib "^2.1.0"
+
+"@firebase/functions-compat@0.3.15":
+ version "0.3.15"
+ resolved "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.15.tgz"
+ integrity sha512-eiHpc6Sd9Y/SNhBsGi944SapiFbfTPKsiSUQ74QxNSs0yoxvABeIRolVMFk4TokP57NGmstGYpYte02XGNPcYw==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/functions" "0.11.9"
+ "@firebase/functions-types" "0.6.2"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/functions-types@0.6.2":
+ version "0.6.2"
+ resolved "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz"
+ integrity sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==
+
+"@firebase/functions@0.11.9":
+ version "0.11.9"
+ resolved "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.9.tgz"
+ integrity sha512-dhO5IUfQRCsrc20YD20nSOX+QCT+cH6N86HlZOLz2XgyEFgzOdBQnUot4EabBJQRkMBI7fZWUrbYfRcnov53ug==
+ dependencies:
+ "@firebase/app-check-interop-types" "0.3.2"
+ "@firebase/auth-interop-types" "0.2.3"
+ "@firebase/component" "0.6.10"
+ "@firebase/messaging-interop-types" "0.2.2"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/installations-compat@0.2.10":
+ version "0.2.10"
+ resolved "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.10.tgz"
+ integrity sha512-YTonkcVz3AK7RF8xFhvs5CwDuJ0xbzzCJIwXoV14gnzdYbMgy6vWlUUbzkvbtEDXzPRHB0n7aGZl56oy9dLOFw==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/installations" "0.6.10"
+ "@firebase/installations-types" "0.5.2"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/installations-types@0.5.2":
+ version "0.5.2"
+ resolved "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz"
+ integrity sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==
+
+"@firebase/installations@0.6.10":
+ version "0.6.10"
+ resolved "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.10.tgz"
+ integrity sha512-TuGSOMqkFrllxa0X/8VZIqBCRH4POndU/iWKWkRmkh12+/xKSpdp+y/kWaVbsySrelltan6LeYlcYPmLibWbwg==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/util" "1.10.1"
+ idb "7.1.1"
+ tslib "^2.1.0"
+
+"@firebase/logger@0.4.3":
+ version "0.4.3"
+ resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.3.tgz"
+ integrity sha512-Th42bWJg18EF5bJwhRosn2M/eYxmbWCwXZr4hHX7ltO0SE3QLrpgiMKeRBR/NW7vJke7i0n3i8esbCW2s93qBw==
+ dependencies:
+ tslib "^2.1.0"
+
+"@firebase/messaging-compat@0.2.13":
+ version "0.2.13"
+ resolved "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.13.tgz"
+ integrity sha512-9ootPClS6m2c2KIzo7AqSHaWzAw28zWcjQPjVv7WeQDu6wjufpbOg+7tuVzb+gqpF9Issa3lDoYOwlO0ZudO3g==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/messaging" "0.12.13"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/messaging-interop-types@0.2.2":
+ version "0.2.2"
+ resolved "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz"
+ integrity sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==
+
+"@firebase/messaging@0.12.13":
+ version "0.12.13"
+ resolved "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.13.tgz"
+ integrity sha512-YLa8PWl+BgiOVR5WOyzl21fVJFJeBRfniNuN25d9DBrQzppSAahuN6yS+vt1OIjvZNPN4pZ/lcRLYupbGu4W0w==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/installations" "0.6.10"
+ "@firebase/messaging-interop-types" "0.2.2"
+ "@firebase/util" "1.10.1"
+ idb "7.1.1"
+ tslib "^2.1.0"
+
+"@firebase/performance-compat@0.2.10":
+ version "0.2.10"
+ resolved "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.10.tgz"
+ integrity sha512-0h1qYkF6I79DSSpHfTQFvb91fo8shmmwiPzWFYAPdPK02bSWpKwVssNYlZX2iUnumxerDMbl7dWN+Im/W3bnXA==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/performance" "0.6.10"
+ "@firebase/performance-types" "0.2.2"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/performance-types@0.2.2":
+ version "0.2.2"
+ resolved "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz"
+ integrity sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==
+
+"@firebase/performance@0.6.10":
+ version "0.6.10"
+ resolved "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.10.tgz"
+ integrity sha512-x/mNYKGxq7A+QV0EiEZeD2S+E+kw+UcZ8FXuE7qDJyGGt/0Wd+bIIL7RakG/VrFt7/UYc//nKygDc7/Ig7sOmQ==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/installations" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/remote-config-compat@0.2.10":
+ version "0.2.10"
+ resolved "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.10.tgz"
+ integrity sha512-fIi5OB2zk0zpChMV/tTd0oEZcZI8TlwQDlLlcrDpMOV5l5dqd0JNlWKh6Fwmh4izmytk+rZIAIpnak/NjGVesQ==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/remote-config" "0.4.10"
+ "@firebase/remote-config-types" "0.3.2"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/remote-config-types@0.3.2":
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz"
+ integrity sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==
+
+"@firebase/remote-config@0.4.10":
+ version "0.4.10"
+ resolved "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.10.tgz"
+ integrity sha512-jTRjy3TdqzVna19m5a1HEHE5BG4Z3BQTxBgvQRTmMKlHacx4QS0CToAas7R9M9UkxpgFcVuAE7FpWIOWQGCEWw==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/installations" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/storage-compat@0.3.13":
+ version "0.3.13"
+ resolved "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.13.tgz"
+ integrity sha512-15kje7JALswRCBKsCSvKg5FbqUYykaIMqMbZRD7I6uVRWwdyTvez5MBQfMhBia2JcEmPiDpXhJTXH4PAWFiA8g==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/storage" "0.13.3"
+ "@firebase/storage-types" "0.8.2"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/storage-types@0.8.2":
+ version "0.8.2"
+ resolved "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz"
+ integrity sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==
+
+"@firebase/storage@0.13.3":
+ version "0.13.3"
+ resolved "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.3.tgz"
+ integrity sha512-B5HiJ7isYKaT4dOEV43f2ySdhQxzq+SQEm7lqXebJ8AYCsebdHrgGzrPR0LR962xGjPzJHFKx63gA8Be/P2MCw==
+ dependencies:
+ "@firebase/component" "0.6.10"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/util@1.10.1", "@firebase/util@1.x":
+ version "1.10.1"
+ resolved "https://registry.npmjs.org/@firebase/util/-/util-1.10.1.tgz"
+ integrity sha512-AIhFnCCjM8FmCqSNlNPTuOk3+gpHC1RkeNUBLtPbcqGYpN5MxI5q7Yby+rxycweOZOCboDzfIj8WyaY4tpQG/g==
+ dependencies:
+ tslib "^2.1.0"
+
+"@firebase/vertexai@1.0.0":
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.0.tgz"
+ integrity sha512-48N3Lp/9GgiCCRfrSdHS+Y1IiMdYXvnHFO/f+HL1PgUtBq7WQ/fWmYOX3mzAN36zvytq13nb68ImF+GALopp+Q==
+ dependencies:
+ "@firebase/app-check-interop-types" "0.3.2"
+ "@firebase/component" "0.6.10"
+ "@firebase/logger" "0.4.3"
+ "@firebase/util" "1.10.1"
+ tslib "^2.1.0"
+
+"@firebase/webchannel-wrapper@1.0.2":
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.2.tgz"
+ integrity sha512-3F4iA2E+NtdMbOU0XC1cHE8q6MqpGIKRj62oGOF38S6AAx5VHR9cXmoDUSj7ejvTAT7m6jxuEeQkHeq0F+mU2w==
+
"@floating-ui/core@^1.6.0":
version "1.6.7"
resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz"
@@ -279,6 +660,24 @@
resolved "https://registry.npmjs.org/@fontsource/barlow/-/barlow-5.0.14.tgz"
integrity sha512-4F+rbfklgWHatFheB3ZQgTFjkqzMiWfHomy69TWSGc0qU+w+QhX9dGz7IVQRksvKciJoXAhxijCxwAJw418g4Q==
+"@grpc/grpc-js@~1.9.0":
+ version "1.9.15"
+ resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz"
+ integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==
+ dependencies:
+ "@grpc/proto-loader" "^0.7.8"
+ "@types/node" ">=12.12.47"
+
+"@grpc/proto-loader@^0.7.8":
+ version "0.7.13"
+ resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz"
+ integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==
+ dependencies:
+ lodash.camelcase "^4.3.0"
+ long "^5.0.0"
+ protobufjs "^7.2.5"
+ yargs "^17.7.2"
+
"@humanwhocodes/config-array@^0.11.14":
version "0.11.14"
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz"
@@ -425,9 +824,9 @@
prop-types "^15.8.1"
"@mui/types@^7.2.14", "@mui/types@^7.2.15":
- version "7.2.15"
- resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz"
- integrity sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==
+ version "7.2.19"
+ resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz"
+ integrity sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA==
"@mui/utils@^5.15.14", "@mui/utils@^5.16.5", "@mui/utils@^5.16.6":
version "5.16.6"
@@ -462,6 +861,11 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
+"@paystack/inline-js@^2.22.1":
+ version "2.22.1"
+ resolved "https://registry.npmjs.org/@paystack/inline-js/-/inline-js-2.22.1.tgz"
+ integrity sha512-h9cf+3UbFY/+/GRA5XeWj769KaSHuedqIcuYDdV6voKGnwF9qcmJ3BorpIST45Y3qVXljOXsexL2tS6GZXJbmg==
+
"@pkgr/core@^0.1.0":
version "0.1.1"
resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz"
@@ -472,20 +876,73 @@
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
+"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz"
+ integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==
+
+"@protobufjs/base64@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz"
+ integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
+
+"@protobufjs/codegen@^2.0.4":
+ version "2.0.4"
+ resolved "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz"
+ integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
+
+"@protobufjs/eventemitter@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz"
+ integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==
+
+"@protobufjs/fetch@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz"
+ integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==
+ dependencies:
+ "@protobufjs/aspromise" "^1.1.1"
+ "@protobufjs/inquire" "^1.1.0"
+
+"@protobufjs/float@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz"
+ integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==
+
+"@protobufjs/inquire@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz"
+ integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==
+
+"@protobufjs/path@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz"
+ integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==
+
+"@protobufjs/pool@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz"
+ integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==
+
+"@protobufjs/utf8@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz"
+ integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
+
"@remix-run/router@1.19.1":
version "1.19.1"
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz"
integrity sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==
-"@rollup/rollup-darwin-arm64@4.21.0":
+"@rollup/rollup-win32-x64-msvc@4.21.0":
version "4.21.0"
- resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz"
- integrity sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==
+ resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.0.tgz"
+ integrity sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==
-"@swc/core-darwin-arm64@1.7.14":
+"@swc/core-win32-x64-msvc@1.7.14":
version "1.7.14"
- resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.14.tgz"
- integrity sha512-V0OUXjOH+hdGxDYG8NkQzy25mKOpcNKFpqtZEzLe5V/CpLJPnpg1+pMz70m14s9ZFda9OxsjlvPbg1FLUwhgIQ==
+ resolved "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.14.tgz"
+ integrity sha512-NNrprQCK6d28mG436jVo2TD+vACHseUECacEBGZ9Ef0qfOIWS1XIt2MisQKG0Oea2VvLFl6tF/V4Lnx/H0Sn3Q==
"@swc/core@^1.5.7":
version "1.7.14"
@@ -518,6 +975,16 @@
dependencies:
"@swc/counter" "^0.1.3"
+"@types/bcryptjs@^2.4.6":
+ version "2.4.6"
+ resolved "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz"
+ integrity sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==
+
+"@types/crypto-js@^4.2.2":
+ version "4.2.2"
+ resolved "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz"
+ integrity sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==
+
"@types/estree@1.0.5":
version "1.0.5"
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz"
@@ -540,7 +1007,7 @@
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz"
integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==
-"@types/node@^18.0.0 || >=20.0.0", "@types/node@^22.5.0":
+"@types/node@^18.0.0 || >=20.0.0", "@types/node@^22.5.0", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
version "22.5.0"
resolved "https://registry.npmjs.org/@types/node/-/node-22.5.0.tgz"
integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==
@@ -552,10 +1019,15 @@
resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz"
integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
+"@types/paystack__inline-js@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/@types/paystack__inline-js/-/paystack__inline-js-1.0.0.tgz"
+ integrity sha512-LCU5rSBs3FAG8tkn1hgV9FHTTRk+Kj2s/DupNlJRem5NaVabj6AASjWJ9tBtJX6dt7bcKhkf8c5MzgJUkpOG2g==
+
"@types/prop-types@*", "@types/prop-types@^15.7.12":
- version "15.7.12"
- resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz"
- integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
+ version "15.7.13"
+ resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz"
+ integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==
"@types/react-dom@^18.3.0":
version "18.3.0"
@@ -571,7 +1043,7 @@
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@^17.0.0 || ^18.0.0", "@types/react@^18.3.4":
+"@types/react@*", "@types/react@^17.0.0 || ^18.0.0", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.3.4":
version "18.3.4"
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz"
integrity sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==
@@ -709,12 +1181,12 @@ ansi-regex@^5.0.1:
resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ansi-styles@^4.0.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
- color-convert "^1.9.0"
+ color-convert "^2.0.1"
ansi-styles@^4.1.0:
version "4.3.0"
@@ -887,6 +1359,11 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+bcryptjs@^2.4.3:
+ version "2.4.3"
+ resolved "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz"
+ integrity sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==
+
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
@@ -930,15 +1407,6 @@ callsites@^3.0.0:
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-chalk@^2.4.2:
- version "2.4.2"
- resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
chalk@^4.0.0:
version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
@@ -970,18 +1438,20 @@ chokidar@^3.5.1:
optionalDependencies:
fsevents "~2.3.2"
+cliui@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz"
+ integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.1"
+ wrap-ansi "^7.0.0"
+
clsx@^2.1.0, clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
-color-convert@^1.9.0:
- version "1.9.3"
- resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
-
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
@@ -994,11 +1464,6 @@ color-name@~1.1.4:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-color-name@1.1.3:
- version "1.1.3"
- resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
- integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
-
commander@^8.0.0:
version "8.3.0"
resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz"
@@ -1039,6 +1504,11 @@ cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"
+crypto-js@^4.2.0:
+ 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==
+
csstype@^3.0.2, csstype@^3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
@@ -1170,6 +1640,11 @@ dom-helpers@^5.0.1:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
emoji-regex@^9.2.2:
version "9.2.2"
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz"
@@ -1350,10 +1825,10 @@ esbuild@^0.21.3:
"@esbuild/win32-ia32" "0.21.5"
"@esbuild/win32-x64" "0.21.5"
-escape-string-regexp@^1.0.5:
- version "1.0.5"
- resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
- integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+escalade@^3.1.1:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz"
+ integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
escape-string-regexp@^4.0.0:
version "4.0.0"
@@ -1651,6 +2126,13 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
+faye-websocket@0.11.4:
+ version "0.11.4"
+ resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz"
+ integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==
+ dependencies:
+ websocket-driver ">=0.5.1"
+
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
@@ -1678,6 +2160,40 @@ find-up@^5.0.0:
locate-path "^6.0.0"
path-exists "^4.0.0"
+firebase@^11.0.1:
+ version "11.0.1"
+ resolved "https://registry.npmjs.org/firebase/-/firebase-11.0.1.tgz"
+ integrity sha512-qsFb8dMcQINEDhJteG7RP+GqwgSRvfyiexQqHd5JToDdm87i9I2rGC4XQsGawKGxzKwZ/ISdgwNWxXAFYdCC6A==
+ dependencies:
+ "@firebase/analytics" "0.10.9"
+ "@firebase/analytics-compat" "0.2.15"
+ "@firebase/app" "0.10.15"
+ "@firebase/app-check" "0.8.9"
+ "@firebase/app-check-compat" "0.3.16"
+ "@firebase/app-compat" "0.2.45"
+ "@firebase/app-types" "0.9.2"
+ "@firebase/auth" "1.8.0"
+ "@firebase/auth-compat" "0.5.15"
+ "@firebase/data-connect" "0.1.1"
+ "@firebase/database" "1.0.9"
+ "@firebase/database-compat" "2.0.0"
+ "@firebase/firestore" "4.7.4"
+ "@firebase/firestore-compat" "0.3.39"
+ "@firebase/functions" "0.11.9"
+ "@firebase/functions-compat" "0.3.15"
+ "@firebase/installations" "0.6.10"
+ "@firebase/installations-compat" "0.2.10"
+ "@firebase/messaging" "0.12.13"
+ "@firebase/messaging-compat" "0.2.13"
+ "@firebase/performance" "0.6.10"
+ "@firebase/performance-compat" "0.2.10"
+ "@firebase/remote-config" "0.4.10"
+ "@firebase/remote-config-compat" "0.2.10"
+ "@firebase/storage" "0.13.3"
+ "@firebase/storage-compat" "0.3.13"
+ "@firebase/util" "1.10.1"
+ "@firebase/vertexai" "1.0.0"
+
flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz"
@@ -1712,11 +2228,6 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-fsevents@~2.3.2, fsevents@~2.3.3:
- version "2.3.3"
- resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
- integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
@@ -1737,6 +2248,11 @@ functions-have-names@^1.2.3:
resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+get-caller-file@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
version "1.2.4"
resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz"
@@ -1850,11 +2366,6 @@ has-bigints@^1.0.1, has-bigints@^1.0.2:
resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz"
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
- integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
-
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
@@ -1905,6 +2416,16 @@ hoist-non-react-statics@^3.3.1:
dependencies:
react-is "^16.7.0"
+http-parser-js@>=0.5.1:
+ version "0.5.8"
+ resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz"
+ integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==
+
+idb@7.1.1:
+ version "7.1.1"
+ resolved "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz"
+ integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==
+
ignore@^5.2.0, ignore@^5.3.1:
version "5.3.2"
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
@@ -2040,6 +2561,11 @@ is-finalizationregistry@^1.0.2:
dependencies:
call-bind "^1.0.2"
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
is-generator-function@^1.0.10:
version "1.0.10"
resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz"
@@ -2175,10 +2701,10 @@ js-yaml@^4.1.0:
dependencies:
argparse "^2.0.1"
-jsesc@^2.5.1:
- version "2.5.2"
- resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz"
- integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+jsesc@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz"
+ integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
@@ -2221,6 +2747,11 @@ jsonfile@^6.0.1:
object.assign "^4.1.4"
object.values "^1.1.6"
+jwt-decode@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz"
+ integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==
+
language-subtag-registry@^0.3.20:
version "0.3.23"
resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz"
@@ -2258,6 +2789,11 @@ lodash-es@^4.17.21:
resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+lodash.camelcase@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz"
+ integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==
+
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
@@ -2268,6 +2804,11 @@ lodash@^4.17.21:
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+long@^5.0.0:
+ version "5.2.3"
+ resolved "https://registry.npmjs.org/long/-/long-5.2.3.tgz"
+ integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
+
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
@@ -2507,9 +3048,9 @@ path-type@^4.0.0:
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
picocolors@^1.0.0, picocolors@^1.0.1:
- version "1.0.1"
- resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz"
- integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
version "2.3.1"
@@ -2556,6 +3097,24 @@ prop-types@^15.6.2, prop-types@^15.8.1:
object-assign "^4.1.1"
react-is "^16.13.1"
+protobufjs@^7.2.5:
+ version "7.4.0"
+ resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz"
+ integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==
+ dependencies:
+ "@protobufjs/aspromise" "^1.1.2"
+ "@protobufjs/base64" "^1.1.2"
+ "@protobufjs/codegen" "^2.0.4"
+ "@protobufjs/eventemitter" "^1.1.0"
+ "@protobufjs/fetch" "^1.1.0"
+ "@protobufjs/float" "^1.0.2"
+ "@protobufjs/inquire" "^1.1.0"
+ "@protobufjs/path" "^1.1.2"
+ "@protobufjs/pool" "^1.1.0"
+ "@protobufjs/utf8" "^1.1.0"
+ "@types/node" ">=13.7.0"
+ long "^5.0.0"
+
punycode@^2.1.0:
version "2.3.1"
resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
@@ -2677,6 +3236,11 @@ regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.2:
es-errors "^1.3.0"
set-function-name "^2.0.1"
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz"
+ integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
@@ -2759,6 +3323,11 @@ safe-array-concat@^1.1.2:
has-symbols "^1.0.3"
isarray "^2.0.5"
+safe-buffer@>=5.1.0:
+ version "5.2.1"
+ resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
safe-regex-test@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz"
@@ -2877,6 +3446,15 @@ stop-iteration-iterator@^1.0.0:
dependencies:
internal-slot "^1.0.4"
+string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
string.prototype.includes@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz"
@@ -2961,13 +3539,6 @@ stylis@4.2.0:
resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz"
integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
-supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
@@ -3058,11 +3629,6 @@ tiny-invariant@^1.1.0:
resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz"
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
-to-fast-properties@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
- integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
-
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
@@ -3085,7 +3651,7 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
-tslib@^2.6.2:
+tslib@^2.1.0, tslib@^2.6.2:
version "2.6.3"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz"
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
@@ -3258,6 +3824,20 @@ vscode-uri@^3.0.2:
resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz"
integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==
+websocket-driver@>=0.5.1:
+ version "0.7.4"
+ resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz"
+ integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
+ dependencies:
+ http-parser-js ">=0.5.1"
+ safe-buffer ">=5.1.0"
+ websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+ version "0.1.4"
+ resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz"
+ integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz"
@@ -3315,16 +3895,48 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrappy@1:
version "1.0.2"
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+yargs-parser@^21.1.1:
+ version "21.1.1"
+ resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz"
+ integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
+
+yargs@^17.7.2:
+ version "17.7.2"
+ resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz"
+ integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
+ dependencies:
+ cliui "^8.0.1"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.3"
+ y18n "^5.0.5"
+ yargs-parser "^21.1.1"
+
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"