Compare commits
194 Commits
feature-de
...
Sprint7.1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b2efcd292 | ||
|
|
f2023cf7b3 | ||
|
|
77fc645767 | ||
|
|
9740fff33c | ||
| 0f678fefc1 | |||
|
|
986e531896 | ||
|
|
734dff43a1 | ||
| d244df302b | |||
|
|
eb14139bcf | ||
|
|
f5e7217304 | ||
|
|
30c51a5b34 | ||
| 1f89ca0a1c | |||
|
|
82215f8569 | ||
|
|
0199a46ed5 | ||
|
|
8cfccf656d | ||
|
|
2e06b52881 | ||
| f99e78a8df | |||
|
|
6f5e83a4bc | ||
|
|
fff3689aeb | ||
|
|
184f42ef59 | ||
| ccc75f50e5 | |||
| 751aa6c673 | |||
| d44b8aea0d | |||
| 5fd9fda73b | |||
| 6216367d21 | |||
| a1b9f1c507 | |||
| 5ff6d5d07b | |||
| 7f1106449f | |||
| da55f00f73 | |||
| 0c56759251 | |||
| cd1cf86fc9 | |||
| 9cd0a4e9c6 | |||
| 0b080733fb | |||
|
|
94b8be1130 | ||
|
|
3079e7f269 | ||
|
|
2147914c81 | ||
|
|
3696ec5e59 | ||
|
|
7f5d3065ca | ||
| 28990bb9d6 | |||
| 2f816f3c45 | |||
|
|
61c81b100c | ||
|
|
fd22732648 | ||
| 2df6ea41a4 | |||
|
|
739b755ec1 | ||
| 6c16d142d6 | |||
|
|
4a54d5c80e | ||
|
|
47d75371bc | ||
|
|
bc8f78d8d6 | ||
| 915242c1f3 | |||
|
|
30a9226f86 | ||
| a6dd60140a | |||
| 512e2936ad | |||
| c9edca64c8 | |||
| 054323978c | |||
|
|
a12ab874cf | ||
|
|
14b24ffa00 | ||
| e47db6c840 | |||
|
|
48e53ea176 | ||
| 36cf9fa610 | |||
| 8a6d9102cb | |||
|
|
88bea104f6 | ||
| 417164cb16 | |||
|
|
c0ce32219e | ||
|
|
aff088c7b7 | ||
| a7d3703244 | |||
| c41deb0534 | |||
| 92ebf64223 | |||
| 36a68e2169 | |||
| 46aa0c4631 | |||
|
|
bd48e3fb06 | ||
|
|
90a433e312 | ||
| 8cd6a65143 | |||
| 105f103fda | |||
| aa6c61e4a4 | |||
| b08030a412 | |||
|
|
149667436e | ||
|
|
bb724d88d1 | ||
|
|
1fabbd9b77 | ||
| c51ae9081f | |||
| cfd811708a | |||
| 6630723092 | |||
| 2ae81ef032 | |||
| 10221c03d9 | |||
| 084641c561 | |||
| 7b24db3e00 | |||
| f8b33e3eb5 | |||
| 9fa42845c7 | |||
|
|
4bded669bf | ||
| bc8d986f29 | |||
| f5497ea6ac | |||
|
|
7f1ef99b6c | ||
| 28978622f3 | |||
|
|
9dca99b1c1 | ||
|
|
8546ca3247 | ||
|
|
ae1cdc8811 | ||
|
|
1a1910c58c | ||
|
|
fdb9ccefa9 | ||
|
|
a126d6515d | ||
|
|
ab175b4c76 | ||
|
|
c9c7a7be69 | ||
|
|
da70893c2b | ||
|
|
a53069f6f6 | ||
|
|
8b43ff77a9 | ||
|
|
8cb693a4c4 | ||
|
|
7b91ad2720 | ||
|
|
416c5ce8aa | ||
| a0a1849a79 | |||
|
|
a1d7b1e9f9 | ||
| 3a327d63e0 | |||
| 753f3d40c3 | |||
|
|
226b8a39bc | ||
| fdbdc61cac | |||
| d1cc24a43b | |||
| c766b29c4b | |||
| 4ee94c1261 | |||
|
|
c2d75c340c | ||
| 8cb25e9189 | |||
| d74481e7f4 | |||
|
|
2281550345 | ||
|
|
6ca97a7ed3 | ||
| 4b3313b1ea | |||
|
|
7a8ea42832 | ||
| 1be4a00ced | |||
|
|
c5d9b32e8d | ||
|
|
4957bd5032 | ||
|
|
f151b67e49 | ||
| b92de5e990 | |||
| 33bbd5f3e6 | |||
|
|
0ab8ac73aa | ||
| 410f18f512 | |||
| 29fdb99366 | |||
|
|
867ad9e7b9 | ||
| 92fe9f66f9 | |||
| d2d18d435f | |||
| ede34c1b41 | |||
| 639a6cfae9 | |||
| 68026ddd66 | |||
|
|
be451086b9 | ||
|
|
566d170226 | ||
| 60d3c7572d | |||
|
|
dceec17c58 | ||
|
|
a041cea256 | ||
|
|
91e362d6c2 | ||
| b3c0662e77 | |||
|
|
86ce31e86c | ||
|
|
0df81c1169 | ||
| 31eb1605bf | |||
| 8dc5eecad9 | |||
|
|
508d7fe5b5 | ||
|
|
9208535613 | ||
|
|
9916d6618e | ||
| 2f7f907a89 | |||
| 8b0454b16a | |||
|
|
f7b06bfd19 | ||
|
|
64b881dd89 | ||
|
|
fba3ad2212 | ||
|
|
026a563d84 | ||
| b713845df6 | |||
| 79bcf851d9 | |||
| 3a7d174766 | |||
|
|
6d315ba2ef | ||
|
|
7748872e29 | ||
|
|
b5f7250691 | ||
| 0db739c557 | |||
| 3165c11af7 | |||
| c97de1314e | |||
| 287fb80f9e | |||
| b690a55ed3 | |||
|
|
b8390bfad9 | ||
|
|
5e4ebe3fb5 | ||
|
|
8b97add9e0 | ||
| 25226d5464 | |||
| 3131ff8610 | |||
|
|
187841b178 | ||
|
|
849b89efc8 | ||
| 116db3b922 | |||
|
|
4313057012 | ||
|
|
cdd0d670ba | ||
| 7c3a6112d2 | |||
| e3ccc3efbc | |||
|
|
129a79c669 | ||
| b7ce3de128 | |||
|
|
97cfd45545 | ||
|
|
e0664d8e21 | ||
| d009848068 | |||
|
|
afb538cc22 | ||
|
|
e0b48abfd5 | ||
| 9083d94813 | |||
| 323d09f88d | |||
| 46d8031d4d | |||
| fb39e32b95 | |||
| 670e4d36a9 | |||
|
|
26777e2ada | ||
| 51f3b512a7 |
@@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/src/assets/favicon.png" />
|
<link rel="icon" type="image/svg+xml" href="/src/assets/favicons.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Tanami Admin</title>
|
<title>Tanami Admin</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
300
package-lock.json
generated
300
package-lock.json
generated
@@ -21,6 +21,7 @@
|
|||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"framer-motion": "^11.1.5",
|
"framer-motion": "^11.1.5",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
|
"quill": "^2.0.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-apexcharts": "^1.4.1",
|
"react-apexcharts": "^1.4.1",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
@@ -28,7 +29,8 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hook-form": "^7.51.3",
|
"react-hook-form": "^7.51.3",
|
||||||
"react-icons": "^5.1.0",
|
"react-icons": "^5.1.0",
|
||||||
"react-quill": "^0.0.2",
|
"react-phone-input-2": "^2.15.1",
|
||||||
|
"react-quill": "^2.0.0",
|
||||||
"react-redux": "^9.1.1",
|
"react-redux": "^9.1.1",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
@@ -2757,6 +2759,15 @@
|
|||||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
|
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/quill": {
|
||||||
|
"version": "1.3.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
|
||||||
|
"integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"parchment": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "18.3.3",
|
"version": "18.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
|
||||||
@@ -3182,7 +3193,6 @@
|
|||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-define-property": "^1.0.0",
|
"es-define-property": "^1.0.0",
|
||||||
@@ -3255,6 +3265,20 @@
|
|||||||
"pnpm": ">=8"
|
"pnpm": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/classnames": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
|
||||||
|
},
|
||||||
|
"node_modules/clone": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/codepage": {
|
"node_modules/codepage": {
|
||||||
"version": "1.15.0",
|
"version": "1.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
||||||
@@ -3460,6 +3484,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/deep-equal": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-arguments": "^1.1.1",
|
||||||
|
"is-date-object": "^1.0.5",
|
||||||
|
"is-regex": "^1.1.4",
|
||||||
|
"object-is": "^1.1.5",
|
||||||
|
"object-keys": "^1.1.1",
|
||||||
|
"regexp.prototype.flags": "^1.5.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/deep-is": {
|
"node_modules/deep-is": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
@@ -3471,7 +3515,6 @@
|
|||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-define-property": "^1.0.0",
|
"es-define-property": "^1.0.0",
|
||||||
@@ -3489,7 +3532,6 @@
|
|||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
||||||
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"define-data-property": "^1.0.1",
|
"define-data-property": "^1.0.1",
|
||||||
@@ -3617,7 +3659,6 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"get-intrinsic": "^1.2.4"
|
"get-intrinsic": "^1.2.4"
|
||||||
@@ -3630,7 +3671,6 @@
|
|||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@@ -4111,10 +4151,16 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eventemitter2": {
|
"node_modules/eventemitter3": {
|
||||||
"version": "0.4.14",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||||
"integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==",
|
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/extend": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
@@ -4125,10 +4171,10 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fast-diff": {
|
"node_modules/fast-diff": {
|
||||||
"version": "1.0.1",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
||||||
"integrity": "sha512-anEzYJ8VOA5iAMjDOVMTVMrUOXveDTMMk5x0E4p0nJ3VPoIOolF51AqYyE+UD0QIyggUwqppqH7XVA9lF3fdaQ==",
|
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
|
||||||
"license": "Apache 2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/fast-json-stable-stringify": {
|
"node_modules/fast-json-stable-stringify": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
@@ -4371,7 +4417,6 @@
|
|||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
|
||||||
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
|
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@@ -4381,7 +4426,6 @@
|
|||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-errors": "^1.3.0",
|
"es-errors": "^1.3.0",
|
||||||
@@ -4489,7 +4533,6 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"get-intrinsic": "^1.1.3"
|
"get-intrinsic": "^1.1.3"
|
||||||
@@ -4528,7 +4571,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-define-property": "^1.0.0"
|
"es-define-property": "^1.0.0"
|
||||||
@@ -4541,7 +4583,6 @@
|
|||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
||||||
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@@ -4554,7 +4595,6 @@
|
|||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@@ -4567,7 +4607,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-symbols": "^1.0.3"
|
"has-symbols": "^1.0.3"
|
||||||
@@ -4689,6 +4728,22 @@
|
|||||||
"loose-envify": "^1.0.0"
|
"loose-envify": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-arguments": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"has-tostringtag": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-array-buffer": {
|
"node_modules/is-array-buffer": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
|
||||||
@@ -4806,7 +4861,6 @@
|
|||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
|
||||||
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
|
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-tostringtag": "^1.0.0"
|
"has-tostringtag": "^1.0.0"
|
||||||
@@ -4926,7 +4980,6 @@
|
|||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
||||||
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
|
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"call-bind": "^1.0.2",
|
"call-bind": "^1.0.2",
|
||||||
@@ -5223,15 +5276,39 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "2.4.2",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-Kak1hi6/hYHGVPmdyiZijoQyz5x2iGVzs6w9GYB/HiXEtylY7tIoYEROMjvM1d9nXJqPOrG2MNPMn01bJ+S0Rw==",
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||||
"engines": [
|
|
||||||
"node",
|
|
||||||
"rhino"
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash-es": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.clonedeep": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.debounce": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isequal": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.memoize": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
|
||||||
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
@@ -5245,6 +5322,16 @@
|
|||||||
"integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
|
"integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.reduce": {
|
||||||
|
"version": "4.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
|
||||||
|
"integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.startswith": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-XClYR1h4/fJ7H+mmCKppbiBmljN/nGs73iq2SjCT9SF4CBPoUHzLvWmH1GtZMhMBZSiRkHXfeA2RY1eIlJ75ww=="
|
||||||
|
},
|
||||||
"node_modules/loose-envify": {
|
"node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
@@ -5351,11 +5438,26 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/object-is": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.7",
|
||||||
|
"define-properties": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-keys": {
|
"node_modules/object-keys": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@@ -5492,6 +5594,12 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parchment": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -5676,20 +5784,40 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/quilljs": {
|
"node_modules/quill": {
|
||||||
"version": "0.18.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/quilljs/-/quilljs-0.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/quill/-/quill-2.0.2.tgz",
|
||||||
"integrity": "sha512-VKaO7GNehgnH4LlFPx5ZAl+KFDoRVtboY0I6UUbYXUsPHP8kR80Tg/CFEYqrqrpCOGQr4OQ5Tjm813gV1DUyQw==",
|
"integrity": "sha512-QfazNrhMakEdRG57IoYFwffUIr04LWJxbS/ZkidRFXYCQt63c1gK6Z7IHUXMx/Vh25WgPBU42oBaNzQ0K1R/xw==",
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eventemitter2": "~0.4.13",
|
"eventemitter3": "^5.0.1",
|
||||||
"lodash": "~2.4.1",
|
"lodash-es": "^4.17.21",
|
||||||
"rich-text": "~1.0.2"
|
"parchment": "^3.0.0",
|
||||||
|
"quill-delta": "^5.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10"
|
"npm": ">=8.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/quill-delta": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-diff": "^1.3.0",
|
||||||
|
"lodash.clonedeep": "^4.5.0",
|
||||||
|
"lodash.isequal": "^4.5.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/quill/node_modules/parchment": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/raf-schd": {
|
"node_modules/raf-schd": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
|
||||||
@@ -5875,19 +6003,76 @@
|
|||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-quill": {
|
"node_modules/react-phone-input-2": {
|
||||||
"version": "0.0.2",
|
"version": "2.15.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-0.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-phone-input-2/-/react-phone-input-2-2.15.1.tgz",
|
||||||
"integrity": "sha512-PeiHXZ63Sumh41OdovBQExXJH7B4UsJpyCW8CtRvXrNBa2RJXdciaJvTeb0x6pYQfqkoCYPT5EbUvEr0Z1tohg==",
|
"integrity": "sha512-W03abwhXcwUoq+vUFvC6ch2+LJYMN8qSOiO889UH6S7SyMCQvox/LF3QWt+cZagZrRdi5z2ON3omnjoCUmlaYw==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"quilljs": "^0.18.1"
|
"classnames": "^2.2.6",
|
||||||
},
|
"lodash.debounce": "^4.0.8",
|
||||||
"engines": {
|
"lodash.memoize": "^4.1.2",
|
||||||
"node": ">= 0.8.x"
|
"lodash.reduce": "^4.6.0",
|
||||||
|
"lodash.startswith": "^4.2.1",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=0.11.0"
|
"react": "^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
|
||||||
|
"react-dom": "^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-quill": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/quill": "^1.3.10",
|
||||||
|
"lodash": "^4.17.4",
|
||||||
|
"quill": "^1.3.7"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16 || ^17 || ^18",
|
||||||
|
"react-dom": "^16 || ^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-quill/node_modules/eventemitter3": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/react-quill/node_modules/fast-diff": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/react-quill/node_modules/quill": {
|
||||||
|
"version": "1.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
|
||||||
|
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"clone": "^2.1.1",
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"eventemitter3": "^2.0.3",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"parchment": "^1.1.4",
|
||||||
|
"quill-delta": "^3.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-quill/node_modules/quill-delta": {
|
||||||
|
"version": "3.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
|
||||||
|
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"fast-diff": "1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-redux": {
|
"node_modules/react-redux": {
|
||||||
@@ -6085,7 +6270,6 @@
|
|||||||
"version": "1.5.2",
|
"version": "1.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
|
||||||
"integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
|
"integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"call-bind": "^1.0.6",
|
"call-bind": "^1.0.6",
|
||||||
@@ -6143,18 +6327,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rich-text": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/rich-text/-/rich-text-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-L+Mi0fBH4/TBGH68XZqUXdUr5Ze+ViYkrKuwEvCpeyB1Blbp4CLO4LyYleutTNybujCMQfcmivaNrE3YLrEUgg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fast-diff": "~1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/rimraf": {
|
"node_modules/rimraf": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
@@ -6292,7 +6464,6 @@
|
|||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"define-data-property": "^1.1.4",
|
"define-data-property": "^1.1.4",
|
||||||
@@ -6310,7 +6481,6 @@
|
|||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
|
||||||
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
|
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"define-data-property": "^1.1.4",
|
"define-data-property": "^1.1.4",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"framer-motion": "^11.1.5",
|
"framer-motion": "^11.1.5",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
|
"quill": "^2.0.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-apexcharts": "^1.4.1",
|
"react-apexcharts": "^1.4.1",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
@@ -30,7 +31,8 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hook-form": "^7.51.3",
|
"react-hook-form": "^7.51.3",
|
||||||
"react-icons": "^5.1.0",
|
"react-icons": "^5.1.0",
|
||||||
"react-quill": "^0.0.2",
|
"react-phone-input-2": "^2.15.1",
|
||||||
|
"react-quill": "^2.0.0",
|
||||||
"react-redux": "^9.1.1",
|
"react-redux": "^9.1.1",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
Routes,
|
Routes,
|
||||||
Route,
|
Route,
|
||||||
Navigate,
|
Navigate,
|
||||||
|
useNavigate,
|
||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
import "./App.css"; // Import CSS file
|
import "./App.css"; // Import CSS file
|
||||||
import DefaultLayout from "./Layout/DefaultLayout";
|
import DefaultLayout from "./Layout/DefaultLayout";
|
||||||
@@ -14,6 +15,8 @@ import Login from "./Pages/Login";
|
|||||||
import GlobalStateContext from "./Contexts/GlobalStateContext";
|
import GlobalStateContext from "./Contexts/GlobalStateContext";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import NoInternetScreen from "./Pages/NoInternetScreen";
|
import NoInternetScreen from "./Pages/NoInternetScreen";
|
||||||
|
import Welcome from "./Pages/PaymentSuccess";
|
||||||
|
import PaymentFailed from "./Pages/PaymentFailed";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
// const { isAuthenticate } = useSelector((state) => state?.auth);
|
// const { isAuthenticate } = useSelector((state) => state?.auth);
|
||||||
@@ -24,6 +27,8 @@ const App = () => {
|
|||||||
const [isOnline, setIsOnline] = useState(navigator.onLine);
|
const [isOnline, setIsOnline] = useState(navigator.onLine);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
|
||||||
const handleOnlineStatusChange = () => {
|
const handleOnlineStatusChange = () => {
|
||||||
setIsOnline(navigator.onLine);
|
setIsOnline(navigator.onLine);
|
||||||
};
|
};
|
||||||
@@ -52,12 +57,15 @@ const App = () => {
|
|||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/login" element={<Login />} />
|
<Route path="/login" element={<Login />} />
|
||||||
|
<Route path="/payment-success" element={<Welcome />} />
|
||||||
|
<Route path="/payment-failed" element={<PaymentFailed />} />
|
||||||
<Route
|
<Route
|
||||||
path="/*"
|
path="/*"
|
||||||
element={
|
element={
|
||||||
// isOnline ? (
|
// isOnline ? (
|
||||||
// isAuthenticate || isAuthenticatedInCookie === "true" ? (
|
// isAuthenticate || isAuthenticatedInCookie === "true" ? (
|
||||||
localStorage.getItem('accessToken') && localStorage.getItem('refreshToken') ? (
|
localStorage.getItem('accessToken') && localStorage.getItem('refreshToken') ? (
|
||||||
|
// true ? (
|
||||||
<DefaultLayout isOnline={isOnline} />
|
<DefaultLayout isOnline={isOnline} />
|
||||||
) : (
|
) : (
|
||||||
<Login />
|
<Login />
|
||||||
|
|||||||
@@ -1,36 +1,32 @@
|
|||||||
import React, { forwardRef } from 'react';
|
import React, { forwardRef } from 'react';
|
||||||
import { Input } from "@chakra-ui/react";
|
import { Input } from "@chakra-ui/react";
|
||||||
|
|
||||||
// export const formatCurrency = (value) => {
|
|
||||||
// if (!value) return '';
|
|
||||||
// const [integer, decimal] = value.split('.');
|
|
||||||
// const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
||||||
// return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
|
|
||||||
// };
|
|
||||||
|
|
||||||
export const formatCurrency = (value) => {
|
export const formatCurrency = (value) => {
|
||||||
if (value === undefined || value === null) return ''; // Handle undefined or null values
|
if (value === undefined || value === null) return '';
|
||||||
const [integer, decimal] = String(value).split('.'); // Convert value to string before splitting
|
const [integer, decimal] = String(value).split('.');
|
||||||
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||||
return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
|
return decimal !== undefined ? `${formattedInteger}.${decimal}` : formattedInteger;
|
||||||
};
|
};
|
||||||
const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
|
const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
let { value } = event?.target;
|
let { value } = event?.target;
|
||||||
|
|
||||||
// Remove non-numeric characters except decimal point
|
// Remove non-numeric characters except decimal point
|
||||||
value = value?.replace(/[^0-9.]/g, '');
|
value = value.replace(/[^0-9.]/g, '');
|
||||||
|
|
||||||
// Ensure only one decimal point
|
// Ensure only one decimal point
|
||||||
const parts = value?.split('.');
|
const parts = value.split('.');
|
||||||
if (parts.length > 2) {
|
if (parts.length > 2) {
|
||||||
value = parts[0] + '.' + parts?.slice(1)?.join('');
|
value = parts[0] + '.' + parts.slice(1).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(value); // Pass the raw value to parent or use it directly
|
// Restrict to two decimal places
|
||||||
|
if (parts[1]?.length > 2) {
|
||||||
|
value = parts[0] + '.' + parts[1].slice(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(value); // Pass the raw value to parent
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -38,6 +34,7 @@ const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
|
|||||||
{...props}
|
{...props}
|
||||||
ref={ref} // Forward ref here
|
ref={ref} // Forward ref here
|
||||||
type="text"
|
type="text"
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
value={formatCurrency(value)}
|
value={formatCurrency(value)}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
@@ -45,3 +42,50 @@ const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default CurrencyInput;
|
export default CurrencyInput;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// import React, { forwardRef } from 'react';
|
||||||
|
// import { Input } from "@chakra-ui/react";
|
||||||
|
|
||||||
|
// export const formatCurrency = (value) => {
|
||||||
|
// if (value === undefined || value === null) return ''; // Handle undefined or null values
|
||||||
|
// const [integer, decimal] = String(value).split('.'); // Convert value to string before splitting
|
||||||
|
// const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||||
|
// return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
|
||||||
|
|
||||||
|
// const handleChange = (event) => {
|
||||||
|
// let { value } = event?.target;
|
||||||
|
|
||||||
|
// // Remove non-numeric characters except decimal point
|
||||||
|
// value = value?.replace(/[^0-9.]/g, '');
|
||||||
|
|
||||||
|
// // Ensure only one decimal point and restrict to two decimal places
|
||||||
|
// const parts = value?.split('.');
|
||||||
|
// if (parts.length > 2) {
|
||||||
|
// value = parts[0] + '.' + parts?.slice(1)?.join('');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (parts[1]?.length > 2) {
|
||||||
|
// value = parts[0] + '.' + parts[1]?.slice(0, 2);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// onChange(value); // Pass the raw value to parent or use it directly
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <Input
|
||||||
|
// {...props}
|
||||||
|
// ref={ref} // Forward ref here
|
||||||
|
// type="text"
|
||||||
|
// value={formatCurrency(value)}
|
||||||
|
// onChange={handleChange}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
|
// export default CurrencyInput;
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const DataTable = ({
|
|||||||
{/* <Box mb={2}>{caption}</Box> */}
|
{/* <Box mb={2}>{caption}</Box> */}
|
||||||
<Table size="sm" {...provided.droppableProps} ref={provided.innerRef}>
|
<Table size="sm" {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
<TableCaption p={0}>{caption}</TableCaption>
|
<TableCaption p={0}>{caption}</TableCaption>
|
||||||
<Thead backgroundColor="gray.50">
|
<Thead backgroundColor="forestGreen.100">
|
||||||
<Tr>
|
<Tr>
|
||||||
{tableHeadRow.map((heading, index) => (
|
{tableHeadRow.map((heading, index) => (
|
||||||
<Th
|
<Th
|
||||||
@@ -97,7 +97,7 @@ const DataTable = ({
|
|||||||
bg: "blue.50",
|
bg: "blue.50",
|
||||||
cursor: "grab",
|
cursor: "grab",
|
||||||
}}
|
}}
|
||||||
bg={snapshot.isDragging ? "blue.100" : "white"}
|
bg={snapshot.isDragging ? "blue.100" : index % 2 ? "white" : "forestGreen.50"}
|
||||||
boxShadow={snapshot.isDragging ? "0 0 1em rgba(0, 0, 0, 0.2)" : "none"}
|
boxShadow={snapshot.isDragging ? "0 0 1em rgba(0, 0, 0, 0.2)" : "none"}
|
||||||
|
|
||||||
>
|
>
|
||||||
@@ -121,7 +121,7 @@ const DataTable = ({
|
|||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
) : (
|
) : (
|
||||||
<Tr key={index}>
|
<Tr bg={index % 2 ? "forestGreen.50" : "white"} key={index}>
|
||||||
{tableHeadRow.map((heading, i) => (
|
{tableHeadRow.map((heading, i) => (
|
||||||
<Td
|
<Td
|
||||||
textAlign={tableHeadRow.length - 1 === i || centered ? "center" : "left"}
|
textAlign={tableHeadRow.length - 1 === i || centered ? "center" : "left"}
|
||||||
|
|||||||
@@ -9,79 +9,171 @@ import {
|
|||||||
Tr,
|
Tr,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
TableCaption,
|
TableCaption,
|
||||||
Tfoot,
|
Checkbox,
|
||||||
|
Radio,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import EmptySearchList from "../EmptySearchList";
|
import EmptySearchList from "../EmptySearchList";
|
||||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||||
|
|
||||||
const DataTable = ({
|
const NormalTable = ({
|
||||||
data,
|
data,
|
||||||
isLoading,
|
isLoading,
|
||||||
tableHeadRow,
|
tableHeadRow,
|
||||||
emptyMessage,
|
emptyMessage,
|
||||||
centered,
|
centered,
|
||||||
|
total,
|
||||||
|
showRadioButton, // Prop for showing the checkboxes
|
||||||
|
selectedRadio,
|
||||||
|
setSelectedRadio, // State for managing selected checkboxes
|
||||||
|
|
||||||
|
handleCheckboxChange: radioChange,
|
||||||
|
radio
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
const columnWidth =
|
const columnWidth =
|
||||||
data && data[0]
|
data && data[0]
|
||||||
? `${(100 / Object.keys(data[0]).length).toFixed(2)}%`
|
? `${(100 / Object.keys(data[0]).length).toFixed(2)}%`
|
||||||
: "auto";
|
: "auto";
|
||||||
|
|
||||||
|
// Toggle checkbox selection for individual rows
|
||||||
|
// const handleCheckboxChange = (value) => {
|
||||||
|
// setSelectedRadio((prev) => {
|
||||||
|
// if (prev.includes(value)) {
|
||||||
|
// // Remove if already selected
|
||||||
|
// return prev.filter((id) => id !== value);
|
||||||
|
// } else {
|
||||||
|
// // Add to selected
|
||||||
|
// return [...prev, value];
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Handle "Check All" checkbox
|
||||||
|
const handleCheckAllChange = () => {
|
||||||
|
if (selectedRadio.length === data.length) {
|
||||||
|
setSelectedRadio([]); // Deselect all if already selected
|
||||||
|
} else {
|
||||||
|
const allIds = data.map((item) => item.id);
|
||||||
|
setSelectedRadio(allIds); // Select all
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleCheckboxChange = (value) => {
|
||||||
|
if (radio) {
|
||||||
|
// If radio is true, select only one option
|
||||||
|
setSelectedRadio([value]); // Set the selected radio to this value only
|
||||||
|
} else {
|
||||||
|
// Handle multiple selection for checkboxes
|
||||||
|
setSelectedRadio((prev) => {
|
||||||
|
if (prev.includes(value)) {
|
||||||
|
// Remove if already selected
|
||||||
|
return prev.filter((id) => id !== value);
|
||||||
|
} else {
|
||||||
|
// Add to selected
|
||||||
|
return [...prev, value];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableContainer overflowX={"hidden"} className="h-auto mb-3 w-100">
|
<TableContainer overflowX={"auto"} className="h-auto w-100 table-scroll">
|
||||||
{data?.length === 0 ? (
|
{data?.length === 0 ? (
|
||||||
<EmptySearchList message={emptyMessage} />
|
<EmptySearchList message={emptyMessage} />
|
||||||
) : (
|
) : (
|
||||||
<Table size="sm">
|
<Table size="sm">
|
||||||
<TableCaption>Tanami v1.0.0</TableCaption>
|
<TableCaption p={total ? 0 : null}>
|
||||||
<Thead backgroundColor="gray.50">
|
{total ? total : "Tanami v1.0.0"}
|
||||||
|
</TableCaption>
|
||||||
|
<Thead bg="forestGreen.100">
|
||||||
<Tr>
|
<Tr>
|
||||||
|
{showRadioButton &&(
|
||||||
|
<Th
|
||||||
|
color={"purple.900"}
|
||||||
|
textAlign={"center"}
|
||||||
|
p={4}
|
||||||
|
whiteSpace="normal"
|
||||||
|
wordBreak="normal"
|
||||||
|
overflowWrap="normal"
|
||||||
|
textTransform={"none"}
|
||||||
|
>
|
||||||
|
{radio? "Select":<Checkbox
|
||||||
|
isChecked={selectedRadio?.length === data?.length}
|
||||||
|
onChange={handleCheckAllChange}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
|
||||||
|
/>}
|
||||||
|
</Th>
|
||||||
|
)}
|
||||||
{tableHeadRow.map((heading, index) => (
|
{tableHeadRow.map((heading, index) => (
|
||||||
<Th
|
<Th
|
||||||
|
color={"purple.900"}
|
||||||
textAlign={
|
textAlign={
|
||||||
tableHeadRow.length - 1 === index || centered
|
tableHeadRow.length - 1 === index || centered
|
||||||
? "center"
|
? "center"
|
||||||
: "left"
|
: "left"
|
||||||
}
|
}
|
||||||
key={index}
|
key={index}
|
||||||
p={3}
|
p={4}
|
||||||
width="20px" // Adjust width as needed
|
whiteSpace="normal"
|
||||||
color={"#004118"}
|
wordBreak="normal"
|
||||||
whiteSpace="normal" // Allow text to wrap
|
overflowWrap="normal"
|
||||||
wordBreak="normal" // Ensure long words break properly
|
textTransform={"none"}
|
||||||
overflowWrap="normal" // Break long words if necessary
|
|
||||||
textTransform={'none'}
|
|
||||||
|
|
||||||
>
|
>
|
||||||
{isLoading ? <Skeleton height="20px" /> : heading}
|
{isLoading ? <Skeleton height="20px" /> : heading}
|
||||||
{/* {heading} */}
|
|
||||||
</Th>
|
</Th>
|
||||||
))}
|
))}
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody className="web-text-small">
|
<Tbody className="web-text-small">
|
||||||
{isLoading
|
{isLoading
|
||||||
? Array.from({ length: TABLE_PAGINATION?.size }).map((_, index) => (
|
? Array.from({ length: TABLE_PAGINATION?.size }).map(
|
||||||
<Tr key={index}>
|
(_, index) => (
|
||||||
|
<Tr
|
||||||
|
bg={index % 2 === 0 ? "white" : "forestGreen.50"}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
{tableHeadRow.map((_, i) => (
|
{tableHeadRow.map((_, i) => (
|
||||||
<Td
|
<Td
|
||||||
width={'fit-content'}
|
|
||||||
key={i}
|
key={i}
|
||||||
style={{
|
style={{
|
||||||
whiteSpace: "nowrap",
|
whiteSpace: "nowrap",
|
||||||
textOverflow: "ellipsis",
|
textOverflow: "ellipsis",
|
||||||
}}
|
}}
|
||||||
className="web-text-small"
|
className="web-text-small"
|
||||||
w={columnWidth}
|
|
||||||
>
|
>
|
||||||
<Skeleton height="20px" mb={1} mt={1} />
|
<Skeleton height="20px" mb={1} mt={1} />
|
||||||
</Td>
|
</Td>
|
||||||
))}
|
))}
|
||||||
</Tr>
|
</Tr>
|
||||||
))
|
)
|
||||||
|
)
|
||||||
: data?.map((item, index) => (
|
: data?.map((item, index) => (
|
||||||
<Tr key={index}>
|
<Tr
|
||||||
|
cursor={"pointer"}
|
||||||
|
transition={"0.2s all"}
|
||||||
|
maxH={8}
|
||||||
|
bg={index % 2 === 0 ? "" : "forestGreen.50"}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
{showRadioButton && (
|
||||||
|
<Td textAlign={"center"}>
|
||||||
|
{radio ? <Radio
|
||||||
|
bg={"#fff"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
value={item.id}
|
||||||
|
isChecked={selectedRadio.includes(item.id)}
|
||||||
|
onChange={() => radioChange(item.id, item)}
|
||||||
|
/>:<Checkbox
|
||||||
|
bg={"#fff"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
value={item.id}
|
||||||
|
isChecked={selectedRadio.includes(item.id)}
|
||||||
|
onChange={() => handleCheckboxChange(item.id)}
|
||||||
|
/>}
|
||||||
|
</Td>
|
||||||
|
)}
|
||||||
{tableHeadRow.map((heading, i) => (
|
{tableHeadRow.map((heading, i) => (
|
||||||
<Td
|
<Td
|
||||||
textAlign={
|
textAlign={
|
||||||
@@ -91,6 +183,7 @@ const DataTable = ({
|
|||||||
}
|
}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
key={i}
|
key={i}
|
||||||
|
fontWeight={500}
|
||||||
style={{
|
style={{
|
||||||
whiteSpace: "nowrap",
|
whiteSpace: "nowrap",
|
||||||
textOverflow: "ellipsis",
|
textOverflow: "ellipsis",
|
||||||
@@ -109,4 +202,4 @@ const DataTable = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DataTable;
|
export default NormalTable;
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ import {
|
|||||||
Td,
|
Td,
|
||||||
InputGroup,
|
InputGroup,
|
||||||
InputRightAddon,
|
InputRightAddon,
|
||||||
|
HStack,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { Controller } from "react-hook-form";
|
import { Controller } from "react-hook-form";
|
||||||
import { TiWarning } from "react-icons/ti";
|
import { TiWarning } from "react-icons/ti";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { AddIcon, CloseIcon } from "@chakra-ui/icons";
|
import { AddIcon, CloseIcon } from "@chakra-ui/icons";
|
||||||
import CurrencyInput from "./CurrencyInput";
|
import CurrencyInput from "./CurrencyInput";
|
||||||
|
import ShariahLogo from "../../src/assets/shariah-icon.png"
|
||||||
|
|
||||||
const today = new Date().toISOString().split("T")[0];
|
const today = new Date().toISOString().split("T")[0];
|
||||||
|
|
||||||
@@ -69,12 +71,13 @@ const FormField = ({
|
|||||||
align,
|
align,
|
||||||
maxLength,
|
maxLength,
|
||||||
dateValue,
|
dateValue,
|
||||||
|
closingDate,
|
||||||
...props
|
...props
|
||||||
}) => (
|
}) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
w={width ? width : "49%"}
|
w={width ? width : "49%"}
|
||||||
isInvalid={errors[name]}
|
isInvalid={errors[name]}
|
||||||
isRequired={type === "date" ? false: isRequired}
|
isRequired={type === "date" ? true: isRequired}
|
||||||
mb={2}
|
mb={2}
|
||||||
>
|
>
|
||||||
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||||
@@ -84,6 +87,7 @@ const FormField = ({
|
|||||||
control={control}
|
control={control}
|
||||||
name={name}
|
name={name}
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
|
|
||||||
rules={rules}
|
rules={rules}
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
if (type === "select") {
|
if (type === "select") {
|
||||||
@@ -404,8 +408,7 @@ const FormField = ({
|
|||||||
w={6}
|
w={6}
|
||||||
h={6}
|
h={6}
|
||||||
src={
|
src={
|
||||||
import.meta.env.VITE_IMAGE_URL +
|
import.meta.env.VITE_IMAGE_URL+item?.logo
|
||||||
item?.logo
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{item.country === "United Arab Emirates"
|
{item.country === "United Arab Emirates"
|
||||||
@@ -477,12 +480,12 @@ const FormField = ({
|
|||||||
placeholder={placeHolder ? placeHolder : label}
|
placeholder={placeHolder ? placeHolder : label}
|
||||||
textAlign={arabic ? "right" : align ? align : "left"}
|
textAlign={arabic ? "right" : align ? align : "left"}
|
||||||
_placeholder={{ fontSize: "sm" }}
|
_placeholder={{ fontSize: "sm" }}
|
||||||
min={type === "date" ? today : undefined}
|
// min={type === "date" ? today : undefined}
|
||||||
maxLength={maxLength}
|
// maxLength={maxLength}
|
||||||
// defaultValue={type === "date" && "2023-07-26" : undefined}
|
// defaultValue={type === "date" && "2023-07-26" : undefined}
|
||||||
// defaultValue={value}
|
// defaultValue={value}
|
||||||
// value={dateValue}
|
// value={dateValue}
|
||||||
|
min={closingDate ? new Date().toISOString().split("T")[0] : undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -506,6 +509,20 @@ const FormField = ({
|
|||||||
// value={dateValue}
|
// value={dateValue}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
);}
|
||||||
|
else if(type === 'checkBox'){
|
||||||
|
return (
|
||||||
|
<HStack bg={"#F5F8F6"} p={"3px"} rounded={"2px"} border={'1px solid #E1E7EF'} justifyContent={"space-between"} mt={3}>
|
||||||
|
{/* <Image w={"38px"} aspectRatio={"1/1"} src={ShariahLogo} /> */}
|
||||||
|
<Checkbox
|
||||||
|
// isChecked={value}
|
||||||
|
isChecked={field.value}
|
||||||
|
ps={1}
|
||||||
|
{...field}
|
||||||
|
{...props} size='md' colorScheme='forestGreen'>
|
||||||
|
<Text as={"span"} fontSize={"sm"}>Is This Sharia Compliant</Text>
|
||||||
|
</Checkbox>
|
||||||
|
</HStack>
|
||||||
);} else{
|
);} else{
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ const FormInputMain = ({
|
|||||||
handleInputChange,
|
handleInputChange,
|
||||||
align,
|
align,
|
||||||
maxLength,
|
maxLength,
|
||||||
dateValue
|
dateValue,
|
||||||
|
closingDate
|
||||||
},
|
},
|
||||||
key
|
key
|
||||||
) => (
|
) => (
|
||||||
@@ -89,6 +90,7 @@ const FormInputMain = ({
|
|||||||
align={align}
|
align={align}
|
||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
dateValue={dateValue}
|
dateValue={dateValue}
|
||||||
|
closingDate={closingDate}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
Th,
|
Th,
|
||||||
Thead,
|
Thead,
|
||||||
Tr,
|
Tr,
|
||||||
|
Checkbox, // Import Checkbox from Chakra UI
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
@@ -34,8 +35,13 @@ const FormInputView = ({
|
|||||||
<Heading as="h6" size="xs" mt={index === 0 ? 3 : 4}>
|
<Heading as="h6" size="xs" mt={index === 0 ? 3 : 4}>
|
||||||
{section}
|
{section}
|
||||||
</Heading>
|
</Heading>
|
||||||
{/* <Box display={"flex"} gap={0}> */}
|
<Box
|
||||||
<Box key={index} width={"100%"} display={"flex"} flexWrap={"wrap"} gap={4}>
|
key={index}
|
||||||
|
width={"100%"}
|
||||||
|
display={"flex"}
|
||||||
|
flexWrap={"wrap"}
|
||||||
|
gap={4}
|
||||||
|
>
|
||||||
{fields.map(
|
{fields.map(
|
||||||
({ value, label, id, width, btn, arabic, type, align }, key) =>
|
({ value, label, id, width, btn, arabic, type, align }, key) =>
|
||||||
type === "table" ? (
|
type === "table" ? (
|
||||||
@@ -62,8 +68,7 @@ const FormInputView = ({
|
|||||||
w={6}
|
w={6}
|
||||||
h={6}
|
h={6}
|
||||||
src={
|
src={
|
||||||
" https://tanami.betadelivery.com/" +
|
import.meta.env.VITE_IMAGE_URL + item?.logo
|
||||||
item?.logo
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{item.country === "United Arab Emirates"
|
{item.country === "United Arab Emirates"
|
||||||
@@ -94,7 +99,6 @@ const FormInputView = ({
|
|||||||
isRequired={true}
|
isRequired={true}
|
||||||
bg={"#F5F8F6"}
|
bg={"#F5F8F6"}
|
||||||
focusBorderColor="forestGreen.300"
|
focusBorderColor="forestGreen.300"
|
||||||
// border="1px solid #000"
|
|
||||||
size={"sm"}
|
size={"sm"}
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
@@ -102,7 +106,6 @@ const FormInputView = ({
|
|||||||
value={item.value}
|
value={item.value}
|
||||||
textAlign={"right"}
|
textAlign={"right"}
|
||||||
placeholder={"00.00"}
|
placeholder={"00.00"}
|
||||||
// color={"#000"}
|
|
||||||
color={"#1A202C"}
|
color={"#1A202C"}
|
||||||
fontWeight={500}
|
fontWeight={500}
|
||||||
border={"1px solid #e2e8f0"}
|
border={"1px solid #e2e8f0"}
|
||||||
@@ -120,7 +123,30 @@ const FormInputView = ({
|
|||||||
</Tr>
|
</Tr>
|
||||||
</Tbody>
|
</Tbody>
|
||||||
</Table>
|
</Table>
|
||||||
|
) : type === "checkBox" ? (
|
||||||
|
// <Box key={id} w={!width ? "49%" : width}>
|
||||||
|
|
||||||
|
<InputGroup
|
||||||
|
display={"flex"}
|
||||||
|
flexDirection={"column"}
|
||||||
|
width={"32%"}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<FormLabel key={id} color={"gray.500"} fontSize={"xs"}>
|
||||||
|
{label}
|
||||||
|
</FormLabel>
|
||||||
|
<Checkbox
|
||||||
|
isChecked={value}
|
||||||
|
colorScheme="green"
|
||||||
|
size="md"
|
||||||
|
fontSize="sm"
|
||||||
|
fontWeight="medium"
|
||||||
|
>
|
||||||
|
Is this shariah compliant
|
||||||
|
</Checkbox>
|
||||||
|
</InputGroup>
|
||||||
) : (
|
) : (
|
||||||
|
// </Box>
|
||||||
<Box key={id} w={!width ? "49%" : width}>
|
<Box key={id} w={!width ? "49%" : width}>
|
||||||
<FormLabel key={id} color={"gray.500"} fontSize={"xs"}>
|
<FormLabel key={id} color={"gray.500"} fontSize={"xs"}>
|
||||||
{label}
|
{label}
|
||||||
@@ -141,7 +167,6 @@ const FormInputView = ({
|
|||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
{/* </Box> */}
|
|
||||||
{index <
|
{index <
|
||||||
Object.entries(groupedFields, groupedFieldsTwo).length - 1 && (
|
Object.entries(groupedFields, groupedFieldsTwo).length - 1 && (
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import * as XLSX from "xlsx";
|
|||||||
import profile from "../assets/proavatar.webp";
|
import profile from "../assets/proavatar.webp";
|
||||||
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||||
import { MdOutlineDarkMode, MdOutlineLightMode } from "react-icons/md";
|
import { MdOutlineDarkMode, MdOutlineLightMode } from "react-icons/md";
|
||||||
import logoMini from "../assets/propic.png"
|
import logoMini from "../assets/propic.png";
|
||||||
import { BsBack } from "react-icons/bs";
|
import { BsBack } from "react-icons/bs";
|
||||||
|
|
||||||
const HeaderMain = ({
|
const HeaderMain = ({
|
||||||
@@ -31,11 +31,11 @@ const HeaderMain = ({
|
|||||||
icon,
|
icon,
|
||||||
logOutHandler,
|
logOutHandler,
|
||||||
slideDirecttion,
|
slideDirecttion,
|
||||||
|
data,
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate();
|
||||||
const { colorMode, toggleColorMode } = useContext(GlobalStateContext);
|
const { colorMode, toggleColorMode } = useContext(GlobalStateContext);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
className={` pt-2 pb-2 fw-400 border-bottom d-flex ${
|
className={` pt-2 pb-2 fw-400 border-bottom d-flex ${
|
||||||
@@ -58,13 +58,12 @@ const HeaderMain = ({
|
|||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
|
|
||||||
<Box me={4} gap={2} className="d-flex justify-content-center ">
|
<Box me={4} gap={2} className="d-flex justify-content-center ">
|
||||||
<Popover placement="bottom">
|
<Popover placement="bottom">
|
||||||
<Portal>
|
<Portal>
|
||||||
<PopoverContent maxW="200px" className="">
|
<PopoverContent maxW="200px" className="">
|
||||||
<PopoverArrow />
|
<PopoverArrow />
|
||||||
<PopoverBody className="web-text-medium pointer link">
|
<PopoverBody onClick={()=> navigate('/profile')} className="web-text-medium pointer link">
|
||||||
Profile
|
Profile
|
||||||
</PopoverBody>
|
</PopoverBody>
|
||||||
<Link to={"/help-and-support"}>
|
<Link to={"/help-and-support"}>
|
||||||
@@ -90,7 +89,7 @@ const HeaderMain = ({
|
|||||||
boxSize={37}
|
boxSize={37}
|
||||||
name="Tanami M"
|
name="Tanami M"
|
||||||
src={logoMini}
|
src={logoMini}
|
||||||
bg={'green.100'}
|
bg={"green.100"}
|
||||||
// p={1}
|
// p={1}
|
||||||
/>
|
/>
|
||||||
<Box
|
<Box
|
||||||
@@ -100,10 +99,10 @@ const HeaderMain = ({
|
|||||||
className=" overflow-hidden ms-3 flex-column "
|
className=" overflow-hidden ms-3 flex-column "
|
||||||
>
|
>
|
||||||
<Text as={"span"} className="web-text-small">
|
<Text as={"span"} className="web-text-small">
|
||||||
Hello, Tanami admin
|
Hello, {data?.data?.firstName} {data?.data?.lastName}
|
||||||
</Text>
|
</Text>
|
||||||
<Text as={"span"} className="web-text-xsmall">
|
<Text as={"span"} className="web-text-xsmall">
|
||||||
admin@tanami.com
|
{data?.data?.emailAddress}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { BiWifi } from "react-icons/bi";
|
|||||||
import { useGetIOByIdQuery } from "../Services/io.service";
|
import { useGetIOByIdQuery } from "../Services/io.service";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import FullscreenLoaders from "./Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "./Loaders/FullscreenLoaders";
|
||||||
import { formatDate } from "../Constants/Constants";
|
import { calculatePercentage, formatDate } from "../Constants/Constants";
|
||||||
import { BsFileText } from "react-icons/bs";
|
import { BsFileText } from "react-icons/bs";
|
||||||
|
|
||||||
const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
||||||
@@ -63,6 +63,13 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
calculatePercentage(
|
||||||
|
IObyID?.data?.totalAmtInvestmentInUSD,
|
||||||
|
IObyID?.data?.goalAmount
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
@@ -122,11 +129,7 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
alignItems={"center"}
|
alignItems={"center"}
|
||||||
h={"100%"}
|
h={"100%"}
|
||||||
>
|
>
|
||||||
<Spinner
|
<Spinner thickness="3px" color="purple.900" size="lg" />
|
||||||
thickness='3px'
|
|
||||||
color='purple.900'
|
|
||||||
size='lg'
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -225,7 +228,7 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
h={"130px"}
|
h={"130px"}
|
||||||
w={"100%"}
|
w={"100%"}
|
||||||
src={
|
src={
|
||||||
"https://tanami.betadelivery.com/" +
|
import.meta.env.VITE_IMAGE_URL+
|
||||||
artifactsImage[0]?.artifactPathName
|
artifactsImage[0]?.artifactPathName
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -246,7 +249,10 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
<Progress
|
<Progress
|
||||||
colorScheme="green"
|
colorScheme="green"
|
||||||
size="sm"
|
size="sm"
|
||||||
value={20}
|
value={calculatePercentage(
|
||||||
|
IObyID?.data?.totalAmtInvestmentInUSD,
|
||||||
|
IObyID?.data?.goalAmount
|
||||||
|
)}
|
||||||
borderRadius={"3px"}
|
borderRadius={"3px"}
|
||||||
/>
|
/>
|
||||||
<Text
|
<Text
|
||||||
@@ -255,7 +261,16 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
fontWeight={600}
|
fontWeight={600}
|
||||||
mb={0}
|
mb={0}
|
||||||
>
|
>
|
||||||
0.0% funded
|
{parseFloat(
|
||||||
|
calculatePercentage(
|
||||||
|
IObyID?.data?.totalAmtInvestmentInUSD,
|
||||||
|
IObyID?.data?.goalAmount
|
||||||
|
) || 0
|
||||||
|
).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
% funded
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
@@ -334,8 +349,10 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
<Heading fontSize="14px" fontWeight={600}>
|
<Heading fontSize="14px" fontWeight={600}>
|
||||||
Key Merits
|
Key Merits
|
||||||
</Heading>
|
</Heading>
|
||||||
|
<Box>
|
||||||
|
{keyMerits &&
|
||||||
|
keyMerits.map((item, index) => (
|
||||||
<Box display={"flex"} alignItems={"center"}>
|
<Box display={"flex"} alignItems={"center"}>
|
||||||
{keyMerits?.[0]?.icon?.iconFilePath && (
|
|
||||||
<Image
|
<Image
|
||||||
rounded={"md"}
|
rounded={"md"}
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
@@ -343,17 +360,18 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
justifyContent={"center"}
|
justifyContent={"center"}
|
||||||
alignItems={"center"}
|
alignItems={"center"}
|
||||||
src={
|
src={
|
||||||
"https://tanami.betadelivery.com/" +
|
import.meta.env.VITE_IMAGE_URL+
|
||||||
keyMerits[0].icon.iconFilePath
|
item?.icon.iconFilePath
|
||||||
}
|
}
|
||||||
w={8}
|
w={8}
|
||||||
h={8}
|
h={8}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
<Text fontSize={"xs"} mb={0}>
|
<Text fontSize={"xs"} mb={0}>
|
||||||
{IObyID?.data?.keyMerits[0]?.meritsDescription}
|
{item?.meritsDescription}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
mb={4}
|
mb={4}
|
||||||
@@ -413,7 +431,7 @@ const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
|
|||||||
>
|
>
|
||||||
<source
|
<source
|
||||||
src={
|
src={
|
||||||
IObyID?.data?.artifactsVideo?.[0]
|
import.meta.env.VITE_IMAGE_URL+IObyID?.data?.artifactsVideo?.[0]
|
||||||
?.artifactStreamingURL
|
?.artifactStreamingURL
|
||||||
}
|
}
|
||||||
type="video/mp4"
|
type="video/mp4"
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
import { Select, HStack, Text, Box, IconButton } from '@chakra-ui/react';
|
import { Select, HStack, Text, Box, IconButton } from "@chakra-ui/react";
|
||||||
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
|
import { ChevronLeftIcon, ChevronRightIcon } from "@chakra-ui/icons";
|
||||||
|
|
||||||
const Pagination = ({ pageSize, setPageSize, totalItems,isLoading, setCurrentPage, currentPage }) => {
|
const Pagination = ({
|
||||||
|
pageSize,
|
||||||
|
setPageSize,
|
||||||
|
totalItems,
|
||||||
|
isLoading,
|
||||||
|
setCurrentPage,
|
||||||
|
currentPage,
|
||||||
|
}) => {
|
||||||
// const [] = useState(itemsPerPageOptions[0]);
|
// const [] = useState(itemsPerPageOptions[0]);
|
||||||
|
|
||||||
|
|
||||||
const totalPages = Math.ceil(totalItems / pageSize);
|
const totalPages = Math.ceil(totalItems / pageSize);
|
||||||
|
|
||||||
const handlePageSizeChange = (e) => {
|
const handlePageSizeChange = (e) => {
|
||||||
@@ -36,7 +42,6 @@ const Pagination = ({ pageSize, setPageSize, totalItems,isLoading, setCurrentPag
|
|||||||
|
|
||||||
<HStack>
|
<HStack>
|
||||||
<Select
|
<Select
|
||||||
|
|
||||||
className="pointer web-text-small"
|
className="pointer web-text-small"
|
||||||
width={"90px"}
|
width={"90px"}
|
||||||
rounded="sm"
|
rounded="sm"
|
||||||
@@ -52,24 +57,34 @@ const Pagination = ({ pageSize, setPageSize, totalItems,isLoading, setCurrentPag
|
|||||||
</Select>
|
</Select>
|
||||||
<IconButton
|
<IconButton
|
||||||
mt={1}
|
mt={1}
|
||||||
size={'sm'}
|
size={"sm"}
|
||||||
rounded="sm"
|
rounded="sm"
|
||||||
icon={<ChevronLeftIcon />}
|
icon={<ChevronLeftIcon />}
|
||||||
onClick={paginationPrev}
|
onClick={paginationPrev}
|
||||||
className="link pointer"
|
className="link pointer"
|
||||||
isDisabled={currentPage === 1}
|
isDisabled={currentPage === 1}
|
||||||
|
aria-label="Previous Page"
|
||||||
/>
|
/>
|
||||||
<Text w={"81px"} display={'flex'} justifyContent={'center'} className="web-text-medium" as={"span"}>
|
<Text
|
||||||
{isLoading ? "0": displayRange?.start} - {isLoading ? "00" :displayRange?.end} of {isLoading ? "00":totalItems}
|
w={"81px"}
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"center"}
|
||||||
|
className="web-text-medium"
|
||||||
|
as={"span"}
|
||||||
|
>
|
||||||
|
{isLoading ? "0" : displayRange?.start} -{" "}
|
||||||
|
{isLoading ? "00" : displayRange?.end} of{" "}
|
||||||
|
{isLoading ? "00" : totalItems}
|
||||||
</Text>
|
</Text>
|
||||||
<IconButton
|
<IconButton
|
||||||
mt={1}
|
mt={1}
|
||||||
icon={<ChevronRightIcon />}
|
icon={<ChevronRightIcon />}
|
||||||
size={'sm'}
|
size={"sm"}
|
||||||
rounded="sm"
|
rounded="sm"
|
||||||
onClick={paginationNext}
|
onClick={paginationNext}
|
||||||
className="link pointer"
|
className="link pointer"
|
||||||
isDisabled={currentPage === totalPages}
|
isDisabled={currentPage === totalPages}
|
||||||
|
aria-label="Next Page"
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { CheckCircleIcon, WarningIcon } from "@chakra-ui/icons";
|
import { CheckCircleIcon, WarningIcon } from "@chakra-ui/icons";
|
||||||
import { Box, Text } from "@chakra-ui/react";
|
import { Box, Text } from "@chakra-ui/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { PiWarningBold } from "react-icons/pi";
|
||||||
|
|
||||||
const ToastBox = ({ message, status }) => {
|
const ToastBox = ({ message, status }) => {
|
||||||
return (
|
return (
|
||||||
@@ -9,10 +10,10 @@ const ToastBox = ({ message, status }) => {
|
|||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
className="web-text-large d-flex gap-2 align-items-center"
|
className="web-text-large d-flex gap-2 align-items-center"
|
||||||
p={3}
|
p={3}
|
||||||
bg={status === "error" ? "red.500" : status === "warn" ? "blue.500" : "green.500"}
|
bg={status === "error" ? "red.500" : status === "warn" ? "yellow.500" : status === "info" ? "blue.500" : "green.500"}
|
||||||
>
|
>
|
||||||
|
|
||||||
{status === "error" || status === "warn" ? <WarningIcon/> : <CheckCircleIcon /> }
|
{status === "error" || status === "warn" ? <PiWarningBold/> : status === "info" ? <WarningIcon/> : <CheckCircleIcon /> }
|
||||||
<Text as={"span"}>{message}</Text>
|
<Text as={"span"}>{message}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
|
||||||
import dns from "node:dns"
|
import dns from "node:dns"
|
||||||
|
import * as XLSX from 'xlsx';
|
||||||
|
|
||||||
|
|
||||||
|
export const generateSerialNumber = (index, currentPage, pageSize) => {
|
||||||
|
return (currentPage - 1) * pageSize + (index + 1);
|
||||||
|
};
|
||||||
|
|
||||||
export function getTomorrowDate() {
|
export function getTomorrowDate() {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
@@ -53,10 +56,14 @@ export function removeTrailingZeros(value) {
|
|||||||
const remainingMinutes = minutes % 60;
|
const remainingMinutes = minutes % 60;
|
||||||
const remainingSeconds = seconds % 60;
|
const remainingSeconds = seconds % 60;
|
||||||
|
|
||||||
return `${remainingDays === 0 ? "": remainingDays+"d"} ${remainingHours === 0 ? "": remainingHours+"h"} ${remainingMinutes}m `;
|
return `${remainingDays === 0 ? "": remainingDays+"d"} ${remainingHours === 0 ? "": remainingHours+"h"} ${remainingMinutes}m ${remainingSeconds}s `;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function bytesToMB(bytes) {
|
||||||
|
return (bytes / (1024 * 1024)).toFixed(2); // Convert bytes to MB and limit to 2 decimal places
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function startCountdown(utcDateString) {
|
export function startCountdown(utcDateString) {
|
||||||
// Function to update the countdown
|
// Function to update the countdown
|
||||||
@@ -137,3 +144,78 @@ export function formatDate(dateString) {
|
|||||||
const date = new Date(dateString);
|
const date = new Date(dateString);
|
||||||
return date.toLocaleDateString('en-US', options);
|
return date.toLocaleDateString('en-US', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function calculatePercentage(part, total) {
|
||||||
|
if (total === 0) {
|
||||||
|
return 0; // To avoid division by zero
|
||||||
|
}
|
||||||
|
return (part / total) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const getNestedValue = (obj, key) => {
|
||||||
|
return key.split('.').reduce((value, part) => {
|
||||||
|
return value && value[part] ? value[part] : null;
|
||||||
|
}, obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const exportToExcel = (data, headers) => {
|
||||||
|
const flattenedData = data.map((item) => {
|
||||||
|
const newItem = {};
|
||||||
|
|
||||||
|
// Loop through customHeaders and get the correct values
|
||||||
|
headers.forEach((header) => {
|
||||||
|
newItem[header.label] = getNestedValue(item, header.key); // Use the helper function
|
||||||
|
});
|
||||||
|
|
||||||
|
return newItem; // Return the new flat object
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now pass flattenedData to your Excel library to generate the file
|
||||||
|
// Assuming you're using a library like `xlsx` for this part:
|
||||||
|
|
||||||
|
const worksheet = XLSX.utils.json_to_sheet(flattenedData);
|
||||||
|
const workbook = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
|
||||||
|
|
||||||
|
// Generate file
|
||||||
|
XLSX.writeFile(workbook, "exported_data.xlsx");
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const exportToExcelNew = (data, fileName = "exported_data.xlsx") => {
|
||||||
|
console.log("Data to export:", data); // Log the data for debugging
|
||||||
|
|
||||||
|
// Ensure the data is not empty
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
console.error("No data provided for export.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the data to a worksheet
|
||||||
|
const worksheet = XLSX.utils.json_to_sheet(data);
|
||||||
|
|
||||||
|
// Create a new workbook and append the worksheet to it
|
||||||
|
const workbook = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
|
||||||
|
|
||||||
|
// Ensure file has a valid .xlsx extension
|
||||||
|
const fileWithExtension = fileName.endsWith(".xlsx") ? fileName : `${fileName}.xlsx`;
|
||||||
|
|
||||||
|
// Write the workbook to a file
|
||||||
|
XLSX.writeFile(workbook, fileWithExtension);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export function formatDateToYYYYMMDD(dateString) {
|
||||||
|
const date = new Date(dateString);
|
||||||
|
|
||||||
|
// Extract individual date components
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-based
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
// Combine the formatted parts
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
@@ -712,136 +712,8 @@ const GlobalStateProvider = ({ children }) => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const [viewInvestor, setViewInvestor] = useState([
|
const [viewInvestor, setViewInvestor] = useState([]);
|
||||||
{
|
const [transaction, setTransaction] = useState([]);
|
||||||
id: 1,
|
|
||||||
dealId: "UWE3424992",
|
|
||||||
dealName: "KKR Private Equity Fund",
|
|
||||||
sponsorName: "KKR",
|
|
||||||
investAmount: "$100,000",
|
|
||||||
holdingPeriod: "4-5 years",
|
|
||||||
estimatedReturn: "50-60%",
|
|
||||||
kycStatus: "Open",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
dealId: "UWE3424992",
|
|
||||||
dealName: "Blackstone Real Estate Income Trust",
|
|
||||||
sponsorName: "Blackstone",
|
|
||||||
investAmount: "$100,000",
|
|
||||||
holdingPeriod: "4-5 years",
|
|
||||||
estimatedReturn: "50-60%",
|
|
||||||
kycStatus: "Pending",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
dealId: "UWE3424992",
|
|
||||||
dealName: "J.P. Morgan",
|
|
||||||
sponsorName: "J.P. Morgan",
|
|
||||||
investAmount: "$100,000",
|
|
||||||
holdingPeriod: "4-5 years",
|
|
||||||
estimatedReturn: "50-60%",
|
|
||||||
kycStatus: "Closed",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const [transaction, setTransaction] = useState([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
date: "2-Jan-24",
|
|
||||||
transaction: "Deposit",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "12000.00",
|
|
||||||
fromUSD: "",
|
|
||||||
toUSD: "2.6376",
|
|
||||||
USDamount: "31,651.20",
|
|
||||||
IOName:"",
|
|
||||||
paymentMethod:"Bank"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
date: "6-Jan-24",
|
|
||||||
transaction: "Invested",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "-4000.00",
|
|
||||||
fromUSD: "",
|
|
||||||
toUSD: "2.6376",
|
|
||||||
USDamount: "-10,550.40",
|
|
||||||
IOName:"KKR Private Equity Fund",
|
|
||||||
paymentMethod:"-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
date: "7-Jan-24",
|
|
||||||
transaction: "Deposit",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "4000.00",
|
|
||||||
fromUSD: "",
|
|
||||||
toUSD: "2.6376",
|
|
||||||
USDamount: "10,550.40",
|
|
||||||
IOName:"-",
|
|
||||||
paymentMethod:"Apple Pay"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
date: "8-Jan-24",
|
|
||||||
transaction: "Invested",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "-3000.00",
|
|
||||||
fromUSD: "",
|
|
||||||
toUSD: "2.6376",
|
|
||||||
USDamount: "-7,912.80",
|
|
||||||
IOName:"Black Stone Real Estate Income Trust",
|
|
||||||
paymentMethod:"-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
date: "2-Jan-24",
|
|
||||||
transaction: "Deposit",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "12000.00",
|
|
||||||
fromUSD: "0.3747",
|
|
||||||
toUSD: "",
|
|
||||||
USDamount: "31,651.20",
|
|
||||||
IOName:"KKR Private Equity Fund",
|
|
||||||
paymentMethod:"-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
date: "2-Jan-24",
|
|
||||||
transaction: "Deposit",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "12000.00",
|
|
||||||
fromUSD: "0.3747",
|
|
||||||
toUSD: "",
|
|
||||||
USDamount: "31,651.20",
|
|
||||||
IOName:"Black Stone Real Estate Income Trust",
|
|
||||||
paymentMethod:"-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
date: "2-Jan-24",
|
|
||||||
transaction: "Deposit",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "12000.00",
|
|
||||||
fromUSD: "0.3747",
|
|
||||||
toUSD: "",
|
|
||||||
USDamount: "31,651.20",
|
|
||||||
IOName:"KKR Private Equity Fund",
|
|
||||||
paymentMethod:"-"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
date: "2-Jan-24",
|
|
||||||
transaction: "Deposit",
|
|
||||||
currency: "BHD",
|
|
||||||
amount: "12000.00",
|
|
||||||
fromUSD: "",
|
|
||||||
toUSD: "2.6376",
|
|
||||||
USDamount: "31,651.20",
|
|
||||||
IOName:"",
|
|
||||||
paymentMethod:"Bank"
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const [investorTransaction, setInvestorTransaction] = useState([
|
const [investorTransaction, setInvestorTransaction] = useState([
|
||||||
{
|
{
|
||||||
@@ -1090,112 +962,14 @@ const GlobalStateProvider = ({ children }) => {
|
|||||||
]);
|
]);
|
||||||
const [deleteHistory, setDeleteHistory] = useState([
|
const [deleteHistory, setDeleteHistory] = useState([
|
||||||
{
|
{
|
||||||
id: uuidv4(),
|
id: 1,
|
||||||
date: "2024-01-15",
|
firstName: "satyam",
|
||||||
Distribution: "Office supplies",
|
lastName: "Bendal",
|
||||||
charge: "200.50",
|
clientId: "QA00000003",
|
||||||
year: "2024",
|
RequestedOn: "2024-08-21T08:12:08.000Z",
|
||||||
quarter: "Q1",
|
phoneNumber: "6387524874",
|
||||||
amount: 1500,
|
country: "Qatar",
|
||||||
},
|
status: "Approved",
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-02-10",
|
|
||||||
Distribution: "Marketing expenses",
|
|
||||||
charge: "450.00",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q1",
|
|
||||||
amount: 2000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-03-05",
|
|
||||||
Distribution: "Software subscription",
|
|
||||||
charge: "300.75",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q1",
|
|
||||||
amount: 1200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-04-18",
|
|
||||||
Distribution: "Travel expenses",
|
|
||||||
charge: "600.30",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q2",
|
|
||||||
amount: 2500,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-05-22",
|
|
||||||
Distribution: "Consulting fees",
|
|
||||||
charge: "800.00",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q2",
|
|
||||||
amount: 3000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-06-14",
|
|
||||||
Distribution: "Office rent",
|
|
||||||
charge: "1200.25",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q2",
|
|
||||||
amount: 3500,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-07-09",
|
|
||||||
Distribution: "Utilities",
|
|
||||||
charge: "150.40",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q3",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-08-29",
|
|
||||||
Distribution: "Employee training",
|
|
||||||
charge: "500.00",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q3",
|
|
||||||
amount: 1800,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-09-13",
|
|
||||||
Distribution: "Website maintenance",
|
|
||||||
charge: "350.65",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q3",
|
|
||||||
amount: 1400,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-10-23",
|
|
||||||
Distribution: "Advertising",
|
|
||||||
charge: "900.50",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q4",
|
|
||||||
amount: 2200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-10-23",
|
|
||||||
Distribution: "Advertising",
|
|
||||||
charge: "900.50",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q4",
|
|
||||||
amount: 2200,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: "2024-10-23",
|
|
||||||
Distribution: "Advertising",
|
|
||||||
charge: "900.50",
|
|
||||||
year: "2024",
|
|
||||||
quarter: "Q4",
|
|
||||||
amount: 2200,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const [investorRequest, setInvestorRequest] = useState([
|
const [investorRequest, setInvestorRequest] = useState([
|
||||||
@@ -1310,113 +1084,25 @@ const GlobalStateProvider = ({ children }) => {
|
|||||||
]);
|
]);
|
||||||
const [deleteRequest, setDeleteRequest] = useState([
|
const [deleteRequest, setDeleteRequest] = useState([
|
||||||
{
|
{
|
||||||
id: uuidv4(),
|
"id": 2,
|
||||||
date: getRandomDate(startDate, endDate),
|
"firstName": "satyam",
|
||||||
Distribution: "lorem ipsum dummy text",
|
"lastName": "Bendal",
|
||||||
charge: "500",
|
"clientId": "QA00000003",
|
||||||
year: "2024",
|
"RequestedOn": "2024-08-21T09:44:21.000Z",
|
||||||
quater: "Q 1",
|
"phoneNumber": "6387524874",
|
||||||
amount: 1000,
|
"country": "Qatar",
|
||||||
|
"status": "Pending"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: uuidv4(),
|
"id": 3,
|
||||||
date: getRandomDate(startDate, endDate),
|
"firstName": "satyam",
|
||||||
Distribution: "lorem ipsum dummy text",
|
"lastName": "Bendal",
|
||||||
charge: "500",
|
"clientId": "QA00000003",
|
||||||
year: "2024",
|
"RequestedOn": "2024-08-21T09:53:03.000Z",
|
||||||
quater: "Q 1",
|
"phoneNumber": "6387524874",
|
||||||
amount: 1000,
|
"country": "Qatar",
|
||||||
},
|
"status": "Pending"
|
||||||
{
|
}
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: uuidv4(),
|
|
||||||
date: getRandomDate(startDate, endDate),
|
|
||||||
Distribution: "lorem ipsum dummy text",
|
|
||||||
charge: "500",
|
|
||||||
year: "2024",
|
|
||||||
quater: "Q 1",
|
|
||||||
amount: 1000,
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
const [viewIO, setViewIO] = useState([
|
const [viewIO, setViewIO] = useState([
|
||||||
{
|
{
|
||||||
@@ -1449,7 +1135,6 @@ const GlobalStateProvider = ({ children }) => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
const [depositRequest, setDepositRequest] = useState([
|
const [depositRequest, setDepositRequest] = useState([
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -1683,6 +1368,28 @@ const GlobalStateProvider = ({ children }) => {
|
|||||||
mailId: "john@gmail.com",
|
mailId: "john@gmail.com",
|
||||||
status: "Incompleted",
|
status: "Incompleted",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
date: "02-Jan-2024",
|
||||||
|
clientId: "SA00000001",
|
||||||
|
firstName: "John",
|
||||||
|
lastName: "David",
|
||||||
|
country: "Saudi Arabia",
|
||||||
|
phoneNumber: "8940035906",
|
||||||
|
mailId: "john@gmail.com",
|
||||||
|
status: "Incompleted",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
date: "02-Jan-2024",
|
||||||
|
clientId: "SA00000001",
|
||||||
|
firstName: "John",
|
||||||
|
lastName: "David",
|
||||||
|
country: "Saudi Arabia",
|
||||||
|
phoneNumber: "8940035906",
|
||||||
|
mailId: "john@gmail.com",
|
||||||
|
status: "Incompleted",
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const [manageAcademy, setManageAcademy] = useState([
|
const [manageAcademy, setManageAcademy] = useState([
|
||||||
@@ -1723,15 +1430,138 @@ const GlobalStateProvider = ({ children }) => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
const [users, setUsers] = useState([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
firstName: "SA00000001",
|
||||||
|
lastName: "John David",
|
||||||
|
emailID: "John",
|
||||||
|
role: "David",
|
||||||
|
phoneNumber:"8940035906",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const [fawateerRequest, setFawateerRequest] = useState([
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
principal_xid: 2,
|
||||||
|
transaction_date: "2024-10-07",
|
||||||
|
transaction_amount: "2000.00",
|
||||||
|
transactionStatus: "Approved",
|
||||||
|
makerComment: "This is a sample comment for the transactio",
|
||||||
|
checkerComment: "This is a sample comment for the transaction",
|
||||||
|
spportFile_path: "public\\spportFile_path\\screenshot_2024_02_15_152810.png",
|
||||||
|
clientReference_id: "BH00000001",
|
||||||
|
firstName: "jayesh",
|
||||||
|
lastName: "jain ",
|
||||||
|
mobileNumber: "+919819906537",
|
||||||
|
emailAddress: "jayeshkjain6@gmail.com",
|
||||||
|
maker: {
|
||||||
|
firstName: "Faisal",
|
||||||
|
lastName: "Aljalahma",
|
||||||
|
emailAddress: "admin@tanami.com",
|
||||||
|
ISDcode: "+973",
|
||||||
|
mobileNumber: "3633133"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
principal_xid: 2,
|
||||||
|
transaction_date: "2024-10-07",
|
||||||
|
transaction_amount: "2000.00",
|
||||||
|
transactionStatus: "Approved",
|
||||||
|
makerComment: "This is a sample comment for the transactio",
|
||||||
|
checkerComment: "This is a sample comment for the transaction",
|
||||||
|
spportFile_path: "public\\spportFile_path\\screenshot_2024_02_15_152810.png",
|
||||||
|
clientReference_id: "BH00000001",
|
||||||
|
firstName: "jayesh",
|
||||||
|
lastName: "jain ",
|
||||||
|
mobileNumber: "+919819906537",
|
||||||
|
emailAddress: "jayeshkjain6@gmail.com",
|
||||||
|
maker: {
|
||||||
|
firstName: "Faisal",
|
||||||
|
lastName: "Aljalahma",
|
||||||
|
emailAddress: "admin@tanami.com",
|
||||||
|
ISDcode: "+973",
|
||||||
|
mobileNumber: "3633133"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
principal_xid: 2,
|
||||||
|
transaction_date: "2024-10-07",
|
||||||
|
transaction_amount: "2000.00",
|
||||||
|
transactionStatus: "Approved",
|
||||||
|
makerComment: "This is a sample comment for the transactio",
|
||||||
|
checkerComment: "This is a sample comment for the transaction",
|
||||||
|
spportFile_path: "public\\spportFile_path\\screenshot_2024_02_15_152810.png",
|
||||||
|
clientReference_id: "BH00000001",
|
||||||
|
firstName: "jayesh",
|
||||||
|
lastName: "jain ",
|
||||||
|
mobileNumber: "+919819906537",
|
||||||
|
emailAddress: "jayeshkjain6@gmail.com",
|
||||||
|
maker: {
|
||||||
|
firstName: "Faisal",
|
||||||
|
lastName: "Aljalahma",
|
||||||
|
emailAddress: "admin@tanami.com",
|
||||||
|
ISDcode: "+973",
|
||||||
|
mobileNumber: "3633133"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
principal_xid: 2,
|
||||||
|
transaction_date: "2024-10-07",
|
||||||
|
transaction_amount: "2000.00",
|
||||||
|
transactionStatus: "Approved",
|
||||||
|
makerComment: "This is a sample comment for the transactio",
|
||||||
|
checkerComment: "This is a sample comment for the transaction",
|
||||||
|
spportFile_path: "public\\spportFile_path\\screenshot_2024_02_15_152810.png",
|
||||||
|
clientReference_id: "BH00000001",
|
||||||
|
firstName: "jayesh",
|
||||||
|
lastName: "jain ",
|
||||||
|
mobileNumber: "+919819906537",
|
||||||
|
emailAddress: "jayeshkjain6@gmail.com",
|
||||||
|
maker: {
|
||||||
|
firstName: "Faisal",
|
||||||
|
lastName: "Aljalahma",
|
||||||
|
emailAddress: "admin@tanami.com",
|
||||||
|
ISDcode: "+973",
|
||||||
|
mobileNumber: "3633133"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const [approveHistory, setApproveHistory] = useState([
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"principal_xid": 2,
|
||||||
|
"transaction_date": "2024-10-07",
|
||||||
|
"transaction_amount": "2000.00",
|
||||||
|
"transactionStatus": "Pending",
|
||||||
|
"makerComment": null,
|
||||||
|
"checkerComment": null,
|
||||||
|
"spportFile_path": null,
|
||||||
|
"clientReference_id": "BH00000001",
|
||||||
|
"firstName": "jayesh",
|
||||||
|
"lastName": "jain",
|
||||||
|
"mobileNumber": "+919819906537",
|
||||||
|
"emailAddress": "jayeshkjain6@gmail.com",
|
||||||
|
"maker": {
|
||||||
|
"firstName": "Faisal",
|
||||||
|
"lastName": "Aljalahma",
|
||||||
|
"emailAddress": "admin@tanami.com",
|
||||||
|
"ISDcode": "+973",
|
||||||
|
"mobileNumber": "3633133"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const [InvestorWallet, setInvestorWallet] = useState(null);
|
||||||
|
|
||||||
|
|
||||||
// ==============[ prod state ]===============================
|
// ==============[ prod state ]===============================
|
||||||
const [IODetails, setIODetails] = useState(null);
|
const [IODetails, setIODetails] = useState(null);
|
||||||
const [ isIOloading, setIOloading ] = useState(false)
|
const [isIOloading, setIOloading] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GlobalStateContext.Provider
|
<GlobalStateContext.Provider
|
||||||
@@ -1804,10 +1634,16 @@ const GlobalStateProvider = ({ children }) => {
|
|||||||
setAcademicDocuments,
|
setAcademicDocuments,
|
||||||
iOArtifactsTwo,
|
iOArtifactsTwo,
|
||||||
setIOArtifactsTwo,
|
setIOArtifactsTwo,
|
||||||
|
InvestorWallet,
|
||||||
|
setInvestorWallet,
|
||||||
isIOloading,
|
isIOloading,
|
||||||
setIOloading
|
setIOloading,
|
||||||
|
users,
|
||||||
|
setUsers,
|
||||||
|
fawateerRequest,
|
||||||
|
setFawateerRequest,
|
||||||
|
approveHistory,
|
||||||
|
setApproveHistory
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import logoMiniDark from "../assets/favicon.png";
|
|||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { loginUser } from "../Redux/Slice/auth";
|
import { loginUser } from "../Redux/Slice/auth";
|
||||||
import Button02 from "../Components/Buttons/Button02";
|
import Button02 from "../Components/Buttons/Button02";
|
||||||
|
import { CgProfile } from "react-icons/cg";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TbArrowBadgeLeftFilled,
|
TbArrowBadgeLeftFilled,
|
||||||
TbListDetails,
|
TbListDetails,
|
||||||
@@ -13,7 +15,7 @@ import {
|
|||||||
TbTransactionDollar,
|
TbTransactionDollar,
|
||||||
} from "react-icons/tb";
|
} from "react-icons/tb";
|
||||||
import { TbArrowBadgeRightFilled } from "react-icons/tb";
|
import { TbArrowBadgeRightFilled } from "react-icons/tb";
|
||||||
import { ArrowBackIcon, ArrowLeftIcon, ArrowRightIcon } from "@chakra-ui/icons";
|
import { ArrowBackIcon, ArrowLeftIcon, ArrowRightIcon, AtSignIcon } from "@chakra-ui/icons";
|
||||||
import {
|
import {
|
||||||
Link,
|
Link,
|
||||||
NavLink,
|
NavLink,
|
||||||
@@ -51,6 +53,8 @@ import {
|
|||||||
AlertIcon,
|
AlertIcon,
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
Divider,
|
Divider,
|
||||||
|
Tooltip,
|
||||||
|
useRadio,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||||
import Cookies from "js-cookie"; // Import the Cookies library
|
import Cookies from "js-cookie"; // Import the Cookies library
|
||||||
@@ -73,8 +77,15 @@ import SplashScreen from "../Pages/SplashScreen";
|
|||||||
import CutomBreadcrumb from "../Components/CutomBreadcrumb";
|
import CutomBreadcrumb from "../Components/CutomBreadcrumb";
|
||||||
import CustomBreadcrumb from "../Components/CutomBreadcrumb";
|
import CustomBreadcrumb from "../Components/CutomBreadcrumb";
|
||||||
import { getCountdownTimer } from "../Constants/Constants";
|
import { getCountdownTimer } from "../Constants/Constants";
|
||||||
|
import { useLogoutMutation } from "../Services/token.serivce";
|
||||||
|
import CreateRequest from "../Pages/Fawateer/CreateRequest";
|
||||||
|
import ApproveRequest from "../Pages/FawateerChecker/ApproveRequest/ApproveRequest";
|
||||||
|
import ApproveHistoryMaker from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker";
|
||||||
|
import ApproveHistory from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker";
|
||||||
|
import { useProfileQuery } from "../Services/io.service";
|
||||||
|
|
||||||
const DashboardLayout = ({ isOnline }) => {
|
const DashboardLayout = ({ isOnline }) => {
|
||||||
|
const userRole = localStorage.getItem("role");
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispach = useDispatch();
|
const dispach = useDispatch();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -91,6 +102,18 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
const [isSplashVisible, setSplashVisible] = useState(true);
|
const [isSplashVisible, setSplashVisible] = useState(true);
|
||||||
const [openIndex, setOpenIndex] = useState(null);
|
const [openIndex, setOpenIndex] = useState(null);
|
||||||
|
|
||||||
|
const { data, refetch } = useProfileQuery();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
!localStorage.getItem("accessToken") &&
|
||||||
|
!localStorage.getItem("refreshToken")
|
||||||
|
) {
|
||||||
|
logOutHandler();
|
||||||
|
return navigate("/login");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const savedIndex = localStorage.getItem("openAccordionIndex");
|
const savedIndex = localStorage.getItem("openAccordionIndex");
|
||||||
if (savedIndex !== null) {
|
if (savedIndex !== null) {
|
||||||
@@ -109,7 +132,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
setSplashVisible(false);
|
setSplashVisible(false);
|
||||||
}, 1000); // 3000ms = 3 seconds
|
}, 1000); // 3000ms = 3 seconds
|
||||||
|
refetch();
|
||||||
// Cleanup the timer
|
// Cleanup the timer
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -118,14 +141,17 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
setOpenDrawerClick(!openDrawerClick);
|
setOpenDrawerClick(!openDrawerClick);
|
||||||
};
|
};
|
||||||
|
|
||||||
const logOutHandler = () => {
|
const [logout] = useLogoutMutation();
|
||||||
|
|
||||||
|
const logOutHandler = async () => {
|
||||||
// dispach(loginUser(false));
|
// dispach(loginUser(false));
|
||||||
setIsAuthenticate(false);
|
setIsAuthenticate(false);
|
||||||
Cookies.remove("isAuthenticated");
|
Cookies.remove("isAuthenticated");
|
||||||
localStorage.removeItem('refreshToken')
|
try {
|
||||||
localStorage.removeItem('accessToken')
|
await logout();
|
||||||
localStorage.removeItem('refreshTokenExp')
|
localStorage.clear();
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// // Function to get the title based on the route
|
// // Function to get the title based on the route
|
||||||
@@ -139,12 +165,24 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
<RiMoneyDollarBoxLine className="h4 m-0" /> Sponsor
|
<RiMoneyDollarBoxLine className="h4 m-0" /> Sponsor
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
case path.startsWith("/email"):
|
||||||
|
return (
|
||||||
|
<span className="d-flex align-items-end gap-2">
|
||||||
|
<AtSignIcon className="h4 m-0" /> Email Notifiation
|
||||||
|
</span>
|
||||||
|
);
|
||||||
case path.startsWith("/investment-type"):
|
case path.startsWith("/investment-type"):
|
||||||
return (
|
return (
|
||||||
<span className="d-flex align-items-end gap-2">
|
<span className="d-flex align-items-end gap-2">
|
||||||
<VscSymbolClass className="h4 m-0" /> Investment Type
|
<VscSymbolClass className="h4 m-0" /> Investment Type
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
case path.startsWith("/profile"):
|
||||||
|
return (
|
||||||
|
<span className="d-flex align-items-end gap-2">
|
||||||
|
<CgProfile className="h4 m-0" /> Profile
|
||||||
|
</span>
|
||||||
|
);
|
||||||
case path.startsWith("/exchange-rate"):
|
case path.startsWith("/exchange-rate"):
|
||||||
return (
|
return (
|
||||||
<span className="d-flex align-items-end gap-2">
|
<span className="d-flex align-items-end gap-2">
|
||||||
@@ -189,28 +227,35 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case path.startsWith("/deposit-request"):
|
case path.startsWith("/deposit-request"):
|
||||||
return (
|
return (
|
||||||
<span className="d-flex align-items-end gap-2">
|
<span className="d-flex align-items-end gap-2">
|
||||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||||
Deposite pending request
|
Deposit pending request
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
case path.startsWith("/deposit-history"):
|
case path.startsWith("/deposit-history"):
|
||||||
return (
|
return (
|
||||||
<span className="d-flex align-items-end gap-2">
|
<span className="d-flex align-items-end gap-2">
|
||||||
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
|
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
|
||||||
Deposite withdrawal request
|
Deposite request
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case path.startsWith("/fawateer"):
|
||||||
|
return (
|
||||||
|
<span className="d-flex align-items-end gap-2">
|
||||||
|
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||||
|
Fawateer Deposit
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
case path.startsWith("/fawateer-history"):
|
||||||
|
return (
|
||||||
|
<span className="d-flex align-items-end gap-2">
|
||||||
|
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||||
|
Fawateer Deposit
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
|
||||||
case path.startsWith("/withdraw-request"):
|
case path.startsWith("/withdraw-request"):
|
||||||
return (
|
return (
|
||||||
@@ -386,7 +431,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
bottom={4}
|
bottom={4}
|
||||||
right={!slideFromRight ? 4 : "auto"}
|
right={!slideFromRight ? 4 : "auto"}
|
||||||
left={slideFromRight ? 4 : "auto"}
|
left={slideFromRight ? 4 : "auto"}
|
||||||
backgroundColor={"#fff"}
|
backgroundColor={"#000"}
|
||||||
rounded={"full"}
|
rounded={"full"}
|
||||||
p={2}
|
p={2}
|
||||||
w={8}
|
w={8}
|
||||||
@@ -438,7 +483,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
}}
|
}}
|
||||||
src={colorMode === "light" ? logo : logoDark}
|
src={colorMode === "light" ? logo : logoDark}
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
onClick={()=> navigate('/')}
|
onClick={() => navigate("/")}
|
||||||
cursor={"pointer"}
|
cursor={"pointer"}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -448,7 +493,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
}}
|
}}
|
||||||
src={colorMode === "light" ? logoMini : logoMiniDark}
|
src={colorMode === "light" ? logoMini : logoMiniDark}
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
onClick={()=> navigate('/')}
|
onClick={() => navigate("/")}
|
||||||
cursor={"pointer"}
|
cursor={"pointer"}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -474,6 +519,15 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
if (type === "accordion") {
|
if (type === "accordion") {
|
||||||
return (
|
return (
|
||||||
<AccordionItem key={index} border={"none"}>
|
<AccordionItem key={index} border={"none"}>
|
||||||
|
<Tooltip
|
||||||
|
isDisabled={isDrawerOpen || openDrawerClick}
|
||||||
|
hasArrow
|
||||||
|
bg={"#fff"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label={title}
|
||||||
|
placement="top-start"
|
||||||
|
color={"blue.800"}
|
||||||
|
>
|
||||||
<AccordionButton
|
<AccordionButton
|
||||||
style={{ height: "auto" }}
|
style={{ height: "auto" }}
|
||||||
className={`${
|
className={`${
|
||||||
@@ -494,10 +548,13 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
fontSize={title === "Admin" ? "18px" : "15px"}
|
fontSize={title === "Admin" ? "18px" : "15px"}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Text
|
<Text
|
||||||
as={"span"}
|
as={"span"}
|
||||||
display={
|
display={
|
||||||
isDrawerOpen || openDrawerClick ? "flex" : "none"
|
isDrawerOpen || openDrawerClick
|
||||||
|
? "flex"
|
||||||
|
: "none"
|
||||||
}
|
}
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
@@ -508,6 +565,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
</Box>
|
</Box>
|
||||||
<AccordionIcon />
|
<AccordionIcon />
|
||||||
</AccordionButton>
|
</AccordionButton>
|
||||||
|
</Tooltip>
|
||||||
<AccordionPanel
|
<AccordionPanel
|
||||||
p={0}
|
p={0}
|
||||||
pb={1}
|
pb={1}
|
||||||
@@ -520,6 +578,15 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
{ title: subMenuTitle, path: link, icon: SubIcon },
|
{ title: subMenuTitle, path: link, icon: SubIcon },
|
||||||
i
|
i
|
||||||
) => (
|
) => (
|
||||||
|
<Tooltip
|
||||||
|
isDisabled={isDrawerOpen || openDrawerClick}
|
||||||
|
hasArrow
|
||||||
|
bg={"#fff"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label={subMenuTitle}
|
||||||
|
placement="right"
|
||||||
|
color={"blue.800"}
|
||||||
|
>
|
||||||
<Box
|
<Box
|
||||||
key={i}
|
key={i}
|
||||||
style={{ height: "auto", position: "relative" }}
|
style={{ height: "auto", position: "relative" }}
|
||||||
@@ -537,7 +604,9 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
width: 2,
|
width: 2,
|
||||||
left: 22,
|
left: 22,
|
||||||
height:
|
height:
|
||||||
i === submenu?.length - 1 ? "55%" : "120%",
|
i === submenu?.length - 1
|
||||||
|
? "55%"
|
||||||
|
: "120%",
|
||||||
borderRadius: "0 0 10px 10px",
|
borderRadius: "0 0 10px 10px",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -575,10 +644,15 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
>
|
>
|
||||||
{subMenuTitle}
|
{subMenuTitle === "Aprover Request"
|
||||||
|
? data?.data?.role === "Maker"
|
||||||
|
? "Create Request"
|
||||||
|
: "Aprover Request"
|
||||||
|
: subMenuTitle}
|
||||||
</Text>
|
</Text>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</AccordionPanel>
|
</AccordionPanel>
|
||||||
@@ -596,6 +670,14 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
);
|
);
|
||||||
} else if (type === "single") {
|
} else if (type === "single") {
|
||||||
return (
|
return (
|
||||||
|
<Tooltip
|
||||||
|
hasArrow
|
||||||
|
bg={"#fff"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label={title}
|
||||||
|
placement="top-start"
|
||||||
|
color={"blue.800"}
|
||||||
|
>
|
||||||
<NavLink
|
<NavLink
|
||||||
key={index}
|
key={index}
|
||||||
style={{ height: "auto", position: "relative" }}
|
style={{ height: "auto", position: "relative" }}
|
||||||
@@ -618,6 +700,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -626,7 +709,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* <Button
|
<Button
|
||||||
colorScheme={"forestGreen"}
|
colorScheme={"forestGreen"}
|
||||||
rounded={"lg"}
|
rounded={"lg"}
|
||||||
// onMouseOver={() => setIsDrawerOpen(true)}
|
// onMouseOver={() => setIsDrawerOpen(true)}
|
||||||
@@ -646,18 +729,18 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
) : (
|
) : (
|
||||||
<ArrowRightIcon className="web-text-small " />
|
<ArrowRightIcon className="web-text-small " />
|
||||||
)}
|
)}
|
||||||
</Button> */}
|
</Button>
|
||||||
<Text textAlign={'center'} fontWeight={500} fontSize={'xs'} color={"gray.600"}>{getCountdownTimer(localStorage.getItem('accessTokenExp'))}</Text>
|
{/* <Text textAlign={'center'} fontWeight={500} fontSize={'xs'} color={"gray.600"}>{getCountdownTimer(localStorage.getItem('accessTokenExp'))}</Text> */}
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<main
|
<main
|
||||||
className={`h-100 ${slideFromRight ? "pe-3" : "ps-3"} d-flex flex-column gap-0`}
|
className={`h-100 ${
|
||||||
|
slideFromRight ? "pe-3" : "ps-3"
|
||||||
|
} d-flex flex-column gap-0`}
|
||||||
style={{
|
style={{
|
||||||
width: `calc(100% - ${isDrawerOpen || openDrawerClick ? 230 : 74}px)`,
|
width: `calc(100% - ${isDrawerOpen || openDrawerClick ? 230 : 74}px)`,
|
||||||
transition: "width 0.3s ease-in-out",
|
transition: "width 0.3s ease-in-out",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <header className="p-2 ps-0 pt-3 fw-400 border-bottom">
|
{/* <header className="p-2 ps-0 pt-3 fw-400 border-bottom">
|
||||||
@@ -665,6 +748,7 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
</header> */}
|
</header> */}
|
||||||
|
|
||||||
<HeaderMain
|
<HeaderMain
|
||||||
|
data={data}
|
||||||
slideDirecttion={slideFromRight}
|
slideDirecttion={slideFromRight}
|
||||||
logOutHandler={logOutHandler}
|
logOutHandler={logOutHandler}
|
||||||
icon
|
icon
|
||||||
@@ -673,253 +757,37 @@ const DashboardLayout = ({ isOnline }) => {
|
|||||||
|
|
||||||
{/* <CustomBreadcrumb /> */}
|
{/* <CustomBreadcrumb /> */}
|
||||||
|
|
||||||
<AppContent />
|
<AppContent data={data} />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{/* =======[ Left ]============ */}
|
|
||||||
|
|
||||||
{slideFromRight ? (
|
|
||||||
<aside
|
|
||||||
className="h-100 position-relative sideBar pe-1"
|
|
||||||
// onMouseOver={() => setIsDrawerOpen(true)}
|
|
||||||
// onMouseLeave={() => setIsDrawerOpen(false)}
|
|
||||||
style={{
|
|
||||||
width: isDrawerOpen || openDrawerClick ? 232 : 74,
|
|
||||||
transition: "width 0.3s ease-in-out", // Smooth transition for width change
|
|
||||||
// overflow: "hidden",
|
|
||||||
backgroundColor: "#0041180A",
|
|
||||||
position: "relative",
|
|
||||||
// backgroundColor: "#002F0F",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`d-flex ${
|
|
||||||
isDrawerOpen || openDrawerClick
|
|
||||||
? "justify-content-end"
|
|
||||||
: "justify-content-center"
|
|
||||||
} p-3 pt-3 pb-4 position-relative `}
|
|
||||||
height={"10%"}
|
|
||||||
>
|
|
||||||
{isDrawerOpen || openDrawerClick ? (
|
|
||||||
<img
|
|
||||||
style={{
|
|
||||||
width: 120,
|
|
||||||
}}
|
|
||||||
src={logo}
|
|
||||||
alt="Logo"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<img
|
|
||||||
style={{
|
|
||||||
width: 30,
|
|
||||||
}}
|
|
||||||
src={logoMini}
|
|
||||||
alt="Logo"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
className="ps-2 scroll-bar"
|
|
||||||
style={{ height: "80%", overflowY: "scroll", overflowX: "hidden" }}
|
|
||||||
>
|
|
||||||
<Accordion m={0} allowToggle>
|
|
||||||
{nav.map(({ title, type, Icon, submenu, path }, index) => {
|
|
||||||
if (type === "accordion") {
|
|
||||||
return (
|
|
||||||
<AccordionItem key={index} border={"none"}>
|
|
||||||
<AccordionButton
|
|
||||||
style={{ height: "auto" }}
|
|
||||||
className={`${
|
|
||||||
isDrawerOpen || openDrawerClick
|
|
||||||
? "p-2 web-text-medium ps-3 justify-content-between"
|
|
||||||
: "p-2 ps-1 web-text-xlarge justify-content-center"
|
|
||||||
} rounded-1 link d-flex align-items-center gap-2 w-100 mb-1`}
|
|
||||||
flexDirection={"row-reverse"}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
as="span"
|
|
||||||
display={"flex"}
|
|
||||||
gap={2}
|
|
||||||
alignItems={"center"}
|
|
||||||
flexDirection={"row-reverse"}
|
|
||||||
>
|
|
||||||
{Icon && <Icon className="web-text-large" />}
|
|
||||||
<Text
|
|
||||||
as={"span"}
|
|
||||||
display={
|
|
||||||
isDrawerOpen || openDrawerClick ? "flex" : "none"
|
|
||||||
}
|
|
||||||
alignItems="center"
|
|
||||||
overflow="hidden"
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
<AccordionIcon />
|
|
||||||
</AccordionButton>
|
|
||||||
<AccordionPanel
|
|
||||||
p={0}
|
|
||||||
pb={1}
|
|
||||||
display={"flex"}
|
|
||||||
flexDirection={"column"}
|
|
||||||
gap={1}
|
|
||||||
>
|
|
||||||
{submenu?.map(
|
|
||||||
(
|
|
||||||
{ title: subMenuTitle, path: link, icon: SubIcon },
|
|
||||||
i
|
|
||||||
) => (
|
|
||||||
<Box
|
|
||||||
key={i}
|
|
||||||
style={{ height: "auto", position: "relative" }}
|
|
||||||
className={`${
|
|
||||||
isDrawerOpen || openDrawerClick
|
|
||||||
? " web-text-medium ps-0 pe-4"
|
|
||||||
: " web-text-xlarge justify-content-center"
|
|
||||||
} d-flex align-items-center p-0`}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
backgroundColor={"gray.300"}
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
top: 0,
|
|
||||||
width: 2,
|
|
||||||
right: 20,
|
|
||||||
height:
|
|
||||||
i === submenu?.length - 1 ? "55%" : "120%",
|
|
||||||
borderRadius: "0 0 10px 10px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Box
|
|
||||||
backgroundColor={"gray.300"}
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
width: 8,
|
|
||||||
right: 20,
|
|
||||||
height: 2,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<NavLink
|
|
||||||
flexDirection={"row-reverse"}
|
|
||||||
className={`${
|
|
||||||
isDrawerOpen || openDrawerClick
|
|
||||||
? "p-2 ps-1 me-1 web-text-medium "
|
|
||||||
: "p-2 ps-0 ms-0 zindex-3 ms-4 web-text-xlarge justify-content-center"
|
|
||||||
} rounded-1 link d-flex align-items-center gap-2 w-100 flex-direction-row-reverse`}
|
|
||||||
to={link}
|
|
||||||
style={{ flexDirection: "row-reverse" }}
|
|
||||||
>
|
|
||||||
{SubIcon && (
|
|
||||||
<SubIcon
|
|
||||||
className="web-text-large ms-0"
|
|
||||||
style={{ zIndex: 111 }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Text
|
|
||||||
as={"span"}
|
|
||||||
display={
|
|
||||||
isDrawerOpen || openDrawerClick
|
|
||||||
? "flex"
|
|
||||||
: "none"
|
|
||||||
}
|
|
||||||
alignItems="center"
|
|
||||||
overflow="hidden"
|
|
||||||
>
|
|
||||||
{subMenuTitle}
|
|
||||||
</Text>
|
|
||||||
</NavLink>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</AccordionPanel>
|
|
||||||
</AccordionItem>
|
|
||||||
);
|
|
||||||
} else if (type === "title") {
|
|
||||||
return (
|
|
||||||
<Text
|
|
||||||
as={"span"}
|
|
||||||
key={index}
|
|
||||||
className="web-text-xxsmall fw-600 mt-1 text-secondary fw-bold me-2"
|
|
||||||
padding={0}
|
|
||||||
display={"flex"}
|
|
||||||
justifyContent={"end"}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
} else if (type === "single") {
|
|
||||||
return (
|
|
||||||
<NavLink
|
|
||||||
key={index}
|
|
||||||
style={{
|
|
||||||
height: "auto",
|
|
||||||
position: "relative",
|
|
||||||
flexDirection: "row-reverse",
|
|
||||||
}}
|
|
||||||
className={`${
|
|
||||||
isDrawerOpen || openDrawerClick
|
|
||||||
? "p-2 web-text-medium"
|
|
||||||
: "p-2 ps-0 web-text-xlarge justify-content-start"
|
|
||||||
} rounded-1 link d-flex align-items-center gap-2 w-100`}
|
|
||||||
to={path}
|
|
||||||
>
|
|
||||||
{Icon && <Icon className="web-text-large ms-2" />}
|
|
||||||
<Text
|
|
||||||
as={"span"}
|
|
||||||
display={
|
|
||||||
isDrawerOpen || openDrawerClick ? "flex" : "none"
|
|
||||||
}
|
|
||||||
alignItems="center"
|
|
||||||
overflow="hidden"
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
</NavLink>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</Accordion>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
colorScheme={"forestGreen"}
|
|
||||||
rounded={"lg"}
|
|
||||||
// onMouseOver={() => setIsDrawerOpen(true)}
|
|
||||||
// onMouseLeave={() => setIsDrawerOpen(false)}
|
|
||||||
onClick={openDrawerOnClick}
|
|
||||||
style={{
|
|
||||||
width: 18,
|
|
||||||
height: 26,
|
|
||||||
position: "absolute",
|
|
||||||
left: -18,
|
|
||||||
bottom: 28,
|
|
||||||
zIndex: 99,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isDrawerOpen || openDrawerClick ? (
|
|
||||||
<ArrowRightIcon className="web-text-small " />
|
|
||||||
) : (
|
|
||||||
<ArrowLeftIcon className="web-text-small" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</aside>
|
|
||||||
) : null}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DashboardLayout;
|
export default DashboardLayout;
|
||||||
|
|
||||||
const AppContent = () => {
|
const AppContent = ({ data }) => {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
{RouteLink.map(({ path, Component }, index) => (
|
{RouteLink.map(({ path, Component }, index) => (
|
||||||
<Route key={index} path={path} element={<Component />} />
|
<Route key={index} path={path} element={<Component />} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="/fawateer"
|
||||||
|
element={
|
||||||
|
data?.data?.role === "Maker" ? <CreateRequest /> : <ApproveRequest />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/fawateer-history"
|
||||||
|
element={
|
||||||
|
data?.data?.role === "Maker" ? (
|
||||||
|
<ApproveHistoryMaker />
|
||||||
|
) : (
|
||||||
|
<ApproveHistory />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Route path="*" element={<NotFound />} />
|
<Route path="*" element={<NotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,66 +11,84 @@ import {
|
|||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
import DataTable from "../../Components/DataTable/DataTable";
|
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||||
import Pagination from "../../Components/Pagination";
|
import Pagination from "../../Components/Pagination";
|
||||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||||
import { formatDate } from "../../Components/Functions/UTCConvertor";
|
import { formatDate } from "../../Components/Functions/UTCConvertor";
|
||||||
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
|
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
|
||||||
|
import { useGetDeleteHistoryQuery } from "../../Services/delete.request.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||||
// import { formatDate } from "../../Components/Functions/UTCConvertor";
|
// import { formatDate } from "../../Components/Functions/UTCConvertor";
|
||||||
|
|
||||||
const DeletionHistory = () => {
|
const DeletionHistory = () => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { slideFromRight, deleteHistory, setDeleteHistory } =
|
const { slideFromRight, setDeleteHistory } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Simulate loading
|
const handler = setTimeout(() => {
|
||||||
const timer = setTimeout(() => {
|
setDebouncedSearchTerm(searchTerm);
|
||||||
setIsLoading(false);
|
}, 500); // Adjust delay as needed
|
||||||
}, 1500);
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
// Cleanup the timer on component unmount
|
|
||||||
return () => clearTimeout(timer);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// ====================================================[Table Filter]================================================================
|
const {
|
||||||
const filteredData = deleteHistory.filter((item) => {
|
data: deleteHistory,
|
||||||
// Filter by name (case insensitive)
|
isLoading,
|
||||||
const name = item.Distribution;
|
refetch
|
||||||
const searchLower = searchTerm.toLowerCase();
|
} = useGetDeleteHistoryQuery({
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
})
|
||||||
|
|
||||||
// Filter by status
|
const formatDate = (date) => {
|
||||||
// const status = item.status;
|
return new Date(date).toLocaleDateString('en-GB', {
|
||||||
// const statusLower = status ? "active" : "inactive";
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
// const statusMatches =
|
year: 'numeric',
|
||||||
// statusFilter === "all" ||
|
|
||||||
// (statusFilter === "active" && status === true) ||
|
|
||||||
// (statusFilter === "inactive" && status === false);
|
|
||||||
|
|
||||||
return nameMatches;
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
"Sr No.",
|
"Sr No.",
|
||||||
"Date",
|
"Request On",
|
||||||
"Distribution Amount",
|
"Client ID",
|
||||||
"Charges (USD)",
|
"First Name",
|
||||||
"Year",
|
"Last Name",
|
||||||
"Quater",
|
"Country",
|
||||||
"Action",
|
"Phone Number",
|
||||||
|
"Status"
|
||||||
];
|
];
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = deleteHistory?.data?.rows?.map((item, index) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr No.": (
|
"Sr No.": (
|
||||||
<Text
|
<Text
|
||||||
@@ -83,7 +101,7 @@ const DeletionHistory = () => {
|
|||||||
{index + 1}.
|
{index + 1}.
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Date": (
|
"Request On": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -91,10 +109,10 @@ const DeletionHistory = () => {
|
|||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{formatDate(item.date)}
|
{formatDate(item.Requested_on)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Distribution Amount": (
|
"Client ID": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -102,10 +120,10 @@ const DeletionHistory = () => {
|
|||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.Distribution}
|
{item.clientId}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Charges (USD)": (
|
"First Name": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -113,11 +131,11 @@ const DeletionHistory = () => {
|
|||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.charge}
|
{item.firstName}
|
||||||
{/* {formatDate(item.charge)} */}
|
{/* {formatDate(item.charge)} */}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
Year: (
|
"Last Name": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -125,10 +143,10 @@ const DeletionHistory = () => {
|
|||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.year}
|
{item.lastName}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
Quater: (
|
"Country": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -136,18 +154,31 @@ const DeletionHistory = () => {
|
|||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.quarter}
|
{item.country}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
Action: (
|
"Phone Number": (
|
||||||
<Box display={'flex'} justifyContent={'space-around'}>
|
<Text
|
||||||
<Tooltip rounded={'sm'} fontSize={'xs'} label='Accept' bg='#fff' color={'green.500'} placement="left-start">
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
<Button color="green.500" rounded={'sm'} size={'xs'}>
|
as={"span"}
|
||||||
<CheckIcon /></Button></Tooltip>
|
color={"gray.600"}
|
||||||
<Tooltip rounded={'sm'} fontSize={'xs'} label='Reject' bg='#fff' color={'red.500'} placement="left-start">
|
className="d-flex align-items-center web-text-small"
|
||||||
<Button color="red.500" rounded={'sm'} size={'xs'}>
|
fontWeight={'500'}
|
||||||
<CloseIcon /></Button></Tooltip>
|
>
|
||||||
</Box>
|
{item.phoneNumber}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Status": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "center"}
|
||||||
|
as={"span"}
|
||||||
|
color={item?.deletionStatus? "red.500": "blue.500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
|
||||||
|
fontWeight={'600'}
|
||||||
|
>
|
||||||
|
{item.deletionStatus}
|
||||||
|
</Text>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -187,13 +218,13 @@ const DeletionHistory = () => {
|
|||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HStack display={"flex"} alignItems={"center"}>
|
{/* <HStack display={"flex"} alignItems={"center"}>
|
||||||
<Pagination totalItems={10} />
|
<Pagination totalItems={10} />
|
||||||
</HStack>
|
</HStack> */}
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<DataTable
|
<NormalTable
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
|
|||||||
@@ -6,15 +6,20 @@ import {
|
|||||||
HStack,
|
HStack,
|
||||||
Input,
|
Input,
|
||||||
Text,
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
useDisclosure,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
import DataTable from "../../Components/DataTable/DataTable";
|
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||||
import Pagination from "../../Components/Pagination";
|
import Pagination from "../../Components/Pagination";
|
||||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||||
import { formatDate } from "../../Components/Functions/UTCConvertor";
|
import { formatDate } from "../../Components/Functions/UTCConvertor";
|
||||||
|
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
|
||||||
|
import DeletionRequestApprove from "./DeletionRequestApprove";
|
||||||
|
import { useGetDeleteRequestQuery } from "../../Services/delete.request.service";
|
||||||
// import { formatDate } from "../../Components/Functions/UTCConvertor";
|
// import { formatDate } from "../../Components/Functions/UTCConvertor";
|
||||||
|
|
||||||
const DeletionRequest = () => {
|
const DeletionRequest = () => {
|
||||||
@@ -28,6 +33,32 @@ const DeletionRequest = () => {
|
|||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: DeletionLoading
|
||||||
|
} = useGetDeleteRequestQuery()
|
||||||
|
|
||||||
|
|
||||||
|
const {
|
||||||
|
isOpen: isConfirmOpen,
|
||||||
|
onOpen: onConfirmOpen,
|
||||||
|
onClose: onConfirmClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
|
||||||
|
const {
|
||||||
|
isOpen: isRejectOpen,
|
||||||
|
onOpen: onRejectOpen,
|
||||||
|
onClose: onRejectClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Simulate loading
|
// Simulate loading
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
@@ -39,9 +70,9 @@ const DeletionRequest = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ====================================================[Table Filter]================================================================
|
// ====================================================[Table Filter]================================================================
|
||||||
const filteredData = deleteRequest.filter((item) => {
|
const filteredData = data?.data?.rows?.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = item.Distribution;
|
const name = item?.firstName;
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -60,19 +91,21 @@ const DeletionRequest = () => {
|
|||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
"Sr No.",
|
"Sr No.",
|
||||||
"Date",
|
"Requested on",
|
||||||
"Distribution Amount",
|
"Client ID",
|
||||||
"Charges (USD)",
|
"First name",
|
||||||
"Year",
|
"Last name",
|
||||||
"Quater",
|
"Country",
|
||||||
"Amount",
|
"Phone number",
|
||||||
|
"Status",
|
||||||
|
"Action"
|
||||||
];
|
];
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = filteredData?.map((item, index) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr No.": (
|
"Sr No.": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.800"}
|
color={"gray.800"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
@@ -81,74 +114,112 @@ const DeletionRequest = () => {
|
|||||||
{index + 1}.
|
{index + 1}.
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Date": (
|
"Requested on": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{formatDate(item.date)}
|
{formatDate(item?.Requested_on)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Distribution Amount": (
|
"Client ID": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.Distribution}
|
{item?.clientId}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Charges (USD)": (
|
"First name": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.800"}
|
color={"gray.800"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.charge}
|
{item?.firstName}
|
||||||
{/* {formatDate(item.charge)} */}
|
{/* {formatDate(item.charge)} */}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
Year: (
|
"Last name": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.800"}
|
color={"gray.800"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.year}
|
{item?.lastName}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
Quater: (
|
Country: (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.quater}
|
{item?.country}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
|
|
||||||
Amount: (
|
"Phone number": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
fontWeight={'500'}
|
fontWeight={'500'}
|
||||||
>
|
>
|
||||||
{item.amount}
|
{item?.phoneNumber}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
|
Status:(<Box w={"auto"} display={'flex'} alignItems={'center'} isTruncated={true}>
|
||||||
|
<Text
|
||||||
|
as={'span'}
|
||||||
|
fontWeight={"700"}
|
||||||
|
textTransform={"none"}
|
||||||
|
color={item.kycStatus ? "blue.500" : "red.500"}
|
||||||
|
// px={2}
|
||||||
|
py={0.5}
|
||||||
|
variant={'solid'}
|
||||||
|
|
||||||
|
>
|
||||||
|
{item.KYCStatus ? "Completed" : "Not complete"}
|
||||||
|
</Text>
|
||||||
|
</Box>),
|
||||||
|
|
||||||
|
Action: (
|
||||||
|
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||||
|
<Button
|
||||||
|
// colorScheme="forestGreen"
|
||||||
|
// color="green.500"
|
||||||
|
rounded={"sm"}
|
||||||
|
size={"xs"}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
px={2}
|
||||||
|
py={1}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item.id);
|
||||||
|
onConfirmOpen();
|
||||||
|
}}
|
||||||
|
colorScheme="green"
|
||||||
|
variant={"outline"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
>
|
||||||
|
Review
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
@@ -187,17 +258,17 @@ const DeletionRequest = () => {
|
|||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HStack display={"flex"} alignItems={"center"}>
|
{/* <HStack display={"flex"} alignItems={"center"}>
|
||||||
<Pagination totalItems={10} />
|
<Pagination totalItems={10} />
|
||||||
</HStack>
|
</HStack> */}
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<DataTable
|
<NormalTable
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
isLoading={isLoading}
|
isLoading={DeletionLoading}
|
||||||
viewActionId={actionId}
|
viewActionId={actionId}
|
||||||
setViewActionId={setActionId}
|
setViewActionId={setActionId}
|
||||||
// totalPages={10}
|
// totalPages={10}
|
||||||
@@ -213,6 +284,22 @@ const DeletionRequest = () => {
|
|||||||
alertHandler={handleDelete}
|
alertHandler={handleDelete}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<DeletionRequestApprove
|
||||||
|
data={deleteRequest}
|
||||||
|
isOpen={isConfirmOpen}
|
||||||
|
onClose={onConfirmClose}
|
||||||
|
id={actionId}
|
||||||
|
// firstField={firstField}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
{/* <DepositRequestReject
|
||||||
|
isOpen={isRejectOpen}
|
||||||
|
onClose={onRejectClose}
|
||||||
|
id={actionId}
|
||||||
|
/> */}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
207
src/Pages/AccountDeletion/DeletionRequestApprove.jsx
Normal file
207
src/Pages/AccountDeletion/DeletionRequestApprove.jsx
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useGetDepositRequestByIdQuery, useGetDepositRequestQuery, useUpdateDepositRequestMutation } from "../../Services/deposit.request.service";
|
||||||
|
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
|
||||||
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
import { useGetDrawalRequestQuery } from "../../Services/drawal.request.service";
|
||||||
|
import { useApproveDepositRequestMutation, useGetDeleteRequestByIdQuery } from "../../Services/delete.request.service";
|
||||||
|
|
||||||
|
const FILE_TYPES = ["image/jpeg", "image/png", "image/gif"];
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
adminComment: yup.string().notRequired(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestData }) => {
|
||||||
|
const toast = useToast()
|
||||||
|
const [file, setFile] = useState();
|
||||||
|
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||||
|
const [isBtnLoadingReject , setIsBtnLoadingReject] = useState(false)
|
||||||
|
const [isReject , setIsReject] = useState(false)
|
||||||
|
|
||||||
|
const fileredData = requestData?.find((item)=> item?.id === id)
|
||||||
|
const [ updateApproveRequest ] = useApproveDepositRequestMutation()
|
||||||
|
const { data, isLoading } = useGetDeleteRequestByIdQuery(id, {
|
||||||
|
skip: !id,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
reset({
|
||||||
|
comment:fileredData?.comment
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}, [requestData, id])
|
||||||
|
|
||||||
|
const onSubmit = async(data) => {
|
||||||
|
setIsBtnLoading(isReject?false:true)
|
||||||
|
setIsBtnLoadingReject(isReject)
|
||||||
|
const approveReq = {
|
||||||
|
adminComment:data?.adminComment,
|
||||||
|
deletionStatus: isReject?"Reject": "Approved"
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await updateApproveRequest({ id ,data:approveReq })
|
||||||
|
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
}else if(res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const onReject = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
reset({
|
||||||
|
comment: data?.data?.comment,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [data, reset]);
|
||||||
|
|
||||||
|
const heandleOnClose = () =>{
|
||||||
|
reset()
|
||||||
|
onClose()
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
setIsReject(false)
|
||||||
|
setIsBtnLoadingReject(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
{/* <ModalHeader fontSize={"md"}>Confirm</ModalHeader> */}
|
||||||
|
<ModalCloseButton />
|
||||||
|
{isLoading ? (
|
||||||
|
<FullscreenLoaders height={"50vh"} />
|
||||||
|
) : (
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mt={6} mb={4}>
|
||||||
|
<FormLabel fontSize="sm">Investor Comment <Badge colorScheme="green">{fileredData?.currencyCode}</Badge></FormLabel>
|
||||||
|
{/* <Textarea
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="comment"
|
||||||
|
{...register("comment")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="text"
|
||||||
|
size="sm"
|
||||||
|
readOnly
|
||||||
|
rows={5}
|
||||||
|
/>
|
||||||
|
{errors.comment && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comment.message}
|
||||||
|
</Text>
|
||||||
|
)} */}
|
||||||
|
|
||||||
|
|
||||||
|
<Text fontSize="sm" fontWeight={500} color={'gray.600'}>{data?.data?.comment}</Text>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl mb={4} isRequired>
|
||||||
|
<FormLabel fontSize="sm">Admin Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={5}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="adminComment"
|
||||||
|
{...register("adminComment")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="sm"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
{errors.adminComment && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.adminComment.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="red"
|
||||||
|
mr={3}
|
||||||
|
type="submit"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
variant={'ghost'}
|
||||||
|
onClick={()=> setIsReject(true)}
|
||||||
|
isLoading={isBtnLoadingReject}
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeletionRequestApprove;
|
||||||
158
src/Pages/AccountDeletion/DeletionRequestReject.jsx
Normal file
158
src/Pages/AccountDeletion/DeletionRequestReject.jsx
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useDepositRejectMutation } from "../../../Services/deposit.request.service";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
comments: yup.string().required("Comment is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const DeletionRequestReject = ({ isOpen, onClose, firstField ,id}) => {
|
||||||
|
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||||
|
const toast = useToast()
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
const [ depositReject ] = useDepositRejectMutation()
|
||||||
|
const onSubmit = async(data) => {
|
||||||
|
setIsBtnLoading(true)
|
||||||
|
try {
|
||||||
|
const res = await depositReject({ id ,data})
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
onClose();
|
||||||
|
|
||||||
|
}else if(res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
onClose();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const selectedFile = event.target.files[0];
|
||||||
|
setFile(selectedFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const { data, isLoading } =
|
||||||
|
(id, {
|
||||||
|
skip: !id,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
reset({
|
||||||
|
investorAmount: data?.data?.investorAmount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [data, reset]);
|
||||||
|
|
||||||
|
const heandleOnClose = () =>{
|
||||||
|
reset()
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Reject</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
{isLoading ? (
|
||||||
|
<FullscreenLoaders height={"50vh"} />
|
||||||
|
) : (
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4} isRequired>
|
||||||
|
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="comments"
|
||||||
|
{...register("comments")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
{errors.comments && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comments.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeletionRequestReject;
|
||||||
85
src/Pages/AccountDeletion/InvestorComment.jsx
Normal file
85
src/Pages/AccountDeletion/InvestorComment.jsx
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Textarea,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const InvestorComment = ({ isOpen, onClose }) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader fontSize={"md"}></ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<Box as="form">
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={5}>
|
||||||
|
<FormLabel fontSize="sm">Investor Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="fileName"
|
||||||
|
// {...register("fileName")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"The amount of investment is not updated... "}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl mb={4}>
|
||||||
|
<FormLabel fontSize="sm">Admin Commment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="fileName"
|
||||||
|
// {...register("fileName")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter pb={8}>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontWeight={500}
|
||||||
|
>
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InvestorComment;
|
||||||
@@ -5,14 +5,6 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
HStack,
|
HStack,
|
||||||
Input,
|
Input,
|
||||||
Menu,
|
|
||||||
MenuButton,
|
|
||||||
MenuItem,
|
|
||||||
MenuList,
|
|
||||||
Portal,
|
|
||||||
Select,
|
|
||||||
Switch,
|
|
||||||
Tag,
|
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
@@ -22,11 +14,7 @@ import React, { useContext, useEffect, useState, useRef } from "react";
|
|||||||
import { HiDotsVertical } from "react-icons/hi";
|
import { HiDotsVertical } from "react-icons/hi";
|
||||||
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
AddIcon,
|
|
||||||
DeleteIcon,
|
|
||||||
EditIcon,
|
EditIcon,
|
||||||
EmailIcon,
|
|
||||||
ViewIcon,
|
|
||||||
} from "@chakra-ui/icons";
|
} from "@chakra-ui/icons";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import DataTable from "../../../Components/DataTable/DataTable";
|
import DataTable from "../../../Components/DataTable/DataTable";
|
||||||
@@ -36,6 +24,7 @@ import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
|||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import { debounce } from "../../Master/Sponser/AddSponser";
|
import { debounce } from "../../Master/Sponser/AddSponser";
|
||||||
import { useGetBankQuery } from "../../../Services/bank.details.service";
|
import { useGetBankQuery } from "../../../Services/bank.details.service";
|
||||||
|
import NormalTable from '../../../Components/DataTable/NormalTable'
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
@@ -116,7 +105,7 @@ const BankDetails = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item) => ({
|
const extractedArray = filteredData?.map((item,index) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr N/O": (
|
"Sr N/O": (
|
||||||
<Text
|
<Text
|
||||||
@@ -131,14 +120,14 @@ const BankDetails = () => {
|
|||||||
"Country name": (
|
"Country name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.country_xid}
|
{item?.country?.countryName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Account Name": (
|
"Account Name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.accountName}
|
{item?.accountName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
@@ -157,16 +146,17 @@ const BankDetails = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Action: (
|
Action: (
|
||||||
<Box display={"flex"} justifyContent={"space-between"} gap={2}>
|
<Box display={"flex"} justifyContent={"space-between"}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
label="View"
|
label="Edit"
|
||||||
bg="#fff"
|
bg="#fff"
|
||||||
color={"green.500"}
|
color={"green.500"}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
|
bg={index % 2 === 0 ? "#6311cb14" : "#fff"}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(`/bank-details/edit-bank-details/${item.id}`);
|
navigate(`/bank-details/edit-bank-details/${item.id}`);
|
||||||
}}
|
}}
|
||||||
@@ -227,8 +217,8 @@ const BankDetails = () => {
|
|||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<DataTable
|
<NormalTable
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Details`}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import { Box, useToast } from "@chakra-ui/react";
|
import { Box, useToast } from "@chakra-ui/react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -10,7 +10,8 @@ import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
|||||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
import SwitchButton from "../../../Components/SwitchButton";
|
import SwitchButton from "../../../Components/SwitchButton";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { useGetBankQuery, useUpdateBankDetailsMutation } from "../../../Services/bank.details.service";
|
import { useGetBankDetailsQuery,useUpdateBankDetailsMutation } from "../../../Services/bank.details.service";
|
||||||
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
// import { useUpdateBankDetailsMutation, useGetBankQuery } from "../../../Services/investorDetails.service";
|
// import { useUpdateBankDetailsMutation, useGetBankQuery } from "../../../Services/investorDetails.service";
|
||||||
|
|
||||||
const editBankSchema = yup.object().shape({
|
const editBankSchema = yup.object().shape({
|
||||||
@@ -28,12 +29,17 @@ const EditBankDetails = () => {
|
|||||||
const id = params?.id;
|
const id = params?.id;
|
||||||
|
|
||||||
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
|
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
|
||||||
|
const { InvestorDetails, setInvestorDetails, slideFromRight } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
const [alert, setAlert] = useState(false);
|
const [alert, setAlert] = useState(false);
|
||||||
const [form, setForm] = useState({});
|
const [form, setForm] = useState({});
|
||||||
const [isSwitchOn, setIsSwitchOn] = useState(false);
|
const [isSwitchOn, setIsSwitchOn] = useState(false);
|
||||||
|
|
||||||
const [updateBankDetails] = useUpdateBankDetailsMutation();
|
const [updateBankDetails] = useUpdateBankDetailsMutation();
|
||||||
const { data: bankDetails, error, isLoading } = useGetBankQuery({ id }, { skip: !id });
|
const { data: bankDetails, error, isLoading, refetch } = useGetBankDetailsQuery({ id }, { skip: !id });
|
||||||
|
|
||||||
|
console.log(bankDetails);
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
@@ -45,16 +51,22 @@ const EditBankDetails = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (bankDetails) {
|
setInvestorDetails({
|
||||||
|
...bankDetails?.data,
|
||||||
|
});
|
||||||
|
// refetch()
|
||||||
|
if (bankDetails?.data) {
|
||||||
reset({
|
reset({
|
||||||
accountNumber: bankDetails.accountNumber,
|
accountName: bankDetails?.data?.accountName,
|
||||||
swiftCode: bankDetails.swiftCode,
|
countryName: bankDetails?.data?.countryName,
|
||||||
bankName: bankDetails.bankName,
|
accountNumber: bankDetails?.data?.accountNumber,
|
||||||
bankAddress: bankDetails.bankAddress,
|
swiftCode: bankDetails?.data?.swiftCode,
|
||||||
IBANnumber: bankDetails.IBANnumber,
|
bankName: bankDetails?.data?.bankName,
|
||||||
|
bankAddress: bankDetails?.data?.bankAddress,
|
||||||
|
IBANnumber: bankDetails?.data?.IBANnumber,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [bankDetails, reset]);
|
}, [bankDetails, reset,id]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <FullscreenLoaders />;
|
return <FullscreenLoaders />;
|
||||||
@@ -62,7 +74,6 @@ const EditBankDetails = () => {
|
|||||||
|
|
||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
setIsLoadingBtn(true);
|
setIsLoadingBtn(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const formData = {
|
const formData = {
|
||||||
...form,
|
...form,
|
||||||
@@ -77,6 +88,7 @@ const EditBankDetails = () => {
|
|||||||
|
|
||||||
setIsLoadingBtn(false);
|
setIsLoadingBtn(false);
|
||||||
setAlert(false);
|
setAlert(false);
|
||||||
|
refetch()
|
||||||
navigate("/bank-details");
|
navigate("/bank-details");
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Something went wrong");
|
throw new Error("Something went wrong");
|
||||||
@@ -91,66 +103,76 @@ const EditBankDetails = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(bankDetails?.accountNumber);
|
||||||
|
|
||||||
|
|
||||||
const formEditFields = [
|
const formEditFields = [
|
||||||
{
|
// {
|
||||||
label: "Country Name",
|
// label: "Country Name",
|
||||||
placeHolder: "Enter country name",
|
// placeHolder:"",
|
||||||
name: "countryName",
|
// name: "countryName",
|
||||||
type: "text",
|
// type: "text",
|
||||||
isRequired: true,
|
// isRequired: true,
|
||||||
section: "Add Details",
|
// section: "Add Details",
|
||||||
maxLength: 50,
|
// maxLength: 50,
|
||||||
width: "32%",
|
// width: "32%",
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
label: "Account Name",
|
label: "Account Name",
|
||||||
|
// value:bankDetails?.accountName,
|
||||||
name: "accountName",
|
name: "accountName",
|
||||||
placeHolder: "Enter account name",
|
placeHolder: "",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section: "Add Details",
|
||||||
maxLength: 255,
|
// maxLength: 255,
|
||||||
width: "32%",
|
width: "32%",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Account Number *",
|
label: "Account Number",
|
||||||
name: "accountNumber",
|
name: "accountNumber",
|
||||||
placeHolder: "Enter account number",
|
placeHolder: "",
|
||||||
type: "text",
|
type: "text",
|
||||||
section: "Add Details",
|
section: "Add Details",
|
||||||
width: "32%",
|
width: "32%",
|
||||||
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "IBAN Number",
|
label: "IBAN Number",
|
||||||
name: "IBANnumber",
|
name: "IBANnumber",
|
||||||
placeHolder: "Enter IBAN number",
|
placeHolder: "",
|
||||||
type: "text",
|
type: "text",
|
||||||
section: "Add Details",
|
section: "Add Details",
|
||||||
width: "32%",
|
width: "32%",
|
||||||
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "SWIFT Code",
|
label: "SWIFT Code",
|
||||||
|
value: bankDetails?.data?.swiftCode,
|
||||||
name: "swiftCode",
|
name: "swiftCode",
|
||||||
placeHolder: "Enter SWIFT code",
|
placeHolder: "",
|
||||||
type: "text",
|
type: "text",
|
||||||
section: "Add Details",
|
section: "Add Details",
|
||||||
width: "32%",
|
width: "32%",
|
||||||
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Bank Name",
|
label: "Bank Name",
|
||||||
name: "bankName",
|
name: "bankName",
|
||||||
placeHolder: "Enter bank name",
|
placeHolder: "",
|
||||||
type: "text",
|
type: "text",
|
||||||
section: "Add Details",
|
section: "Add Details",
|
||||||
width: "32%",
|
width: "32%",
|
||||||
|
isRequired: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Bank Address",
|
label: "Bank Address",
|
||||||
name: "bankAddress",
|
name: "bankAddress",
|
||||||
placeHolder: "Enter bank address",
|
placeHolder: "",
|
||||||
type: "text",
|
type: "text",
|
||||||
section: "Add Details",
|
section: "Add Details",
|
||||||
width: "32%",
|
width: "32%",
|
||||||
|
isRequired: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -163,7 +185,7 @@ const EditBankDetails = () => {
|
|||||||
return groups;
|
return groups;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const onSubmit = (data) => {
|
const onSubmit = async(data) => {
|
||||||
if (!Object.keys(errors).length) {
|
if (!Object.keys(errors).length) {
|
||||||
setForm(data);
|
setForm(data);
|
||||||
setAlert(true);
|
setAlert(true);
|
||||||
|
|||||||
@@ -20,14 +20,35 @@ import { v4 as uuidv4 } from "uuid";
|
|||||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
import FormInputMain from "../../Components/FormInputMain";
|
import FormInputMain from "../../Components/FormInputMain";
|
||||||
import { useGetContactQuery, useUpdateContactMutation } from "../../Services/contact.service";
|
import {
|
||||||
|
useGetContactQuery,
|
||||||
|
useUpdateContactMutation,
|
||||||
|
} from "../../Services/contact.service";
|
||||||
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
|
||||||
import ToastBox from "../../Components/ToastBox";
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
|
||||||
export const addSponser = yup.object().shape({
|
export const addSponser = yup.object().shape({
|
||||||
phoneNumber: yup.string().required("Phone Number is required"),
|
phoneNumber: yup
|
||||||
emailAddress: yup.string().required("E-mail ID is required"),
|
.string()
|
||||||
websiteUrl: yup.string().required("Website URL is required"),
|
.required("Phone Number is required"),
|
||||||
|
// .matches(
|
||||||
|
// /^\+?[1-9]\d{1,14}$/,
|
||||||
|
// "Phone Number must include a valid ISD code and be in E.164 format"
|
||||||
|
// ),
|
||||||
|
emailAddress: yup
|
||||||
|
.string()
|
||||||
|
.required("E-mail ID is required")
|
||||||
|
.matches(
|
||||||
|
/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
||||||
|
"Invalid email address"
|
||||||
|
),
|
||||||
|
websiteUrl: yup
|
||||||
|
.string()
|
||||||
|
.required("Website URL is required")
|
||||||
|
.matches(
|
||||||
|
/^(https?:\/\/)?([\w.-]+)+(:\d+)?(\/[\w.-]*)*\/?$/,
|
||||||
|
"Invalid URL format"
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function debounce(func, delay) {
|
export function debounce(func, delay) {
|
||||||
@@ -39,10 +60,10 @@ export function debounce(func, delay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Contact = () => {
|
const Contact = () => {
|
||||||
const toast = useToast()
|
const toast = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [form, setForm] = useState({});
|
const [form, setForm] = useState({});
|
||||||
const [ isLoading, setIsLoading ] = useState(false)
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
// const { sponser, setSponser } = useContext(GlobalStateContext);
|
// const { sponser, setSponser } = useContext(GlobalStateContext);
|
||||||
const {
|
const {
|
||||||
@@ -52,16 +73,17 @@ const Contact = () => {
|
|||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm({
|
} = useForm({
|
||||||
resolver: yupResolver(addSponser),
|
resolver: yupResolver(addSponser),
|
||||||
|
// mode: all
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(errors);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: contact,
|
data: contact,
|
||||||
isLoading: contactLoading,
|
isLoading: contactLoading,
|
||||||
error,
|
error,
|
||||||
} = useGetContactQuery();
|
} = useGetContactQuery();
|
||||||
const [ updateContact ] = useUpdateContactMutation()
|
const [updateContact] = useUpdateContactMutation();
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (contact) {
|
if (contact) {
|
||||||
@@ -84,7 +106,7 @@ const Contact = () => {
|
|||||||
name: "phoneNumber",
|
name: "phoneNumber",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section:"",
|
||||||
// value: contact?.phoneNumber || "",
|
// value: contact?.phoneNumber || "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -93,7 +115,7 @@ const Contact = () => {
|
|||||||
placeHolder: " ",
|
placeHolder: " ",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section:"",
|
||||||
// value: contact?.emailAddress || "",
|
// value: contact?.emailAddress || "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -102,7 +124,7 @@ const Contact = () => {
|
|||||||
placeHolder: " ",
|
placeHolder: " ",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section:"",
|
||||||
// value: contact?.websiteUrl || "",
|
// value: contact?.websiteUrl || "",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -117,24 +139,20 @@ const Contact = () => {
|
|||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const onSubmit = async (data) => {
|
const onSubmit = async (data) => {
|
||||||
setIsLoading(true)
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await updateContact(data)
|
const res = await updateContact(data);
|
||||||
if (res?.data?.statusCode === 200) {
|
if (res?.data?.statusCode === 200) {
|
||||||
toast({
|
toast({
|
||||||
render: () => <ToastBox message={res?.data?.message} />,
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
});
|
});
|
||||||
setIsLoading(false)
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
||||||
setIsLoading(false)
|
setIsLoading(false);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
360
src/Pages/Admin/Investor/BankInvestor/BankInvestor.jsx
Normal file
360
src/Pages/Admin/Investor/BankInvestor/BankInvestor.jsx
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||||
|
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
|
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||||
|
import { debounce } from "../../../Master/Sponser/AddSponser";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||||
|
import NormalTable from "../../../../Components/DataTable/NormalTable";
|
||||||
|
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||||
|
import Pagination from "../../../../Components/Pagination";
|
||||||
|
import ToastBox from "../../../../Components/ToastBox";
|
||||||
|
import ReasonBanModal from "./ReasonBanModal";
|
||||||
|
import { useGetbanInvestorQuery } from "../../../../Services/ban.investor.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../../../Constants/Paginations";
|
||||||
|
|
||||||
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
|
const BankInvestor = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const toast = useToast();
|
||||||
|
const thirdField = useRef();
|
||||||
|
const { bankInvestor, setBankInvestor, slideFromRight } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
const { isOpen: isOpen, onOpen: onOpen, onClose: onClose } = useDisclosure();
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const [status, setStatus] = useState("");
|
||||||
|
const [kyc, setKyc] = useState("");
|
||||||
|
const [country, setCountry] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: unbanLoading,
|
||||||
|
error,
|
||||||
|
refetch,
|
||||||
|
} = useGetbanInvestorQuery(
|
||||||
|
{
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
KYCStatus: kyc,
|
||||||
|
country_xid: country,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Simulate loading
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Cleanup the timer on component unmount
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr N/O",
|
||||||
|
"Date",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"Country",
|
||||||
|
"Phone Number",
|
||||||
|
"E-mail ID",
|
||||||
|
"KYC Status",
|
||||||
|
"Action",
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleUpdateStatus = debounce((id) => {
|
||||||
|
setBankInvestor((prevData) =>
|
||||||
|
prevData.map((bankInvestor) =>
|
||||||
|
bankInvestor.id === id ? { ...bankInvestor } : bankInvestor
|
||||||
|
)
|
||||||
|
);
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
// ====================================================[Table Filter]================================================================
|
||||||
|
const filteredData = data?.data?.rows?.filter((item) => {
|
||||||
|
// Filter by name (case insensitive)
|
||||||
|
const name = item?.clientReference_id;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
// Filter by status
|
||||||
|
// const status = item.status;
|
||||||
|
// const statusLower = status ? "active" : "inactive";
|
||||||
|
|
||||||
|
// const statusMatches =
|
||||||
|
// statusFilter === "all" ||
|
||||||
|
// (statusFilter === "active" && status === true) ||
|
||||||
|
// (statusFilter === "inactive" && status === false);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
|
const extractedArray = data?.data?.rows?.map((item) => ({
|
||||||
|
id: item?.id,
|
||||||
|
"Sr N/O": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{item.id}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
Date: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{formatDate(item?.date)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Country: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.country}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.phoneNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"KYC Status": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Badge
|
||||||
|
fontWeight={"500"}
|
||||||
|
textTransform={"none"}
|
||||||
|
color={item?.KYCStatus === false ? "red" : "blue"}
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
variant={"ghost"}
|
||||||
|
>
|
||||||
|
{item?.KYCStatus === true ? "Completed" : "Incompleted"}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Action: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Badge
|
||||||
|
cursor={"pointer"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
textTransform={"none"}
|
||||||
|
colorScheme={"red"}
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item?.id);
|
||||||
|
onOpen();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Ban Investor
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log(extractedArray);
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
const updatedInvestorDetails = InvestorDetails.filter(
|
||||||
|
(sponsor) => sponsor.id !== actionId
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setInvestorDetails(updatedInvestorDetails);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 100);
|
||||||
|
setIsLoading(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (id) => {
|
||||||
|
setActionId(id);
|
||||||
|
onEditOpen();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
mt={1}
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<HStack display={"flex"} alignItems={"center"}>
|
||||||
|
{/* <Select
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setStatus(e.target.value)}
|
||||||
|
value={status}
|
||||||
|
>
|
||||||
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
|
Status
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="">Status</option>
|
||||||
|
<option value="0">Ban</option>
|
||||||
|
<option value="1">UnBan</option>
|
||||||
|
</Select> */}
|
||||||
|
|
||||||
|
<Select
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setKyc(e.target.value)}
|
||||||
|
value={kyc}
|
||||||
|
>
|
||||||
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
|
KYC Status
|
||||||
|
</option>
|
||||||
|
<option value="">KYC Status</option>
|
||||||
|
<option value="0">Incompleted</option>
|
||||||
|
<option value="1">Completed</option>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setCountry(e.target.value)}
|
||||||
|
value={country}
|
||||||
|
>
|
||||||
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
|
Country
|
||||||
|
</option>
|
||||||
|
<option value="">All</option>
|
||||||
|
<option value="1">Behrain</option>
|
||||||
|
<option value="2">Kuwait</option>
|
||||||
|
<option value="3">Oman</option>
|
||||||
|
<option value="4">Qatar</option>
|
||||||
|
<option value="5">Saudi arabia</option>
|
||||||
|
<option value="6">United arab emirates</option>
|
||||||
|
</Select>
|
||||||
|
</HStack>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<NormalTable
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
isLoading={isLoading}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<ReasonBanModal isOpen={isOpen} onClose={onClose} id={actionId} />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BankInvestor;
|
||||||
27
src/Pages/Admin/Investor/BankInvestor/Investor.jsx
Normal file
27
src/Pages/Admin/Investor/BankInvestor/Investor.jsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react";
|
||||||
|
import React from "react";
|
||||||
|
import BankInvestor from "./BankInvestor";
|
||||||
|
import UnbanInvestor from "../UnbanInvestor/UnbanInvestor";
|
||||||
|
|
||||||
|
const Investor = () => {
|
||||||
|
return (
|
||||||
|
<Box overflowY={"scroll"} height={"100vh"}>
|
||||||
|
<Tabs colorScheme="green" mt={3}>
|
||||||
|
<TabList>
|
||||||
|
<Tab fontSize={"sm"}>Unban Investor</Tab>
|
||||||
|
<Tab fontSize={"sm"}>Ban Investor</Tab>
|
||||||
|
</TabList>
|
||||||
|
<TabPanels>
|
||||||
|
<TabPanel>
|
||||||
|
<UnbanInvestor />
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel>
|
||||||
|
<BankInvestor />
|
||||||
|
</TabPanel>
|
||||||
|
</TabPanels>
|
||||||
|
</Tabs>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Investor;
|
||||||
143
src/Pages/Admin/Investor/BankInvestor/ReasonBanModal.jsx
Normal file
143
src/Pages/Admin/Investor/BankInvestor/ReasonBanModal.jsx
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import ToastBox from "../../../../Components/ToastBox";
|
||||||
|
import { useDepositRejectMutation } from "../../../../Services/drawal.request.service";
|
||||||
|
import { useUpdateBanMutation } from "../../../../Services/ban.investor.service";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
comments: yup.string().required("Comment is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const ReasonBanModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||||
|
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ updateBanMutation ] = useUpdateBanMutation()
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = async(data) => {
|
||||||
|
setIsBtnLoading(true)
|
||||||
|
try {
|
||||||
|
const res = await updateBanMutation({ id ,data})
|
||||||
|
console.log(res);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
|
||||||
|
}else if(res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const heandleOnClose = () =>{
|
||||||
|
reset()
|
||||||
|
onClose()
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Reason for Unban</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4} isRequired>
|
||||||
|
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="comments"
|
||||||
|
{...register("comments")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
{errors.comments && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comments.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
fontWeight={400}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReasonBanModal;
|
||||||
|
|
||||||
147
src/Pages/Admin/Investor/UnbanInvestor/ReasonBanModal.jsx
Normal file
147
src/Pages/Admin/Investor/UnbanInvestor/ReasonBanModal.jsx
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import ToastBox from "../../../../Components/ToastBox";
|
||||||
|
import { useDepositRejectMutation } from "../../../../Services/drawal.request.service";
|
||||||
|
import { useUpdateBanMutation, useUpdateUnbanMutation } from "../../../../Services/ban.investor.service";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
comments: yup.string().required("Comment is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const ReasonBanModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||||
|
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ updateBan ] = useUpdateUnbanMutation()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = async(data) => {
|
||||||
|
console.log(data);
|
||||||
|
setIsBtnLoading(true)
|
||||||
|
try {
|
||||||
|
const res = await updateBan({ id ,data})
|
||||||
|
console.log(res);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
|
||||||
|
}else if(res?.data) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const heandleOnClose = () =>{
|
||||||
|
reset()
|
||||||
|
onClose()
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Reason for Ban</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4} isRequired>
|
||||||
|
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="comments"
|
||||||
|
{...register("comments")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
{errors.comments && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comments.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
fontWeight={400}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReasonBanModal;
|
||||||
|
|
||||||
352
src/Pages/Admin/Investor/UnbanInvestor/UnbanInvestor.jsx
Normal file
352
src/Pages/Admin/Investor/UnbanInvestor/UnbanInvestor.jsx
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Text,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||||
|
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
|
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||||
|
import { debounce } from "../../../Master/Sponser/AddSponser";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||||
|
import DataTable from "../../../../Components/DataTable/NormalTable";
|
||||||
|
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||||
|
import Pagination from "../../../../Components/Pagination";
|
||||||
|
import ToastBox from "../../../../Components/ToastBox";
|
||||||
|
import ReasonBanModal from "./ReasonBanModal";
|
||||||
|
import {
|
||||||
|
useGetInvestorQuery,
|
||||||
|
useGetUnbanInvestorQuery,
|
||||||
|
} from "../../../../Services/ban.investor.service";
|
||||||
|
import { generateSerialNumber } from "../../../../Constants/Constants";
|
||||||
|
import { TABLE_PAGINATION } from "../../../../Constants/Paginations";
|
||||||
|
|
||||||
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
|
const UnbanInvestor = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const toast = useToast();
|
||||||
|
const thirdField = useRef();
|
||||||
|
const { bankInvestor, setBankInvestor, slideFromRight } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState("");
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
const { isOpen: isOpen, onOpen: onOpen, onClose: onClose } = useDisclosure();
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const [status, setStatus] = useState("");
|
||||||
|
const [kyc, setKyc] = useState("");
|
||||||
|
const [country, setCountry] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: unbanLoading,
|
||||||
|
error,
|
||||||
|
refetch,
|
||||||
|
} = useGetUnbanInvestorQuery(
|
||||||
|
{
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
searchTerm: debouncedSearchTerm,
|
||||||
|
KYCStatus: kyc,
|
||||||
|
country_xid: country,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Simulate loading
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Cleanup the timer on component unmount
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr N/O",
|
||||||
|
"Date",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"Country",
|
||||||
|
"Phone Number",
|
||||||
|
"E-mail ID",
|
||||||
|
"KYC Status",
|
||||||
|
"Action",
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleUpdateStatus = debounce((id) => {
|
||||||
|
setBankInvestor((prevData) =>
|
||||||
|
prevData.map((bankInvestor) =>
|
||||||
|
bankInvestor.id === id ? { ...bankInvestor } : bankInvestor
|
||||||
|
)
|
||||||
|
);
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
// ====================================================[Table Filter]================================================================
|
||||||
|
const filteredData = data?.data?.rows?.filter((item) => {
|
||||||
|
// Filter by name (case insensitive)
|
||||||
|
const name = item?.clientReference_id;
|
||||||
|
const searchLower = searchTerm?.toLowerCase();
|
||||||
|
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
|
const extractedArray = data?.data?.rows?.map((item, index) => ({
|
||||||
|
id: item?.id,
|
||||||
|
"Sr N/O": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{generateSerialNumber(index, currentPage, pageSize)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
Date: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{formatDate(item?.date)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Country: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.country}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.phoneNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"KYC Status": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Badge
|
||||||
|
fontWeight={"500"}
|
||||||
|
textTransform={"none"}
|
||||||
|
color={item?.KYCStatus === false ? "red" : "blue"}
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
variant={"ghost"}
|
||||||
|
>
|
||||||
|
{item?.KYCStatus === true ? "Completed" : "Incompleted"}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Action: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Badge
|
||||||
|
cursor={"pointer"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
textTransform={"none"}
|
||||||
|
colorScheme={"red"}
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item?.id);
|
||||||
|
onOpen();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Ban Investor
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
const updatedInvestorDetails = InvestorDetails.filter(
|
||||||
|
(sponsor) => sponsor.id !== actionId
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setInvestorDetails(updatedInvestorDetails);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 100);
|
||||||
|
setIsLoading(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (id) => {
|
||||||
|
setActionId(id);
|
||||||
|
onEditOpen();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
mt={1}
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
<HStack display={"flex"} alignItems={"center"}>
|
||||||
|
{/* <Select
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setStatus(e.target.value)}
|
||||||
|
value={status}
|
||||||
|
>
|
||||||
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
|
Status
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="">Status</option>
|
||||||
|
<option value="0">Ban</option>
|
||||||
|
<option value="1">UnBan</option>
|
||||||
|
</Select> */}
|
||||||
|
|
||||||
|
<Select
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setKyc(e.target.value)}
|
||||||
|
value={kyc}
|
||||||
|
>
|
||||||
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
|
KYC Status
|
||||||
|
</option>
|
||||||
|
<option value="">KYC Status</option>
|
||||||
|
<option value="0">Incompleted</option>
|
||||||
|
<option value="1">Completed</option>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setCountry(e.target.value)}
|
||||||
|
value={country}
|
||||||
|
>
|
||||||
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
|
Country
|
||||||
|
</option>
|
||||||
|
<option value="">All</option>
|
||||||
|
<option value="1">Behrain</option>
|
||||||
|
<option value="2">Kuwait</option>
|
||||||
|
<option value="3">Oman</option>
|
||||||
|
<option value="4">Qatar</option>
|
||||||
|
<option value="5">Saudi arabia</option>
|
||||||
|
<option value="6">United arab emirates</option>
|
||||||
|
</Select>
|
||||||
|
</HStack>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<DataTable
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
isLoading={isLoading}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<ReasonBanModal isOpen={isOpen} onClose={onClose} id={actionId} />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UnbanInvestor;
|
||||||
@@ -1,22 +1,342 @@
|
|||||||
import { Box, Image, Text } from "@chakra-ui/react"
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
// import error from "../assets/Error.svg"
|
import {
|
||||||
import robot from "../../assets/robot.png"
|
Badge,
|
||||||
// import robot from "../assets/robot.png"
|
Box,
|
||||||
const Notification = () => {
|
Button,
|
||||||
return (
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import { useForm} from "react-hook-form";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
import FormInputMain from "../../Components/FormInputMain";
|
||||||
|
import {
|
||||||
|
useGetContactQuery,
|
||||||
|
useSendNotificationMutation,
|
||||||
|
useUpdateContactMutation,
|
||||||
|
} from "../../Services/contact.service";
|
||||||
|
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
|
||||||
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||||
|
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||||
|
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||||
|
import { formatDate, generateSerialNumber } from "../../Constants/Constants";
|
||||||
|
import { ViewIcon } from "@chakra-ui/icons";
|
||||||
|
import { useGetUnbanInvestorQuery } from "../../Services/ban.investor.service";
|
||||||
|
|
||||||
<Box
|
export const notification = yup.object().shape({
|
||||||
h={'100vh'}
|
title: yup
|
||||||
display={'flex'}
|
.string()
|
||||||
justifyContent={'center'}
|
.required("Investment Name is required"),
|
||||||
alignItems={'center'}
|
ManualDate: yup
|
||||||
flexDirection={'column'}
|
.date()
|
||||||
gap={8}
|
.required("Manual Date is required")
|
||||||
>
|
.typeError("Invalid date format"),
|
||||||
<Image src={robot} w={"171px"} />
|
ManualTime: yup
|
||||||
{/* <Text color={'green.800'} as={'span'} fontSize={'small'}>The requested URL was not found on this server.</Text> */}
|
.string()
|
||||||
</Box>
|
.required("Manual Time is required")
|
||||||
)
|
.matches(
|
||||||
|
/^([01]\d|2[0-3]):?([0-5]\d)$/,
|
||||||
|
"Invalid time format, must be in HH:mm"
|
||||||
|
),
|
||||||
|
expectedReturn: yup
|
||||||
|
.string()
|
||||||
|
.required("Expected Return is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const notificationNew = yup.object().shape({
|
||||||
|
title: yup
|
||||||
|
.string()
|
||||||
|
.required("Investment Name is required"),
|
||||||
|
message: yup
|
||||||
|
.string()
|
||||||
|
.required("Message is required"),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Notification = () => {
|
||||||
|
const toast = useToast();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [form, setForm] = useState({});
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [ selectedRadio, setSelectedRadio] = useState([])
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
reset,
|
||||||
|
watch,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(notificationNew),
|
||||||
|
|
||||||
|
defaultValues: {
|
||||||
|
title: '',
|
||||||
|
message: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(errors);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: contact,
|
||||||
|
isLoading: contactLoading,
|
||||||
|
error,
|
||||||
|
} = useGetContactQuery();
|
||||||
|
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// const {
|
||||||
|
// data: investorDetails,
|
||||||
|
// isLoading: investorDetailsLoading,
|
||||||
|
// // error,
|
||||||
|
// } = useGetInvestorsQuery({ page: currentPage, size: pageSize });
|
||||||
|
|
||||||
|
|
||||||
|
const {
|
||||||
|
data : investorDetails,
|
||||||
|
isLoading: investorDetailsLoading,
|
||||||
|
refetch,
|
||||||
|
} = useGetUnbanInvestorQuery({
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
});;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
console.log(investorDetails);
|
||||||
|
|
||||||
|
|
||||||
|
const [sendNotification] = useSendNotificationMutation();
|
||||||
|
|
||||||
|
|
||||||
|
if (contactLoading) {
|
||||||
|
return <FullscreenLoaders />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Notification
|
const formFields = [
|
||||||
|
{
|
||||||
|
label: "Notification Header",
|
||||||
|
placeHolder: " ",
|
||||||
|
name: "title",
|
||||||
|
type: "text",
|
||||||
|
width:"100%",
|
||||||
|
maxLength:100,
|
||||||
|
helperText:`Maximum length should be 100 characters. You have entered ${watch()?.title?.length || 0} characters.`,
|
||||||
|
isRequired: true,
|
||||||
|
section: "Send Custom Push Notification",
|
||||||
|
// value: contact?.phoneNumber || "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Notification Message",
|
||||||
|
placeHolder: " ",
|
||||||
|
name: "message",
|
||||||
|
width:"100%",
|
||||||
|
type: "textarea",
|
||||||
|
isRequired: true,
|
||||||
|
maxLength:200,
|
||||||
|
helperText:`Maximum length should be 200 characters. You have entered ${watch()?.message?.length || 0} characters.`,
|
||||||
|
section: "Send Custom Push Notification",
|
||||||
|
// value: contact?.phoneNumber || "",
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
const groupedFields = formFields.reduce((groups, field) => {
|
||||||
|
const { section } = field;
|
||||||
|
if (!groups[section]) {
|
||||||
|
groups[section] = [];
|
||||||
|
}
|
||||||
|
groups[section].push(field);
|
||||||
|
return groups;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const onSubmit = async (data) => {
|
||||||
|
|
||||||
|
const dataToPass = {
|
||||||
|
...data,
|
||||||
|
principal_xid:selectedRadio
|
||||||
|
}
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await sendNotification(dataToPass);
|
||||||
|
console.log(res);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false)
|
||||||
|
}else if(res?.data){
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false)
|
||||||
|
setSelectedRadio([])
|
||||||
|
reset({
|
||||||
|
title: '', // Resetting specific fields
|
||||||
|
message: '',
|
||||||
|
}); // Clears the form fields
|
||||||
|
}else{
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={'error'} message={"Something went wrong"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr N/O",
|
||||||
|
"Date",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"Country",
|
||||||
|
"Phone Number",
|
||||||
|
"E-mail ID",
|
||||||
|
"KYC Status",
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||||
|
id: item?.principal_xid,
|
||||||
|
"Sr N/O": (
|
||||||
|
<Text
|
||||||
|
justifyContent={"left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
Date: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{formatDate(item?.date)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Country: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.country}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.phoneNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"KYC Status": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Badge
|
||||||
|
fontWeight={"500"}
|
||||||
|
textTransform={"none"}
|
||||||
|
color={item?.KYCStatus === false ? "red" : "blue"}
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
variant={'ghost'}
|
||||||
|
>
|
||||||
|
{item?.KYCStatus === true ? "Completed" : "Incompleted"}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
||||||
|
<FormInputMain
|
||||||
|
groupedFields={groupedFields}
|
||||||
|
control={control}
|
||||||
|
errors={errors}
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
btnLoading={isLoading}
|
||||||
|
>
|
||||||
|
<Box overflow={'scroll'} h={'58vh'}>
|
||||||
|
<NormalTable
|
||||||
|
centered={true}
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
// isLoading={isLoading}
|
||||||
|
setSelectedRadio={setSelectedRadio}
|
||||||
|
selectedRadio={selectedRadio}
|
||||||
|
showRadioButton={true}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</FormInputMain>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Notification;
|
||||||
|
|||||||
@@ -1,22 +1,241 @@
|
|||||||
import { Box, Image, Text } from "@chakra-ui/react"
|
import {
|
||||||
// import error from "../assets/Error.svg"
|
Box,
|
||||||
import robot from "../../assets/robot.png"
|
Button,
|
||||||
// import robot from "../assets/robot.png"
|
HStack,
|
||||||
|
Input,
|
||||||
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||||
|
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
|
import {EditIcon,} from "@chakra-ui/icons";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
import DataTable from "../../Components/DataTable/NormalTable";
|
||||||
|
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||||
|
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||||
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
import { debounce } from "./Contact";
|
||||||
|
|
||||||
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
const Users = () => {
|
const Users = () => {
|
||||||
return (
|
const navigate = useNavigate();
|
||||||
|
const toast = useToast();
|
||||||
|
const thirdField = useRef();
|
||||||
|
const { users, setUsers, slideFromRight } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
// const {
|
||||||
|
// isOpen: isEditOpen,
|
||||||
|
// onOpen: onEditOpen,
|
||||||
|
// onClose: onEditClose,
|
||||||
|
// } = useDisclosure();
|
||||||
|
|
||||||
<Box
|
const btnRef = React.useRef();
|
||||||
h={'100vh'}
|
|
||||||
display={'flex'}
|
// const {
|
||||||
justifyContent={'center'}
|
// data: bankDetails,
|
||||||
alignItems={'center'}
|
// isLoading: bankDetailsLoading,
|
||||||
flexDirection={'column'}
|
// error,
|
||||||
gap={8}
|
// } = useGetBankQuery({ page: 1, size: 10 });
|
||||||
>
|
|
||||||
<Image src={robot} w={"171px"} />
|
|
||||||
{/* <Text color={'green.800'} as={'span'} fontSize={'small'}>The requested URL was not found on this server.</Text> */}
|
useEffect(() => {
|
||||||
</Box>
|
// Simulate loading
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Cleanup the timer on component unmount
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr N/O",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"E-mail ID",
|
||||||
|
"Role",
|
||||||
|
"Phone Number",
|
||||||
|
"Action",
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleUpdateStatus = debounce((id) => {
|
||||||
|
setUsers((prevData) =>
|
||||||
|
prevData.map((users) =>
|
||||||
|
users.id === id ? { ...users } : users
|
||||||
)
|
)
|
||||||
}
|
);
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
|
||||||
export default Users
|
// ====================================================[Table Filter]================================================================
|
||||||
|
const filteredData = users?.data?.filter((item) => {
|
||||||
|
// Filter by name (case insensitive)
|
||||||
|
const name = item.emailID;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
// Filter by status
|
||||||
|
// const status = item.status;
|
||||||
|
// const statusLower = status ? "active" : "inactive";
|
||||||
|
|
||||||
|
// const statusMatches =
|
||||||
|
// statusFilter === "all" ||
|
||||||
|
// (statusFilter === "active" && status === true) ||
|
||||||
|
// (statusFilter === "inactive" && status === false);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const extractedArray = filteredData?.map((item) => ({
|
||||||
|
id: item?.id,
|
||||||
|
"Sr N/O": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{item.id}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.emailID}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Role": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.role}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.phoneNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Action: (
|
||||||
|
<Box display={"flex"} justifyContent={"space-between"} gap={2}>
|
||||||
|
<Tooltip
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label="View"
|
||||||
|
bg="#fff"
|
||||||
|
color={"green.500"}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
navigate(`/bank-details/edit-bank-details/${item.id}`);
|
||||||
|
}}
|
||||||
|
_hover={{ color: "green.500" }}
|
||||||
|
// transition={"0.5s all"}
|
||||||
|
color="green.300"
|
||||||
|
rounded={"sm"}
|
||||||
|
size={"xs"}
|
||||||
|
>
|
||||||
|
<EditIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
const updatedInvestorDetails = InvestorDetails.filter(
|
||||||
|
(sponsor) => sponsor.id !== actionId
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setInvestorDetails(updatedInvestorDetails);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 100);
|
||||||
|
setIsLoading(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (id) => {
|
||||||
|
setActionId(id);
|
||||||
|
onEditOpen();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
mt={1}
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<DataTable
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
isLoading={isLoading}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Users;
|
||||||
|
|||||||
@@ -35,16 +35,18 @@ import NormalTable from "../../../Components/DataTable/NormalTable";
|
|||||||
import { useGetDepositRequestQuery } from "../../../Services/deposit.request.service";
|
import { useGetDepositRequestQuery } from "../../../Services/deposit.request.service";
|
||||||
import { current } from "@reduxjs/toolkit";
|
import { current } from "@reduxjs/toolkit";
|
||||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
import { removeTrailingZeros } from "../../../Constants/Constants";
|
import {
|
||||||
|
generateSerialNumber,
|
||||||
|
removeTrailingZeros,
|
||||||
|
} from "../../../Constants/Constants";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
export const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
const DepositRequest = () => {
|
const DepositRequest = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { depositRequest, setDepositRequest, slideFromRight } =
|
const { depositRequest, setDepositRequest, slideFromRight } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState("");
|
const [actionId, setActionId] = useState("");
|
||||||
@@ -61,26 +63,61 @@ const DepositRequest = () => {
|
|||||||
onClose: onRejectClose,
|
onClose: onRejectClose,
|
||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
isLoading: depositRequestLoading,
|
isLoading: depositRequestLoading,
|
||||||
error,
|
error,
|
||||||
} = useGetDepositRequestQuery({ page: currentPage, size: pageSize });
|
refetch,
|
||||||
|
} = useGetDepositRequestQuery({
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
// "Sr.no",
|
"Sr.no",
|
||||||
"Client ID",
|
"Client ID",
|
||||||
"First Name",
|
"First Name",
|
||||||
"Last Name",
|
"Last Name",
|
||||||
"Country",
|
"Country",
|
||||||
"Phone Number",
|
"Phone Number",
|
||||||
"Amount in Investor currency",
|
"Deposit Amount",
|
||||||
"Deposit Date",
|
"Deposit Date",
|
||||||
"Action",
|
"Action",
|
||||||
];
|
];
|
||||||
@@ -101,7 +138,9 @@ const DepositRequest = () => {
|
|||||||
const filteredData = data?.data?.rows
|
const filteredData = data?.data?.rows
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = [item.firstName, item.lastName, item.countryName].filter(Boolean).join(' ');
|
const name = [item.firstName, item.lastName, item.countryName]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" ");
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -118,21 +157,18 @@ const DepositRequest = () => {
|
|||||||
})
|
})
|
||||||
.sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
|
.sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
|
||||||
|
|
||||||
console.log(data?.data?.rows);
|
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||||
|
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
|
||||||
// id: item?.id,
|
// id: item?.id,
|
||||||
"Sr.no": (
|
"Sr.no": (
|
||||||
<Text
|
<Text
|
||||||
w={"30px"}
|
w={"20px"}
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{index + 1}
|
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Client ID": (
|
"Client ID": (
|
||||||
@@ -148,7 +184,7 @@ const DepositRequest = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"First Name": (
|
"First Name": (
|
||||||
<Box isTruncated={true} w={"70px"}>
|
<Box isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
{item?.firstName}
|
{item?.firstName}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -175,12 +211,22 @@ const DepositRequest = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Amount in Investor currency": (
|
"Deposit Amount": (
|
||||||
<Box display={'flex'} justifyContent={'end'} w={"100px"} isTruncated={true}>
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"end"}
|
||||||
|
w={"130px"}
|
||||||
|
isTruncated={true}
|
||||||
|
>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{/* {formatCurrency(removeTrailingZeros(item?.investorAmount))} */}
|
{/* {formatCurrency(removeTrailingZeros(item?.investorAmount))} */}
|
||||||
{parseFloat(item?.investorAmount||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
{parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
|
||||||
<Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge>
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
<Badge ms={1} colorScheme="green">
|
||||||
|
{item?.currencyCode}
|
||||||
|
</Badge>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormErrorMessage,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
Input,
|
Input,
|
||||||
Modal,
|
Modal,
|
||||||
@@ -20,10 +21,15 @@ import {
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import { useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { useGetDepositRequestByIdQuery, useUpdateDepositRequestMutation } from "../../../Services/deposit.request.service";
|
import {
|
||||||
|
useGetDepositRequestByIdQuery,
|
||||||
|
useGetDepositRequestQuery,
|
||||||
|
useUpdateDepositRequestMutation,
|
||||||
|
} from "../../../Services/deposit.request.service";
|
||||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
import CurrencyInput, { formatCurrency } from "../../../Components/CurrencyInput";
|
||||||
|
|
||||||
const FILE_TYPES = ["image/jpeg", "image/png", "image/gif"];
|
const FILE_TYPES = ["image/jpeg", "image/png", "image/gif"];
|
||||||
|
|
||||||
@@ -36,21 +42,29 @@ export const conformModalSchema = yup.object().shape({
|
|||||||
// }),
|
// }),
|
||||||
});
|
});
|
||||||
|
|
||||||
const DepositRequestApprove = ({ isOpen, onClose, firstField, id, data:requestData }) => {
|
const DepositRequestApprove = ({
|
||||||
const toast = useToast()
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
firstField,
|
||||||
|
id,
|
||||||
|
data: requestData,
|
||||||
|
}) => {
|
||||||
|
const toast = useToast();
|
||||||
const [file, setFile] = useState();
|
const [file, setFile] = useState();
|
||||||
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
const [isBtnLoading, setIsBtnLoading] = useState(false);
|
||||||
|
|
||||||
const fileredData = requestData?.find((item)=> item?.id === id)
|
const [updateDepositRequest] = useUpdateDepositRequestMutation();
|
||||||
console.log(fileredData);
|
const { data, isLoading } = useGetDepositRequestByIdQuery(id, {
|
||||||
|
skip: !id,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(data?.data?.investorAmount);
|
||||||
|
|
||||||
const [ updateDepositRequest ] = useUpdateDepositRequestMutation()
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
control,
|
||||||
register,
|
register,
|
||||||
reset,
|
reset,
|
||||||
|
watch,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm({
|
} = useForm({
|
||||||
@@ -58,15 +72,17 @@ const DepositRequestApprove = ({ isOpen, onClose, firstField, id, data:requestDa
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
const investorAmount = parseFloat(data?.data?.investorAmount);
|
||||||
reset({
|
reset({
|
||||||
investorAmount:fileredData?.investorAmount
|
investorAmount: investorAmount,
|
||||||
})
|
accountName: data?.data?.accountName,
|
||||||
|
});
|
||||||
|
}
|
||||||
}, [requestData, id])
|
}, [id, data, reset]);
|
||||||
|
|
||||||
const onSubmit = async (data) => {
|
const onSubmit = async (data) => {
|
||||||
setIsBtnLoading(true)
|
setIsBtnLoading(true);
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
formData.append("investorAmount", data.investorAmount);
|
formData.append("investorAmount", data.investorAmount);
|
||||||
@@ -74,10 +90,8 @@ const DepositRequestApprove = ({ isOpen, onClose, firstField, id, data:requestDa
|
|||||||
const file = data.supporting_FileName["0"];
|
const file = data.supporting_FileName["0"];
|
||||||
formData.append("supporting_FileName", file);
|
formData.append("supporting_FileName", file);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await updateDepositRequest({ id ,data: formData})
|
const res = await updateDepositRequest({ id, data: formData });
|
||||||
|
|
||||||
|
|
||||||
if (res?.error) {
|
if (res?.error) {
|
||||||
toast({
|
toast({
|
||||||
@@ -85,48 +99,29 @@ const DepositRequestApprove = ({ isOpen, onClose, firstField, id, data:requestDa
|
|||||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
setIsBtnLoading(false)
|
setIsBtnLoading(false);
|
||||||
} else if (res?.data?.statusCode === 200) {
|
} else if (res?.data?.statusCode === 200) {
|
||||||
toast({
|
toast({
|
||||||
render: () => (
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
<ToastBox message={res?.data?.message} />
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
setIsBtnLoading(false)
|
setIsBtnLoading(false);
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
heandleOnClose();
|
heandleOnClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFileChange = (event) => {
|
const heandleOnClose = () => {
|
||||||
const selectedFile = event.target.files[0];
|
reset();
|
||||||
setFile(selectedFile);
|
onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data, isLoading } =
|
|
||||||
(id, {
|
|
||||||
skip: !id,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data) {
|
|
||||||
reset({
|
|
||||||
investorAmount: data?.data?.investorAmount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [data, reset]);
|
|
||||||
|
|
||||||
const heandleOnClose = () =>{
|
|
||||||
reset()
|
|
||||||
onClose()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={heandleOnClose}
|
||||||
|
initialFocusRef={firstField}
|
||||||
|
>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
|
|
||||||
<ModalContent pb={4}>
|
<ModalContent pb={4}>
|
||||||
@@ -137,12 +132,16 @@ const DepositRequestApprove = ({ isOpen, onClose, firstField, id, data:requestDa
|
|||||||
) : (
|
) : (
|
||||||
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<FormControl mb={4} isRequired>
|
{/* <FormControl mb={4} isRequired>
|
||||||
<FormLabel fontSize="sm">Deposit Amount <Badge colorScheme="green">{fileredData?.currencyCode}</Badge></FormLabel>
|
<FormLabel fontSize="sm">
|
||||||
|
Deposit Amount
|
||||||
|
<Badge colorScheme="green">{data?.data?.currencyCode}</Badge>
|
||||||
|
</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
focusBorderColor="green.400"
|
focusBorderColor="green.400"
|
||||||
name="investorAmount"
|
name="investorAmount"
|
||||||
{...register("investorAmount")}
|
{...register("investorAmount")}
|
||||||
|
value={formatCurrency(watch("investorAmount"))}
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
type="number"
|
type="number"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -155,7 +154,24 @@ const DepositRequestApprove = ({ isOpen, onClose, firstField, id, data:requestDa
|
|||||||
{errors.investorAmount.message}
|
{errors.investorAmount.message}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
</FormControl> */}
|
||||||
|
|
||||||
|
<FormControl mb={5} isRequired>
|
||||||
|
<FormLabel fontSize={"sm"}>Deposit Amount</FormLabel>
|
||||||
|
<Controller
|
||||||
|
name="investorAmount"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CurrencyInput {...field} textAlign={'right'} fontSize={"sm"} type="number" size={"sm"} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.investorAmount && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.investorAmount.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl mb={4} isRequired>
|
<FormControl mb={4} isRequired>
|
||||||
<FormLabel fontSize="sm">Upload Supporting</FormLabel>
|
<FormLabel fontSize="sm">Upload Supporting</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ const DepositRequestReject = ({ isOpen, onClose, firstField ,id}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
<Modal isCentered isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent pb={4}>
|
<ModalContent pb={4}>
|
||||||
<ModalHeader fontSize={"md"}>Reject</ModalHeader>
|
<ModalHeader fontSize={"md"}>Investor Comment</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<FullscreenLoaders height={"50vh"} />
|
<FullscreenLoaders height={"50vh"} />
|
||||||
|
|||||||
@@ -27,17 +27,24 @@ import {
|
|||||||
useDepositRejectMutation,
|
useDepositRejectMutation,
|
||||||
useGetDepositHistoryQuery,
|
useGetDepositHistoryQuery,
|
||||||
} from "../../../Services/deposit.request.service";
|
} from "../../../Services/deposit.request.service";
|
||||||
|
|
||||||
import { ExternalLinkIcon } from "@chakra-ui/icons";
|
import { ExternalLinkIcon } from "@chakra-ui/icons";
|
||||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString('en-GB', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
}; // Simple date formatter
|
||||||
|
|
||||||
const DepositHistory = () => {
|
const DepositHistory = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { depositHistory, setDepositHistory, slideFromRight } =
|
const { depositHistory, setDepositHistory, slideFromRight } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
@@ -54,26 +61,51 @@ const DepositHistory = () => {
|
|||||||
// onClose: onRejectClose,
|
// onClose: onRejectClose,
|
||||||
// } = useDisclosure();
|
// } = useDisclosure();
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
error,
|
error,
|
||||||
|
refetch,
|
||||||
isLoading: depositHistoryLoading,
|
isLoading: depositHistoryLoading,
|
||||||
} = useGetDepositHistoryQuery({ page: currentPage, size: pageSize });
|
} = useGetDepositHistoryQuery({
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
// "Sr.no",
|
"Sr.no",
|
||||||
"Client ID",
|
"Client ID",
|
||||||
"First Name",
|
"First Name",
|
||||||
"Last Name",
|
"Last Name",
|
||||||
"Country",
|
"Country",
|
||||||
"Phone Number",
|
"Phone Number",
|
||||||
"Amount in Investor currency",
|
"Deposit Amount",
|
||||||
"Deposit Date",
|
"Deposit Date",
|
||||||
"Status",
|
"Status",
|
||||||
"Supporting's",
|
"Supporting's",
|
||||||
@@ -92,14 +124,12 @@ const DepositHistory = () => {
|
|||||||
});
|
});
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const filteredData = data?.data?.rows
|
const filteredData = data?.data?.rows
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = [item.firstName, item.lastName, item.countryName].filter(Boolean).join(' ');
|
const name = [item.firstName, item.lastName, item.countryName]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" ");
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -116,24 +146,22 @@ const filteredData = data?.data?.rows
|
|||||||
})
|
})
|
||||||
.sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
|
.sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
|
||||||
|
|
||||||
|
|
||||||
// const handleView = (id) => {
|
// const handleView = (id) => {
|
||||||
// setActionId(id);
|
// setActionId(id);
|
||||||
// onViewOpen();
|
// onViewOpen();
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const extractedArray =
|
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||||
filteredData?.map((item, index) => ({
|
|
||||||
"Sr.no": (
|
"Sr.no": (
|
||||||
<Text
|
<Text
|
||||||
w={"30px"}
|
w={"10px"}
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{index + 1}
|
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Client ID": (
|
"Client ID": (
|
||||||
@@ -176,12 +204,20 @@ const filteredData = data?.data?.rows
|
|||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Amount in Investor currency": (
|
"Deposit Amount": (
|
||||||
<Box w={"100px"} isTruncated={true}>
|
<Box
|
||||||
<Text as={"span"} color={"teal.900"}>
|
isTruncated={true}
|
||||||
{/* <Badge px={2} py={1}> */}
|
display={"flex"}
|
||||||
{item?.investorAmount} <Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge>
|
justifyContent={"end"}
|
||||||
{/* </Badge> */}
|
>
|
||||||
|
<Text as={"span"} color={"teal.900"} textAlign={"right"}>
|
||||||
|
{parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
<Badge ms={1} colorScheme="green">
|
||||||
|
{item?.currencyCode}
|
||||||
|
</Badge>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
@@ -200,16 +236,18 @@ const filteredData = data?.data?.rows
|
|||||||
Status: (
|
Status: (
|
||||||
<Box w={"70px"} isTruncated={true} cursor={"pointer"}>
|
<Box w={"70px"} isTruncated={true} cursor={"pointer"}>
|
||||||
<Text
|
<Text
|
||||||
|
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={item.transactionStatus === "Approved" ? "green.500" : "red.500"}
|
color={
|
||||||
|
item.transactionStatus === "Approved" ? "green.500" : "red.500"
|
||||||
|
}
|
||||||
fontWeight={700}
|
fontWeight={700}
|
||||||
>
|
>
|
||||||
{item.transactionStatus}
|
{item.transactionStatus}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Supporting's": (
|
"Supporting's":
|
||||||
|
item.transactionStatus === "Approved" ? (
|
||||||
<Text
|
<Text
|
||||||
w={"60px"}
|
w={"60px"}
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
@@ -232,10 +270,7 @@ const filteredData = data?.data?.rows
|
|||||||
href={import.meta.env.VITE_IMAGE_URL + item?.supporting_FileName}
|
href={import.meta.env.VITE_IMAGE_URL + item?.supporting_FileName}
|
||||||
isExternal
|
isExternal
|
||||||
>
|
>
|
||||||
<Box
|
<Box as="span" cursor={"pointer"}>
|
||||||
as="span"
|
|
||||||
cursor={"pointer"}
|
|
||||||
>
|
|
||||||
View
|
View
|
||||||
</Box>
|
</Box>
|
||||||
<ExternalLinkIcon />
|
<ExternalLinkIcon />
|
||||||
@@ -245,8 +280,10 @@ const filteredData = data?.data?.rows
|
|||||||
</Link> */}
|
</Link> */}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Text>
|
</Text>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
),
|
),
|
||||||
}))
|
}));
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
const IOtype = investmentType.filter(
|
const IOtype = investmentType.filter(
|
||||||
|
|||||||
303
src/Pages/EmailNotification/EmailNotification.jsx
Normal file
303
src/Pages/EmailNotification/EmailNotification.jsx
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormHelperText,
|
||||||
|
FormLabel,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Text,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||||
|
import { useGetUnbanInvestorQuery } from "../../Services/ban.investor.service";
|
||||||
|
import { formatDate, generateSerialNumber } from "../../Constants/Constants";
|
||||||
|
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||||
|
import ReactQuill from "react-quill";
|
||||||
|
import "react-quill/dist/quill.snow.css"; // Importing the Quill snow theme
|
||||||
|
import { useSendCustomEmailMutation } from "../../Services/contact.service";
|
||||||
|
import { EmailIcon } from "@chakra-ui/icons";
|
||||||
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
|
||||||
|
const EmailNotification = () => {
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [selectedRadio, setSelectedRadio] = useState([]);
|
||||||
|
const [subject, setSubject] = useState("");
|
||||||
|
const [value, setValue] = useState(""); // Quill content (body)
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
|
const [sendCustomNotification] = useSendCustomEmailMutation();
|
||||||
|
|
||||||
|
// ===========================[Table Setup]==============================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr N/O",
|
||||||
|
"Date",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"Country",
|
||||||
|
"Phone Number",
|
||||||
|
"E-mail ID",
|
||||||
|
"KYC Status",
|
||||||
|
];
|
||||||
|
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: investorDetails,
|
||||||
|
isLoading: investorDetailsLoading,
|
||||||
|
refetch,
|
||||||
|
} = useGetUnbanInvestorQuery({
|
||||||
|
page: currentPage, // Omit pagination for search
|
||||||
|
size: 10000, // Omit pagination for search
|
||||||
|
});
|
||||||
|
|
||||||
|
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||||
|
id: item?.principal_xid,
|
||||||
|
"Sr N/O": (
|
||||||
|
<Text
|
||||||
|
justifyContent={"left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
Date: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{formatDate(item?.date)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Country: (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.country}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.phoneNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"KYC Status": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Badge
|
||||||
|
fontWeight={"500"}
|
||||||
|
textTransform={"none"}
|
||||||
|
color={item?.KYCStatus === false ? "red" : "blue"}
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
variant={"ghost"}
|
||||||
|
>
|
||||||
|
{item?.KYCStatus === true ? "Completed" : "Incompleted"}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const modules = {
|
||||||
|
toolbar: [
|
||||||
|
// [{ header: "1" }, { header: "2" },
|
||||||
|
// // { font: [] }
|
||||||
|
// ],
|
||||||
|
// [{ size: [] }],
|
||||||
|
["bold", "italic", "underline", "strike", "blockquote"],
|
||||||
|
[{ list: "ordered" }, { list: "bullet" }],
|
||||||
|
["clean"],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main submission logic
|
||||||
|
const handleSend = async (e) => {
|
||||||
|
e.preventDefault(); // Prevent default form submission
|
||||||
|
|
||||||
|
if (!subject || !value) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={"error"} message={"Subject or email body cannot be empty"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedRadio.length === 0) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={"error"} message={"Please select at least one recipient"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const emailPayload = {
|
||||||
|
subject,
|
||||||
|
body: value,
|
||||||
|
principal_xid: selectedRadio,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await sendCustomNotification(emailPayload)
|
||||||
|
console.log(res);
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false)
|
||||||
|
}else if(res?.data){
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false)
|
||||||
|
setSubject("")
|
||||||
|
setValue("")
|
||||||
|
setSelectedRadio([])
|
||||||
|
|
||||||
|
}else{
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={'error'} message={"Something went wrong"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
as={"form"}
|
||||||
|
{...OPACITY_ON_LOAD}
|
||||||
|
overflowY={"scroll"}
|
||||||
|
height={"100vh"}
|
||||||
|
pb={14}
|
||||||
|
pt={4}
|
||||||
|
>
|
||||||
|
<FormControl mb={0}>
|
||||||
|
{/* <HStack
|
||||||
|
py={4}
|
||||||
|
pb={3}
|
||||||
|
w={"100%"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
alignItems={"center"}
|
||||||
|
>
|
||||||
|
<Text as={"span"} fontSize={"sm"}>
|
||||||
|
Customize your email
|
||||||
|
</Text>
|
||||||
|
</HStack> */}
|
||||||
|
|
||||||
|
<FormControl isRequired mb={3} p={1}>
|
||||||
|
<FormLabel fontSize={"sm"}>Subject</FormLabel>
|
||||||
|
<Input
|
||||||
|
size={"md"}
|
||||||
|
value={subject}
|
||||||
|
onChange={(e) => setSubject(e.target.value)}
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
|
rounded={0.5}
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
{/* <FormHelperText>Entered subject will be reflected on emails subject body.</FormHelperText> */}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
|
||||||
|
<FormControl minH={400} isRequired mb={3} p={1}>
|
||||||
|
<FormLabel fontSize={"sm"}>Create Custom body</FormLabel>
|
||||||
|
<ReactQuill
|
||||||
|
theme="snow"
|
||||||
|
style={{
|
||||||
|
height:300
|
||||||
|
}}
|
||||||
|
value={value}
|
||||||
|
onChange={setValue}
|
||||||
|
modules={modules}
|
||||||
|
placeholder="Start typing here..."
|
||||||
|
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
{/* <FormHelperText fontSize={"xs"}>
|
||||||
|
We'll never share your email.
|
||||||
|
</FormHelperText> */}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<Box overflow={'scroll'} h={'58vh'}>
|
||||||
|
<NormalTable
|
||||||
|
centered={true}
|
||||||
|
emptyMessage={`We don't have any Sponsors`}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
setSelectedRadio={setSelectedRadio}
|
||||||
|
selectedRadio={selectedRadio}
|
||||||
|
showRadioButton={true}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<HStack justifyContent={"flex-end"} px={2}>
|
||||||
|
<Button
|
||||||
|
rightIcon={<EmailIcon />}
|
||||||
|
rounded={"sm"}
|
||||||
|
size={"sm"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
type="submit"
|
||||||
|
isLoading={isLoading}
|
||||||
|
onClick={handleSend}
|
||||||
|
>
|
||||||
|
Send Email
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EmailNotification;
|
||||||
313
src/Pages/Fawateer/CreateRequest.jsx
Normal file
313
src/Pages/Fawateer/CreateRequest.jsx
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
import { Box, Button, HStack, Input, InputGroup, InputRightAddon, Textarea, useDisclosure, Image, Icon, VStack, Text, useToast } from "@chakra-ui/react";
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
FormHelperText,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import { DeleteIcon, Search2Icon } from "@chakra-ui/icons";
|
||||||
|
import SelectInvestorModal from "./SelectInvestorModal";
|
||||||
|
import { Controller, useForm } from "react-hook-form"; // Import useForm
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup"; // Import resolver for Yup
|
||||||
|
import * as Yup from "yup"; // Import Yup for validation
|
||||||
|
import { motion } from 'framer-motion'; // Import Framer Motion for animations
|
||||||
|
import { bytesToMB } from "../../Constants/Constants";
|
||||||
|
import { useCreateFawateerRequestMutation } from "../../Services/fawateer.maker.service";
|
||||||
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import CurrencyInput from "../../Components/CurrencyInput";
|
||||||
|
|
||||||
|
// Validation schema using Yup
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
investorName: Yup.string().required("Investor name is required"),
|
||||||
|
clientId: Yup.string().required("Client ID is required"),
|
||||||
|
transaction_date: Yup.date()
|
||||||
|
.required('Date is required')
|
||||||
|
.transform((value, originalValue) => {
|
||||||
|
return originalValue === "" ? null : value; // Convert empty strings to null
|
||||||
|
})
|
||||||
|
.typeError('Please enter a valid date').max(new Date(), "Date cannot be in the future"),
|
||||||
|
transaction_amount: Yup.number()
|
||||||
|
.required("Transaction amount is required")
|
||||||
|
.transform((value, originalValue) => originalValue === "" ? null : value) // Convert empty strings to null
|
||||||
|
.typeError('Transaction amount must be a number') // Custom error message if it's not a number
|
||||||
|
.positive('Transaction amount must be greater than zero'),
|
||||||
|
spportFile_path: Yup.mixed().required("Support file is required"),
|
||||||
|
makerComment: Yup.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const CreateRequest = () => {
|
||||||
|
const toast = useToast()
|
||||||
|
const navigate=useNavigate()
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const [selectedInvestor, setSelectorInvestor] = useState({});
|
||||||
|
const [filePreview, setFilePreview] = useState(null); // State for previewing the file
|
||||||
|
const [fileType, setFileType] = useState(null); // State to store file type for conditional rendering
|
||||||
|
const[ isLoading, setIsLoading ] = useState(false)
|
||||||
|
const [id, setId ] = useState(null)
|
||||||
|
|
||||||
|
// Initialize useForm with the resolver for Yup validation
|
||||||
|
const {control, register, handleSubmit, setValue,reset, formState: { errors } } = useForm({
|
||||||
|
resolver: yupResolver(validationSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const [ creatFawaateerRequest ] = useCreateFawateerRequestMutation()
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = async (data) => {
|
||||||
|
console.log(data);
|
||||||
|
setIsLoading(true)
|
||||||
|
|
||||||
|
// Convert data to FormData
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
// Append each field from the data object to the FormData
|
||||||
|
Object.keys(data).forEach((key) => {
|
||||||
|
if (key === "spportFile_path" && data[key] instanceof FileList) {
|
||||||
|
// Append the first file from FileList (assuming single file input)
|
||||||
|
formData.append(key, data[key][0]); // Append the file
|
||||||
|
} else {
|
||||||
|
formData.append(key, data[key]); // Append other fields
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Make the API call with formData
|
||||||
|
const res = await creatFawaateerRequest({ data: formData, id });
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
reset()
|
||||||
|
return
|
||||||
|
} else if (res?.data) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
navigate('/fawateer-history')
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={'error'} message={"Something went wrong"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error:", error);
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={'error'} message={"An error occurred"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Handle file change and preview
|
||||||
|
const handleFileChange = (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
console.log(file);
|
||||||
|
setValue("spportFile_path", file); // Set the file value in the form
|
||||||
|
setFileType(file); // Set the file type
|
||||||
|
|
||||||
|
if (file && file.type.startsWith("image/")) {
|
||||||
|
// If the file is an image, generate a preview
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
setFilePreview(reader.result); // Set the image preview
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
} else {
|
||||||
|
setFilePreview(null); // Clear preview if the file is not an image
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
flexWrap={'wrap'}
|
||||||
|
alignItems={"center"}
|
||||||
|
mt={5}
|
||||||
|
px={4}
|
||||||
|
as="form"
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
>
|
||||||
|
{/* Investor Name Field */}
|
||||||
|
<FormControl isRequired w={"49%"} mb={2} isInvalid={errors.investorName}>
|
||||||
|
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||||
|
Investor name
|
||||||
|
</FormLabel>
|
||||||
|
<InputGroup size='sm'>
|
||||||
|
<Input
|
||||||
|
bg={"#F5F8F6"}
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
type={"text"}
|
||||||
|
readOnly={true}
|
||||||
|
placeholder={"Investor name"}
|
||||||
|
{...register("investorName")}
|
||||||
|
_placeholder={{ fontSize: "sm" }}
|
||||||
|
/>
|
||||||
|
<InputRightAddon gap={2} color={'forestgreen.400'} onClick={onOpen} cursor={'pointer'} fontWeight={600} fontSize={'xs'}>
|
||||||
|
<Search2Icon /> Search
|
||||||
|
</InputRightAddon>
|
||||||
|
</InputGroup>
|
||||||
|
<FormHelperText fontSize={'xs'} fontWeight={500} style={{ color: "red" }}>{errors.investorName?.message}</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{/* Client ID Field */}
|
||||||
|
<FormControl isRequired w={"49%"} mb={2} isInvalid={errors.clientId}>
|
||||||
|
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||||
|
Client Id
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#F5F8F6"}
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
type={"text"}
|
||||||
|
readOnly={true}
|
||||||
|
placeholder={"Client ID"}
|
||||||
|
{...register("clientId")}
|
||||||
|
/>
|
||||||
|
<FormHelperText fontSize={'xs'} fontWeight={500} style={{ color: "red" }}>{errors.clientId?.message}</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{/* Date Field */}
|
||||||
|
<FormControl isRequired w={"49%"} mb={2} isInvalid={errors.date}>
|
||||||
|
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||||
|
Date
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#F5F8F6"}
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
type={"date"}
|
||||||
|
max={new Date().toISOString().split("T")[0]} // Disable future dates
|
||||||
|
{...register("transaction_date")}
|
||||||
|
/>
|
||||||
|
<FormHelperText fontSize={'xs'} fontWeight={500} style={{ color: "red" }}>{errors.transaction_date?.message}</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{/* Amount Field */}
|
||||||
|
<FormControl isRequired w={"49%"} mb={2} isInvalid={errors.amount}>
|
||||||
|
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||||
|
Amount (BHD)
|
||||||
|
</FormLabel>
|
||||||
|
<Controller
|
||||||
|
name="transaction_amount"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CurrencyInput bg={"#F5F8F6"} {...field} textAlign={'right'} fontSize={"sm"} type="number" size={"sm"} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormHelperText fontSize={'xs'} fontWeight={500} style={{ color: "red" }}>
|
||||||
|
{errors.transaction_amount?.message}
|
||||||
|
</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{/* Support File Field with Preview */}
|
||||||
|
<FormControl isRequired w={"49%"} mb={2} isInvalid={errors.spportFile_path}>
|
||||||
|
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||||
|
Support file
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#F5F8F6"}
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
type={"file"}
|
||||||
|
className="form-control"
|
||||||
|
name="spportFile_path"
|
||||||
|
placeholder={"Support file"}
|
||||||
|
{...register("spportFile_path")}
|
||||||
|
// onChange={handleFileChange}
|
||||||
|
/>
|
||||||
|
<FormHelperText fontSize={'xs'} fontWeight={500} style={{ color: "red" }}>{errors.spportFile_path?.message}</FormHelperText>
|
||||||
|
|
||||||
|
{/* Animated Preview */}
|
||||||
|
{filePreview && fileType?.type.startsWith("image/") && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
style={{ marginTop: "10px" }}
|
||||||
|
>
|
||||||
|
<Box position={'relative'} display={'flex'} alignContent={'flex-end'} gap={3} mt={2}>
|
||||||
|
<Image src={filePreview} alt="File preview" maxW={"150px"} borderRadius="md" boxShadow="md" />
|
||||||
|
<Icon onClick={()=> setFilePreview(null)} className="link" rounded={'md'} color={'red.700'} cursor={'pointer'} p={1.5} position={'absolute'} top={0} right={0} as={DeleteIcon} boxSize={7} />
|
||||||
|
<VStack justifyItems={'flex-end'} alignItems={'flex-start'}>
|
||||||
|
<Text as={'span'} color={'gray.600'} fontSize={'xs'}>File Name: <Text as={'span'} color={'GrayText'}> {fileType?.name}</Text></Text>
|
||||||
|
<Text as={'span'} color={'gray.600'} fontSize={'xs'}>File Size: <Text as={'span'} color={'GrayText'}> {bytesToMB(fileType?.size)} Mb</Text></Text>
|
||||||
|
<Text as={'span'} color={'gray.600'} fontSize={'xs'}>File Type: <Text as={'span'} color={'GrayText'}> {fileType?.type}</Text></Text>
|
||||||
|
|
||||||
|
</VStack>
|
||||||
|
</Box>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{/* Description Field */}
|
||||||
|
<FormControl w={"100%"} mb={2} isInvalid={errors.makerComment}>
|
||||||
|
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||||
|
Description
|
||||||
|
</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
bg={"#F5F8F6"}
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
placeholder={"Description"}
|
||||||
|
{...register("makerComment")}
|
||||||
|
/>
|
||||||
|
<FormHelperText fontSize={'xs'} fontWeight={500} style={{ color: "red" }}>{errors.makerComment?.message}</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{/* Submit Button */}
|
||||||
|
<HStack mt={2} w={'100%'} justifyContent={'flex-end'}>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
type="submit"
|
||||||
|
isLoading={isLoading}
|
||||||
|
>
|
||||||
|
Create request
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<SelectInvestorModal setId={setId} setValue={setValue} onClose={onClose} isOpen={isOpen} onOpen={onOpen}/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateRequest;
|
||||||
@@ -19,6 +19,8 @@ import {
|
|||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||||
import { HiDotsVertical } from "react-icons/hi";
|
import { HiDotsVertical } from "react-icons/hi";
|
||||||
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
@@ -28,30 +30,68 @@ import {
|
|||||||
EmailIcon,
|
EmailIcon,
|
||||||
ViewIcon,
|
ViewIcon,
|
||||||
} from "@chakra-ui/icons";
|
} from "@chakra-ui/icons";
|
||||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
|
||||||
import { debounce } from "../Master/Sponser/AddSponser";
|
|
||||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
|
||||||
import DataTable from "../../Components/DataTable/DataTable";
|
|
||||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
|
||||||
import Pagination from "../../Components/Pagination";
|
import Pagination from "../../Components/Pagination";
|
||||||
|
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||||
|
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||||
import ToastBox from "../../Components/ToastBox";
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
import { debounce } from "../Master/Sponser/AddSponser";
|
||||||
|
// import InvestmentDetailsEdit from "./InvestmentDetailsEdit";
|
||||||
|
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||||
|
import { exportToExcel, generateSerialNumber } from "../../Constants/Constants";
|
||||||
|
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
|
||||||
|
|
||||||
const BankInvestor = () => {
|
const FawateerRequest = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const thirdField = useRef();
|
const thirdField = useRef();
|
||||||
const { bankInvestor, setBankInvestor, slideFromRight } =
|
const { InvestorDetails, setInvestorDetails, slideFromRight } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
const {isOpen: isEditOpen,onOpen: onEditOpen,onClose: onEditClose,} = useDisclosure();
|
const {
|
||||||
const btnRef = React.useRef()
|
isOpen: isEditOpen,
|
||||||
|
onOpen: onEditOpen,
|
||||||
|
onClose: onEditClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
const btnRef = React.useRef();
|
||||||
|
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: investorDetails,
|
||||||
|
isLoading: investorDetailsLoading,
|
||||||
|
error,
|
||||||
|
} = useGetInvestorsQuery({
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Simulate loading
|
// Simulate loading
|
||||||
@@ -65,21 +105,22 @@ const BankInvestor = () => {
|
|||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
"Sr N/O",
|
"Sr No",
|
||||||
"Client ID",
|
"Client ID",
|
||||||
"First Name",
|
"First Name",
|
||||||
"Last Name",
|
"Last Name",
|
||||||
"Country",
|
"Country",
|
||||||
"Phone Number",
|
"Phone Number",
|
||||||
"E-mail ID",
|
"E-mail ID",
|
||||||
"KYC Status",
|
// "Type",
|
||||||
"Action",
|
// "KYC Status",
|
||||||
|
"Approval Status",
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleUpdateStatus = debounce((id) => {
|
const handleUpdateStatus = debounce((id) => {
|
||||||
setBankInvestor((prevData) =>
|
setInvestorDetails((prevData) =>
|
||||||
prevData.map((bankInvestor) =>
|
prevData.map((InvestorDetails) =>
|
||||||
bankInvestor.id === id ? { ...bankInvestor } : bankInvestor
|
InvestorDetails.id === id ? { ...InvestorDetails } : InvestorDetails
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
toast({
|
toast({
|
||||||
@@ -88,9 +129,9 @@ const BankInvestor = () => {
|
|||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
// ====================================================[Table Filter]================================================================
|
// ====================================================[Table Filter]================================================================
|
||||||
const filteredData = bankInvestor?.filter((item) => {
|
const filteredData = investorDetails?.data?.rows?.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = item.firstName;
|
const name = [item?.principal?.firstName, item?.principal?.lastName, item?.country?.countryName, item?.principal?.mobileNumber, item?.principal?.emailAddress].filter(Boolean).join(' ');
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name?.toLowerCase().includes(searchLower);
|
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -106,74 +147,100 @@ const BankInvestor = () => {
|
|||||||
return nameMatches;
|
return nameMatches;
|
||||||
});
|
});
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item) => ({
|
|
||||||
|
|
||||||
|
const customHeaders = [
|
||||||
|
{ label: "ID", key: "id" },
|
||||||
|
{ label: "Client ID", key: "clientReference_id" },
|
||||||
|
{ label: "First Name", key: "principal.firstName" }, // Nested property
|
||||||
|
{ label: "Last Name", key: "principal.lastName" }, // Nested property
|
||||||
|
{ label: "Country", key: "country.countryName" }, // Nested property
|
||||||
|
{ label: "Phone Number", key: "principal.mobileNumber" }, // Nested property
|
||||||
|
{ label: "E-mail ID", key: "principal.emailAddress" }, // Nested property
|
||||||
|
{ label: "Type", key: "investor_type.investorTypeName" }, // Nested property
|
||||||
|
{ label: "Status", key: "ioStatus" }, // Simple property
|
||||||
|
{ label: "KYC Status", key: "KYCStatus" }, // Simple property
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr N/O": (
|
"Sr No": (
|
||||||
<Text
|
<Text
|
||||||
|
w={'24px'}
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
className="d-flex align-items-center fw-bold web-text-small"
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
>
|
>
|
||||||
{item.id}
|
{/* {item.id} */}
|
||||||
|
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||||
|
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Client ID": (
|
"Client ID": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.clientId}
|
{item.clientReference_id}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"First Name": (
|
"First Name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.firstName}
|
{item?.principal?.firstName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Last Name": (
|
"Last Name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"70px"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.lastName}
|
{item?.principal?.lastName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Country: (
|
Country: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.country}
|
{item?.country?.countryName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Phone Number": (
|
"Phone Number": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.phoneNumber}
|
{item?.principal?.mobileNumber}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"E-mail ID": (
|
"E-mail ID": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.mailId}
|
{item?.principal?.emailAddress}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"KYC Status": (
|
"Type": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Badge fontWeight={'500'} textTransform={'none'} color={item.status === "Completed" ? "blue" : "red"} px={2} py={0.5}>
|
<Text as={"span"} >
|
||||||
{item.status}
|
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}>
|
||||||
|
{item?.investor_type?.investorTypeName}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Action: (
|
"Approval Status": (
|
||||||
<Switch
|
<Box w={"auto"} isTruncated={true}>
|
||||||
size={"sm"}
|
<Badge
|
||||||
colorScheme="forestGreen"
|
fontWeight={"700"}
|
||||||
onChange={() => handleUpdateStatus(item.id)}
|
textTransform={"none"}
|
||||||
isChecked={item.status}
|
colorScheme={item.ioStatus ? "red" : "purple"}
|
||||||
/>
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
>
|
||||||
|
Approved
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -195,6 +262,10 @@ const BankInvestor = () => {
|
|||||||
onEditOpen();
|
onEditOpen();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(investorDetails?.data?.totalItems);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
<Box bg="white.500">
|
<Box bg="white.500">
|
||||||
@@ -218,17 +289,45 @@ const BankInvestor = () => {
|
|||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<HStack display={"flex"} alignItems={"center"}>
|
<HStack display={"flex"} alignItems={"center"}>
|
||||||
<Pagination totalItems={10} />
|
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
isLoading={investorDetailsLoading}
|
||||||
|
pageSize={pageSize}
|
||||||
|
setPageSize={setPageSize}
|
||||||
|
currentPage={currentPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
totalItems={investorDetails?.data?.totalItems}
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<Button
|
||||||
|
leftIcon={<AddIcon />}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
onClick={()=> navigate('create-request')}
|
||||||
|
>
|
||||||
|
Create request
|
||||||
|
</Button> */}
|
||||||
|
|
||||||
</HStack>
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<DataTable
|
<NormalTable
|
||||||
|
// centered={true}
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
isLoading={isLoading}
|
isLoading={investorDetailsLoading}
|
||||||
viewActionId={actionId}
|
viewActionId={actionId}
|
||||||
setViewActionId={setActionId}
|
setViewActionId={setActionId}
|
||||||
setMouseEnteredId={setMouseEnteredId}
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
@@ -246,4 +345,4 @@ const BankInvestor = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BankInvestor;
|
export default FawateerRequest
|
||||||
247
src/Pages/Fawateer/SelectInvestorModal.jsx
Normal file
247
src/Pages/Fawateer/SelectInvestorModal.jsx
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalOverlay,
|
||||||
|
ModalContent,
|
||||||
|
ModalHeader,
|
||||||
|
ModalFooter,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
Button,
|
||||||
|
Text,
|
||||||
|
Box,
|
||||||
|
Badge,
|
||||||
|
Select,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
useToast,
|
||||||
|
} from '@chakra-ui/react'
|
||||||
|
import NormalTable from '../../Components/DataTable/NormalTable'
|
||||||
|
import { generateSerialNumber } from '../../Constants/Constants';
|
||||||
|
import { useGetInvestorsQuery } from '../../Services/investor.details.service';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { TABLE_PAGINATION } from '../../Constants/Paginations';
|
||||||
|
import Pagination from '../../Components/Pagination';
|
||||||
|
import { AddIcon } from '@chakra-ui/icons';
|
||||||
|
import { useGetFawateerInvestorsQuery } from '../../Services/fawateer.request.service';
|
||||||
|
import ToastBox from '../../Components/ToastBox';
|
||||||
|
|
||||||
|
const SelectInvestorModal = ({ isOpen, setValue, onClose, setId}) => {
|
||||||
|
const toast = useToast()
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: investorDetails,
|
||||||
|
isLoading: investorDetailsLoading,
|
||||||
|
error,
|
||||||
|
} = useGetFawateerInvestorsQuery({
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const [ selectedRadio, setSelectedRadio] = useState([])
|
||||||
|
const [ selectedInvestor, setSelectorInvestor] = useState(null)
|
||||||
|
|
||||||
|
const handleCheckboxChange = (id) => {
|
||||||
|
|
||||||
|
setSelectedRadio([id]);
|
||||||
|
const investor = investorDetails?.data?.rows?.find((item)=> item?.id === id)
|
||||||
|
setSelectorInvestor(investor)
|
||||||
|
setId(investor?.principal_xid)
|
||||||
|
// setValue("investorName",`${selectedInvestor?.firstName} ${selectedInvestor?.lastName}`)
|
||||||
|
// setValue("clientId",selectedInvestor?.clientReference_id)
|
||||||
|
return
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
if(selectedRadio?.length === 0){
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={'info'} message={"Please Select Investor"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setValue("investorName",`${selectedInvestor?.firstName} ${selectedInvestor?.lastName}`)
|
||||||
|
setValue("clientId",selectedInvestor?.clientReference_id)
|
||||||
|
return onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
|
||||||
|
"Sr No",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
// "Country",
|
||||||
|
"Phone Number",
|
||||||
|
"E-mail ID",
|
||||||
|
// "Type",
|
||||||
|
// "KYC Status",
|
||||||
|
// "Approval Status",
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||||
|
id: item?.id,
|
||||||
|
"Sr No": (
|
||||||
|
<Text
|
||||||
|
w={'24px'}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{/* {item.id} */}
|
||||||
|
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||||
|
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"70px"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.phoneNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Type": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} >
|
||||||
|
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}>
|
||||||
|
{item?.investor_type?.investorTypeName}
|
||||||
|
</Badge>
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Approval Status": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Badge
|
||||||
|
fontWeight={"700"}
|
||||||
|
textTransform={"none"}
|
||||||
|
colorScheme={item.ioStatus ? "red" : "purple"}
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
>
|
||||||
|
Approved
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setSelectorInvestor(null)
|
||||||
|
handleClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isCentered
|
||||||
|
onClose={onClose}
|
||||||
|
isOpen={isOpen}
|
||||||
|
motionPreset='scale'
|
||||||
|
>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent maxW={1200}>
|
||||||
|
<ModalHeader fontSize={'md'}>View Investor's</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
{/* <Lorem count={2} /> */}
|
||||||
|
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
mt={1}
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Button leftIcon={<AddIcon/>} fontSize={'xs'} colorScheme='forestGreen' size={'sm'} rounded={'sm'} onClick={handleAdd}>
|
||||||
|
Select Investor
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
|
||||||
|
{investorDetailsLoading?"Loaading":<NormalTable
|
||||||
|
// centered={true}
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
isLoading={investorDetailsLoading}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
handleCheckboxChange={handleCheckboxChange}
|
||||||
|
setSelectedRadio={setSelectedRadio}
|
||||||
|
selectedRadio={selectedRadio}
|
||||||
|
showRadioButton={true}
|
||||||
|
radio={true}
|
||||||
|
/>}
|
||||||
|
|
||||||
|
</ModalBody>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectInvestorModal
|
||||||
@@ -0,0 +1,336 @@
|
|||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Link,
|
||||||
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
|
import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||||
|
import Pagination from "../../../Components/Pagination";
|
||||||
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
|
import DrawalRequestReject from "../../WithDrawal/DrawalRequest/DrawalRequestReject";
|
||||||
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
|
import DrawalRequestApprove from "../../WithDrawal/DrawalRequest/DrawalRequestApprove";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
import {
|
||||||
|
useGetApproveHistoryQuery,
|
||||||
|
useGetFawateerRequestQuery,
|
||||||
|
} from "../../../Services/fawateer.request.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
|
|
||||||
|
const ApproveHistory = () => {
|
||||||
|
const toast = useToast();
|
||||||
|
const { slideFromRight, approveHistory, setApproveHistory } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
isOpen: isConfirmOpen,
|
||||||
|
onOpen: onConfirmOpen,
|
||||||
|
onClose: onConfirmClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
const {
|
||||||
|
isOpen: isRejectOpen,
|
||||||
|
onOpen: onRejectOpen,
|
||||||
|
onClose: onRejectClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: drawalRequestLoading,
|
||||||
|
error,
|
||||||
|
refetch,
|
||||||
|
} = useGetApproveHistoryQuery();
|
||||||
|
|
||||||
|
console.log(data?.data?.rows);
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Simulate loading
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Cleanup the timer on component unmount
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ====================================================[Table Filter]================================================================
|
||||||
|
const filteredData = data?.data?.rows?.filter((item) => {
|
||||||
|
// Filter by name (case insensitive)
|
||||||
|
const name = item.firstName;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
// Filter by status
|
||||||
|
// const status = item.status;
|
||||||
|
// const statusLower = status ? "active" : "inactive";
|
||||||
|
|
||||||
|
// const statusMatches =
|
||||||
|
// statusFilter === "all" ||
|
||||||
|
// (statusFilter === "active" && status === true) ||
|
||||||
|
// (statusFilter === "inactive" && status === false);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr.no",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"E-mail ID",
|
||||||
|
"Phone Number",
|
||||||
|
"Deposit Date",
|
||||||
|
"Deposit Amount (BHD)",
|
||||||
|
"Support Image",
|
||||||
|
"Status",
|
||||||
|
];
|
||||||
|
|
||||||
|
const extractedArray = filteredData?.map((item, idx) => ({
|
||||||
|
// id: item?.id,
|
||||||
|
"Sr.no": (
|
||||||
|
<Text
|
||||||
|
w={"auto"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Text
|
||||||
|
w={"60px"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box isTruncated={true} w={"80px"}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"50px"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"100px"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.mobileNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Deposit Date": (
|
||||||
|
<Box
|
||||||
|
w={"100px"}
|
||||||
|
isTruncated={true}
|
||||||
|
display={"flex"}
|
||||||
|
>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{formatDate(item?.transaction_date)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Deposit Amount (BHD)": (
|
||||||
|
<Box w={"130px"} isTruncated={true} display={"flex"}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{/* {item.investorAmount} */}
|
||||||
|
{parseFloat(item?.transaction_amount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
{/* <Badge ms={1} colorScheme="green">{item?.transaction_amount}</Badge> */}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Support Image": (
|
||||||
|
<Text
|
||||||
|
color={"green.500"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item?.spportFile_path&&<Badge
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
colorScheme={"forestGreen"}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={import.meta.env.VITE_IMAGE_URL + item?.spportFile_path}
|
||||||
|
isExternal
|
||||||
|
display={"flex"}
|
||||||
|
alignItems={"center"}
|
||||||
|
>
|
||||||
|
<Box me={"1px"}
|
||||||
|
as="span"
|
||||||
|
cursor={"pointer"}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Box>
|
||||||
|
<ExternalLinkIcon />
|
||||||
|
</Link>
|
||||||
|
</Badge>}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
Status: (
|
||||||
|
<Box isTruncated={true} display={"flex"}>
|
||||||
|
<Badge
|
||||||
|
my={1}
|
||||||
|
fontWeight={500}
|
||||||
|
px={2}
|
||||||
|
py={"2px"}
|
||||||
|
rounded={4}
|
||||||
|
colorScheme={
|
||||||
|
item?.transactionStatus === "Approved"
|
||||||
|
? "green"
|
||||||
|
: item?.transactionStatus === "Pending"
|
||||||
|
? "yellow"
|
||||||
|
: item?.transactionStatus === "Reject"
|
||||||
|
? "red"
|
||||||
|
: "gray" // default border color if status doesn't match any condition
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.transactionStatus}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
const updatedSponsors = sponser.filter(
|
||||||
|
(sponsor) => sponsor.id !== actionId
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setSponser(updatedSponsors);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 100);
|
||||||
|
setIsLoading(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
isLoading={drawalRequestLoading}
|
||||||
|
pageSize={pageSize}
|
||||||
|
setPageSize={setPageSize}
|
||||||
|
currentPage={currentPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
totalItems={data?.data?.totalItems}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<NormalTable
|
||||||
|
isLoading={drawalRequestLoading}
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
// totalPages={10}
|
||||||
|
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<DrawalRequestApprove
|
||||||
|
// data={data?.data?.rows}
|
||||||
|
isOpen={isConfirmOpen}
|
||||||
|
onClose={onConfirmClose}
|
||||||
|
id={actionId}
|
||||||
|
// firstField={firstField}
|
||||||
|
/>
|
||||||
|
<DrawalRequestReject
|
||||||
|
isOpen={isRejectOpen}
|
||||||
|
onClose={onRejectClose}
|
||||||
|
id={actionId}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApproveHistory;
|
||||||
358
src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker.jsx
Normal file
358
src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker.jsx
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Link,
|
||||||
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
|
import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||||
|
import Pagination from "../../../Components/Pagination";
|
||||||
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
|
import DrawalRequestReject from "../../WithDrawal/DrawalRequest/DrawalRequestReject";
|
||||||
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
|
import DrawalRequestApprove from "../../WithDrawal/DrawalRequest/DrawalRequestApprove";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
import {
|
||||||
|
useGetApproveHistoryQuery,
|
||||||
|
useGetFawateerForMakerRequestQuery,
|
||||||
|
useGetFawateerRequestQuery,
|
||||||
|
} from "../../../Services/fawateer.request.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
|
|
||||||
|
const ApproveHistoryMaker = () => {
|
||||||
|
const toast = useToast();
|
||||||
|
const { slideFromRight, approveHistory, setApproveHistory } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
isOpen: isConfirmOpen,
|
||||||
|
onOpen: onConfirmOpen,
|
||||||
|
onClose: onConfirmClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
const {
|
||||||
|
isOpen: isRejectOpen,
|
||||||
|
onOpen: onRejectOpen,
|
||||||
|
onClose: onRejectClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: drawalRequestLoading,
|
||||||
|
error,
|
||||||
|
refetch
|
||||||
|
} = useGetFawateerForMakerRequestQuery(
|
||||||
|
{
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
searchTerm: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Simulate loading
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Cleanup the timer on component unmount
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ====================================================[Table Filter]================================================================
|
||||||
|
const filteredData = data?.data?.rows?.filter((item) => {
|
||||||
|
// Filter by name (case insensitive)
|
||||||
|
const name = item.firstName;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
// Filter by status
|
||||||
|
// const status = item.status;
|
||||||
|
// const statusLower = status ? "active" : "inactive";
|
||||||
|
|
||||||
|
// const statusMatches =
|
||||||
|
// statusFilter === "all" ||
|
||||||
|
// (statusFilter === "active" && status === true) ||
|
||||||
|
// (statusFilter === "inactive" && status === false);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr.no",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"E-mail ID",
|
||||||
|
"Phone Number",
|
||||||
|
"Deposit Date",
|
||||||
|
"Deposit Amount (BHD)",
|
||||||
|
"Support Image",
|
||||||
|
"Status",
|
||||||
|
];
|
||||||
|
|
||||||
|
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||||
|
|
||||||
|
// id: item?.id,
|
||||||
|
"Sr.no": (
|
||||||
|
<Text
|
||||||
|
w={"auto"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Text
|
||||||
|
w={"60px"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box isTruncated={true} w={"80px"}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box w={"50px"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"100px"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.mobileNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Deposit Date": (
|
||||||
|
<Box
|
||||||
|
w={"100px"}
|
||||||
|
isTruncated={true}
|
||||||
|
display={"flex"}
|
||||||
|
>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{formatDate(item?.transaction_date)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Deposit Amount (BHD)": (
|
||||||
|
<Box w={"130px"} isTruncated={true} display={"flex"}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{/* {item.investorAmount} */}
|
||||||
|
{parseFloat(item?.transaction_amount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
{/* <Badge ms={1} colorScheme="green">{item?.transaction_amount}</Badge> */}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Support Image": (
|
||||||
|
<Text
|
||||||
|
color={"green.500"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item?.spportFile_path&&<Badge
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
colorScheme={"forestGreen"}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={import.meta.env.VITE_IMAGE_URL + item?.spportFile_path}
|
||||||
|
isExternal
|
||||||
|
display={"flex"}
|
||||||
|
alignItems={"center"}
|
||||||
|
>
|
||||||
|
<Box me={"1px"}
|
||||||
|
as="span"
|
||||||
|
cursor={"pointer"}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Box>
|
||||||
|
<ExternalLinkIcon />
|
||||||
|
</Link>
|
||||||
|
</Badge>}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
Status: (
|
||||||
|
<Box isTruncated={true} display={"flex"}>
|
||||||
|
<Badge
|
||||||
|
my={1}
|
||||||
|
fontWeight={500}
|
||||||
|
px={2}
|
||||||
|
py={"2px"}
|
||||||
|
rounded={4}
|
||||||
|
colorScheme={
|
||||||
|
item?.transactionStatus === "Approved"
|
||||||
|
? "green"
|
||||||
|
: item?.transactionStatus === "Pending"
|
||||||
|
? "yellow"
|
||||||
|
: item?.transactionStatus === "Reject"
|
||||||
|
? "red"
|
||||||
|
: "gray" // default border color if status doesn't match any condition
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.transactionStatus}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
const updatedSponsors = sponser.filter(
|
||||||
|
(sponsor) => sponsor.id !== actionId
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setSponser(updatedSponsors);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 100);
|
||||||
|
setIsLoading(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
isLoading={drawalRequestLoading}
|
||||||
|
pageSize={pageSize}
|
||||||
|
setPageSize={setPageSize}
|
||||||
|
currentPage={currentPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
totalItems={data?.data?.totalItems}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<NormalTable
|
||||||
|
isLoading={drawalRequestLoading}
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
// totalPages={10}
|
||||||
|
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<DrawalRequestApprove
|
||||||
|
// data={data?.data?.rows}
|
||||||
|
isOpen={isConfirmOpen}
|
||||||
|
onClose={onConfirmClose}
|
||||||
|
id={actionId}
|
||||||
|
// firstField={firstField}
|
||||||
|
/>
|
||||||
|
<DrawalRequestReject
|
||||||
|
isOpen={isRejectOpen}
|
||||||
|
onClose={onRejectClose}
|
||||||
|
id={actionId}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApproveHistoryMaker;
|
||||||
|
|
||||||
95
src/Pages/FawateerChecker/ApproveHistory/ConfirmHistory.jsx
Normal file
95
src/Pages/FawateerChecker/ApproveHistory/ConfirmHistory.jsx
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
useDisclosure,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
fees: yup.string().required("File name is required"),
|
||||||
|
totalAmount: yup.string().required("File name is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const ConfirmHistory = ({ isOpen, onClose, firstField }) => {
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (data) => {
|
||||||
|
console.log(data);
|
||||||
|
setFile(data.document[0]);
|
||||||
|
|
||||||
|
const newDocument = {
|
||||||
|
...data,
|
||||||
|
document: data.document[0].name, // Store the document name
|
||||||
|
status: true,
|
||||||
|
id: uuidv4(),
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
Type: getFileIcon(file.type),
|
||||||
|
};
|
||||||
|
|
||||||
|
setCreate((prevCreate) => [...prevCreate, newDocument]);
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const selectedFile = event.target.files[0];
|
||||||
|
setFile(selectedFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Confirm</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4}>
|
||||||
|
<FormLabel fontSize="sm">Withdrawal Amount</FormLabel>
|
||||||
|
<Input
|
||||||
|
focusBorderColor='green.400'
|
||||||
|
name="fileName"
|
||||||
|
{...register("fileName")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="text"
|
||||||
|
size="sm"
|
||||||
|
placeholder={"$100,000"}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button colorScheme="gray" mr={3} onClick={onClose} size={'sm'} rounded={'sm'}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button colorScheme="forestGreen" variant="solid" size={'sm'} rounded={'sm'}>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ConfirmHistory;
|
||||||
|
|
||||||
100
src/Pages/FawateerChecker/ApproveHistory/RejectHistory.jsx
Normal file
100
src/Pages/FawateerChecker/ApproveHistory/RejectHistory.jsx
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
comment: yup.string().required("Comment is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const RejectHistory = ({ isOpen, onClose, firstField }) => {
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (data) => {
|
||||||
|
console.log(data);
|
||||||
|
setFile(data.document[0]);
|
||||||
|
|
||||||
|
const newDocument = {
|
||||||
|
...data,
|
||||||
|
document: data.document[0].name, // Store the document name
|
||||||
|
comment: true,
|
||||||
|
id: uuidv4(),
|
||||||
|
Type: getFileIcon(file.type),
|
||||||
|
};
|
||||||
|
|
||||||
|
setCreate((prevCreate) => [...prevCreate, newDocument]);
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const selectedFile = event.target.files[0];
|
||||||
|
setFile(selectedFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Reject</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4}>
|
||||||
|
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||||
|
<Textarea rows={6}
|
||||||
|
focusBorderColor='green.400'
|
||||||
|
name="fileName"
|
||||||
|
{...register("fileName")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"$100,000"}
|
||||||
|
rounded={'md'}
|
||||||
|
resize={'none'}
|
||||||
|
/>
|
||||||
|
{errors.comment && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comment.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button colorScheme="gray" mr={3} onClick={onClose} size={'sm'} rounded={'sm'}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button colorScheme="forestGreen" variant="solid" size={'sm'} rounded={'sm'}>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RejectHistory;
|
||||||
|
|
||||||
416
src/Pages/FawateerChecker/ApproveRequest/ApproveRequest.jsx
Normal file
416
src/Pages/FawateerChecker/ApproveRequest/ApproveRequest.jsx
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Link,
|
||||||
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
|
import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||||
|
import Pagination from "../../../Components/Pagination";
|
||||||
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
import { useGetFawateerRequestQuery } from "../../../Services/fawateer.request.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
|
import RequestApproveModal from "./RequestApproveModal";
|
||||||
|
import RequestRejectModal from "./RequestRejectModal";
|
||||||
|
|
||||||
|
const ApproveRequest = () => {
|
||||||
|
const toast = useToast();
|
||||||
|
const { slideFromRight, fawateerRequest, setFawateerRequest } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString('en-GB', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
const {
|
||||||
|
isOpen: isConfirmOpen,
|
||||||
|
onOpen: onConfirmOpen,
|
||||||
|
onClose: onConfirmClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
const {
|
||||||
|
isOpen: isRejectOpen,
|
||||||
|
onOpen: onRejectOpen,
|
||||||
|
onClose: onRejectClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: drawalRequestLoading,
|
||||||
|
error,
|
||||||
|
refetch
|
||||||
|
} = useGetFawateerRequestQuery(
|
||||||
|
{
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
searchTerm: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(data?.data?.rows);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
// Simulate loading
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Cleanup the timer on component unmount
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ====================================================[Table Filter]================================================================
|
||||||
|
const filteredData = data?.data?.rows?.filter((item) => {
|
||||||
|
// Filter by name (case insensitive)
|
||||||
|
const name = item.firstName;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
// Filter by status
|
||||||
|
// const status = item.status;
|
||||||
|
// const statusLower = status ? "active" : "inactive";
|
||||||
|
|
||||||
|
// const statusMatches =
|
||||||
|
// statusFilter === "all" ||
|
||||||
|
// (statusFilter === "active" && status === true) ||
|
||||||
|
// (statusFilter === "inactive" && status === false);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const role = localStorage?.getItem('role')
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr.no",
|
||||||
|
"Client ID",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"E-mail ID",
|
||||||
|
"Phone Number",
|
||||||
|
"Deposit Date",
|
||||||
|
"Deposit Amount (BHD)",
|
||||||
|
"Support Image",
|
||||||
|
"Action",
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const extractedArray = filteredData?.map((item, idx) => ({
|
||||||
|
// id: item?.id,
|
||||||
|
"Sr.no": (
|
||||||
|
<Text
|
||||||
|
w={"auto"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Client ID": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.clientReference_id}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"First Name": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item.firstName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Last Name": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.lastName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"E-mail ID": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.emailAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Phone Number": (
|
||||||
|
<Box w={"100px"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.mobileNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Deposit Date": (
|
||||||
|
<Box isTruncated={true} display={'flex'} >
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{formatDate(item?.transaction_date)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Deposit Amount (BHD)": (
|
||||||
|
<Box isTruncated={true} display={'flex'} >
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{/* {item.investorAmount} */}
|
||||||
|
{parseFloat(item?.transaction_amount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
{/* <Badge ms={1} colorScheme="green">{item?.transaction_amount}</Badge> */}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Support Image": (
|
||||||
|
<Text
|
||||||
|
color={"green.500"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
colorScheme={"forestGreen"}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={import.meta.env.VITE_IMAGE_URL + item?.spportFile_path}
|
||||||
|
isExternal
|
||||||
|
display={"flex"}
|
||||||
|
alignItems={"center"}
|
||||||
|
>
|
||||||
|
<Box me={"1px"}
|
||||||
|
as="span"
|
||||||
|
cursor={"pointer"}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Box>
|
||||||
|
<ExternalLinkIcon />
|
||||||
|
</Link>
|
||||||
|
</Badge>
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Status": (
|
||||||
|
<Box isTruncated={true} display={'flex'} >
|
||||||
|
<Badge
|
||||||
|
my={1}
|
||||||
|
fontWeight={500}
|
||||||
|
px={2}
|
||||||
|
py={"2px"}
|
||||||
|
rounded={4}
|
||||||
|
colorScheme={
|
||||||
|
item?.transactionStatus === "Approved"
|
||||||
|
? "green"
|
||||||
|
: item?.transactionStatus === "Pending"
|
||||||
|
? "yellow"
|
||||||
|
: item?.transactionStatus === "Reject"
|
||||||
|
? "red"
|
||||||
|
: "gray" // default border color if status doesn't match any condition
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.transactionStatus}
|
||||||
|
</Badge>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Action: (
|
||||||
|
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||||
|
<Tooltip
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label="Approve"
|
||||||
|
bg="#fff"
|
||||||
|
color={"green.500"}
|
||||||
|
placement="left-start"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
// colorScheme="forestGreen"
|
||||||
|
// color="green.500"
|
||||||
|
rounded={"sm"}
|
||||||
|
size={"xs"}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
px={2}
|
||||||
|
py={1}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item.id);
|
||||||
|
onConfirmOpen();
|
||||||
|
}}
|
||||||
|
colorScheme="green"
|
||||||
|
variant={"solid"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
>
|
||||||
|
<CheckIcon fontSize={"12px"} />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label="Reject"
|
||||||
|
bg="#fff"
|
||||||
|
color={"red.500"}
|
||||||
|
placement="left-start"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
colorScheme="red"
|
||||||
|
// color="red.500"
|
||||||
|
rounded={"sm"}
|
||||||
|
size={"xs"}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
px={2}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item.id);
|
||||||
|
onRejectOpen();
|
||||||
|
}}
|
||||||
|
py={1}
|
||||||
|
// variant={"solid"}
|
||||||
|
>
|
||||||
|
<CloseIcon fontSize={"10px"} />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
const updatedSponsors = sponser.filter(
|
||||||
|
(sponsor) => sponsor.id !== actionId
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setSponser(updatedSponsors);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 100);
|
||||||
|
setIsLoading(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
isLoading={drawalRequestLoading}
|
||||||
|
pageSize={pageSize}
|
||||||
|
setPageSize={setPageSize}
|
||||||
|
currentPage={currentPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
totalItems={data?.data?.totalItems}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<NormalTable
|
||||||
|
isLoading={drawalRequestLoading}
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
// totalPages={10}
|
||||||
|
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
<RequestApproveModal
|
||||||
|
// data={data?.data?.rows}
|
||||||
|
isOpen={isConfirmOpen}
|
||||||
|
onClose={onConfirmClose}
|
||||||
|
id={actionId}
|
||||||
|
// firstField={firstField}
|
||||||
|
/>
|
||||||
|
<RequestRejectModal
|
||||||
|
isOpen={isRejectOpen}
|
||||||
|
onClose={onRejectClose}
|
||||||
|
id={actionId}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApproveRequest;
|
||||||
|
|
||||||
177
src/Pages/FawateerChecker/ApproveRequest/RequestApproveModal.jsx
Normal file
177
src/Pages/FawateerChecker/ApproveRequest/RequestApproveModal.jsx
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormHelperText,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useDepositRejectMutation } from "../../../Services/deposit.request.service";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
import { useApproveCommentMutation } from "../../../Services/fawateer.request.service";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
// checkerComment: yup.string().required("Comment is required")
|
||||||
|
// .max(50, "Investment name cannot be more than 50 characters"),
|
||||||
|
checkerComment: yup
|
||||||
|
.string()
|
||||||
|
.required("Comment is required")
|
||||||
|
.max(200, "Approve Comment cannot be more than 200 characters"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const RequestApproveModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||||
|
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
watch,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ approveFawateer ] = useApproveCommentMutation()
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = async(data) => {
|
||||||
|
console.log(data, "tewxttttt");
|
||||||
|
setIsBtnLoading(true)
|
||||||
|
try {
|
||||||
|
const res = await approveFawateer({data,id})
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}else if(res?.data){
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
onClose()
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}else{
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={'error'} message={"Something went wrong"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const selectedFile = event.target.files[0];
|
||||||
|
setFile(selectedFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const { data, isLoading } =
|
||||||
|
(id, {
|
||||||
|
skip: !id,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
reset({
|
||||||
|
investorAmount: data?.data?.investorAmount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [data, reset]);
|
||||||
|
|
||||||
|
const heandleOnClose = () =>{
|
||||||
|
reset()
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isCentered isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Approve Comment</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
{isLoading ? (
|
||||||
|
<FullscreenLoaders height={"50vh"} />
|
||||||
|
) : (
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4} isRequired>
|
||||||
|
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="checkerComment"
|
||||||
|
{...register("checkerComment")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"Enter your checkerComment...."}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
maxLength={200}
|
||||||
|
/>
|
||||||
|
{errors.checkerComment && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.checkerComment.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
<FormHelperText fontSize="xs" color="gray.500">
|
||||||
|
Maximum length should be 200 characters. You have entered
|
||||||
|
{watch("checkerComment")?.length || 0} characters.
|
||||||
|
</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RequestApproveModal;
|
||||||
165
src/Pages/FawateerChecker/ApproveRequest/RequestRejectModal.jsx
Normal file
165
src/Pages/FawateerChecker/ApproveRequest/RequestRejectModal.jsx
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useDepositRejectMutation } from "../../../Services/deposit.request.service";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
import { useRejectCommentMutation } from "../../../Services/fawateer.request.service";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
comments: yup.string().required("Comment is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||||
|
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ rejectFawateer ] = useRejectCommentMutation()
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = async(data) => {
|
||||||
|
console.log(data, "tewxttttt");
|
||||||
|
setIsBtnLoading(true)
|
||||||
|
try {
|
||||||
|
const res = await rejectFawateer({data,id})
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}else if(res?.data){
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
onClose()
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}else{
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox status={'error'} message={"Something went wrong"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const selectedFile = event.target.files[0];
|
||||||
|
setFile(selectedFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const { data, isLoading } =
|
||||||
|
(id, {
|
||||||
|
skip: !id,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
reset({
|
||||||
|
investorAmount: data?.data?.investorAmount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [data, reset]);
|
||||||
|
|
||||||
|
const heandleOnClose = () =>{
|
||||||
|
reset()
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isCentered isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Reject Comment</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
{isLoading ? (
|
||||||
|
<FullscreenLoaders height={"50vh"} />
|
||||||
|
) : (
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4} isRequired>
|
||||||
|
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="comments"
|
||||||
|
{...register("comments")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
{errors.comments && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comments.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RequestRejectModal;
|
||||||
@@ -30,9 +30,9 @@ import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
|||||||
import CurrencyInput from "../../../Components/CurrencyInput";
|
import CurrencyInput from "../../../Components/CurrencyInput";
|
||||||
|
|
||||||
const cashDetails = yup.object().shape({
|
const cashDetails = yup.object().shape({
|
||||||
transactionDate: yup.string().required("Artifact name is required"),
|
transactionDate: yup.string().required("Date is required"),
|
||||||
ioTransType_xid: yup.number().required("Artifact name is required"),
|
ioTransType_xid: yup.number().required("Cash transaction is required"),
|
||||||
transactionAmount: yup.number().required("Artifact name is required"),
|
transactionAmount: yup.number().required("Transaction Amount is required"),
|
||||||
comments: yup.string().notRequired(),
|
comments: yup.string().notRequired(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -140,7 +140,8 @@ const AddCashDetails = ({ isOpen, onClose, firstField, actionId, setActionId, da
|
|||||||
name="transactionDate"
|
name="transactionDate"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input {...field} fontSize={"sm"} type="date" size={"sm"} />
|
<Input
|
||||||
|
focusBorderColor="forestGreen.300" {...field} fontSize={"sm"} type="date" size={"sm"} />
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
|
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
|
||||||
@@ -160,6 +161,7 @@ const AddCashDetails = ({ isOpen, onClose, firstField, actionId, setActionId, da
|
|||||||
placeholder="Select an option"
|
placeholder="Select an option"
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
size={"sm"}
|
size={"sm"}
|
||||||
|
focusBorderColor="forestGreen.300"
|
||||||
>
|
>
|
||||||
{IODetails?.ioCashTransaction?.map(({ id, transactionName }) => (
|
{IODetails?.ioCashTransaction?.map(({ id, transactionName }) => (
|
||||||
<option key={id} value={id}>
|
<option key={id} value={id}>
|
||||||
@@ -199,7 +201,8 @@ const AddCashDetails = ({ isOpen, onClose, firstField, actionId, setActionId, da
|
|||||||
name="comments"
|
name="comments"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Textarea {...field} textAlign={'right'} fontSize={"sm"} type="text" size={"sm"} />
|
<Textarea {...field} textAlign={'left'}
|
||||||
|
focusBorderColor="forestGreen.300" fontSize={"sm"} type="text" size={"sm"} />
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
|
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ import {
|
|||||||
FormControl,
|
FormControl,
|
||||||
FormErrorMessage,
|
FormErrorMessage,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
|
HStack,
|
||||||
Input,
|
Input,
|
||||||
Select,
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
|
Text,
|
||||||
Textarea,
|
Textarea,
|
||||||
|
VStack,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
@@ -31,8 +34,8 @@ import {
|
|||||||
import { formatDatee } from "../../../Components/FormField";
|
import { formatDatee } from "../../../Components/FormField";
|
||||||
|
|
||||||
const ioNav = yup.object().shape({
|
const ioNav = yup.object().shape({
|
||||||
transactionDate: yup.string().required("Artifact name is required"),
|
transactionDate: yup.string().required("Date is required"),
|
||||||
transactionAmount: yup.number().required("Artifact name is required"),
|
transactionAmount: yup.number().required("New NAV is required"),
|
||||||
comments: yup.string().notRequired(),
|
comments: yup.string().notRequired(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -85,10 +88,10 @@ import { formatDatee } from "../../../Components/FormField";
|
|||||||
});
|
});
|
||||||
handleClose()
|
handleClose()
|
||||||
}else if(res?.error?.status === 400){
|
}else if(res?.error?.status === 400){
|
||||||
setIsLoading(false);
|
|
||||||
toast({
|
toast({
|
||||||
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
||||||
});
|
});
|
||||||
|
handleClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -110,6 +113,7 @@ import { formatDatee } from "../../../Components/FormField";
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
setIsLoading(false);
|
||||||
setAlert(false)
|
setAlert(false)
|
||||||
onClose()
|
onClose()
|
||||||
reset({
|
reset({
|
||||||
@@ -124,6 +128,14 @@ import { formatDatee } from "../../../Components/FormField";
|
|||||||
|
|
||||||
const today = formatDatee(new Date(), 'yyyy-MM-dd');
|
const today = formatDatee(new Date(), 'yyyy-MM-dd');
|
||||||
|
|
||||||
|
function calculatePercentage(newNav, currNav) {
|
||||||
|
const per = (newNav - currNav) / currNav * 100
|
||||||
|
return per.toFixed(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
console.log(calculatePercentage(1092500, 976070));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -161,7 +173,7 @@ const today = formatDatee(new Date(), 'yyyy-MM-dd');
|
|||||||
|
|
||||||
|
|
||||||
<FormControl isInvalid={errors.transactionAmount} isRequired>
|
<FormControl isInvalid={errors.transactionAmount} isRequired>
|
||||||
<FormLabel fontSize={"sm"}>Transaction Amount</FormLabel>
|
<FormLabel fontSize={"sm"}>New NAV</FormLabel>
|
||||||
<Controller
|
<Controller
|
||||||
name="transactionAmount"
|
name="transactionAmount"
|
||||||
control={control}
|
control={control}
|
||||||
@@ -175,6 +187,25 @@ const today = formatDatee(new Date(), 'yyyy-MM-dd');
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
|
|
||||||
|
<HStack justify={'start'} gap={10} bg={'green.100'} p={3} rounded={'md'} shadow={'md'}>
|
||||||
|
<VStack align={'start'}>
|
||||||
|
<Text as={'span'} fontSize={'sm'} fontWeight={500}>Current nav</Text>
|
||||||
|
<Text as={'span'} fontSize={'sm'}>
|
||||||
|
{parseFloat(IODetails?.ioNAV || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
|
||||||
|
|
||||||
|
<VStack align={'start'}>
|
||||||
|
<Text as={'span'} fontSize={'sm'} fontWeight={500}>Live return %</Text>
|
||||||
|
<Text as={'span'} fontSize={'sm'}>{calculatePercentage(watch()?.transactionAmount||IODetails?.ioNAV,IODetails?.ioNAV)}</Text>
|
||||||
|
</VStack>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormControl isInvalid={errors.comments}>
|
<FormControl isInvalid={errors.comments}>
|
||||||
<FormLabel fontSize={"sm"}>Comments</FormLabel>
|
<FormLabel fontSize={"sm"}>Comments</FormLabel>
|
||||||
|
|||||||
@@ -16,14 +16,12 @@ import { useParams } from "react-router-dom";
|
|||||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
import { useGetIOprepopulateDataQuery } from "../../../Services/io.service";
|
import { useGetIOprepopulateDataQuery } from "../../../Services/io.service";
|
||||||
import UnderConstruction from "../../UnderConstruction";
|
import UnderConstruction from "../../UnderConstruction";
|
||||||
|
import Destribution from "./Destribution";
|
||||||
|
|
||||||
const CreateIO = () => {
|
const CreateIO = () => {
|
||||||
const id = useParams()?.id;
|
const id = useParams()?.id;
|
||||||
const { data, error, isLoading } = useGetIOprepopulateDataQuery();
|
const { data, error, isLoading } = useGetIOprepopulateDataQuery();
|
||||||
|
|
||||||
|
|
||||||
// console.log(data?.data);
|
|
||||||
|
|
||||||
const enableNextTab = (index) => {
|
const enableNextTab = (index) => {
|
||||||
setTabs((prevTabs) => {
|
setTabs((prevTabs) => {
|
||||||
const newTabs = [...prevTabs];
|
const newTabs = [...prevTabs];
|
||||||
@@ -44,38 +42,38 @@ const CreateIO = () => {
|
|||||||
{
|
{
|
||||||
label: "Investment documents",
|
label: "Investment documents",
|
||||||
Content: InvestmentDocument,
|
Content: InvestmentDocument,
|
||||||
isDisabled: id ? false : true,
|
isDisabled: id ? true : true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Key merits",
|
label: "Key merits",
|
||||||
Content: KeyMerits,
|
Content: KeyMerits,
|
||||||
isDisabled: id ? false : true,
|
isDisabled: id ? true : true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "IO artifacts",
|
label: "IO artifacts",
|
||||||
Content: IOArtifacts,
|
Content: IOArtifacts,
|
||||||
isDisabled: id ? false : true,
|
isDisabled: id ? true : true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Investors",
|
label: "Investors",
|
||||||
// Content: Investors,
|
Content: Investors,
|
||||||
Content: UnderConstruction,
|
// Content: UnderConstruction,
|
||||||
isDisabled: id ? false : true,
|
isDisabled: id ? true : true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "IO Cash Detail",
|
label: "IO Cash Detail",
|
||||||
Content: IOCashDetails,
|
Content: IOCashDetails,
|
||||||
isDisabled: id ? false : true,
|
isDisabled: id ? true : true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "IO NAV Details",
|
label: "IO NAV Details",
|
||||||
Content: IONAVDetails,
|
Content: IONAVDetails,
|
||||||
isDisabled: id ? false : true,
|
isDisabled: id ? true : true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Distribution to Investors",
|
label: "Distribution to Investors",
|
||||||
Content: IONAVDetails,
|
Content: Destribution,
|
||||||
isDisabled: id ? false : true,
|
isDisabled: id ? true : true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,228 @@
|
|||||||
import React from 'react'
|
import React, { useContext, useEffect, useRef, useState } from 'react'
|
||||||
|
import GlobalStateContext from '../../../Contexts/GlobalStateContext';
|
||||||
|
import { Box, HStack, Input,Text, Table, Tbody, Th, Tr, Avatar, useDisclosure,Button, Badge } from '@chakra-ui/react';
|
||||||
|
import { OPACITY_ON_LOAD } from '../../../Layout/animations';
|
||||||
|
import Pagination from '../../../Components/Pagination';
|
||||||
|
import NormalTable from '../../../Components/DataTable/NormalTable';
|
||||||
|
import CustomAlertDialog from '../../../Components/CustomAlertDialog';
|
||||||
|
import { formatDatee } from '../../../Components/FormField';
|
||||||
|
import { AddIcon } from '@chakra-ui/icons';
|
||||||
|
import AddIONav from './AddIONav';
|
||||||
|
|
||||||
const Distribution = () => {
|
const Destribution = () => {
|
||||||
|
const { navDetails, setNavDetails, IODetails } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
const firstField = useRef();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
|
||||||
|
console.log(IODetails?.ioNAVHistory);
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString('en-GB', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Simulate loading
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Cleanup the timer on component unmount
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Table setup
|
||||||
|
const tableHeadRow = [
|
||||||
|
// "Sr.No",
|
||||||
|
"Date",
|
||||||
|
"Amount",
|
||||||
|
"% of Investment"
|
||||||
|
];
|
||||||
|
|
||||||
|
// Table filter
|
||||||
|
const filteredData = IODetails?.distributionToInvestor?.filter((item) => {
|
||||||
|
const name = item?.transactionAmount;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
return nameMatches;
|
||||||
|
}).sort((b, a) => new Date(a.transactionDate) - new Date(b.transactionDate));
|
||||||
|
|
||||||
|
const extractedArray=filteredData?.map((item, index) => ({
|
||||||
|
id: item?.id,
|
||||||
|
"Sr.No": <Text
|
||||||
|
justifyContent={"start"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-start web-text-small"
|
||||||
|
>{item?.id}</Text>,
|
||||||
|
"Date": (
|
||||||
|
<Text
|
||||||
|
justifyContent={"center"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{formatDate(item.transactionDate)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Amount": (
|
||||||
|
<Text
|
||||||
|
justifyContent={"center"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>$</Badge>
|
||||||
|
{`${parseFloat(item.transactionAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"% of Investment": (
|
||||||
|
<Text
|
||||||
|
justifyContent={"center"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{parseFloat(item.percentage).toFixed(2)}%
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
const updatedNav = navDetails.filter(
|
||||||
|
(sponsor) => sponsor.id !== actionId
|
||||||
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setNavDetails(updatedNav);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 100);
|
||||||
|
setIsLoading(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Total = () => {
|
||||||
return (
|
return (
|
||||||
<div>Distribution</div>
|
<Table size="sm">
|
||||||
|
<Tbody>
|
||||||
|
<Tr backgroundColor="gray.50">
|
||||||
|
<Th
|
||||||
|
textAlign={"center"}
|
||||||
|
p={3}
|
||||||
|
width="60px"
|
||||||
|
color={"#004118"}
|
||||||
|
whiteSpace="normal"
|
||||||
|
wordBreak="normal"
|
||||||
|
overflowWrap="normal"
|
||||||
|
>
|
||||||
|
Total
|
||||||
|
</Th>
|
||||||
|
<Th
|
||||||
|
textAlign={"center"}
|
||||||
|
p={3}
|
||||||
|
width="90px"
|
||||||
|
color={"#004118"}
|
||||||
|
whiteSpace="normal"
|
||||||
|
wordBreak="normal"
|
||||||
|
overflowWrap="normal"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>$</Badge>{IODetails?.total_distributeToInvestor_amt?.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
||||||
|
</Th>
|
||||||
|
<Th
|
||||||
|
textAlign={"center"}
|
||||||
|
p={3}
|
||||||
|
width="100px"
|
||||||
|
color={"#004118"}
|
||||||
|
whiteSpace="normal"
|
||||||
|
wordBreak="normal"
|
||||||
|
overflowWrap="normal"
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
</Th>
|
||||||
|
</Tr>
|
||||||
|
</Tbody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (<Box {...OPACITY_ON_LOAD} pb={0}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
pb={3}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<NormalTable
|
||||||
|
centered={true}
|
||||||
|
emptyMessage={`We don't have any Sponers`}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
isLoading={isLoading}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
total={<Total/>}
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<AddIONav
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
firstField={firstField} />
|
||||||
|
|
||||||
|
|
||||||
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Distribution
|
export default Destribution
|
||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
} from "@chakra-ui/icons";
|
} from "@chakra-ui/icons";
|
||||||
import IOArtifactsAdd from "../IOArtifactsAdd";
|
import IOArtifactsAdd from "../IOArtifactsAdd";
|
||||||
import IOArtifactsVideo from "./IOArtifactsVideo";
|
import IOArtifactsVideo from "./IOArtifactsVideo";
|
||||||
import SetDisplayOrder from "./SetDisplayOrder";
|
import SetDisplayOrder from "./SetDisplayOrderKeyMerits";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
useDeleteImageArtifactsMutation,
|
useDeleteImageArtifactsMutation,
|
||||||
@@ -32,6 +32,8 @@ import {
|
|||||||
import { getFileNameFromPath } from "../../../Constants/Constants";
|
import { getFileNameFromPath } from "../../../Constants/Constants";
|
||||||
import ImageViewer from "../../../Components/ImageViewer";
|
import ImageViewer from "../../../Components/ImageViewer";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
import SetDisplayOrderIOArtifactsImages from "./SetDisplayOrderIOArtifactsImages";
|
||||||
|
import SetDisplayOrderIOArtifactsVideo from "./SetDisplayOrderIOArtifactsVideo";
|
||||||
|
|
||||||
const IOArtifacts = ({ enableNextTab, index, data }) => {
|
const IOArtifacts = ({ enableNextTab, index, data }) => {
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -143,7 +145,14 @@ const IOArtifacts = ({ enableNextTab, index, data }) => {
|
|||||||
|
|
||||||
const tableHeadRow = ["Sr.no", "File Name", "View image", "Action"];
|
const tableHeadRow = ["Sr.no", "File Name", "View image", "Action"];
|
||||||
|
|
||||||
const extractedArray = IObyID?.data?.artifactsImage?.map((item, index) => ({
|
console.log(IObyID?.data?.artifactsImage);
|
||||||
|
// console.log(filteredData);
|
||||||
|
const sortedDataImage = [...(IObyID?.data?.artifactsImage || [])]?.sort(
|
||||||
|
(a, b) => a?.displayOrder - b?.displayOrder
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const extractedArray = sortedDataImage?.map((item, index) => ({
|
||||||
"Sr.no": (
|
"Sr.no": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
@@ -246,6 +255,17 @@ const IOArtifacts = ({ enableNextTab, index, data }) => {
|
|||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
console.log(IObyID?.data?.artifactsVideo);
|
||||||
|
// console.log(filteredData);
|
||||||
|
const sortedDataVideo = [...(IObyID?.data?.artifactsVideo || [])]?.sort(
|
||||||
|
(a, b) => a?.displayOrder - b?.displayOrder
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const tableHeadRowTwo = [
|
const tableHeadRowTwo = [
|
||||||
"Sr.no",
|
"Sr.no",
|
||||||
"File Name",
|
"File Name",
|
||||||
@@ -253,7 +273,7 @@ const IOArtifacts = ({ enableNextTab, index, data }) => {
|
|||||||
"Action",
|
"Action",
|
||||||
];
|
];
|
||||||
|
|
||||||
const extractedArrayTwo = IObyID?.data?.artifactsVideo?.map(
|
const extractedArrayTwo = sortedDataVideo?.map(
|
||||||
(item, index) => ({
|
(item, index) => ({
|
||||||
"Sr.no": (
|
"Sr.no": (
|
||||||
<Text
|
<Text
|
||||||
@@ -354,7 +374,7 @@ const IOArtifacts = ({ enableNextTab, index, data }) => {
|
|||||||
<HStack>
|
<HStack>
|
||||||
|
|
||||||
|
|
||||||
{IObyID?.data?.artifactsImage?.length !== 0 &&<SetDisplayOrder data={IObyID?.data?.artifactsImage} />}
|
{IObyID?.data?.artifactsImage?.length !== 0 &&<SetDisplayOrderIOArtifactsImages data={sortedDataImage} />}
|
||||||
<Button
|
<Button
|
||||||
leftIcon={<AddIcon />}
|
leftIcon={<AddIcon />}
|
||||||
onClick={onOpen}
|
onClick={onOpen}
|
||||||
@@ -390,7 +410,7 @@ const IOArtifacts = ({ enableNextTab, index, data }) => {
|
|||||||
Manage IO videos
|
Manage IO videos
|
||||||
</Box>
|
</Box>
|
||||||
<HStack>
|
<HStack>
|
||||||
{IObyID?.data?.artifactsVideo?.length !== 0 &&<SetDisplayOrder data={IObyID?.data?.artifactsVideo} />}
|
{IObyID?.data?.artifactsVideo?.length !== 0 &&<SetDisplayOrderIOArtifactsVideo data={sortedDataVideo} />}
|
||||||
<Button
|
<Button
|
||||||
leftIcon={<AddIcon />}
|
leftIcon={<AddIcon />}
|
||||||
onClick={onOpenVideo}
|
onClick={onOpenVideo}
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ const investmentVideoSchema = yup.object().shape({
|
|||||||
artifactName: yup.string().required("Artifact name is required"),
|
artifactName: yup.string().required("Artifact name is required"),
|
||||||
artifactStreamingURL: yup.string()
|
artifactStreamingURL: yup.string()
|
||||||
.required("Artifact streaming URL is required")
|
.required("Artifact streaming URL is required")
|
||||||
.url("Invalid URL format")
|
.url("Invalid URL format"),
|
||||||
.matches(/\.mp4$/, "URL must end with .mp4"),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const IOArtifactsAdd = ({ isOpen, onClose, firstField, actionId, setActionId, data }) => {
|
const IOArtifactsAdd = ({ isOpen, onClose, firstField, actionId, setActionId, data }) => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
|
Badge,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
HStack,
|
HStack,
|
||||||
@@ -23,6 +24,8 @@ import ToastBox from "../../../Components/ToastBox";
|
|||||||
import { debounce } from "../../Master/Sponser/AddSponser";
|
import { debounce } from "../../Master/Sponser/AddSponser";
|
||||||
import { AddIcon } from "@chakra-ui/icons";
|
import { AddIcon } from "@chakra-ui/icons";
|
||||||
import AddCashDetails from "./AddCashDetails";
|
import AddCashDetails from "./AddCashDetails";
|
||||||
|
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||||
|
import { exportToExcel, exportToExcelNew } from "../../../Constants/Constants";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
@@ -30,7 +33,8 @@ const IOCashDetails = () => {
|
|||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const firstField = useRef();
|
const firstField = useRef();
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const { caseDetails, setCaseDetails, IODetails } = useContext(GlobalStateContext);
|
const { caseDetails, setCaseDetails, IODetails } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
@@ -48,6 +52,14 @@ const IOCashDetails = () => {
|
|||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Calculate totals
|
// Calculate totals
|
||||||
const totalAmount = caseDetails.reduce(
|
const totalAmount = caseDetails.reduce(
|
||||||
(acc, caseDetail) => acc + caseDetail.amount,
|
(acc, caseDetail) => acc + caseDetail.amount,
|
||||||
@@ -76,17 +88,18 @@ const IOCashDetails = () => {
|
|||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
// Table filter
|
// Table filter
|
||||||
const filteredData = IODetails?.ioCashHistory?.filter((item) => {
|
const filteredData = IODetails?.ioCashHistory
|
||||||
|
?.filter((item) => {
|
||||||
const name = item.transactionType;
|
const name = item.transactionType;
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
return nameMatches;
|
return nameMatches;
|
||||||
}).sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
|
})
|
||||||
|
.sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = filteredData?.map((item, index) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Date": (
|
Date: (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={"center"}
|
justifyContent={"center"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -94,7 +107,7 @@ const IOCashDetails = () => {
|
|||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{item?.transactionDate}
|
{formatDate(item?.transactionDate)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Transaction type": (
|
"Transaction type": (
|
||||||
@@ -108,18 +121,25 @@ const IOCashDetails = () => {
|
|||||||
{item?.transactionType}
|
{item?.transactionType}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Amount": (
|
Amount: (
|
||||||
<Text
|
<Text
|
||||||
justifyContent ={"center"}
|
justifyContent={"left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{`$${parseFloat(item.transactionAmount||0).toLocaleString()}`}
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{/* {parseFloat(item.transactionAmount || 0).toLocaleString()} */}
|
||||||
|
{`${parseFloat(item.transactionAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Comments": (
|
Comments: (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={"center"}
|
justifyContent={"center"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -139,8 +159,12 @@ const IOCashDetails = () => {
|
|||||||
gap={2}
|
gap={2}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
|
<Avatar
|
||||||
<Avatar size='sm' name={item.creator?.firstName} src={item.creator?.profilePhoto} />{item.creator?.firstName}
|
size="sm"
|
||||||
|
name={item.creator?.firstName}
|
||||||
|
src={item.creator?.profilePhoto}
|
||||||
|
/>
|
||||||
|
{item.creator?.firstName}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Update On": (
|
"Update On": (
|
||||||
@@ -151,11 +175,32 @@ const IOCashDetails = () => {
|
|||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{item.updateOn}
|
{formatDate(item.updatedAt)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const customHeaders = [
|
||||||
|
{ label: "Date", key: "transactionDate" },
|
||||||
|
{ label: "Transaction type", key: "transactionType" },
|
||||||
|
{ label: "Amount", key: "transactionAmount" },
|
||||||
|
{ label: "Comments", key: "comments" },
|
||||||
|
// { label: "Update by", key: "creator" },
|
||||||
|
// { label: "Update On", key: "updateOn" },
|
||||||
|
// Add more headers as needed
|
||||||
|
];
|
||||||
|
|
||||||
|
const ioCashExporteDetails = IODetails?.ioCashHistory?.map((item, index) =>({
|
||||||
|
"Date": item?.transactionDate,
|
||||||
|
"Transaction type": item?.transactionType,
|
||||||
|
"Amount":parseFloat(item?.transactionAmount) || 0,
|
||||||
|
"Comments": item?.comments
|
||||||
|
}))
|
||||||
|
|
||||||
|
console.log(ioCashExporteDetails);
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
const updatedSponsors = sponser.filter(
|
const updatedSponsors = sponser.filter(
|
||||||
(sponsor) => sponsor.id !== actionId
|
(sponsor) => sponsor.id !== actionId
|
||||||
@@ -268,8 +313,36 @@ const IOCashDetails = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
{IODetails?.isInvestedAmount ? <Button onClick={onOpen} leftIcon={<AddIcon/>} colorScheme="forestGreen" size={'sm'} rounded={'sm'} fontSize={'xs'} >Add IO Cash</Button>:null}
|
<HStack display={"flex"} alignItems={"center"}>
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
exportToExcelNew(ioCashExporteDetails, "IO Cash History")
|
||||||
|
}
|
||||||
|
leftIcon={<LuFileSpreadsheet />}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
|
||||||
|
isDisabled={ioCashExporteDetails?.length === 0}
|
||||||
|
>
|
||||||
|
Export xls
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{IODetails?.isInvestedAmount ? (
|
||||||
|
<Button
|
||||||
|
onClick={onOpen}
|
||||||
|
leftIcon={<AddIcon />}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
>
|
||||||
|
Add IO Cash
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -294,23 +367,11 @@ const IOCashDetails = () => {
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<AddCashDetails
|
<AddCashDetails
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
firstField={firstField} />
|
firstField={firstField}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ import { useForm } from "react-hook-form";
|
|||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
import { generateUniqueId } from "../../../Contexts/GlobalStateProvider";
|
|
||||||
import { useGetInvestmentTypesQuery } from "../../../Services/investment.type.service";
|
|
||||||
import { useGetActiveSponserMasterQuery } from "../../../Services/sponser.service";
|
|
||||||
import {
|
import {
|
||||||
useCreateIOMutation,
|
useCreateIOMutation,
|
||||||
useGetIOByIdQuery,
|
useGetIOByIdQuery,
|
||||||
@@ -16,25 +13,10 @@ import {
|
|||||||
} from "../../../Services/io.service";
|
} from "../../../Services/io.service";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import {
|
import {
|
||||||
Input,
|
|
||||||
Table,
|
|
||||||
Tbody,
|
|
||||||
Td,
|
|
||||||
Th,
|
|
||||||
Thead,
|
|
||||||
Tr,
|
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { formatDate } from "../../Master/Sponser/Sponsers";
|
|
||||||
|
|
||||||
import behrain from "../../../assets/bahrain_flag.png";
|
|
||||||
import kuwait from "../../../assets/kuwait_flag.png";
|
|
||||||
import oman from "../../../assets/oman_flag.png";
|
|
||||||
import qatar from "../../../assets/qatar_flag.png";
|
|
||||||
import uae from "../../../assets/uae_flag.png";
|
|
||||||
import saudi from "../../../assets/saudi_arabia_flag.png";
|
|
||||||
import { formatDatee } from "../../../Components/FormField";
|
import { formatDatee } from "../../../Components/FormField";
|
||||||
import { removeTrailingZeros } from "../../../Constants/Constants";
|
import { formatDateToYYYYMMDD, removeTrailingZeros } from "../../../Constants/Constants";
|
||||||
|
|
||||||
const schema = yup.object().shape({
|
const schema = yup.object().shape({
|
||||||
investmentNameEnglish: yup
|
investmentNameEnglish: yup
|
||||||
@@ -69,7 +51,6 @@ const schema = yup.object().shape({
|
|||||||
.typeError("Goal Amount is must be number")
|
.typeError("Goal Amount is must be number")
|
||||||
.required('Goal amount is required')
|
.required('Goal amount is required')
|
||||||
.positive('Goal amount must be a positive number'),
|
.positive('Goal amount must be a positive number'),
|
||||||
|
|
||||||
closingDate: yup
|
closingDate: yup
|
||||||
.date()
|
.date()
|
||||||
.notRequired("Closing date is required")
|
.notRequired("Closing date is required")
|
||||||
@@ -89,7 +70,7 @@ const schema = yup.object().shape({
|
|||||||
InvestmentDetails: yup.string().notRequired(),
|
InvestmentDetails: yup.string().notRequired(),
|
||||||
|
|
||||||
comment: yup.string().notRequired()
|
comment: yup.string().notRequired()
|
||||||
.min(10, "Comment must be at least 10 characters long")
|
// .min(10, "Comment must be at least 10 characters long")
|
||||||
.max(100, "Comment must be at most 100 characters long"),
|
.max(100, "Comment must be at most 100 characters long"),
|
||||||
|
|
||||||
expectedReturn: yup
|
expectedReturn: yup
|
||||||
@@ -97,22 +78,29 @@ const schema = yup.object().shape({
|
|||||||
.required("Expected return is required"),
|
.required("Expected return is required"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const IODetails = ({ enableNextTab, index, data }) => {
|
const IODetails = ({ enableNextTab, index, data }) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
|
|
||||||
const handleInputChange = (index, newValue) => {
|
const handleInputChangeCreate = (index, newValue) => {
|
||||||
|
|
||||||
const updatedValues = [...values];
|
const updatedValues = [...values];
|
||||||
updatedValues[index].value = newValue;
|
updatedValues[index].value = newValue;
|
||||||
setValues(updatedValues);
|
setValues(updatedValues);
|
||||||
|
console.log(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChangeEdit = (index, newValue) => {
|
||||||
|
// Allow only whole numbers using regex
|
||||||
|
if (/^\d*$/.test(newValue)) {
|
||||||
|
const updatedValues = [...values];
|
||||||
|
updatedValues[index].value = newValue;
|
||||||
|
setValues(updatedValues);
|
||||||
|
console.log(values);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ======================[ States ]
|
// ======================[ States ]
|
||||||
@@ -132,6 +120,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
isLoading: IObyIDisLoading,
|
isLoading: IObyIDisLoading,
|
||||||
error: IObyIDerror,
|
error: IObyIDerror,
|
||||||
} = useGetIOByIdQuery(id, { skip: !id });
|
} = useGetIOByIdQuery(id, { skip: !id });
|
||||||
|
console.log(IObyID);
|
||||||
|
|
||||||
const [creatIO] = useCreateIOMutation();
|
const [creatIO] = useCreateIOMutation();
|
||||||
const [updateIO] = useUpdateIOMutation();
|
const [updateIO] = useUpdateIOMutation();
|
||||||
@@ -165,20 +154,89 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const minInvestmentById = IObyID?.data?.minInvestmentAmt?.map(({minInvestmentAmt, country, currencyCode, country_xid,id })=>{
|
||||||
|
console.log(currencyCode);
|
||||||
const minInvestmentById = IObyID?.data?.minInvestmentAmt?.map(({minInvestmentAmt, country, country_xid, })=>{
|
|
||||||
return{
|
return{
|
||||||
|
_id:id,
|
||||||
id:country_xid,
|
id:country_xid,
|
||||||
country: country?.countryName,
|
country: country?.countryName,
|
||||||
value: removeTrailingZeros(minInvestmentAmt),
|
value: removeTrailingZeros(minInvestmentAmt),
|
||||||
logo: country?.flagIcon,
|
logo: country?.flagIcon,
|
||||||
curr: country?.countryCode,
|
curr: currencyCode,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const schemaEdit = yup.object().shape({
|
||||||
|
investmentNameEnglish: yup
|
||||||
|
.string()
|
||||||
|
.required("IO name in English is required")
|
||||||
|
.min(3, "IO name in English must be at least 3 characters long")
|
||||||
|
.max(150, "IO name in English must be at most 150 characters long"),
|
||||||
|
|
||||||
|
investmentNameArabic: yup
|
||||||
|
.string()
|
||||||
|
.required("IO name in Arabic is required")
|
||||||
|
.min(3, "IO name in Arabic must be at least 3 characters long")
|
||||||
|
.max(50, "IO name in Arabic must be at most 50 characters long"),
|
||||||
|
|
||||||
|
descriptionEnglish: yup
|
||||||
|
.string()
|
||||||
|
.required("Description in English is required")
|
||||||
|
.min(10, "Description in English must be at least 10 characters long")
|
||||||
|
.max(1000, "Description in English must be at most 1000 characters long"),
|
||||||
|
|
||||||
|
descriptionArabic: yup
|
||||||
|
.string()
|
||||||
|
.required("Description in Arabic is required")
|
||||||
|
.min(10, "Description in Arabic must be at least 10 characters long")
|
||||||
|
.max(2000, "Description in Arabic must be at most 500 characters long"),
|
||||||
|
expectedReturnArabic: yup
|
||||||
|
.string()
|
||||||
|
.required("Expected return in Arabic is required"),
|
||||||
|
|
||||||
|
goalAmount: yup
|
||||||
|
.number()
|
||||||
|
.typeError("Goal Amount is must be number")
|
||||||
|
.required('Goal amount is required')
|
||||||
|
.positive('Goal amount must be a positive number')
|
||||||
|
.min(IObyID?.data?.totalAmtInvestmentInUSD, `Goal amount should not be lesser then amount raised ${IObyID?.data?.totalAmtInvestmentInUSD}`),
|
||||||
|
closingDate: yup
|
||||||
|
.date()
|
||||||
|
.notRequired("Closing date is required")
|
||||||
|
.min(new Date(), "Closing date cannot be in the past"),
|
||||||
|
|
||||||
|
holdingPeriod: yup.string().required("Holding period is required"),
|
||||||
|
holdingPeriodArabic: yup.string().required("Holding period is required"),
|
||||||
|
isShariah: yup.string().required("CheckBox is required"),
|
||||||
|
|
||||||
|
|
||||||
|
// minInvestmentAmount: yup
|
||||||
|
// .number()
|
||||||
|
// .required("Minimum investment is required")
|
||||||
|
// .positive("Minimum investment must be a positive number")
|
||||||
|
// .min(1, "Minimum investment must be at least 1"),
|
||||||
|
|
||||||
|
ISIN: yup.string().notRequired(),
|
||||||
|
|
||||||
|
InvestmentDetails: yup.string().notRequired(),
|
||||||
|
|
||||||
|
comment: yup.string().notRequired()
|
||||||
|
.min(10, "Comment must be at least 10 characters long")
|
||||||
|
.max(100, "Comment must be at most 100 characters long"),
|
||||||
|
|
||||||
|
expectedReturn: yup
|
||||||
|
.string()
|
||||||
|
.required("Expected return is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [values, setValues] = useState(id?minInvestmentById:miniValue);
|
const [values, setValues] = useState(id?minInvestmentById:miniValue);
|
||||||
|
|
||||||
|
console.log(values);
|
||||||
|
|
||||||
const formatNumber = (num) => {
|
const formatNumber = (num) => {
|
||||||
// Remove non-numeric characters and format with commas
|
// Remove non-numeric characters and format with commas
|
||||||
return num.replace(/\D/g, '')
|
return num.replace(/\D/g, '')
|
||||||
@@ -195,7 +253,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm({
|
} = useForm({
|
||||||
resolver: yupResolver(schema),
|
resolver: yupResolver(id ? schemaEdit : schema),
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -220,17 +278,12 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
minInvestmentAmount: IObyID?.data?.minInvestmentAmount,
|
minInvestmentAmount: IObyID?.data?.minInvestmentAmount,
|
||||||
holdingPeriodArabic: IObyID?.data?.minInvestmentAmount,
|
holdingPeriodArabic: IObyID?.data?.minInvestmentAmount,
|
||||||
expectedReturnArabic: IObyID?.data?.minInvestmentAmount,
|
expectedReturnArabic: IObyID?.data?.minInvestmentAmount,
|
||||||
|
isShariah: IObyID?.data?.isShariah
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [id, IObyID]);
|
}, [id, IObyID]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const minInvestmentById =
|
|
||||||
|
|
||||||
//=======================[ Creator ]
|
//=======================[ Creator ]
|
||||||
const formFields = [
|
const formFields = [
|
||||||
{
|
{
|
||||||
@@ -313,7 +366,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: " ",
|
section: " ",
|
||||||
width: "49%",
|
width: "32.3%",
|
||||||
value: IObyID?.data?.expectedReturn,
|
value: IObyID?.data?.expectedReturn,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -324,9 +377,19 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
isRequired: true,
|
isRequired: true,
|
||||||
arabic: true,
|
arabic: true,
|
||||||
section: " ",
|
section: " ",
|
||||||
width: "49%",
|
width: "32.3%",
|
||||||
value: IObyID?.data?.expectedReturnArabic,
|
value: IObyID?.data?.expectedReturnArabic,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "Shariah",
|
||||||
|
name: "isShariah",
|
||||||
|
type: "checkBox",
|
||||||
|
value:IObyID?.data?.isShariah,
|
||||||
|
// isRequired: true,
|
||||||
|
section: " ",
|
||||||
|
width: "32.3%",
|
||||||
|
value: IObyID?.data?.isShariah,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -371,6 +434,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
width: "32.3%",
|
width: "32.3%",
|
||||||
dateValue:formatDatee(IObyID?.data?.closingDate),
|
dateValue:formatDatee(IObyID?.data?.closingDate),
|
||||||
// helperText: IObyID && `Current closing date is : ${formatDate(IObyID?.data?.closingDate)}`
|
// helperText: IObyID && `Current closing date is : ${formatDate(IObyID?.data?.closingDate)}`
|
||||||
|
closingDate:true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "ISIN",
|
label: "ISIN",
|
||||||
@@ -389,6 +453,8 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
section: " ",
|
section: " ",
|
||||||
width: "32.3%",
|
width: "32.3%",
|
||||||
value: IObyID?.data?.InvestmentDetails,
|
value: IObyID?.data?.InvestmentDetails,
|
||||||
|
maxLength:20,
|
||||||
|
helperText:`Maximum length should be 20 characters. You have entered ${watch()?.InvestmentDetails?.length || 0} characters.`
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -400,7 +466,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
options: investmentTypeOptions,
|
options: investmentTypeOptions,
|
||||||
handleInputChange: handleInputChange,
|
handleInputChange:id ? handleInputChangeEdit : handleInputChangeCreate,
|
||||||
value: values,
|
value: values,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -417,151 +483,6 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
helperText:`Maximum length should be 100 characters. You have entered ${watch()?.comment?.length || 0} characters.`
|
helperText:`Maximum length should be 100 characters. You have entered ${watch()?.comment?.length || 0} characters.`
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
//=======================[ Editor ]
|
|
||||||
// const formEditFields = [
|
|
||||||
// {
|
|
||||||
// label: "IO Name",
|
|
||||||
// value: IObyID?.data?.investmentNameEnglish,
|
|
||||||
// name: "investmentNameEnglish",
|
|
||||||
// type: "text",
|
|
||||||
// section: " ",
|
|
||||||
// width: "49%",
|
|
||||||
// isRequired: true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "IO Name (Arabic)",
|
|
||||||
// name: "investmentNameArabic",
|
|
||||||
// type: "text",
|
|
||||||
// value: IObyID?.data?.investmentNameArabic,
|
|
||||||
// isRequired: true,
|
|
||||||
// arabic: true,
|
|
||||||
// section: " ",
|
|
||||||
// width: "49%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Description",
|
|
||||||
// name: "descriptionEnglish",
|
|
||||||
// value: IObyID?.data?.descriptionEnglish,
|
|
||||||
// type: "textarea",
|
|
||||||
// isRequired: true,
|
|
||||||
// section: " ",
|
|
||||||
// width: "49%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Description (Arabic)",
|
|
||||||
// name: "descriptionArabic",
|
|
||||||
// value: IObyID?.data?.descriptionArabic,
|
|
||||||
// type: "textarea",
|
|
||||||
// isRequired: true,
|
|
||||||
// arabic: true,
|
|
||||||
// section: " ",
|
|
||||||
// width: "49%",
|
|
||||||
// },
|
|
||||||
|
|
||||||
// {
|
|
||||||
// label: "Goal Amount",
|
|
||||||
// placeHolder: "$00.00",
|
|
||||||
// value: IObyID?.data?.goalAmount,
|
|
||||||
// name: "goalAmount",
|
|
||||||
// type: "number",
|
|
||||||
// isRequired: true,
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Closing Date",
|
|
||||||
// name: "closingDate",
|
|
||||||
// type: "date",
|
|
||||||
// isRequired: true,
|
|
||||||
// value: IObyID?.data?.closingDate,
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Holding Period",
|
|
||||||
// name: "holdingPeriod",
|
|
||||||
// value: IObyID?.data?.holdingPeriod,
|
|
||||||
// type: "number",
|
|
||||||
// isRequired: true,
|
|
||||||
// placeHolder: "1Y",
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Minimum Investment Amount",
|
|
||||||
// placeHolder: "$00.00",
|
|
||||||
// name: "minInvestmentAmount",
|
|
||||||
// value: IObyID?.data?.minInvestmentAmount,
|
|
||||||
// type: "number",
|
|
||||||
// isRequired: true,
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "ISIN",
|
|
||||||
// placeHolder: "$00.00",
|
|
||||||
// name: "ISIN",
|
|
||||||
// value: IObyID?.data?.ISIN,
|
|
||||||
// type: "number",
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Investment Details",
|
|
||||||
// placeHolder: "",
|
|
||||||
// name: "InvestmentDetails",
|
|
||||||
// value: IObyID?.data?.InvestmentDetails,
|
|
||||||
// type: "text",
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Expected Return Estimated",
|
|
||||||
// placeHolder: "$00.00",
|
|
||||||
// name: "expectedReturn",
|
|
||||||
// type: "number",
|
|
||||||
// isRequired: true,
|
|
||||||
// value: IObyID?.data?.expectedReturn,
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
|
|
||||||
// {
|
|
||||||
// label: "Investment Type",
|
|
||||||
// placeHolder: "Select option",
|
|
||||||
// value: IObyID?.data?.investmentType_xid,
|
|
||||||
// name: "investmentType_xid",
|
|
||||||
// type: "select",
|
|
||||||
// isRequired: true,
|
|
||||||
// section: " ",
|
|
||||||
// width: "32.3%",
|
|
||||||
// options: investmentTypeOptions,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "Sponsorer Name",
|
|
||||||
// placeHolder: "Select option",
|
|
||||||
// name: "sponsor_xid",
|
|
||||||
// type: "select",
|
|
||||||
// options: sponserNameOption,
|
|
||||||
// value: IObyID?.data?.sponsor_xid,
|
|
||||||
// section: " ",
|
|
||||||
// isRequired: true,
|
|
||||||
// width: "32.3%",
|
|
||||||
// },
|
|
||||||
|
|
||||||
// {
|
|
||||||
// label: "Comment",
|
|
||||||
// placeHolder: "Enter comment here",
|
|
||||||
// name: "comment",
|
|
||||||
// type: "textarea",
|
|
||||||
// value: IObyID?.data?.comment,
|
|
||||||
// section: " ",
|
|
||||||
// width: "100%",
|
|
||||||
// // options: investmentTypeOptions,
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// ======================[ Form Contructor Filter ]
|
|
||||||
const groupedFields = formFields.reduce((groups, field) => {
|
const groupedFields = formFields.reduce((groups, field) => {
|
||||||
const { section } = field;
|
const { section } = field;
|
||||||
if (!groups[section]) {
|
if (!groups[section]) {
|
||||||
@@ -572,27 +493,30 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const onSubmit = async (data) => {
|
const onSubmit = async (data) => {
|
||||||
delete data.table;
|
|
||||||
setIsLoading(true);
|
|
||||||
// console.log(data);
|
|
||||||
|
|
||||||
const updatedMinAmount = values?.map(({id, value})=>{
|
delete data.table;
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
const updatedMinAmount = values?.map(({id, value, _id})=>{
|
||||||
return {
|
return {
|
||||||
|
id:_id,
|
||||||
country_xid:id,
|
country_xid:id,
|
||||||
minInvestmentAmt: Number(value)
|
minInvestmentAmt: Number(value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// console.log(formatDateToYYYYMMDD(data.closingDate));
|
||||||
const formData = {
|
const formData = {
|
||||||
...data,
|
...data,
|
||||||
investmentType_xid: Number(data.investmentType),
|
investmentType_xid: Number(data.investmentType),
|
||||||
sponsor_xid: Number(data.sponserName),
|
sponsor_xid: Number(data.sponserName),
|
||||||
minInvestmentAmt:updatedMinAmount
|
minInvestmentAmt:updatedMinAmount,
|
||||||
|
closingDate: formatDateToYYYYMMDD(data.closingDate)
|
||||||
};
|
};
|
||||||
|
|
||||||
// console.log(formData);
|
|
||||||
// console.log(formData);
|
// console.log(formData);
|
||||||
if (id) {
|
if (id) {
|
||||||
|
console.log("========================",formData);
|
||||||
const res = await updateIO({ data: formData, id });
|
const res = await updateIO({ data: formData, id });
|
||||||
console.log(res);
|
console.log(res);
|
||||||
if (res?.data?.statusCode === 200) {
|
if (res?.data?.statusCode === 200) {
|
||||||
@@ -607,9 +531,15 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
toast({
|
toast({
|
||||||
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
||||||
});
|
});
|
||||||
|
} else if(res?.error?.status === 500){
|
||||||
|
setIsLoading(false);
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
console.log("========================",formData);
|
||||||
const res = await creatIO(formData);
|
const res = await creatIO(formData);
|
||||||
console.log(res?.error?.status);
|
console.log(res?.error?.status);
|
||||||
if (res?.data?.statusCode === 200) {
|
if (res?.data?.statusCode === 200) {
|
||||||
@@ -667,7 +597,13 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
|||||||
onSubmit={handleSubmit(onSubmit)}
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
btnLoading={isLoading}
|
btnLoading={isLoading}
|
||||||
submitTitle={id ? "Update" : "Submit"}
|
submitTitle={id ? "Update" : "Submit"}
|
||||||
></FormInputMain>
|
>
|
||||||
|
{/* <Box display={"flex"} justifyContent={"end"} mb={3} mt={4} me={3}>
|
||||||
|
<Checkbox colorScheme='forestGreen' display={"flex"} gap={3} flexDirection= {"row-reverse"}>
|
||||||
|
<Text as={"span"} fontWeight={500} fontSize={"sm"}>Shariah</Text>
|
||||||
|
</Checkbox>
|
||||||
|
</Box> */}
|
||||||
|
</FormInputMain>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,29 @@
|
|||||||
import React, { useContext, useEffect, useRef, useState } from 'react'
|
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||||
import GlobalStateContext from '../../../Contexts/GlobalStateContext';
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
import { Box, HStack, Input,Text, Table, Tbody, Th, Tr, Avatar, useDisclosure,Button } from '@chakra-ui/react';
|
import {
|
||||||
import { OPACITY_ON_LOAD } from '../../../Layout/animations';
|
Box,
|
||||||
import Pagination from '../../../Components/Pagination';
|
HStack,
|
||||||
import NormalTable from '../../../Components/DataTable/NormalTable';
|
Input,
|
||||||
import CustomAlertDialog from '../../../Components/CustomAlertDialog';
|
Text,
|
||||||
import { formatDatee } from '../../../Components/FormField';
|
Table,
|
||||||
import { AddIcon } from '@chakra-ui/icons';
|
Tbody,
|
||||||
import AddIONav from './AddIONav';
|
Th,
|
||||||
|
Tr,
|
||||||
|
Avatar,
|
||||||
|
useDisclosure,
|
||||||
|
Button,
|
||||||
|
Badge,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
|
import Pagination from "../../../Components/Pagination";
|
||||||
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
|
import { formatDatee } from "../../../Components/FormField";
|
||||||
|
import { AddIcon } from "@chakra-ui/icons";
|
||||||
|
import AddIONav from "./AddIONav";
|
||||||
|
import { formatDate } from "../../Master/Sponser/Sponsers";
|
||||||
|
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||||
|
import { exportToExcel, exportToExcelNew } from "../../../Constants/Constants";
|
||||||
|
|
||||||
const IONAVDetails = () => {
|
const IONAVDetails = () => {
|
||||||
const { navDetails, setNavDetails, IODetails } =
|
const { navDetails, setNavDetails, IODetails } =
|
||||||
@@ -21,11 +37,8 @@ const IONAVDetails = () => {
|
|||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
|
||||||
console.log(IODetails?.ioNAVHistory);
|
console.log(IODetails?.ioNAVHistory);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Simulate loading
|
// Simulate loading
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
@@ -49,12 +62,15 @@ const IONAVDetails = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Table filter
|
// Table filter
|
||||||
const filteredData = IODetails?.ioNAVHistory?.filter((item) => {
|
const filteredData = IODetails?.ioNAVHistory
|
||||||
|
?.filter((item) => {
|
||||||
const name = item.transactionType;
|
const name = item.transactionType;
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
return nameMatches;
|
return nameMatches;
|
||||||
}).sort((b, a) => new Date(a.transactionDate) - new Date(b.transactionDate));
|
})
|
||||||
|
.reverse()
|
||||||
|
// .sort((b, a) => new Date(a.transactionDate) - new Date(b.transactionDate));
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = filteredData?.map((item, index) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
@@ -67,20 +83,22 @@ const IONAVDetails = () => {
|
|||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{formatDatee(item.transactionDate)}
|
{/* {/ {formatDatee(item.transactionDate)} /} */}
|
||||||
|
{formatDate(item?.transactionDate)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"NAV": (
|
NAV: (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={"center"}
|
justifyContent={"center"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
|
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{/* {`${item.transactionAmount}`} */}
|
{/* {/ {`${item.transactionAmount}`} /} */}
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>$</Badge>
|
||||||
{`$${parseFloat(item.transactionAmount||0).toLocaleString()}`}
|
{`${parseFloat(item.transactionAmount || 0).toLocaleString()}`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Last NAV update": (
|
"Last NAV update": (
|
||||||
@@ -105,13 +123,25 @@ const IONAVDetails = () => {
|
|||||||
{item.initialNAVvalue && `${item.initialNAVvalue}`}
|
{item.initialNAVvalue && `${item.initialNAVvalue}`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Comments": (
|
Comments: (
|
||||||
|
// <Text
|
||||||
|
// justifyContent={"center"}
|
||||||
|
// as={"span"}
|
||||||
|
// color={"teal.900"}
|
||||||
|
// fontWeight={"500"}
|
||||||
|
// className="d-flex align-items-center web-text-small"
|
||||||
|
// >
|
||||||
|
// {item.comments}
|
||||||
|
// </Text>
|
||||||
<Text
|
<Text
|
||||||
justifyContent={"center"}
|
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
maxWidth="200px" // Adjust width as needed
|
||||||
|
display="block" // Ensure block display for proper truncation
|
||||||
|
overflow="hidden"
|
||||||
|
isTruncated
|
||||||
|
textOverflow="ellipsis"
|
||||||
>
|
>
|
||||||
{item.comments}
|
{item.comments}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -125,8 +155,12 @@ const IONAVDetails = () => {
|
|||||||
gap={2}
|
gap={2}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
|
<Avatar
|
||||||
<Avatar size='sm' name={"faisal"} src={null} />Faisal
|
size="sm"
|
||||||
|
name={item.creator?.firstName}
|
||||||
|
src={item.creator?.profilePhoto}
|
||||||
|
/>
|
||||||
|
{item.creator?.firstName}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Update On": (
|
"Update On": (
|
||||||
@@ -137,17 +171,41 @@ const IONAVDetails = () => {
|
|||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{item.updateOn}
|
{formatDate(item.updatedAt)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const customHeaders = [
|
||||||
|
{ label: "ID", key: "id" },
|
||||||
|
{ label: "Valuation Date", key: "transactionDate" },
|
||||||
|
{ label: "NAV", key: "transactionAmount" },
|
||||||
|
{ label: "Last NAV update", key: "previousNAVvalue" },
|
||||||
|
|
||||||
|
{ label: "Investment Closed", key: "initialNAVvalue" },
|
||||||
|
{ label: "Comments", key: "comments" },
|
||||||
|
|
||||||
|
// { label: "Update by", key: "creator" },
|
||||||
|
{ label: "Transaction Type", key: "transactionType" },
|
||||||
|
// { label: "Comments", key: "comments" },
|
||||||
|
// Add more headers as needed
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log(IODetails?.ioNAVHistory);
|
||||||
|
const ioNavExport = IODetails?.ioNAVHistory?.map((item, index) => ({
|
||||||
|
"ID": item?.id, // Keep as integer if it's already a number
|
||||||
|
"Valuation Date": formatDate(item?.transactionDate), // Assuming this is a date, no conversion needed
|
||||||
|
"NAV": parseFloat(item?.transactionAmount) || 0, // Convert to float
|
||||||
|
"Last NAV update": parseFloat(item?.previousNAVvalue) || 0, // Convert to float
|
||||||
|
"Investment Closed": parseFloat(item?.initialNAVvalue) || 0, // Convert to float
|
||||||
|
"Comments": item?.comments, // Keep as string
|
||||||
|
"Transaction Type": item?.transactionType, // Keep as string
|
||||||
|
"Update by ": item?.creator?.firstName, // Keep as string
|
||||||
|
// "Update On": formatDate(item?.updatedAt) // Assuming this is a date, no conversion needed
|
||||||
|
}));
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
const updatedNav = navDetails.filter(
|
const updatedNav = navDetails.filter((sponsor) => sponsor.id !== actionId);
|
||||||
(sponsor) => sponsor.id !== actionId
|
|
||||||
);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setNavDetails(updatedNav);
|
setNavDetails(updatedNav);
|
||||||
@@ -157,10 +215,10 @@ const IONAVDetails = () => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleExport = () => {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} pb={0}>
|
||||||
return (<Box {...OPACITY_ON_LOAD} pb={0}>
|
|
||||||
<Box bg="white.500">
|
<Box bg="white.500">
|
||||||
<HStack
|
<HStack
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
@@ -179,13 +237,35 @@ const IONAVDetails = () => {
|
|||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* <HStack display={"flex"} alignItems={"center"}>
|
<HStack display={"flex"} alignItems={"center"}>
|
||||||
<Pagination totalItems={10} />
|
<Button
|
||||||
</HStack> */}
|
onClick={() =>
|
||||||
|
exportToExcelNew(ioNavExport, "Io Nav details")
|
||||||
|
}
|
||||||
{IODetails?.isInvestedAmount ? <Button onClick={onOpen} leftIcon={<AddIcon/>} colorScheme="forestGreen" size={'sm'} rounded={'sm'} fontSize={'xs'} >Add IO NAV</Button>:null}
|
leftIcon={<LuFileSpreadsheet />}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
isDisabled={ioNavExport?.length === 0}
|
||||||
|
>
|
||||||
|
Export xls
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{IODetails?.isInvestedAmount ? (
|
||||||
|
<Button
|
||||||
|
onClick={onOpen}
|
||||||
|
leftIcon={<AddIcon />}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
>
|
||||||
|
Add IO Nav
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -210,16 +290,9 @@ const IONAVDetails = () => {
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<AddIONav isOpen={isOpen} onClose={onClose} firstField={firstField} />
|
||||||
|
|
||||||
<AddIONav
|
|
||||||
isOpen={isOpen}
|
|
||||||
onClose={onClose}
|
|
||||||
firstField={firstField} />
|
|
||||||
|
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default IONAVDetails
|
export default IONAVDetails;
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ import {
|
|||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import { getFileNameFromPath } from "../../../Constants/Constants";
|
import { getFileNameFromPath } from "../../../Constants/Constants";
|
||||||
import { TbFileTypeDocx } from "react-icons/tb";
|
import { TbFileTypeDocx } from "react-icons/tb";
|
||||||
import SetDisplayOrder from "./SetDisplayOrder";
|
import SetDisplayOrder from "./SetDisplayOrderKeyMerits";
|
||||||
|
import SetDisplayOrderIODocuments from "./SetDisplayOrderIODocuments";
|
||||||
|
|
||||||
const downloadFile = (filePath, fileName) => {
|
const downloadFile = (filePath, fileName) => {
|
||||||
|
|
||||||
@@ -134,6 +135,10 @@ const InvestmentDocument = ({ control, errors, enableNextTab, index, }) => {
|
|||||||
item?.documentName?.toLowerCase().includes(searchTerm.toLowerCase())
|
item?.documentName?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sortedData = filteredData?.sort(
|
||||||
|
(a, b) => a.displayOrder - b.displayOrder
|
||||||
|
);
|
||||||
|
|
||||||
const handleView = (id) => {
|
const handleView = (id) => {
|
||||||
setActionId(id);
|
setActionId(id);
|
||||||
onViewOpen();
|
onViewOpen();
|
||||||
@@ -168,7 +173,7 @@ const InvestmentDocument = ({ control, errors, enableNextTab, index, }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = sortedData?.map((item, index) => ({
|
||||||
"Sr.no": (
|
"Sr.no": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
@@ -300,7 +305,7 @@ const InvestmentDocument = ({ control, errors, enableNextTab, index, }) => {
|
|||||||
<Box display="flex" justifyContent="end" mb={4} gap={2}>
|
<Box display="flex" justifyContent="end" mb={4} gap={2}>
|
||||||
|
|
||||||
|
|
||||||
{filteredData?.length !== 0 &&<SetDisplayOrder data={filteredData} />}
|
{filteredData?.length !== 0 &&<SetDisplayOrderIODocuments data={filteredData} />}
|
||||||
<Button
|
<Button
|
||||||
leftIcon={<AddIcon />}
|
leftIcon={<AddIcon />}
|
||||||
onClick={onOpen}
|
onClick={onOpen}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
Thead,
|
Thead,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Tr,
|
Tr,
|
||||||
|
keyframes,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
@@ -37,27 +38,32 @@ import { formatCurrency } from "../../../Components/CurrencyInput";
|
|||||||
import { FiRefreshCw } from "react-icons/fi";
|
import { FiRefreshCw } from "react-icons/fi";
|
||||||
import { useGetIOByIdQuery } from "../../../Services/io.service";
|
import { useGetIOByIdQuery } from "../../../Services/io.service";
|
||||||
import { RepeatIcon } from "@chakra-ui/icons";
|
import { RepeatIcon } from "@chakra-ui/icons";
|
||||||
|
import { exportToExcel, exportToExcelNew } from "../../../Constants/Constants";
|
||||||
|
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||||
|
|
||||||
|
const rotate = keyframes`
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
const Investors = ({ data }) => {
|
const Investors = ({ data }) => {
|
||||||
const params = useParams()
|
const params = useParams();
|
||||||
const id = params?.id
|
const id = params?.id;
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { investors, setInvestors, slideFromRight, IODetails } =
|
const { investors, setInvestors, slideFromRight, IODetails } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
|
|
||||||
|
const [isRefetchLoading, setIsRefetchLoading] = useState(false);
|
||||||
|
|
||||||
console.log(params?.id);
|
const { isLoading: IObyIDisLoading, refetch } = useGetIOByIdQuery(id, {
|
||||||
|
skip: !id,
|
||||||
const {
|
});
|
||||||
data: IObyID,
|
|
||||||
isLoading: IObyIDisLoading,
|
|
||||||
error: IObyIDerror,
|
|
||||||
refetch
|
|
||||||
} = useGetIOByIdQuery(id, { skip: !id });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@@ -120,16 +126,48 @@ const Investors = ({data}) => {
|
|||||||
});
|
});
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Table filter
|
// Table filter
|
||||||
const filteredData = IODetails?.investors?.filter((item) => {
|
const filteredData = IODetails?.investors?.filter((item) => {
|
||||||
|
const clientId = item?.clientReference_id;
|
||||||
const name = item.firstName;
|
const name = item.firstName;
|
||||||
|
const lastName = item?.lastName
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower) || lastName.toLowerCase().includes(searchLower) || clientId.toLowerCase().includes(searchLower);
|
||||||
return nameMatches;
|
return nameMatches;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const customHeaders = [
|
||||||
|
{ label: "Client ID", key: "clientReference_id" },
|
||||||
|
{ label: "First Name", key: "firstName" }, // Nested property
|
||||||
|
{ label: "Last Name", key: "lastName" }, // Nested property
|
||||||
|
{ label: "Investment amount", key: "InvestedAmount_USD" }, // Nested property
|
||||||
|
{ label: "Percentage", key: "Investor_Holidings" }, // Nested property
|
||||||
|
{ label: "Market Value", key: "Market_Value" }, // Nested property
|
||||||
|
{ label: "Return on Investment", key: "Return_On_Investment" }, // Nested property
|
||||||
|
{ label: "Distribution", key: "Distribution_Amt" }, // Simple property
|
||||||
|
{ label: "Distribution Percent", key: "Distribution_Per" }, // Simple property // Simple property
|
||||||
|
{ label: "Total Return", key: "Total_Return" }, // Simple property
|
||||||
|
{ label: "Total return on Investment", key: "Total_Return_On_Investment" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const exportInvestorDetails = IODetails?.investors?.map((item, index) => ({
|
||||||
|
"Client ID": item?.clientReference_id, // Keep as string
|
||||||
|
"First Name": item?.firstName,
|
||||||
|
"Last Name": item?.lastName,
|
||||||
|
"Investment Amount": parseFloat(item?.InvestedAmount_USD) || 0, // Convert to float
|
||||||
|
"Percentage": parseFloat(item?.Investor_Holidings) || 0, // Convert to float
|
||||||
|
"Market Value": parseFloat(item?.Market_Value) || 0, // Convert to float
|
||||||
|
"Return on Investment": parseFloat(item?.Return_On_Investment) || 0, // Convert to float
|
||||||
|
"Distribution": parseFloat(item?.Distribution_Amt) || 0, // Convert to float
|
||||||
|
"Distribution Percent": parseFloat(item?.Distribution_Per) || 0, // Convert to float
|
||||||
|
"Total Return": parseFloat(item?.Total_Return) || 0, // Convert to float
|
||||||
|
"Total return on Investment": parseFloat(item?.Total_Return_On_Investment) || 0, // Convert to float
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log(exportInvestorDetails);
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = filteredData?.map((item, index) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
@@ -168,17 +206,23 @@ const Investors = ({data}) => {
|
|||||||
),
|
),
|
||||||
"Investment amount": (
|
"Investment amount": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "center"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
{/* {`$${formatCurrency(item.InvestedAmount_USD)}`} */}
|
{/* {`$${formatCurrency(item.InvestedAmount_USD)}`} */}
|
||||||
{`$${parseFloat(item.InvestedAmount_USD||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
|
{`${parseFloat(item.InvestedAmount_USD || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Percentage": (
|
Percentage: (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "center"}
|
justifyContent={slideFromRight ? "right" : "center"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -191,13 +235,19 @@ const Investors = ({data}) => {
|
|||||||
),
|
),
|
||||||
"Market Value": (
|
"Market Value": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "center"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{`$${parseFloat(item.Market_Value ||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{`${parseFloat(item.Market_Value || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Return on Investment": (
|
"Return on Investment": (
|
||||||
@@ -212,16 +262,22 @@ const Investors = ({data}) => {
|
|||||||
{item.Return_On_Investment || 0} %
|
{item.Return_On_Investment || 0} %
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Distribution": (
|
Distribution: (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "center"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
{/* {`$${item.Distribution_Amt}`} */}
|
{/* {`$${item.Distribution_Amt}`} */}
|
||||||
{`$${parseFloat(item.Distribution_Amt||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
|
{`${parseFloat(item.Distribution_Amt || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Distribution Percent": (
|
"Distribution Percent": (
|
||||||
@@ -233,19 +289,28 @@ const Investors = ({data}) => {
|
|||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{/* {`$${item.Distribution_Amt}`} */}
|
{/* {`$${item.Distribution_Amt}`} */}
|
||||||
{`${parseFloat(item.Distribution_Per||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} %`}
|
{`${parseFloat(item.Distribution_Per || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})} %`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Total Return": (
|
"Total Return": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "center"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
{/* {`$${formatCurrency(item.Total_Return) || 0}`} */}
|
{/* {`$${formatCurrency(item.Total_Return) || 0}`} */}
|
||||||
{`$${parseFloat(item.Total_Return||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
|
{`${parseFloat(item.Total_Return || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Total return on Investment": (
|
"Total return on Investment": (
|
||||||
@@ -395,10 +460,16 @@ const Investors = ({data}) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRefresh = async () => {
|
||||||
|
setIsRefetchLoading(true);
|
||||||
|
|
||||||
|
await refetch();
|
||||||
|
setIsRefetchLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
console.log(IODetails?.investors);
|
||||||
|
|
||||||
const handleRefresh = () =>{
|
|
||||||
refetch()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box {...OPACITY_ON_LOAD} pb={0}>
|
<Box {...OPACITY_ON_LOAD} pb={0}>
|
||||||
@@ -408,9 +479,8 @@ const Investors = ({data}) => {
|
|||||||
justifyContent={"space-between"}
|
justifyContent={"space-between"}
|
||||||
pb={3}
|
pb={3}
|
||||||
spacing="24px"
|
spacing="24px"
|
||||||
|
|
||||||
>
|
>
|
||||||
<span>
|
<Box display={'flex'} gap={3}>
|
||||||
<Input
|
<Input
|
||||||
type="search"
|
type="search"
|
||||||
width={300}
|
width={300}
|
||||||
@@ -421,13 +491,70 @@ const Investors = ({data}) => {
|
|||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<Icon ms={3} bg={"gray.100"} onClick={handleRefresh} fontWeight={600} as={RepeatIcon} boxSize={8} p={2} rounded={'md'} _hover={{bg:'gray.100'}} cursor={'pointer'} />
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<HStack bg={'#C6F6D5'} ps={4} pe={4} pt={1.5} pb={1.5} rounded={'md'} boxShadow={'sm'} display={"flex"} alignItems={"end"} flexDirection={'column'} >
|
<Button
|
||||||
<Text fontWeight={600} fontSize={'sm'} as={'span'}>$ {parseFloat(IODetails?.totalAmtInvestmentInUSD).toLocaleString()}</Text>
|
onClick={() =>
|
||||||
<Text fontWeight={600} color={'gray.500'} fontSize={'xs'} as={'span'}>Total Investment Amount ( USD )</Text>
|
exportToExcelNew(exportInvestorDetails, "IO Investors Details")
|
||||||
|
}
|
||||||
|
leftIcon={<LuFileSpreadsheet />}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
w={100}
|
||||||
|
me={2}
|
||||||
|
isDisabled={exportInvestorDetails?.length === 0}
|
||||||
|
>
|
||||||
|
Export xls
|
||||||
|
</Button>
|
||||||
|
<Box as="span">
|
||||||
|
<Icon
|
||||||
|
ms={0}
|
||||||
|
animation={
|
||||||
|
isRefetchLoading ? `${rotate} 1s linear infinite` : "none"
|
||||||
|
}
|
||||||
|
bg={"gray.50"}
|
||||||
|
onClick={handleRefresh}
|
||||||
|
fontWeight={600}
|
||||||
|
as={RepeatIcon}
|
||||||
|
boxSize={8}
|
||||||
|
p={2}
|
||||||
|
rounded={"full"}
|
||||||
|
_hover={{ bg: "gray.100" }}
|
||||||
|
cursor={"pointer"}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<HStack
|
||||||
|
bg={"#C6F6D5"}
|
||||||
|
ps={4}
|
||||||
|
pe={4}
|
||||||
|
pt={1.5}
|
||||||
|
pb={1.5}
|
||||||
|
rounded={"md"}
|
||||||
|
boxShadow={"sm"}
|
||||||
|
display={"flex"}
|
||||||
|
// alignItems={"end"}
|
||||||
|
// flexDirection={"column"}
|
||||||
|
alignItems={"center"}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fontWeight={600}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
as={"span"}
|
||||||
|
>
|
||||||
|
Total Investment Amount ( USD )
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text display={'flex'} alignItems={'center'} fontWeight={600} fontSize={"sm"} as={"span"} pt={"2px"}>
|
||||||
|
<Badge p={1} ms={2} fontSize={'md'} colorScheme="green" me={0}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{parseFloat(IODetails?.totalAmtInvestmentInUSD).toLocaleString()}
|
||||||
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import {
|
|||||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import KeyMeritsEdit from "../KeyMeritsEdit";
|
import KeyMeritsEdit from "../KeyMeritsEdit";
|
||||||
import SetDisplayOrder from "./SetDisplayOrder";
|
import SetDisplayOrder from "./SetDisplayOrderKeyMerits";
|
||||||
|
|
||||||
const KeyMerits = ({ enableNextTab, index, data: prepopData }) => {
|
const KeyMerits = ({ enableNextTab, index, data: prepopData }) => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
@@ -71,7 +71,7 @@ const KeyMerits = ({ enableNextTab, index, data: prepopData }) => {
|
|||||||
|
|
||||||
const filteredData = IODetails?.keyMerits?.filter((item) => {
|
const filteredData = IODetails?.keyMerits?.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = item.meritsHeader;
|
const name = item?.meritsHeader;
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ const KeyMerits = ({ enableNextTab, index, data: prepopData }) => {
|
|||||||
|
|
||||||
// console.log(filteredData);
|
// console.log(filteredData);
|
||||||
const sortedData = filteredData?.sort(
|
const sortedData = filteredData?.sort(
|
||||||
(a, b) => a.displayOder - b.displayOder
|
(a, b) => a.displayOrder - b.displayOrder
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
@@ -97,6 +97,8 @@ const KeyMerits = ({ enableNextTab, index, data: prepopData }) => {
|
|||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const extractedArray = sortedData?.map((item, index) => ({
|
const extractedArray = sortedData?.map((item, index) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
"Sr.no": (
|
"Sr.no": (
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalOverlay,
|
||||||
|
ModalContent,
|
||||||
|
ModalHeader,
|
||||||
|
ModalFooter,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
useDisclosure,
|
||||||
|
Button,
|
||||||
|
Box,
|
||||||
|
Text,
|
||||||
|
Image,
|
||||||
|
HStack,
|
||||||
|
useToast,
|
||||||
|
Link,
|
||||||
|
Badge,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
|
||||||
|
import { AddIcon, DragHandleIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||||
|
import DataTable from "../../../Components/DataTable/DataTable";
|
||||||
|
import { useSetDisplayOrderIOArtifactsImageMutation } from "../../../Services/io.service";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
|
||||||
|
const SetDisplayOrderIOArtifactsImages = ({ data, }) => {
|
||||||
|
console.log(data);
|
||||||
|
const toast = useToast();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const tableHeadRow = ["", "File Name", "View image"];
|
||||||
|
|
||||||
|
const [extractedArray, setExtractedArray] = useState([]);
|
||||||
|
const [displayOrder, setDisplayOrder] = useState(null);
|
||||||
|
const [resetDisplayOrder] = useSetDisplayOrderIOArtifactsImageMutation();
|
||||||
|
|
||||||
|
// Update state when `data` prop changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
const formattedData = data?.map((item, index) => ({
|
||||||
|
id: item?.id,
|
||||||
|
displayOrder: index + 1, // Add displayOrder property
|
||||||
|
"": (
|
||||||
|
<Box w={"20px"} isTruncated={true}>
|
||||||
|
<DragHandleIcon />
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"File Name": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item.artifactName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
|
||||||
|
"View image": (
|
||||||
|
<Text
|
||||||
|
color={"green.500"}
|
||||||
|
justifyContent={"left"}
|
||||||
|
as={"span"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
display={"flex"}
|
||||||
|
alignItems={"center"}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
colorScheme={"forestGreen"}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={import.meta.env.VITE_IMAGE_URL + item?.artifactPathName}
|
||||||
|
isExternal
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
// onClick={() => {
|
||||||
|
// setImageSrc(item?.artifactPathName);
|
||||||
|
// onOpenImageViewer();
|
||||||
|
// }}
|
||||||
|
as="span"
|
||||||
|
cursor={"pointer"}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Box>{" "}
|
||||||
|
<ExternalLinkIcon />
|
||||||
|
</Link>
|
||||||
|
</Badge>
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
setExtractedArray(formattedData);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// Log the updated order in the desired format whenever `extractedArray` changes
|
||||||
|
useEffect(() => {
|
||||||
|
const displayOrderArray = extractedArray.map((item, index) => ({
|
||||||
|
id: item.id,
|
||||||
|
displayOrder: index + 1,
|
||||||
|
}));
|
||||||
|
setDisplayOrder(displayOrderArray);
|
||||||
|
}, [extractedArray]);
|
||||||
|
|
||||||
|
const handleSetOrder = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
const data = {
|
||||||
|
displayOrder: displayOrder,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await resetDisplayOrder({ data });
|
||||||
|
console.log(res?.data?.statusCode);
|
||||||
|
if (res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(res);
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
leftIcon={<AddIcon />}
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
onClick={onOpen}
|
||||||
|
>
|
||||||
|
Set Display Order
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Modal isCentered size={"xl"} isOpen={isOpen} onClose={onClose}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader fontSize={"lg"}>Set Display Order</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
<DataTable
|
||||||
|
emptyMessage={`We don't have any Sponsors`}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
setData={setExtractedArray}
|
||||||
|
isDraggable={true}
|
||||||
|
/>
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
Reset order
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
onClick={handleSetOrder}
|
||||||
|
isLoading={isLoading}
|
||||||
|
>
|
||||||
|
Set order
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SetDisplayOrderIOArtifactsImages;
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalOverlay,
|
||||||
|
ModalContent,
|
||||||
|
ModalHeader,
|
||||||
|
ModalFooter,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
useDisclosure,
|
||||||
|
Button,
|
||||||
|
Box,
|
||||||
|
Text,
|
||||||
|
Image,
|
||||||
|
HStack,
|
||||||
|
useToast,
|
||||||
|
Badge,
|
||||||
|
Link,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
|
||||||
|
import { AddIcon, DragHandleIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||||
|
import DataTable from "../../../Components/DataTable/DataTable";
|
||||||
|
import { useSetDisplayOrderIOArtifactsVideoMutation } from "../../../Services/io.service";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
|
||||||
|
const SetDisplayOrderIOArtifactsVideo = ({ data, }) => {
|
||||||
|
const toast = useToast();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const tableHeadRow = ["", "File Name", "Video streaming URL"];
|
||||||
|
|
||||||
|
const [extractedArray, setExtractedArray] = useState([]);
|
||||||
|
const [displayOrder, setDisplayOrder] = useState(null);
|
||||||
|
const [resetDisplayOrder] = useSetDisplayOrderIOArtifactsVideoMutation();
|
||||||
|
|
||||||
|
// Update state when `data` prop changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
const formattedData = data.map((item, index) => ({
|
||||||
|
id: item?.id,
|
||||||
|
displayOrder: index + 1, // Add displayOrder property
|
||||||
|
"": (
|
||||||
|
<Box w={"20px"} isTruncated={true}>
|
||||||
|
<DragHandleIcon />
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"File Name": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item.artifactName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Video streaming URL": (
|
||||||
|
<Text
|
||||||
|
color={"green.500"}
|
||||||
|
justifyContent={"left"}
|
||||||
|
as={"span"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
px={2}
|
||||||
|
py={0.5}
|
||||||
|
display={"flex"}
|
||||||
|
alignItems={"center"}
|
||||||
|
textTransform={"inherit"}
|
||||||
|
fontWeight={500}
|
||||||
|
colorScheme={"forestGreen"}
|
||||||
|
>
|
||||||
|
<Link href={item?.artifactStreamingURL} isExternal>
|
||||||
|
<Box as="span">View</Box> <ExternalLinkIcon />
|
||||||
|
</Link>
|
||||||
|
</Badge>
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
setExtractedArray(formattedData);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// Log the updated order in the desired format whenever `extractedArray` changes
|
||||||
|
useEffect(() => {
|
||||||
|
const displayOrderArray = extractedArray.map((item, index) => ({
|
||||||
|
id: item.id,
|
||||||
|
displayOrder: index + 1,
|
||||||
|
}));
|
||||||
|
setDisplayOrder(displayOrderArray);
|
||||||
|
}, [extractedArray]);
|
||||||
|
|
||||||
|
const handleSetOrder = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
const data = {
|
||||||
|
displayOrder: displayOrder,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await resetDisplayOrder({ data });
|
||||||
|
console.log(res?.data?.statusCode);
|
||||||
|
if (res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(res);
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
leftIcon={<AddIcon />}
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
onClick={onOpen}
|
||||||
|
>
|
||||||
|
Set Display Order
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Modal isCentered size={"xl"} isOpen={isOpen} onClose={onClose}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader fontSize={"lg"}>Set Display Order</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
<DataTable
|
||||||
|
emptyMessage={`We don't have any Sponsors`}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
setData={setExtractedArray}
|
||||||
|
isDraggable={true}
|
||||||
|
/>
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
Reset order
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
onClick={handleSetOrder}
|
||||||
|
isLoading={isLoading}
|
||||||
|
>
|
||||||
|
Set order
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SetDisplayOrderIOArtifactsVideo;
|
||||||
165
src/Pages/IO_Management/CreateIO/SetDisplayOrderIODocuments.jsx
Normal file
165
src/Pages/IO_Management/CreateIO/SetDisplayOrderIODocuments.jsx
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalOverlay,
|
||||||
|
ModalContent,
|
||||||
|
ModalHeader,
|
||||||
|
ModalFooter,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
useDisclosure,
|
||||||
|
Button,
|
||||||
|
Box,
|
||||||
|
Text,
|
||||||
|
Image,
|
||||||
|
HStack,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
|
||||||
|
import { AddIcon, DragHandleIcon } from "@chakra-ui/icons";
|
||||||
|
import DataTable from "../../../Components/DataTable/DataTable";
|
||||||
|
import { useSetDisplayOrderIODocumentsMutation } from "../../../Services/io.service";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
import { GrDocumentPdf } from "react-icons/gr";
|
||||||
|
import { TbFileTypeDocx } from "react-icons/tb";
|
||||||
|
|
||||||
|
const SetDisplayOrderIODocuments = ({ data, }) => {
|
||||||
|
const toast = useToast();
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const tableHeadRow = ["", "Type", "File name"];
|
||||||
|
|
||||||
|
const [extractedArray, setExtractedArray] = useState([]);
|
||||||
|
const [displayOrder, setDisplayOrder] = useState(null);
|
||||||
|
const [resetDisplayOrder] = useSetDisplayOrderIODocumentsMutation();
|
||||||
|
|
||||||
|
// Update state when `data` prop changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
const formattedData = data.map((item, index) => ({
|
||||||
|
id: item?.id,
|
||||||
|
displayOrder: index + 1, // Add displayOrder property
|
||||||
|
"": (
|
||||||
|
<Box maxW={"20px"} isTruncated={true}>
|
||||||
|
<DragHandleIcon />
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Type: (
|
||||||
|
<Text
|
||||||
|
justifyContent={"left"}
|
||||||
|
as="span"
|
||||||
|
color="teal.900"
|
||||||
|
fontWeight="500"
|
||||||
|
className="d-flex align-items-center"
|
||||||
|
fontSize={"xl"}
|
||||||
|
>
|
||||||
|
{item.documentType === "application/pdf" ? (
|
||||||
|
<GrDocumentPdf />
|
||||||
|
) : (
|
||||||
|
<TbFileTypeDocx fontSize={21} />
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"File name": (
|
||||||
|
<Text as="span" color="teal.900" fontWeight="500">
|
||||||
|
{item.documentName}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
setExtractedArray(formattedData);
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// Log the updated order in the desired format whenever `extractedArray` changes
|
||||||
|
useEffect(() => {
|
||||||
|
const displayOrderArray = extractedArray.map((item, index) => ({
|
||||||
|
id: item.id,
|
||||||
|
displayOrder: index + 1,
|
||||||
|
}));
|
||||||
|
setDisplayOrder(displayOrderArray);
|
||||||
|
}, [extractedArray]);
|
||||||
|
|
||||||
|
const handleSetOrder = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
const data = {
|
||||||
|
displayOrder: displayOrder,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await resetDisplayOrder({ data });
|
||||||
|
console.log(res?.data?.statusCode);
|
||||||
|
if (res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(res);
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
leftIcon={<AddIcon />}
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
onClick={onOpen}
|
||||||
|
>
|
||||||
|
Set Display Order
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Modal isCentered size={"xl"} isOpen={isOpen} onClose={onClose}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader fontSize={"lg"}>Set Display Order</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody>
|
||||||
|
<DataTable
|
||||||
|
emptyMessage={`We don't have any Sponsors`}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
setData={setExtractedArray}
|
||||||
|
isDraggable={true}
|
||||||
|
/>
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
Reset order
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
rounded={"sm"}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
onClick={handleSetOrder}
|
||||||
|
isLoading={isLoading}
|
||||||
|
>
|
||||||
|
Set order
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SetDisplayOrderIODocuments;
|
||||||
@@ -21,7 +21,7 @@ import DataTable from "../../../Components/DataTable/DataTable";
|
|||||||
import { useSetDisplayOrderMutation } from "../../../Services/io.service";
|
import { useSetDisplayOrderMutation } from "../../../Services/io.service";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
|
||||||
const SetDisplayOrder = ({ data }) => {
|
const SetDisplayOrderKeyMerits = ({ data, }) => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@@ -57,6 +57,10 @@ const SetDisplayOrder = ({ data }) => {
|
|||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Icon: item?.icon?.iconFilePath && (
|
Icon: item?.icon?.iconFilePath && (
|
||||||
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"center"}
|
||||||
|
alignItems={"center"}>
|
||||||
<Image
|
<Image
|
||||||
rounded={"md"}
|
rounded={"md"}
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
@@ -66,7 +70,7 @@ const SetDisplayOrder = ({ data }) => {
|
|||||||
src={import.meta.env.VITE_IMAGE_URL + item?.icon?.iconFilePath}
|
src={import.meta.env.VITE_IMAGE_URL + item?.icon?.iconFilePath}
|
||||||
w={8}
|
w={8}
|
||||||
h={8}
|
h={8}
|
||||||
/>
|
/></Box>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
setExtractedArray(formattedData);
|
setExtractedArray(formattedData);
|
||||||
@@ -164,4 +168,4 @@ const SetDisplayOrder = ({ data }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SetDisplayOrder;
|
export default SetDisplayOrderKeyMerits;
|
||||||
@@ -34,7 +34,8 @@ import { formatTimestampInGulfTimezone } from "../../Constants/Constants";
|
|||||||
import { IoMdRemoveCircleOutline } from "react-icons/io";
|
import { IoMdRemoveCircleOutline } from "react-icons/io";
|
||||||
|
|
||||||
const investmentImageSchema = yup.object().shape({
|
const investmentImageSchema = yup.object().shape({
|
||||||
artifactName: yup.string().required("Artifact image name is required"),
|
artifactName: yup.string().required("Artifact image name is required")
|
||||||
|
.max(25, "File name must be at most 25 characters"),
|
||||||
artifactPathName: yup.mixed().required("Artifact image is required"),
|
artifactPathName: yup.mixed().required("Artifact image is required"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -60,7 +61,6 @@ const IOArtifactsAdd = ({
|
|||||||
const found = data?.find((item) => item?.id === actionId);
|
const found = data?.find((item) => item?.id === actionId);
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@@ -82,8 +82,8 @@ const IOArtifactsAdd = ({
|
|||||||
}
|
}
|
||||||
}, [found, reset]);
|
}, [found, reset]);
|
||||||
|
|
||||||
|
|
||||||
const onSubmit = async (data) => {
|
const onSubmit = async (data) => {
|
||||||
|
console.log("hit");
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("artifactName", data.artifactName);
|
formData.append("artifactName", data.artifactName);
|
||||||
@@ -95,6 +95,7 @@ const IOArtifactsAdd = ({
|
|||||||
data: formData,
|
data: formData,
|
||||||
id: found?.id,
|
id: found?.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res?.data?.statusCode === 200) {
|
if (res?.data?.statusCode === 200) {
|
||||||
toast({
|
toast({
|
||||||
render: () => <ToastBox message={res?.data?.message} />,
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
@@ -108,6 +109,21 @@ const IOArtifactsAdd = ({
|
|||||||
artifactName: "",
|
artifactName: "",
|
||||||
artifactPathName: "",
|
artifactPathName: "",
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={"Something went wronng"} error="error" />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setFile(null);
|
||||||
|
setIsLoading(false);
|
||||||
|
setAlert(false);
|
||||||
|
setPreview(null);
|
||||||
|
onClose();
|
||||||
|
reset({
|
||||||
|
artifactName: "",
|
||||||
|
artifactPathName: "",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res?.error) {
|
if (res?.error) {
|
||||||
@@ -155,10 +171,12 @@ const IOArtifactsAdd = ({
|
|||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
|
if (!alert) {
|
||||||
|
setAlert(true)
|
||||||
|
}else{
|
||||||
handleSubmit(onSubmit)();
|
handleSubmit(onSubmit)();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
@@ -173,17 +191,19 @@ const IOArtifactsAdd = ({
|
|||||||
setActionId(false);
|
setActionId(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleRemove = () => {
|
const handleRemove = () => {
|
||||||
|
setFile(null);
|
||||||
setFile(null)
|
setPreview(null);
|
||||||
setPreview(null)
|
|
||||||
// Reset the file input value
|
// Reset the file input value
|
||||||
if (fileInputRef.current) {
|
if (fileInputRef.current) {
|
||||||
fileInputRef.current.value = "";
|
fileInputRef.current.value = "";
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const handleAlertClose = () => {
|
||||||
|
setAlert(false);
|
||||||
|
setIsLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -198,16 +218,22 @@ const IOArtifactsAdd = ({
|
|||||||
<DrawerContent>
|
<DrawerContent>
|
||||||
<DrawerCloseButton />
|
<DrawerCloseButton />
|
||||||
<DrawerHeader fontSize={"sm"}>IO Artifacts Image</DrawerHeader>
|
<DrawerHeader fontSize={"sm"}>IO Artifacts Image</DrawerHeader>
|
||||||
|
<Box as="form">
|
||||||
<DrawerBody>
|
<DrawerBody>
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<FormControl isInvalid={errors.artifactName}>
|
<FormControl isInvalid={errors.artifactName} isRequired={true}>
|
||||||
<FormLabel fontSize={"sm"}>Artifact Name</FormLabel>
|
<FormLabel fontSize={"sm"}>Artifact Name</FormLabel>
|
||||||
<Controller
|
<Controller
|
||||||
name="artifactName"
|
name="artifactName"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input {...field} fontSize={"sm"} type="text" size={"sm"} />
|
<Input
|
||||||
|
{...field}
|
||||||
|
fontSize={"sm"}
|
||||||
|
type="text"
|
||||||
|
size={"sm"}
|
||||||
|
maxLength={25}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
|
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
|
||||||
@@ -221,11 +247,12 @@ const IOArtifactsAdd = ({
|
|||||||
errors.artifactPathName?.message &&
|
errors.artifactPathName?.message &&
|
||||||
errors.artifactPathName
|
errors.artifactPathName
|
||||||
}
|
}
|
||||||
|
isRequired={true}
|
||||||
>
|
>
|
||||||
<FormLabel fontSize={"sm"}>Artifact Image</FormLabel>
|
<FormLabel fontSize={"sm"}>Artifact Image (600 X 300)</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*"
|
accept=".jpg,.jpeg,.png"
|
||||||
onChange={handleFileChange}
|
onChange={handleFileChange}
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
size={"sm"}
|
size={"sm"}
|
||||||
@@ -244,15 +271,41 @@ const IOArtifactsAdd = ({
|
|||||||
src={preview}
|
src={preview}
|
||||||
alt="Image Preview"
|
alt="Image Preview"
|
||||||
mt={3}
|
mt={3}
|
||||||
width={'100%'}
|
width={300}
|
||||||
height={300}
|
height={150}
|
||||||
objectFit={'cover'}
|
objectFit={"cover"}
|
||||||
|
backgroundSize={"cover"}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
w={"100%"}
|
||||||
|
position={"relative"}
|
||||||
|
mt={2}
|
||||||
|
fontSize={"xs"}
|
||||||
|
display={"flex"}
|
||||||
|
flexDirection={"column"}
|
||||||
|
as="span"
|
||||||
|
>
|
||||||
|
<Text as={"span"}>Name: {file?.name}</Text>
|
||||||
|
<Text as={"span"} fontSize={"xs"}>
|
||||||
|
File size: {bytesToMB(file?.size)}
|
||||||
|
</Text>
|
||||||
|
<Text as={"span"} fontSize={"xs"}>
|
||||||
|
Last update:{" "}
|
||||||
|
{formatTimestampInGulfTimezone(file?.lastModified)}
|
||||||
|
</Text>
|
||||||
|
<Icon
|
||||||
|
onClick={() => handleRemove()}
|
||||||
|
_hover={{ bg: "gray.100" }}
|
||||||
|
transition={"all 0-5s"}
|
||||||
|
cursor={"pointer"}
|
||||||
|
position={"absolute"}
|
||||||
|
right={0}
|
||||||
|
p={1}
|
||||||
|
bottom={0}
|
||||||
|
rounded={"lg"}
|
||||||
|
boxSize={7}
|
||||||
|
as={IoMdRemoveCircleOutline}
|
||||||
/>
|
/>
|
||||||
<Box w={'100%'} position={'relative'} mt={2} fontSize={'xs'} display={'flex'} flexDirection={'column'} as="span">
|
|
||||||
<Text as={'span'}>Name: {file?.name}</Text>
|
|
||||||
<Text as={'span'} fontSize={'xs'}>File size: {bytesToMB(file?.size)}</Text>
|
|
||||||
<Text as={'span'} fontSize={'xs'}>Last update: {formatTimestampInGulfTimezone(file?.lastModified)}</Text>
|
|
||||||
<Icon onClick={() => handleRemove()} _hover={{ bg: "gray.100" }} transition={'all 0-5s'} cursor={'pointer'} position={'absolute'} right={0} p={1} bottom={0} rounded={'lg'} boxSize={7} as={IoMdRemoveCircleOutline} />
|
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -271,14 +324,14 @@ const IOArtifactsAdd = ({
|
|||||||
</Stack>
|
</Stack>
|
||||||
</DrawerBody>
|
</DrawerBody>
|
||||||
|
|
||||||
<DrawerFooter>
|
<DrawerFooter mt={5}>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
colorScheme={"forestGreen"}
|
colorScheme={"forestGreen"}
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
size={"sm"}
|
size={"sm"}
|
||||||
mr={3}
|
mr={3}
|
||||||
onClick={onClose}
|
onClick={handleClose}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
@@ -287,16 +340,19 @@ const IOArtifactsAdd = ({
|
|||||||
colorScheme={"forestGreen"}
|
colorScheme={"forestGreen"}
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
size={"sm"}
|
size={"sm"}
|
||||||
onClick={() => setAlert(true)}
|
// onClick={() => setAlert(true)}
|
||||||
|
onClick={handleSave}
|
||||||
|
// type="submit"
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</DrawerFooter>
|
</DrawerFooter>
|
||||||
|
</Box>
|
||||||
</DrawerContent>
|
</DrawerContent>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<CustomAlertDialog
|
<CustomAlertDialog
|
||||||
isOpen={alert}
|
isOpen={alert}
|
||||||
onClose={() => setAlert(false)}
|
onClose={handleAlertClose}
|
||||||
alertHandler={handleSave}
|
alertHandler={handleSave}
|
||||||
message={"Are you sure you want to add this artifact?"}
|
message={"Are you sure you want to add this artifact?"}
|
||||||
isLoading={loading}
|
isLoading={loading}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
|||||||
const [alert, setAlert] = useState(false);
|
const [alert, setAlert] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
reset,
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
|
|||||||
@@ -59,8 +59,10 @@ export const investmentDocSchema = yup.object().shape({
|
|||||||
// console.log("File size:", value ? value.size : "No file");
|
// console.log("File size:", value ? value.size : "No file");
|
||||||
// return value && value.size <= 2 * 1024 * 1024; // 2MB in bytes
|
// return value && value.size <= 2 * 1024 * 1024; // 2MB in bytes
|
||||||
// })
|
// })
|
||||||
fileName: yup.string().required("File name is required"),
|
fileName: yup.string().required("File name is required")
|
||||||
|
.max(25, "File name must be at most 25 characters"), // Maximum length validation,
|
||||||
documentNameArabic: yup.string().required("File name Arabic is required")
|
documentNameArabic: yup.string().required("File name Arabic is required")
|
||||||
|
.max(25, "File name must be at most 30 characters"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const InvestmentDocuments = ({
|
const InvestmentDocuments = ({
|
||||||
@@ -196,8 +198,8 @@ const InvestmentDocuments = ({
|
|||||||
>
|
>
|
||||||
<DrawerOverlay />
|
<DrawerOverlay />
|
||||||
<DrawerContent>
|
<DrawerContent>
|
||||||
<DrawerCloseButton />
|
<DrawerCloseButton onClick={handleClose} />
|
||||||
<DrawerHeader fontSize="sm">Add Details</DrawerHeader>
|
<DrawerHeader fontSize="sm">Add Investment Documents</DrawerHeader>
|
||||||
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
<DrawerBody>
|
<DrawerBody>
|
||||||
<FormControl mb={4} isRequired>
|
<FormControl mb={4} isRequired>
|
||||||
@@ -208,6 +210,7 @@ const InvestmentDocuments = ({
|
|||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
type="text"
|
type="text"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
maxLength={25} // Maximum length constraint in the input field
|
||||||
/>
|
/>
|
||||||
{errors.fileName && (
|
{errors.fileName && (
|
||||||
<Text mt={1} fontSize="xs" fontWeight={500} color="red">
|
<Text mt={1} fontSize="xs" fontWeight={500} color="red">
|
||||||
@@ -226,6 +229,7 @@ const InvestmentDocuments = ({
|
|||||||
type="text"
|
type="text"
|
||||||
size="sm"
|
size="sm"
|
||||||
textAlign={'right'}
|
textAlign={'right'}
|
||||||
|
maxLength={30} // Maximum length constraint in the input field
|
||||||
/>
|
/>
|
||||||
{errors.documentNameArabic && (
|
{errors.documentNameArabic && (
|
||||||
<Text mt={1} fontSize="xs" fontWeight={500} color="red">
|
<Text mt={1} fontSize="xs" fontWeight={500} color="red">
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id, icons }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Drawer
|
<Drawer
|
||||||
size={"xl"}
|
size={"lg"}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
placement="right"
|
placement="right"
|
||||||
initialFocusRef={firstField}
|
initialFocusRef={firstField}
|
||||||
@@ -210,7 +210,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id, icons }) => {
|
|||||||
isInvalid={!!errors.meritsDescription}
|
isInvalid={!!errors.meritsDescription}
|
||||||
isRequired={true}
|
isRequired={true}
|
||||||
>
|
>
|
||||||
<FormLabel fontSize={"sm"}>Description (English)</FormLabel>
|
<FormLabel fontSize={"sm"}>Sub title</FormLabel>
|
||||||
<Controller
|
<Controller
|
||||||
name="meritsDescription"
|
name="meritsDescription"
|
||||||
control={control}
|
control={control}
|
||||||
@@ -235,7 +235,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id, icons }) => {
|
|||||||
isInvalid={!!errors.meritsDescriptionArabic}
|
isInvalid={!!errors.meritsDescriptionArabic}
|
||||||
isRequired={true}
|
isRequired={true}
|
||||||
>
|
>
|
||||||
<FormLabel fontSize={"sm"}>Description (Arabic)</FormLabel>
|
<FormLabel fontSize={"sm"}>Sub title (Arabic)</FormLabel>
|
||||||
<Controller
|
<Controller
|
||||||
name="meritsDescriptionArabic"
|
name="meritsDescriptionArabic"
|
||||||
control={control}
|
control={control}
|
||||||
|
|||||||
@@ -82,12 +82,16 @@ const KeyMeritsEdit = ({
|
|||||||
meritsDescription: found?.meritsDescription,
|
meritsDescription: found?.meritsDescription,
|
||||||
meritsHeaderArabic: found?.meritsHeaderArabic,
|
meritsHeaderArabic: found?.meritsHeaderArabic,
|
||||||
meritsDescriptionArabic: found?.meritsDescriptionArabic,
|
meritsDescriptionArabic: found?.meritsDescriptionArabic,
|
||||||
iconImage: null,
|
icon_xid: found?.icon_xid,
|
||||||
});
|
});
|
||||||
|
console.log("==============",found);
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [found, reset]);
|
}, [found, reset]);
|
||||||
|
|
||||||
const onSubmit = async (data) => {
|
const onSubmit = async (data) => {
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const id = actionId;
|
const id = actionId;
|
||||||
@@ -97,6 +101,9 @@ const KeyMeritsEdit = ({
|
|||||||
render: () => <ToastBox message={res?.data?.message} />,
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
});
|
});
|
||||||
handleClose()
|
handleClose()
|
||||||
|
reset({
|
||||||
|
meritsHeader: "",
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (res?.error?.data?.code === 400) {
|
if (res?.error?.data?.code === 400) {
|
||||||
@@ -106,6 +113,7 @@ const KeyMeritsEdit = ({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
handleClose()
|
handleClose()
|
||||||
|
reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -288,7 +296,7 @@ const KeyMeritsEdit = ({
|
|||||||
alt={selectedImageIcon}
|
alt={selectedImageIcon}
|
||||||
boxSize="1rem"
|
boxSize="1rem"
|
||||||
mr="12px"
|
mr="12px"
|
||||||
/>}{" "}
|
/>}
|
||||||
<Text as={"span"} fontSize={"sm"} fontWeight={500}>
|
<Text as={"span"} fontSize={"sm"} fontWeight={500}>
|
||||||
{selectedIcon}
|
{selectedIcon}
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
@@ -15,28 +15,29 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useForm } from 'react-hook-form';
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import * as yup from 'yup';
|
import * as yup from "yup";
|
||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import GlobalStateContext from '../../../../Contexts/GlobalStateContext';
|
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from "react-router-dom";
|
||||||
import { useAmountIvestmentMutation } from '../../../../Services/io.service';
|
import { useAmountIvestmentMutation } from "../../../../Services/io.service";
|
||||||
import ToastBox from '../../../../Components/ToastBox';
|
import ToastBox from "../../../../Components/ToastBox";
|
||||||
|
import CurrencyInput from "../../../../Components/CurrencyInput";
|
||||||
|
|
||||||
// Validation schema
|
// Validation schema
|
||||||
const validationSchema = yup.object().shape({
|
const validationSchema = yup.object().shape({
|
||||||
transactionDate: yup.date().required('Date is required'),
|
transactionDate: yup.date().required("Date is required"),
|
||||||
Total_Amount: yup.number().required('Amount is required'),
|
Total_Amount: yup.number().required("Amount is required"),
|
||||||
amountInvested: yup.number().required('Amount to invest is required'),
|
amountInvested: yup.number().required("Amount to invest is required"),
|
||||||
IoCash: yup.number().positive('IO Cash must be positive').required('IO Cash is required'),
|
IoCash: yup.number().positive("IO Cash must be positive").required("IO Cash is required"),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Function to format currency
|
// Function to format currency
|
||||||
const formatCurrency = (value) => {
|
const formatCurrency = (value) => {
|
||||||
if (isNaN(value)) return '';
|
if (isNaN(value)) return "";
|
||||||
const formatted = parseFloat(value).toFixed(2).toString();
|
const formatted = parseFloat(value).toFixed(2).toString();
|
||||||
const [integer, decimal] = formatted.split('.');
|
const [integer, decimal] = formatted.split(".");
|
||||||
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
|
return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,7 +45,14 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
|||||||
const params = useParams();
|
const params = useParams();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const id = params?.id;
|
const id = params?.id;
|
||||||
const { control, register, handleSubmit, reset, watch, formState: { errors } } = useForm({
|
const {
|
||||||
|
control,
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
watch,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
resolver: yupResolver(validationSchema),
|
resolver: yupResolver(validationSchema),
|
||||||
});
|
});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@@ -54,7 +62,7 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (IODetails?.totalAmtInvestmentInUSD) {
|
if (IODetails?.totalAmtInvestmentInUSD) {
|
||||||
const totalAmount = parseFloat(IODetails.totalAmtInvestmentInUSD);
|
const totalAmount = parseFloat(IODetails.totalAmtInvestmentInUSD);
|
||||||
const ioCashUpdate = parseFloat(IODetails.totalAmtInvestmentInUSD)
|
const ioCashUpdate = parseFloat(IODetails.totalAmtInvestmentInUSD);
|
||||||
reset({
|
reset({
|
||||||
Total_Amount: totalAmount,
|
Total_Amount: totalAmount,
|
||||||
IoCash: ioCashUpdate,
|
IoCash: ioCashUpdate,
|
||||||
@@ -89,14 +97,18 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAmountChange = (e) => {
|
const handleAmountChange = (e) => {
|
||||||
const amount = parseFloat(e.target.value) || 0;
|
// e might be an object or just a value, handle both cases
|
||||||
|
const amount =
|
||||||
|
typeof e === "object" && e.target
|
||||||
|
? parseFloat(e.target.value) || 0
|
||||||
|
: parseFloat(e) || 0;
|
||||||
const totalAmount = parseFloat(IODetails?.totalAmtInvestmentInUSD) || 0;
|
const totalAmount = parseFloat(IODetails?.totalAmtInvestmentInUSD) || 0;
|
||||||
const ioCash = (totalAmount - amount).toFixed(2);
|
const ioCash = (totalAmount - amount).toFixed(2);
|
||||||
|
|
||||||
reset({
|
reset({
|
||||||
amountInvested: parseFloat(amount),
|
amountInvested: parseFloat(amount),
|
||||||
IoCash: parseFloat(ioCash),
|
IoCash: parseFloat(ioCash),
|
||||||
Total_Amount: IODetails?.totalAmtInvestmentInUSD
|
Total_Amount: IODetails?.totalAmtInvestmentInUSD,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,43 +116,67 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
|||||||
<Modal isOpen={isOpen} onClose={onClose}>
|
<Modal isOpen={isOpen} onClose={onClose}>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
<ModalHeader fontSize={'md'}>Amount Invested</ModalHeader>
|
<ModalHeader fontSize={"md"}>Amount Invested</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<FormControl mb={"15px"} isInvalid={!!errors.transactionDate} isRequired>
|
<FormControl
|
||||||
|
mb={"15px"}
|
||||||
|
isInvalid={!!errors.transactionDate}
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
||||||
Date
|
Date
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
type="date"
|
type="date"
|
||||||
{...register('transactionDate')}
|
{...register("transactionDate")}
|
||||||
size="sm"
|
size="sm"
|
||||||
rounded={'sm'}
|
rounded={"sm"}
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
focusBorderColor="forestGreen.300"
|
focusBorderColor="forestGreen.300"
|
||||||
/>
|
/>
|
||||||
{errors.transactionDate && <Text color="red.500">{errors.transactionDate.message}</Text>}
|
{errors.transactionDate && (
|
||||||
|
<Text fontSize={"xs"} fontWeight={600} color="red.500">
|
||||||
|
{errors.transactionDate.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl mb={"15px"} isInvalid={!!errors.Total_Amount} isReadOnly>
|
<FormControl
|
||||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>Amount</FormLabel>
|
mb={"15px"}
|
||||||
|
isInvalid={!!errors.Total_Amount}
|
||||||
|
isReadOnly
|
||||||
|
>
|
||||||
|
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
||||||
|
Amount
|
||||||
|
</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
value={formatCurrency(watch('Total_Amount'))}
|
value={formatCurrency(watch("Total_Amount"))}
|
||||||
size="sm"
|
size="sm"
|
||||||
rounded={'sm'}
|
rounded={"sm"}
|
||||||
textAlign={'end'}
|
textAlign={"end"}
|
||||||
focusBorderColor="forestGreen.300"
|
focusBorderColor="forestGreen.300"
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
{errors.Total_Amount && <Text color="red.500">{errors.Total_Amount.message}</Text>}
|
{errors.Total_Amount && (
|
||||||
|
<Text fontSize={"xs"} fontWeight={600} color="red.500">
|
||||||
|
{errors.Total_Amount.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl mb={"15px"} isInvalid={!!errors.amountInvested} isRequired>
|
<FormControl
|
||||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>Amount to invest</FormLabel>
|
mb={"15px"}
|
||||||
<Input
|
isInvalid={!!errors.amountInvested}
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
||||||
|
Amount to invest
|
||||||
|
</FormLabel>
|
||||||
|
{/* <Input
|
||||||
type="number"
|
type="number"
|
||||||
{...register('amountInvested')}
|
{...register('amountInvested')}
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -149,8 +185,29 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
|||||||
focusBorderColor="forestGreen.300"
|
focusBorderColor="forestGreen.300"
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
onChange={handleAmountChange}
|
onChange={handleAmountChange}
|
||||||
|
/> */}
|
||||||
|
<Controller
|
||||||
|
name="amountInvested"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CurrencyInput
|
||||||
|
{...field}
|
||||||
|
textAlign={"right"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
type="number"
|
||||||
|
size={"sm"}
|
||||||
|
onChange={(value) => {
|
||||||
|
field.onChange(value); // This will keep the form's internal state updated
|
||||||
|
handleAmountChange(value); // This will trigger your custom logic
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{errors.amountInvested && <Text color="red.500">{errors.amountInvested.message}</Text>}
|
)}
|
||||||
|
/>
|
||||||
|
{errors.amountInvested && (
|
||||||
|
<Text fontSize={"xs"} fontWeight={600} color="red.500">
|
||||||
|
{errors.amountInvested.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl mb={"15px"} isInvalid={!!errors.IoCash}>
|
<FormControl mb={"15px"} isInvalid={!!errors.IoCash}>
|
||||||
@@ -159,15 +216,19 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
value={formatCurrency(watch('IoCash'))}
|
value={formatCurrency(watch("IoCash"))}
|
||||||
size="sm"
|
size="sm"
|
||||||
rounded={'sm'}
|
rounded={"sm"}
|
||||||
focusBorderColor="forestGreen.300"
|
focusBorderColor="forestGreen.300"
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
textAlign={'right'}
|
textAlign={"right"}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
{errors.IoCash && <Text color="red.500">{errors.IoCash.message}</Text>}
|
{errors.IoCash && (
|
||||||
|
<Text fontSize={"xs"} fontWeight={600} color="red.500">
|
||||||
|
{errors.IoCash.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
@@ -179,15 +240,13 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
|||||||
_hover={{
|
_hover={{
|
||||||
bg: "hsl(139deg 98.99% 26.59%)",
|
bg: "hsl(139deg 98.99% 26.59%)",
|
||||||
}}
|
}}
|
||||||
size={'sm'}
|
size={"sm"}
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
|
||||||
size={'sm'}
|
|
||||||
rounded={"sm"} mr={3} onClick={onClose}>
|
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
|
Alert,
|
||||||
|
AlertIcon,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
FormControl,
|
FormControl,
|
||||||
@@ -20,29 +22,42 @@ import {
|
|||||||
Textarea,
|
Textarea,
|
||||||
Th,
|
Th,
|
||||||
Tr,
|
Tr,
|
||||||
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import DataTable from "../../../../Components/DataTable/DataTable";
|
import NormalData from "../../../../Components/DataTable/NormalTable";
|
||||||
import { useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { AddIcon } from "@chakra-ui/icons";
|
import { AddIcon } from "@chakra-ui/icons";
|
||||||
import { useGetDistributionInvestorMutation } from "../../../../Services/io.service";
|
import {
|
||||||
|
useGetDistributedToInvestorMutation,
|
||||||
|
useGetDistributionInvestorMutation,
|
||||||
|
useUpdateExitToInvestorMutation,
|
||||||
|
} from "../../../../Services/io.service";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import ToastBox from "../../../../Components/ToastBox";
|
||||||
|
import CurrencyInput from "../../../../Components/CurrencyInput";
|
||||||
export const investor = yup.object().shape({
|
import { IoCalculator } from "react-icons/io5";
|
||||||
amount: yup.string().required("Amount is required"),
|
import { debounce } from "../../../Master/Sponser/AddSponser";
|
||||||
});
|
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const DistributionInvestor = ({ isOpen, onClose, }) => {
|
const DistributionInvestor = ({ isOpen, onClose }) => {
|
||||||
|
const params = useParams();
|
||||||
|
const toast = useToast();
|
||||||
|
const id = params?.id;
|
||||||
|
const [ isCalculateLoading, setIsCalculateLoading ] = useState(false)
|
||||||
|
const [ isFinalCalculateLoading, setIsFinalCalculateLoading ] = useState(false)
|
||||||
|
const [ calcualtedData, setCalculatedDate ] = useState(null)
|
||||||
|
const [ isCalcualtedData, setIsCalcualtedData ] = useState(false)
|
||||||
|
const { IODetails } = useContext(GlobalStateContext);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const params = useParams()
|
|
||||||
const id = params?.id
|
|
||||||
|
|
||||||
// const {
|
// const {
|
||||||
// data:IObyID,
|
// data:IObyID,
|
||||||
@@ -50,7 +65,32 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
// isLoading,
|
// isLoading,
|
||||||
// } = useGetDistributionInvestorMutation(id);
|
// } = useGetDistributionInvestorMutation(id);
|
||||||
|
|
||||||
const [ getDistributionInvestment ] = useGetDistributionInvestorMutation()
|
const [getDistributionInvestment] = useGetDistributionInvestorMutation();
|
||||||
|
const [getFinalDistributionInvestment] =
|
||||||
|
useGetDistributedToInvestorMutation();
|
||||||
|
const [updateExitToInvestor] = useUpdateExitToInvestorMutation();
|
||||||
|
|
||||||
|
const investorExit = yup.object().shape({
|
||||||
|
amount: yup
|
||||||
|
.string()
|
||||||
|
.required("Amount is required")
|
||||||
|
.test(
|
||||||
|
"max",
|
||||||
|
`Distribution amount should not be greater than IO cash amount ${IODetails?.ioCash}`,
|
||||||
|
function(value) {
|
||||||
|
const { ioCash } = IODetails || {}; // Safely get ioCash
|
||||||
|
if (value && ioCash) {
|
||||||
|
return parseFloat(value) <= parseFloat(ioCash); // Ensure both are compared as numbers
|
||||||
|
}
|
||||||
|
return true; // If ioCash is not available, skip validation
|
||||||
|
}
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const investor = yup.object().shape({
|
||||||
|
amount: yup.string().required("Amount is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
@@ -58,25 +98,9 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
formState: { errors },
|
formState: { errors },
|
||||||
reset,
|
reset,
|
||||||
} = useForm({
|
} = useForm({
|
||||||
resolver: yupResolver(investor),
|
resolver: yupResolver(investorExit),
|
||||||
});
|
});
|
||||||
|
|
||||||
// useEffect(()=>{
|
|
||||||
// try {
|
|
||||||
// const res = getDistributionInvestment({id,data})
|
|
||||||
// console.log(res);
|
|
||||||
|
|
||||||
// } catch (error) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// },[])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// console.log(IObyID);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
@@ -86,27 +110,12 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
"First name",
|
"First name",
|
||||||
"Last Name",
|
"Last Name",
|
||||||
"Amount",
|
"Amount",
|
||||||
"%",
|
"Holding (%)",
|
||||||
"($)",
|
"Distriution Amt($)",
|
||||||
|
"Yeild (%)",
|
||||||
];
|
];
|
||||||
|
|
||||||
const filteredData = [
|
const extractedArray = calcualtedData?.data?.map((item, index) => ({
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [extractedArray, setExtractedArray] = useState(
|
|
||||||
filteredData?.map((item, index) => ({
|
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr No.": (
|
"Sr No.": (
|
||||||
<Box
|
<Box
|
||||||
@@ -124,58 +133,71 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
"Client Id": (
|
"Client Id": (
|
||||||
<Box w={100} isTruncated={true}>
|
<Box w={100} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
BH00000001
|
{item?.clientId}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"First name": (
|
"First name": (
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
Faisal
|
{item?.firstName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Last Name": (
|
"Last Name": (
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
Aljalahma
|
{item?.lastName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Amount: (
|
Amount: (
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
$100,000 /-
|
{item?.amount?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"%": (
|
"Holding (%)": (
|
||||||
<Box minW={19} isTruncated={true}>
|
|
||||||
<Text
|
|
||||||
textAlign={"right"}
|
|
||||||
as={"span"}
|
|
||||||
color={"teal.900"}
|
|
||||||
fontWeight={"500"}
|
|
||||||
>
|
|
||||||
26.0 %
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
),
|
|
||||||
"($)": (
|
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
$100,000 /-
|
{item?.investor_holidings?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}%
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
}))
|
"Distriution Amt($)": (
|
||||||
);
|
<Box minW={24} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item?.distribution_amt?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Yeild (%)": (
|
||||||
|
<Box minW={24} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item?.distribution_per?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}%
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
const Total = () => {
|
const Total = () => {
|
||||||
return (
|
return (
|
||||||
<Table size="sm">
|
<Table size="sm">
|
||||||
<Tbody backgroundColor="gray.50">
|
<Tbody>
|
||||||
<Tr>
|
<Tr backgroundColor="gray.50">
|
||||||
<Th
|
<Th
|
||||||
textAlign={"left"}
|
textAlign={"left"}
|
||||||
p={3}
|
p={3}
|
||||||
@@ -229,7 +251,10 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
overflowWrap="normal"
|
overflowWrap="normal"
|
||||||
>
|
>
|
||||||
$100200
|
{calcualtedData?.totalInvestedAmt?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Th>
|
</Th>
|
||||||
<Th
|
<Th
|
||||||
textAlign={"left"}
|
textAlign={"left"}
|
||||||
@@ -239,8 +264,9 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
whiteSpace="normal"
|
whiteSpace="normal"
|
||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
overflowWrap="normal"
|
overflowWrap="normal"
|
||||||
|
opacity={0}
|
||||||
>
|
>
|
||||||
100.0%
|
{calcualtedData?.distributed_per?.toFixed(2)}%
|
||||||
</Th>
|
</Th>
|
||||||
<Th
|
<Th
|
||||||
textAlign={"center"}
|
textAlign={"center"}
|
||||||
@@ -251,7 +277,10 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
overflowWrap="normal"
|
overflowWrap="normal"
|
||||||
>
|
>
|
||||||
$100230
|
{calcualtedData?.distributed_amt?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Th>
|
</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Tbody>
|
</Tbody>
|
||||||
@@ -259,19 +288,87 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (data) => {
|
||||||
|
setIsCalculateLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getDistributionInvestment({ id, data });
|
||||||
|
console.log(res?.data?.data);
|
||||||
|
|
||||||
const onSubmit = (data) =>{
|
if (res?.error?.status === 401) {
|
||||||
console.log( data );
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsCalculateLoading(false);
|
||||||
|
setIsCalcualtedData(false);
|
||||||
|
} else if (res?.data?.statusCode === 200) {
|
||||||
|
setCalculatedDate(res?.data?.data);
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
setIsCalculateLoading(false);
|
||||||
|
setIsCalcualtedData(true);
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinalSubmit = async (data) => {
|
||||||
|
setIsFinalCalculateLoading(true);
|
||||||
|
if (!isCalcualtedData) {
|
||||||
|
setIsFinalCalculateLoading(false);
|
||||||
|
return toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox
|
||||||
|
message={"Please calculate investment first."}
|
||||||
|
status="warn"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const finalData = {
|
||||||
|
transactionAmount: data?.amount,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getFinalDistributionInvestment({ id, data: finalData });
|
||||||
|
console.log(finalData);
|
||||||
|
|
||||||
|
if (res?.error?.status === 401) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status="error" />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else if (res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
handleClose();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("An error occurred:", error);
|
||||||
|
} finally {
|
||||||
|
handleClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
onClose();
|
||||||
|
setIsFinalCalculateLoading(false);
|
||||||
|
reset({
|
||||||
|
amount:""
|
||||||
|
});
|
||||||
|
setCalculatedDate(null);
|
||||||
|
setIsCalcualtedData(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal size={"xl"} isOpen={isOpen} onClose={onClose}>
|
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose}>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent maxW={1000}>
|
<ModalContent maxW={1200}>
|
||||||
<ModalHeader fontSize={"md"}>
|
<ModalHeader fontSize={"md"}>
|
||||||
Distribution To Investor Transaction
|
Distribution To Investor Transaction
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
@@ -282,40 +379,67 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
</Text> */}
|
</Text> */}
|
||||||
<HStack onSubmit={handleSubmit(onSubmit)} as={"form"} mb={4}>
|
<HStack onSubmit={handleSubmit(onSubmit)} as={"form"} mb={4}>
|
||||||
{/* <Input placeholder="$00.00" size={"sm"} className="col" /> */}
|
{/* <Input placeholder="$00.00" size={"sm"} className="col" /> */}
|
||||||
<FormControl isInvalid={errors.amount}>
|
<FormControl isInvalid={errors.amount} isRequired>
|
||||||
<FormLabel fontSize={"sm"}> Amount to Distribute</FormLabel>
|
<FormLabel textAlign={"right"} fontSize={"sm"}>
|
||||||
|
{" "}
|
||||||
|
Amount to Distribute
|
||||||
|
</FormLabel>
|
||||||
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"end"}
|
||||||
|
alignItems={"end"}
|
||||||
|
gap={2}
|
||||||
|
>
|
||||||
<Controller
|
<Controller
|
||||||
name="amount"
|
name="amount"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input {...field} fontSize={"sm"} type="number" size={"sm"} textAlign={"right"} />
|
<CurrencyInput
|
||||||
|
rounded={0}
|
||||||
|
w={"18%"}
|
||||||
|
{...field}
|
||||||
|
fontSize={"sm"}
|
||||||
|
type="number"
|
||||||
|
size={"sm"}
|
||||||
|
textAlign={"right"}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
|
|
||||||
{errors.amount?.message}
|
|
||||||
</FormErrorMessage>
|
|
||||||
</FormControl>
|
|
||||||
<Button
|
<Button
|
||||||
// leftIcon={<AddIcon />}
|
leftIcon={<IoCalculator />}
|
||||||
size={"sm"}
|
size={"sm"}
|
||||||
rounded={"sm"}
|
rounded={0}
|
||||||
colorScheme="forestGreen"
|
colorScheme="forestGreen"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
isLoading={isCalculateLoading}
|
||||||
>
|
>
|
||||||
Calculate
|
Calculate
|
||||||
</Button>
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<FormErrorMessage display={'flex'} justifyContent={'end'} pe={125} fontSize={"xs"} fontWeight={600}>
|
||||||
|
{errors.amount?.message}
|
||||||
|
</FormErrorMessage>
|
||||||
|
</FormControl>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
<DataTable
|
{calcualtedData ? (
|
||||||
|
<NormalData
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
setData={setExtractedArray}
|
// total={<Total />}
|
||||||
caption={<Total />}
|
|
||||||
// isLoading={isLoading}
|
// isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<Alert status="info" fontSize={"sm"} rounded={"sm"}>
|
||||||
|
<AlertIcon />
|
||||||
|
Please enter amount to calcutale Distribution!
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter pt={0}>
|
<ModalFooter pt={0}>
|
||||||
|
{isCalcualtedData ? (
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
bg={"hsla(139, 100%, 14%, 1)"}
|
bg={"hsla(139, 100%, 14%, 1)"}
|
||||||
mr={3}
|
mr={3}
|
||||||
@@ -325,12 +449,18 @@ const DistributionInvestor = ({ isOpen, onClose, }) => {
|
|||||||
}}
|
}}
|
||||||
size={"sm"}
|
size={"sm"}
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
|
onClick={handleSubmit(onFinalSubmit)}
|
||||||
|
isLoading={isFinalCalculateLoading}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
<Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
|
<Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
|
Alert,
|
||||||
|
AlertIcon,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormErrorMessage,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
HStack,
|
HStack,
|
||||||
Input,
|
Input,
|
||||||
@@ -19,46 +22,136 @@ import {
|
|||||||
Textarea,
|
Textarea,
|
||||||
Th,
|
Th,
|
||||||
Tr,
|
Tr,
|
||||||
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import DataTable from "../../../../Components/DataTable/DataTable";
|
import NormalData from "../../../../Components/DataTable/NormalTable";
|
||||||
import { useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { AddIcon } from "@chakra-ui/icons";
|
import { AddIcon } from "@chakra-ui/icons";
|
||||||
|
import {
|
||||||
|
useGetDistributedToInvestorMutation,
|
||||||
|
useGetDistributionInvestorMutation,
|
||||||
|
useUpdateExitToInvestorMutation,
|
||||||
|
} from "../../../../Services/io.service";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import ToastBox from "../../../../Components/ToastBox";
|
||||||
|
import CurrencyInput from "../../../../Components/CurrencyInput";
|
||||||
|
import { IoCalculator } from "react-icons/io5";
|
||||||
|
import { debounce } from "../../../Master/Sponser/AddSponser";
|
||||||
|
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||||
|
|
||||||
const Exit = ({ isOpen, onClose }) => {
|
const Exit = ({ isOpen, onClose }) => {
|
||||||
|
const params = useParams();
|
||||||
|
const toast = useToast();
|
||||||
|
const id = params?.id;
|
||||||
|
const [isCalculateLoading, setIsCalculateLoading] = useState(false);
|
||||||
|
const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false);
|
||||||
|
const [calcualtedData, setCalculatedDate] = useState(null);
|
||||||
|
const [isCalcualtedData, setIsCalcualtedData] = useState(false);
|
||||||
|
const { IODetails } = useContext(GlobalStateContext);
|
||||||
|
|
||||||
|
const investorExit = yup.object().shape({
|
||||||
|
amount: yup
|
||||||
|
.string()
|
||||||
|
.required("Amount is required")
|
||||||
|
.test(
|
||||||
|
"max",
|
||||||
|
`Distribution amount should not be greater than IO cash amount ${IODetails?.ioCash}`,
|
||||||
|
function (value) {
|
||||||
|
const { ioCash } = IODetails || {}; // Safely get ioCash
|
||||||
|
if (value && ioCash) {
|
||||||
|
return parseFloat(value) <= parseFloat(ioCash); // Ensure both are compared as numbers
|
||||||
|
}
|
||||||
|
return true; // If ioCash is not available, skip validation
|
||||||
|
}
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
reset,
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(investorExit),
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("hiit useEffectc");
|
||||||
|
handleCalculate(id, {
|
||||||
|
amount: IODetails?.ioMVNAV,
|
||||||
|
});
|
||||||
|
reset({
|
||||||
|
amount: IODetails?.ioMVNAV,
|
||||||
|
});
|
||||||
|
}, [IODetails, id]);
|
||||||
|
|
||||||
|
const handleCalculate = async (id, data) => {
|
||||||
|
try {
|
||||||
|
const res = await getDistributionInvestment({ id, data });
|
||||||
|
console.log(res?.data?.data);
|
||||||
|
|
||||||
|
if (res?.error?.status === 401) {
|
||||||
|
// toast({
|
||||||
|
// render: () => (
|
||||||
|
// <ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
// ),
|
||||||
|
// });
|
||||||
|
setIsCalculateLoading(false);
|
||||||
|
setIsCalcualtedData(false);
|
||||||
|
} else if (res?.data?.statusCode === 200) {
|
||||||
|
setCalculatedDate(res?.data?.data);
|
||||||
|
// toast({
|
||||||
|
// render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
// });
|
||||||
|
setIsCalculateLoading(false);
|
||||||
|
setIsCalcualtedData(true);
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// const {
|
||||||
|
// data:IObyID,
|
||||||
|
// error,
|
||||||
|
// isLoading,
|
||||||
|
// } = useGetDistributionInvestorMutation(id);
|
||||||
|
|
||||||
|
const [getDistributionInvestment] = useGetDistributionInvestorMutation();
|
||||||
|
const [getFinalDistributionInvestment] =
|
||||||
|
useGetDistributedToInvestorMutation();
|
||||||
|
const [updateExitToInvestor] = useUpdateExitToInvestorMutation();
|
||||||
|
|
||||||
|
const investor = yup.object().shape({
|
||||||
|
amount: yup.string().required("Amount is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
// useEffect(()=>{
|
||||||
|
// try {
|
||||||
|
// const res = getDistributionInvestment({id,data})
|
||||||
|
// console.log(res);
|
||||||
|
|
||||||
|
// } catch (error) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// },[])
|
||||||
|
|
||||||
|
// console.log(IObyID);
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
"Sr No.",
|
"Sr No.",
|
||||||
"Client Id",
|
"Client Id",
|
||||||
"First name",
|
"First name",
|
||||||
"Last Name",
|
"Last Name",
|
||||||
"Invested Amount",
|
"Amount",
|
||||||
"Distribution %",
|
"Holding (%)",
|
||||||
"Exit Amount",
|
"Exit Amt($)",
|
||||||
];
|
];
|
||||||
|
|
||||||
const filteredData = [
|
const extractedArray = calcualtedData?.data?.map((item, index) => ({
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [extractedArray, setExtractedArray] = useState(
|
|
||||||
filteredData?.map((item, index) => ({
|
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr No.": (
|
"Sr No.": (
|
||||||
<Box
|
<Box
|
||||||
@@ -76,58 +169,61 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
"Client Id": (
|
"Client Id": (
|
||||||
<Box w={100} isTruncated={true}>
|
<Box w={100} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
BH0000000
|
{item?.clientId}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"First name": (
|
"First name": (
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
Faisal
|
{item?.firstName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Last Name": (
|
"Last Name": (
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
Aljalahma
|
{item?.lastName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Invested Amount": (
|
Amount: (
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
$100,000
|
{item?.amount?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Distribution %": (
|
"Holding (%)": (
|
||||||
<Box minW={19} isTruncated={true}>
|
|
||||||
<Text
|
|
||||||
textAlign={"right"}
|
|
||||||
as={"span"}
|
|
||||||
color={"teal.900"}
|
|
||||||
fontWeight={"500"}
|
|
||||||
>
|
|
||||||
26.0 %
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
),
|
|
||||||
"Exit Amount": (
|
|
||||||
<Box minW={24} isTruncated={true}>
|
<Box minW={24} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
$100,000
|
{item?.investor_holidings?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}%
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
}))
|
"Exit Amt($)": (
|
||||||
);
|
<Box minW={24} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item?.distribution_amt?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
const Total = () => {
|
const Total = () => {
|
||||||
return (
|
return (
|
||||||
<Table size="sm">
|
<Table size="sm">
|
||||||
<Tbody backgroundColor="gray.50">
|
<Tbody>
|
||||||
<Tr>
|
<Tr backgroundColor="gray.50">
|
||||||
<Th
|
<Th
|
||||||
textAlign={"left"}
|
textAlign={"left"}
|
||||||
p={3}
|
p={3}
|
||||||
@@ -142,7 +238,7 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
<Th
|
<Th
|
||||||
textAlign={"center"}
|
textAlign={"center"}
|
||||||
p={3}
|
p={3}
|
||||||
width="100px"
|
width="110px"
|
||||||
color={"#004118"}
|
color={"#004118"}
|
||||||
whiteSpace="normal"
|
whiteSpace="normal"
|
||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
@@ -153,7 +249,7 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
<Th
|
<Th
|
||||||
textAlign={"center"}
|
textAlign={"center"}
|
||||||
p={3}
|
p={3}
|
||||||
width="90px"
|
width="110px"
|
||||||
color={"#004118"}
|
color={"#004118"}
|
||||||
whiteSpace="normal"
|
whiteSpace="normal"
|
||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
@@ -164,7 +260,7 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
<Th
|
<Th
|
||||||
textAlign={"center"}
|
textAlign={"center"}
|
||||||
p={3}
|
p={3}
|
||||||
width="90px"
|
width="110px"
|
||||||
color={"#004118"}
|
color={"#004118"}
|
||||||
whiteSpace="normal"
|
whiteSpace="normal"
|
||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
@@ -175,13 +271,16 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
<Th
|
<Th
|
||||||
textAlign={"left"}
|
textAlign={"left"}
|
||||||
p={3}
|
p={3}
|
||||||
width="100px"
|
width="110px"
|
||||||
color={"#004118"}
|
color={"#004118"}
|
||||||
whiteSpace="normal"
|
whiteSpace="normal"
|
||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
overflowWrap="normal"
|
overflowWrap="normal"
|
||||||
>
|
>
|
||||||
$1,000,000
|
{calcualtedData?.totalInvestedAmt?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Th>
|
</Th>
|
||||||
<Th
|
<Th
|
||||||
textAlign={"left"}
|
textAlign={"left"}
|
||||||
@@ -191,8 +290,9 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
whiteSpace="normal"
|
whiteSpace="normal"
|
||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
overflowWrap="normal"
|
overflowWrap="normal"
|
||||||
|
opacity={0}
|
||||||
>
|
>
|
||||||
100.0%
|
{calcualtedData?.distributed_per?.toFixed(2)}%
|
||||||
</Th>
|
</Th>
|
||||||
<Th
|
<Th
|
||||||
textAlign={"center"}
|
textAlign={"center"}
|
||||||
@@ -203,7 +303,10 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
wordBreak="normal"
|
wordBreak="normal"
|
||||||
overflowWrap="normal"
|
overflowWrap="normal"
|
||||||
>
|
>
|
||||||
$1,229,750
|
{calcualtedData?.distributed_amt?.toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Th>
|
</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Tbody>
|
</Tbody>
|
||||||
@@ -211,35 +314,129 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (data) => {
|
||||||
|
setIsCalculateLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getDistributionInvestment({ id, data });
|
||||||
|
console.log(res?.data?.data);
|
||||||
|
|
||||||
|
if (res?.error?.status === 401) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsCalculateLoading(false);
|
||||||
|
setIsCalcualtedData(false);
|
||||||
|
} else if (res?.data?.statusCode === 200) {
|
||||||
|
setCalculatedDate(res?.data?.data);
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
setIsCalculateLoading(false);
|
||||||
|
setIsCalcualtedData(true);
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinalSubmit = async (data) => {
|
||||||
|
console.log("hit");
|
||||||
|
setIsFinalCalculateLoading(true);
|
||||||
|
// if (!isCalcualtedData) {
|
||||||
|
// setIsFinalCalculateLoading(false);
|
||||||
|
// return toast({
|
||||||
|
// render: () => (
|
||||||
|
// <ToastBox
|
||||||
|
// message={"Please calculate investment first."}
|
||||||
|
// status="warn"
|
||||||
|
// />
|
||||||
|
// ),
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
const finalData = {
|
||||||
|
transactionAmount: IODetails?.ioMVNAV,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await updateExitToInvestor({ id, data: finalData });
|
||||||
|
console.log(finalData);
|
||||||
|
|
||||||
|
if (res?.error?.status === 401) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status="error" />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else if (res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
handleClose();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("An error occurred:", error);
|
||||||
|
} finally {
|
||||||
|
handleClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
onClose();
|
||||||
|
setIsFinalCalculateLoading(false);
|
||||||
|
setIsCalcualtedData(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal size={"xl"} isOpen={isOpen} onClose={onClose}>
|
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose}>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent maxW={1000}>
|
<ModalContent maxW={1000}>
|
||||||
<ModalHeader fontSize={"md"}>Exit Transaction</ModalHeader>
|
<ModalHeader fontSize={"md"}>Exit Transaction</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Text as="label" mb='5px' fontSize='sm' fontWeight={500}>Enter Exit Amount</Text>
|
{/* <Text as="label" mb="5px" fontSize="sm" fontWeight={500}>
|
||||||
<HStack mb={4}>
|
Amount to Distribute
|
||||||
<Input focusBorderColor="forestGreen.400" placeholder="$00.00" size={"sm"} className="col" />
|
</Text> */}
|
||||||
<Button
|
<HStack onSubmit={handleSubmit(onSubmit)} as={"form"} mb={4} alignItems={'center'}>
|
||||||
size={"sm"}
|
{/* <Input placeholder="$00.00" size={"sm"} className="col" /> */}
|
||||||
rounded={"sm"}
|
{/* <FormControl isInvalid={errors.amount} isRequired>*/}
|
||||||
colorScheme="forestGreen"
|
<Text textAlign={"right"} fontSize={"sm"}>
|
||||||
|
Exit Amount :
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
textAlign={"start"}
|
||||||
|
bg={"green.100"}
|
||||||
|
p={2}
|
||||||
|
rounded={"md"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
pt={1}
|
||||||
|
pb={1}
|
||||||
|
fontWeight={600}
|
||||||
>
|
>
|
||||||
Calculate
|
${" "}
|
||||||
</Button>
|
{parseFloat(IODetails?.ioMVNAV || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{/* </FormControl> */}
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
<DataTable
|
{/* {calcualtedData && ( */}
|
||||||
|
<NormalData
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
setData={setExtractedArray}
|
// total={<Total />}
|
||||||
caption={<Total />}
|
|
||||||
// isLoading={isLoading}
|
// isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
{/* ) } */}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter pt={0}>
|
<ModalFooter pt={0}>
|
||||||
|
{isCalcualtedData ? (
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
bg={"hsla(139, 100%, 14%, 1)"}
|
bg={"hsla(139, 100%, 14%, 1)"}
|
||||||
mr={3}
|
mr={3}
|
||||||
@@ -247,16 +444,20 @@ const Exit = ({ isOpen, onClose }) => {
|
|||||||
_hover={{
|
_hover={{
|
||||||
bg: "hsl(139deg 98.99% 26.59%)",
|
bg: "hsl(139deg 98.99% 26.59%)",
|
||||||
}}
|
}}
|
||||||
size={'sm'}
|
size={"sm"}
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
|
onClick={() => onFinalSubmit()}
|
||||||
|
isLoading={isFinalCalculateLoading}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
|
||||||
size={'sm'}
|
|
||||||
rounded={"sm"} mr={3} onClick={onClose}>
|
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -16,10 +16,12 @@ import {
|
|||||||
ModalFooter,
|
ModalFooter,
|
||||||
ModalHeader,
|
ModalHeader,
|
||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
FormErrorMessage
|
FormErrorMessage,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import {
|
import {
|
||||||
useGetIOprepopulateDataQuery,
|
useGetIOprepopulateDataQuery,
|
||||||
|
useUpdateCancleStatusMutation,
|
||||||
|
useUpdateCancleStatusToMutation,
|
||||||
useUpdateStatusIoMutation,
|
useUpdateStatusIoMutation,
|
||||||
} from "../../../../Services/io.service";
|
} from "../../../../Services/io.service";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
@@ -30,10 +32,11 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
|||||||
const [selectedItem, setSelectedItem] = useState();
|
const [selectedItem, setSelectedItem] = useState();
|
||||||
const [isLoadingg, setIsLoading] = useState(false);
|
const [isLoadingg, setIsLoading] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [selectedStatusId, setSelectedStatusId] = useState('');
|
const [selectedStatusId, setSelectedStatusId] = useState("");
|
||||||
|
|
||||||
const { data } = useGetIOprepopulateDataQuery();
|
const { data } = useGetIOprepopulateDataQuery();
|
||||||
const [updateStatusIo] = useUpdateStatusIoMutation();
|
const [updateStatusIo] = useUpdateStatusIoMutation();
|
||||||
|
const [updateCancleStatus] = useUpdateCancleStatusToMutation();
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// setSelectedStatusId(status?.[0]?.id);
|
// setSelectedStatusId(status?.[0]?.id);
|
||||||
@@ -52,13 +55,25 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
|||||||
setError("");
|
setError("");
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await updateStatusIo({
|
let res;
|
||||||
|
|
||||||
|
// If selectedItem is 'Cancelled', make the updateCancelStatus API call
|
||||||
|
if (selectedItem === "Cancelled") {
|
||||||
|
res = await updateCancleStatus({
|
||||||
|
id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Otherwise, make the updateStatusIo API call
|
||||||
|
else {
|
||||||
|
res = await updateStatusIo({
|
||||||
data: {
|
data: {
|
||||||
ioStatus_xid: selectedStatusId,
|
ioStatus_xid: selectedStatusId,
|
||||||
},
|
},
|
||||||
id,
|
id,
|
||||||
});
|
});
|
||||||
console.log(res);
|
}
|
||||||
|
|
||||||
|
console.log("API Response:", res);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
handleClose();
|
handleClose();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -67,11 +82,11 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setSelectedItem(null)
|
setSelectedItem(null);
|
||||||
setSelectedStatusId(null)
|
setSelectedStatusId(null);
|
||||||
onClose()
|
onClose();
|
||||||
setError("")
|
setError("");
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onClose={handleClose}>
|
<Modal isOpen={isOpen} onClose={handleClose}>
|
||||||
@@ -114,18 +129,22 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
|||||||
? "green"
|
? "green"
|
||||||
: selectedItem === "Exited"
|
: selectedItem === "Exited"
|
||||||
? "red"
|
? "red"
|
||||||
: selectedItem === "Canclled"
|
: selectedItem === "Cancelled"
|
||||||
? "orange"
|
? "orange"
|
||||||
: "purple"
|
: "purple"
|
||||||
}
|
}
|
||||||
py={"3px"} px={"8px"}
|
py={"3px"}
|
||||||
|
px={"8px"}
|
||||||
>
|
>
|
||||||
{selectedItem}
|
{selectedItem}
|
||||||
</Badge>
|
</Badge>
|
||||||
) : "Select Item"}
|
) : (
|
||||||
|
"Select Item"
|
||||||
|
)}
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
|
|
||||||
{status?.length > 0 ?<MenuList w={"400px"}>
|
{status?.length > 0 ? (
|
||||||
|
<MenuList w={"400px"}>
|
||||||
{status?.map(({ id, statusAdmin }) => (
|
{status?.map(({ id, statusAdmin }) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={id}
|
key={id}
|
||||||
@@ -152,19 +171,25 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
|||||||
? "green"
|
? "green"
|
||||||
: statusAdmin === "Exited"
|
: statusAdmin === "Exited"
|
||||||
? "red"
|
? "red"
|
||||||
: statusAdmin === "Canclled"
|
: statusAdmin === "Cancelled"
|
||||||
? "orange"
|
? "orange"
|
||||||
: "purple"
|
: "purple"
|
||||||
}
|
}
|
||||||
py={"1px"} px={"8px"}
|
py={"1px"}
|
||||||
|
px={"8px"}
|
||||||
>
|
>
|
||||||
{statusAdmin}
|
{statusAdmin}
|
||||||
</Badge>
|
</Badge>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</MenuList>:""}
|
</MenuList>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</Menu>
|
</Menu>
|
||||||
<FormErrorMessage fontSize={'xs'} fontWeight={600} >{error}</FormErrorMessage>
|
<FormErrorMessage fontSize={"xs"} fontWeight={600}>
|
||||||
|
{error}
|
||||||
|
</FormErrorMessage>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
|||||||
@@ -42,18 +42,25 @@ import { formatCurrency } from "../../../Components/CurrencyInput";
|
|||||||
import { IoIosPhonePortrait } from "react-icons/io";
|
import { IoIosPhonePortrait } from "react-icons/io";
|
||||||
import MobileView from "../../../Components/MobileView";
|
import MobileView from "../../../Components/MobileView";
|
||||||
import { ImMobile } from "react-icons/im";
|
import { ImMobile } from "react-icons/im";
|
||||||
import { removeTrailingZeros } from "../../../Constants/Constants";
|
import {
|
||||||
|
generateSerialNumber,
|
||||||
|
removeTrailingZeros,
|
||||||
|
} from "../../../Constants/Constants";
|
||||||
// import { debounce } from "./AddIOCharges";
|
// import { debounce } from "./AddIOCharges";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
}; // Simple date formatter
|
||||||
|
|
||||||
const ViewIOTable = () => {
|
const ViewIOTable = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { IODetails, setIODetails, slideFromRight } =
|
const { IODetails, setIODetails, slideFromRight } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
const [statusFilter, setStatusFilter] = useState("all");
|
|
||||||
// const [isLoading, setIsLoading] = useState(true);
|
// const [isLoading, setIsLoading] = useState(true);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
@@ -65,23 +72,45 @@ const ViewIOTable = () => {
|
|||||||
// ===============================[ Paginations ]
|
// ===============================[ Paginations ]
|
||||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [statusFilter, setStatusFilter] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
// ===============================[ RTK Api calls ]
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
// ===============================[ RTK Api calls ] =============================================
|
||||||
const { data, isLoading, error } = useGetIOsQuery({
|
const { data, isLoading, error } = useGetIOsQuery({
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
size: pageSize,
|
size: pageSize,
|
||||||
|
ioStatus_xid: statusFilter,
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
// ===============================[ Table Header ]
|
// ===============================[ Table Header ]
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
|
"Sr No.",
|
||||||
"IO ID",
|
"IO ID",
|
||||||
"IO Name",
|
"IO Name",
|
||||||
"Sponsor",
|
"Sponsor",
|
||||||
"Investment Type",
|
"Investment Type",
|
||||||
"Goal Amount",
|
"Goal Amount",
|
||||||
"Holding Period",
|
"Amount Raised",
|
||||||
|
"Closing Date",
|
||||||
"IO Status",
|
"IO Status",
|
||||||
"Preview",
|
// "Preview",
|
||||||
"Action",
|
"Action",
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -101,7 +130,19 @@ const ViewIOTable = () => {
|
|||||||
return nameMatches && statusMatches;
|
return nameMatches && statusMatches;
|
||||||
});
|
});
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||||
|
"Sr No.": (
|
||||||
|
<Text
|
||||||
|
w={"24px"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{/* {item.id} */}
|
||||||
|
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
"IO ID": (
|
"IO ID": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
@@ -110,13 +151,31 @@ const ViewIOTable = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"IO Name": (
|
"IO Name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Tooltip
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
hasArrow
|
||||||
|
bg="#c6f6d5"
|
||||||
|
fontSize={"xs"}
|
||||||
|
label={item.investmentNameEnglish ? item.investmentNameEnglish : "---"}
|
||||||
|
placement="top-start"
|
||||||
|
color={"blue.800"}
|
||||||
|
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
maxWidth="100px" // Adjust width as needed
|
||||||
|
display="block" // Ensure block display for proper truncation
|
||||||
|
overflow="hidden"
|
||||||
|
isTruncated
|
||||||
|
textOverflow="ellipsis"
|
||||||
|
cursor={"pointer"}
|
||||||
|
>
|
||||||
{item.investmentNameEnglish ? item.investmentNameEnglish : "---"}
|
{item.investmentNameEnglish ? item.investmentNameEnglish : "---"}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Tooltip>
|
||||||
),
|
),
|
||||||
Sponsorer: (
|
Sponsor: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
{item?.sponsor?.sponsorName ? item.sponsor?.sponsorName : "---"}
|
{item?.sponsor?.sponsorName ? item.sponsor?.sponsorName : "---"}
|
||||||
@@ -124,7 +183,7 @@ const ViewIOTable = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Investment Type": (
|
"Investment Type": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"120px"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
{item?.investmentType?.investmentTypeName
|
{item?.investmentType?.investmentTypeName
|
||||||
? item.investmentType?.investmentTypeName
|
? item.investmentType?.investmentTypeName
|
||||||
@@ -133,24 +192,40 @@ const ViewIOTable = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Goal Amount": (
|
"Goal Amount": (
|
||||||
<Box w={"100%"} display={"flex"} alignItems={"center"}>
|
<Box w={"100%"} display={"flex"} justifyContent={"start"} alignItems={'center'}>
|
||||||
<Text
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
w={"100%"}
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
textAlign={"center"}
|
$
|
||||||
as={"span"}
|
</Badge>
|
||||||
color={"teal.900"}
|
{`${parseFloat(item.goalAmount || 0).toLocaleString(undefined, {
|
||||||
fontWeight={"500"}
|
minimumFractionDigits: 2,
|
||||||
>
|
maximumFractionDigits: 2,
|
||||||
{item.goalAmount
|
})}`}
|
||||||
? formatCurrency(removeTrailingZeros(item.goalAmount))
|
|
||||||
: "---"}
|
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Holding Period": (
|
"Amount Raised": (
|
||||||
|
<Box w={"100%"} display={"flex"} justifyContent={"start"} alignItems={'center'}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{/* {item.goalAmount
|
||||||
|
? formatCurrency(removeTrailingZeros(item.goalAmount))
|
||||||
|
: "---"} */}
|
||||||
|
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{`${parseFloat(item.totalRaisedAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}`}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Closing Date": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
{item.holdingPeriod ? item.holdingPeriod : "---"}
|
{/* {item.closingDate ? item.closingDate : "---"} */}
|
||||||
|
{formatDate(item.closingDate ? item.closingDate : "---")}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
@@ -190,12 +265,15 @@ const ViewIOTable = () => {
|
|||||||
Preview: (
|
Preview: (
|
||||||
<Box display={"flex"} justifyContent={"start"}>
|
<Box display={"flex"} justifyContent={"start"}>
|
||||||
<Badge
|
<Badge
|
||||||
display={"flex"} px={2} py={1} alignItems={"center"}
|
display={"flex"}
|
||||||
|
px={2}
|
||||||
|
py={1}
|
||||||
|
alignItems={"center"}
|
||||||
color={"#000"}
|
color={"#000"}
|
||||||
fontWeight={500}
|
fontWeight={500}
|
||||||
bg="purple.200"
|
bg="purple.200"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActionId(item.id)
|
setActionId(item.id);
|
||||||
onOpen();
|
onOpen();
|
||||||
}}
|
}}
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
@@ -315,17 +393,17 @@ const ViewIOTable = () => {
|
|||||||
cursor={"pointer"}
|
cursor={"pointer"}
|
||||||
value={statusFilter} // Use the value prop here
|
value={statusFilter} // Use the value prop here
|
||||||
>
|
>
|
||||||
<option value="all" selected disabled hidden defaultChecked>
|
<option value="" selected disabled hidden defaultChecked>
|
||||||
Status
|
Status
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option value="all">All</option>
|
<option value="">All</option>
|
||||||
<option value="Draft">Draft</option>
|
<option value="1">Draft</option>
|
||||||
<option value="Cancelled">Cancelled</option>
|
<option value="6">Cancelled</option>
|
||||||
<option value="Processing">Processing</option>
|
<option value="3">Processing</option>
|
||||||
<option value="Open">Open</option>
|
<option value="2">Open</option>
|
||||||
<option value="Exited">Exited</option>
|
<option value="5">Exited</option>
|
||||||
<option value="Closed">Closed</option>
|
<option value="4">Closed</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<Pagination
|
<Pagination
|
||||||
@@ -367,7 +445,7 @@ const ViewIOTable = () => {
|
|||||||
setMouseEntered={setMouseEntered}
|
setMouseEntered={setMouseEntered}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MobileView isOpen={isOpen} onClose={onClose} actionId={actionId} />
|
{/* <MobileView isOpen={isOpen} onClose={onClose} actionId={actionId} /> */}
|
||||||
|
|
||||||
<CustomAlertDialog
|
<CustomAlertDialog
|
||||||
onClose={() => setDeleteAlert(false)}
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
|||||||
@@ -29,18 +29,18 @@ import ViewIOnav from "./ViewIOnav";
|
|||||||
import ViewDistribution from "./ViewDistribution";
|
import ViewDistribution from "./ViewDistribution";
|
||||||
import InvestmentDocument from "../CreateIO/InvestmentDocument";
|
import InvestmentDocument from "../CreateIO/InvestmentDocument";
|
||||||
import KeyMerits from "../CreateIO/KeyMerits";
|
import KeyMerits from "../CreateIO/KeyMerits";
|
||||||
import Investors from "../CreateIO/Investors"
|
import Investors from "../CreateIO/Investors";
|
||||||
import EditIO from "../EditIO/EditIO";
|
import EditIO from "../EditIO/EditIO";
|
||||||
import IOArtifacts from "../CreateIO/IOArtifacts";
|
import IOArtifacts from "../CreateIO/IOArtifacts";
|
||||||
import IOCashDetails from "../CreateIO/IOCashDetails";
|
import IOCashDetails from "../CreateIO/IOCashDetails";
|
||||||
import IONAVDetails from "../CreateIO/IONAVDetails";
|
import IONAVDetails from "../CreateIO/IONAVDetails";
|
||||||
import { useGetIOprepopulateDataQuery } from "../../../Services/io.service";
|
import { useGetIOprepopulateDataQuery } from "../../../Services/io.service";
|
||||||
import UnderConstruction from "../../UnderConstruction";
|
import UnderConstruction from "../../UnderConstruction";
|
||||||
|
import Destribution from "../CreateIO/Destribution";
|
||||||
|
|
||||||
const ViewIOdata = () => {
|
const ViewIOdata = () => {
|
||||||
const params = useParams()
|
const params = useParams();
|
||||||
const id = params?.id
|
const id = params?.id;
|
||||||
const { data, error, isLoading } = useGetIOprepopulateDataQuery();
|
const { data, error, isLoading } = useGetIOprepopulateDataQuery();
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -48,23 +48,33 @@ const ViewIOdata = () => {
|
|||||||
const { IODetails, setIODetails } = useContext(GlobalStateContext);
|
const { IODetails, setIODetails } = useContext(GlobalStateContext);
|
||||||
console.log(IODetails?.isInvestedAmount);
|
console.log(IODetails?.isInvestedAmount);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ label: "IO Details", content: <ViewIOdetails data={data?.data} /> },
|
{ label: "IO Details", content: <ViewIOdetails data={data?.data} /> },
|
||||||
{ label: "Investment documents", content: <InvestmentDocument data={data?.data} /> },
|
{
|
||||||
|
label: "Investment documents",
|
||||||
|
content: <InvestmentDocument data={data?.data} />,
|
||||||
|
},
|
||||||
{ label: "Key merits", content: <KeyMerits data={data?.data} /> },
|
{ label: "Key merits", content: <KeyMerits data={data?.data} /> },
|
||||||
{ label: "IO artifacts", content: <IOArtifacts data={data?.data} /> },
|
{ label: "IO artifacts", content: <IOArtifacts data={data?.data} /> },
|
||||||
{ label: "Investors", content: <Investors data={data?.data} /> },
|
{ label: "Investors", content: <Investors data={data?.data} /> },
|
||||||
// { label: "Investors", content: <UnderConstruction h={'75vh'} /> },
|
// { label: "Investors", content: <UnderConstruction h={'75vh'} /> },
|
||||||
{ label: "IO Cash Details", content: <IOCashDetails data={data?.data} /> },
|
{ label: "IO Cash Details", content: <IOCashDetails data={data?.data} /> },
|
||||||
{ label: "IO NAV Details", content: <IONAVDetails data={data?.data} /> },
|
{ label: "IO NAV Details", content: <IONAVDetails data={data?.data} /> },
|
||||||
// { label: "Distribution to Investors", content: <IONAVDetails data={data?.data} /> },
|
{
|
||||||
{ label: "Distribution to Investors", content: <UnderConstruction h={'75vh'} /> },
|
label: "Distribution to Investors",
|
||||||
|
content: <Destribution data={data?.data} />,
|
||||||
|
},
|
||||||
|
// { label: "Distribution to Investors", content: <UnderConstruction h={'75vh'} /> },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} overflowX={"hidden"} height={"100vh"} pb={14} >
|
<Box
|
||||||
|
{...OPACITY_ON_LOAD}
|
||||||
|
overflowY={"scroll"}
|
||||||
|
overflowX={"hidden"}
|
||||||
|
height={"100vh"}
|
||||||
|
pb={14}
|
||||||
|
>
|
||||||
<Box paddingInline={"12px"} mt={2}>
|
<Box paddingInline={"12px"} mt={2}>
|
||||||
{/* <span
|
{/* <span
|
||||||
onClick={() => navigate(-1)}
|
onClick={() => navigate(-1)}
|
||||||
@@ -76,8 +86,8 @@ const ViewIOdata = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Tabs mt={4}>
|
<Tabs mt={4}>
|
||||||
<TabList justifyContent={'space-between'} pe={4} alignItems={'center'}>
|
<TabList justifyContent={"space-between"} pe={4} alignItems={"center"}>
|
||||||
<Box display={'flex'} >
|
<Box display={"flex"}>
|
||||||
{tabs.map(({ label }, index) => (
|
{tabs.map(({ label }, index) => (
|
||||||
<Tab
|
<Tab
|
||||||
px={3}
|
px={3}
|
||||||
@@ -86,9 +96,10 @@ const ViewIOdata = () => {
|
|||||||
index === 1 ||
|
index === 1 ||
|
||||||
index === 2 ||
|
index === 2 ||
|
||||||
index === 3 ||
|
index === 3 ||
|
||||||
index === 4 ?
|
index === 4
|
||||||
false :
|
? false
|
||||||
!IODetails?.isInvestedAmount}
|
: !IODetails?.isInvestedAmount
|
||||||
|
}
|
||||||
key={index}
|
key={index}
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
_selected={{
|
_selected={{
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ const ViewIOdataHeader = ({data, isLoading}) => {
|
|||||||
const btnRef = useRef();
|
const btnRef = useRef();
|
||||||
const { IODetails, isIOloading } = useContext(GlobalStateContext);
|
const { IODetails, isIOloading } = useContext(GlobalStateContext);
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isOpen: isInvestmentOpen,
|
isOpen: isInvestmentOpen,
|
||||||
onOpen: onInvestmentOpen,
|
onOpen: onInvestmentOpen,
|
||||||
@@ -104,17 +103,16 @@ const ViewIOdataHeader = ({data, isLoading}) => {
|
|||||||
fontWeight: "400",
|
fontWeight: "400",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(
|
||||||
console.log(import.meta.env.VITE_IMAGE_URL +
|
import.meta.env.VITE_IMAGE_URL +
|
||||||
IODetails?.artifactsImage?.[0]?.artifactPathName);
|
IODetails?.artifactsImage?.[0]?.artifactPathName
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
const menu = [
|
const menu = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "Amount Invested",
|
title: "Amount Invested",
|
||||||
onClickFunction: onInvestmentOpen
|
onClickFunction: onInvestmentOpen,
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// id:2,
|
// id:2,
|
||||||
@@ -129,45 +127,45 @@ const ViewIOdataHeader = ({data, isLoading}) => {
|
|||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
title: "Distribution To Investors",
|
title: "Distribution To Investors",
|
||||||
onClickFunction:onDistInvestorOpen
|
onClickFunction: onDistInvestorOpen,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
title: "Update IO NAV",
|
title: "Update IO NAV",
|
||||||
onClickFunction:onUpdateNavOpen
|
onClickFunction: onUpdateNavOpen,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 8,
|
id: 8,
|
||||||
title: "Exit",
|
title: "Exit",
|
||||||
onClickFunction:onExitOpen
|
onClickFunction: onExitOpen,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 9,
|
id: 9,
|
||||||
title: "Cancel",
|
title: "Cancel",
|
||||||
onClickFunction:onCancleOpen
|
onClickFunction: onCancleOpen,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 10,
|
id: 10,
|
||||||
title: "Update IO Status",
|
title: "Update IO Status",
|
||||||
onClickFunction:onUpdateStatusOpen
|
onClickFunction: onUpdateStatusOpen,
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
// console.log(IODetails?.mainTranscation);
|
// console.log(IODetails?.mainTranscation);
|
||||||
|
|
||||||
|
|
||||||
// Extract titles from apiTransaction
|
// Extract titles from apiTransaction
|
||||||
const apiTransactionTitles = IODetails?.mainTranscation?.map(transaction => transaction.id);
|
const apiTransactionTitles = IODetails?.mainTranscation?.map(
|
||||||
|
(transaction) => transaction.id
|
||||||
|
);
|
||||||
// Filter menu items
|
// Filter menu items
|
||||||
const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id));
|
const filteredMenu = menu?.filter((item) =>
|
||||||
|
apiTransactionTitles?.includes(item.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const balanceAmount = IODetails?.goalAmount - IODetails?.totalAmtInvestmentInUSD
|
||||||
|
|
||||||
|
return IODetails?.investmentNameEnglish ? (
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
IODetails?.investmentNameEnglish ?
|
|
||||||
<Box
|
<Box
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
alignItems={"center"}
|
alignItems={"center"}
|
||||||
@@ -183,9 +181,9 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
: IODetails?.ioStatus?.statusAdmin === "Closed"
|
: IODetails?.ioStatus?.statusAdmin === "Closed"
|
||||||
? "#C6F6D5"
|
? "#C6F6D5"
|
||||||
: IODetails?.ioStatus?.statusAdmin === "Exited"
|
: IODetails?.ioStatus?.statusAdmin === "Exited"
|
||||||
? "red.500"
|
? "#FED7D7"
|
||||||
: IODetails?.ioStatus?.statusAdmin === "Canclled"
|
: IODetails?.ioStatus?.statusAdmin === "Cancelled"
|
||||||
? "orange.500"
|
? "#E9D8FD"
|
||||||
: IODetails?.ioStatus?.statusAdmin === "DeActivate"
|
: IODetails?.ioStatus?.statusAdmin === "DeActivate"
|
||||||
? "#E9D8FD"
|
? "#E9D8FD"
|
||||||
: null
|
: null
|
||||||
@@ -200,10 +198,7 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
boxShadow={"md"}
|
boxShadow={"md"}
|
||||||
position={"relative"}
|
position={"relative"}
|
||||||
>
|
>
|
||||||
|
<HStack gap={4}>
|
||||||
|
|
||||||
|
|
||||||
<HStack gap={8}>
|
|
||||||
<Box h={100} w={200} p={1.5}>
|
<Box h={100} w={200} p={1.5}>
|
||||||
{/* <Image rounded={'md'} h={"100%"} src={ " https://tanami.betadelivery.com/" + IODetails?.ioName} alt={IODetails?.ioName}/> */}
|
{/* <Image rounded={'md'} h={"100%"} src={ " https://tanami.betadelivery.com/" + IODetails?.ioName} alt={IODetails?.ioName}/> */}
|
||||||
{IODetails?.artifactsImage?.[0]?.artifactPathName ? (
|
{IODetails?.artifactsImage?.[0]?.artifactPathName ? (
|
||||||
@@ -233,44 +228,136 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display={"flex"} w={"auto"} flexDirection={"column"} gap={2}>
|
<Box>
|
||||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
|
||||||
IO Name
|
<Box display={"flex"} gap={2} pb={1}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
me={2}
|
||||||
|
>
|
||||||
|
IO Name :-
|
||||||
</Text>
|
</Text>
|
||||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
{IODetails?.investmentNameEnglish
|
{IODetails?.investmentNameEnglish
|
||||||
? IODetails?.investmentNameEnglish
|
? IODetails?.investmentNameEnglish
|
||||||
: "---"}
|
: "---"}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
<Box display={"flex"} gap={2} pb={1}>
|
||||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
<Text
|
||||||
Sponsor Name
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
me={2}
|
||||||
|
>
|
||||||
|
Sponsor Name :-
|
||||||
</Text>
|
</Text>
|
||||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
{IODetails?.sponsor?.sponsorName
|
{IODetails?.sponsor?.sponsorName
|
||||||
? IODetails?.sponsor?.sponsorName
|
? IODetails?.sponsor?.sponsorName
|
||||||
: "---"}
|
: "---"}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Box display={"flex"} gap={2} pb={1}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
me={2}
|
||||||
|
>
|
||||||
|
IO ID :-
|
||||||
|
</Text>
|
||||||
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
|
{IODetails?.io_id
|
||||||
|
? IODetails?.io_id
|
||||||
|
: "---"}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
|
<Box gap={8} me={12} w={"220px"}>
|
||||||
|
|
||||||
<HStack gap={8} me={20}>
|
<Box display={"flex"} justifyContent={"space-between"} gap={2} pb={1}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
>
|
||||||
|
Goal Amount :-
|
||||||
|
</Text>
|
||||||
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
|
{/* {IODetails?.ioNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioNAV)) : "00.00"} */}
|
||||||
|
{parseFloat(IODetails?.goalAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
<Box display={"flex"} justifyContent={"space-between"} gap={2} pb={1}>
|
||||||
<Text as={"span"} textAlign={'center'} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
<Text
|
||||||
IO Status
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
>
|
||||||
|
Amount Raised :-
|
||||||
|
</Text>
|
||||||
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
|
{/* {IODetails?.ioCash ? formatCurrency(removeTrailingZeros(IODetails?.ioCash)) : "00.00"} */}
|
||||||
|
{parseFloat(IODetails?.totalAmtInvestmentInUSD || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box display={"flex"} justifyContent={"space-between"} gap={2}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
>
|
||||||
|
Balance :-
|
||||||
|
</Text>
|
||||||
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
|
{/* {IODetails?.ioMVNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioMVNAV)) : "00.00"} */}
|
||||||
|
{parseFloat(balanceAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box gap={8} me={12} w={"180px"}>
|
||||||
|
<Box display={"flex"} justifyContent={"space-between"} gap={2} pb={1}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
textAlign={"center"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
>
|
||||||
|
IO Status :-
|
||||||
</Text>
|
</Text>
|
||||||
<Badge
|
<Badge
|
||||||
rounded={"full"}
|
rounded={"full"}
|
||||||
pt={0}
|
pt={0}
|
||||||
pb={0.5}
|
pb={0.5}
|
||||||
ps={4}
|
|
||||||
pe={4}
|
|
||||||
textTransform={"none"}
|
textTransform={"none"}
|
||||||
|
|
||||||
// variant={"solid"}
|
// variant={"solid"}
|
||||||
colorScheme={
|
colorScheme={
|
||||||
IODetails?.ioStatus?.statusAdmin === "Draft"
|
IODetails?.ioStatus?.statusAdmin === "Draft"
|
||||||
@@ -283,8 +370,8 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
? "green"
|
? "green"
|
||||||
: IODetails?.ioStatus?.statusAdmin === "Exited"
|
: IODetails?.ioStatus?.statusAdmin === "Exited"
|
||||||
? "red"
|
? "red"
|
||||||
: IODetails?.ioStatus?.statusAdmin === "Canclled"
|
: IODetails?.ioStatus?.statusAdmin === "Cancelled"
|
||||||
? "orange"
|
? "purple"
|
||||||
: "purple"
|
: "purple"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -294,37 +381,60 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
</Badge>
|
</Badge>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
<Box display={"flex"} justifyContent={"space-between"} gap={2} pb={1}>
|
||||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
<Text
|
||||||
IO MV
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
>
|
||||||
|
IO MV :-
|
||||||
</Text>
|
</Text>
|
||||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
{/* {IODetails?.ioNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioNAV)) : "00.00"} */}
|
{/* {IODetails?.ioNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioNAV)) : "00.00"} */}
|
||||||
{parseFloat(IODetails?.ioNAV||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
{parseFloat(IODetails?.ioNAV || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
<Box display={"flex"} justifyContent={"space-between"} gap={2} pb={1}>
|
||||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
<Text
|
||||||
IO cash
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
>
|
||||||
|
IO cash :-
|
||||||
</Text>
|
</Text>
|
||||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
{/* {IODetails?.ioCash ? formatCurrency(removeTrailingZeros(IODetails?.ioCash)) : "00.00"} */}
|
{/* {IODetails?.ioCash ? formatCurrency(removeTrailingZeros(IODetails?.ioCash)) : "00.00"} */}
|
||||||
{parseFloat(IODetails?.ioCash||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
{parseFloat(IODetails?.ioCash || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
<Box display={"flex"} justifyContent={"space-between"} gap={2}>
|
||||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
<Text
|
||||||
IO NAV
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
>
|
||||||
|
IO NAV :-
|
||||||
</Text>
|
</Text>
|
||||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||||
{/* {IODetails?.ioMVNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioMVNAV)) : "00.00"} */}
|
{/* {IODetails?.ioMVNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioMVNAV)) : "00.00"} */}
|
||||||
{parseFloat(IODetails?.ioMVNAV||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
{parseFloat(IODetails?.ioMVNAV || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Box>
|
||||||
</HStack>
|
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
position={"absolute"}
|
position={"absolute"}
|
||||||
@@ -356,16 +466,18 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
Tansaction
|
Tansaction
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
{filteredMenu?.map(({id, title, onClickFunction})=><MenuItem key={id} onClick={onClickFunction} className="border-bottom">
|
{filteredMenu?.map(({ id, title, onClickFunction }) => (
|
||||||
|
<MenuItem
|
||||||
|
key={id}
|
||||||
|
onClick={onClickFunction}
|
||||||
|
className="border-bottom"
|
||||||
|
>
|
||||||
{title}
|
{title}
|
||||||
</MenuItem>)}
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
|
||||||
</MenuList>
|
</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* Modals */}
|
{/* Modals */}
|
||||||
<AmountInvested isOpen={isInvestmentOpen} onClose={onInvestmentClose} />
|
<AmountInvested isOpen={isInvestmentOpen} onClose={onInvestmentClose} />
|
||||||
<FeesExpenses isOpen={isFeesOpen} onClose={onFeesClose} />
|
<FeesExpenses isOpen={isFeesOpen} onClose={onFeesClose} />
|
||||||
@@ -379,6 +491,7 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
isOpen={isDistInvestorOpen}
|
isOpen={isDistInvestorOpen}
|
||||||
onClose={onDistInvestorClose}
|
onClose={onDistInvestorClose}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UpdateIONav isOpen={isUpdateNavOpen} onClose={onUpdateNavClose} />
|
<UpdateIONav isOpen={isUpdateNavOpen} onClose={onUpdateNavClose} />
|
||||||
<UpdateIOStatus
|
<UpdateIOStatus
|
||||||
status={IODetails?.nextStatus}
|
status={IODetails?.nextStatus}
|
||||||
@@ -386,9 +499,8 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
onClose={onUpdateStatusClose}
|
onClose={onUpdateStatusClose}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Box>
|
||||||
</Box>:
|
) : (
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
alignItems={"center"}
|
alignItems={"center"}
|
||||||
@@ -403,7 +515,10 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
|
|||||||
// bgGradient='linear(to-r, #ffd54f, #caf5d8)'
|
// bgGradient='linear(to-r, #ffd54f, #caf5d8)'
|
||||||
// bgGradient='linear(to-r, #caf5d8, #a8e6cf)'
|
// bgGradient='linear(to-r, #caf5d8, #a8e6cf)'
|
||||||
boxShadow={"md"}
|
boxShadow={"md"}
|
||||||
> <Loader01 /></Box>
|
>
|
||||||
|
{" "}
|
||||||
|
<Loader01 />
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ const ViewIOdetails = () => {
|
|||||||
descriptionArabic: IObyID?.data?.descriptionArabic,
|
descriptionArabic: IObyID?.data?.descriptionArabic,
|
||||||
goalAmount: removeTrailingZeros(IObyID?.data?.goalAmount),
|
goalAmount: removeTrailingZeros(IObyID?.data?.goalAmount),
|
||||||
closingDate: IObyID?.data?.closingDate,
|
closingDate: IObyID?.data?.closingDate,
|
||||||
holdingPeriod: IObyID?.data?.holdingPeriod,
|
holdingPeriod: IObyID?.dpata?.holdingPeriod,
|
||||||
ISIN: IObyID?.data?.ISIN,
|
ISIN: IObyID?.data?.ISIN,
|
||||||
comment: IObyID?.data?.comment,
|
comment: IObyID?.data?.comment,
|
||||||
expectedReturn: IObyID?.data?.expectedReturn,
|
expectedReturn: IObyID?.data?.expectedReturn,
|
||||||
@@ -203,9 +203,6 @@ const ViewIOdetails = () => {
|
|||||||
section: " ",
|
section: " ",
|
||||||
width: "49%",
|
width: "49%",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
label: "Expected Return",
|
label: "Expected Return",
|
||||||
placeHolder: "$00.00",
|
placeHolder: "$00.00",
|
||||||
@@ -216,7 +213,7 @@ const ViewIOdetails = () => {
|
|||||||
? IObyID?.data?.expectedReturn
|
? IObyID?.data?.expectedReturn
|
||||||
: "---",
|
: "---",
|
||||||
section: " ",
|
section: " ",
|
||||||
width: "49%",
|
width: "32.3%",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -230,10 +227,22 @@ const ViewIOdetails = () => {
|
|||||||
? IObyID?.data?.expectedReturnArabic
|
? IObyID?.data?.expectedReturnArabic
|
||||||
: "---",
|
: "---",
|
||||||
section: " ",
|
section: " ",
|
||||||
width: "49%",
|
width: "32.3%",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "Shariah",
|
||||||
|
name: "isShariah",
|
||||||
|
type: "checkBox",
|
||||||
|
// isRequired: true,
|
||||||
|
section: " ",
|
||||||
|
width: "32.3%",
|
||||||
|
value: IObyID?.data?.isShariah,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -354,8 +363,8 @@ const ViewIOdetails = () => {
|
|||||||
size={"xs"}
|
size={"xs"}
|
||||||
>
|
>
|
||||||
Edit IO
|
Edit IO
|
||||||
</Button>{" "}
|
</Button>
|
||||||
<FormInputView groupedFields={groupedFields} />{" "}
|
<FormInputView groupedFields={groupedFields} />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
245
src/Pages/Investor_Management/InvestorDetails/BankDetails.jsx
Normal file
245
src/Pages/Investor_Management/InvestorDetails/BankDetails.jsx
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
|
import {
|
||||||
|
Link,
|
||||||
|
Link as RouterLink,
|
||||||
|
useNavigate,
|
||||||
|
useParams,
|
||||||
|
} from "react-router-dom";
|
||||||
|
import { AddIcon, DeleteIcon, EditIcon, ViewIcon } from "@chakra-ui/icons";
|
||||||
|
import Pagination from "../../../Components/Pagination";
|
||||||
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
|
import {
|
||||||
|
useDeleteInvestmentTypeMutation,
|
||||||
|
useGetInvestmentTypesQuery,
|
||||||
|
} from "../../../Services/io.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
import { useGetInvestorsDetailsByIdQuery } from "../../../Services/investor.details.service";
|
||||||
|
|
||||||
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
|
const BankDetails = () => {
|
||||||
|
const params = useParams();
|
||||||
|
const id = params?.id;
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
|
// ======================== [Use State] =========================
|
||||||
|
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
// const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const { investmentType, setInvestmentType, slideFromRight } =
|
||||||
|
useContext(GlobalStateContext);
|
||||||
|
|
||||||
|
const [deleteInvestmentType] = useDeleteInvestmentTypeMutation();
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
|
||||||
|
// const {
|
||||||
|
// data: investmentTypes,
|
||||||
|
// isLoading: investmentTypesLoading,
|
||||||
|
// error,
|
||||||
|
// } = useGetInvestmentTypesQuery({ page: currentPage, size: pageSize });
|
||||||
|
const { data, isLoading:bankDetailsLoading, errors, refetch } = useGetInvestorsDetailsByIdQuery(
|
||||||
|
id,
|
||||||
|
{
|
||||||
|
skip: !id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(data?.data?.bank_details);
|
||||||
|
|
||||||
|
const filteredData = data?.data?.bank_details?.filter((item) => {
|
||||||
|
const name = item.bankNickName;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ==================================================== [Table Setup] ================================================================
|
||||||
|
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr No",
|
||||||
|
"Bank Nick Name",
|
||||||
|
"IBAN",
|
||||||
|
"Account No",
|
||||||
|
"Bank Name",
|
||||||
|
"Account Name",
|
||||||
|
"Bank Address",
|
||||||
|
"SWIFT Code",
|
||||||
|
];
|
||||||
|
|
||||||
|
const extractedArray = filteredData?.map((item, idx) => ({
|
||||||
|
"Sr No": (
|
||||||
|
<Text
|
||||||
|
w={"24px"}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{/* {item.id} */}
|
||||||
|
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Bank Nick Name": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
isTruncated={true}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.bankNickName}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
IBAN: (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
isTruncated={true}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.IBANnumber}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Account No": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
isTruncated={true}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.accountNumber}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Bank Name": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
isTruncated={true}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.bankName}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Account Name": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
isTruncated={true}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.accountName}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"Bank Address": (
|
||||||
|
<Text
|
||||||
|
w={"200px"} // Set a width to constrain the text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
whiteSpace={"normal"} // Allow wrapping
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.bankAddress}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
"SWIFT Code": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
isTruncated={true}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.swiftCode}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// ==================== [Delete Function] =======================
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
console.log(actionId);
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await deleteInvestmentType(actionId);
|
||||||
|
console.log(response);
|
||||||
|
setIsLoading(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
|
<HStack>
|
||||||
|
<Text as={'span'} fontSize={'sm'} fontWeight={700}>Bank Deatils</Text>
|
||||||
|
</HStack>
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
{/* ======================= [Search Input] ======================== */}
|
||||||
|
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
{/* ======================== [Data Table] ======================= */}
|
||||||
|
|
||||||
|
<NormalTable
|
||||||
|
emptyMessage={`We don't have any Investment type `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
isLoading={bankDetailsLoading}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BankDetails;
|
||||||
@@ -5,11 +5,6 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
HStack,
|
HStack,
|
||||||
Input,
|
Input,
|
||||||
Menu,
|
|
||||||
MenuButton,
|
|
||||||
MenuItem,
|
|
||||||
MenuList,
|
|
||||||
Portal,
|
|
||||||
Select,
|
Select,
|
||||||
Switch,
|
Switch,
|
||||||
Tag,
|
Tag,
|
||||||
@@ -21,13 +16,8 @@ import {
|
|||||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import NormalTable from "../../../Components/DataTable/NormalTable";
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
import { HiDotsVertical } from "react-icons/hi";
|
|
||||||
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
AddIcon,
|
|
||||||
DeleteIcon,
|
|
||||||
EditIcon,
|
|
||||||
EmailIcon,
|
|
||||||
ViewIcon,
|
ViewIcon,
|
||||||
} from "@chakra-ui/icons";
|
} from "@chakra-ui/icons";
|
||||||
import Pagination from "../../../Components/Pagination";
|
import Pagination from "../../../Components/Pagination";
|
||||||
@@ -38,6 +28,8 @@ import { debounce } from "../../Master/Sponser/AddSponser";
|
|||||||
import InvestmentDetailsEdit from "./InvestmentDetailsEdit";
|
import InvestmentDetailsEdit from "./InvestmentDetailsEdit";
|
||||||
import { useGetInvestorsQuery } from "../../../Services/investor.details.service";
|
import { useGetInvestorsQuery } from "../../../Services/investor.details.service";
|
||||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import { exportToExcel, exportToExcelNew, generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
@@ -47,7 +39,6 @@ const InvestorDetails = () => {
|
|||||||
const thirdField = useRef();
|
const thirdField = useRef();
|
||||||
const { InvestorDetails, setInvestorDetails, slideFromRight } =
|
const { InvestorDetails, setInvestorDetails, slideFromRight } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
@@ -60,13 +51,43 @@ const InvestorDetails = () => {
|
|||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
const btnRef = React.useRef();
|
const btnRef = React.useRef();
|
||||||
|
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const [status, setStatus] = useState("");
|
||||||
|
const [kyc, setKyc] = useState("");
|
||||||
|
const [country, setCountry] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
const {
|
const {
|
||||||
data: investorDetails,
|
data: investorDetails,
|
||||||
isLoading: investorDetailsLoading,
|
isLoading: investorDetailsLoading,
|
||||||
error,
|
error,
|
||||||
} = useGetInvestorsQuery({ page: currentPage, size: pageSize });
|
} = useGetInvestorsQuery({
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search userStatus KYCStatus investorType_xid
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
userStatus: status,
|
||||||
|
KYCStatus: kyc,
|
||||||
|
country_xid: country
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -81,60 +102,48 @@ const InvestorDetails = () => {
|
|||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
// "Sr N/O",
|
"Sr No",
|
||||||
|
|
||||||
"Client ID",
|
"Client ID",
|
||||||
"First Name",
|
"First Name",
|
||||||
"Last Name",
|
"Last Name",
|
||||||
"Country",
|
"Country",
|
||||||
"Phone Number",
|
"Phone Number",
|
||||||
"E-mail ID",
|
"E-mail ID",
|
||||||
"Investor Type",
|
"Type",
|
||||||
"KYC Status",
|
"KYC Status",
|
||||||
"Status",
|
"Status",
|
||||||
"Action",
|
"Action",
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleUpdateStatus = debounce((id) => {
|
|
||||||
setInvestorDetails((prevData) =>
|
|
||||||
prevData.map((InvestorDetails) =>
|
|
||||||
InvestorDetails.id === id ? { ...InvestorDetails } : InvestorDetails
|
|
||||||
)
|
|
||||||
);
|
|
||||||
toast({
|
|
||||||
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
|
||||||
});
|
|
||||||
}, 300);
|
|
||||||
|
|
||||||
// ====================================================[Table Filter]================================================================
|
// ====================================================[Table Filter]================================================================
|
||||||
const filteredData = investorDetails?.data?.rows?.filter((item) => {
|
const exportInvestor = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||||
// Filter by name (case insensitive)
|
"Id": parseInt(item?.id, 10) || item?.id, // Convert to integer, fallback to string if conversion fails
|
||||||
const name = [item?.principal?.firstName, item?.principal?.lastName, item?.country?.countryName, item?.principal?.mobileNumber, item?.principal?.emailAddress].filter(Boolean).join(' ');
|
"Client ID": item?.clientReference_id, // This is likely a string
|
||||||
const searchLower = searchTerm.toLowerCase();
|
"First Name": item?.principal?.firstName,
|
||||||
const nameMatches = name?.toLowerCase().includes(searchLower);
|
"Last Name": item?.principal?.lastName,
|
||||||
|
"Country": item?.country?.countryName,
|
||||||
|
"Phone Number": item?.principal?.mobileNumber, // Skipping integer conversion, as this is likely a string
|
||||||
|
"E-mail ID": item?.principal?.emailAddress,
|
||||||
|
"Type": item?.investor_type?.investorTypeName,
|
||||||
|
"Status": item.ioStatus ? "Ban" : "Unban",
|
||||||
|
"KYC Status": item.KYCStatus ? "Completed" : "Not complete"
|
||||||
|
}));
|
||||||
|
|
||||||
// Filter by status
|
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||||
// const status = item.status;
|
|
||||||
// const statusLower = status ? "active" : "inactive";
|
|
||||||
|
|
||||||
// const statusMatches =
|
|
||||||
// statusFilter === "all" ||
|
|
||||||
// (statusFilter === "active" && status === true) ||
|
|
||||||
// (statusFilter === "inactive" && status === false);
|
|
||||||
|
|
||||||
return nameMatches;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item) => ({
|
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr N/O": (
|
"Sr No": (
|
||||||
<Text
|
<Text
|
||||||
|
w={'24px'}
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
className="d-flex align-items-center fw-bold web-text-small"
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
>
|
>
|
||||||
{item.id}
|
{/* {item.id} */}
|
||||||
|
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||||
|
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Client ID": (
|
"Client ID": (
|
||||||
@@ -152,7 +161,7 @@ const InvestorDetails = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Last Name": (
|
"Last Name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"70px"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item?.principal?.lastName}
|
{item?.principal?.lastName}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -179,10 +188,10 @@ const InvestorDetails = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Investor Type": (
|
"Type": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"purple"}>
|
<Text as={"span"} >
|
||||||
<Badge colorScheme="purple" variant={'solid'} fontWeight={"500"} px={2} py={0.5}>
|
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}>
|
||||||
{item?.investor_type?.investorTypeName}
|
{item?.investor_type?.investorTypeName}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Text>
|
</Text>
|
||||||
@@ -191,29 +200,31 @@ const InvestorDetails = () => {
|
|||||||
Status: (
|
Status: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Badge
|
<Badge
|
||||||
fontWeight={"500"}
|
fontWeight={"700"}
|
||||||
// textTransform={"none"}
|
textTransform={"none"}
|
||||||
colorScheme={item.ioStatus ? "red" : "green"}
|
colorScheme={item.ioStatus ? "red" : "green"}
|
||||||
px={2}
|
px={2}
|
||||||
py={0.5}
|
py={0.5}
|
||||||
variant={'solid'}
|
|
||||||
>
|
>
|
||||||
{item.ioStatus ? "Ban" : "Unban"}
|
{item.ioStatus ? "Ban" : "Unban"}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"KYC Status": (
|
"KYC Status": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} display={'flex'} alignItems={'center'} isTruncated={true}>
|
||||||
<Badge
|
<Text
|
||||||
fontWeight={"500"}
|
as={'span'}
|
||||||
// textTransform={"none"}
|
fontWeight={"700"}
|
||||||
colorScheme={item.kycStatus ? "blue" : "red"}
|
textTransform={"none"}
|
||||||
|
color={item?.KYCStatus === true ? "green" : "yellow.500"}
|
||||||
px={2}
|
px={2}
|
||||||
py={0.5}
|
py={0.5}
|
||||||
variant={'solid'}
|
variant={'solid'}
|
||||||
|
|
||||||
>
|
>
|
||||||
{item.KYCStatus ? "Completed" : "Not complete"}
|
{/* {item.KYCStatus ? "Completed" : "Not complete"} */}
|
||||||
</Badge>
|
{item?.KYCStatus === true ? "Completed" : "NotCompleted"}
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Action: (
|
Action: (
|
||||||
@@ -227,6 +238,7 @@ const InvestorDetails = () => {
|
|||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
|
isDisabled={item.ioStatus}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(`/investor-details/profile-view/${item.id}`);
|
navigate(`/investor-details/profile-view/${item.id}`);
|
||||||
}}
|
}}
|
||||||
@@ -257,13 +269,6 @@ const InvestorDetails = () => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = (id) => {
|
|
||||||
setActionId(id);
|
|
||||||
onEditOpen();
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(investorDetails?.data?.totalItems);
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
@@ -295,14 +300,16 @@ const InvestorDetails = () => {
|
|||||||
size={"sm"}
|
size={"sm"}
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
cursor={"pointer"}
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setStatus(e.target.value)}
|
||||||
|
value={status}
|
||||||
>
|
>
|
||||||
<option value="" defaultValue={"all"} disabled hidden>
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
Status
|
Status
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option value="all">All</option>
|
<option value="">Status</option>
|
||||||
<option value="ban">Ban</option>
|
<option value="0">Ban</option>
|
||||||
<option value="unban">UnBan</option>
|
<option value="1">UnBan</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
@@ -310,43 +317,15 @@ const InvestorDetails = () => {
|
|||||||
size={"sm"}
|
size={"sm"}
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
cursor={"pointer"}
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setKyc(e.target.value)}
|
||||||
|
value={kyc}
|
||||||
>
|
>
|
||||||
<option value="" defaultValue={"all"} disabled hidden>
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
Status
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option value="all">All</option>
|
|
||||||
<option value="ban">Ban</option>
|
|
||||||
<option value="unban">UnBan</option>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
focusBorderColor="green.500"
|
|
||||||
size={"sm"}
|
|
||||||
fontSize={"xs"}
|
|
||||||
cursor={"pointer"}
|
|
||||||
>
|
|
||||||
<option value="" defaultValue={"all"} disabled hidden>
|
|
||||||
Status
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option value="all">All</option>
|
|
||||||
<option value="ban">Ban</option>
|
|
||||||
<option value="unban">UnBan</option>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
focusBorderColor="green.500"
|
|
||||||
size={"sm"}
|
|
||||||
fontSize={"xs"}
|
|
||||||
cursor={"pointer"}
|
|
||||||
>
|
|
||||||
<option value="" defaultValue={"all"} disabled hidden>
|
|
||||||
KYC Status
|
KYC Status
|
||||||
</option>
|
</option>
|
||||||
<option value="all">All</option>
|
<option value="">KYC Status</option>
|
||||||
<option value="completed">Completed</option>
|
<option value="0">Incompleted</option>
|
||||||
<option value="incompleted">Incompleted</option>
|
<option value="1">Completed</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
@@ -354,15 +333,19 @@ const InvestorDetails = () => {
|
|||||||
size={"sm"}
|
size={"sm"}
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
cursor={"pointer"}
|
cursor={"pointer"}
|
||||||
|
onChange={(e) => setCountry(e.target.value)}
|
||||||
|
value={country}
|
||||||
>
|
>
|
||||||
<option value="" defaultValue={"all"} disabled hidden>
|
<option value="" defaultValue={""} disabled hidden>
|
||||||
Country
|
Country
|
||||||
</option>
|
</option>
|
||||||
<option value="behrain">Behrain</option>
|
<option value="">All</option>
|
||||||
<option value="kuwait">Kuwait</option>
|
<option value="1">Behrain</option>
|
||||||
<option value="oman">Oman</option>
|
<option value="2">Kuwait</option>
|
||||||
<option value="saudi arabia">Saudi arabia</option>
|
<option value="3">Oman</option>
|
||||||
<option value="united arab emirates">United arab emirates</option>
|
<option value="4">Qatar</option>
|
||||||
|
<option value="5">Saudi arabia</option>
|
||||||
|
<option value="6">United arab emirates</option>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<Pagination
|
<Pagination
|
||||||
@@ -374,7 +357,27 @@ const InvestorDetails = () => {
|
|||||||
totalItems={investorDetails?.data?.totalItems}
|
totalItems={investorDetails?.data?.totalItems}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
exportToExcelNew(exportInvestor, "Investor Details")
|
||||||
|
}
|
||||||
|
leftIcon={<LuFileSpreadsheet />}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
size={"sm"}
|
||||||
|
variant={"outline"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
w={100}
|
||||||
|
me={2}
|
||||||
|
|
||||||
|
isDisabled={exportInvestor?.length === 0}
|
||||||
|
>
|
||||||
|
Export xls
|
||||||
|
</Button>
|
||||||
</HStack>
|
</HStack>
|
||||||
<InvestmentDetailsEdit
|
<InvestmentDetailsEdit
|
||||||
id={actionId}
|
id={actionId}
|
||||||
|
|||||||
216
src/Pages/Investor_Management/InvestorDetails/Kyc.jsx
Normal file
216
src/Pages/Investor_Management/InvestorDetails/Kyc.jsx
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Checkbox,
|
||||||
|
CheckboxGroup,
|
||||||
|
Divider,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Heading,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
Select,
|
||||||
|
Stack,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { useGetInvestorsDetailsByIdQuery } from "../../../Services/investor.details.service";
|
||||||
|
|
||||||
|
const Kyc = () => {
|
||||||
|
const params = useParams();
|
||||||
|
const id = params?.id;
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: bankDetailsLoading,
|
||||||
|
errors,
|
||||||
|
refetch,
|
||||||
|
} = useGetInvestorsDetailsByIdQuery(id, { skip: !id });
|
||||||
|
// const [value, setValue] = useState('2')
|
||||||
|
|
||||||
|
console.log(data?.data?.KYC?.questions);
|
||||||
|
|
||||||
|
return (
|
||||||
|
!bankDetailsLoading && (
|
||||||
|
<Box>
|
||||||
|
<Box mb={5}>
|
||||||
|
{/*<Heading fontSize={"md"} fontWeight={500}>
|
||||||
|
Additional Questions
|
||||||
|
</Heading>
|
||||||
|
<Text fontSize={"sm"}>
|
||||||
|
Please provide additional Information to complete your profile.
|
||||||
|
</Text> */}
|
||||||
|
<Heading fontSize={"md"} fontWeight={500}>
|
||||||
|
Address
|
||||||
|
</Heading>
|
||||||
|
<Divider />
|
||||||
|
<HStack spacing={4} mb={4}>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>
|
||||||
|
House/Unit
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#ccc3"}
|
||||||
|
border={"none"}
|
||||||
|
size={"sm"}
|
||||||
|
value={data?.data?.KYC?.otherInformation?.houseOrUnit}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>
|
||||||
|
Road/Street
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#ccc3"}
|
||||||
|
border={"none"}
|
||||||
|
size={"sm"}
|
||||||
|
value={data?.data?.KYC?.otherInformation?.roadOrStreet}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</HStack>
|
||||||
|
<HStack spacing={4} mb={5}>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>
|
||||||
|
Block
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#ccc3"}
|
||||||
|
border={"none"}
|
||||||
|
size={"sm"}
|
||||||
|
value={data?.data?.KYC?.otherInformation?.block}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>
|
||||||
|
City
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#ccc3"}
|
||||||
|
border={"none"}
|
||||||
|
size={"sm"}
|
||||||
|
value={data?.data?.KYC?.otherInformation?.city}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</HStack>
|
||||||
|
<HStack spacing={4} mb={7}>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>
|
||||||
|
Country
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#ccc3"}
|
||||||
|
border={"none"}
|
||||||
|
size={"sm"}
|
||||||
|
value={data?.data?.KYC?.otherInformation?.country}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl></FormControl>
|
||||||
|
</HStack>
|
||||||
|
<Heading fontSize={"md"} fontWeight={500}>
|
||||||
|
Additional Questions
|
||||||
|
</Heading>
|
||||||
|
<Divider />
|
||||||
|
<HStack spacing={4} mb={4}>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>
|
||||||
|
Occupation
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#ccc3"}
|
||||||
|
border={"none"}
|
||||||
|
size={"sm"}
|
||||||
|
value={data?.data?.KYC?.otherInformation?.occupation}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>
|
||||||
|
Source of Funds
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
bg={"#ccc3"}
|
||||||
|
border={"none"}
|
||||||
|
size={"sm"}
|
||||||
|
value={data?.data?.KYC?.otherInformation?.sourceOfFund}
|
||||||
|
type="text"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</HStack>
|
||||||
|
{/* <HStack spacing={4}>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel mb={1} fontSize={"sm"}>Address</FormLabel>
|
||||||
|
<Textarea bg={"#ccc3"} border={"none"} size={"sm"} type="textarea" resize={"none"} value={data?.data?.KYC?.otherInformation?.address} readOnly />
|
||||||
|
</FormControl>
|
||||||
|
<FormControl></FormControl>
|
||||||
|
</HStack> */}
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Heading fontSize={"md"} fontWeight={500}>
|
||||||
|
Investor Eligibilty Notice
|
||||||
|
</Heading>
|
||||||
|
<Text fontSize={"sm"}>
|
||||||
|
Please note that Tanami is currently only available to qualifield or
|
||||||
|
accredited investors. Please confirm your status
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<RadioGroup>
|
||||||
|
{data?.data?.KYC?.questions.map((question, index) => (
|
||||||
|
<>
|
||||||
|
<Radio
|
||||||
|
isChecked={question?.answers}
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<Text fontSize={"sm"} mb={0}>
|
||||||
|
{question?.question_text}
|
||||||
|
</Text>
|
||||||
|
</Radio>
|
||||||
|
<CheckboxGroup colorScheme="forestGreen">
|
||||||
|
<Stack ml={8}>
|
||||||
|
{question?.subQuestions?.map((subQuestion, index) => (
|
||||||
|
<Checkbox
|
||||||
|
isChecked={subQuestion.answers}
|
||||||
|
size="sm"
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<Text as="span">{subQuestion.question_text}</Text>
|
||||||
|
</Checkbox>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</CheckboxGroup>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
{/* {value === '2' && (
|
||||||
|
<CheckboxGroup colorScheme='forestGreen'>
|
||||||
|
<Stack ml={8}>
|
||||||
|
{data?.data?.KYC?.questions[1]?.subQuestions?.map((subQuestion, index) => (
|
||||||
|
<Checkbox isChecked={subQuestion.answers} size="sm" key={index}>
|
||||||
|
<Text as="span">{subQuestion.question_text}</Text>
|
||||||
|
</Checkbox>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</CheckboxGroup>
|
||||||
|
)} */}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Kyc;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Box,
|
Box,
|
||||||
|
Divider,
|
||||||
Icon,
|
Icon,
|
||||||
Tab,
|
Tab,
|
||||||
TabList,
|
TabList,
|
||||||
@@ -19,30 +20,47 @@ import FormInputView from "../../../Components/FormInputView";
|
|||||||
import ViewInvestorDetails from "./ViewInvestorDetails";
|
import ViewInvestorDetails from "./ViewInvestorDetails";
|
||||||
import { LuWallet } from "react-icons/lu";
|
import { LuWallet } from "react-icons/lu";
|
||||||
import Transaction from "./Transaction";
|
import Transaction from "./Transaction";
|
||||||
import FullscreenLoaders from '../../../Components/Loaders/FullscreenLoaders'
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
import { useGetInvestorsDetailsByIdQuery } from "../../../Services/investor.details.service";
|
import { useGetInvestorsDetailsByIdQuery } from "../../../Services/investor.details.service";
|
||||||
|
import BankDetails from "./BankDetails";
|
||||||
|
import Kyc from "./Kyc";
|
||||||
|
|
||||||
const ProfileView = () => {
|
const ProfileView = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const { InvestorDetails } = useContext(GlobalStateContext);
|
const {
|
||||||
|
InvestorDetails,
|
||||||
|
setViewInvestor,
|
||||||
|
setTransaction,
|
||||||
|
InvestorWallet,
|
||||||
|
setInvestorWallet,
|
||||||
|
} = useContext(GlobalStateContext);
|
||||||
const { reset } = useForm(); // assuming react-hook-form
|
const { reset } = useForm(); // assuming react-hook-form
|
||||||
|
|
||||||
const id = params?.id;
|
const id = params?.id;
|
||||||
|
|
||||||
const { data, isLoading, errors } = useGetInvestorsDetailsByIdQuery(id, {
|
const { data, isLoading, errors, refetch} = useGetInvestorsDetailsByIdQuery(id, {
|
||||||
skip: !id,
|
skip: !id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
const foundObject = data?.data;
|
const foundObject = data?.data;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setViewInvestor(data?.data?.portfolio);
|
||||||
|
setTransaction(data?.data?.transaction);
|
||||||
|
setInvestorWallet(data?.data.wallet);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
const formFields = [
|
const formFields = [
|
||||||
{
|
{
|
||||||
label: "Client ID",
|
label: "Client ID",
|
||||||
value: foundObject?.id,
|
value: foundObject?.clientReference_id,
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
@@ -50,7 +68,7 @@ const ProfileView = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "First Name",
|
label: "First Name",
|
||||||
value: foundObject?.principal?.firstName,
|
value: foundObject?.firstName,
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
@@ -59,7 +77,7 @@ const ProfileView = () => {
|
|||||||
|
|
||||||
{
|
{
|
||||||
label: "Last Name",
|
label: "Last Name",
|
||||||
value: foundObject?.principal?.lastName,
|
value: foundObject?.lastName,
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
@@ -67,7 +85,7 @@ const ProfileView = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "E-mail ID",
|
label: "E-mail ID",
|
||||||
value: foundObject?.principal?.emailAddress,
|
value: foundObject?.emailAddress,
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
@@ -75,7 +93,7 @@ const ProfileView = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Phone Number",
|
label: "Phone Number",
|
||||||
value: foundObject?.principal?.mobileNumber,
|
value: foundObject?.mobileNumber,
|
||||||
type: "tel",
|
type: "tel",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
@@ -83,7 +101,7 @@ const ProfileView = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Country",
|
label: "Country",
|
||||||
value: foundObject?.country?.countryName,
|
value: foundObject?.country ? foundObject?.country : "---",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
@@ -91,20 +109,20 @@ const ProfileView = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Investment type",
|
label: "Investment type",
|
||||||
value: foundObject?.investor_type?.investorTypeName,
|
value: foundObject?.investorTypeName,
|
||||||
type: "text",
|
|
||||||
isRequired: true,
|
|
||||||
section: "Personal Details",
|
|
||||||
width: "32%",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Investor limit",
|
|
||||||
value: foundObject?.investorLimit,
|
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
width: "32%",
|
width: "32%",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// label: "Investor limit",
|
||||||
|
// value: foundObject?.investorLimit,
|
||||||
|
// type: "text",
|
||||||
|
// isRequired: true,
|
||||||
|
// section: "Personal Details",
|
||||||
|
// width: "32%",
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
label: "KYC Status",
|
label: "KYC Status",
|
||||||
value: foundObject?.KYCStatus ? "Completed" : "Not complete",
|
value: foundObject?.KYCStatus ? "Completed" : "Not complete",
|
||||||
@@ -131,12 +149,60 @@ const ProfileView = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "App Notification",
|
label: "App Notification",
|
||||||
value: foundObject?.IsAppNotificationEnabled === 1 ? "Yes" : "No" ,
|
value: foundObject?.IsAppNotificationEnabled === true ? "Yes" : "No",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Personal Details",
|
section: "Personal Details",
|
||||||
width: "32%",
|
width: "32%",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// label: "Account Name",
|
||||||
|
// value: foundObject?.accountName,
|
||||||
|
// type: "text",
|
||||||
|
// isRequired: true,
|
||||||
|
// section: "Bank Details",
|
||||||
|
// width: "32%",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: "Account No",
|
||||||
|
// value: foundObject?.accountNumber,
|
||||||
|
// type: "text",
|
||||||
|
// isRequired: true,
|
||||||
|
// section: "Bank Details",
|
||||||
|
// width: "32%",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: "IBAN",
|
||||||
|
// value: foundObject?.IBANnumber,
|
||||||
|
// type: "text",
|
||||||
|
// isRequired: true,
|
||||||
|
// section: "Bank Details",
|
||||||
|
// width: "32%",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: "SWIFT Code",
|
||||||
|
// value: foundObject?.swiftCode,
|
||||||
|
// type: "text",
|
||||||
|
// isRequired: true,
|
||||||
|
// section: "Bank Details",
|
||||||
|
// width: "32%",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: "Bank Name",
|
||||||
|
// value: foundObject?.bankName,
|
||||||
|
// type: "text",
|
||||||
|
// isRequired: true,
|
||||||
|
// section: "Bank Details",
|
||||||
|
// width: "32%",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: "Bank Address",
|
||||||
|
// value: foundObject?.bankAddress,
|
||||||
|
// type: "text",
|
||||||
|
// isRequired: true,
|
||||||
|
// section: "Bank Details",
|
||||||
|
// width: "32%",
|
||||||
|
// },
|
||||||
];
|
];
|
||||||
|
|
||||||
const groupedFields = formFields.reduce((groups, field) => {
|
const groupedFields = formFields.reduce((groups, field) => {
|
||||||
@@ -148,8 +214,9 @@ const ProfileView = () => {
|
|||||||
return groups;
|
return groups;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return (
|
return isLoading ? (
|
||||||
isLoading? <FullscreenLoaders />:
|
<FullscreenLoaders />
|
||||||
|
) : (
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
||||||
<Box
|
<Box
|
||||||
pt={2}
|
pt={2}
|
||||||
@@ -190,10 +257,10 @@ const ProfileView = () => {
|
|||||||
display={"flex"}
|
display={"flex"}
|
||||||
>
|
>
|
||||||
<Text fontWeight={500} as={"span"}>
|
<Text fontWeight={500} as={"span"}>
|
||||||
26,763.40
|
{parseFloat(InvestorWallet?.WalletBalance_InUSD || 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
||||||
</Text>
|
</Text>
|
||||||
<Badge display={"flex"} alignItems={"center"}>
|
<Badge display={"flex"} alignItems={"center"}>
|
||||||
USD
|
{InvestorWallet?.currencyCode_USD}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -210,10 +277,10 @@ const ProfileView = () => {
|
|||||||
display={"flex"}
|
display={"flex"}
|
||||||
>
|
>
|
||||||
<Text fontWeight={500} as={"span"}>
|
<Text fontWeight={500} as={"span"}>
|
||||||
10,075.01
|
{parseFloat(InvestorWallet?.WalletBalance_InInvCur || 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
||||||
</Text>
|
</Text>
|
||||||
<Badge display={"flex"} alignItems={"center"}>
|
<Badge display={"flex"} alignItems={"center"}>
|
||||||
BHD
|
{InvestorWallet?.currencyCode_InCur}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -237,7 +304,7 @@ const ProfileView = () => {
|
|||||||
View Details
|
View Details
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
isDisabled={true}
|
// isDisabled={true}
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
_selected={{
|
_selected={{
|
||||||
color: "#004118",
|
color: "#004118",
|
||||||
@@ -247,7 +314,7 @@ const ProfileView = () => {
|
|||||||
Portfolio
|
Portfolio
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
isDisabled={true}
|
// isDisabled={true}
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
_selected={{
|
_selected={{
|
||||||
color: "#004118",
|
color: "#004118",
|
||||||
@@ -257,20 +324,22 @@ const ProfileView = () => {
|
|||||||
Transaction
|
Transaction
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
isDisabled={true}
|
// isDisabled={true}
|
||||||
fontSize={"sm"}
|
fontSize={"sm"}
|
||||||
_selected={{
|
_selected={{
|
||||||
color: "#004118",
|
color: "#004118",
|
||||||
borderBottom: "2px solid #38a169",
|
borderBottom: "2px solid #38a169",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
documents
|
KYC
|
||||||
</Tab>
|
</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
</Box>
|
</Box>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<FormInputView width={"32%"} groupedFields={groupedFields} />
|
<FormInputView width={"32%"} groupedFields={groupedFields} />
|
||||||
|
<Divider/>
|
||||||
|
<BankDetails />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<ViewInvestorDetails />
|
<ViewInvestorDetails />
|
||||||
@@ -278,6 +347,9 @@ const ProfileView = () => {
|
|||||||
<TabPanel>
|
<TabPanel>
|
||||||
<Transaction />
|
<Transaction />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
<TabPanel>
|
||||||
|
<Kyc />
|
||||||
|
</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -23,16 +23,7 @@ import {
|
|||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import DataTable from "../../../Components/DataTable/DataTable";
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
import { HiDotsVertical } from "react-icons/hi";
|
|
||||||
import { Link, Navigate, Link as RouterLink } from "react-router-dom";
|
|
||||||
import {
|
|
||||||
AddIcon,
|
|
||||||
DeleteIcon,
|
|
||||||
EditIcon,
|
|
||||||
EmailIcon,
|
|
||||||
ViewIcon,
|
|
||||||
} from "@chakra-ui/icons";
|
|
||||||
import Pagination from "../../../Components/Pagination";
|
import Pagination from "../../../Components/Pagination";
|
||||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
@@ -43,7 +34,7 @@ import {
|
|||||||
|
|
||||||
const Transaction = () => {
|
const Transaction = () => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { transaction, setTransaction, slideFromRight } =
|
const { transaction, setTransaction, slideFromRight, InvestorWallet } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@@ -62,36 +53,23 @@ import {
|
|||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
const formatDate = (date) => {
|
||||||
const tableHeadRow = [
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
"Sr N/O",
|
day: "2-digit",
|
||||||
"Date",
|
month: "2-digit",
|
||||||
"Transaction",
|
year: "numeric",
|
||||||
"Currency",
|
|
||||||
"Amount",
|
|
||||||
"From USD",
|
|
||||||
"TO USD",
|
|
||||||
"USD amount",
|
|
||||||
"IO Name",
|
|
||||||
"Payment Method",
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleUpdateStatus = debounce((id) => {
|
|
||||||
setViewInvestor((prevData) =>
|
|
||||||
prevData.map((transaction) =>
|
|
||||||
transaction.id === id ? { ...transaction } : transaction
|
|
||||||
)
|
|
||||||
);
|
|
||||||
toast({
|
|
||||||
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
|
||||||
});
|
});
|
||||||
}, 300);
|
};
|
||||||
|
|
||||||
|
console.log(transaction);
|
||||||
|
|
||||||
// ====================================================[Table Filter]================================================================
|
// ====================================================[Table Filter]================================================================
|
||||||
const filteredData = transaction?.filter((item) => {
|
const filteredData = transaction?.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = item.date;
|
console.log(item?.investorTransaction?.transactionName);
|
||||||
const searchLower = searchTerm.toLowerCase();
|
|
||||||
|
const name = item?.investorTransaction?.transactionName;
|
||||||
|
const searchLower = searchTerm?.toLowerCase();
|
||||||
const nameMatches = name?.toLowerCase().includes(searchLower);
|
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
// Filter by status
|
// Filter by status
|
||||||
@@ -106,10 +84,26 @@ import {
|
|||||||
return nameMatches;
|
return nameMatches;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(filteredData);
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
const tableHeadRow = [
|
||||||
|
// "Sr N/O",
|
||||||
|
"Date",
|
||||||
|
"Transaction",
|
||||||
|
"Amount",
|
||||||
|
// "Currency",
|
||||||
|
// "TO USD",
|
||||||
|
// "From USD",
|
||||||
|
// "USD amount",
|
||||||
|
"IO Name",
|
||||||
|
"Payment Method",
|
||||||
|
];
|
||||||
const extractedArray = filteredData?.map((item) => ({
|
const extractedArray = filteredData?.map((item) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr N/O": (
|
"Sr N/O": (
|
||||||
<Text w={'50px'}
|
<Text
|
||||||
|
w={"100px"}
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
@@ -118,71 +112,139 @@ import {
|
|||||||
{item.id}
|
{item.id}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Date": (
|
Date: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"80px"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.date}
|
{formatDate(item.transactionDate)}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Transaction": (
|
Transaction: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"80px"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.transaction}
|
{item.investorTransaction?.transactionName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Currency": (
|
Currency: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.currency}
|
{item.investorCurrency}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Amount": (
|
Amount: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={100} display={"flex"} justifyContent={"right"}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text
|
||||||
{item.amount}
|
as={"span"}
|
||||||
|
w={"100%"}
|
||||||
|
color={"teal.900"}
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"end"}
|
||||||
|
>
|
||||||
|
{/* <Badge ms={1} colorScheme="green" me={1}>$</Badge> */}
|
||||||
|
{parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
<Badge ms={1} colorScheme="green">
|
||||||
|
{item?.investorCurrency}
|
||||||
|
</Badge>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"From USD": (
|
"From USD": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.fromUSD}
|
{item.USDToInvCur_Rate}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
|
||||||
),
|
),
|
||||||
"TO USD": (
|
"TO USD": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.toUSD}
|
{item.invCurToUSD_Rate}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
|
||||||
),
|
|
||||||
"USD amount": (
|
|
||||||
<Box w={"auto"} isTruncated={true}>
|
|
||||||
<Text as={"span"} color={"teal.900"}>
|
|
||||||
{item.USDamount}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
),
|
),
|
||||||
|
// "USD amount": (
|
||||||
|
// <Box w={100} display={"flex"} justifyContent={"left"}>
|
||||||
|
// {item?.invCurToUSD_Rate === "0.0000" && (
|
||||||
|
// <Text as={"span"} w={"100%"} color={"teal.900"}>
|
||||||
|
// <Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
// $
|
||||||
|
// </Badge>
|
||||||
|
// {parseFloat(item?.USDAmount || 0).toLocaleString(undefined, {
|
||||||
|
// minimumFractionDigits: 2,
|
||||||
|
// maximumFractionDigits: 2,
|
||||||
|
// })}
|
||||||
|
// </Text>
|
||||||
|
// )}
|
||||||
|
// </Box>
|
||||||
|
// ),
|
||||||
"IO Name": (
|
"IO Name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.IOName}
|
{item.io && item.io?.investmentNameEnglish}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Payment Method": (
|
"Payment Method": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.paymentMethod}
|
{item.paymentMethod && item.paymentMethod?.paymentMethodName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const totalRow = {
|
||||||
|
// id: "total", // or any unique ID
|
||||||
|
// "Sr N/O": (
|
||||||
|
// <Text w={'100px'} color={"gray.600"} fontWeight={"bold"}>Total</Text>
|
||||||
|
// ),
|
||||||
|
Date: (
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
textAlign={"start"}
|
||||||
|
w={"100%"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"bold"}
|
||||||
|
>
|
||||||
|
<Badge ms={1} colorScheme="gray">
|
||||||
|
Total
|
||||||
|
</Badge>
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
Transaction: null,
|
||||||
|
// "Currency": null,
|
||||||
|
Amount: InvestorWallet?.currencyCode_InCur && (
|
||||||
|
<Box w={100} display={"flex"} justifyContent={"end"}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
textAlign={"right"}
|
||||||
|
w={"100%"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={600}
|
||||||
|
>
|
||||||
|
{/* <Badge ms={1} colorScheme="green" me={1}>$</Badge> */}
|
||||||
|
{parseFloat(
|
||||||
|
InvestorWallet?.WalletBalance_InInvCur || 0
|
||||||
|
).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
<Badge ms={1} colorScheme="green">
|
||||||
|
{InvestorWallet?.currencyCode_InCur}
|
||||||
|
</Badge>
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
// "TO USD": null,
|
||||||
|
// "From USD": null,
|
||||||
|
"USD amount": null,
|
||||||
|
"IO Name": null,
|
||||||
|
"Payment Method": null,
|
||||||
|
};
|
||||||
|
|
||||||
|
extractedArray?.push(totalRow);
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
const updatedInvestorDetails = InvestorDetails.filter(
|
const updatedInvestorDetails = InvestorDetails.filter(
|
||||||
(sponsor) => sponsor.id !== actionId
|
(sponsor) => sponsor.id !== actionId
|
||||||
@@ -196,129 +258,8 @@ import {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Total = () => {
|
|
||||||
return (
|
return (
|
||||||
<Table size="sm">
|
<Box {...OPACITY_ON_LOAD} height={"100vh"} pb={38}>
|
||||||
<Tbody backgroundColor="gray.50">
|
|
||||||
<Tr >
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="60px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
Balance:
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="60px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="60px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="60px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="80px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
10,075.01
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="60px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="60px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="80px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
26,763.40
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="120px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
</Th>
|
|
||||||
<Th
|
|
||||||
textAlign={"center"}
|
|
||||||
p={3}
|
|
||||||
width="120px"
|
|
||||||
color={"#004118"}
|
|
||||||
whiteSpace="normal"
|
|
||||||
wordBreak="normal"
|
|
||||||
overflowWrap="normal"
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
</Th>
|
|
||||||
</Tr>
|
|
||||||
</Tbody>
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
|
||||||
<Box bg="white.500">
|
<Box bg="white.500">
|
||||||
<HStack
|
<HStack
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
@@ -340,13 +281,13 @@ import {
|
|||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HStack display={"flex"} alignItems={"center"}>
|
{/* <HStack display={"flex"} alignItems={"center"}>
|
||||||
<Pagination totalItems={10} />
|
<Pagination totalItems={10} />
|
||||||
</HStack>
|
</HStack> */}
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<DataTable
|
<NormalTable
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
@@ -354,7 +295,6 @@ import {
|
|||||||
viewActionId={actionId}
|
viewActionId={actionId}
|
||||||
setViewActionId={setActionId}
|
setViewActionId={setActionId}
|
||||||
setMouseEnteredId={setMouseEnteredId}
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
caption={<Total />}
|
|
||||||
setMouseEntered={setMouseEntered}
|
setMouseEntered={setMouseEntered}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -365,10 +305,8 @@ import {
|
|||||||
alertHandler={handleDelete}
|
alertHandler={handleDelete}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Transaction;
|
export default Transaction;
|
||||||
|
|
||||||
@@ -19,9 +19,14 @@ import {
|
|||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import DataTable from "../../../Components/DataTable/DataTable";
|
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||||
import { HiDotsVertical } from "react-icons/hi";
|
import { HiDotsVertical } from "react-icons/hi";
|
||||||
import { Link, Navigate, Link as RouterLink } from "react-router-dom";
|
import {
|
||||||
|
Link,
|
||||||
|
Navigate,
|
||||||
|
Link as RouterLink,
|
||||||
|
useParams,
|
||||||
|
} from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
AddIcon,
|
AddIcon,
|
||||||
DeleteIcon,
|
DeleteIcon,
|
||||||
@@ -34,12 +39,13 @@ import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
|||||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import { debounce } from "../../Master/Sponser/AddSponser";
|
import { debounce } from "../../Master/Sponser/AddSponser";
|
||||||
|
import { useGetInvestorsDetailsById_InInvCurQuery } from "../../../Services/investor.details.service";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
const ViewInvestorDetails = () => {
|
const ViewInvestorDetails = () => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { viewInvestor, setViewInvestor, slideFromRight } =
|
const { viewInvestor, setViewInvestor, slideFromRight, InvestorWallet } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@@ -47,6 +53,16 @@ const ViewInvestorDetails = () => {
|
|||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
const [isSwitchOn, setIsSwitchOn] = useState(false);
|
||||||
|
const params = useParams();
|
||||||
|
const id = params?.id;
|
||||||
|
|
||||||
|
const { data, errors, refetch } = useGetInvestorsDetailsById_InInvCurQuery(
|
||||||
|
{ id, currencyIn: !isSwitchOn },
|
||||||
|
{
|
||||||
|
skip: !id,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Simulate loading
|
// Simulate loading
|
||||||
@@ -60,31 +76,27 @@ const ViewInvestorDetails = () => {
|
|||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
"Sr N/O",
|
// "Sr N/O",
|
||||||
"Deal Name",
|
// "Deal Name",
|
||||||
|
"IO Name",
|
||||||
"Sponsor Name",
|
"Sponsor Name",
|
||||||
|
"Investment Type",
|
||||||
"Investment Amount",
|
"Investment Amount",
|
||||||
"Holding Period",
|
"Percentage",
|
||||||
"Estimated return",
|
"Market Value",
|
||||||
|
"Return on Investment",
|
||||||
|
"Distribution",
|
||||||
|
"Distribution Percent",
|
||||||
|
"Total return",
|
||||||
|
"Total return on Investment",
|
||||||
"Status",
|
"Status",
|
||||||
"Action",
|
// "Action",
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleUpdateStatus = debounce((id) => {
|
|
||||||
setViewInvestor((prevData) =>
|
|
||||||
prevData.map((viewInvestor) =>
|
|
||||||
viewInvestor.id === id ? { ...viewInvestor } : viewInvestor
|
|
||||||
)
|
|
||||||
);
|
|
||||||
toast({
|
|
||||||
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
|
||||||
});
|
|
||||||
}, 300);
|
|
||||||
|
|
||||||
// ====================================================[Table Filter]================================================================
|
// ====================================================[Table Filter]================================================================
|
||||||
const filteredData = viewInvestor?.filter((item) => {
|
const filteredData = viewInvestor?.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = item.dealId;
|
const name = item.sponsorName;
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name?.toLowerCase().includes(searchLower);
|
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -100,22 +112,23 @@ const ViewInvestorDetails = () => {
|
|||||||
return nameMatches;
|
return nameMatches;
|
||||||
});
|
});
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item) => ({
|
const extractedArray = filteredData?.map((item, index) => ({
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
"Sr N/O": (
|
"Sr N/O": (
|
||||||
<Text w={'50px'}
|
<Text
|
||||||
|
w={"50px"}
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"gray.600"}
|
color={"gray.600"}
|
||||||
className="d-flex align-items-center fw-bold web-text-small"
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
>
|
>
|
||||||
{item.id}
|
{index + 1}.
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Deal Name": (
|
"IO Name": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.dealName}
|
{item.investmentNameEnglish}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
@@ -126,45 +139,205 @@ const ViewInvestorDetails = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
|
"Investment Type": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.investmentTypeName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
"Investment Amount": (
|
"Investment Amount": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={isSwitchOn ? "end" : "start"}
|
||||||
|
w={"auto"}
|
||||||
|
isTruncated={true}
|
||||||
|
>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.investAmount}
|
{isSwitchOn ? (
|
||||||
|
<>
|
||||||
|
{parseFloat(item?.investedAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
{InvestorWallet?.currencyCode_InCur}
|
||||||
|
</Badge>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{parseFloat(item?.investedAmount || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Holding Period": (
|
Percentage: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.holdingPeriod}
|
{item?.Investor_Holidings} %
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Estimated return": (
|
"Market Value": (
|
||||||
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={isSwitchOn ? "end" : "start"}
|
||||||
|
w={"auto"}
|
||||||
|
isTruncated={true}
|
||||||
|
>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{isSwitchOn ? (
|
||||||
|
<>
|
||||||
|
{parseFloat(item?.MarketValue || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
{InvestorWallet?.currencyCode_InCur}
|
||||||
|
</Badge>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{parseFloat(item?.MarketValue || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Return on Investment": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box w={"auto"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.estimatedReturn}
|
{item.MarketValue_Per} %
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Distribution: (
|
||||||
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={isSwitchOn ? "end" : "start"}
|
||||||
|
w={"auto"}
|
||||||
|
isTruncated={true}
|
||||||
|
>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{isSwitchOn ? (
|
||||||
|
<>
|
||||||
|
{parseFloat(item?.DistributionAmountReceived || 0).toLocaleString(
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
{InvestorWallet?.currencyCode_InCur}
|
||||||
|
</Badge>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{parseFloat(item?.DistributionAmountReceived || 0).toLocaleString(
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Distribution Percent": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item?.Distribution_Per} %
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Total return": (
|
||||||
|
<Box
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={isSwitchOn ? "end" : "start"}
|
||||||
|
w={"auto"}
|
||||||
|
isTruncated={true}
|
||||||
|
>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{isSwitchOn ? (
|
||||||
|
<>
|
||||||
|
{parseFloat(item?.TotalReturn || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
{InvestorWallet?.currencyCode_InCur}
|
||||||
|
</Badge>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Badge ms={1} colorScheme="green" me={1}>
|
||||||
|
$
|
||||||
|
</Badge>
|
||||||
|
{parseFloat(item?.TotalReturn || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
"Total return on Investment": (
|
||||||
|
<Box w={"auto"} isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"}>
|
||||||
|
{item.TotalReturn_Per} %
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Status: (
|
Status: (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
|
||||||
<Badge
|
<Badge
|
||||||
fontWeight={"500"}
|
rounded={"full"}
|
||||||
|
pt={1}
|
||||||
|
pb={1}
|
||||||
|
ps={4}
|
||||||
|
pe={4}
|
||||||
|
mt={1.5}
|
||||||
|
mb={1.5}
|
||||||
textTransform={"none"}
|
textTransform={"none"}
|
||||||
color={
|
// variant={"solid"}
|
||||||
item.kycStatus === "Open"
|
colorScheme={
|
||||||
? "green"
|
item?.statusAdmin === "Draft"
|
||||||
: item.kycStatus === "Pending"
|
? "gray"
|
||||||
|
: item?.statusAdmin === "Processing"
|
||||||
|
? "yellow"
|
||||||
|
: item?.statusAdmin === "Open"
|
||||||
? "blue"
|
? "blue"
|
||||||
: "red"
|
: item?.statusAdmin === "Closed"
|
||||||
|
? "green"
|
||||||
|
: item?.statusAdmin === "Exited"
|
||||||
|
? "red"
|
||||||
|
: item?.statusAdmin === "Canclled"
|
||||||
|
? "orange"
|
||||||
|
: "purple"
|
||||||
}
|
}
|
||||||
px={2}
|
boxShadow={"0 4px 6px rgba(0, 0, 0, 0.1)"} // Adjusted shadow
|
||||||
py={0.5}
|
|
||||||
>
|
>
|
||||||
{item.kycStatus}
|
{item?.statusAdmin}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Box>
|
|
||||||
),
|
),
|
||||||
Action: (
|
Action: (
|
||||||
<Box display={"flex"} justifyContent={"space-between"}>
|
<Box display={"flex"} justifyContent={"space-between"}>
|
||||||
@@ -203,6 +376,11 @@ const ViewInvestorDetails = () => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const switchOnChangeHandle = () => {
|
||||||
|
setIsSwitchOn(!isSwitchOn); // Toggle the switch state
|
||||||
|
setViewInvestor(data?.data?.portfolio);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
<Box bg="white.500">
|
<Box bg="white.500">
|
||||||
@@ -226,13 +404,53 @@ const ViewInvestorDetails = () => {
|
|||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HStack display={"flex"} alignItems={"center"}>
|
{/*
|
||||||
|
<Box
|
||||||
|
as="button"
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent={isSwitchOn ? "flex-end" : "flex-start"} // Use this if needed
|
||||||
|
width="155px"
|
||||||
|
height="30px"
|
||||||
|
borderRadius="20px"
|
||||||
|
backgroundColor={isSwitchOn ? "#004118" : "#ef0000"}
|
||||||
|
onClick={switchOnChangeHandle} // Correct handler name
|
||||||
|
position="relative"
|
||||||
|
fontSize="13px"
|
||||||
|
fontWeight="100"
|
||||||
|
transition="background-color 0.2s"
|
||||||
|
_before={{
|
||||||
|
content: '""',
|
||||||
|
position: "absolute",
|
||||||
|
width: "20px",
|
||||||
|
height: "20px",
|
||||||
|
borderRadius: "50%",
|
||||||
|
backgroundColor: "#FFF",
|
||||||
|
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)",
|
||||||
|
transform: isSwitchOn ? "translateX(128px)" : "translateX(0)",
|
||||||
|
transition: "transform 0.2s",
|
||||||
|
left: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fontWeight="400"
|
||||||
|
zIndex={1}
|
||||||
|
position="absolute"
|
||||||
|
mb={0}
|
||||||
|
color="#fff"
|
||||||
|
left={isSwitchOn ? "10px" : "auto"}
|
||||||
|
right={isSwitchOn ? "auto" : "10px"}
|
||||||
|
>
|
||||||
|
{isSwitchOn ? "Investor Currency" : "Investor Currency"}
|
||||||
|
</Text>
|
||||||
|
</Box> */}
|
||||||
|
{/* <HStack display={"flex"} alignItems={"center"}>
|
||||||
<Pagination totalItems={10} />
|
<Pagination totalItems={10} />
|
||||||
</HStack>
|
</HStack> */}
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<DataTable
|
<NormalTable
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
@@ -250,7 +468,6 @@ const ViewInvestorDetails = () => {
|
|||||||
alertHandler={handleDelete}
|
alertHandler={handleDelete}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,8 +52,9 @@ const Login = () => {
|
|||||||
const [login] = useLoginMutation()
|
const [login] = useLoginMutation()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (isAuthenticate) {
|
if (isAuthenticate) {
|
||||||
navigate("/sponser");
|
navigate("/");
|
||||||
}
|
}
|
||||||
}, [navigate, isAuthenticate]);
|
}, [navigate, isAuthenticate]);
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ import {
|
|||||||
} from "../../../Services/exchange.rate.service";
|
} from "../../../Services/exchange.rate.service";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import { getTomorrowDate } from "../../../Constants/Constants";
|
import { getTomorrowDate } from "../../../Constants/Constants";
|
||||||
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
|
|
||||||
|
|
||||||
// Convert date to YYYY-MM-DD format
|
// Convert date to YYYY-MM-DD format
|
||||||
const formatDateValue = (date) => {
|
const formatDateValue = (date) => {
|
||||||
@@ -47,11 +46,16 @@ const formatDateValue = (date) => {
|
|||||||
return [year, month, day].join("-");
|
return [year, month, day].join("-");
|
||||||
};
|
};
|
||||||
|
|
||||||
const EditExchangeRate = ({ id, setIsLoading }) => {
|
const EditExchangeRate = ({
|
||||||
const btnRef = useRef();
|
id,
|
||||||
|
setIsLoading,
|
||||||
|
isOpen,
|
||||||
|
onOpen,
|
||||||
|
onClose,
|
||||||
|
btnRef,
|
||||||
|
}) => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const {} = useDisclosure();
|
||||||
const { rateExchange, setRateExchange } = useContext(GlobalStateContext);
|
|
||||||
const [isBtnLoading, setIsBtnLoading] = useState(false);
|
const [isBtnLoading, setIsBtnLoading] = useState(false);
|
||||||
|
|
||||||
const { data, isLoading, errors } = useGetExchangeRateByIdQuery(id, {
|
const { data, isLoading, errors } = useGetExchangeRateByIdQuery(id, {
|
||||||
@@ -89,31 +93,6 @@ const EditExchangeRate = ({ id, setIsLoading }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip
|
|
||||||
rounded={"sm"}
|
|
||||||
fontSize={"xs"}
|
|
||||||
label="Edit"
|
|
||||||
bg="#fff"
|
|
||||||
color={"blue.500"}
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
ref={btnRef}
|
|
||||||
onClick={onOpen}
|
|
||||||
// _hover={{ color: "blue.500" }}
|
|
||||||
// transition={"0.5s all"}
|
|
||||||
// color="blue.400"
|
|
||||||
colorScheme="blue"
|
|
||||||
size={"xs"}
|
|
||||||
// size={{base:'xs', lg:'sm'}}
|
|
||||||
rounded={"sm"}
|
|
||||||
display={"flex"}
|
|
||||||
alignItems={"center"}
|
|
||||||
gap={1}
|
|
||||||
>
|
|
||||||
<EditIcon />
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Drawer
|
<Drawer
|
||||||
// size={"md"}
|
// size={"md"}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
@@ -132,6 +111,11 @@ const EditExchangeRate = ({ id, setIsLoading }) => {
|
|||||||
<DrawerCloseButton />
|
<DrawerCloseButton />
|
||||||
<DrawerHeader fontSize={"md"}>Edit rate</DrawerHeader>
|
<DrawerHeader fontSize={"md"}>Edit rate</DrawerHeader>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<FullscreenLoaders />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
<DrawerBody>
|
<DrawerBody>
|
||||||
<Box display={"flex"} mb={5}>
|
<Box display={"flex"} mb={5}>
|
||||||
<Box
|
<Box
|
||||||
@@ -158,17 +142,15 @@ const EditExchangeRate = ({ id, setIsLoading }) => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<FormControl mb={4}>
|
{/* <FormControl mb={4}>
|
||||||
<FormLabel fontSize={"sm"}>Last effective date</FormLabel>
|
<FormLabel fontSize={"sm"}>Last effective date</FormLabel>
|
||||||
<Text color={'gray.500'} fontSize={"sm"}>
|
<Text color={'gray.500'} fontSize={"sm"}>
|
||||||
{formatDate(foundObject?.effectiveFrom)}
|
{formatDate(foundObject?.effectiveFrom)}
|
||||||
</Text>
|
</Text>
|
||||||
</FormControl>
|
</FormControl> */}
|
||||||
<FormControl mb={4}>
|
<FormControl mb={4}>
|
||||||
<FormLabel fontSize={"sm"}>Effective from</FormLabel>
|
<FormLabel fontSize={"sm"}>Effective from</FormLabel>
|
||||||
<Text fontSize={"sm"}>
|
<Text fontSize={"sm"}>{formatDate(getTomorrowDate())}</Text>
|
||||||
{formatDate(getTomorrowDate())}
|
|
||||||
</Text>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl mb={4} isRequired>
|
<FormControl mb={4} isRequired>
|
||||||
@@ -183,7 +165,6 @@ const EditExchangeRate = ({ id, setIsLoading }) => {
|
|||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</DrawerBody>
|
</DrawerBody>
|
||||||
|
|
||||||
<DrawerFooter>
|
<DrawerFooter>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@@ -205,6 +186,8 @@ const EditExchangeRate = ({ id, setIsLoading }) => {
|
|||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</DrawerFooter>
|
</DrawerFooter>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</DrawerContent>
|
</DrawerContent>
|
||||||
</form>
|
</form>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|||||||
@@ -15,14 +15,15 @@ import {
|
|||||||
Tag,
|
Tag,
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
useDisclosure,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import DataTable from "../../../Components/DataTable/DataTable";
|
import DataTable from "../../../Components/DataTable/DataTable";
|
||||||
import { HiDotsVertical } from "react-icons/hi";
|
import { HiDotsVertical } from "react-icons/hi";
|
||||||
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
import { AddIcon, EmailIcon } from "@chakra-ui/icons";
|
import { AddIcon, EditIcon, EmailIcon } from "@chakra-ui/icons";
|
||||||
import Pagination from "../../../Components/Pagination";
|
import Pagination from "../../../Components/Pagination";
|
||||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
@@ -38,6 +39,7 @@ import { formatCurrency } from "../../../Components/CurrencyInput";
|
|||||||
|
|
||||||
const ExchangeRate = () => {
|
const ExchangeRate = () => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
const btnRef = useRef();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { slideFromRight, rateExchange, setRateExchange } =
|
const { slideFromRight, rateExchange, setRateExchange } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
@@ -48,6 +50,8 @@ const ExchangeRate = () => {
|
|||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
|
|
||||||
// ===============================[ Paginations ]
|
// ===============================[ Paginations ]
|
||||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
@@ -60,17 +64,33 @@ const ExchangeRate = () => {
|
|||||||
|
|
||||||
console.log(data?.data);
|
console.log(data?.data);
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString("en-GB", {
|
||||||
|
day: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredData = data?.data?.filter((item) => {
|
||||||
|
const name = item?.fromCurrency?.currencyCode;
|
||||||
|
const searchLower = searchTerm.toLowerCase();
|
||||||
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
"Sr.No",
|
"Sr.No",
|
||||||
"From currency",
|
"From Currency",
|
||||||
"To currency",
|
"To Currency",
|
||||||
"Effective from",
|
"Effective From",
|
||||||
"Rate",
|
"Rate",
|
||||||
"Action",
|
"Action",
|
||||||
];
|
];
|
||||||
|
|
||||||
const extractedArray = data?.data?.map((item, index) => ({
|
const extractedArray = filteredData?.map((item, index) => ({
|
||||||
"Sr.No": (
|
"Sr.No": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
@@ -79,10 +99,10 @@ const ExchangeRate = () => {
|
|||||||
fontWeight={"600"}
|
fontWeight={"600"}
|
||||||
className="d-flex align-items-center fw- web-text-small"
|
className="d-flex align-items-center fw- web-text-small"
|
||||||
>
|
>
|
||||||
{index + 1}.
|
{index + 1}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"From currency": (
|
"From Currency": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -93,7 +113,7 @@ const ExchangeRate = () => {
|
|||||||
{item?.fromCurrency?.currencyCode}
|
{item?.fromCurrency?.currencyCode}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"To currency": (
|
"To Currency": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -104,7 +124,7 @@ const ExchangeRate = () => {
|
|||||||
{item?.toCurrency?.currencyCode}
|
{item?.toCurrency?.currencyCode}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Effective from": (
|
"Effective From": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -132,12 +152,34 @@ const ExchangeRate = () => {
|
|||||||
// Edit
|
// Edit
|
||||||
// </Button>
|
// </Button>
|
||||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||||
<EditExchangeRate
|
<Tooltip
|
||||||
setIsLoading={setIsLoading}
|
rounded={"sm"}
|
||||||
id={item.id}
|
fontSize={"xs"}
|
||||||
// updateHistory={updateHistory}
|
label="Edit"
|
||||||
/>
|
bg="#fff"
|
||||||
|
color={"blue.500"}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
ref={btnRef}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item?.id);
|
||||||
|
onOpen();
|
||||||
|
}}
|
||||||
|
// _hover={{ color: "blue.500" }}
|
||||||
|
// transition={"0.5s all"}
|
||||||
|
// color="blue.400"
|
||||||
|
colorScheme="blue"
|
||||||
|
size={"xs"}
|
||||||
|
// size={{base:'xs', lg:'sm'}}
|
||||||
|
rounded={"sm"}
|
||||||
|
display={"flex"}
|
||||||
|
alignItems={"center"}
|
||||||
|
gap={1}
|
||||||
|
>
|
||||||
|
<EditIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
@@ -208,10 +250,6 @@ const ExchangeRate = () => {
|
|||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
isLoading={isExchangeRateLoading}
|
isLoading={isExchangeRateLoading}
|
||||||
viewActionId={actionId}
|
|
||||||
setViewActionId={setActionId}
|
|
||||||
// totalPages={10}
|
|
||||||
|
|
||||||
setMouseEnteredId={setMouseEnteredId}
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
setMouseEntered={setMouseEntered}
|
setMouseEntered={setMouseEntered}
|
||||||
/>
|
/>
|
||||||
@@ -223,6 +261,18 @@ const ExchangeRate = () => {
|
|||||||
alertHandler={handleDelete}
|
alertHandler={handleDelete}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<EditExchangeRate
|
||||||
|
setIsLoading={setIsLoading}
|
||||||
|
id={actionId}
|
||||||
|
setId={setActionId}
|
||||||
|
onClose={onClose}
|
||||||
|
onOpen={onOpen}
|
||||||
|
isOpen={isOpen}
|
||||||
|
btnRef={btnRef}
|
||||||
|
// id={item.id}
|
||||||
|
// updateHistory={updateHistory}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import { Box, Button, useToast } from "@chakra-ui/react";
|
import { Box, Button, Text, useToast } from "@chakra-ui/react";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
@@ -11,21 +11,23 @@ import {
|
|||||||
useCreateInvestmentTypeMutation,
|
useCreateInvestmentTypeMutation,
|
||||||
useGetInvestmentTypeByIdQuery,
|
useGetInvestmentTypeByIdQuery,
|
||||||
useUpdateInvestmentTypeMutation,
|
useUpdateInvestmentTypeMutation,
|
||||||
} from "../../../Services/investment.type.service";
|
} from "../../../Services/io.service";
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
|
import { ArrowBackIcon } from "@chakra-ui/icons";
|
||||||
|
|
||||||
// ======================= [validation] =========================
|
// ======================= [validation] =========================
|
||||||
|
|
||||||
export const addInvestmentType = yup.object().shape({
|
export const addInvestmentType = yup.object().shape({
|
||||||
investmentTypeName: yup.string()
|
investmentTypeName: yup
|
||||||
.required('Investment type is required')
|
.string()
|
||||||
.max(50, 'Investment name cannot be more than 50 characters'),
|
.required("Investment type is required")
|
||||||
note: yup.string()
|
.max(50, "Investment name cannot be more than 50 characters"),
|
||||||
.optional()
|
note: yup.string().optional().max(255, "Note cannot exceed 255 characters"),
|
||||||
.max(255, 'Note cannot exceed 255 characters'),
|
investmentTypeNameArabic: yup
|
||||||
investmentTypeNameArabic: yup.string().required("Investment type in arabic required"),
|
.string()
|
||||||
|
.required("Investment type in required"),
|
||||||
noteArabic: yup.string().notRequired(),
|
noteArabic: yup.string().notRequired(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -40,12 +42,11 @@ export function debounce(func, delay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AddInvestmentType = () => {
|
const AddInvestmentType = () => {
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const id = params?.id;
|
const id = params?.id;
|
||||||
console.log('hit');
|
console.log("hit");
|
||||||
|
|
||||||
// =====================[useState]=======================
|
// =====================[useState]=======================
|
||||||
|
|
||||||
@@ -54,8 +55,6 @@ const AddInvestmentType = () => {
|
|||||||
const [alert, setAlert] = useState(false);
|
const [alert, setAlert] = useState(false);
|
||||||
const [form, setForm] = useState();
|
const [form, setForm] = useState();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [createInvestmentType] = useCreateInvestmentTypeMutation();
|
const [createInvestmentType] = useCreateInvestmentTypeMutation();
|
||||||
const [updateInvestmentType] = useUpdateInvestmentTypeMutation();
|
const [updateInvestmentType] = useUpdateInvestmentTypeMutation();
|
||||||
|
|
||||||
@@ -71,9 +70,11 @@ const AddInvestmentType = () => {
|
|||||||
resolver: yupResolver(addInvestmentType),
|
resolver: yupResolver(addInvestmentType),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: investmentTypeByIdData, error, isLoading, } = useGetInvestmentTypeByIdQuery(id, { skip: !id });
|
const {
|
||||||
|
data: investmentTypeByIdData,
|
||||||
|
error,
|
||||||
|
isLoading,
|
||||||
|
} = useGetInvestmentTypeByIdQuery(id, { skip: !id });
|
||||||
|
|
||||||
// ========================== [useEffect] ================================
|
// ========================== [useEffect] ================================
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ const AddInvestmentType = () => {
|
|||||||
note: investmentTypeByIdData?.data?.note,
|
note: investmentTypeByIdData?.data?.note,
|
||||||
noteArabic: investmentTypeByIdData?.data?.noteArabic,
|
noteArabic: investmentTypeByIdData?.data?.noteArabic,
|
||||||
});
|
});
|
||||||
setIsSwitchOn(investmentTypeByIdData?.data?.isActive)
|
setIsSwitchOn(investmentTypeByIdData?.data?.isActive);
|
||||||
}
|
}
|
||||||
}, [investmentTypeByIdData, reset]);
|
}, [investmentTypeByIdData, reset]);
|
||||||
|
|
||||||
@@ -174,9 +175,11 @@ const AddInvestmentType = () => {
|
|||||||
name: "investmentTypeName",
|
name: "investmentTypeName",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
maxLength: 50,
|
maxLength: 50,
|
||||||
helperText:`Maximum length should be 50 characters. You have entered ${watch()?.investmentTypeName?.length || 0} characters.`
|
helperText: `Maximum length should be 50 characters. You have entered ${
|
||||||
|
watch()?.investmentTypeName?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Investment Type (Arabic) ",
|
label: "Investment Type (Arabic) ",
|
||||||
@@ -184,10 +187,12 @@ const AddInvestmentType = () => {
|
|||||||
placeHolder: " ",
|
placeHolder: " ",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
arabic: true,
|
arabic: true,
|
||||||
maxLength: 255,
|
maxLength: 255,
|
||||||
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.investmentTypeNameArabic?.length || 0} characters.`
|
helperText: `Maximum length should be 255 characters. You have entered ${
|
||||||
|
watch()?.investmentTypeNameArabic?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Description (English)",
|
label: "Description (English)",
|
||||||
@@ -195,9 +200,11 @@ const AddInvestmentType = () => {
|
|||||||
name: "note",
|
name: "note",
|
||||||
type: "textarea",
|
type: "textarea",
|
||||||
// isRequired: true,
|
// isRequired: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
maxLength: 255,
|
maxLength: 255,
|
||||||
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.note?.length || 0} characters.`
|
helperText: `Maximum length should be 255 characters. You have entered ${
|
||||||
|
watch()?.note?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Description (Arabic)",
|
label: "Description (Arabic)",
|
||||||
@@ -206,9 +213,11 @@ const AddInvestmentType = () => {
|
|||||||
type: "textarea",
|
type: "textarea",
|
||||||
// isRequired: true,
|
// isRequired: true,
|
||||||
arabic: true,
|
arabic: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
maxLength: 255,
|
maxLength: 255,
|
||||||
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.noteArabic?.length || 0} characters.`
|
helperText: `Maximum length should be 255 characters. You have entered ${
|
||||||
|
watch()?.noteArabic?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -221,9 +230,11 @@ const AddInvestmentType = () => {
|
|||||||
name: "investmentTypeName",
|
name: "investmentTypeName",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
maxLength: 50,
|
maxLength: 50,
|
||||||
helperText:`Maximum length should be 50 characters. You have entered ${watch()?.investmentTypeName?.length || 0} characters.`
|
helperText: `Maximum length should be 50 characters. You have entered ${
|
||||||
|
watch()?.investmentTypeName?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Investment Type (Arabic)",
|
label: "Investment Type (Arabic)",
|
||||||
@@ -231,10 +242,12 @@ const AddInvestmentType = () => {
|
|||||||
placeHolder: " ",
|
placeHolder: " ",
|
||||||
type: "text",
|
type: "text",
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
arabic: true,
|
arabic: true,
|
||||||
maxLength: 255,
|
maxLength: 255,
|
||||||
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.investmentTypeNameArabic?.length || 0} characters.`
|
helperText: `Maximum length should be 255 characters. You have entered ${
|
||||||
|
watch()?.investmentTypeNameArabic?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Description (English)",
|
label: "Description (English)",
|
||||||
@@ -242,9 +255,11 @@ const AddInvestmentType = () => {
|
|||||||
name: "note",
|
name: "note",
|
||||||
type: "textarea",
|
type: "textarea",
|
||||||
// isRequired: true,
|
// isRequired: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
maxLength: 255,
|
maxLength: 255,
|
||||||
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.note?.length || 0} characters.`
|
helperText: `Maximum length should be 255 characters. You have entered ${
|
||||||
|
watch()?.note?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Description (Arabic)",
|
label: "Description (Arabic)",
|
||||||
@@ -253,9 +268,11 @@ const AddInvestmentType = () => {
|
|||||||
type: "textarea",
|
type: "textarea",
|
||||||
// isRequired: true,
|
// isRequired: true,
|
||||||
arabic: true,
|
arabic: true,
|
||||||
section: "Add Details",
|
section: "",
|
||||||
maxLength: 255,
|
maxLength: 255,
|
||||||
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.noteArabic?.length || 0} characters.`
|
helperText: `Maximum length should be 255 characters. You have entered ${
|
||||||
|
watch()?.noteArabic?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -281,7 +298,6 @@ const AddInvestmentType = () => {
|
|||||||
return groups;
|
return groups;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
|
|
||||||
// ==================== [On Submit] ========================
|
// ==================== [On Submit] ========================
|
||||||
|
|
||||||
const onSubmit = async (data) => {
|
const onSubmit = async (data) => {
|
||||||
@@ -292,13 +308,16 @@ const AddInvestmentType = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return isLoading ? (
|
||||||
isLoading ? <FullscreenLoaders /> :
|
<FullscreenLoaders />
|
||||||
|
) : (
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
||||||
|
|
||||||
{/* ===================== [Switch Button] ======================== */}
|
{/* ===================== [Switch Button] ======================== */}
|
||||||
|
|
||||||
<Box mt={5} display={"flex"} justifyContent={"right"} mr={5}>
|
<Box display={"flex"} justifyContent={"space-between"} alignItems={"center"} mt={5} px={4} mb={5}>
|
||||||
|
<Text fontSize={"sm"} mb={0} onClick={() => navigate(-1)} cursor={"pointer"}>
|
||||||
|
<ArrowBackIcon fontSize={"xl"} me={2} />Add Details
|
||||||
|
</Text>
|
||||||
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
|
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -311,8 +330,7 @@ const AddInvestmentType = () => {
|
|||||||
onSubmit={handleSubmit(onSubmit)}
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
submitTitle={params?.id ? "Update" : "Submit"}
|
submitTitle={params?.id ? "Update" : "Submit"}
|
||||||
// btnLoading={isLoadingBtn}
|
// btnLoading={isLoadingBtn}
|
||||||
>
|
></FormInputMain>
|
||||||
</FormInputMain>
|
|
||||||
|
|
||||||
{/* ======================= [Modal] =========================== */}
|
{/* ======================= [Modal] =========================== */}
|
||||||
|
|
||||||
@@ -320,10 +338,9 @@ const AddInvestmentType = () => {
|
|||||||
isOpen={alert}
|
isOpen={alert}
|
||||||
onClose={() => setAlert(false)}
|
onClose={() => setAlert(false)}
|
||||||
alertHandler={handleConfirm}
|
alertHandler={handleConfirm}
|
||||||
message={"Are you sure you want to add this?"}
|
message={id ? "Are you sure you want to update this document?" : " Are you sure you want to add this document?"}
|
||||||
isLoading={isLoadingBtn}
|
isLoading={isLoadingBtn}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ import NormalTable from "../../../Components/DataTable/NormalTable";
|
|||||||
import {
|
import {
|
||||||
useDeleteInvestmentTypeMutation,
|
useDeleteInvestmentTypeMutation,
|
||||||
useGetInvestmentTypesQuery,
|
useGetInvestmentTypesQuery,
|
||||||
} from "../../../Services/investment.type.service";
|
} from "../../../Services/io.service";
|
||||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ const InvestmentType = () => {
|
|||||||
// ===========================[Table Filter]=============================
|
// ===========================[Table Filter]=============================
|
||||||
|
|
||||||
const filteredData = investmentTypes?.data?.rows?.filter((item) => {
|
const filteredData = investmentTypes?.data?.rows?.filter((item) => {
|
||||||
const name = item.investmentTypeName;
|
const name = item?.investmentTypeName;
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ const InvestmentType = () => {
|
|||||||
// ==================================================== [Table Setup] ================================================================
|
// ==================================================== [Table Setup] ================================================================
|
||||||
|
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
// "Sr.no",
|
"Sr No",
|
||||||
"Investment Type",
|
"Investment Type",
|
||||||
"Description",
|
"Description",
|
||||||
"Status",
|
"Status",
|
||||||
@@ -92,17 +93,18 @@ const InvestmentType = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item, index) => ({
|
const extractedArray = filteredData?.map((item, index) => ({
|
||||||
// "Sr.no": (
|
"Sr No": (
|
||||||
// <Text
|
<Text
|
||||||
// justifyContent={slideFromRight ? "right" : "left"}
|
w={"24px"}
|
||||||
// as={"span"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
// color={"teal.900"}
|
as={"span"}
|
||||||
// fontWeight={"500"}
|
color={"gray.600"}
|
||||||
// className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
// >
|
>
|
||||||
// {index + 1}
|
{/* {item.id} */}
|
||||||
// </Text>
|
{generateSerialNumber(index, currentPage, pageSize)}
|
||||||
// ),
|
</Text>
|
||||||
|
),
|
||||||
"Investment Type": (
|
"Investment Type": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
@@ -112,12 +114,18 @@ const InvestmentType = () => {
|
|||||||
isTruncated={true}
|
isTruncated={true}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{item.investmentTypeName}
|
{item?.investmentTypeName}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
Description: (
|
Description: (
|
||||||
|
<Tooltip
|
||||||
<Tooltip hasArrow bg={"#fff"} fontSize={"xs"} label={item.note} placement="top-start" color={"blue.800"} >
|
hasArrow
|
||||||
|
bg={"#fff"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label={item.note}
|
||||||
|
placement="top-start"
|
||||||
|
color={"blue.800"}
|
||||||
|
>
|
||||||
<Text
|
<Text
|
||||||
as={"span"}
|
as={"span"}
|
||||||
color={"teal.900"}
|
color={"teal.900"}
|
||||||
@@ -129,9 +137,7 @@ const InvestmentType = () => {
|
|||||||
textOverflow="ellipsis"
|
textOverflow="ellipsis"
|
||||||
cursor={"grab"}
|
cursor={"grab"}
|
||||||
>
|
>
|
||||||
|
{item?.note ? item?.note : "---"}
|
||||||
{item.note}
|
|
||||||
|
|
||||||
</Text>
|
</Text>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
),
|
),
|
||||||
@@ -139,6 +145,7 @@ const InvestmentType = () => {
|
|||||||
<Box isTruncated={true}>
|
<Box isTruncated={true}>
|
||||||
<Text as={"span"} fontWeight={"500"}>
|
<Text as={"span"} fontWeight={"500"}>
|
||||||
<Badge
|
<Badge
|
||||||
|
bg={index % 2 === 0 ? "#6311cb14" : "#fff"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
textTransform={"none"}
|
textTransform={"none"}
|
||||||
color={item.isActive ? "green" : "red"}
|
color={item.isActive ? "green" : "red"}
|
||||||
@@ -152,7 +159,7 @@ const InvestmentType = () => {
|
|||||||
),
|
),
|
||||||
Action: (
|
Action: (
|
||||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||||
<Tooltip
|
{/* <Tooltip
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
label="View"
|
label="View"
|
||||||
@@ -173,7 +180,7 @@ const InvestmentType = () => {
|
|||||||
>
|
>
|
||||||
<ViewIcon />
|
<ViewIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip> */}
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
@@ -185,7 +192,7 @@ const InvestmentType = () => {
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(`/investment-type/add-investment/${item.id}`)
|
navigate(`/investment-type/add-investment/${item?.id}`)
|
||||||
}
|
}
|
||||||
// _hover={{ color: "blue.500" }}
|
// _hover={{ color: "blue.500" }}
|
||||||
// color="blue.400"
|
// color="blue.400"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import FormInputView from "../../../Components/FormInputView";
|
|||||||
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
|
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import { ArrowBackIcon } from "@chakra-ui/icons";
|
import { ArrowBackIcon } from "@chakra-ui/icons";
|
||||||
import { useGetInvestmentTypeByIdQuery } from "../../../Services/investment.type.service";
|
import { useGetInvestmentTypeByIdQuery } from "../../../Services/io.service";
|
||||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
|
|
||||||
const ViewInvestmentType = () => {
|
const ViewInvestmentType = () => {
|
||||||
|
|||||||
@@ -1,28 +1,36 @@
|
|||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import { Box, Button, useToast } from "@chakra-ui/react";
|
import { Box, Button, Text, useToast } from "@chakra-ui/react";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import FormInputMain from "../../../Components/FormInputMain";
|
import FormInputMain from "../../../Components/FormInputMain";
|
||||||
import {useCreateSponserMutation,useGetSponserByIdQuery,useUpdateSponserMutation,} from "../../../Services/sponser.service";
|
|
||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
import SwitchButton from "../../../Components/SwitchButton";
|
import SwitchButton from "../../../Components/SwitchButton";
|
||||||
import DummyComponent from "../../../Components/DummyComponent";
|
import DummyComponent from "../../../Components/DummyComponent";
|
||||||
|
import {
|
||||||
|
useCreateSponserMutation,
|
||||||
|
useGetSponserByIdQuery,
|
||||||
|
useUpdateSponserMutation,
|
||||||
|
} from "../../../Services/io.service";
|
||||||
|
import { ArrowBackIcon } from "@chakra-ui/icons";
|
||||||
// ======================= [validation] =========================
|
// ======================= [validation] =========================
|
||||||
|
|
||||||
export const addSponser = yup.object().shape({
|
export const addSponser = yup.object().shape({
|
||||||
sponsorName: yup.
|
sponsorName: yup
|
||||||
string()
|
.string()
|
||||||
.required('Sponsor Name is required')
|
.required("Sponsor Name is required")
|
||||||
.min(3, 'Sponsor Name must be at least 3 characters long')
|
.min(3, "Sponsor Name must be at least 3 characters long")
|
||||||
.max(50, 'Investment Type Name cannot exceed 50 characters'),
|
.max(50, "Sponsor Name cannot exceed 50 characters")
|
||||||
sponsorNameArabic: yup.string().required("Sponser name in arabic is required"),
|
.matches(/^[^\d]+$/, "Sponsor Name cannot contain numbers"),
|
||||||
|
|
||||||
|
sponsorNameArabic: yup
|
||||||
|
.string()
|
||||||
|
.required("Sponser name in arabic is required"),
|
||||||
email: yup.string().email("Invalid email address").notRequired(),
|
email: yup.string().email("Invalid email address").notRequired(),
|
||||||
// .test("emailValidity", "Email address is invalid", async function (value) {
|
// .test("emailValidity", "Email address is invalid", async function (value) {
|
||||||
// if (!value) {
|
// if (!value) {
|
||||||
@@ -43,7 +51,6 @@ export function debounce(func, delay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AddSponser = () => {
|
const AddSponser = () => {
|
||||||
|
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -60,7 +67,11 @@ const AddSponser = () => {
|
|||||||
const [updateSponser] = useUpdateSponserMutation();
|
const [updateSponser] = useUpdateSponserMutation();
|
||||||
|
|
||||||
// Fetch sponsor data only if id exists
|
// Fetch sponsor data only if id exists
|
||||||
const {data: sponserByIdData,error,isLoading,} = useGetSponserByIdQuery(id, {skip: !id,});
|
const {
|
||||||
|
data: sponserByIdData,
|
||||||
|
error,
|
||||||
|
isLoading,
|
||||||
|
} = useGetSponserByIdQuery(id, { skip: !id });
|
||||||
|
|
||||||
// ======================== [validators] ===========================
|
// ======================== [validators] ===========================
|
||||||
|
|
||||||
@@ -72,7 +83,6 @@ const AddSponser = () => {
|
|||||||
reset,
|
reset,
|
||||||
} = useForm({
|
} = useForm({
|
||||||
resolver: yupResolver(addSponser),
|
resolver: yupResolver(addSponser),
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ========================== [useEffect] ================================
|
// ========================== [useEffect] ================================
|
||||||
@@ -84,15 +94,13 @@ const AddSponser = () => {
|
|||||||
sponsorNameArabic: sponserByIdData?.data?.sponsorNameArabic,
|
sponsorNameArabic: sponserByIdData?.data?.sponsorNameArabic,
|
||||||
email: sponserByIdData?.data?.email,
|
email: sponserByIdData?.data?.email,
|
||||||
});
|
});
|
||||||
setIsSwitchOn(sponserByIdData?.data?.isActive)
|
setIsSwitchOn(sponserByIdData?.data?.isActive);
|
||||||
console.log(sponserByIdData?.data?.isActive);
|
console.log(sponserByIdData?.data?.isActive);
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [sponserByIdData, reset]);
|
}, [sponserByIdData, reset]);
|
||||||
|
|
||||||
// console.log(isSwitchOn);
|
// console.log(isSwitchOn);
|
||||||
|
|
||||||
|
|
||||||
if (false) {
|
if (false) {
|
||||||
return <FullscreenLoaders />;
|
return <FullscreenLoaders />;
|
||||||
}
|
}
|
||||||
@@ -109,7 +117,7 @@ const AddSponser = () => {
|
|||||||
isActive: isSwitchOn,
|
isActive: isSwitchOn,
|
||||||
};
|
};
|
||||||
// Remove email field if it's an empty string
|
// Remove email field if it's an empty string
|
||||||
if (formData.email === '') {
|
if (formData.email === "") {
|
||||||
delete formData.email;
|
delete formData.email;
|
||||||
}
|
}
|
||||||
await updateSponser({ data: formData, id }).then((response) => {
|
await updateSponser({ data: formData, id }).then((response) => {
|
||||||
@@ -124,12 +132,15 @@ const AddSponser = () => {
|
|||||||
} else if (response?.error?.status === 400) {
|
} else if (response?.error?.status === 400) {
|
||||||
toast({
|
toast({
|
||||||
render: () => (
|
render: () => (
|
||||||
<ToastBox message={response?.error?.data?.message} status={"error"} />
|
<ToastBox
|
||||||
|
message={response?.error?.data?.message}
|
||||||
|
status={"error"}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoadingBtn(false);
|
setIsLoadingBtn(false);
|
||||||
setAlert(false)
|
setAlert(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -155,12 +166,15 @@ const AddSponser = () => {
|
|||||||
} else if (response?.error?.status === 400) {
|
} else if (response?.error?.status === 400) {
|
||||||
toast({
|
toast({
|
||||||
render: () => (
|
render: () => (
|
||||||
<ToastBox message={response?.error?.data?.message} status={"error"} />
|
<ToastBox
|
||||||
|
message={response?.error?.data?.message}
|
||||||
|
status={"error"}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsLoadingBtn(false);
|
setIsLoadingBtn(false);
|
||||||
setAlert(false)
|
setAlert(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -183,7 +197,9 @@ const AddSponser = () => {
|
|||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "",
|
section: "",
|
||||||
maxLength: 50,
|
maxLength: 50,
|
||||||
helperText:`Maximum length should be 50 characters. You have entered ${watch()?.sponsorName?.length || 0} characters.`
|
helperText: `Maximum length should be 50 characters. You have entered ${
|
||||||
|
watch()?.sponsorName?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Sponsor name (Arabic)",
|
label: "Sponsor name (Arabic)",
|
||||||
@@ -195,7 +211,9 @@ const AddSponser = () => {
|
|||||||
arabic: true,
|
arabic: true,
|
||||||
right: true,
|
right: true,
|
||||||
maxLength: 55,
|
maxLength: 55,
|
||||||
helperText:`Maximum length should be 55 characters. You have entered ${watch()?.sponsorNameArabic?.length || 0} characters.`
|
helperText: `Maximum length should be 55 characters. You have entered ${
|
||||||
|
watch()?.sponsorNameArabic?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Email address",
|
label: "Email address",
|
||||||
@@ -218,7 +236,9 @@ const AddSponser = () => {
|
|||||||
isRequired: true,
|
isRequired: true,
|
||||||
section: "",
|
section: "",
|
||||||
maxLength: 55,
|
maxLength: 55,
|
||||||
helperText:`Maximum length should be 55 characters. You have entered ${watch()?.sponsorName?.length || 0} characters.`
|
helperText: `Maximum length should be 55 characters. You have entered ${
|
||||||
|
watch()?.sponsorName?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Sponsor name (Arabic)",
|
label: "Sponsor name (Arabic)",
|
||||||
@@ -229,7 +249,9 @@ const AddSponser = () => {
|
|||||||
section: "",
|
section: "",
|
||||||
arabic: true,
|
arabic: true,
|
||||||
maxLength: 55,
|
maxLength: 55,
|
||||||
helperText:`Maximum length should be 55 characters. You have entered ${watch()?.sponsorNameArabic?.length || 0} characters.`
|
helperText: `Maximum length should be 55 characters. You have entered ${
|
||||||
|
watch()?.sponsorNameArabic?.length || 0
|
||||||
|
} characters.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Email adress",
|
label: "Email adress",
|
||||||
@@ -272,17 +294,18 @@ const AddSponser = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return isLoading ? (
|
||||||
isLoading?<FullscreenLoaders/>:
|
<FullscreenLoaders />
|
||||||
|
) : (
|
||||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
||||||
|
|
||||||
{/* ===================== [Switch Button] ======================== */}
|
{/* ===================== [Switch Button] ======================== */}
|
||||||
|
<Box display={"flex"} justifyContent={"space-between"} alignItems={"center"} mt={5} px={4}>
|
||||||
<Box mt={5} display={"flex"} justifyContent={"right"} mr={5}>
|
<Text fontSize={"sm"} mb={0} onClick={() => navigate(-1)} cursor={"pointer"}>
|
||||||
|
<ArrowBackIcon fontSize={"xl"} me={2} />Add Details
|
||||||
|
</Text>
|
||||||
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
|
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
{/* ====================== [Form Input] ====================== */}
|
{/* ====================== [Form Input] ====================== */}
|
||||||
|
|
||||||
<FormInputMain
|
<FormInputMain
|
||||||
@@ -299,7 +322,7 @@ const AddSponser = () => {
|
|||||||
isOpen={alert}
|
isOpen={alert}
|
||||||
onClose={() => setAlert(false)}
|
onClose={() => setAlert(false)}
|
||||||
alertHandler={handleConfirm}
|
alertHandler={handleConfirm}
|
||||||
message={"Are you sure you want to add this?"}
|
message={id ? "Are you sure you want to update this?" : "Are you sure you want to add this?"}
|
||||||
isLoading={isLoadingBtn}
|
isLoading={isLoadingBtn}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import ToastBox from "../../../Components/ToastBox";
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
import { debounce } from "./AddSponser";
|
import { debounce } from "./AddSponser";
|
||||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
import {useDeleteSponserMutation,useGetSponserMasterQuery,useToggleStatusMutation,} from "../../../Services/sponser.service";
|
import { useDeleteSponserMutation, useGetSponserMasterQuery } from "../../../Services/io.service";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
|
||||||
export const formatDate = (date) => {
|
export const formatDate = (date) => {
|
||||||
const d = new Date(date);
|
const d = new Date(date);
|
||||||
@@ -26,29 +27,40 @@ const Sponser = () => {
|
|||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
const [toggleStatus] = useToggleStatusMutation();
|
|
||||||
const [deleteSponser] = useDeleteSponserMutation();
|
const [deleteSponser] = useDeleteSponserMutation();
|
||||||
const { sponser, setSponser, slideFromRight } = useContext(GlobalStateContext);
|
const { sponser, setSponser, slideFromRight } = useContext(GlobalStateContext);
|
||||||
|
|
||||||
// =========================== [Use State] =============================
|
// =========================== [Use State] =============================
|
||||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
const {data: sponsors,error,isLoading: isSponserLoading,} = useGetSponserMasterQuery({ page: currentPage, size: pageSize });
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
// console.log(sponsors?.data?.rows);
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
const { data: sponsors, error, isLoading: isSponserLoading } = useGetSponserMasterQuery(
|
||||||
|
{
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
searchTerm: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log(sponsors?.data?.rows);
|
||||||
|
|
||||||
// ==============================[Table Filter]========================
|
// ==============================[Table Filter]========================
|
||||||
|
|
||||||
@@ -62,14 +74,27 @@ const Sponser = () => {
|
|||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
|
|
||||||
const tableHeadRow = [
|
const tableHeadRow = [
|
||||||
"Sponsor name",
|
"Sr No",
|
||||||
"Email address",
|
"Sponsor Name",
|
||||||
|
"Email Address",
|
||||||
"Status",
|
"Status",
|
||||||
"Action",
|
"Action",
|
||||||
];
|
];
|
||||||
|
|
||||||
const extractedArray = filteredData?.map((item) => ({
|
const extractedArray = sponsors?.data?.rows?.map((item, index) => ({
|
||||||
"Sponsor name": (
|
"Sr No": (
|
||||||
|
<Text
|
||||||
|
w={'24px'}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{/* {item.id} */}
|
||||||
|
{generateSerialNumber(index,currentPage, pageSize )}
|
||||||
|
|
||||||
|
</Text>),
|
||||||
|
"Sponsor Name": (
|
||||||
<Text
|
<Text
|
||||||
justifyContent={slideFromRight ? "right" : "left"}
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
as={"span"}
|
as={"span"}
|
||||||
@@ -81,16 +106,17 @@ const Sponser = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
|
|
||||||
"Email address": (
|
"Email Address": (
|
||||||
<Box w={"auto"} isTruncated={true}>
|
<Box isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
{item.email}
|
{item.email ? item.email : "---" }
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Status: (
|
Status: (
|
||||||
<Box minW={24} isTruncated={true} >
|
<Box minW={24} isTruncated={true} >
|
||||||
<Badge
|
<Badge
|
||||||
|
bg={index % 2 === 0 ? "#6311cb14" : "#fff"}
|
||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
textTransform={"none"}
|
textTransform={"none"}
|
||||||
color={item.isActive ? "green" : "red"}
|
color={item.isActive ? "green" : "red"}
|
||||||
@@ -161,7 +187,7 @@ const Sponser = () => {
|
|||||||
console.log(response?.data);
|
console.log(response?.data);
|
||||||
if(response?.error?.data?.code === 400){
|
if(response?.error?.data?.code === 400){
|
||||||
toast({
|
toast({
|
||||||
render: () => <ToastBox message={response?.error?.data?.message} status={'error'} />,
|
render: () => <ToastBox message={response?.error?.data?.message} status={'warn'} />,
|
||||||
});
|
});
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setDeleteAlert(false);
|
setDeleteAlert(false);
|
||||||
@@ -210,7 +236,13 @@ const Sponser = () => {
|
|||||||
|
|
||||||
{/* ====================[Pagination]===================== */}
|
{/* ====================[Pagination]===================== */}
|
||||||
|
|
||||||
<Pagination isLoading={isSponserLoading} pageSize={pageSize} setPageSize={setPageSize} currentPage={currentPage} setCurrentPage={setCurrentPage} totalItems={sponsors?.data?.totalItems} />
|
<Pagination
|
||||||
|
isLoading={isSponserLoading}
|
||||||
|
pageSize={pageSize}
|
||||||
|
setPageSize={setPageSize}
|
||||||
|
currentPage={currentPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
totalItems={sponsors?.data?.totalItems} />
|
||||||
|
|
||||||
{/* =====================[Add Button]===================== */}
|
{/* =====================[Add Button]===================== */}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useContext, useEffect, useState } from "react";
|
|||||||
import FormInputView from "../../../Components/FormInputView";
|
import FormInputView from "../../../Components/FormInputView";
|
||||||
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
|
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
|
||||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import { useGetSponserByIdQuery } from "../../../Services/sponser.service";
|
import { useGetSponserByIdQuery } from "../../../Services/io.service";
|
||||||
|
|
||||||
const ViewSponser = () => {
|
const ViewSponser = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|||||||
15
src/Pages/PaymentFailed.jsx
Normal file
15
src/Pages/PaymentFailed.jsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Box, Button, Heading, Image, Img, Text } from "@chakra-ui/react";
|
||||||
|
import failed from "../assets/failed.gif";
|
||||||
|
|
||||||
|
const PaymentFailed = () => {
|
||||||
|
return (
|
||||||
|
<Box h={"100vh"} display={"flex"} alignItems={"center"} flexDirection={"column"} p={"15px"} justifyContent={"center"}>
|
||||||
|
<Img w={"180px"} src={failed} />
|
||||||
|
<Heading fontSize={"20px"} fontWeight={600}>Payment Failed !!</Heading>
|
||||||
|
<Text fontSize={"18px"}>Your payment was Failed</Text>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PaymentFailed;
|
||||||
15
src/Pages/PaymentSuccess.jsx
Normal file
15
src/Pages/PaymentSuccess.jsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Box, Button, Heading, Image, Img, Text } from "@chakra-ui/react";
|
||||||
|
import success from "../assets/successimg.gif";
|
||||||
|
|
||||||
|
const Welcome = () => {
|
||||||
|
return (
|
||||||
|
<Box h={"100vh"} display={"flex"} alignItems={"center"} flexDirection={"column"} p={"15px"} justifyContent={"center"}>
|
||||||
|
<Img w={"180px"} src={success} />
|
||||||
|
<Heading fontSize={"20px"} fontWeight={600} textAlign={"center"}>SuccessFul !!</Heading>
|
||||||
|
<Text fontSize={"18px"} extAlign={"center"}>Your payment was done successfully</Text>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Welcome;
|
||||||
227
src/Pages/Profile/Profile.jsx
Normal file
227
src/Pages/Profile/Profile.jsx
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Box,
|
||||||
|
ButtonGroup,
|
||||||
|
Editable,
|
||||||
|
EditableInput,
|
||||||
|
EditablePreview,
|
||||||
|
EditableTextarea,
|
||||||
|
Flex,
|
||||||
|
HStack,
|
||||||
|
Heading,
|
||||||
|
Icon,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
Text,
|
||||||
|
VStack,
|
||||||
|
useEditableControls,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React from "react";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
import { CheckIcon, CloseIcon, EditIcon, InfoIcon } from "@chakra-ui/icons";
|
||||||
|
import { FaEarthAmericas } from "react-icons/fa6";
|
||||||
|
import logoMini from "../../assets/propic.png";
|
||||||
|
|
||||||
|
const Profile = () => {
|
||||||
|
/* Here's a custom control */
|
||||||
|
function EditableControls() {
|
||||||
|
const {
|
||||||
|
isEditing,
|
||||||
|
getSubmitButtonProps,
|
||||||
|
getCancelButtonProps,
|
||||||
|
getEditButtonProps,
|
||||||
|
} = useEditableControls();
|
||||||
|
|
||||||
|
return (
|
||||||
|
isEditing && (
|
||||||
|
<ButtonGroup position={"absolute"} right={0} bottom={-8} size="sm">
|
||||||
|
<IconButton
|
||||||
|
boxShadow={"sm"}
|
||||||
|
rounded={"md"}
|
||||||
|
size={"xs"}
|
||||||
|
icon={<CheckIcon />}
|
||||||
|
{...getSubmitButtonProps()}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
boxShadow={"sm"}
|
||||||
|
rounded={"md"}
|
||||||
|
size={"xs"}
|
||||||
|
icon={<CloseIcon />}
|
||||||
|
{...getCancelButtonProps()}
|
||||||
|
/>
|
||||||
|
</ButtonGroup>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Array of fields to render
|
||||||
|
const fields = [
|
||||||
|
{ name: "firstName", label: "First Name", defaultValue: "Faisal" },
|
||||||
|
{ name: "lastName", label: "Last Name", defaultValue: "Aljalahma" },
|
||||||
|
{ name: "email", label: "Email Address", defaultValue: "f.aljalahma@tanamicapital.com" },
|
||||||
|
{ name: "mobile", label: "Mobile Number", defaultValue: "9898767876" },
|
||||||
|
{ name: "role", label: "Role", defaultValue: "Maker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<VStack
|
||||||
|
// bg={'forestGreen.50'}
|
||||||
|
overflowY={"scroll"}
|
||||||
|
overflowX={"hidden"}
|
||||||
|
height={"100vh"}
|
||||||
|
pb={10}
|
||||||
|
w={"100%"}
|
||||||
|
{...OPACITY_ON_LOAD}
|
||||||
|
>
|
||||||
|
<VStack alignItems={"start"} w={"50%"} mt={4}>
|
||||||
|
<Heading as="h3" size="md">
|
||||||
|
Profile setting
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<Text color={"gray.500"} fontSize="xs">
|
||||||
|
Manage your personal information, and control which information other
|
||||||
|
people see and apps may access.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Heading as="h3" size="sm">
|
||||||
|
Profile photo and role
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
mb={6}
|
||||||
|
rounded={"md"}
|
||||||
|
boxShadow={"base"}
|
||||||
|
bg={"#fff"}
|
||||||
|
minH={200}
|
||||||
|
w={"100%"}
|
||||||
|
display={"flex"}
|
||||||
|
flexDirection={"column"}
|
||||||
|
alignItems={"start"}
|
||||||
|
p={8}
|
||||||
|
pb={6}
|
||||||
|
pe={6}
|
||||||
|
>
|
||||||
|
<HStack>
|
||||||
|
<Avatar size="xl" name="Faisal Aljalahma" src={logoMini} me={4} />
|
||||||
|
<VStack alignItems={"start"} gap={0}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"md"}
|
||||||
|
color={"gray.700"}
|
||||||
|
fontWeight={500}
|
||||||
|
>
|
||||||
|
Faisal Aljalahma
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
color={"gray.500"}
|
||||||
|
fontWeight={400}
|
||||||
|
>
|
||||||
|
f.aljalahma@tanamicapital.com
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
<HStack mt={3} w={"100%"} justifyContent={"flex-end"}>
|
||||||
|
<VStack alignItems={"flex-start"} gap={1}>
|
||||||
|
<Text
|
||||||
|
display={"flex"}
|
||||||
|
alignItems={"center"}
|
||||||
|
gap={1}
|
||||||
|
color={"gray.500"}
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"11px"}
|
||||||
|
>
|
||||||
|
You can see your role below ? <InfoIcon />
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
display={"flex"}
|
||||||
|
color={"gray.700"}
|
||||||
|
alignItems={"center"}
|
||||||
|
gap={2}
|
||||||
|
as={"span"}
|
||||||
|
fontSize={"md"}
|
||||||
|
fontWeight={500}
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
<Icon as={FaEarthAmericas} /> Maker
|
||||||
|
</Text>
|
||||||
|
</VStack>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Heading as="h3" size="sm">
|
||||||
|
About you
|
||||||
|
</Heading>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
rounded="md"
|
||||||
|
boxShadow="base"
|
||||||
|
bg="#fff"
|
||||||
|
w="100%"
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="flex-start"
|
||||||
|
p={6}
|
||||||
|
gap={0}
|
||||||
|
|
||||||
|
pb={6}
|
||||||
|
>
|
||||||
|
|
||||||
|
{fields?.map((item) => (
|
||||||
|
<VStack alignItems={"flex-start"} w={"100%"} gap={1.5} mb={6} key={item?.label}>
|
||||||
|
<Text
|
||||||
|
as={"span"}
|
||||||
|
fontSize="xs"
|
||||||
|
fontWeight="semibold"
|
||||||
|
color={"gray.500"}
|
||||||
|
>
|
||||||
|
{item?.label}
|
||||||
|
</Text>
|
||||||
|
<Editable
|
||||||
|
position={"relative"}
|
||||||
|
gap={0}
|
||||||
|
defaultValue={item?.defaultValue}
|
||||||
|
w="100%"
|
||||||
|
>
|
||||||
|
<EditablePreview
|
||||||
|
cursor={'pointer'}
|
||||||
|
p={2}
|
||||||
|
rounded={"sm"}
|
||||||
|
w={"100%"}
|
||||||
|
_hover={{
|
||||||
|
bg: "gray.100",
|
||||||
|
}}
|
||||||
|
fontSize="sm"
|
||||||
|
transition={"0.5s"}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
as={EditableInput}
|
||||||
|
ps={2}
|
||||||
|
size={'sm'}
|
||||||
|
fontSize="sm"
|
||||||
|
rounded={"sm"}
|
||||||
|
_focus={{
|
||||||
|
borderColor:"blue.500"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<EditableControls />
|
||||||
|
</Editable>
|
||||||
|
</VStack>
|
||||||
|
))}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
</VStack>
|
||||||
|
</VStack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Profile;
|
||||||
155
src/Pages/User/AddUser.jsx
Normal file
155
src/Pages/User/AddUser.jsx
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Box, useToast } from "@chakra-ui/react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import FormInputMain from "../../Components/FormInputMain";
|
||||||
|
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
|
||||||
|
// Validation schema
|
||||||
|
export const addSponser = yup.object().shape({
|
||||||
|
firstName: yup
|
||||||
|
.string()
|
||||||
|
.min(2, "First name must be at least 2 characters")
|
||||||
|
.max(35, "First name cannot exceed 35 characters")
|
||||||
|
.required("First name is required"),
|
||||||
|
|
||||||
|
lastName: yup
|
||||||
|
.string()
|
||||||
|
.min(2, "Last name must be at least 2 characters")
|
||||||
|
.max(35, "Last name cannot exceed 35 characters")
|
||||||
|
.required("Last name is required"),
|
||||||
|
|
||||||
|
emailAddress: yup
|
||||||
|
.string()
|
||||||
|
.email("Email address must be a valid email")
|
||||||
|
.required("Email address is required"),
|
||||||
|
mobileNumber: yup
|
||||||
|
.string()
|
||||||
|
.matches(/^[0-9]+$/, "Mobile number must be digits only")
|
||||||
|
.min(8, "Mobile number must be at least 8 digits")
|
||||||
|
.max(15, "Mobile number must be at most 15 digits")
|
||||||
|
.required("Mobile number is required"),
|
||||||
|
ISDcode: yup.string().required("ISD code is required"),
|
||||||
|
role_xid: yup.string().required("Role ID is required"), // Assuming role_xid is a required string field
|
||||||
|
});
|
||||||
|
|
||||||
|
// Debounce function (if needed)
|
||||||
|
export function debounce(func, delay) {
|
||||||
|
let debounceTimer;
|
||||||
|
return function (...args) {
|
||||||
|
clearTimeout(debounceTimer);
|
||||||
|
debounceTimer = setTimeout(() => func.apply(this, args), delay);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddUser = () => {
|
||||||
|
const toast = useToast();
|
||||||
|
const params = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const id = params?.id;
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [alert, setAlert] = useState(false);
|
||||||
|
const [form, setForm] = useState(null);
|
||||||
|
const [isSwitchOn, setIsSwitchOn] = useState(true);
|
||||||
|
|
||||||
|
// React Hook Form setup
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(addSponser),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form fields configuration
|
||||||
|
const formFields = [
|
||||||
|
{
|
||||||
|
label: "First Name",
|
||||||
|
placeHolder: " ",
|
||||||
|
name: "firstName",
|
||||||
|
type: "text",
|
||||||
|
isRequired: true,
|
||||||
|
section: "Add Users",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Last Name",
|
||||||
|
name: "lastName",
|
||||||
|
placeHolder: " ",
|
||||||
|
type: "text",
|
||||||
|
isRequired: true,
|
||||||
|
section: "Add Users",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Email address",
|
||||||
|
name: "emailAddress",
|
||||||
|
placeHolder: " ",
|
||||||
|
type: "email",
|
||||||
|
isRequired: true,
|
||||||
|
section: "Add Users",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Mobile Number",
|
||||||
|
name: "mobileNumber",
|
||||||
|
placeHolder: " ",
|
||||||
|
type: "number",
|
||||||
|
isRequired: true,
|
||||||
|
section: "Add Users",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "ISD Code",
|
||||||
|
name: "ISDcode",
|
||||||
|
placeHolder: " ",
|
||||||
|
type: "text",
|
||||||
|
isRequired: true,
|
||||||
|
section: "Add Users",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// Grouping fields by section (if needed)
|
||||||
|
const groupedFields = formFields.reduce((groups, field) => {
|
||||||
|
const { section } = field;
|
||||||
|
if (!groups[section]) {
|
||||||
|
groups[section] = [];
|
||||||
|
}
|
||||||
|
groups[section].push(field);
|
||||||
|
return groups;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
// const onSubmit = async (data) => {
|
||||||
|
// if (Object.keys(errors).length === 0) {
|
||||||
|
// setForm(data);
|
||||||
|
// setAlert(true);
|
||||||
|
// console.log(data); // Display the form data in the console
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
const onSubmit = async (data) => {
|
||||||
|
if (Object.keys(errors).length === 0) {
|
||||||
|
setForm(data);
|
||||||
|
setAlert(true);
|
||||||
|
console.log(data); // Display the form data in the console
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return isLoading ? (
|
||||||
|
<FullscreenLoaders />
|
||||||
|
) : (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14} mt={5}>
|
||||||
|
{/* Form Input */}
|
||||||
|
<FormInputMain
|
||||||
|
groupedFields={groupedFields}
|
||||||
|
control={control}
|
||||||
|
errors={errors}
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddUser;
|
||||||
286
src/Pages/User/User.jsx
Normal file
286
src/Pages/User/User.jsx
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
import {Badge, Box,Button,HStack,Input,Text,Tooltip,useToast,} from "@chakra-ui/react";
|
||||||
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
|
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||||
|
import NormalTable from '../../Components/DataTable/NormalTable'
|
||||||
|
import { Link, Link as RouterLink } from "react-router-dom";
|
||||||
|
import {AddIcon,DeleteIcon,EditIcon,} from "@chakra-ui/icons";
|
||||||
|
import Pagination from "../../Components/Pagination";
|
||||||
|
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||||
|
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import ToastBox from "../../Components/ToastBox";
|
||||||
|
// import { debounce } from "./AddSponser";
|
||||||
|
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||||
|
import { useDeleteSponserMutation, useGetSponserMasterQuery } from "../../Services/io.service";
|
||||||
|
import { generateSerialNumber } from "../../Constants/Constants";
|
||||||
|
|
||||||
|
export const formatDate = (date) => {
|
||||||
|
const d = new Date(date);
|
||||||
|
const year = d.getFullYear();
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
|
||||||
|
const day = String(d.getDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
return `${day}/${month}/${year}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const User = () => {
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const toast = useToast();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
const [actionId, setActionId] = useState(false);
|
||||||
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
const [deleteSponser] = useDeleteSponserMutation();
|
||||||
|
const { sponser, setSponser, slideFromRight } = useContext(GlobalStateContext);
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
const { data: sponsors, error, isLoading: isSponserLoading } = useGetSponserMasterQuery(
|
||||||
|
{
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
searchTerm: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log(sponsors?.data?.rows);
|
||||||
|
|
||||||
|
// ==============================[Table Filter]========================
|
||||||
|
|
||||||
|
const filteredData = sponsors?.data?.rows?.filter((item) => {
|
||||||
|
const name = item.sponsorName;
|
||||||
|
const searchLower = searchTerm?.toLowerCase();
|
||||||
|
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||||
|
return nameMatches;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ====================================================[Table Setup]================================================================
|
||||||
|
|
||||||
|
const tableHeadRow = [
|
||||||
|
"Sr No",
|
||||||
|
"First Name",
|
||||||
|
"Last Name",
|
||||||
|
"Email Address",
|
||||||
|
"Action",
|
||||||
|
];
|
||||||
|
|
||||||
|
const extractedArray = sponsors?.data?.rows?.map((item, index) => ({
|
||||||
|
"Sr No": (
|
||||||
|
<Text
|
||||||
|
w={'24px'}
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"gray.600"}
|
||||||
|
className="d-flex align-items-center fw-bold web-text-small"
|
||||||
|
>
|
||||||
|
{/* {item.id} */}
|
||||||
|
{generateSerialNumber(index,currentPage, pageSize )}
|
||||||
|
|
||||||
|
</Text>),
|
||||||
|
"First Name": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.sponsorName}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
|
||||||
|
"Last Name": (
|
||||||
|
<Text
|
||||||
|
justifyContent={slideFromRight ? "right" : "left"}
|
||||||
|
as={"span"}
|
||||||
|
color={"teal.900"}
|
||||||
|
fontWeight={"500"}
|
||||||
|
className="d-flex align-items-center web-text-small"
|
||||||
|
>
|
||||||
|
{item.sponsorName}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
|
||||||
|
"Email Address": (
|
||||||
|
<Box isTruncated={true}>
|
||||||
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
|
{item.email ? item.email : "---" }
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
Action: (
|
||||||
|
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||||
|
<Tooltip
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label="Edit"
|
||||||
|
bg="#fff"
|
||||||
|
color={"blue.500"}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => navigate(`/sponser/add-sponser/${item.id}`)}
|
||||||
|
// _hover={{ color: "blue.500" }}
|
||||||
|
// color="blue.400"
|
||||||
|
rounded={"sm"}
|
||||||
|
size={"xs"}
|
||||||
|
colorScheme="blue"
|
||||||
|
>
|
||||||
|
<EditIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={"xs"}
|
||||||
|
label="Delete"
|
||||||
|
bg="#fff"
|
||||||
|
color={"red.500"}
|
||||||
|
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item?.id);
|
||||||
|
setDeleteAlert(true);
|
||||||
|
}}
|
||||||
|
// _hover={{ color: "red.500" }}
|
||||||
|
// color="red"
|
||||||
|
rounded={"sm"}
|
||||||
|
size={"xs"}
|
||||||
|
colorScheme="red"
|
||||||
|
variant={'solid'}
|
||||||
|
>
|
||||||
|
<DeleteIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// =========================== [Delete Function] =================================
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
console.log(actionId);
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await deleteSponser(actionId);
|
||||||
|
console.log(response?.data);
|
||||||
|
if(response?.error?.data?.code === 400){
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={response?.error?.data?.message} status={'warn'} />,
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
} else if(response?.data?.statusCode === 201 || response?.data?.statusCode === 200){
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={response?.data?.message} status={'error'} />,
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
setDeleteAlert(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||||
|
<Box bg="white.500">
|
||||||
|
<HStack
|
||||||
|
display={"flex"}
|
||||||
|
justifyContent={"space-between"}
|
||||||
|
ps={1}
|
||||||
|
pe={1}
|
||||||
|
pb={4}
|
||||||
|
pt={4}
|
||||||
|
spacing="24px"
|
||||||
|
>
|
||||||
|
|
||||||
|
{/* =======================[Search Input]======================== */}
|
||||||
|
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
width={300}
|
||||||
|
placeholder="Search..."
|
||||||
|
size="sm"
|
||||||
|
rounded="sm"
|
||||||
|
focusBorderColor="green.500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<HStack display={"flex"} alignItems={"center"}>
|
||||||
|
|
||||||
|
{/* ====================[Pagination]===================== */}
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
isLoading={isSponserLoading}
|
||||||
|
pageSize={pageSize}
|
||||||
|
setPageSize={setPageSize}
|
||||||
|
currentPage={currentPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
totalItems={sponsors?.data?.totalItems} />
|
||||||
|
|
||||||
|
{/* =====================[Add Button]===================== */}
|
||||||
|
|
||||||
|
<Link to={"/users/add-user"}>
|
||||||
|
<Button
|
||||||
|
leftIcon={<AddIcon />}
|
||||||
|
colorScheme={"forestGreen"}
|
||||||
|
rounded={"sm"}
|
||||||
|
fontSize={'xs'}
|
||||||
|
size={"sm"}
|
||||||
|
>
|
||||||
|
Add User
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</HStack>
|
||||||
|
</HStack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* =================== [Data Table] ===================== */}
|
||||||
|
|
||||||
|
<NormalTable
|
||||||
|
emptyMessage={`We don't have any Sponers `}
|
||||||
|
tableHeadRow={tableHeadRow}
|
||||||
|
data={extractedArray}
|
||||||
|
isLoading={isSponserLoading}
|
||||||
|
viewActionId={actionId}
|
||||||
|
setViewActionId={setActionId}
|
||||||
|
setMouseEnteredId={setMouseEnteredId}
|
||||||
|
setMouseEntered={setMouseEntered}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* ======================== [Modal] ======================== */}
|
||||||
|
|
||||||
|
<CustomAlertDialog
|
||||||
|
onClose={() => setDeleteAlert(false)}
|
||||||
|
isOpen={deleteAlert}
|
||||||
|
message={"Are you sure you want to delete sponers?"}
|
||||||
|
alertHandler={handleDelete}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default User;
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import welcome from '../assets/welcome.avif';
|
|
||||||
import welcome2 from '../assets/welcome2.avif';
|
|
||||||
import welcome3 from '../assets/welcome3.avif';
|
|
||||||
import welcome4 from '../assets/welcome4.avif';
|
|
||||||
import { Box, Button, Image } from '@chakra-ui/react';
|
|
||||||
import logo from "../../src/assets/logo.png"
|
|
||||||
|
|
||||||
const Welcome = () => {
|
|
||||||
return (
|
|
||||||
<Box position="relative" h="100vh">
|
|
||||||
<div id="carouselExampleSlidesOnly" className="carousel slide" data-bs-ride="carousel">
|
|
||||||
<div className="carousel-inner">
|
|
||||||
<div className="carousel-item active" data-bs-interval="3000">
|
|
||||||
<img src={welcome4} className="d-block w-100" alt="Welcome 2" />
|
|
||||||
</div>
|
|
||||||
<div className="carousel-item" data-bs-interval="3000">
|
|
||||||
<img src={welcome3} className="d-block w-100" alt="Welcome 3" />
|
|
||||||
</div>
|
|
||||||
<div className="carousel-item" data-bs-interval="3000">
|
|
||||||
<img src={welcome2} className="d-block w-100" alt="Welcome 4" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* <a className="carousel-control-prev" href="#carouselExampleSlidesOnly" role="button" data-bs-slide="prev">
|
|
||||||
<span className="carousel-control-prev-icon" aria-hidden="true"></span>
|
|
||||||
<span className="visually-hidden">Previous</span>
|
|
||||||
</a>
|
|
||||||
<a className="carousel-control-next" href="#carouselExampleSlidesOnly" role="button" data-bs-slide="next">
|
|
||||||
<span className="carousel-control-next-icon" aria-hidden="true"></span>
|
|
||||||
<span className="visually-hidden">Next</span>
|
|
||||||
</a> */}
|
|
||||||
</div>
|
|
||||||
<Box
|
|
||||||
opacity={1}
|
|
||||||
bgGradient="linear(to-b, rgba(0, 0, 0, 0.5), #0047178e 100%)"
|
|
||||||
zIndex={999}
|
|
||||||
position="absolute"
|
|
||||||
top={0}
|
|
||||||
left={0}
|
|
||||||
w="100%"
|
|
||||||
h="100%"
|
|
||||||
display={'flex'}
|
|
||||||
justifyContent={'center'}
|
|
||||||
alignItems={'center'}
|
|
||||||
>
|
|
||||||
<Image src={logo} />
|
|
||||||
|
|
||||||
{/* <Box
|
|
||||||
position="absolute"
|
|
||||||
bottom={12}
|
|
||||||
right={0}
|
|
||||||
p={4} // Adjust padding as needed
|
|
||||||
>
|
|
||||||
<Button color={'#004717'} size={'lg'} bg="white" variant="solid">
|
|
||||||
Let's get started
|
|
||||||
</Button>
|
|
||||||
</Box> */}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Welcome;
|
|
||||||
298
src/Pages/WithDrawal/DrawalRequest/DrawalRequestApprove.jsx
Normal file
298
src/Pages/WithDrawal/DrawalRequest/DrawalRequestApprove.jsx
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Heading,
|
||||||
|
HStack,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
import {
|
||||||
|
useGetDrawalRequestByIdQuery,
|
||||||
|
useUpdateDrawalRequestMutation,
|
||||||
|
} from "../../../Services/drawal.request.service";
|
||||||
|
import CurrencyInput from "../../../Components/CurrencyInput";
|
||||||
|
import { GrClose } from "react-icons/gr";
|
||||||
|
|
||||||
|
const FILE_TYPES = ["image/jpeg", "image/png", "image/gif"];
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
investorAmount: yup.string().required("Investor amount is required"),
|
||||||
|
comment: yup.string().notRequired(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const DrawalRequestApprove = ({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
firstField,
|
||||||
|
id,
|
||||||
|
data: requestData,
|
||||||
|
}) => {
|
||||||
|
const toast = useToast();
|
||||||
|
const [file, setFile] = useState();
|
||||||
|
const [isBtnLoading, setIsBtnLoading] = useState(false);
|
||||||
|
|
||||||
|
const [updateDrawalRequest] = useUpdateDrawalRequestMutation();
|
||||||
|
const { data, isLoading } = useGetDrawalRequestByIdQuery(id, {
|
||||||
|
skip: !id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const filteredData = data?.dat;
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
const investorAmount = parseFloat(data?.data?.investorAmount);
|
||||||
|
reset({
|
||||||
|
investorAmount: Math.abs(investorAmount),
|
||||||
|
accountName: data?.data?.accountName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [id, data, reset]);
|
||||||
|
|
||||||
|
const onSubmit = async (data) => {
|
||||||
|
setIsBtnLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await updateDrawalRequest({ id, data });
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false);
|
||||||
|
} else if (res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => <ToastBox message={res?.data?.message} />,
|
||||||
|
});
|
||||||
|
setIsBtnLoading(false);
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
|
heandleOnClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const selectedFile = event.target.files[0];
|
||||||
|
setFile(selectedFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (data) {
|
||||||
|
// reset({
|
||||||
|
// investorAmount: data?.data?.dataValues?.investorAmount,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }, [data, reset]);
|
||||||
|
|
||||||
|
const heandleOnClose = () => {
|
||||||
|
reset({
|
||||||
|
investorAmount: "",
|
||||||
|
});
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={heandleOnClose}
|
||||||
|
initialFocusRef={firstField}
|
||||||
|
>
|
||||||
|
<ModalOverlay />
|
||||||
|
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<HStack justifyContent={"space-between"}>
|
||||||
|
<ModalHeader fontSize={"md"}>Confirm</ModalHeader>
|
||||||
|
<Button onClick={onClose} bg={"transparent"} _hover={{backgroundColor:"transparent"}}>
|
||||||
|
<GrClose />
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
{/* <ModalCloseButton /> */}
|
||||||
|
{isLoading ? (
|
||||||
|
<FullscreenLoaders height={"50vh"} />
|
||||||
|
) : (
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
{/* <FormControl mb={5} isRequired>
|
||||||
|
<FormLabel fontSize="sm">
|
||||||
|
Withdrawal Amount{" "}
|
||||||
|
<Badge colorScheme="green">
|
||||||
|
{filteredData?.currencyCode}
|
||||||
|
</Badge>
|
||||||
|
</FormLabel>
|
||||||
|
<Input
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="investorAmount"
|
||||||
|
{...register("investorAmount")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="number"
|
||||||
|
size="sm"
|
||||||
|
placeholder={"100,000"}
|
||||||
|
textAlign={"right"}
|
||||||
|
// readOnly
|
||||||
|
/>
|
||||||
|
{errors.investorAmount && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.investorAmount.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl> */}
|
||||||
|
{/* =======================[ Coma is acchived using Controller ]================================ */}
|
||||||
|
<FormControl mb={5} isRequired>
|
||||||
|
<FormLabel fontSize={"sm"}>Withdrawal Amount</FormLabel>
|
||||||
|
<Controller
|
||||||
|
name="investorAmount"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CurrencyInput
|
||||||
|
{...field}
|
||||||
|
textAlign={"right"}
|
||||||
|
fontSize={"sm"}
|
||||||
|
type="number"
|
||||||
|
size={"sm"}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.investorAmount && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.investorAmount.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<Heading fontSize="sm" fontWeight={600} mb={4}>
|
||||||
|
Investor Account Details
|
||||||
|
</Heading>
|
||||||
|
<Box display={"flex"} mb={3}>
|
||||||
|
<Text fontSize="xs" mb={0} fontWeight={500} me={2} w={"110px"}>
|
||||||
|
IBAN:
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" mb={0}>
|
||||||
|
{data?.data?.bank_payouts?.IBANnumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box display={"flex"} mb={3}>
|
||||||
|
<Text fontSize="xs" mb={0} fontWeight={500} me={2} w={"110px"}>
|
||||||
|
Account No:
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" mb={0}>
|
||||||
|
{data?.data?.bank_payouts?.accountNumber}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box display={"flex"} mb={3}>
|
||||||
|
<Text fontSize="xs" mb={0} fontWeight={500} me={2} w={"110px"}>
|
||||||
|
Bank Name:
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" mb={0}>
|
||||||
|
{data?.data?.bank_payouts?.bankName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box display={"flex"} mb={3}>
|
||||||
|
<Text fontSize="xs" mb={0} fontWeight={500} me={2} w={"110px"}>
|
||||||
|
Account Name:
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" mb={0}>
|
||||||
|
{data?.data?.bank_payouts?.accountName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box display={"flex"} mb={3}>
|
||||||
|
<Text fontSize="xs" mb={0} fontWeight={500} me={2} w={"110px"}>
|
||||||
|
SWIFT Code:
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" mb={0}>
|
||||||
|
{data?.data?.bank_payouts?.swiftCode}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box display={"flex"} mb={5}>
|
||||||
|
<Text fontSize="xs" mb={0} fontWeight={500} me={2} w={"110px"}>
|
||||||
|
Bank Address:
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" mb={0}>
|
||||||
|
{data?.data?.bank_payouts?.bankAddress}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box display={"flex"} mb={5}>
|
||||||
|
<Text fontSize="xs" mb={0} fontWeight={500} me={2} w={"110px"}>
|
||||||
|
Bank Nick Name:
|
||||||
|
</Text>
|
||||||
|
<Text fontSize="xs" mb={0}>
|
||||||
|
{data?.data?.bank_payouts?.bankNickName}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<FormControl mb={4}>
|
||||||
|
<FormLabel fontSize="sm">Comments</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={5}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="comment"
|
||||||
|
{...register("comment")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="sm"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
{errors.comment && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comment.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DrawalRequestApprove;
|
||||||
140
src/Pages/WithDrawal/DrawalRequest/DrawalRequestReject.jsx
Normal file
140
src/Pages/WithDrawal/DrawalRequest/DrawalRequestReject.jsx
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
FormLabel,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
Textarea,
|
||||||
|
useDisclosure,
|
||||||
|
useToast,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import ToastBox from "../../../Components/ToastBox";
|
||||||
|
import { useDepositRejectMutation } from "../../../Services/drawal.request.service";
|
||||||
|
|
||||||
|
export const conformModalSchema = yup.object().shape({
|
||||||
|
comments: yup.string().required("Comment is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const DrawalRequestReject = ({ isOpen, onClose, firstField ,id}) => {
|
||||||
|
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
reset,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(conformModalSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ depositReject ] = useDepositRejectMutation()
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = async(data) => {
|
||||||
|
setIsBtnLoading(true)
|
||||||
|
try {
|
||||||
|
const res = await depositReject({ id ,data})
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
|
||||||
|
}else if(res?.data?.statusCode === 200) {
|
||||||
|
toast({
|
||||||
|
render: () => (
|
||||||
|
<ToastBox message={res?.data?.message} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
heandleOnClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const heandleOnClose = () =>{
|
||||||
|
reset()
|
||||||
|
onClose()
|
||||||
|
setIsBtnLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||||
|
<ModalOverlay />
|
||||||
|
<ModalContent pb={4}>
|
||||||
|
<ModalHeader fontSize={"md"}>Reject</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<ModalBody>
|
||||||
|
<FormControl mb={4} isRequired>
|
||||||
|
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||||
|
<Textarea
|
||||||
|
rows={6}
|
||||||
|
focusBorderColor="green.400"
|
||||||
|
name="comments"
|
||||||
|
{...register("comments")}
|
||||||
|
fontSize="sm"
|
||||||
|
type="textarea"
|
||||||
|
size="md"
|
||||||
|
placeholder={"Enter your comments...."}
|
||||||
|
rounded={"md"}
|
||||||
|
resize={"none"}
|
||||||
|
/>
|
||||||
|
{errors.comments && (
|
||||||
|
<Text fontSize="xs" color="red">
|
||||||
|
{errors.comments.message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button
|
||||||
|
colorScheme="gray"
|
||||||
|
mr={3}
|
||||||
|
onClick={onClose}
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme="forestGreen"
|
||||||
|
variant="solid"
|
||||||
|
size={"sm"}
|
||||||
|
rounded={"sm"}
|
||||||
|
isLoading={isBtnLoading}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Box>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DrawalRequestReject;
|
||||||
|
|
||||||
@@ -7,30 +7,99 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
useDisclosure,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import React, { useContext, useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||||
import DataTable from "../../Components/DataTable/DataTable";
|
import DataTable from "../../../Components/DataTable/DataTable";
|
||||||
import Pagination from "../../Components/Pagination";
|
import Pagination from "../../../Components/Pagination";
|
||||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||||
import { formatDate } from "../../Components/Functions/UTCConvertor";
|
|
||||||
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
|
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
|
||||||
// import { formatDate } from "../../Components/Functions/UTCConvertor";
|
import DrawalRequestReject from "./DrawalRequestReject";
|
||||||
|
import { useGetDrawalRequestQuery } from "../../../Services/drawal.request.service";
|
||||||
|
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||||
|
import NormalTable from "../../../Components/DataTable/NormalTable"
|
||||||
|
import DrawalRequestApprove from "./DrawalRequestApprove";
|
||||||
|
import { formatDate } from "../../../Components/Functions/UTCConvertor";
|
||||||
|
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||||
|
|
||||||
const PendingRequest = () => {
|
const PendingRequest = () => {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { slideFromRight, pendingRequest, setPendingRequest } =
|
const { slideFromRight, pendingRequest, setPendingRequest } =
|
||||||
useContext(GlobalStateContext);
|
useContext(GlobalStateContext);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
const [actionId, setActionId] = useState(false);
|
const [actionId, setActionId] = useState(false);
|
||||||
const [mouseEntered, setMouseEntered] = useState(false);
|
const [mouseEntered, setMouseEntered] = useState(false);
|
||||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||||
|
|
||||||
|
|
||||||
|
const formatDate = (date) => {
|
||||||
|
return new Date(date).toLocaleDateString('en-GB', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
isOpen: isConfirmOpen,
|
||||||
|
onOpen: onConfirmOpen,
|
||||||
|
onClose: onConfirmClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
const {
|
||||||
|
isOpen: isRejectOpen,
|
||||||
|
onOpen: onRejectOpen,
|
||||||
|
onClose: onRejectClose,
|
||||||
|
} = useDisclosure();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =========================== [Use State] =============================
|
||||||
|
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||||
|
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
|
// Debounce the search term to avoid making a request on every keystroke
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedSearchTerm(searchTerm);
|
||||||
|
}, 500); // Adjust delay as needed
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
}, [searchTerm]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading: drawalRequestLoading,
|
||||||
|
error,
|
||||||
|
refetch
|
||||||
|
} = useGetDrawalRequestQuery({
|
||||||
|
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||||
|
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||||
|
search: debouncedSearchTerm,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Use useEffect to refetch data when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
refetch();
|
||||||
|
}, [refetch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
// Simulate loading
|
// Simulate loading
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -41,9 +110,9 @@ const PendingRequest = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ====================================================[Table Filter]================================================================
|
// ====================================================[Table Filter]================================================================
|
||||||
const filteredData = pendingRequest.filter((item) => {
|
const filteredData = data?.data?.rows.filter((item) => {
|
||||||
// Filter by name (case insensitive)
|
// Filter by name (case insensitive)
|
||||||
const name = item.clientId;
|
const name = item.firstName;
|
||||||
const searchLower = searchTerm.toLowerCase();
|
const searchLower = searchTerm.toLowerCase();
|
||||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||||
|
|
||||||
@@ -57,6 +126,8 @@ const PendingRequest = () => {
|
|||||||
// (statusFilter === "inactive" && status === false);
|
// (statusFilter === "inactive" && status === false);
|
||||||
|
|
||||||
return nameMatches;
|
return nameMatches;
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ====================================================[Table Setup]================================================================
|
// ====================================================[Table Setup]================================================================
|
||||||
@@ -67,15 +138,17 @@ const PendingRequest = () => {
|
|||||||
"First Name",
|
"First Name",
|
||||||
"Last Name",
|
"Last Name",
|
||||||
"Country",
|
"Country",
|
||||||
"Phone Number",
|
// "Phone Number",
|
||||||
"Currency",
|
"Amount in Wallet Pre-Withdrawal",
|
||||||
"Withdrawal Amount",
|
"Withdrawal Amount",
|
||||||
"Amount in Investor currency",
|
// "Currency",
|
||||||
|
// "Withdrawal Amount",
|
||||||
"Action",
|
"Action",
|
||||||
];
|
];
|
||||||
|
|
||||||
const [extractedArray, setExtractedArray] = useState(
|
|
||||||
filteredData?.map((item, index) => ({
|
|
||||||
|
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||||
// id: item?.id,
|
// id: item?.id,
|
||||||
"Sr.no": (
|
"Sr.no": (
|
||||||
<Text
|
<Text
|
||||||
@@ -86,7 +159,7 @@ const PendingRequest = () => {
|
|||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{index + 1}
|
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Date": (
|
"Date": (
|
||||||
@@ -98,7 +171,7 @@ const PendingRequest = () => {
|
|||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{item.date}
|
{formatDate(item?.createdAt)}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"Client ID": (
|
"Client ID": (
|
||||||
@@ -110,11 +183,11 @@ const PendingRequest = () => {
|
|||||||
fontWeight={"500"}
|
fontWeight={"500"}
|
||||||
className="d-flex align-items-center web-text-small"
|
className="d-flex align-items-center web-text-small"
|
||||||
>
|
>
|
||||||
{item.clientId}
|
{item.clientReference_id}
|
||||||
</Text>
|
</Text>
|
||||||
),
|
),
|
||||||
"First Name": (
|
"First Name": (
|
||||||
<Box isTruncated={true} w={'50px'}>
|
<Box isTruncated={true} w={'80px'}>
|
||||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||||
{item.firstName}
|
{item.firstName}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -130,40 +203,59 @@ const PendingRequest = () => {
|
|||||||
Country: (
|
Country: (
|
||||||
<Box w={"70px"} isTruncated={true}>
|
<Box w={"70px"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.country}
|
{item.countryName}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Phone Number": (
|
"Phone Number": (
|
||||||
<Box w={"70px"} isTruncated={true}>
|
<Box w={"100px"} isTruncated={true}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.phoneNumber}
|
{item.mobileNumber}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Currency: (
|
// Currency: (
|
||||||
<Box w={"50px"} isTruncated={true}>
|
// <Box w={"60px"} isTruncated={true}>
|
||||||
|
// <Text as={"span"} color={"teal.900"}>
|
||||||
|
// <Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge>
|
||||||
|
// </Text>
|
||||||
|
// </Box>
|
||||||
|
// ),
|
||||||
|
// "Withdrawal Amount": (
|
||||||
|
// <Box w={"80px"} isTruncated={true}>
|
||||||
|
// <Text as={"span"} color={"teal.900"}>
|
||||||
|
// {parseFloat(item?.USDAmount || 0).toLocaleString(undefined, {
|
||||||
|
// minimumFractionDigits: 2,
|
||||||
|
// maximumFractionDigits: 2,
|
||||||
|
// })}💲
|
||||||
|
// {/* {item.USDAmount} */}
|
||||||
|
// </Text>
|
||||||
|
// </Box>
|
||||||
|
// ),
|
||||||
|
"Amount in Wallet Pre-Withdrawal": (
|
||||||
|
<Box w={"100px"} isTruncated={true} display={'flex'} justifyContent={'end'}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
<Badge px={2} py={1}>{item.currency}</Badge>
|
{/* {item.investorAmount} */}
|
||||||
|
{parseFloat(item?.wallet_balance || 0).toLocaleString(undefined, {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
})}<Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
"Withdrawal Amount": (
|
"Withdrawal Amount": (
|
||||||
<Box w={"50px"} isTruncated={true}>
|
<Box w={"130px"} isTruncated={true} display={'flex'} justifyContent={'end'}>
|
||||||
<Text as={"span"} color={"teal.900"}>
|
<Text as={"span"} color={"teal.900"}>
|
||||||
{item.withDrawalAmount}
|
{/* {item.investorAmount} */}
|
||||||
</Text>
|
{parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
|
||||||
</Box>
|
minimumFractionDigits: 2,
|
||||||
),
|
maximumFractionDigits: 2,
|
||||||
"Amount in Investor currency": (
|
})}<Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge>
|
||||||
<Box w={"70px"} isTruncated={true}>
|
|
||||||
<Text as={"span"} color={"teal.900"}>
|
|
||||||
{item.amountcurrency}
|
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
Action: (
|
Action: (
|
||||||
<Box display={"flex"} justifyContent={"space-around"} gap={2}>
|
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
fontSize={"xs"}
|
fontSize={"xs"}
|
||||||
@@ -172,18 +264,25 @@ const PendingRequest = () => {
|
|||||||
color={"green.500"}
|
color={"green.500"}
|
||||||
placement="left-start"
|
placement="left-start"
|
||||||
>
|
>
|
||||||
<Badge
|
<Button
|
||||||
colorScheme="forestGreen"
|
// colorScheme="forestGreen"
|
||||||
color="green.500"
|
// color="green.500"
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
size={"xs"}
|
size={"xs"}
|
||||||
textTransform={"inherit"}
|
textTransform={"inherit"}
|
||||||
fontWeight={500}
|
fontWeight={500}
|
||||||
px={2}
|
px={2}
|
||||||
py={1}
|
py={1}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item.id);
|
||||||
|
onConfirmOpen();
|
||||||
|
}}
|
||||||
|
colorScheme="green"
|
||||||
|
variant={"solid"}
|
||||||
|
cursor={"pointer"}
|
||||||
>
|
>
|
||||||
<CheckIcon fontSize={'12px'} />
|
<CheckIcon fontSize={"12px"} />
|
||||||
</Badge>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
@@ -193,23 +292,27 @@ const PendingRequest = () => {
|
|||||||
color={"red.500"}
|
color={"red.500"}
|
||||||
placement="left-start"
|
placement="left-start"
|
||||||
>
|
>
|
||||||
<Badge
|
<Button
|
||||||
colorScheme="red"
|
colorScheme="red"
|
||||||
color="red.500"
|
// color="red.500"
|
||||||
rounded={"sm"}
|
rounded={"sm"}
|
||||||
size={"xs"}
|
size={"xs"}
|
||||||
textTransform={"inherit"}
|
textTransform={"inherit"}
|
||||||
fontWeight={500}
|
fontWeight={500}
|
||||||
px={2}
|
px={2}
|
||||||
|
onClick={() => {
|
||||||
|
setActionId(item.id);
|
||||||
|
onRejectOpen();
|
||||||
|
}}
|
||||||
py={1}
|
py={1}
|
||||||
|
// variant={"solid"}
|
||||||
>
|
>
|
||||||
<CloseIcon fontSize={'10px'} />
|
<CloseIcon fontSize={"10px"} />
|
||||||
</Badge>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
}))
|
}));
|
||||||
);
|
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
const updatedSponsors = sponser.filter(
|
const updatedSponsors = sponser.filter(
|
||||||
@@ -247,17 +350,22 @@ const PendingRequest = () => {
|
|||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HStack display={"flex"} alignItems={"center"}>
|
<Pagination
|
||||||
<Pagination totalItems={10} />
|
isLoading={drawalRequestLoading}
|
||||||
</HStack>
|
pageSize={pageSize}
|
||||||
|
setPageSize={setPageSize}
|
||||||
|
currentPage={currentPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
totalItems={data?.data?.totalItems}
|
||||||
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<DataTable
|
<NormalTable
|
||||||
|
isLoading={drawalRequestLoading}
|
||||||
emptyMessage={`We don't have any Sponers `}
|
emptyMessage={`We don't have any Sponers `}
|
||||||
tableHeadRow={tableHeadRow}
|
tableHeadRow={tableHeadRow}
|
||||||
data={extractedArray}
|
data={extractedArray}
|
||||||
isLoading={isLoading}
|
|
||||||
viewActionId={actionId}
|
viewActionId={actionId}
|
||||||
setViewActionId={setActionId}
|
setViewActionId={setActionId}
|
||||||
// totalPages={10}
|
// totalPages={10}
|
||||||
@@ -273,6 +381,18 @@ const PendingRequest = () => {
|
|||||||
alertHandler={handleDelete}
|
alertHandler={handleDelete}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
|
<DrawalRequestApprove
|
||||||
|
// data={data?.data?.rows}
|
||||||
|
isOpen={isConfirmOpen}
|
||||||
|
onClose={onConfirmClose}
|
||||||
|
id={actionId}
|
||||||
|
// firstField={firstField}
|
||||||
|
/>
|
||||||
|
<DrawalRequestReject
|
||||||
|
isOpen={isRejectOpen}
|
||||||
|
onClose={onRejectClose}
|
||||||
|
id={actionId}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user