Compare commits

..

93 Commits

Author SHA1 Message Date
victorAnumudu 52358ce421 Button Centralized 2023-05-16 17:48:28 +01:00
tokslaw 3290fce6da Merge branch 'manage-active-jobs' of WrenchBoard/Users-Wrench into master 2023-05-16 14:11:59 +00:00
victorAnumudu 21e4221301 unused snippet of code cleaned up 2023-05-16 15:06:05 +01:00
victorAnumudu d9f1771045 'Merge master with branch` 2023-05-16 15:00:11 +01:00
victorAnumudu 119dfcde06 active jobs page implementation 2023-05-16 14:53:57 +01:00
CHIEFSOFT\ameye f6e37d0f14 My Task page 2023-05-16 06:45:53 -04:00
ameye 3b1dc859e0 Merge branch 'transfer-fund-page' of WrenchBoard/Users-Wrench into master 2023-05-16 10:33:00 +00:00
ameye a45d21cd2d Merge branch 'edit-delete-btn-position' of WrenchBoard/Users-Wrench into master 2023-05-16 10:32:51 +00:00
ameye 1774d07980 Merge branch 'broken-link' of WrenchBoard/Users-Wrench into master 2023-05-16 10:32:02 +00:00
Ebube 69ec1e3766 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into transfer-fund-page 2023-05-16 00:59:34 +01:00
Ebube 7e0f19212f manage pop up 2023-05-16 00:58:43 +01:00
victorAnumudu 5fd3940911 Fixed broken link on active job view button 2023-05-15 21:39:07 +01:00
victorAnumudu 4f1a4dd045 Delete/Edit Btn Position Changed 2023-05-15 21:16:18 +01:00
ameye f755786adc Merge branch 'transfer-fund-page' of WrenchBoard/Users-Wrench into master 2023-05-15 13:06:23 +00:00
Ebube 19f111c6a8 fixed button for family acc 2023-05-15 12:28:31 +01:00
CHIEFSOFT\ameye c877c70bf0 Active Jobs 2023-05-14 21:49:08 -04:00
CHIEFSOFT\ameye 7c2f90b1b8 active pending jobs 2023-05-14 13:33:08 -04:00
ameye 872ba05a01 Merge branch 'positioning-delete-edit-btn' of WrenchBoard/Users-Wrench into master 2023-05-14 12:06:35 +00:00
victorAnumudu 7083e67667 Positioned the delete and edit button in my jobs list 2023-05-14 07:33:46 +01:00
ameye 94e7c549df Merge branch 'job-page-layout-fix' of WrenchBoard/Users-Wrench into master 2023-05-13 14:48:37 +00:00
victorAnumudu 0d013c261b Job layout implemented 2023-05-13 14:04:40 +01:00
ameye 60eca6e703 Merge branch 'deleted-job-api-implementation' of WrenchBoard/Users-Wrench into master 2023-05-12 20:48:20 +00:00
victorAnumudu d51c9dc55d delete job api implementation 2023-05-12 21:07:17 +01:00
ameye c7985e6b48 Merge branch 'transfer-fund-page' of WrenchBoard/Users-Wrench into master 2023-05-12 19:00:31 +00:00
Ebube 985dc58f37 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into transfer-fund-page 2023-05-12 19:07:40 +01:00
Ebube d3a19d0a31 changed layout 2023-05-12 19:06:53 +01:00
tokslaw e1a7b8647b Merge branch 'delete-job-implementation' of WrenchBoard/Users-Wrench into master 2023-05-12 15:18:02 +00:00
victorAnumudu 77bc0ca795 delete job implemented 2023-05-12 16:06:59 +01:00
ameye 7a5e5580f9 Merge branch 'add-family-acc' of WrenchBoard/Users-Wrench into master 2023-05-12 08:46:22 +00:00
Ebube 666389cff6 cleanup 2023-05-12 09:06:42 +01:00
Ebube 3d084a99f3 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into add-family-acc 2023-05-12 08:56:55 +01:00
Ebube 6bb7da4639 fixed popup 2023-05-12 08:56:21 +01:00
CHIEFSOFT\ameye 2fd0aaa89c google login starter 2023-05-11 23:30:10 -04:00
CHIEFSOFT\ameye c21c67c336 balance page 2023-05-11 21:21:11 -04:00
ameye 9f8b9d317b Merge branch 'implementing-zero-state' of WrenchBoard/Users-Wrench into master 2023-05-11 21:05:09 +00:00
Ebube 5155efda1d Merge branch 'master' of into implementing-zero-state 2023-05-11 22:01:28 +01:00
CHIEFSOFT\ameye d002bee612 Balance Page 2023-05-11 16:52:02 -04:00
tokslaw 4ac4965dbe Merge branch 'add-job-page' of WrenchBoard/Users-Wrench into master 2023-05-11 20:38:32 +00:00
victorAnumudu 8132bb6f3f Add job implemented 2023-05-11 21:33:34 +01:00
CHIEFSOFT\ameye 63861ea32c Job Page 2023-05-11 11:05:13 -04:00
ameye bce3d1adea Merge branch 'table_horizontal_scroll' of WrenchBoard/Users-Wrench into master 2023-05-11 11:00:38 +00:00
victorAnumudu 8aa1e06592 horizontal scroll removed from medium screen display 2023-05-11 10:15:53 +01:00
ameye edf8f2ba8d Merge branch 'add-family-acc' of WrenchBoard/Users-Wrench into master 2023-05-10 19:01:57 +00:00
ameye f06be4b178 Merge branch 'joblist-popout' of WrenchBoard/Users-Wrench into master 2023-05-10 19:01:22 +00:00
victorAnumudu 2f8677877a title position flex style changed to space between 2023-05-10 19:39:07 +01:00
victorAnumudu 00271dc3cf title position changed 2023-05-10 19:36:56 +01:00
victorAnumudu 3a7498848a consoled value removed 2023-05-10 19:33:29 +01:00
victorAnumudu 8369dbfeff Job list popout added 2023-05-10 19:29:15 +01:00
Ebube 4e5cd7a40c another one 2023-05-10 17:32:26 +01:00
Ebube 4202941d43 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into add-family-acc 2023-05-10 17:28:30 +01:00
Ebube bd40a4c7c0 little optimization 2023-05-10 17:26:59 +01:00
ameye f3c4efa409 Merge branch 'add-family-acc' of WrenchBoard/Users-Wrench into master 2023-05-10 15:56:56 +00:00
Ebube b0dae469d5 Implemented zero state to all listings 2023-05-10 16:33:10 +01:00
Ebube 6a1d5f549f Merge branch 'master' into add-family-acc 2023-05-10 16:12:54 +01:00
Ebube 25f77eb6ba Fixed popup design and refresh list 2023-05-10 16:07:33 +01:00
ameye 1e0dbbfff7 Merge branch 'terms_agreement_apicall' of WrenchBoard/Users-Wrench into master 2023-05-10 12:39:28 +00:00
victorAnumudu 211276cccb start job posting API consumed 2023-05-10 13:20:47 +01:00
CHIEFSOFT\ameye 4d076dd649 Rem stats 2023-05-10 07:32:03 -04:00
CHIEFSOFT\ameye bb05100c68 Fix menu 2023-05-09 19:55:20 -04:00
ameye 9cecbbfcb1 Merge branch 'active-job-popout-style-fixed' of WrenchBoard/Users-Wrench into master 2023-05-09 22:02:39 +00:00
victorAnumudu c043eeebbe popout style fixed 2023-05-09 23:00:45 +01:00
ameye 3a3827e9aa Merge branch 'terms_and_agreement' of WrenchBoard/Users-Wrench into master 2023-05-09 19:37:35 +00:00
victorAnumudu f59c0c1522 terms and agreement implementation 2023-05-09 20:27:18 +01:00
ameye d7f3d10cdd Merge branch 'family-listings' of WrenchBoard/Users-Wrench into master 2023-05-09 15:51:06 +00:00
Ebube 900b51ace3 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into family-listings 2023-05-09 15:12:25 +01:00
Ebube 5e6d2f3db9 added auth links for login page 2023-05-09 15:03:29 +01:00
Ebube e49c7eb779 Almost complete 2023-05-09 14:59:25 +01:00
CHIEFSOFT\ameye 159ec53410 Stas compo 2023-05-09 08:17:30 -04:00
ameye a7ef1fe603 Merge branch 'add-family-acc' of WrenchBoard/Users-Wrench into master 2023-05-09 11:25:42 +00:00
Ebube 6dea851021 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into add-family-acc 2023-05-09 12:02:45 +01:00
Ebube 4eee3a4683 Add family acc 2023-05-09 11:59:49 +01:00
ameye a06cf0262e Merge branch 'active-jobs-popout' of WrenchBoard/Users-Wrench into master 2023-05-09 10:40:40 +00:00
victorAnumudu 85e3800e18 active jobs popout implemented 2023-05-09 10:38:02 +01:00
Olusesan Ameye 872ba3e0cc file name typo fix 2023-05-09 05:14:09 +00:00
ameye 9b240afa96 Merge branch 'task-bubble-length' of WrenchBoard/Users-Wrench into master 2023-05-08 21:36:02 +00:00
Ebube c50f8d10c0 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into task-bubble-length 2023-05-08 22:24:35 +01:00
Ebube cef0860a4b Mobile 2023-05-08 22:22:40 +01:00
tokslaw 1c7b107ac1 Merge branch 'job_menu_control' of WrenchBoard/Users-Wrench into master 2023-05-08 21:08:45 +00:00
victorAnumudu 0aefc601bb implemented job menu control based on post jobs date 2023-05-08 21:58:20 +01:00
ameye a202cfffe8 Merge branch 'pagination_alignment' of WrenchBoard/Users-Wrench into master 2023-05-08 20:25:24 +00:00
victorAnumudu 3624743c67 pagination display re-aligned 2023-05-08 21:13:00 +01:00
ameye efeb282468 Merge branch 'task-bubble-length' of WrenchBoard/Users-Wrench into master 2023-05-08 16:57:35 +00:00
Ebube 6583d2600b few cleanups 2023-05-08 17:25:55 +01:00
Ebube 25884c5194 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into task-bubble-length 2023-05-08 17:13:26 +01:00
Ebube dc288937ac Added the number 2023-05-08 17:12:37 +01:00
CHIEFSOFT\ameye 293c165ab9 Family starter 2023-05-08 10:38:08 -04:00
ameye 6b380d7ca5 Merge branch 'history_table' of WrenchBoard/Users-Wrench into master 2023-05-08 14:13:20 +00:00
victorAnumudu 4ff53fbfa1 added history table to history page 2023-05-08 12:52:21 +01:00
CHIEFSOFT\ameye e201d4726d Start job page 2023-05-08 07:19:56 -04:00
ameye 2786f41971 Merge branch 'pagination_implementation' of WrenchBoard/Users-Wrench into master 2023-05-08 11:08:50 +00:00
ameye a11ecd9f0c Merge branch 'login-home-links' of WrenchBoard/Users-Wrench into master 2023-05-08 11:07:32 +00:00
CHIEFSOFT\ameye a7d41f8a06 menu adjust 2023-05-07 18:22:07 -04:00
Ebube 6b5546579a login home links added 2023-05-07 15:01:49 +01:00
84 changed files with 4883 additions and 3604 deletions
+3
View File
@@ -31,5 +31,8 @@ REACT_APP_RESET_START_ERROR_TIMEOUT=3000
#NUMBER OF ITEMS PER PAGE
REACT_APP_ITEM_PER_PAGE=5
# Empty Listings
REACT_APP_ZERO_STATE=0
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
View File
+40 -51
View File
@@ -8,6 +8,7 @@
"name": "WrenchBoard-Users",
"version": "0.2.0",
"dependencies": {
"@react-oauth/google": "^0.11.0",
"@reduxjs/toolkit": "^1.8.2",
"@tailwindcss/line-clamp": "^0.3.1",
"@testing-library/jest-dom": "^5.11.4",
@@ -18,15 +19,15 @@
"chartjs": "^0.3.24",
"cors": "^2.8.5",
"faker": "^6.6.6",
"flutterwave-react-v3": "^1.3.0",
"formik": "^2.2.9",
"react": "^18.0.0",
"react": "^18.2.0",
"react-chartjs-2": "^4.1.0",
"react-countup": "^6.2.0",
"react-dom": "^18.0.0",
"react-lottie": "^1.2.3",
"react-redux": "^8.0.2",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.0.2",
"react-scripts": "5.0.0",
"react-scripts": "5.0.1",
"react-slick": "^0.29.0",
"react-toastify": "^9.0.1",
"redux": "^4.2.0",
@@ -3509,6 +3510,15 @@
}
}
},
"node_modules/@react-oauth/google": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@react-oauth/google/-/google-0.11.0.tgz",
"integrity": "sha512-yeypwdQCcFIAo43OqVOLBfUXuxmxt3xiybfP9h3smtBW4UeFXFVQDsq+d+GlbZFo0TpONPR2+KCk/KT1/pQnvQ==",
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@reduxjs/toolkit": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.1.tgz",
@@ -5476,20 +5486,6 @@
"babel-plugin-transform-react-remove-prop-types": "^0.4.24"
}
},
"node_modules/babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
"dependencies": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
}
},
"node_modules/babel-runtime/node_modules/regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -6173,13 +6169,6 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
"hasInstallScript": true
},
"node_modules/core-js-compat": {
"version": "3.27.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.1.tgz",
@@ -8307,6 +8296,26 @@
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ=="
},
"node_modules/flutterwave-react-v3": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/flutterwave-react-v3/-/flutterwave-react-v3-1.3.0.tgz",
"integrity": "sha512-y0dGSgxh9H/KMSDFurnoPYO3D6DSeOCZHPdLt8DnbtCkjgYgzNdqeXKvxerEaOJyitzXITsmlbzYdrEO/Lju3g==",
"dependencies": {
"axios": "^0.21.1"
},
"peerDependencies": {
"react": "^15.0.0 || ^18.0.0",
"react-dom": "^15.0.0 || ^18.0.0"
}
},
"node_modules/flutterwave-react-v3/node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
@@ -12506,11 +12515,6 @@
"loose-envify": "cli.js"
}
},
"node_modules/lottie-web": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.10.1.tgz",
"integrity": "sha512-u17bVNf/vA3oK9Wkyb1Vpo83WUIEQwaT0GeEN0qcvaExizyJ/RjmcbjSDj0CnwQCtpGqTgYhqprCC7cTWuXMNw=="
},
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
@@ -15045,21 +15049,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-lottie": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/react-lottie/-/react-lottie-1.2.3.tgz",
"integrity": "sha512-qLCERxUr8M+4mm1LU0Ruxw5Y5Fn/OmYkGfnA+JDM/dZb3oKwVAJCjwnjkj9TMHtzR2U6sMEUD3ZZ1RaHagM7kA==",
"dependencies": {
"babel-runtime": "^6.26.0",
"lottie-web": "^5.1.3"
},
"engines": {
"npm": "^3.0.0"
},
"peerDependencies": {
"react": "^0.14.7 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
@@ -15142,9 +15131,9 @@
}
},
"node_modules/react-scripts": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.0.tgz",
"integrity": "sha512-3i0L2CyIlROz7mxETEdfif6Sfhh9Lfpzi10CtcGs1emDQStmZfWjJbAIMtRD0opVUjQuFWqHZyRZ9PPzKCFxWg==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
"integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==",
"dependencies": {
"@babel/core": "^7.16.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
@@ -15162,7 +15151,7 @@
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.0",
"eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1",
"file-loader": "^6.2.0",
"fs-extra": "^10.0.0",
@@ -15179,7 +15168,7 @@
"postcss-preset-env": "^7.0.1",
"prompts": "^2.4.2",
"react-app-polyfill": "^3.0.0",
"react-dev-utils": "^12.0.0",
"react-dev-utils": "^12.0.1",
"react-refresh": "^0.11.0",
"resolve": "^1.20.0",
"resolve-url-loader": "^4.0.0",
+1
View File
@@ -3,6 +3,7 @@
"version": "0.2.0",
"private": true,
"dependencies": {
"@react-oauth/google": "^0.11.0",
"@reduxjs/toolkit": "^1.8.2",
"@tailwindcss/line-clamp": "^0.3.1",
"@testing-library/jest-dom": "^5.11.4",
+8
View File
@@ -33,6 +33,10 @@ import ReferralPage from "./views/ReferralPage";
import VerifyLinkPages from "./views/VerifyLinkPages";
import MyActiveJobsPage from "./views/MyActiveJobsPage";
import FamilyAccPage from "./views/FamilyAccPage";
import StartJob from "./components/MyJobs/StartJob";
import AddJobPage from "./views/AddJobPage";
import MyPendingJobsPage from "./views/MyPendingJobsPage";
import ManageActiveJobs from "./views/ManageActiveJobs";
export default function Routers() {
return (
@@ -75,8 +79,12 @@ export default function Routers() {
<Route exact path="/notification" element={<Notification />} />
<Route exact path="/mytask" element={<MyTaskPage />} />
<Route exact path="/myjobs" element={<MyJobsPage />} />
<Route exact path="/add-job" element={<AddJobPage />} />
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
<Route exact path="/my-pending-jobs" element={<MyPendingJobsPage />} />
<Route exact path="/acc-family" element={<FamilyAccPage />} />
<Route exact path="/start-job" element={<StartJob />} />
<Route exact path="/manage-active-job" element={<ManageActiveJobs />} />
<Route
exact
path="/my-collection/collection-item"
+1 -1
View File
@@ -12,7 +12,7 @@ export default function AllBidsSection({ className, allBids = [] }) {
</div>
<div className="w-full">
<div className="grid xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 2xl:gap-8 xl:gap-5 gap-5 mb-10">
<DataIteration datas={allBids} startLength={0} endLength={8}>
<DataIteration datas={allBids} startLength={process.env.REACT_APP_ZERO_STATE} endLength={8}>
{({ datas }) => (
<div key={datas.id} className="item">
<ProductCardStyleOne datas={datas} />
+351
View File
@@ -0,0 +1,351 @@
import React, {useState, useEffect} from 'react'
import { Link, useNavigate } from 'react-router-dom';
import InputCom from '../Helpers/Inputs/InputCom';
import LoadingSpinner from '../Spinners/LoadingSpinner';
import usersService from '../../services/UsersService';
import { Form, Formik } from "formik";
import * as Yup from "yup";
const validationSchema = Yup.object().shape({
country: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Country is required"),
price: Yup.number()
.typeError("you must specify a number")
.min(1, "Price must be greater than 0")
.required("Price is required"),
title: Yup.string()
.min(3, "Minimum 3 characters")
.max(100, "Maximum 25 characters")
.required("Title is required"),
description: Yup.string()
.min(3, "Minimum 3 characters")
.max(250, "Maximum 250 characters")
.required("Description is required"),
job_detail: Yup.string()
.min(3, "Minimum 3 characters")
.max(250, "Maximum 250 characters")
.required("Details is required"),
timeline_days: Yup.number()
.typeError("you must specify a number")
.min(1, "Price must be greater than 0")
.required("Price is required"),
});
let initialValues = { // initial values for formik
country: '',
price: 0,
title: '',
description: '',
job_detail: '',
timeline_days: ''
}
function AddJob() {
const ApiCall = new usersService()
const navigate = useNavigate()
let [pageLoading, setPageLoading] = useState(true) // State used for knowing when the page is mounting
let [country, setCountry] = useState({loading: false, status: false, data:[]}) // To Hold the array of country getUserCountry returns
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message:''}) // Holds state when submit button is pressed
// FUNCTION TO GET COUNTRY
const getUserCountry = () =>{
setCountry(prev => ({...prev, loading:true}))
ApiCall.getSignupCountryData().then(res => {
if(res.data.internal_return < 1){
setCountry({loading: false, status: true, data:[]})
return
}
setCountry({loading: false, status: true, data:res.data.signup_country})
}).catch(err => {
setCountry({loading: false, status: false, data:[]})
})
}
// FUNCTION TO HANDLE ADD JOB FORM
const handleAddJob = (values, helpers) => {
setRequestStatus({loading: true, status: false, message:''})
ApiCall.jobManagerCreateJob(values).then(res => {
if(res.data.internal_return < 1){
setRequestStatus({loading: false, status: false, message:'Could not complete your request at the moment'})
return
}
setRequestStatus({loading: false, status: true, message:'Job Added Successfully'})
setTimeout(()=>{
navigate('/myjobs', {replace: true})
},1000)
}).catch(err => {
setRequestStatus({loading: false, status: false, message:'Opps! soemthing went wrong. Try Again'})
}).finally(()=>{
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message:''})
}, 5000)
})
}
useEffect(()=>{
setPageLoading(false)
getUserCountry()
},[])
return pageLoading.loading ? (
<div className="personal-info-tab w-full flex flex-col justify-between">
<div className="p-3">
<LoadingSpinner size="32" color="sky-blue" />
</div>
</div>
) : (
<div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleAddJob}
>
{(props) => {
return (
<Form>
<h1 className='py-2 my-4 text-lg md:text-xl font-bold tracking-wide'>Create New Job</h1>
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
{/* inputs starts here */}
{/* country */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
{/* <InputCom
fieldClass="px-6"
label="Country"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="country"
// placeholder="Select Country"
value={props.values.country}
inputHandler={props.handleChange}
/> */}
<label
htmlFor='country'
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block">
Country
</label>
<select
id='country'
name='country'
value={props.values.country}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{country.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : country.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select...
</option>
{country.data.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item[0]}
>
{item[1]}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
{props.errors.country && props.touched.country && (
<p className="text-sm text-red-500">
{props.errors.country}
</p>
)}
</div>
{/* Price */}
<div className="field w-full">
<InputCom
fieldClass="px-6"
label="Price"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="number"
name="price"
fieldClass='text-right'
// placeholder="Please Enter Amount"
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.price && props.touched.price && (
<p className="text-sm text-red-500">
{props.errors.price}
</p>
)}
</div>
</div>
{/* Title */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Title"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="title"
// placeholder="Enter Job Title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.title && props.touched.title && (
<p className="text-sm text-red-500">
{props.errors.title}
</p>
)}
</div>
{/* Description */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Description"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="description"
// placeholder="Enter a description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.description && props.touched.description && (
<p className="text-sm text-red-500">
{props.errors.description}
</p>
)}
</div>
{/* Details */}
<div className="field w-full mb-6">
{/* <InputCom
fieldClass="px-6"
label="Job Delivery Details"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="details"
// placeholder="Please Enter Detail Description of Job"
value={props.values.details}
inputHandler={props.handleChange}
/> */}
<label
htmlFor="Job Delivery Details"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'>
Job Delivery Details
</label>
<textarea name="details" id="Job Delivery Details" rows="7"
className={`input-field p-6 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
style={{resize:'none'}}
name='job_detail'
value={props.values.job_detail}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
{props.errors.job_detail && props.touched.job_detail && (
<p className="text-sm text-red-500">
{props.errors.job_detail}
</p>
)}
</div>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Timeline"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="timeline_days"
spanTag = ' - Expected duration of this task'
// placeholder="Please Enter Detail Description of Job"
value={props.values.timeline_days}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.timeline_days && props.touched.timeline_days && (
<p className="text-sm text-red-500">
{props.errors.timeline_days}
</p>
)}
</div>
{/* inputs ends here */}
</div>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full">
{/* error or success display */}
{requestStatus.message != "" && (
!requestStatus.status ?
(<div className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{requestStatus.message}
</div>)
:
requestStatus.status &&
(<div className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{requestStatus.message}
</div>
)
)}
{/* End of error or success display */}
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-9">
<Link
to="/myjobs"
className="text-18 text-light-red tracking-wide "
>
<span className="border-b dark:border-[#5356fb29] border-light-red">
{" "}
Cancel
</span>
</Link>
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
// className='w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'
>
Add Job
</button>
)}
</div>
</div>
</div>
</Form>
);
}}
</Formik>
</div>
)
}
export default AddJob
+24 -9
View File
@@ -11,15 +11,30 @@ export default function LoginLayout({ slogan, children }) {
</div>
<div className="flex-1 flex justify-center items-center p-10">
<div className="flex items-center">
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
About
</Link>
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
Services
</Link>
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
Contact Us
</Link>
<a
href="https://www.wrenchboard.com/about-us"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
About
</a>
<a
href="https://www.wrenchboard.com/service"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Services
</a>
<a
href="https://www.wrenchboard.com/contact"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Contact Us
</a>
</div>
</div>
<div className="flex-1 flex justify-center items-center p-10">
@@ -42,7 +42,7 @@ export default function CollectionTab({ className, products }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
@@ -42,7 +42,7 @@ export default function OnSaleTab({ className, products }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
@@ -42,7 +42,7 @@ export default function OwnTab({ className, products }) {
<div className="grid xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 2xl:gap-8 xl:gap-5 gap-5 mb-10">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
@@ -1,17 +1,17 @@
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from 'react-router-dom';
import WrenchBoard from "../../../assets/images/wrenchboard.png"
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
import usersService from "../../../services/UsersService";
export default function ForgotPassword() {
const [checked, setValue] = useState(false);
const [resetLoading, setResetLoading] = useState(false)
const [resetLoading, setResetLoading] = useState(false);
// email
const [email, setMail] = useState("");
const [msgError, setMsgError] = useState('');
const [msgSuccess, setMsgSuccess] = useState(false)
const [msgError, setMsgError] = useState("");
const [msgSuccess, setMsgSuccess] = useState(false);
const navigate = useNavigate();
const userApi = new usersService();
@@ -21,52 +21,54 @@ export default function ForgotPassword() {
};
const humanChecker = () => {
setValue(!checked)
}
setValue(!checked);
};
const resetHandler = async () => {
if (email == '') {
setMsgError('An email is required')
if (email == "") {
setMsgError("An email is required");
} else if (!checked) {
setMsgError('Check if you are human')
setMsgError("Check if you are human");
}
if (email !== '' && checked) {
const reqData = { email }
setResetLoading(true)
if (email !== "" && checked) {
const reqData = { email };
setResetLoading(true);
try {
const res = await userApi.StartResetPassword(reqData)
const res = await userApi.StartResetPassword(reqData);
if (res.status === 200) {
setMsgSuccess(true)
setMail("")
setValue(false)
setResetLoading(false)
setMsgSuccess(true);
setMail("");
setValue(false);
setResetLoading(false);
}
} catch (error) {
setResetLoading(false)
setMail("")
setMsgError('An error occurred')
throw new Error(error)
setResetLoading(false);
setMail("");
setMsgError("An error occurred");
throw new Error(error);
} finally {
setTimeout(() => {
setMsgError(null)
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT)
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
}
setTimeout(() => {
setMsgError(null)
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT)
}
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
};
return (
<>
<AuthLayout
slogan="Welcome to WrenchBoard"
>
<AuthLayout slogan="Welcome to WrenchBoard">
<div className="w-full">
<div className='mb-12'>
<Link to='#'>
<img src={WrenchBoard} alt="wrenchboard" className="h-10 mx-auto" />
<div className="mb-12">
<Link to="#">
<img
src={WrenchBoard}
alt="wrenchboard"
className="h-10 mx-auto"
/>
</Link>
</div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
@@ -75,11 +77,14 @@ export default function ForgotPassword() {
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
Forget Password
</h1>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">Enter your email to reset your password.</span>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
Enter your email to reset your password.
</span>
</div>
<div className="input-area">
<div className="input-item mb-10">
<InputCom
fieldClass="px-6"
placeholder="Your Username/Email"
label="Email"
name="email"
@@ -98,7 +103,14 @@ export default function ForgotPassword() {
<div className="relative table top-0 h-full">
<div className="table-cell align-middle">
<div className="relative w-[30px] h-[30px] mx-[15px]">
<input type="checkbox" name="human-checkbox" id="human-checkbox" className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white" checked={checked} onChange={humanChecker} />
<input
type="checkbox"
name="human-checkbox"
id="human-checkbox"
className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white"
checked={checked}
onChange={humanChecker}
/>
</div>
</div>
</div>
@@ -106,7 +118,10 @@ export default function ForgotPassword() {
<div className="h-full relative inline-block w-[170px]">
<label className="relative table top-0 h-full">
<label className="table-cell align-middle">
<label className="text-800 text-sm" htmlFor="human-checkbox">
<label
className="text-800 text-sm"
htmlFor="human-checkbox"
>
I am human
</label>
</label>
@@ -116,8 +131,24 @@ export default function ForgotPassword() {
</div>
</div>
</div>
{msgError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">{msgError}</div>}
{msgSuccess && <div className="relative p-4 text-[#44228c] bg-[#e3d7fb] border-[#d5c4f9] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">If we find your email, you will receive a link to reset your password. Please use or <Link to='/contact' className="text-[#4687ba] hover:text-[#009ef7]">contact form</Link> if you did not get our message after few minutes.</div>}
{msgError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
{msgError}
</div>
)}
{msgSuccess && (
<div className="relative p-4 text-[#44228c] bg-[#e3d7fb] border-[#d5c4f9] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
If we find your email, you will receive a link to reset your
password. Please use or{" "}
<Link
to="/contact"
className="text-[#4687ba] hover:text-[#009ef7]"
>
contact form
</Link>{" "}
if you did not get our message after few minutes.
</div>
)}
<div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2">
+33 -42
View File
@@ -1,15 +1,16 @@
import React, { useState } from "react";
import { useNavigate, Link } from "react-router-dom";
import { toast } from "react-toastify";
import googleLogo from "../../../assets/images/google-logo.svg";
import { Link, useNavigate } from "react-router-dom";
import appleLogo from "../../../assets/images/apple-black.svg";
import facebookLogo from "../../../assets/images/facebook-4.svg";
import googleLogo from "../../../assets/images/google-logo.svg";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
//import { GoogleOAuthProvider } from '@react-oauth/google';
// import { googleLogout, useGoogleLogin } from '@react-oauth/google';
import { useDispatch, useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { updateUserDetails } from "../../../store/UserDetails";
export default function Login() {
@@ -73,7 +74,7 @@ export default function Login() {
setLoginError(true);
}
} else {
setMsgError("Please fill in fields");
setMsgError("Please fill in the fields");
}
} catch (error) {
setMsgError("An error occurred");
@@ -117,6 +118,7 @@ export default function Login() {
<div className="input-area">
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
@@ -129,6 +131,7 @@ export default function Login() {
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
@@ -139,39 +142,6 @@ export default function Login() {
forgotPassword
/>
</div>
{/* <div className="forgot-password-area flex justify-between items-center mb-7">
<div className="remember-checkbox flex items-center space-x-2.5">
<button
onClick={rememberMe}
type="button"
className="w-5 h-5 text-dark-gray dark:text-white flex justify-center items-center border border-light-gray"
>
{checked && (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
)}
</button>
<span
onClick={rememberMe}
className="text-base text-dark-gray dark:text-white"
>
Remember Me
</span>
</div>
<a href="/forgot-password" className="text-base text-purple">
Forgot Password
</a>
</div> */}
{loginError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
Invalid username or password- Please{" "}
@@ -203,9 +173,9 @@ export default function Login() {
)}
</button>
</div>
<BrandBtn link="#" imgSrc={googleLogo} brand="Google" />
<BrandBtn link="#" imgSrc={facebookLogo} brand="Facebook" />
<BrandBtn link="#" imgSrc={appleLogo} brand="Apple" />
<BrandBtn link="#" imgSrc={googleLogo} brand="Google" />
<BrandBtn link="#" imgSrc={facebookLogo} brand="Facebook" />
<BrandBtn link="#" imgSrc={appleLogo} brand="Apple" />
</div>
{/* <div className="signup-area flex justify-center">
<p className="sm:text-lg text-sm text-thin-light-gray font-normal">
@@ -229,10 +199,31 @@ export default function Login() {
}
const BrandBtn = ({ link, imgSrc, brand }) => {
const doGoogle = async ()=>{
alert('start google');
}
// onSuccess: (codeResponse) => setUser(codeResponse),
// const doGoogle = useGoogleLogin({
// onSuccess: (codeResponse) => console.log('Login onSuccess:', codeResponse),
// onError: (error) => console.log('Login Failed:', error)
// });
const doApple = async ()=>{
alert('start apple');
}
const doFacebook = async ()=>{
alert('start facebook');
}
return (
<div className="flex justify-center bottomMargin">
<a
href={link}
// onClick={doGoogle}
href="#dd"
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
>
<img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
+20 -10
View File
@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useState } from "react";
import { useNavigate, Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import facebookLogo from "../../../assets/images/facebook-4.svg";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import usersService from "../../../services/UsersService";
@@ -171,6 +171,7 @@ export default function SignUp() {
<div className="input-fl-name mb-5 sm:flex w-full sm:space-x-6 ">
<div className="input-item sm:w-1/2 w-full mb-5 sm:mb-0">
<InputCom
fieldClass="px-6"
placeholder="Firstname"
label="First Name"
name="first_name"
@@ -181,6 +182,7 @@ export default function SignUp() {
</div>
<div className="input-item flex-1">
<InputCom
fieldClass="px-6"
placeholder="Lastname"
label="Last Name"
name="last_name"
@@ -192,6 +194,7 @@ export default function SignUp() {
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="support@mermsemr.com"
label="Email"
name="email"
@@ -202,6 +205,7 @@ export default function SignUp() {
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
@@ -277,24 +281,30 @@ export default function SignUp() {
</div>
<div className="flex-1 flex justify-center items-center p-10">
<div className="flex items-center">
<Link
to="#"
<a
href="https://www.wrenchboard.com/about-us"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
About
</Link>
<Link
to="#"
</a>
<a
href="https://www.wrenchboard.com/service"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Services
</Link>
<Link
to="#"
</a>
<a
href="https://www.wrenchboard.com/contact"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Contact Us
</Link>
</a>
</div>
</div>
<div className="flex-1 flex justify-center items-center p-10">
@@ -16,9 +16,7 @@ export default function UpdatePassword() {
return (
<>
<AuthLayout
slogan="Welcome to myFit"
>
<AuthLayout slogan="Welcome to myFit">
{updated === false ? (
<div className="content-wrapper update-password-section xl:bg-white dark:bg-dark-white w-full 2xl:h-[818px] xl:h-[600px] sm:w-auto sm:px-[70px] px-5 2xl:px-[100px] rounded-xl flex flex-col justify-center">
<div>
@@ -34,6 +32,7 @@ export default function UpdatePassword() {
<div className="input-area">
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="*********"
label="Old Password"
name="password"
@@ -43,6 +42,7 @@ export default function UpdatePassword() {
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="*********"
label="New Password"
name="password"
@@ -52,6 +52,7 @@ export default function UpdatePassword() {
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="*********"
label="Re-enter Password"
name="password"
@@ -42,7 +42,7 @@ export default function CollectionTab({ className, products }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
@@ -42,7 +42,7 @@ export default function OnSaleTab({ className, products }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
@@ -42,7 +42,7 @@ export default function OwnTab({ className, products }) {
<div className="grid xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 2xl:gap-8 xl:gap-5 gap-5 mb-10">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
@@ -1,10 +1,10 @@
import { useState, useEffect, useCallback } from "react";
import { useLocation, Link, useNavigate } from "react-router-dom";
import AuthLayout from "../AuthLayout";
import InputCom from "../../Helpers/Inputs/InputCom";
import usersService from "../../../services/UsersService";
import { useCallback, useEffect, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import debounce from "../../../hooks/debounce";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
export default function VerifyLink() {
const [email, setEmail] = useState("");
@@ -173,6 +173,7 @@ const SuccessfulComponent = ({
{/* INPUT */}
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
@@ -184,6 +185,7 @@ const SuccessfulComponent = ({
</div>
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
@@ -1,9 +1,9 @@
import { useState, useEffect, useCallback } from "react";
import { useLocation, Link, useNavigate } from "react-router-dom";
import AuthLayout from "../AuthLayout";
import InputCom from "../../Helpers/Inputs/InputCom";
import usersService from "../../../services/UsersService";
import { useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
const VerifyPassword = () => {
const [password, setPassword] = useState("");
@@ -158,6 +158,7 @@ const SuccessfulComponent = ({
{/* INPUT */}
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
@@ -165,13 +166,12 @@ const SuccessfulComponent = ({
name="password"
type={showPassword ? "text" : "password"}
onClick={onClick}
passIcon={
showPassword ? "show-password" : "hide-password"
}
passIcon={showPassword ? "show-password" : "hide-password"}
/>
</div>
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={confirmPassword}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
+107 -116
View File
@@ -5,123 +5,114 @@ import localImgLoad from "../../lib/localImgLoad";
import Icons from "../Helpers/Icons";
export default function AvailableJobsCard({
className,
datas,
hidden = false,
}) {
//debugger;
const [addFavorite, setValue] = useState(datas.whishlisted);
const [options, setOption] = useState(false);
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
toast.success("Added to Favorite List");
} else {
setValue(false);
toast.warn("Remove to Favorite List");
}
};
return (
<div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="flex flex-col justify-between w-full h-full">
<Link to="/shop-details" className="mb-2.5">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.title}
</h1>
</Link>
className,
datas,
hidden = false,
}) {
//debugger;
const [addFavorite, setValue] = useState(datas.whishlisted);
const [options, setOption] = useState(false);
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
toast.success("Added to Favorite List");
} else {
setValue(false);
toast.warn("Remove to Favorite List");
}
};
return (
<div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="flex flex-col justify-between w-full h-full">
<Link to="/shop-details" className="mb-2.5">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.title}
</h1>
</Link>
<div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
style={{
background: `url(${localImgLoad(
`images/${datas.thumbnil}`
)}) 0% 0% / cover no-repeat`,
}}
>
<div className="flex justify-center">
{datas.description}
</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{datas.price*0.01}{datas.currency} | {datas.timeline_days} day(s)
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code})
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
>
View
</button>
</div>
</div>
</div>
<div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
);
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
style={{
background: `url(${localImgLoad(
`images/${datas.thumbnil}`
)}) 0% 0% / cover no-repeat`,
}}
>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{datas.price * 0.01}
{datas.currency} | {datas.timeline_days} day(s)
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code})
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
>
View
</button>
</div>
</div>
</div>
</div>
</div>
);
}
+92 -74
View File
@@ -1,80 +1,98 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function FamilyTable({ className }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
export default function FamilyTable({ className, familyList, loader }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">
<td className="py-4">Name</td>
<td className="py-4 text-center">Last Login</td>
<td className="py-4 text-center">No of Tasks</td>
<td className="py-4 text-right">Status</td>
</tr>
<tr className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage1}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
Firstname Lastname (age)
</h1>
<span className="text-sm text-thin-light-gray">
Added <span className="text-purple">10-10-2029</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
10-10-2019
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
100
</span>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</button>
</td>
</tr>
</tbody>
</table>
const [selectedCategory, setCategory] = useState(filterCategories[0]);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${
className || ""
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
{loader ? (
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size='16' color='sky-blue' />
</div>
</div>
);
) : (
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<>
<thead className="sticky top-0">
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
<th className="py-4">Name</th>
<th className="py-4 text-center">Last Login</th>
<th className="py-4 text-center">No of Tasks</th>
<th className="py-4 text-right">Status</th>
</tr>
</thead>
<tbody className="overflow-y-scroll h-auto">
<>
{familyList?.length > 0 ? (
familyList?.map(({ firstname, lastname, age }, idx) => (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={idx}
>
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage1}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
{`${firstname} ${lastname} (${age})`}
</h1>
<span className="text-sm text-thin-light-gray">
Added{" "}
<span className="text-purple">10-10-2029</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
10-10-2019
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
100
</span>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</button>
</td>
</tr>
))
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2" colSpan="4">
No Family Accounts Found!
</td>
</tr>
)}
</>
</tbody>
</>
</table>
)}
</div>
</div>
);
}
+295 -30
View File
@@ -1,40 +1,305 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import InputCom from "../Helpers/Inputs/InputCom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import FamilyTable from "./FamilyTable";
import SiteService from "../../services/SiteService";
import ModalCom from "../Helpers/ModalCom";
export default function FamilyAcc() {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
return (
<Layout>
{/*<CommonHead />*/}
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
const [selectTab, setValue] = useState("today");
const [selectedAge, setSelectedAge] = useState(undefined);
const [familyList, setFamilyList] = useState([]);
const [loader, setLoader] = useState(false);
const [popUp, setPopUp] = useState(false);
const [listReload, setListReload] = useState(false);
const [msgErr, setMsgErr] = useState("");
const [formData, setFormData] = useState({
first_name: "",
last_name: "",
});
const apiCall = useMemo(() => new SiteService(), []);
// This is to make sure it's called once and used everywhere
let memberId = localStorage.getItem("member_id");
let uid = localStorage.getItem("uid");
let sessionId = localStorage.getItem("session_token");
const popUpHandler = () => {
setPopUp((prev) => !prev);
};
// tab handler
const filterHandler = (value) => {
setValue(value);
};
// For the age drop down
let startAge = 5;
let endAge = 16;
// creates an array of age values ranging from 16 to 70
const ageRange = Array.from(
{ length: endAge - startAge + 1 },
(_, index) => startAge + index
);
// age handler
const handleAgeSelect = (event) => {
setSelectedAge(parseInt(event.target.value));
};
// Input handler
const handleInputChange = (event) => {
const { name, value } = event?.target;
setFormData({ ...formData, [name]: value });
};
// Add member
const addMember = async () => {
const { first_name, last_name } = formData;
setLoader(true);
try {
if (first_name !== "" && last_name !== "") {
let reqData = {
member_id: memberId,
uid: uid,
session_id: sessionId,
firstname: first_name,
lastname: last_name,
age: selectedAge,
};
let res = await apiCall.addFamily(reqData);
const { data } = res;
if (data?.internal_return > 0 && data?.status == "OK") {
setLoader(false);
setListReload((prev) => !prev);
} else {
setLoader(false);
setMsgErr("Sorry, something went wrong");
}
} else {
setLoader(false);
setMsgErr("Please fill in the fields");
}
} catch (error) {
setLoader(false);
setMsgErr("An error occurred");
throw new Error(error);
} finally {
setTimeout(() => {
setMsgErr(null);
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
setFormData({
first_name: "",
last_name: "",
});
}
};
// member listing
const memberList = useCallback(async () => {
setLoader(true);
try {
let reqData = {
member_id: memberId,
uid: uid,
session_id: sessionId,
limit: 20,
offset: 0,
action: 22010,
};
let res = await apiCall.familyListings(reqData);
const { data } = res;
if (data?.internal_return >= 0 && data?.status == "OK") {
let { result_list } = data;
setFamilyList(result_list);
setLoader(false);
} else return;
} catch (error) {
setLoader(false);
throw new Error(error);
}
}, [apiCall, memberId, sessionId, uid]);
useEffect(() => {
memberList();
}, [listReload, memberList]);
return (
<Layout>
{/*<CommonHead />*/}
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Family Accounts
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div onClick={() => filterHandler("today")} className="relative">
</div>
</div>
</div>
<FamilyTable />
</div>
<button
onClick={popUpHandler}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Add
</button>
</h1>
</div>
</Layout>
);
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div>
<FamilyTable familyList={familyList} loader={loader} />
</div>
</div>
{popUp && (
<ModalCom action={popUpHandler} situation={popUp}>
<FamilyForm
popUpHandler={popUpHandler}
value={formData}
ageHandler={handleAgeSelect}
ageRange={ageRange}
ageValue={selectedAge}
inputHandler={handleInputChange}
msgErr={msgErr}
onClick={addMember}
loader={loader}
/>
</ModalCom>
)}
</Layout>
);
}
const FamilyForm = ({
value: { first_name, last_name },
ageValue,
inputHandler,
ageHandler,
ageRange,
msgErr,
loader,
onClick,
popUpHandler,
}) => {
return (
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Add Members
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={popUpHandler}
>
<CloseIcon />
</button>
</div>
<form className="logout-modal-body w-full flex flex-col items-center px-10 py-8 gap-4">
<InputCom
placeholder="Firstname"
label="First Name:"
name="first_name"
type="text"
parentClass="flex items-center gap-1 w-full"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8]"
fieldClass="px-2"
value={first_name}
inputHandler={inputHandler}
/>
<InputCom
placeholder="Lastname"
label="Last Name:"
name="last_name"
type="text"
parentClass="flex items-center gap-1 w-full"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8]"
fieldClass="px-2"
value={last_name}
inputHandler={inputHandler}
/>
<div className="input-com mb-7 flex gap-1 items-center w-full justify-between">
{/* Age dropdown */}
<div className="flex items-center justify-between flex-[0.3]">
<label
className="input-label text-[#181c32] dark:text-white text-[15px] font-semibold"
htmlFor="age-selection"
>
Select your age:
</label>
</div>
<div className=" flex-[0.7] max-w-[150px]">
<select
name="age-selection"
id="age-selection"
className="input-wrapper border border-[#f5f8fa]] dark:border-[#5e6278] w-full rounded-[0.475rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent px-2"
onChange={ageHandler}
value={ageValue}
>
<option value={""}>Select your age</option>
{ageRange?.length > 0 &&
ageRange?.map((age) => (
<option value={age} key={age}>
{age}
</option>
))}
</select>
</div>
</div>
{msgErr && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-xs font-light leading-[19.5px]">
{msgErr}
</div>
)}
<div className="signin-area w-full">
<div className="flex justify-center">
<button
type="button"
onClick={onClick}
// className={`rounded-[0.475rem] text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
className="text-white btn-gradient text-lg tracking-wide px-6 py-2 rounded-full"
>
{loader ? (
<div className="signup btn-loader"></div>
) : (
<span>Add</span>
)}
</button>
</div>
</div>
</form>
</div>
);
};
const CloseIcon = () => (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
);
@@ -12,84 +12,81 @@ export default function InputCom({
inputHandler,
value,
forgotPassword,
parentClass,
labelClass,
inputClass,
fieldClass,
onClick,
disable,
blurHandler
blurHandler,
spanTag,
inputBg,
direction
}) {
const inputRef = useRef(null)
const inputRef = useRef(null);
// Entry Validation
// for Min Length:
const minLengthValidation = () => {
if (inputRef && inputRef?.current && inputRef?.current?.name === 'email') {
return 7
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'first_name') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'last_name') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'address') {
return 5
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'password') {
return 8
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'state') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'province') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'city') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'amount') {
return 1
}
}
const inputConfig = inputConfigs[inputRef?.current?.name]?.minLength;
return inputConfig || 0;
};
// for MaxLength
const maxLengthValidation = () => {
if (inputRef && inputRef?.current && inputRef?.current?.name === 'email') {
return 35
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'first_name') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'last_name') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'address') {
return 49
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'password') {
return 15
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'state') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'province') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'city') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'amount') {
return 9
}
const inputConfig = inputConfigs[inputRef?.current?.name]?.maxLength;
return inputConfig || 30;
};
// for Patterns
const inputPatterns = () => {
const inputConfig = inputConfigs[inputRef?.current?.name]?.pattern;
return inputConfig || ""
}
return (
<div className="input-com">
<div className="flex items-center justify-between">
{label && (
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block mb-2.5"
htmlFor={name}
>
{label}
</label>
)}
{forgotPassword && <Link to="/forgot-password" className="text-[13.975px] leading-[20.9625px] text-[#019ef7] hover:text-[#009ef7]">Forgot Password?</Link>}
<div className={`input-com ${parentClass}`}>
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
{label && (
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
htmlFor={name}
>
{label}
{spanTag && (
<span className="text-green-700 text-sm tracking-wide">
{spanTag}
</span>
)}
</label>
)}
{forgotPassword && (
<Link
to="/forgot-password"
className="text-[13.975px] leading-[20.9625px] text-[#019ef7] hover:text-[#009ef7]"
>
Forgot Password?
</Link>
)}
</div>
<div className="input-wrapper border border-[#f5f8fa]] dark:border-[#5e6278] w-full rounded-[0.475rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ">
<div
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-[0.475rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`}
>
<input
placeholder={placeholder}
value={value}
onChange={inputHandler}
className="input-field placeholder:text-base px-6 text-dark-gray dark:text-white w-full h-full bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none"
className={`input-field placeholder:text-base text-dark-gray w-full h-full ${
inputBg ? inputBg : "bg-[#FAFAFA]"
} dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`}
type={type}
id={name}
name={name}
minLength={minLengthValidation()}
maxLength={maxLengthValidation()}
pattern={() => inputPatterns}
ref={inputRef}
readOnly={disable}
onBlur={blurHandler}
dir={direction}
/>
{iconName && (
<div className="absolute right-6 bottom-[10px] z-10">
@@ -97,7 +94,10 @@ export default function InputCom({
</div>
)}
{passIcon && (
<div className="absolute right-6 bottom-[10px] z-10" onClick={onClick}>
<div
className="absolute right-6 bottom-[10px] z-10"
onClick={onClick}
>
<Icons name={passIcon} />
</div>
)}
@@ -105,3 +105,21 @@ export default function InputCom({
</div>
);
}
const inputConfigs = {
email: { minLength: 7, maxLength: 30 },
first_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
last_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
address: { minLength: 5, maxLength: 49, pattern: "[a-zA-Z0-9]+" },
password: { minLength: 8, maxLength: 15, pattern: ".{8,}" },
state: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
province: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
city: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" },
};
/* Numbers Only: <input type="text" pattern="[0-9]*" /> strictly numbers
Alphabets Only: <input type="text" pattern="[a-zA-Z]+" /> strictly alphabets
Alphanumeric: <input type="text" pattern="[a-zA-Z0-9]+" /> mix
Password: <input type="text" pattern=".{8,}" /> a minimum of 8 characters
*/
+2 -2
View File
@@ -1,6 +1,6 @@
import React, { useEffect } from "react";
export default function ModalCom({ action, children, situation }) {
export default function ModalCom({ action, children, situation, isOpen }) {
useEffect(() => {
if (situation) {
document.body.style.overflowY = "hidden";
@@ -13,7 +13,7 @@ export default function ModalCom({ action, children, situation }) {
return (
<div className="modal-com">
<div
onClick={action}
onClick={action || isOpen}
className="fixed top-0 left-0 w-full lg:h-[100vh] h-full bg-black bg-opacity-40 backdrop-filter backdrop-blur-sm z-50"
></div>
<div className="children-element fixed lg:h-100vh h-full z-[99999999999999] w-full lg:w-auto ">
File diff suppressed because it is too large Load Diff
+82 -2
View File
@@ -1,4 +1,4 @@
import React from "react";
import React, {useState, useEffect} from "react";
import HistoryAnalyticsCard from "../Cards/HistoryAnalyticsCard";
import SellHistoryMarketVisitorAnalytic from "../Home/SellHistoryMarketVisitorAnalytic";
import Layout from "../Partials/Layout";
@@ -6,7 +6,59 @@ import HistoryTable from "./HistoryTable";
import MarketHistorySection from "./MarketHistorySection";
import TopHxBox from "./TopHxBox";
import usersService from "../../services/UsersService";
import PurchasesTable from "../MyWallet/WalletComponent/PurchasesTable";
import RecentActivityTable from "../MyWallet/WalletComponent/RecentActivityTable";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function History() {
const apiCall = new usersService()
let [paymentHistory, setPaymentHistory] = useState({ // FOR PAYMENT HISTORY
loading: true,
data: [],
error: false
})
let [purchaseHistory, setPurchaseHistory] = useState({ // FOR PURCHASE HISTORY
loading: true,
data: [],
error: false
})
//FUNCTION TO GET PAYMENT HISTORY
const getPaymentHistory = ()=>{
apiCall.getPaymentHx().then((res)=>{
if(res.data.internal_return < 0){ // success but no data
setPaymentHistory(prev => ({...prev, loading: false}))
return
}
setPaymentHistory(prev => ({...prev, loading: false, data: res.data.result_list}))
}).catch((error)=>{
setPaymentHistory(prev => ({...prev, loading: false, error: true}))
})
}
//FUNCTION TO GET PURCHASE HISTORY
const getPurchaseHistory = ()=>{
apiCall.getPurchaseHx().then((res)=>{
if(res.data.internal_return < 0){ // success but no data
setPurchaseHistory(prev => ({...prev, loading: false}))
return
}
// console.log('purchase',res.data)
setPurchaseHistory(prev => ({...prev, loading: false, data: res.data.result_list}))
}).catch((error)=>{
setPurchaseHistory(prev => ({...prev, loading: false, error: true}))
})
}
useEffect(()=>{
getPaymentHistory()
getPurchaseHistory()
}, [])
return (
<>
<Layout>
@@ -148,7 +200,35 @@ export default function History() {
</div>
</div>
{/*<MarketHistorySection />*/}
<TopHxBox className="mb-11" />
{/* <TopHxBox className="mb-11" /> */}
<div className='w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin'>
{/* PURCHASE SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Purchases</h2>
{purchaseHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<PurchasesTable purchase={purchaseHistory} />
}
</div>
</div>
{/* END OF PURCHASE SECTION */}
{/* RECENT ACTIVITY SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
{paymentHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={paymentHistory} />
}
</div>
</div>
{/* END OF RECENT ACTIVITY SECTION */}
</div>
<HistoryTable />
</div>
</div>
+1 -1
View File
@@ -95,7 +95,7 @@ export default function MainSection({ className, marketPlaceProduct }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]">
<DataIteration
datas={products}
startLength="0"
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products?.length}
>
{({ datas }) => (
+8 -6
View File
@@ -1,19 +1,21 @@
import React from "react";
import products from "../../data/marketplace_data.json";
// import products from "../../data/marketplace_data.json";
//import CreateNft from "../Home/CreateNft";
import Layout from "../Partials/Layout";
import MainSection from "./MainSection";
import CommonHead from "../UserHeader/CommonHead";
import { useSelector } from "react-redux";
export default function MarketPlace(props) {
const JobList = props.activeJobList?.result_list;
console.log("activeJobList->",props.activeJobList.result_list);
const marketProduct = products.data;
export default function MarketPlace() {
let { jobLists } = useSelector((state) => state.jobLists);
const marketData = jobLists?.result_list;
// const marketProduct = products.data;
return (
<>
<Layout>
<CommonHead />
<MainSection marketPlaceProduct={JobList} className="mb-10" />
<MainSection marketPlaceProduct={marketData} className="mb-10" />
</Layout>
</>
);
+157
View File
@@ -0,0 +1,157 @@
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import ModalCom from "../Helpers/ModalCom";
import Layout from "../Partials/Layout";
import { useLocation, useNavigate } from "react-router-dom";
function ActiveJobs() {
let { userDetails } = useSelector((state) => state.userDetails);
let navigate = useNavigate()
let {state} = useLocation()
let [details, setDetails] = useState({})
// console.log(state, userDetails);
useEffect(()=>{
if(!state){
navigate('/my-active-jobs', {replace: true})
}
setDetails(state)
},[])
return (
<Layout>
{/* <div className="logout-modal-wrapper min-w-[850px] h-full lg:h-auto lg:rounded-2xl overflow-y-auto"> */}
<div className="p-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0 rounded-lg shadow-lg bg-slate-100">
<div className="w-full lg:w-3/4">
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
{/* back btn and title */}
<div className="w-full flex justify-start space-x-3 items-center">
<button
type="button"
className="text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() => navigate('/my-active-jobs', {replace: true})}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
{details.title && details.title}
</h1>
</div>
{/* END of back btn and title */}
<div className="mt-2 w-full lg:flex lg:justify-between lg:items-center lg:space-x-2">
<div className="my-2 lg:my-0">
<p className="text-base text-slate-700 dark:text-black">
{details.contract && details.contract}
</p>
<p className="text-base text-slate-700 dark:text-black">
<span className="font-semibold">Description: </span>
{details.description && details.description}
</p>
<p className="text-base text-sky-blue">Delivery Detail</p>
</div>
<div className="">
<p className="text-base text-sky-blue">
{userDetails.firstname && userDetails.firstname}
</p>
<p className="text-base text-slate-700 dark:text-black">
<span className="font-semibold">Due: </span>
{details.delivery_date &&
details.delivery_date.split(" ")[0]}
</p>
<p className="text-base text-slate-700 dark:text-black">
{details.delivery_date &&
details.delivery_date.split(" ")[1]}
</p>
<p className="text-base text-slate-700 dark:text-black">
{details.timeline_days && details.timeline_days} day(s)
</p>
</div>
</div>
</div>
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
<div className="">
<p className="text-lg font-bold text-slate-600 dark:text-blask tracking-wide">Message(s)</p>
<textarea
className="p-4 w-full text-base text-slate-600 border border-slate-300 outline-none rounded-md"
rows="10"
style={{ resize: "none" }}
/>
</div>
{/* Buttons Sections */}
<div className="py-2 mb-8 sm:flex sm:justify-center sm:items-center">
<div className="w-full sm:w-3/4 mb-5 sm:mb-0">
<button
onClick={()=> console.log('working')}
type="button"
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-md flex justify-center items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill='white'>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z"/>
</svg>
<span className="text-white">Upload Files</span>
</button>
</div>
<div className="w-full sm:w-1/4 flex justify-between items-center space-x-2">
<button
type="button"
className="bg-red-600 text-base text-white tracking-wide px-4 py-2 rounded-md hover:opacity-90"
>
<span className="text-white">Clear</span>
</button>
<button
type="button"
className="btn-gradient text-base text-white tracking-wide px-4 py-2 rounded-md"
>
<span className="text-white">Send</span>
</button>
</div>
</div>
{/* end of Buttons Sections */}
</div>
</div>
{/* ACTION SECTION */}
<div className="w-full lg:w-1/4 h-full">
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">Actions</h1>
<p className="my-3 py-1 text-base">
Waiting for the completion message from the client before you can approve.
</p>
</div>
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
<div className="">
<p className="text-lg font-bold text-dark-gray dark:text-black tracking-wide">Message</p>
<textarea
className="p-4 w-full text-base text-slate-600 border border-slate-300 outline-none rounded-md"
rows="10"
style={{ resize: "none" }}
/>
</div>
</div>
</div>
</div>
{/* </div> */}
</Layout>
);
}
export default ActiveJobs;
+122 -88
View File
@@ -1,102 +1,136 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
import PaginatedList from "../Pagination/PaginatedList";
import { useNavigate } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
export default function MyActiveJobTable({MyJobList, className }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
export default function MyActiveJobTable({ MyJobList, className }) {
const navigate = useNavigate()
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentActiveJobList = MyJobList?.result_list?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e,setCurrentPage)
}
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
{MyJobList && MyJobList?.result_list &&
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{/*<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4">All Product</td>*/}
{/* <td className="py-4 text-right">.</td>*/}
{/*</tr>*/}
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentActiveJobList = MyJobList?.result_list?.slice(
indexOfFirstItem,
indexOfLastItem
);
{
<>
{MyJobList && MyJobList?.result_list &&
MyJobList.result_list.length > 0 &&
currentActiveJobList.map((value, index) => (
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
{value.title}
</h1>
<div>
{value.description}
</div>
<span className="text-sm text-thin-light-gray">
Price: <span className="text-purple">{value.price*0.01}</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration: <span className="text-purple"> {value.timeline_days} day(s)</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire: <span className="text-purple"> {value.expire}</span>
</span>
<span className="text-sm text-thin-light-gray">
Send to: <span className="text-purple"> {value.job_to}</span>
</span>
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
</div>
</div>
</td>
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
{MyJobList && MyJobList?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{/*<tr className="text-base text-thin-light-gray border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4">All Product</td>*/}
{/* <td className="py-4 text-right">.</td>*/}
{/*</tr>*/}
{
<>
{MyJobList &&
MyJobList?.result_list &&
MyJobList.result_list.length > 0 &&
currentActiveJobList.map((value, index) => (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray">
Price:{" "}
<span className="text-purple">
{value.price * 0.01}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire:{" "}
<span className="text-purple">
{" "}
{value.expire}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Send to:{" "}
<span className="text-purple">
{" "}
{value.job_to}
</span>
</span>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
))}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= MyJobList?.result_list.length ? true : false} data={MyJobList?.result_list} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</div>
<td className="text-right py-4 px-2">
<div className="flex justify-center items-center">
<button
type="button"
onClick={() => {
navigate('/manage-active-job', {state:value});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</div>
</td>
</tr>
))}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
MyJobList?.result_list.length
? true
: false
}
data={MyJobList?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
);
)}
</div>
);
}
+1 -1
View File
@@ -22,7 +22,7 @@ export default function MyActiveJobs(props) {
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Current Job(s)
Active Job(s)
</span>
</h1>
@@ -9,7 +9,7 @@ export default function MainSection({ collectionData, className }) {
<div className="grid xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 2xl:gap-8 xl:gap-5 gap-5 mb-10">
<DataIteration
datas={collectionData}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={collectionData.length}
>
{({ datas }) => (
+1 -1
View File
@@ -8,7 +8,7 @@ function MainSection({ collectionData, className }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
<DataIteration
datas={collectionData}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={collectionData.length}
>
{({ datas }) => (
+59 -31
View File
@@ -4,6 +4,8 @@ import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
import JobListPopout from "../jobPopout/JobListPopout";
import DeleteJobPopout from "../jobPopout/DeleteJobPopout";
import PaginatedList from "../Pagination/PaginatedList";
import { handlePagingFunc } from "../Pagination/HandlePagination";
@@ -12,6 +14,10 @@ export default function MyJobTable({MyJobList, className }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
let [jobPopout,setJobPopout] = useState({show:false, data:{}}) // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let [deleteJobPopout,setDeleteJobPopout] = useState({show:false, data:{}}) // STATE TO HOLD THE VALUE OF THE ITEM DETAILS TO DELETE AND DETERMINE WHEN TO SHOW
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
@@ -23,14 +29,14 @@ export default function MyJobTable({MyJobList, className }) {
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="header w-full flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
All Jobs
</h1>
</div>
<SelectBox
@@ -41,12 +47,12 @@ export default function MyJobTable({MyJobList, className }) {
/>
</div>
{MyJobList && MyJobList?.result_list &&
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="table-auto min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">
<td className="py-4">All Product</td>
<td className="py-4 text-right">.</td>
<tr className="text-base text-thin-light-gray border-b default-border-b dark:border-[#5356fb29] ottom ">
<td className="py-1">.</td>
<td className="py-1 text-right">.</td>
</tr>
{selectedCategory === "All Categories" ? (
@@ -55,39 +61,49 @@ export default function MyJobTable({MyJobList, className }) {
MyJobList.result_list.length > 0 &&
currentJobList.map((value, index) => (
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
{value.title}
</h1>
<div>
{value.description}
<td className="py-9">
<div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items">
<div className="flex space-x-2 items-center job-items">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<span className="text-sm text-thin-light-gray">
Price: <span className="text-purple">{value.price*0.01}</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration: <span className="text-purple"> {value.timeline_days} day(s)</span>
</span>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>
{value.description}
</div>
<span className="text-sm text-thin-light-gray">
Price: <span className="text-purple">{value.price*0.01}</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration: <span className="text-purple"> {value.timeline_days} day(s)</span>
</span>
</div>
</div>
<div className="min-w-[110px] max-w-[110px] bg-yellow-300 mx-2 rounded-md flex flex-nowrap space-x-2 justify-center items-center self-end">
<button type="button" className="p-2 w-[60px] h-11" onClick={()=>{setDeleteJobPopout({show:true, data:value})}}>[Delete]</button>
<span>|</span>
<button type="button" className="p-2 w-[40px] h-11">Edit</button>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<td className="text-right py-9 px-2">
<button
type="button"
onClick={()=>{setJobPopout({show:true, data:value})}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
Manage
</button>
</td>
</tr>
@@ -112,6 +128,18 @@ export default function MyJobTable({MyJobList, className }) {
{/* END OF PAGINATION BUTTON */}
</div>
}
{/* Job List Popout */}
{jobPopout.show &&
<JobListPopout details={jobPopout.data} onClose={()=>{setJobPopout({show:false, data:{}})}} situation={jobPopout.show} />
}
{/* End of Job List Popout */}
{/* Delete Job Popout */}
{deleteJobPopout.show &&
<DeleteJobPopout details={deleteJobPopout.data} onClose={()=>{setDeleteJobPopout({show:false, data:{}})}} situation={deleteJobPopout.show} />
}
{/* END of Delete Job Popout */}
</div>
);
}
+74 -20
View File
@@ -1,24 +1,49 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import Layout from "../Partials/Layout";
import MyJobTable from "./MyJobTable";
import CommonHead from "../UserHeader/CommonHead";
import SelectBox from "../Helpers/SelectBox";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import usersService from "../../services/UsersService";
export default function StartJob(props) {
const apiCall = new usersService() // instantiating API CALL
const navigate = useNavigate()
let [request, setRequest] = useState({loading: false, status: false, message: ''})
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
console.log("AMEYE LOC1", props.MyJobList);
const handleOnclick = () => {
setRequest({loading: true, status: false, message: ''})
apiCall.jobManagerAgree().then((res)=>{
if(res.status != 200 || res.data.internal_return < 1){
setRequest({loading: false, status: false, message: 'Could not complete request, Try Again'})
return
}
setRequest({loading: false, status: true, message: 'Request completed successfully'})
setTimeout(()=>{
navigate('/', {replace: true})
window.location.reload()
}, 2000)
}).catch(error => {
setRequest({loading: false, status: false, message: 'Opps! An Error Occured. Try Again'})
console.log(error)
})
}
return (
<Layout>
{/*<CommonHead />*/}
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
{/* <div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
@@ -34,16 +59,16 @@ export default function StartJob(props) {
</div>
</div>
</div>
</div> */}
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px]`}
>
<div className="header w-full flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
Terms & Agreement
</h1>
<h3 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
Additional Terms for Jobs Posting.
</h3>
</div>
{/*<SelectBox*/}
{/* action={setCategory}*/}
@@ -53,24 +78,53 @@ export default function StartJob(props) {
{/*/>*/}
</div>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
All terms of sale must follow WrenchBoard policies for buying and selling. Setting and meeting expectations in a listing's terms of sale ensure a smooth transaction and buyer satisfaction while helping WrenchBoard remain a reputable marketplace.
<p className="my-2 text-base">All terms of sale must follow WrenchBoard policies for buying and selling. Setting and meeting expectations in a listing's terms of sale ensure a smooth transaction and buyer satisfaction while helping WrenchBoard remain a reputable marketplace.
</p>
What is the policy?
Task or Job owners should provide clear and accurate delivery terms and conditions required to meet the expectations they have set in their listings. These should include:
Delivery mode, timelines, and reviews
The forms of payment available for the task
A returns policy:
Clearly stated criteria under which cancellation will be accepted.
Clearly stated the time period in which the buyer must notify the seller about the delivery delay.
How refunds/returns/cancellations will be issued
<h3 className="mb-2 mt-6 text-lg font-bold">What is the policy?</h3>
<p className="mt-2 text-base">Task or Job owners should provide clear and accurate delivery terms and conditions required to meet the expectations they have set in their listings. These should include:</p>
<ul className="mt-3 mb-10 border-2 rounded-md">
<li className="px-2 py-1 text-sm text-slate-900 border-b-2">Delivery mode, timelines, and reviews</li>
<li className="px-2 py-1 text-sm text-slate-900">The forms of payment available for the task</li>
<li className="px-2 py-1 text-sm text-slate-900">A returns policy:
<ul>
<li className="px-2 py-1 text-sm text-slate-900">Clearly stated criteria under which cancellation will be accepted.</li>
<li className="px-2 py-1 text-sm text-slate-900">Clearly stated the time period in which the buyer must notify the seller about the delivery delay.</li>
<li className="px-2 py-1 text-sm text-slate-900 border-2 rounded-md">How refunds/returns/cancellations will be issued</li>
</ul>
</li>
</ul>
Activity that doesn't follow WrenchBoard policy could result in a range of actions, including for example: administratively ending or canceling listings, hiding or demoting all listings from search results, lowering rating, buying or selling restrictions, and account suspension.
All fees paid or payable concerning listings or accounts on which we take any action will not be refunded or otherwise credited to your account.
<p className="my-2 mt-6 text-base">Activity that doesn't follow WrenchBoard policy could result in a range of actions, including for example: administratively ending or canceling listings, hiding or demoting all listings from search results, lowering rating, buying or selling restrictions, and account suspension.
All fees paid or payable concerning listings or accounts on which we take any action will not be refunded or otherwise credited to your account.</p>
Why does WrencBoard have this policy?
Buyers and sellers enter a contract when they complete transactions, so it's necessary to have precise details on what the transaction entails to guarantee satisfaction. This policy also helps sellers meet our performance standards.
<h3 className="mb-2 mt-6 text-lg font-bold">Why does WrencBoard have this policy?</h3>
<p className="my-2 text-base">Buyers and sellers enter a contract when they complete transactions, so it's necessary to have precise details on what the transaction entails to guarantee satisfaction. This policy also helps sellers meet our performance standards.</p>
{/* error or success display */}
{request.message && !request.status ?
<div className={`relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{request.message}
</div>
:
request.message && request.status &&
(<div className={`relative p-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{request.message}
</div>
)
}
{/* End of error or success display */}
<div className="my-2 p-2 flex justify-end items-center">
{request.loading ?
<LoadingSpinner size='6' color='sky-blue' />
:
<button onClick={handleOnclick} className="text-white btn-gradient text-lg tracking-wide px-4 py-3 rounded-full">Agree to Terms</button>
}
</div>
</div>
</div>
+9 -6
View File
@@ -18,13 +18,16 @@ export default function MyJobs(props) {
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
My Jobs
</span>
<h1 className="text-26 font-bold flex items-center space-x-1 text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
My Jobs
</span>
<Link to='/add-job' className='w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'>
Add Job
</Link>
</h1>
</div>
<div className="slider-btns flex space-x-4">
@@ -0,0 +1,112 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
import PendingJobsPopout from "../jobPopout/PendingJobsPopout";
import PaginatedList from "../Pagination/PaginatedList";
import { handlePagingFunc } from "../Pagination/HandlePagination";
export default function MyPendingJobTable({MyJobList, className }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
let [jobPopout,setJobPopout] = useState({show:false, data:{}}) // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentActiveJobList = MyJobList?.result_list?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e,setCurrentPage)
}
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
{MyJobList && MyJobList?.result_list &&
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{/*<tr className="text-base text-thin-light-gray border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4">All Product</td>*/}
{/* <td className="py-4 text-right">.</td>*/}
{/*</tr>*/}
{
<>
{MyJobList && MyJobList?.result_list &&
MyJobList.result_list.length > 0 &&
currentActiveJobList.map((value, index) => (
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>
{value.description}
</div>
<span className="text-sm text-thin-light-gray">
Price: <span className="text-purple">{value.price*0.01}</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration: <span className="text-purple"> {value.timeline_days} day(s)</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire: <span className="text-purple"> {value.expire}</span>
</span>
<span className="text-sm text-thin-light-gray">
Send to: <span className="text-purple"> {value.job_to}</span>
</span>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={()=>{setJobPopout({show:true, data:value})}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
))}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= MyJobList?.result_list.length ? true : false} data={MyJobList?.result_list} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</div>
}
{/* Active Job Popout */}
{jobPopout.show &&
<PendingJobsPopout details={jobPopout.data} onClose={()=>{setJobPopout({show:false, data:{}})}} situation={jobPopout.show} />
}
{/* End of Active Job Popout */}
</div>
);
}
+41
View File
@@ -0,0 +1,41 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import MyPendingJobTable from "./MyPendingJobTable";
export default function MyPendingJobs(props) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
console.log("AMEYE LOC1", props.MyJobList);
return (
<Layout>
<CommonHead />
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Pending Job(s)
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div onClick={() => filterHandler("today")} className="relative">
</div>
</div>
</div>
<MyPendingJobTable MyJobList={props.MyJobList} />
</div>
</div>
</Layout>
);
}
+2 -2
View File
@@ -71,9 +71,9 @@ function AddFund({payment}) {
</div>
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[590px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-gray-600 dark:text-white'>Activity Report</p>
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
+472 -343
View File
@@ -1,370 +1,499 @@
import React, {useEffect, useState} from 'react'
import { Link, useNavigate } from 'react-router-dom'
import Icons from '../Helpers/Icons'
import usersService from '../../services/UsersService'
import InputCom from '../Helpers/Inputs/InputCom'
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import usersService from "../../services/UsersService";
import Icons from "../Helpers/Icons";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from '../Spinners/LoadingSpinner'
import {toast} from 'react-toastify'
import {Formik, Form} from 'formik'
import * as Yup from 'yup'
import { toast } from "react-toastify";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { Form, Formik } from "formik";
import * as Yup from "yup";
const validationSchema = Yup.object().shape({
firstname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Firstname is required'),
lastname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Lastname is required'),
country: Yup.string()
.min(1, 'Minimum 1 characters')
.max(25, 'Maximum 25 characters')
.required('Country is required'),
bank: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Bank name is required'),
accountNumber: Yup.string()
firstname: Yup.string()
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Firstname is required"),
lastname: Yup.string()
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Lastname is required"),
country: Yup.string()
.min(1, "Minimum 1 characters")
.max(25, "Maximum 25 characters")
.required("Country is required"),
bank: Yup.string()
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Bank name is required"),
accountNumber: Yup.string()
.matches(/\d/, "must be a number")
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Account Number is required'),
repeatAccountNumber: Yup.string()
.required('Repeat Account Number is required')
.oneOf([Yup.ref('accountNumber'), null], 'Must match Account Number'),
accountType: Yup.string()
.min(1, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Account Type is required'),
city: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('City is required'),
state: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('State is required'),
})
const initialValues = {
firstname: '',
lastname: '',
country: '',
bank: '',
accountNumber: '',
repeatAccountNumber: '',
accountType: '',
state: '',
city: ''
}
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Account Number is required"),
repeatAccountNumber: Yup.string()
.required("Repeat Account Number is required")
.oneOf([Yup.ref("accountNumber"), null], "Must match Account Number"),
accountType: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Account Type is required"),
city: Yup.string()
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("City is required"),
state: Yup.string()
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("State is required"),
});
const initialValues = {
firstname: "",
lastname: "",
country: "",
bank: "",
accountNumber: "",
repeatAccountNumber: "",
accountType: "",
state: "",
city: "",
};
function AddRecipient() {
const apiURL = new usersService();
const apiURL = new usersService()
const navigate = useNavigate();
const navigate = useNavigate()
let [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
status: false,
});
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false})
let [allCountries, setAllCountries] = useState({
// STATE TO HOLD LIST OF COUNTRIES
loading: true,
data: [],
});
let [allCountries, setAllCountries] = useState({ // STATE TO HOLD LIST OF COUNTRIES
loading: true,
data: []
})
let [bankName, setBankName] = useState({
// STATE TO HOLD LIST OF BANK NAME
loading: true,
data: [],
});
let [bankName, setBankName] = useState({ // STATE TO HOLD LIST OF BANK NAME
loading: true,
data: []
})
let [accType, setAccType] = useState({
// STATE TO HOLD LIST ACCOUNT TYPE
loading: true,
data: [],
});
let [accType, setAccType] = useState({ // STATE TO HOLD LIST ACCOUNT TYPE
loading: true,
data: []
})
//FUNCTION TO HANDLE ADD RECIPIENT SUBMIT
const handleSubmit = (values, helpers) => {
setRequestStatus({ message: "", loading: true, status: false });
//FUNCTION TO HANDLE ADD RECIPIENT SUBMIT
const handleSubmit = (values, helpers) => {
setRequestStatus({message: '', loading: true, status: false})
let reqData = {
//REQUEST DATA FOR API CALL
firstname: values.firstname,
lastname: values.lastname,
bank_code: values.bank,
account_no: values.accountNumber,
account_type: values.accountType,
country: values.country,
state: values.state,
city: values.city,
};
let reqData = { //REQUEST DATA FOR API CALL
firstname: values.firstname,
lastname: values.lastname,
bank_code: values.bank,
account_no: values.accountNumber,
account_type: values.accountType,
country: values.country,
state: values.state,
city: values.city
//CALL TO ADD RECIPIENT API
apiURL
.addRecipient(reqData)
.then((res) => {
if (res.data.internal_return < 0) {
setRequestStatus({
message: "could not add recipient, try again!",
loading: false,
status: true,
});
return;
}
// setRequestStatus({message: 'Recipient Added Successfully!', loading: false, status: true})
toast.success("Recipient Added Successfully!");
setTimeout(() => {
navigate("/my-wallet/transfer-fund", { replace: true });
}, 1000);
})
.catch((error) => {
setRequestStatus({
message: "Opps! an error occured! Try again later",
loading: false,
status: false,
});
});
};
//CALL TO ADD RECIPIENT API
apiURL.addRecipient(reqData).then((res)=>{
if(res.data.internal_return < 0){
setRequestStatus({message: 'could not add recipient, try again!', loading: false, status: true})
return
}
// setRequestStatus({message: 'Recipient Added Successfully!', loading: false, status: true})
toast.success("Recipient Added Successfully!");
setTimeout(()=>{navigate('/my-wallet/transfer-fund',{replace:true})},1000)
}).catch((error)=>{
setRequestStatus({message: 'Opps! an error occured! Try again later', loading: false, status: false})
})
}
// FUNCTION TO GET COUNTRIES
const getCountry = () => {
apiURL
.getSignupCountryData()
.then((res) => {
if (res.data.internal_return < 0) {
setAllCountries((prev) => ({ loading: false, data: [] }));
return;
}
setAllCountries((prev) => ({
loading: false,
data: res.data.signup_country,
}));
})
.catch((error) => {
setAllCountries((prev) => ({ loading: false, data: [] }));
});
};
// END OF FUNCTION TO GET COUNTRIES
// FUNCTION TO GET COUNTRY BANK
const getCountryBank = () => {
apiURL
.getCountryBank()
.then((res) => {
if (res.data.internal_return < 0) {
setBankName((prev) => ({ loading: false, data: [] }));
return;
}
setBankName((prev) => ({ loading: false, data: res.data.result_list }));
})
.catch((error) => {
setBankName((prev) => ({ loading: false, data: [] }));
});
};
// END OF FUNCTION TO GET COUNTRY BANK
// FUNCTION TO GET COUNTRIES
const getCountry = ()=> {
apiURL.getSignupCountryData().then((res)=>{
if(res.data.internal_return < 0){
setAllCountries(prev => ({loading: false, data: []}))
return
}
setAllCountries(prev => ({loading: false, data:res.data.signup_country}))
}).catch((error)=>{
setAllCountries(prev => ({loading: false, data: []}))
})
}
// END OF FUNCTION TO GET COUNTRIES
// FUNCTION TO GET ACCOUNT TYPES
const getAccountTypes = () => {
apiURL
.getAccountTypes()
.then((res) => {
if (res.data.internal_return < 0) {
setAccType((prev) => ({ loading: false, data: [] }));
return;
}
setAccType((prev) => ({ loading: false, data: res.data.result_list }));
})
.catch((error) => {
setAccType((prev) => ({ loading: false, data: [] }));
});
};
// END OF FUNCTION TO GET ACCOUNT TYPES
// FUNCTION TO GET COUNTRY BANK
const getCountryBank = ()=> {
apiURL.getCountryBank().then((res)=>{
if(res.data.internal_return < 0){
setBankName(prev => ({loading: false, data: []}))
return
}
setBankName(prev => ({loading: false, data:res.data.result_list}))
}).catch((error)=>{
setBankName(prev => ({loading: false, data: []}))
})
}
// END OF FUNCTION TO GET COUNTRY BANK
useEffect(() => {
getCountry(); // TO LOAD LIST COUNTRY
getCountryBank(); // TO LOAD LIST COUNTRY BANK
getAccountTypes(); // TO LOAD LIST ACCOUNT TYPES
}, []);
// FUNCTION TO GET ACCOUNT TYPES
const getAccountTypes = ()=> {
apiURL.getAccountTypes().then((res)=>{
if(res.data.internal_return < 0){
setAccType(prev => ({loading: false, data: []}))
return
}
setAccType(prev => ({loading: false, data:res.data.result_list}))
}).catch((error)=>{
setAccType(prev => ({loading: false, data: []}))
})
}
// END OF FUNCTION TO GET ACCOUNT TYPES
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="w-full mb-10 lg:mb-0">
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="my-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-semibold">
ADD BANK ACCOUNT
</h2>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => (
<Form className="add-recipient-info px-1 md:px-[50px] lg:px-[100px]">
{/* inputs starts here */}
{/* firstname */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
fieldClass="px-6"
label="Firstname"
type="text"
name="firstname"
placeholder="Account Firstname"
value={props.values.firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.firstname && props.touched.firstname && (
<p className="text-sm text-red-500">
{props.errors.firstname}
</p>
)}
</div>
useEffect(()=>{
getCountry() // TO LOAD LIST COUNTRY
getCountryBank() // TO LOAD LIST COUNTRY BANK
getAccountTypes() // TO LOAD LIST ACCOUNT TYPES
},[])
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="w-full mb-10 lg:mb-0">
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className='my-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-semibold'>ADD BANK ACCOUNT</h2>
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
{(props)=>(
<Form className='add-recipient-info px-1 md:px-[50px] lg:px-[100px]'>
{/* inputs starts here */}
{/* firstname */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
label="Firstname"
type="text"
name="firstname"
placeholder="Account Firstname"
value={props.values.firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
</div>
{/* lastname */}
<div className="field w-full">
<InputCom
label="Lastname"
type="text"
name="lastname"
placeholder="Account Lastname"
value={props.values.lastname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
</div>
</div>
<div className="xl:flex xl:space-x-7 mb-6">
{/* country */}
<div className='add-recipient w-full mb-6 xl:mb-0'>
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Country <span className='text-red-500'>*</span></label>
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='country'
value={props.values.country}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{allCountries.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
allCountries.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{allCountries.data.map((item, index)=>(
<option key={index} className='text-slate-500 text-lg' value={item[0]}>{item[1]}</option>
))}
</>
:
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
}
</select>
{(props.errors.country && props.touched.country) && <p className="text-sm text-red-500">{props.errors.country}</p>}
</div>
{/* bank name */}
<div className='add-recipient w-full'>
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Bank Name <span className='text-red-500'>*</span></label>
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='bank'
value={props.values.bank}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{bankName.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
bankName.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{bankName.data.map((item, index)=>(
<option key={index} className='text-slate-500 text-lg' value={item.code}>{item.name}</option>
))}
</>
:
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
}
</select>
{(props.errors.bank && props.touched.bank) && <p className="text-sm text-red-500">{props.errors.bank}</p>}
</div>
</div>
{/* ACCOUNT NUMBER */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
label="Account Number"
type="text"
name="accountNumber"
placeholder="Account No"
value={props.values.accountNumber}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.accountNumber && props.touched.accountNumber) && <p className="text-sm text-red-500">{props.errors.accountNumber}</p>}
</div>
{/* REPEAT ACCT. NUMBER */}
<div className="field w-full">
<InputCom
label="Repeat Account Number"
type="text"
name="repeatAccountNumber"
placeholder="Repeat Account Number"
value={props.values.repeatAccountNumber}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.repeatAccountNumber && props.touched.repeatAccountNumber) && <p className="text-sm text-red-500">{props.errors.repeatAccountNumber}</p>}
</div>
</div>
<div className="xl:flex xl:space-x-7 mb-6">
{/* Account Type */}
<div className='add-recipient w-full'>
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Account Type <span className='text-red-500'>*</span></label>
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='accountType'
value={props.values.accountType}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{accType.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
accType.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{accType.data.map((item, index)=>(
<option key={index} className='text-slate-500 text-lg' value={item.value}>{item.name}</option>
))}
</>
:
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
}
</select>
{(props.errors.accountType && props.touched.accountType) && <p className="text-sm text-red-500">{props.errors.accountType}</p>}
</div>
</div>
{/* state */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
label="State"
type="text"
name="state"
placeholder="State/Province"
value={props.values.state}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.state && props.touched.state) && <p className="text-sm text-red-500">{props.errors.state}</p>}
</div>
{/* city */}
<div className="field w-full">
<InputCom
label="City"
type="text"
name="city"
placeholder="City"
value={props.values.city}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.city && props.touched.city) && <p className="text-sm text-red-500">{props.errors.city}</p>}
</div>
</div>
{/* end of inputs starts here */}
{/* REQUEST ERROR DISPLAY */}
{requestStatus.message && <p className='text-sm text-red-500'>{requestStatus.message}</p>}
<div className='add-recipient-btn flex justify-end items-center py-4'>
{requestStatus.loading ?
<LoadingSpinner size={6} color='sky-blue' />
:
<button type='submit' className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md flex items-center space-x-1'>
<span className='pr-2'>ADD RECIPIENT</span>
<Icons name="arrows" />
</button>
}
</div>
</Form>
)}
</Formik>
{/* lastname */}
<div className="field w-full">
<InputCom
fieldClass="px-6"
label="Lastname"
type="text"
name="lastname"
placeholder="Account Lastname"
value={props.values.lastname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.lastname && props.touched.lastname && (
<p className="text-sm text-red-500">
{props.errors.lastname}
</p>
)}
</div>
</div>
</div>
<div className="xl:flex xl:space-x-7 mb-6">
{/* country */}
<div className="add-recipient w-full mb-6 xl:mb-0">
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
Country <span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
name="country"
value={props.values.country}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{allCountries.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : allCountries.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select...
</option>
{allCountries.data.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item[0]}
>
{item[1]}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
{props.errors.country && props.touched.country && (
<p className="text-sm text-red-500">
{props.errors.country}
</p>
)}
</div>
{/* bank name */}
<div className="add-recipient w-full">
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
Bank Name <span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
name="bank"
value={props.values.bank}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{bankName.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : bankName.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select...
</option>
{bankName.data.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item.code}
>
{item.name}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
{props.errors.bank && props.touched.bank && (
<p className="text-sm text-red-500">
{props.errors.bank}
</p>
)}
</div>
</div>
{/* ACCOUNT NUMBER */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
fieldClass="px-6"
label="Account Number"
type="text"
name="accountNumber"
placeholder="Account No"
value={props.values.accountNumber}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.accountNumber &&
props.touched.accountNumber && (
<p className="text-sm text-red-500">
{props.errors.accountNumber}
</p>
)}
</div>
{/* REPEAT ACCT. NUMBER */}
<div className="field w-full">
<InputCom
fieldClass="px-6"
label="Repeat Account Number"
type="text"
name="repeatAccountNumber"
placeholder="Repeat Account Number"
value={props.values.repeatAccountNumber}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.repeatAccountNumber &&
props.touched.repeatAccountNumber && (
<p className="text-sm text-red-500">
{props.errors.repeatAccountNumber}
</p>
)}
</div>
</div>
<div className="xl:flex xl:space-x-7 mb-6">
{/* Account Type */}
<div className="add-recipient w-full">
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
Account Type <span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
name="accountType"
value={props.values.accountType}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{accType.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : accType.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select...
</option>
{accType.data.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item.value}
>
{item.name}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
{props.errors.accountType && props.touched.accountType && (
<p className="text-sm text-red-500">
{props.errors.accountType}
</p>
)}
</div>
</div>
{/* state */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
fieldClass="px-6"
label="State"
type="text"
name="state"
placeholder="State/Province"
value={props.values.state}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.state && props.touched.state && (
<p className="text-sm text-red-500">
{props.errors.state}
</p>
)}
</div>
{/* city */}
<div className="field w-full">
<InputCom
fieldClass="px-6"
label="City"
type="text"
name="city"
placeholder="City"
value={props.values.city}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.city && props.touched.city && (
<p className="text-sm text-red-500">
{props.errors.city}
</p>
)}
</div>
</div>
{/* end of inputs starts here */}
{/* REQUEST ERROR DISPLAY */}
{requestStatus.message && (
<p className="text-sm text-red-500">
{requestStatus.message}
</p>
)}
<div className="add-recipient-btn flex justify-end items-center py-4">
{requestStatus.loading ? (
<LoadingSpinner size={6} color="sky-blue" />
) : (
<button
type="submit"
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md flex items-center space-x-1"
>
<span className="pr-2">ADD RECIPIENT</span>
<Icons name="arrows" />
</button>
)}
</div>
</Form>
)}
</Formik>
</div>
)
</div>
</div>
);
}
export default AddRecipient
export default AddRecipient;
+8 -36
View File
@@ -5,7 +5,7 @@ import PurchasesTable from './WalletComponent/PurchasesTable'
import CouponTable from './WalletComponent/CouponTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
function Balance({wallet, payment, coupon, purchase}) {
function Balance({wallet, coupon}) {
return (
<div className="content-wrapper">
<div className='w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin'>
@@ -25,12 +25,12 @@ function Balance({wallet, payment, coupon, purchase}) {
<div key={index} className="md:flex items-center flex-wrap my-3 border-t-2 border-slate-400">
<div className='text-slate-900 w-full md:w-1/2 flex space-x-3 items-start justify-start'>
<div className='balance-info'>
<p className='py-2'>Currency</p>
<p className='py-2'></p>
<span className='text-base'>{item.description}</span>
<p className='text-base text-slate-500'>{item.symbol}</p>
</div>
<div className='balance-info'>
<p className='py-2'>balance</p>
<p className='py-2'>Balance</p>
<span className='text-sm py-1 px-2 bg-green-100 text-green-500 rounded-lg'>{item.symbol}{(item.amount*0.01).toFixed(2)}</span>
</div>
<div className='balance-info'>
@@ -40,7 +40,10 @@ function Balance({wallet, payment, coupon, purchase}) {
</div>
<div className='w-full my-2 md:my-0 md:w-1/2 flex space-x-2 items-center justify-start md:justify-end'>
<Link to='transfer-fund' className='text-base text-white px-3 py-1 bg-purple rounded-md hover:opacity-80'>Transfer</Link>
{
item.action_type != 'AC_AD_FD_ONLY' ?
<Link to='transfer-fund' className='text-base text-white px-3 py-1 bg-purple rounded-md hover:opacity-80'>Transfer</Link>:''
}
<Link to='add-fund' className='text-base text-white px-3 py-1 bg-[orange] rounded-md hover:opacity-80'>Top Up</Link>
</div>
</div>
@@ -65,36 +68,6 @@ function Balance({wallet, payment, coupon, purchase}) {
{/* END OF WALLET SECTION */}
{/* RECENT ACTIVITY SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[500px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-slate-500 dark:text-white'>Activity Report</p>
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={payment} />
}
</div>
</div>
{/* END OF RECENT ACTIVITY SECTION */}
</div>
<div className='w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin'>
{/* PURCHASE SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[500px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Purchases</h2>
{purchase.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<PurchasesTable purchase={purchase} />
}
</div>
</div>
{/* END OF PURCHASE SECTION */}
{/* COUPON SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[500px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
@@ -107,8 +80,7 @@ function Balance({wallet, payment, coupon, purchase}) {
</div>
</div>
{/* END OF COUPON SECTION */}
</div>
</div>
</div>
)
}
+140 -116
View File
@@ -1,132 +1,156 @@
import React, {useState, useEffect} from 'react'
import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import InputCom from '../Helpers/Inputs/InputCom'
import {toast} from 'react-toastify'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSelector } from 'react-redux'
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
import usersService from '../../services/UsersService'
import usersService from "../../services/UsersService";
import { FlutterWaveButton, closePaymentModal } from 'flutterwave-react-v3'
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
function ConfirmAddFund({ payment }) {
let { userDetails } = useSelector((state) => state.userDetails); // TO GET LOGGEDIN USER DETAILS
function ConfirmAddFund({payment}) {
let [pageLoading, setPageLoading] = useState(true);
let {userDetails} = useSelector(state => state.userDetails) // TO GET LOGGEDIN USER DETAILS
let [pageLoading, setPageLoading] = useState(true)
let [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
status: false,
}); // STATE FOR API REQUEST
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false}) // STATE FOR API REQUEST
const apiURL = new usersService();
const navigate = useNavigate();
const apiURL = new usersService()
const navigate = useNavigate()
let { state } = useLocation();
let {state} = useLocation()
//FUNCTION TO HANDLE SUBMIT
const onSuccessPayment = () => {
setRequestStatus({message: '', loading: true, status: false})
let reqData = {amount: state?.account, currency: 'NGN'}
apiURL.startTopUp(reqData).then((res)=>{
if(res.data.internal_return < 0){
setRequestStatus({message: 'Could not finish transaction', loading: false, status: false})
toast.success('Opps! something went wrong')
}
// do something
setRequestStatus({message: 'Topup successful', loading: false, status: true})
toast.success('Account Topup was sucessful')
setTimeout(()=>{
navigate('/my-wallet', {replace: true})
window.location.reload(true)
}, 1000)
}).catch(err => {
// do something
setRequestStatus({message: 'Opps! An Error Occured', loading: false, status: false})
toast.success('Opps! something went wrong')
})
}
const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: Date.now(),
amount: state?.amount,
currency: 'NGN',
payment_options: 'card,mobilemoney,ussd',
customer: {
email: `${userDetails.email}`,
phone_number: userDetails.phone,
name: `${userDetails.lastname} ${userDetails.firstname}`
},
customizations: {
title: 'WrenchBoard',
description: 'Topup Payment',
logo: 'https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg',
},
};
const fwConfig = {
...config,
text: 'Proceed',
callback: (response) => {
onSuccessPayment()
closePaymentModal() // this will close the modal programmatically
},
onClose: () => {},
};
useEffect(()=>{
// what happens if not state redirect user
if(!state){
navigate('/my-wallet/add-fund',{replace: true})
}else{
setPageLoading(false)
//FUNCTION TO HANDLE SUBMIT
const onSuccessPayment = () => {
setRequestStatus({ message: "", loading: true, status: false });
let reqData = { amount: state?.account, currency: "NGN" };
apiURL
.startTopUp(reqData)
.then((res) => {
if (res.data.internal_return < 0) {
setRequestStatus({
message: "Could not finish transaction",
loading: false,
status: false,
});
toast.success("Opps! something went wrong");
}
},[])
// do something
setRequestStatus({
message: "Topup successful",
loading: false,
status: true,
});
toast.success("Account Topup was sucessful");
setTimeout(() => {
navigate("/my-wallet", { replace: true });
window.location.reload(true);
}, 1000);
})
.catch((err) => {
// do something
setRequestStatus({
message: "Opps! An Error Occured",
loading: false,
status: false,
});
toast.success("Opps! something went wrong");
});
};
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className='md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Confirm Add Fund To Account</h2>
<hr />
<div className='px-4 md:px-8 py-4 add-fund-info'>
<div className="field w-full mb-3">
<InputCom
label="Amount (Naira):"
type="text"
name="amount"
value={state.amount || ''}
disable={true}
/>
</div>
</div>
const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: Date.now(),
amount: state?.amount,
currency: "NGN",
payment_options: "card,mobilemoney,ussd",
customer: {
email: `${userDetails.email}`,
phone_number: userDetails.phone,
name: `${userDetails.lastname} ${userDetails.firstname}`,
},
customizations: {
title: "WrenchBoard",
description: "Topup Payment",
logo: "https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg",
},
};
<hr />
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
<FlutterWaveButton {...fwConfig} className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md' />
</div>
</div>
const fwConfig = {
...config,
text: "Proceed",
callback: (response) => {
onSuccessPayment();
closePaymentModal(); // this will close the modal programmatically
},
onClose: () => {},
};
useEffect(() => {
// what happens if not state redirect user
if (!state) {
navigate("/my-wallet/add-fund", { replace: true });
} else {
setPageLoading(false);
}
}, []);
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Confirm Add Fund To Account
</h2>
<hr />
<div className="px-4 md:px-8 py-4 add-fund-info">
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Amount (Naira):"
type="text"
name="amount"
value={state.amount || ""}
disable={true}
/>
</div>
</div>
}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-gray-600 dark:text-white'>Activity Report</p>
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={payment}/>
}
</div>
<hr />
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4">
<FlutterWaveButton
{...fwConfig}
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md"
/>
</div>
</div>
</div>
)
)}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className="text-gray-900 dark:text-white text-xl lg:text-2xl font-medium">
Recent Activity
</h2>
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
{payment.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<RecentActivityTable payment={payment} />
)}
</div>
</div>
</div>
);
}
export default ConfirmAddFund
export default ConfirmAddFund;
+198 -156
View File
@@ -1,168 +1,210 @@
import React, {useState, useEffect} from 'react'
import {useLocation, useNavigate} from 'react-router-dom'
import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import InputCom from '../Helpers/Inputs/InputCom'
import {toast} from 'react-toastify'
import React, { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
import usersService from '../../services/UsersService'
import usersService from "../../services/UsersService";
function ConfirmTransfer({payment, wallet}) {
const apiURL = new usersService()
function ConfirmTransfer({ payment, wallet }) {
const apiURL = new usersService();
const navigate = useNavigate()
let {state} = useLocation()
const navigate = useNavigate();
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false})
let [pageLoading, setPageLoading] = useState(true)
let { state } = useLocation();
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = () => {
setRequestStatus({message: '', loading: true, status: false})
let reqData = {
amount: Number(state.amount),
Fee: Number(state.fee),
recipientid: Number(state.recipientID)
let [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
status: false,
});
let [pageLoading, setPageLoading] = useState(true);
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = () => {
setRequestStatus({ message: "", loading: true, status: false });
let reqData = {
amount: Number(state.amount),
Fee: Number(state.fee),
recipientid: Number(state.recipientID),
};
apiURL
.sendMoney(reqData)
.then((res) => {
if (res.data.internal_return < 0) {
setRequestStatus({
message: "Could not perform transaction",
loading: false,
status: false,
});
return;
}
apiURL.sendMoney(reqData).then((res)=>{
if(res.data.internal_return < 0){
setRequestStatus({message: 'Could not perform transaction', loading: false, status: false})
return
}
setRequestStatus({message: 'transfer successful', loading: false, status: true})
toast.success('Transfer sucessful')
setTimeout(()=>{
navigate('/my-wallet', {replace: true})
window.location.reload(true)
}, 1000)
}).catch(error=>{
setRequestStatus({message: 'Opps! something went wrong! Try Again', loading: false, status: false})
})
setRequestStatus({
message: "transfer successful",
loading: false,
status: true,
});
toast.success("Transfer sucessful");
setTimeout(() => {
navigate("/my-wallet", { replace: true });
window.location.reload(true);
}, 1000);
})
.catch((error) => {
setRequestStatus({
message: "Opps! something went wrong! Try Again",
loading: false,
status: false,
});
});
};
useEffect(() => {
// what happens if not state redirect user
if (!state) {
navigate("/my-wallet/transfer-fund", { replace: true });
} else {
setPageLoading(false);
}
useEffect(()=>{
// what happens if not state redirect user
if(!state){
navigate('/my-wallet/transfer-fund',{replace: true})
}else{
setPageLoading(false)
}
},[])
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ?
<LoadingSpinner size='8' color='sky-blue' />
:
(
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<div className='px-4 md:px-8 py-4'>
{wallet.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
wallet.data.length ?
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>
{wallet.data.map(item => {
if(item.description == 'Naira'){
return `Withdraw from Naira Wallet : ${item.symbol}${(item.amount*0.01).toFixed(2)}`
}
})}
</h2>
:
wallet.error ?
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>Opps! An Error Occured</h2>
:
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>No Wallet Information Found!</h2>
}
</div>
<hr />
<div className='px-4 md:px-8 py-4 add-fund-info'>
<h2 className='my-2 text-slate-900 dark:text-white text-sm xl:text-xl font-medium'>Confirm Withdraw to Account</h2>
{/* AMOUNT */}
<div className="field w-full mb-3">
<InputCom
label="Amount:"
type="text"
name="amount"
value={state?.amount || ''}
disable={true}
/>
</div>
{/* RECIPIENT ACC: */}
<div className="field w-full mb-3">
<InputCom
label="Recipient Acc:"
type="text"
name="recipient"
value={state?.details.recipient || ''}
disable={true}
/>
</div>
{/* PROCESSING FEE: */}
<div className="field w-full mb-3">
<InputCom
label="Processing Fee:"
type="text"
name="processingFee"
value={state?.fee || ''}
disable={true}
/>
</div>
{/* TOTAL */}
<div className="field w-full mb-3">
<InputCom
label="Total"
type="text"
name="total"
value={state?.total || ''}
disable={true}
/>
</div>
{/* COMMENT/NOTE */}
<div className="field w-full mb-3">
<InputCom
label="Comment/Note:"
type="text"
name="comment"
value={state?.comment || ''}
disable={true}
/>
</div>
</div>
<hr />
{requestStatus.message && <p className={`text-base ${requestStatus.status? 'text-green-500' : 'text-red-500'} px-4 md:px-8 py-4`}>{requestStatus.message}</p>}
<div className='px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center'>
{requestStatus.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button onClick={handleSubmit} className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md'>Transfer</button>
}
</div>
</div>
</div>
)
}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full px-4 md:px-8 py-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-gray-600 dark:text-white'>Activity Report</p>
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={payment}/>
}, []);
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<div className="px-4 md:px-8 py-4">
{wallet.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : wallet.data.length ? (
<h2 className="my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium">
{wallet.data.map((item) => {
if (item.description == "Naira") {
return `Withdraw from Naira Wallet : ${item.symbol}${(
item.amount * 0.01
).toFixed(2)}`;
}
</div>
})}
</h2>
) : wallet.error ? (
<h2 className="my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium">
Opps! An Error Occured
</h2>
) : (
<h2 className="my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium">
No Wallet Information Found!
</h2>
)}
</div>
<hr />
<div className="px-4 md:px-8 py-4 add-fund-info">
<h2 className="my-2 text-slate-900 dark:text-white text-sm xl:text-xl font-medium">
Confirm Withdraw to Account
</h2>
{/* AMOUNT */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Amount:"
type="text"
name="amount"
value={state?.amount || ""}
disable={true}
/>
</div>
{/* RECIPIENT ACC: */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Recipient Acc:"
type="text"
name="recipient"
value={state?.details.recipient || ""}
disable={true}
/>
</div>
{/* PROCESSING FEE: */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Processing Fee:"
type="text"
name="processingFee"
value={state?.fee || ""}
disable={true}
/>
</div>
{/* TOTAL */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Total"
type="text"
name="total"
value={state?.total || ""}
disable={true}
/>
</div>
{/* COMMENT/NOTE */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Comment/Note:"
type="text"
name="comment"
value={state?.comment || ""}
disable={true}
/>
</div>
</div>
<hr />
{requestStatus.message && (
<p
className={`text-base ${
requestStatus.status ? "text-green-500" : "text-red-500"
} px-4 md:px-8 py-4`}
>
{requestStatus.message}
</p>
)}
<div className="px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center">
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
onClick={handleSubmit}
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md"
>
Transfer
</button>
)}
</div>
</div>
</div>
)
)}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full px-4 md:px-8 py-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className="text-gray-900 dark:text-white text-xl lg:text-2xl font-medium">
Recent Activity
</h2>
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
{payment.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<RecentActivityTable payment={payment} />
)}
</div>
</div>
</div>
);
}
export default ConfirmTransfer
export default ConfirmTransfer;
+314 -219
View File
@@ -1,240 +1,335 @@
import React, {useEffect, useState} from 'react'
import { Link, useNavigate } from 'react-router-dom'
import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import InputCom from '../Helpers/Inputs/InputCom'
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
import usersService from '../../services/UsersService'
import usersService from "../../services/UsersService";
import {toast} from 'react-toastify'
import {Formik, Form} from 'formik'
import * as Yup from 'yup'
import { Form, Formik } from "formik";
import * as Yup from "yup";
const validationSchema = Yup.object().shape({
amount: Yup.number()
amount: Yup.number()
.typeError("you must specify a number")
.min(1, 'Amount must be greater than 0')
.required('Amount is required'),
recipientID: Yup.string()
.min(1, 'Minimum 1 characters')
.max(50, 'Maximum 50 characters')
.required('Recipient is required'),
})
const initialValues = {
amount: '',
recipientID: '',
comment: '',
}
.min(1, "Amount must be greater than 0")
.required("Amount is required"),
recipientID: Yup.string()
.min(1, "Minimum 1 characters")
.max(50, "Maximum 50 characters")
.required("Recipient is required"),
});
function TransferFund({payment, wallet}) {
const apiCall = new usersService() // API CLASS CALL
const initialValues = {
amount: "",
recipientID: "",
comment: "",
};
const navigate = useNavigate()
function TransferFund({ payment, wallet }) {
const apiCall = new usersService(); // API CLASS CALL
let [requestStatus, setRequestStatus] = useState(false)
const navigate = useNavigate();
let [recipients, setRecipients] = useState({ // FOR COUPON HISTORY
loading: true,
data: [],
error: false
})
let [requestStatus, setRequestStatus] = useState(false);
let [sendMoneyFee, setSendMoneyFee] = useState({loading: false, fee: 0, total: 0}) // HOLD THE VALUE FOR SEND MONEY FEE
let [recipients, setRecipients] = useState({
// FOR COUPON HISTORY
loading: true,
data: [],
error: false,
});
let [sendMoneyFee, setSendMoneyFee] = useState({
loading: false,
fee: 0,
total: 0,
}); // HOLD THE VALUE FOR SEND MONEY FEE
//FUNCTION TO GET RECIPIENT LIST
const getRecipients = ()=>{
apiCall.getRecipient().then((res)=>{
if(res.data.internal_return < 0){ // success but no data
setRecipients(prev => ({...prev, loading: false}))
return
}
setRecipients(prev => ({...prev, loading: false, data: res.data.result_list}))
}).catch((error)=>{
setRecipients(prev => ({...prev, loading: false, error: true}))
})
}
//FUNCTION TO GET SEND MONEY FEE
const getSendMoneyFee = ({target:{value}})=>{
setSendMoneyFee({loading: true, fee: 0, total: 0})
let amount = value
if(Number(amount) <= 0 || amount=='' || isNaN(amount)){
setSendMoneyFee({loading: false, fee: 0, total: 0})
return
//FUNCTION TO GET RECIPIENT LIST
const getRecipients = () => {
apiCall
.getRecipient()
.then((res) => {
if (res.data.internal_return < 0) {
// success but no data
setRecipients((prev) => ({ ...prev, loading: false }));
return;
}
apiCall.getSendMoneyFee(Number(amount)).then((res)=>{
setSendMoneyFee({loading: false, fee: res.data.processing_fee, total: res.data.total_amount})
}).catch((error)=>{
setSendMoneyFee({loading: false, fee: 0, total: 0})
})
setRecipients((prev) => ({
...prev,
loading: false,
data: res.data.result_list,
}));
})
.catch((error) => {
setRecipients((prev) => ({ ...prev, loading: false, error: true }));
});
};
//FUNCTION TO GET SEND MONEY FEE
const getSendMoneyFee = ({ target: { value } }) => {
setSendMoneyFee({ loading: true, fee: 0, total: 0 });
let amount = value;
if (Number(amount) <= 0 || amount == "" || isNaN(amount)) {
setSendMoneyFee({ loading: false, fee: 0, total: 0 });
return;
}
apiCall
.getSendMoneyFee(Number(amount))
.then((res) => {
setSendMoneyFee({
loading: false,
fee: res.data.processing_fee,
total: res.data.total_amount,
});
})
.catch((error) => {
setSendMoneyFee({ loading: false, fee: 0, total: 0 });
});
};
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = (values, helpers) => {
setRequestStatus(true);
let recipientDetails = recipients.data?.filter(
(item) => item.recipient_id == values.recipientID
);
let stateData = {
...values,
...sendMoneyFee,
details: { ...recipientDetails[0] },
};
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = (values, helpers) => {
setRequestStatus(true)
let recipientDetails = recipients.data?.filter(item => item.recipient_id == values.recipientID)
let stateData = {...values, ...sendMoneyFee, details:{...recipientDetails[0]}}
setTimeout(() => {
setRequestStatus(false);
navigate("confirm-transfer", { state: stateData });
}, 1000);
};
setTimeout(()=>{
setRequestStatus(false)
navigate('confirm-transfer', {state: stateData})
}, 1000)
}
useEffect(()=>{
getRecipients()
},[])
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
{(props)=>{
return (
<Form className='transfer-fund-info'>
{wallet.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
wallet.data.length ?
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>
{wallet.data.map(item => {
if(item.description == 'Naira'){
return `Withdraw from Naira Wallet : ${item.symbol}${(item.amount*0.01).toFixed(2)}`
}
})}
</h2>
:
wallet.error ?
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Opps! An Error Occured</h2>
:
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>No Wallet Information Found!</h2>
}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
label="Amount"
type="text"
name="amount"
placeholder='0'
value={props.values.amount}
inputHandler={props.handleChange}
blurHandler={(e)=>{
getSendMoneyFee(e)
}}
// props.handleBlur
// onMouseLeave={(e)=>{getSendMoneyFee(e)}}
/>
{(props.errors.amount && props.touched.amount) && <p className="text-sm text-red-500">{props.errors.amount}</p>}
</div>
<div className="field w-full">
<InputCom
label="Fee"
type="text"
name="fee"
value={sendMoneyFee.loading ? 'loading' : sendMoneyFee.fee}
disable={true}
/>
</div>
</div>
<div className='md:flex items-center justify-end'>
<div className="field w-full lg:w-1/2 mb-6">
<InputCom
label="Total"
type="text"
name="total"
value={sendMoneyFee.loading ? 'loading' : sendMoneyFee.total}
disable={true}
/>
</div>
</div>
<div className='w-full'>
<div className='relative my-3 md:flex items-center'>
<div className='transfer-input w-full'>
<div className='flex items-center justify-start py-2'>
<label className='text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Recipient
<span className='text-red-500 mx-2'>*</span>
<span title='Transfer Recipient' className={`text-white text-sm bg-slate-500 w-1 h-1 rounded-full px-3 py-1 cursor-pointer`}>!</span>
</label>
<Link to='add-recipient' className='mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80'>Add New</Link>
</div>
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' value={props.values.recipientID} name='recipientID' onChange={props.handleChange} onBlur={props.handleBlur}>
{recipients.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
recipients.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{recipients.data.map((item, index)=>(
<option key={index} value={item.recipient_id} className='text-slate-500 text-lg'>{item.recipient}</option>
))}
</>
:
recipients.error ?
<option className='text-slate-500 text-lg' value="">Could'nt Load, try again!</option>
:
<option className='text-slate-500 text-lg' value="">No Recipient Found! Click Add to Add</option>
}
</select>
</div>
</div>
{(props.errors.recipientID && props.touched.recipientID) && <p className="text-sm text-red-500">{props.errors.recipientID}</p>}
</div>
<div className="field w-full mb-6">
{/* <InputCom
label="Comment"
type="text"
name="comment"
value={inputs.comment}
inputHandler={handleChange}
/> */}
<label className='text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Comment</label>
<textarea style={{resize: 'none'}}
className='text-base px-6 text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none'
name="comment"
value={props.values.comment}
onChange={props.handleChange}
onBlur={props.handleBlur}
cols="30"
rows="2"
/>
</div>
<div className='transfer-fund-btn flex justify-end items-center py-4'>
{requestStatus ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button type='submit' className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md'>Continue</button>
}
</div>
</Form>
)
useEffect(() => {
getRecipients();
}, []);
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => {
return (
<Form className="transfer-fund-info">
{wallet.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : wallet.data.length ? (
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
{wallet.data.map((item) => {
if (item.description == "Naira") {
return `Withdraw from Naira Wallet : ${item.symbol}${(
item.amount * 0.01
).toFixed(2)}`;
}
})}
</h2>
) : wallet.error ? (
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Opps! An Error Occurred
</h2>
) : (
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
No Wallet Information Found!
</h2>
)}
<div className=" mb-6 gap-4 flex flex-col">
<div className="field w-full">
<InputCom
fieldClass="px-4"
parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] max-w-[12rem]"
label="Amount:"
type="number"
name="amount"
placeholder="0"
direction="rtl"
value={props.values.amount}
inputHandler={props.handleChange}
blurHandler={(e) => {
getSendMoneyFee(e);
}}
</Formik>
</div>
</div>
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-slate-500 dark:text-white'>Activity Report</p>
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={payment}/>
}
</div>
</div>
// props.handleBlur
// onMouseLeave={(e)=>{getSendMoneyFee(e)}}
/>
{props.errors.amount && props.touched.amount && (
<p className="sm:text-sm text-[12px] text-red-500 sm:text-left text-right sm:translate-y-0 translate-y-1">
{props.errors.amount}
</p>
)}
</div>
<div className="field w-full">
<InputCom
fieldClass="px-4 transfer-field"
parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
label="Fee:"
type="text"
name="fee"
direction="rtl"
value={
sendMoneyFee.loading ? "loading" : sendMoneyFee.fee
}
disable={true}
/>
</div>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-4 transfer-field"
parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
label="Total:"
type="text"
name="total"
direction="rtl"
value={
sendMoneyFee.loading ? "loading" : sendMoneyFee.total
}
disable={true}
/>
</div>
</div>
<div className="w-full">
<div className="relative my-3 md:flex items-center">
<div className="transfer-input w-full flex items-start gap-1 justify-between">
<label className="text-[#181c32] dark:text-white text-base font-semibold block flex-[0.2] mb-0 mt-3">
Recipient:
</label>
<div className="flex flex-col gap-3 flex-[0.8] sm:items-start items-end">
<select
className="sm:w-full w-48 text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0 flex-[0.8]"
value={props.values.recipientID}
name="recipientID"
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{recipients.loading ? (
<option
className="text-slate-500 text-lg"
value=""
>
Loading...
</option>
) : recipients.data.length ? (
<>
<option
className="text-slate-500 text-lg"
value=""
>
Select...
</option>
{recipients.data.map((item, index) => (
<option
key={index}
value={item.recipient_id}
className="text-slate-500 text-lg"
>
{item.recipient}
</option>
))}
</>
) : recipients.error ? (
<option
className="text-slate-500 text-lg"
value=""
>
Could'nt load, try again!
</option>
) : (
<option
className="text-slate-500 text-lg"
value=""
>
No Recipient Found!
</option>
)}
</select>
<div className="flex justify-end relative w-full">
{props.errors.recipientID &&
props.touched.recipientID && (
<p className="sm:text-sm text-[12px] text-red-500 absolute sm:top-1 -top-20 sm:left-0 left-[160px]">
{props.errors.recipientID}
</p>
)}
<Link
to="add-recipient"
className="mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80 max-w-[5rem]"
>
Add New
</Link>
</div>
</div>
</div>
</div>
</div>
<div className="field w-full mb-6 flex gap-1 justify-between">
<label className="text-[#181c32] dark:text-white text-base font-semibold flex flex-[0.2] mt-2.5">
Comment:
</label>
<textarea
style={{ resize: "none" }}
className="text-base px-4 py-2 rounded-md min-h-[100px] sm:max-w-[550px] max-w-[250px] text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none flex-[0.8]"
name="comment"
value={props.values.comment}
onChange={props.handleChange}
onBlur={props.handleBlur}
cols="30"
rows="2"
/>
</div>
<div className="transfer-fund-btn flex justify-end items-center py-4">
{requestStatus ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md"
>
Continue
</button>
)}
</div>
</Form>
);
}}
</Formik>
</div>
)
</div>
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[650px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className="text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Recent Activity
</h2>
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
{payment.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<RecentActivityTable payment={payment} />
)}
</div>
</div>
</div>
);
}
export default TransferFund
export default TransferFund;
+1 -1
View File
@@ -115,7 +115,7 @@ const WalletRoutes = () => {
<Route path='add-fund' element={<AddFund payment={paymentHistory} />} />
<Route path='add-fund/confirm-add-fund' element={<ConfirmAddFund payment={paymentHistory} />} />
<Route path='transfer-fund' element={<TransferFund payment={paymentHistory} wallet={walletList} />} />
<Route index element={<Balance payment={paymentHistory} purchase={purchaseHistory} coupon={couponHistory} wallet={walletList} />} />
<Route index element={<Balance coupon={couponHistory} wallet={walletList} />} />
<Route path='transfer-fund/add-recipient' element={<AddRecipient />} />
<Route path='transfer-fund/confirm-transfer' element={<ConfirmTransfer payment={paymentHistory} wallet={walletList} />} />
<Route path='*' element={<Navigate to='/' />} />
@@ -15,7 +15,7 @@ function CouponTable({coupon}) {
}
return (
<>
<div className='flex flex-col justify-between h-full'>
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
@@ -59,7 +59,7 @@ function CouponTable({coupon}) {
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= coupon?.data?.length ? true : false} data={coupon?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</>
</div>
)
}
@@ -15,7 +15,7 @@ function PurchasesTable({purchase}) {
}
return (
<>
<div className='flex flex-col justify-between h-full'>
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
@@ -59,7 +59,7 @@ function PurchasesTable({purchase}) {
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= purchase?.data?.length ? true : false} data={purchase?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</>
</div>
)
}
@@ -15,7 +15,7 @@ function RecentActivityTable({payment}) {
}
return (
<>
<div className='flex flex-col justify-between h-full'>
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
@@ -59,7 +59,7 @@ function RecentActivityTable({payment}) {
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= payment?.data?.length ? true : false} data={payment?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</>
</div>
)
}
@@ -0,0 +1,60 @@
import React, {useState} from 'react'
import PaginatedList from '../../Pagination/PaginatedList';
import {handlePagingFunc} from '../../Pagination/HandlePagination';
function ReferralTable({history}) {
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentReferral = history?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e,setCurrentPage)
}
return (
<div className='flex flex-col justify-between h-full'>
<table className="referral-list w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
<th className="p-3">Added/Name</th>
<th className="p-3">Email</th>
<th className="p-3">Status</th>
</tr>
</thead>
<tbody>
{history.data.length ?
currentReferral.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td className="p-3">{item.added_date} / {item.firstname} {item.lastname}</td>
<td className="p-3">{item.email}</td>
<td className="p-3">{item.status}</td>
</tr>
))
:
(
history.error ?
<tr className='text-slate-500'>
<td colSpan={3}>Opps! couldn't get referral history. Try reloading the page</td>
</tr>
:
(
<tr className='text-slate-500'>
<td colSpan={3}>No Item Found on referral List</td>
</tr>
)
)
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= history?.data?.length ? true : false} data={history?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</div>
)
}
export default ReferralTable
+183 -169
View File
@@ -1,4 +1,4 @@
import {Link} from 'react-router-dom'
import { Link, useLocation, useNavigate } from "react-router-dom";
import Icons from "../Helpers/Icons";
import bank1 from "../../assets/images/bank-1.png";
import bank2 from "../../assets/images/bank-2.png";
@@ -8,180 +8,194 @@ import Accordion from "../Helpers/Accordion";
export default function WalletHeader(props) {
// debugger;
//props.myWalletList.result_list
return (
<>
<div
className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-purple pr-1.5 pl-4">
<div
onClick={() => props.handlerBalance()}
className="flex items-center lg:justify-between justify-center w-full h-full"
>
<span className="lg:block hidden">
<Icons name="wallet"/>
</span>
<p className="lg:text-xl text-lg font-bold text-white">
Wallet
</p>
<span className="lg:block hidden">
<Icons name="deep-plus"/>
</span>
</div>
<div
className={`balance-dropdown w-96 z-30 bg-white dark:bg-dark-white absolute -left-24 rounded-lg cursor-pointer ${
props.balanceDropdown ? "active" : ""
}`}
>
<div className="heading border-b dark:border-[#5356fb29] border-light-purple px-7 py-6">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
Wallet
</h3>
//props.myWalletList.result_list
let { pathname } = useLocation();
let navigate = useNavigate();
return (
<>
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-purple pr-1.5 pl-4">
<div
onClick={() => props.handlerBalance()}
className="flex items-center lg:justify-between justify-center w-full h-full"
>
<span className="lg:block hidden">
<Icons name="wallet" />
</span>
<p className="lg:text-xl text-lg font-bold text-white">Wallet</p>
<span className="lg:block hidden">
<Icons name="deep-plus" />
</span>
</div>
<div
className={`balance-dropdown w-96 z-30 bg-white dark:bg-dark-white absolute -left-24 rounded-lg cursor-pointer ${
props.balanceDropdown ? "active" : ""
}`}
>
<div className="heading border-b dark:border-[#5356fb29] border-light-purple px-7 py-6">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
Wallet
</h3>
</div>
<div className="content px-7 pb-7">
<ul>
{props.myWalletList &&
props.myWalletList?.result_list?.length > 0 &&
props.myWalletList.result_list.map((value, index) => (
<li
key={index}
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
>
<div className="sm:flex justify-between items-center">
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
<div className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">
<img src={bank1} alt="" />
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium">
{value.description}
</p>
</div>
</div>
<div>
<p className="eth text-xl font-bold text-purple">
{(value.amount * 0.01).toFixed(2)} {value.code}
</p>
<p className="usd text-base text-thin-light-gray text-right">
{/*(773.69 USD)*/}
</p>
</div>
</div>
<div className="content px-7 pb-7">
<ul>
</li>
))}
{props.myWalletList &&
props.myWalletList?.result_list?.length > 0 &&
props.myWalletList.result_list.map((value, index) => (
<li key={index} className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">
<div className="sm:flex justify-between items-center">
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
<div
className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">
<img src={bank1} alt=""/>
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium">
{value.description}
</p>
</div>
</div>
<div>
<p className="eth text-xl font-bold text-purple">
{(value.amount*0.01).toFixed(2)} {value.code}
</p>
<p className="usd text-base text-thin-light-gray text-right">
{/*(773.69 USD)*/}
</p>
</div>
</div>
</li>
))}
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank1} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* MetaMask*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 75,320 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank2} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* Coinbase Wallet*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 56,124 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank3} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* Bitski*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 99,123 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
{/*<li className="content-item py-5">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank4} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* WalletConnect*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 43,728 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
</ul>
<div className="add-money-btn flex justify-center items-center mt-3">
{/* <button
onClick={() => props.addMoneyHandler()}
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank1} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* MetaMask*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 75,320 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank2} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* Coinbase Wallet*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 56,124 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank3} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* Bitski*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 99,123 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
{/*<li className="content-item py-5">*/}
{/* <div className="sm:flex justify-between items-center">*/}
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
{/* <div*/}
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
{/* <img src={bank4} alt=""/>*/}
{/* </div>*/}
{/* <div className="name">*/}
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
{/* WalletConnect*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="eth text-xl font-bold text-purple">*/}
{/* 43,728 ETH*/}
{/* </p>*/}
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
{/* (773.69 USD)*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/*</li>*/}
</ul>
<div className="add-money-btn flex justify-center items-center mt-3">
{/* <button
onClick={() => {
if(pathname == '/my-wallet') props.setBalanceDropdown.toggle()
else navigate('/my-wallet', {replace: true})
}}
type="button"
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</button> */}
<Link to='/my-wallet' className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">Manage</Link>
</div>
</div>
</div>
<Link
to="/my-wallet"
onClick={() => {
if (pathname == "/my-wallet")
props.setBalanceDropdown.toggle();
else navigate("/my-wallet", { replace: true });
}}
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</Link>
</div>
{/*<div*/}
{/* className="lg:hidden flex user-balance cursor-pointer lg:w-[252px] w-[150px] h-[48px] items-center rounded-full relative bg-purple">*/}
{/* <div className="flex items-center lg:justify-between justify-center w-full h-full">*/}
{/* <p className="lg:text-xl text-lg font-bold text-white">*/}
{/* $ 234,435.34*/}
{/* </p>*/}
{/* </div>*/}
{/*</div>*/}
<div className="lg:hidden block"></div>
</>);
</div>
</div>
</div>
{/*<div*/}
{/* className="lg:hidden flex user-balance cursor-pointer lg:w-[252px] w-[150px] h-[48px] items-center rounded-full relative bg-purple">*/}
{/* <div className="flex items-center lg:justify-between justify-center w-full h-full">*/}
{/* <p className="lg:text-xl text-lg font-bold text-white">*/}
{/* $ 234,435.34*/}
{/* </p>*/}
{/* </div>*/}
{/*</div>*/}
<div className="lg:hidden block"></div>
</>
);
}
+1 -1
View File
@@ -5,7 +5,7 @@ const PaginatedList = ({ onClick, prev, next, data, start, stop }) => {
if(data.length){
return (
<div className='p-3 flex justify-center items-center space-x-2'>
<div className='p-3 flex justify-center items-center space-x-2 border-t-2'>
{/* Render pagination buttons */}
{!prev &&
<button
+12 -2
View File
@@ -1,5 +1,5 @@
import React, { useContext,useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
import bank1 from "../../assets/images/bank-1.png";
import bank2 from "../../assets/images/bank-2.png";
import bank3 from "../../assets/images/bank-3.png";
@@ -91,6 +91,15 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
setToggleNotification.toggle()
}
// getting the location of head
let {pathname} = useLocation()
const handleWalletBtn = () => {
if (pathname === "/my-wallet"){
setbalanceValue.set(false)
} else return balanceDropdown
}
// User Profile
let {firstname, lastname, email, profile_pic} = userDetails
let userEmail = email.split('@')[0]
@@ -234,7 +243,8 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
myWalletList={myWalletList}
handlerBalance={handlerBalance}
balanceDropdown={balanceDropdown}
addMoneyHandler={addMoneyHandler} />
addMoneyHandler={addMoneyHandler}
setBalanceDropdown = {setbalanceValue} />
{/* notification */}
<div className="user-notification lg:block hidden relative">
<div
+2 -2
View File
@@ -90,7 +90,7 @@ export default function Layout({ children }) {
</div>
{logoutModal && (
<ModalCom action={logoutModalHandler} situation={logoutModal}>
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Confirm
@@ -168,4 +168,4 @@ export default function Layout({ children }) {
)}
</>
);
}
}
+138 -76
View File
@@ -4,9 +4,16 @@ import logo from "../../assets/images/wrenchboard.png"; //logo-2.svg";
import logo3 from "../../assets/images/wrenchboard.png"; //logo-3.svg";
import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons";
import { useSelector } from "react-redux";
export default function MobileSidebar({ sidebar, action, logoutModalHandler }) {
let { userDetails } = useSelector((state) => state.userDetails);
const darkMode = useContext(DarkModeContext);
let { jobLists } = useSelector((state) => state.jobLists);
const marketData = jobLists?.result_list;
let noOfJobs = marketData?.length;
return (
<div className="w-full h-full">
{/* logo-area */}
@@ -73,49 +80,20 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler }) {
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
className="nav-item flex items-center justify-start space-x-3.5"
to="/"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="dashboard" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
Dashboard
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/market"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="active-bids" />
</span>
<span className="item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium active flex-1">
Market
<span className="absolute left-24 -top-1 text-sm flex justify-center items-center w-5 h-5 primary-gradient rounded-full text-white">
0
</span>
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/mytask"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="market" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
My Task(s)
</span>
</NavLink>
</li>
{/* Using mini component reduces the bulk amount of html */}
{[
{ name: "Dashboard", path: "/" },
{ name: "Market", path: "/market", bubble: noOfJobs },
{ name: "My Task(s)", path: "/mytask" },
].map(({ name, path, bubble }, idx) => (
<ListItem
key={idx}
title={name}
route={path}
bubble={bubble}
sidebar
/>
))}
{/*<li className="item group">*/}
{/* <NavLink*/}
{/* to="/notification"*/}
@@ -184,41 +162,95 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler }) {
</ul>
</div>
</div>
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">My Jobs</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
to="/myjobs"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="people-two" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
My Jobs
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/market"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="setting" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
Active Job(s)
</span>
</NavLink>
</li>
</ul>
{!userDetails.post_jobs ?
<div className="setting-item">
<div className="top-platform bg-pink dark:bg-dark-white rounded-2xl p-16 2xl:w-[180px] w-full 2xl:mb-10 2xl:border-none border ">
<NavLink to="/start-job" className="nav-item flex items-center justify-start space-x-3.5">
<span className="item-content relative group-hover:text-purple text-xl transition-all duration-300 ease-in-out text-lighter-gray font-medium active flex-1">
Enable Job Post
</span>
</NavLink>
</div>
</div>
:
jobLists?.result_list?.length ?
(
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">My Jobs</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
to="/myjobs"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="people-two" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
My Jobs
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/my-active-jobs"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="setting" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
Pending
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/my-active-jobs"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="setting" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
Active Job(s)
</span>
</NavLink>
</li>
</ul>
</div>
</div>
)
:
(
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">My Jobs</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
to="/add-job"
className="nav-item flex items-center justify-start space-x-3.5"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white">
<Icons name="people-two" />
</span>
<span className="item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium active flex-1">
My Jobs
</span>
</NavLink>
</li>
</ul>
</div>
</div>
)
}
</div>
{/* signout area */}
{sidebar ? (
@@ -284,3 +316,33 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler }) {
</div>
);
}
const ListItem = ({ sidebar, route, title, bubble }) => {
return (
<li className="item group">
<NavLink
to={route}
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="market" />
</span>
<span
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
{title && title}
{bubble && (
<span className="absolute left-24 -top-1 text-sm flex justify-center items-center w-5 h-5 primary-gradient rounded-full text-white">
{bubble}
</span>
)}
</span>
</NavLink>
</li>
);
};
+51 -193
View File
@@ -1,18 +1,6 @@
import React, { useState } from "react";
import topCreator1 from "../../assets/images/top-creator-1.png";
import topCreator2 from "../../assets/images/top-creator-2.png";
import topCreator3 from "../../assets/images/top-creator-3.png";
import topCreator4 from "../../assets/images/top-creator-4.png";
import topCreator5 from "../../assets/images/top-creator-5.png";
import DoughnutChart from "../Charts/DoughnutChart";
import MiniLineChart from "../Charts/MiniLineChart";
import Icons from "../Helpers/Icons";
import BtcIco from "../Helpers/Icons/BtcIco";
import EthIco from "../Helpers/Icons/EthIco";
import LtcIco from "../Helpers/Icons/LtcIco";
import Usdt from "../Helpers/Icons/Usdt";
import SelectBox from "../Helpers/SelectBox";
import { NavLink } from "react-router-dom";
//import SideStatistics from "./SideStatistics";
export default function RightSideBar() {
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
@@ -41,6 +29,7 @@ export default function RightSideBar() {
}
setRateStaticsDropdown(!filterRateStatics);
};
return (
<>
<div className="right-sidebar-wrapper overflow-y-scroll overflow-style-none 2xl:fixed 2xl:grid-cols-none 2xl:block grid lg:grid-cols-2 grid-cols-1 xl:gap-7 gap-4 h-full 2xl:pb-96">
@@ -50,8 +39,7 @@ export default function RightSideBar() {
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
Quick Links
</h3>
<div>
</div>
<div></div>
</div>
<div className="platform-list">
@@ -87,32 +75,29 @@ export default function RightSideBar() {
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.5745"
rx="20"
ry="19.9392"
fill="#FDD903"
cx="20"
cy="20.5745"
rx="20"
ry="19.9392"
fill="#FDD903"
/>
<path
d="M30.0432 20.1565C29.8181 20.2625 29.8101 20.5908 30.0328 20.7018C31.565 21.4629 32.3814 22.7261 32.4556 24.4068C32.5245 25.8708 32.4715 27.3349 32.4821 28.7989C32.4821 29.0738 32.3973 29.1636 32.1216 29.1636C30.0169 29.153 27.907 29.153 25.8023 29.1636C25.4524 29.1636 25.4471 28.9945 25.4471 28.7408C25.4524 27.5569 25.4524 26.3782 25.4471 25.1943C25.4418 23.91 24.9169 23.318 23.6287 23.3022C20.8825 23.2705 18.1417 23.2916 15.3955 23.2757C15.0615 23.2757 15.035 23.4237 15.035 23.688C15.0456 25.3476 15.0297 27.0072 15.0456 28.6668C15.0509 29.0526 14.9608 29.1742 14.5526 29.1689C12.5327 29.1478 10.5182 29.1478 8.49834 29.1689C8.09543 29.1742 8 29.0632 8 28.6668C8.0106 23.2123 8.0106 17.7578 8.0053 12.3034C8.0053 11.9757 8.03181 11.8013 8.44532 11.8013C14.1444 11.8171 19.8488 11.8066 25.5478 11.833C27.0216 11.8383 28.4901 11.9968 29.842 12.6469C31.5279 13.4609 32.3125 14.8562 32.2117 16.7748C32.1332 18.3693 31.4419 19.4977 30.0432 20.1565ZM19.6208 18.6035C20.909 18.6035 22.2026 18.6088 23.4909 18.5982C23.7877 18.5982 24.0952 18.5824 24.3868 18.5242C24.7791 18.4449 24.9965 18.186 25.0018 17.7737C25.0071 17.3509 24.8109 17.0549 24.3815 16.9809C24.0899 16.9281 23.7877 16.9016 23.4855 16.9016C21.084 16.8963 18.6771 16.8963 16.2756 16.8963C15.0191 16.8963 15.035 16.8963 15.0297 18.1701C15.0297 18.5295 15.1464 18.6088 15.4804 18.6035C16.864 18.5929 18.2424 18.6035 19.6208 18.6035Z"
fill="#020200"
d="M30.0432 20.1565C29.8181 20.2625 29.8101 20.5908 30.0328 20.7018C31.565 21.4629 32.3814 22.7261 32.4556 24.4068C32.5245 25.8708 32.4715 27.3349 32.4821 28.7989C32.4821 29.0738 32.3973 29.1636 32.1216 29.1636C30.0169 29.153 27.907 29.153 25.8023 29.1636C25.4524 29.1636 25.4471 28.9945 25.4471 28.7408C25.4524 27.5569 25.4524 26.3782 25.4471 25.1943C25.4418 23.91 24.9169 23.318 23.6287 23.3022C20.8825 23.2705 18.1417 23.2916 15.3955 23.2757C15.0615 23.2757 15.035 23.4237 15.035 23.688C15.0456 25.3476 15.0297 27.0072 15.0456 28.6668C15.0509 29.0526 14.9608 29.1742 14.5526 29.1689C12.5327 29.1478 10.5182 29.1478 8.49834 29.1689C8.09543 29.1742 8 29.0632 8 28.6668C8.0106 23.2123 8.0106 17.7578 8.0053 12.3034C8.0053 11.9757 8.03181 11.8013 8.44532 11.8013C14.1444 11.8171 19.8488 11.8066 25.5478 11.833C27.0216 11.8383 28.4901 11.9968 29.842 12.6469C31.5279 13.4609 32.3125 14.8562 32.2117 16.7748C32.1332 18.3693 31.4419 19.4977 30.0432 20.1565ZM19.6208 18.6035C20.909 18.6035 22.2026 18.6088 23.4909 18.5982C23.7877 18.5982 24.0952 18.5824 24.3868 18.5242C24.7791 18.4449 24.9965 18.186 25.0018 17.7737C25.0071 17.3509 24.8109 17.0549 24.3815 16.9809C24.0899 16.9281 23.7877 16.9016 23.4855 16.9016C21.084 16.8963 18.6771 16.8963 16.2756 16.8963C15.0191 16.8963 15.035 16.8963 15.0297 18.1701C15.0297 18.5295 15.1464 18.6088 15.4804 18.6035C16.864 18.5929 18.2424 18.6035 19.6208 18.6035Z"
fill="#020200"
/>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink
to="/history">
History
</NavLink>
<NavLink to="/history">History</NavLink>
</p>
</div>
{/* action */}
@@ -121,31 +106,31 @@ export default function RightSideBar() {
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.4043"
rx="20"
ry="19.9392"
fill="url(#paint0_linear_249_2794)"
cx="20"
cy="20.4043"
rx="20"
ry="19.9392"
fill="url(#paint0_linear_249_2794)"
/>
<path
d="M16.7403 14.4243C17.8836 14.4243 19.0272 14.4261 20.1705 14.4233C20.5666 14.4226 20.9612 14.4431 21.3489 14.5184C22.272 14.698 23.0864 15.0843 23.742 15.7545C23.8172 15.8312 23.8625 15.8401 23.9512 15.7762C24.8988 15.091 25.9527 14.6419 27.1244 14.484C27.8811 14.3821 28.6353 14.4115 29.3836 14.5947C30.3403 14.829 31.1613 15.277 31.8103 16.0013C32.413 16.674 32.7934 17.4511 32.9361 18.3386C33.054 19.0731 32.9989 19.7955 32.8499 20.5197C32.6718 21.3867 32.5167 22.2578 32.3477 23.1265C32.1933 23.92 32.0337 24.7123 31.8768 25.5054C31.7749 26.0202 31.6807 26.5367 31.5694 27.0493C31.5198 27.2772 31.3745 27.371 31.1365 27.3713C29.9446 27.3727 28.7528 27.3742 27.561 27.3745C27.2971 27.3745 27.1996 27.273 27.2463 27.0252C27.3872 26.2776 27.5365 25.5313 27.6807 24.7844C27.8136 24.095 27.9428 23.4052 28.076 22.7158C28.2148 21.9976 28.356 21.2798 28.4958 20.5616C28.5601 20.2311 28.6272 19.9038 28.5196 19.5662C28.3527 19.0422 27.8877 18.7075 27.3171 18.667C26.2023 18.5882 25.2894 19.4682 25.1459 20.415C25.0269 21.2017 24.844 21.9788 24.6918 22.7609C24.5703 23.386 24.4546 24.0126 24.3319 24.6378C24.1727 25.4483 24.0125 26.2587 23.8446 27.0674C23.8026 27.2694 23.65 27.3749 23.4365 27.3752C22.2322 27.377 21.028 27.3774 19.8237 27.3763C19.5956 27.3759 19.4854 27.2393 19.5292 27.0142C19.6609 26.3365 19.7956 25.6591 19.9278 24.9814C20.0869 24.1649 20.2446 23.3481 20.4031 22.5312C20.5549 21.7495 20.7017 20.9671 20.8604 20.1868C21.013 19.4359 20.4038 18.7124 19.6179 18.6688C18.5688 18.6102 17.6843 19.3695 17.4934 20.2162C17.3587 20.8144 17.2583 21.42 17.1415 22.0225C16.9389 23.0648 16.7359 24.1067 16.5322 25.1486C16.4114 25.7681 16.2895 26.3873 16.1683 27.0067C16.1187 27.2602 15.9832 27.3798 15.7197 27.3802C13.4145 27.3816 11.1097 27.3816 8.8045 27.3795C8.47305 27.3791 8.20621 27.1083 8.20548 26.7866C8.20475 26.471 8.48911 26.192 8.82823 26.1902C9.56414 26.186 10.3 26.1916 11.0359 26.1863C11.4995 26.1828 11.7854 25.749 11.5864 25.3581C11.5003 25.1888 11.3524 25.0904 11.1641 25.0503C11.0078 25.0169 10.8491 25.0304 10.6914 25.0301C9.77293 25.029 8.85451 25.0304 7.93645 25.0287C7.58712 25.0279 7.36408 24.893 7.27063 24.636C7.12754 24.242 7.42395 23.8444 7.87878 23.8323C8.18869 23.8241 8.49897 23.8305 8.80925 23.8305C9.95253 23.8302 11.0962 23.8312 12.2395 23.8287C12.5326 23.828 12.7702 23.6388 12.8148 23.3814C12.867 23.0807 12.7301 22.839 12.4494 22.7243C12.3493 22.6835 12.2468 22.6885 12.1442 22.6885C11.2805 22.687 10.4169 22.687 9.55318 22.6863C9.25933 22.686 9.03557 22.5749 8.91766 22.3001C8.76471 21.944 8.9998 21.5713 9.39257 21.5209C10.0653 21.4346 10.7403 21.5028 11.4138 21.4793C11.5171 21.4758 11.6207 21.4804 11.7237 21.4719C12.0642 21.4435 12.2891 21.206 12.2814 20.8886C12.2741 20.5943 12.0037 20.3351 11.6861 20.3277C11.4127 20.3213 11.1385 20.3316 10.8651 20.3231C10.5895 20.3142 10.3292 20.098 10.2884 19.8601C10.2362 19.5556 10.365 19.3056 10.633 19.1849C10.7487 19.1327 10.871 19.1402 10.9914 19.1398C11.7211 19.1367 12.4512 19.1388 13.1809 19.1342C13.5488 19.1317 13.7376 19.0099 13.8482 18.7444C13.9891 18.4064 13.6992 18.0148 13.3919 17.9829C13.1791 17.9609 12.967 17.9687 12.7549 17.9683C11.8124 17.9673 10.8699 17.9729 9.92734 17.9744C9.65539 17.9747 9.39002 17.6992 9.37468 17.4074C9.35899 17.1096 9.62181 16.8153 9.93318 16.7865C10.0117 16.7794 10.0912 16.7826 10.1701 16.7826C11.5689 16.7823 12.9677 16.783 14.3665 16.7819C14.6666 16.7816 14.8754 16.6342 14.9535 16.3754C15.0312 16.1184 14.9316 15.8546 14.702 15.7112C14.5728 15.6303 14.4264 15.625 14.28 15.6246C13.8055 15.6235 13.3313 15.6285 12.8567 15.6221C12.4822 15.6171 12.2252 15.4088 12.1876 15.0964C12.1435 14.7271 12.4253 14.4282 12.8359 14.4254C13.5963 14.4204 14.3563 14.4236 15.1167 14.4236C15.658 14.4236 16.1993 14.4236 16.7407 14.4236C16.7403 14.424 16.7403 14.424 16.7403 14.4243Z"
fill="white"
d="M16.7403 14.4243C17.8836 14.4243 19.0272 14.4261 20.1705 14.4233C20.5666 14.4226 20.9612 14.4431 21.3489 14.5184C22.272 14.698 23.0864 15.0843 23.742 15.7545C23.8172 15.8312 23.8625 15.8401 23.9512 15.7762C24.8988 15.091 25.9527 14.6419 27.1244 14.484C27.8811 14.3821 28.6353 14.4115 29.3836 14.5947C30.3403 14.829 31.1613 15.277 31.8103 16.0013C32.413 16.674 32.7934 17.4511 32.9361 18.3386C33.054 19.0731 32.9989 19.7955 32.8499 20.5197C32.6718 21.3867 32.5167 22.2578 32.3477 23.1265C32.1933 23.92 32.0337 24.7123 31.8768 25.5054C31.7749 26.0202 31.6807 26.5367 31.5694 27.0493C31.5198 27.2772 31.3745 27.371 31.1365 27.3713C29.9446 27.3727 28.7528 27.3742 27.561 27.3745C27.2971 27.3745 27.1996 27.273 27.2463 27.0252C27.3872 26.2776 27.5365 25.5313 27.6807 24.7844C27.8136 24.095 27.9428 23.4052 28.076 22.7158C28.2148 21.9976 28.356 21.2798 28.4958 20.5616C28.5601 20.2311 28.6272 19.9038 28.5196 19.5662C28.3527 19.0422 27.8877 18.7075 27.3171 18.667C26.2023 18.5882 25.2894 19.4682 25.1459 20.415C25.0269 21.2017 24.844 21.9788 24.6918 22.7609C24.5703 23.386 24.4546 24.0126 24.3319 24.6378C24.1727 25.4483 24.0125 26.2587 23.8446 27.0674C23.8026 27.2694 23.65 27.3749 23.4365 27.3752C22.2322 27.377 21.028 27.3774 19.8237 27.3763C19.5956 27.3759 19.4854 27.2393 19.5292 27.0142C19.6609 26.3365 19.7956 25.6591 19.9278 24.9814C20.0869 24.1649 20.2446 23.3481 20.4031 22.5312C20.5549 21.7495 20.7017 20.9671 20.8604 20.1868C21.013 19.4359 20.4038 18.7124 19.6179 18.6688C18.5688 18.6102 17.6843 19.3695 17.4934 20.2162C17.3587 20.8144 17.2583 21.42 17.1415 22.0225C16.9389 23.0648 16.7359 24.1067 16.5322 25.1486C16.4114 25.7681 16.2895 26.3873 16.1683 27.0067C16.1187 27.2602 15.9832 27.3798 15.7197 27.3802C13.4145 27.3816 11.1097 27.3816 8.8045 27.3795C8.47305 27.3791 8.20621 27.1083 8.20548 26.7866C8.20475 26.471 8.48911 26.192 8.82823 26.1902C9.56414 26.186 10.3 26.1916 11.0359 26.1863C11.4995 26.1828 11.7854 25.749 11.5864 25.3581C11.5003 25.1888 11.3524 25.0904 11.1641 25.0503C11.0078 25.0169 10.8491 25.0304 10.6914 25.0301C9.77293 25.029 8.85451 25.0304 7.93645 25.0287C7.58712 25.0279 7.36408 24.893 7.27063 24.636C7.12754 24.242 7.42395 23.8444 7.87878 23.8323C8.18869 23.8241 8.49897 23.8305 8.80925 23.8305C9.95253 23.8302 11.0962 23.8312 12.2395 23.8287C12.5326 23.828 12.7702 23.6388 12.8148 23.3814C12.867 23.0807 12.7301 22.839 12.4494 22.7243C12.3493 22.6835 12.2468 22.6885 12.1442 22.6885C11.2805 22.687 10.4169 22.687 9.55318 22.6863C9.25933 22.686 9.03557 22.5749 8.91766 22.3001C8.76471 21.944 8.9998 21.5713 9.39257 21.5209C10.0653 21.4346 10.7403 21.5028 11.4138 21.4793C11.5171 21.4758 11.6207 21.4804 11.7237 21.4719C12.0642 21.4435 12.2891 21.206 12.2814 20.8886C12.2741 20.5943 12.0037 20.3351 11.6861 20.3277C11.4127 20.3213 11.1385 20.3316 10.8651 20.3231C10.5895 20.3142 10.3292 20.098 10.2884 19.8601C10.2362 19.5556 10.365 19.3056 10.633 19.1849C10.7487 19.1327 10.871 19.1402 10.9914 19.1398C11.7211 19.1367 12.4512 19.1388 13.1809 19.1342C13.5488 19.1317 13.7376 19.0099 13.8482 18.7444C13.9891 18.4064 13.6992 18.0148 13.3919 17.9829C13.1791 17.9609 12.967 17.9687 12.7549 17.9683C11.8124 17.9673 10.8699 17.9729 9.92734 17.9744C9.65539 17.9747 9.39002 17.6992 9.37468 17.4074C9.35899 17.1096 9.62181 16.8153 9.93318 16.7865C10.0117 16.7794 10.0912 16.7826 10.1701 16.7826C11.5689 16.7823 12.9677 16.783 14.3665 16.7819C14.6666 16.7816 14.8754 16.6342 14.9535 16.3754C15.0312 16.1184 14.9316 15.8546 14.702 15.7112C14.5728 15.6303 14.4264 15.625 14.28 15.6246C13.8055 15.6235 13.3313 15.6285 12.8567 15.6221C12.4822 15.6171 12.2252 15.4088 12.1876 15.0964C12.1435 14.7271 12.4253 14.4282 12.8359 14.4254C13.5963 14.4204 14.3563 14.4236 15.1167 14.4236C15.658 14.4236 16.1993 14.4236 16.7407 14.4236C16.7403 14.424 16.7403 14.424 16.7403 14.4243Z"
fill="white"
/>
<defs>
<linearGradient
id="paint0_linear_249_2794"
x1="3"
y1="16.4165"
x2="26.9783"
y2="26.4379"
gradientUnits="userSpaceOnUse"
id="paint0_linear_249_2794"
x1="3"
y1="16.4165"
x2="26.9783"
y2="26.4379"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#E100C5" />
<stop offset="1" stopColor="#FF812B" />
@@ -156,8 +141,7 @@ export default function RightSideBar() {
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink
to="/referral">Refer a Friend</NavLink>
<NavLink to="/referral">Refer a Friend</NavLink>
</p>
</div>
</div>
@@ -165,165 +149,39 @@ export default function RightSideBar() {
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.2341"
rx="20"
ry="19.9392"
fill="#5165FF"
cx="20"
cy="20.2341"
rx="20"
ry="19.9392"
fill="#5165FF"
/>
<path
d="M26.1647 27.2085C22.5316 27.2448 19.3317 24.2111 19.3359 20.2195C19.3402 16.4128 22.3393 13.2525 26.1704 13.2554C30.0813 13.2583 33.012 16.5264 33.0006 20.2501C32.9892 24.1456 29.8505 27.2492 26.1647 27.2085Z"
fill="white"
d="M26.1647 27.2085C22.5316 27.2448 19.3317 24.2111 19.3359 20.2195C19.3402 16.4128 22.3393 13.2525 26.1704 13.2554C30.0813 13.2583 33.012 16.5264 33.0006 20.2501C32.9892 24.1456 29.8505 27.2492 26.1647 27.2085Z"
fill="white"
/>
<path
d="M20.5815 27.1983C20.5217 27.2245 20.4405 27.207 20.3607 27.207C16.0039 27.2085 11.647 27.2085 7.29019 27.2085C7.25742 27.2085 7.22465 27.2099 7.1933 27.2085C7.01094 27.2026 7.00951 27.2026 7.00381 27.0076C7.00239 26.9581 7.00381 26.9086 7.00381 26.8576C7.00381 22.4395 7.00381 18.0214 7.00381 13.6033C7.00381 13.5072 6.99099 13.4082 7.01236 13.334C11.5373 17.9559 16.0566 22.5749 20.5815 27.1983Z"
fill="white"
d="M20.5815 27.1983C20.5217 27.2245 20.4405 27.207 20.3607 27.207C16.0039 27.2085 11.647 27.2085 7.29019 27.2085C7.25742 27.2085 7.22465 27.2099 7.1933 27.2085C7.01094 27.2026 7.00951 27.2026 7.00381 27.0076C7.00239 26.9581 7.00381 26.9086 7.00381 26.8576C7.00381 22.4395 7.00381 18.0214 7.00381 13.6033C7.00381 13.5072 6.99099 13.4082 7.01236 13.334C11.5373 17.9559 16.0566 22.5749 20.5815 27.1983Z"
fill="white"
/>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink
to="/resources">
Resources
</NavLink>
<NavLink to="/resources">Resources</NavLink>
</p>
</div>
</div>
</div>
</div>
<div className="chart-one bg-white dark:bg-dark-white rounded-2xl p-8 2xl:w-[268px] w-full 2xl:mb-10 2xl:border-none border flex flex-col sm:flex-row 2xl:flex-col 2xl:block lg:justify-between sm:items-center space-x-5 2xl:space-x-0 ">
<div>
<div className="chart-heading mb-4 xl:flex justify-between items-center">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
Statistics
</h3>
<SelectBox datas={filterDatas} action={dataSetHandler} />
</div>
<div id="chartjs-tooltip" className="chart relative 2xl:mb-6">
<DoughnutChart dataSets={filterDataSet} />
<div className="sm:flex hidden absolute 2xl:top-[19%] 2xl:left-[20%] xl:top-[28%] xl:left-[28%] lg:left-[20%] lg:top-[20%] left-[30%] top-[30%] justify-center">
<span>
<svg
width="123"
height="123"
viewBox="0 0 123 123"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M70.7788 45.749C70.7788 46.2809 70.7788 46.5811 70.7788 46.8865C70.7788 59.9678 70.7735 73.0544 70.8052 86.1357C70.8052 87.0204 70.5881 87.2679 69.7035 87.2311C67.8601 87.1573 66.0167 87.1889 64.1733 87.2205C63.5324 87.2311 63.2464 87.1257 63.2517 86.3779C63.2781 74.7396 63.2728 63.1012 63.2728 51.4681C63.2728 51.0784 63.2623 50.7467 63.6807 50.4781C65.9849 48.9667 68.268 47.4237 70.7788 45.749Z"
fill="#ECECEC"
/>
<path
d="M81.6339 55.6284C81.6339 56.0918 81.6339 56.3604 81.6339 56.6343C81.6339 66.4663 81.6233 76.2983 81.6604 86.1304C81.6657 87.0098 81.4432 87.2574 80.5586 87.2258C78.6835 87.152 76.803 87.1731 74.9226 87.2205C74.2392 87.2363 74.1068 87.0046 74.1068 86.3832C74.128 78.0309 74.1227 69.6787 74.128 61.3265C74.128 61.021 74.0379 60.6893 74.3717 60.4628C76.75 58.8882 79.1178 57.3083 81.6339 55.6284Z"
fill="#ECECEC"
/>
<path
d="M56.158 64.1334C54.3623 64.1228 53.0433 62.8115 53.0698 60.942C53.0751 60.3891 52.9109 60.1258 52.4553 59.894C51.1046 59.2042 49.7591 58.4932 48.4296 57.756C47.9528 57.4926 47.6138 57.4505 47.1106 57.8086C45.8658 58.6933 44.2767 58.5512 43.1908 57.5769C42.1684 56.6606 41.8771 55.007 42.5233 53.7905C43.1855 52.5371 44.6581 51.8736 46.03 52.2106C47.5026 52.5687 48.456 53.7115 48.4243 55.2808C48.4137 55.8864 48.6308 56.1708 49.1129 56.4131C50.0293 56.8765 50.9351 57.3505 51.8356 57.8507C52.8844 58.4353 53.9067 59.2568 55.0827 58.093C55.1038 58.0719 55.1515 58.0561 55.1833 58.0561C57.0955 58.1983 57.4239 56.708 58.0384 55.4178C59.8765 51.5787 61.7781 47.7659 63.6586 43.9427C63.844 43.5635 64.0294 43.1843 64.2201 42.8051C64.665 41.9099 65.11 41.1463 64.2677 40.0825C63.4573 39.0661 63.9022 37.4336 64.861 36.5173C65.8568 35.5746 67.2765 35.3798 68.5001 36.017C69.729 36.6595 70.4229 38.0024 70.0415 39.4032C69.8349 40.1615 70.0574 40.5407 70.5818 40.9988C72.2557 42.4681 73.9031 43.969 75.524 45.4962C75.9424 45.8912 76.2656 45.9596 76.8164 45.749C78.199 45.2171 79.6821 45.7174 80.4661 46.8917C81.2236 48.0187 81.1388 49.6249 80.2754 50.636C79.3431 51.7261 77.8176 52.0474 76.5145 51.426C75.2167 50.8045 74.4646 49.4406 74.8671 48.0029C75.079 47.234 74.8512 46.8654 74.3321 46.4125C72.69 44.9643 71.0639 43.4898 69.4641 41.9889C69.0033 41.5518 68.5901 41.3253 68.0022 41.694C67.9439 41.7308 67.8644 41.7782 67.8062 41.7677C66.2435 41.4939 65.9204 42.7051 65.4278 43.7215C63.5103 47.6817 61.5768 51.6313 59.6699 55.5968C59.2991 56.3657 58.727 57.0187 58.4992 57.8876C58.3562 58.4353 58.3827 58.7513 58.7111 59.1989C59.4633 60.2206 59.5216 61.3686 58.9336 62.4903C58.3509 63.5857 57.3975 64.1176 56.158 64.1334Z"
fill="url(#paint0_linear_197_92226)"
/>
<path
d="M49.0697 62.2479C49.0697 68.0039 49.0697 73.5018 49.0697 78.9998C49.0697 81.4696 49.0485 83.9342 49.0856 86.4041C49.0962 87.0676 48.8949 87.2362 48.2434 87.2204C46.2941 87.1782 44.3395 87.1835 42.3901 87.2204C41.7863 87.2309 41.532 87.1203 41.5373 86.4252C41.5691 80.2531 41.5532 74.0811 41.5585 67.9091C41.5585 67.6037 41.4896 67.293 41.8339 67.0613C44.1911 65.513 46.5324 63.9436 49.0697 62.2479Z"
fill="#ECECEC"
/>
<path
d="M59.9298 68.0092C59.9298 74.355 59.9245 80.4796 59.9351 86.6042C59.9351 87.0518 59.7973 87.2203 59.3312 87.2151C57.2071 87.194 55.083 87.1993 52.9589 87.2151C52.5457 87.2203 52.408 87.0729 52.408 86.6674C52.4186 82.2648 52.4186 77.8675 52.4133 73.465C52.4133 73.149 52.5298 72.9489 52.7946 72.7751C55.1095 71.2321 57.419 69.6838 59.9298 68.0092Z"
fill="#ECECEC"
/>
<path
d="M30.9572 92.2319C14.058 75.3327 14.058 47.8462 30.9572 30.947C47.8564 14.0478 75.3428 14.0478 92.242 30.947C109.141 47.8462 109.141 75.3327 92.242 92.2319C75.3428 109.131 47.8564 109.131 30.9572 92.2319ZM90.691 32.498C74.655 16.462 48.5577 16.4485 32.5082 32.498C16.4722 48.534 16.4722 74.6448 32.5082 90.6809C48.5442 106.717 74.655 106.717 90.691 90.6809C106.727 74.6448 106.727 48.534 90.691 32.498Z"
fill="#EBEDED"
/>
<defs>
<linearGradient
id="paint0_linear_197_92226"
x1="42.1803"
y1="35.6461"
x2="71.0724"
y2="74.1629"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F539F8" />
<stop offset="0.416763" stopColor="#C342F9" />
<stop offset="1" stopColor="#5356FB" />
</linearGradient>
</defs>
</svg>
</span>
</div>
</div>
</div>
<div className="chart-analysis mt-5">
<div className="heading text-center">
<h1 className="text-base font-medium text-dark-gray dark:text-white mb-4">
Your All Artwork Statistics
</h1>
</div>
<div className="analysis-list">
<ul>
<li className="flex items-center mb-3.5">
<span className="w-4 h-4 bg-light-purple rounded-full block mr-2"></span>
<div>
<span className="text-sm text-thin-light-gray mr-2">
Profit :
</span>
<span className="text-sm text-dark-gray dark:text-white font-bold">
{/* don't change variable only change state */}
{filterDataSet[0]}%
</span>
</div>
</li>
<li className="flex items-center mb-3.5">
<span className="w-4 h-4 bg-purple rounded-full block mr-2"></span>
<div>
<span className="text-sm text-thin-light-gray mr-2">
Total Sold :
</span>
<span className="text-sm text-dark-gray dark:text-white font-bold">
{/* don't change variable only change state */}
{filterDataSet[1]}%
</span>
</div>
</li>
<li className="flex items-center mb-3.5">
<span className="w-4 h-4 bg-pink rounded-full block mr-2"></span>
<div>
<span className="text-sm text-thin-light-gray mr-2">
Total Sold :
</span>
<span className="text-sm text-dark-gray dark:text-white font-bold">
{/* don't change variable only change state */}
{filterDataSet[2]}%
</span>
</div>
</li>
<li className="flex items-center mb-3.5">
<span className="w-4 h-4 bg-[#FFCD00] rounded-full block mr-2"></span>
<div>
<span className="text-sm text-thin-light-gray mr-2">
Total Sold :
</span>
<span className="text-sm text-dark-gray dark:text-white font-bold">
{/* don't change variable only change state */}
{filterDataSet[3]}%
</span>
</div>
</li>
</ul>
</div>
</div>
</div>
{/*<SideStatistics />*/}
</div>
</>
);
@@ -3,6 +3,12 @@ import DoughnutChart from "../Charts/DoughnutChart";
import SelectBox from "../Helpers/SelectBox";
export default function SideStatistics() {
const showStats = false;
if( showStats == false){
return '';
}
debugger;
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
const [filterDataSet, setFilterDataSet] = useState([10, 30, 20, 40]);
const dataSetHandler = (value) => {
+224 -167
View File
@@ -4,9 +4,17 @@ import logo from "../../assets/images/wrenchboard.png"; //logo-2.svg";
import logo3 from "../../assets/images/wrenchboard.png"; //logo-3.svg";
import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons";
import { useSelector } from "react-redux";
export default function Sidebar({ sidebar, action, logoutModalHandler }) {
const darkMode = useContext(DarkModeContext);
let { userDetails } = useSelector((state) => state.userDetails);
let { jobLists } = useSelector((state) => state.jobLists);
const marketData = jobLists?.result_list;
let noOfJobs = marketData?.length;
useEffect(() => {
const title = document.querySelectorAll(".menu-setting-items .heading");
if (sidebar) {
@@ -93,69 +101,20 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
} `}
to="/"
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="dashboard" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
Dashboard
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/market"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="market" />
</span>
<span
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
Market
<span className="absolute left-24 -top-1 text-sm flex justify-center items-center w-5 h-5 primary-gradient rounded-full text-white">
0
</span>
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/mytask"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="active-bids" />
</span>
<span
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
My Task(s)
</span>
</NavLink>
</li>
{/* Using mini component reduces the bulk amount of html */}
{[
{ name: "Dashboard", path: "/" },
{ name: "Market", path: "/market", bubble: noOfJobs },
{ name: "My Task(s)", path: "/mytask" },
].map(({ name, path, bubble }, idx) => (
<ListItem
key={idx}
title={name}
route={path}
bubble={bubble}
sidebar
/>
))}
{/*<li className="item group">*/}
{/* <NavLink*/}
{/* to="/notification"*/}
@@ -216,7 +175,7 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
{/* </span>*/}
{/* </NavLink>*/}
{/*</li>*/}
{/*<li className="item group">*/}
{/* <NavLink*/}
{/* to="/history"*/}
@@ -261,113 +220,181 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
</ul>
</div>
</div>
<div className="setting-item">
<div class="top-platform bg-pink dark:bg-dark-white rounded-2xl p-6 2xl:w-[180px] w-full 2xl:mb-10 2xl:border-none border ">
<NavLink
to="/acc-family" >
<span className="item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium active flex-1">Family Account</span>
</NavLink>
</div>
</div>
<div className="setting-item">
<div
className="top-platform bg-pink dark:bg-dark-white rounded-2xl p-16 2xl:w-[180px] w-full 2xl:mb-10 2xl:border-none border ">
<NavLink
to="/start-job" >
<span className="item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium active flex-1">Enable Job Post</span>
</NavLink>
</div>
{/*<div className="setting-item">*/}
{/* <div class="heading bg-pink dark:bg-dark-white rounded-2xl p-6 2xl:w-[180px] w-full 2xl:mb-10 2xl:border-none border ">*/}
{/* <NavLink to="/acc-family">*/}
{/* <span className="item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium active flex-1">*/}
{/* Family Account*/}
{/* </span>*/}
{/* </NavLink>*/}
{/* </div>*/}
{/*</div>*/}
</div>
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">My Jobs</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
to="/myjobs"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
Job List
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/my-active-jobs"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
Active Jobs
</span>
</NavLink>
</li>
{/*<li className="item group">*/}
{/* <NavLink*/}
{/* to="/profile"*/}
{/* className={`nav-item flex items-center ${*/}
{/* ((navData) => (navData.isActive ? "active" : ""),*/}
{/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
{/* }`}*/}
{/* >*/}
{/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
{/* <Icons name="people-two" />*/}
{/* </span>*/}
{/* <span*/}
{/* className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${*/}
{/* sidebar ? "active flex-1" : "w-0"*/}
{/* }`}*/}
{/* >*/}
{/* My Profile*/}
{/* </span>*/}
{/* </NavLink>*/}
{/*</li>*/}
{/*<li className="item group">*/}
{/* <NavLink*/}
{/* to="/settings"*/}
{/* className={`nav-item flex items-center ${*/}
{/* ((navData) => (navData.isActive ? "active" : ""),*/}
{/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
{/* }`}*/}
{/* >*/}
{/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
{/* <Icons name="setting" />*/}
{/* </span>*/}
{/* <span*/}
{/* className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${*/}
{/* sidebar ? "active flex-1" : "w-0"*/}
{/* }`}*/}
{/* >*/}
{/* Settings*/}
{/* </span>*/}
{/* </NavLink>*/}
{/*</li>*/}
</ul>
<div className="heading mb-5 bg-dark-blue rounded-2xl p-2 2xl:w-[180px] w-full 2xl:mb-10 2xl:border-none border">
<NavLink to="/acc-family">
<h1 className="title text-xl font-bold text-purple">Family Corner</h1>
</NavLink>
</div>
</div>
{!userDetails.post_jobs ?
<div className="setting-item">
<div className="top-platform bg-pink dark:bg-dark-white rounded-2xl p-16 2xl:w-[180px] w-full 2xl:mb-10 2xl:border-none border ">
<NavLink to="/start-job">
<span className="item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium active flex-1">
Enable Job Post
</span>
</NavLink>
</div>
</div>
:
jobLists?.result_list?.length ?
(
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">My Jobs</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
to="/myjobs"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
List
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/my-pending-jobs"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
Pending
</span>
</NavLink>
</li>
<li className="item group">
<NavLink
to="/my-active-jobs"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
Active
</span>
</NavLink>
</li>
{/*<li className="item group">*/}
{/* <NavLink*/}
{/* to="/profile"*/}
{/* className={`nav-item flex items-center ${*/}
{/* ((navData) => (navData.isActive ? "active" : ""),*/}
{/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
{/* }`}*/}
{/* >*/}
{/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
{/* <Icons name="people-two" />*/}
{/* </span>*/}
{/* <span*/}
{/* className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${*/}
{/* sidebar ? "active flex-1" : "w-0"*/}
{/* }`}*/}
{/* >*/}
{/* My Profile*/}
{/* </span>*/}
{/* </NavLink>*/}
{/*</li>*/}
{/*<li className="item group">*/}
{/* <NavLink*/}
{/* to="/settings"*/}
{/* className={`nav-item flex items-center ${*/}
{/* ((navData) => (navData.isActive ? "active" : ""),*/}
{/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
{/* }`}*/}
{/* >*/}
{/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
{/* <Icons name="setting" />*/}
{/* </span>*/}
{/* <span*/}
{/* className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${*/}
{/* sidebar ? "active flex-1" : "w-0"*/}
{/* }`}*/}
{/* >*/}
{/* Settings*/}
{/* </span>*/}
{/* </NavLink>*/}
{/*</li>*/}
</ul>
</div>
</div>
)
:
(
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">My Jobs</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
<li className="item group">
<NavLink
to="/add-job"
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
Add Job
</span>
</NavLink>
</li>
</ul>
</div>
</div>
)
}
</div>
{/* signout area */}
{sidebar ? (
@@ -433,3 +460,33 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
</div>
);
}
const ListItem = ({ sidebar, route, title, bubble }) => {
return (
<li className="item group">
<NavLink
to={route}
className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center")
}`}
>
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
<Icons name="market" />
</span>
<span
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
{title && title}
{bubble && (
<span className="absolute left-24 -top-1 text-sm flex justify-center items-center w-5 h-5 primary-gradient rounded-full text-white">
{bubble}
</span>
)}
</span>
</NavLink>
</li>
);
};
+197 -186
View File
@@ -1,213 +1,224 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import usersService from '../../services/UsersService';
import InputCom from '../Helpers/Inputs/InputCom';
import LoadingSpinner from '../Spinners/LoadingSpinner';
import usersService from "../../services/UsersService";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import {Formik, Form} from 'formik'
import * as Yup from 'yup'
import { Form, Formik } from "formik";
import * as Yup from "yup";
import ReferralTable from "../MyWallet/WalletComponent/ReferralTable";
const validationSchema = Yup.object().shape({
email: Yup.string()
.email('Wrong email format')
.min(3, 'Minimum 3 characters')
.max(50, 'Maximum 50 characters')
.required('Email is required'),
firstname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Firstname is required'),
lastname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Lastname is required'),
})
const initialValues = {
firstname: '',
lastname: '',
email: ''
}
email: Yup.string()
.email("Wrong email format")
.min(3, "Minimum 3 characters")
.max(50, "Maximum 50 characters")
.required("Email is required"),
firstname: Yup.string()
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Firstname is required"),
lastname: Yup.string()
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Lastname is required"),
});
const initialValues = {
firstname: "",
lastname: "",
email: "",
};
function ReferralDisplay() {
const apiCall = new usersService() // GET API CALL
const navigate = useNavigate()
const apiCall = new usersService(); // GET API CALL
const navigate = useNavigate();
let [refHistoryReload, setRefHistoryReload] = useState(false) // Determines when referral history reloads
let [refHistoryReload, setRefHistoryReload] = useState(false); // Determines when referral history reloads
// STATE TO HOLD REFERRAL HISTORY
let [referralList, setReferralList] = useState({
loading: true,
error: false,
data: []
})
// STATE TO HOLD REFERRAL HISTORY
let [referralList, setReferralList] = useState({
loading: true,
error: false,
data: [],
});
let [error, setError] = useState({message: '', loading: false, status: false}) // for displaying error message on the page
let [error, setError] = useState({
message: "",
loading: false,
status: false,
}); // for displaying error message on the page
//function to call referral history API
const allReferrals = () => {
setReferralList({
loading: true,
error: false,
data: []
})
apiCall.getReferralHx().then((res)=>{
setReferralList((prev)=>{
return {...prev, loading: false, data:[...res.data.result_list]}
})
}).catch((error)=>{
setReferralList(prev => ({...prev, loading: false, error: true}))
})
}
//function to call referral history API
const allReferrals = () => {
setReferralList({
loading: true,
error: false,
data: [],
});
apiCall
.getReferralHx()
.then((res) => {
setReferralList((prev) => {
return { ...prev, loading: false, data: [...res.data.result_list] };
});
})
.catch((error) => {
setReferralList((prev) => ({ ...prev, loading: false, error: true }));
});
};
//FUNCTION TO SEND REFERRAL MESSAGE
const sendReferralMsg = (postData) => {
apiCall.sendReferralMsg(postData).then((res)=>{
if(res.data.internal_return < 0){
setError({message:'Email already referred', loading: false, status: false})
return
}else{
toast.success("Message Sent");
setError({message:'', loading: false, status: true})
setRefHistoryReload(prev => !prev)
}
}).catch((error)=>{
setError({message:'Opps! an error occured, try again later', loading: false, status: false})
})
}
//FUNCTION TO SEND REFERRAL MESSAGE
const sendReferralMsg = (postData) => {
apiCall
.sendReferralMsg(postData)
.then((res) => {
if (res.data.internal_return < 0) {
setError({
message: "Email already referred",
loading: false,
status: false,
});
return;
} else {
toast.success("Message Sent");
setError({ message: "", loading: false, status: true });
setRefHistoryReload((prev) => !prev);
}
})
.catch((error) => {
setError({
message: "Opps! an error occured, try again later",
loading: false,
status: false,
});
});
};
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = (values, helpers) => {
setError({message: '', loading: true, status: false})
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = (values, helpers) => {
setError({ message: "", loading: true, status: false });
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11032,
...values
};
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11032,
...values,
};
sendReferralMsg(postData) // FUNCTION TO SEND REFERRAL MESSAGE
}
sendReferralMsg(postData); // FUNCTION TO SEND REFERRAL MESSAGE
};
useEffect(()=>{
allReferrals()
}, [refHistoryReload])
useEffect(() => {
allReferrals();
}, [refHistoryReload]);
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="referral w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Send Referral</h2>
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
{(props)=>(
<Form className='referral-info'>
{/* Firstname */}
<div className="field w-full mb-6">
<InputCom
label="Firstname"
type="text"
name="firstname"
placeholder="Firstname"
value={props.values.firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
</div>
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="referral w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Send Referral
</h2>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => (
<Form className="referral-info">
{/* Firstname */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Firstname"
type="text"
name="firstname"
placeholder="Firstname"
value={props.values.firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.firstname && props.touched.firstname && (
<p className="text-sm text-red-500">
{props.errors.firstname}
</p>
)}
</div>
{/* Lastname */}
<div className="field w-full mb-6">
<InputCom
label="Lastname"
type="text"
name="lastname"
placeholder="Lastname"
value={props.values.lastname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
</div>
{/* Lastname */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Lastname"
type="text"
name="lastname"
placeholder="Lastname"
value={props.values.lastname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.lastname && props.touched.lastname && (
<p className="text-sm text-red-500">
{props.errors.lastname}
</p>
)}
</div>
<div className="field w-full mb-6">
<InputCom
label="Email"
type="text"
name="email"
placeholder="Email"
value={props.values.email}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.email && props.touched.email) && <p className="text-sm text-red-500">{props.errors.email}</p>}
</div>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Email"
type="text"
name="email"
placeholder="Email"
value={props.values.email}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.email && props.touched.email && (
<p className="text-sm text-red-500">{props.errors.email}</p>
)}
</div>
<hr />
{error.message != '' && <p className='text-base text-red-500 py-2'>{error.message}</p>}
<div className='referral-btn flex justify-end items-center py-4 border-b-4'>
{error.loading ?
<LoadingSpinner size='6' color='sky-blue' />
:
<button type='submit' className='text-lg text-white bg-sky-blue p-2 hover:opacity-90 rounded-md'>Send Message</button>
}
</div>
</Form>
)}
</Formik>
</div>
<hr />
{error.message != "" && (
<p className="text-base text-red-500 py-2">{error.message}</p>
)}
<div className="referral-btn flex justify-end items-center py-4 border-b-4">
{error.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<button
type="submit"
className="text-lg text-white bg-sky-blue p-2 hover:opacity-90 rounded-md"
>
Send Message
</button>
)}
</div>
</Form>
)}
</Formik>
</div>
</div>
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="referral w-full md:p-8 p-4 h-full max-h-[500px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Referral List</h2>
{referralList.loading ?
(
<LoadingSpinner size='32' color='sky-blue' />
)
:
(
<table className="referral-list w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
<th className="p-3">Added/Name</th>
<th className="p-3">Email</th>
<th className="p-3">Status</th>
</tr>
</thead>
<tbody>
{referralList.data.length ?
referralList.data.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td className="p-3">{item.added_date} / {item.firstname} {item.lastname}</td>
<td className="p-3">{item.email}</td>
<td className="p-3">{item.status}</td>
</tr>
))
:
(
referralList.error ?
<tr className='text-slate-500'>
<td colSpan={3}>Opps! couldn't get referral history. Try reloading the page</td>
</tr>
:
(
<tr className='text-slate-500'>
<td colSpan={3}>No Item Found on referral List</td>
</tr>
)
)
}
</tbody>
</table>
)
}
</div>
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="referral w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className="mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Referral List
</h2>
{referralList.loading ? (
<LoadingSpinner size="32" color="sky-blue" />
) : (
<ReferralTable history={referralList} />
)}
</div>
</div>
</div>
)
);
}
export default ReferralDisplay
export default ReferralDisplay;
+1 -1
View File
@@ -42,7 +42,7 @@ export default function CollectionTab({ className, products }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
+1 -1
View File
@@ -42,7 +42,7 @@ export default function OnSaleTab({ className, products }) {
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
+1 -1
View File
@@ -42,7 +42,7 @@ export default function OwnTab({ className, products }) {
<div className="grid xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 2xl:gap-8 xl:gap-5 gap-5 mb-10">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
+1 -1
View File
@@ -7,7 +7,7 @@ export default function MainSection({ products }) {
<div className="grid xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2 2xl:gap-8 xl:gap-5 gap-5 mb-6">
<DataIteration
datas={products}
startLength={0}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
>
{({ datas }) => (
+185 -109
View File
@@ -1,39 +1,39 @@
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Link, useNavigate } from "react-router-dom";
import usersService from "../../../services/UsersService";
import Icons from "../../Helpers/Icons";
import InputCom from "../../Helpers/Inputs/InputCom";
import {Link, useNavigate} from 'react-router-dom'
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { useSelector } from "react-redux";
import {toast} from 'react-toastify'
import { toast } from "react-toastify";
import {Formik, Form} from 'formik'
import * as Yup from 'yup'
import { Form, Formik } from "formik";
import * as Yup from "yup";
const validationSchema = Yup.object().shape({
email: Yup.string()
.email('Wrong email format')
.min(3, 'Minimum 3 characters')
.max(50, 'Maximum 50 characters')
.required('Email is required'),
.email("Wrong email format")
.min(3, "Minimum 3 characters")
.max(50, "Maximum 50 characters")
.required("Email is required"),
firstname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Firstname is required'),
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Firstname is required"),
lastname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Lastname is required'),
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Lastname is required"),
city: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('City is required'),
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("City is required"),
state: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('State is required'),
})
.min(3, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("State is required"),
});
export default function PersonalInfoTab({
datas,
@@ -49,72 +49,86 @@ export default function PersonalInfoTab({
browseCoverImg,
coverImgChangHandler,
}) {
let { userDetails } = useSelector((state) => state.userDetails);
let {userDetails} = useSelector((state) => state.userDetails)
const apiCall = new usersService()
const apiCall = new usersService();
let navigate = useNavigate()
let navigate = useNavigate();
let [togglePromotion, setTogglePromotion] = useState(false)
let [togglePromotion, setTogglePromotion] = useState(false);
const initialValues = {
firstname: userDetails?.firstname,
lastname: userDetails?.lastname,
state: userDetails?.state,
city: userDetails?.city,
email: userDetails?.email
}
email: userDetails?.email,
};
let [profile, setProfile] = useState({ // state for requesting from load profile API
let [profile, setProfile] = useState({
// state for requesting from load profile API
loading: true,
status: false
})
status: false,
});
let [requestStatus, setRequestState] = useState({ // state for requesting from update api
message: '',
let [requestStatus, setRequestState] = useState({
// state for requesting from update api
message: "",
loading: false,
status: false
})
status: false,
});
const handleUpdateUser = (values, helpers)=> {
setRequestState({message: '', loading: true, status: false})
apiCall.updateProfile(values).then((res)=>{ // API CALL TO UPDATE USER DETAILS
if(res.data.internal_return < 0){
setRequestState({message: 'Profile Was unable to update', loading: false, status: false})
return
}
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
toast.success("Update Successful");
setTimeout(()=>{
navigate('/',{replace:true})
window.location.reload(true)
},1000)
}).catch(error => {
setRequestState({message: 'Opps! an error occurred. Try Agian', loading: false, status: false})
})
}
const handleUpdateUser = (values, helpers) => {
setRequestState({ message: "", loading: true, status: false });
useEffect(()=>{
setProfile({loading: false, status: true})
},[])
apiCall
.updateProfile(values)
.then((res) => {
// API CALL TO UPDATE USER DETAILS
if (res.data.internal_return < 0) {
setRequestState({
message: "Profile Was unable to update",
loading: false,
status: false,
});
return;
}
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
toast.success("Update Successful");
setTimeout(() => {
navigate("/", { replace: true });
window.location.reload(true);
}, 1000);
})
.catch((error) => {
setRequestState({
message: "Opps! an error occurred. Try Agian",
loading: false,
status: false,
});
});
};
return (
useEffect(() => {
setProfile({ loading: false, status: true });
}, []);
profile.loading ?
<div className="personal-info-tab w-full flex flex-col justify-between">
<div className="p-3">
<LoadingSpinner size='32' color='sky-blue' />
</div>
return profile.loading ? (
<div className="personal-info-tab w-full flex flex-col justify-between">
<div className="p-3">
<LoadingSpinner size="32" color="sky-blue" />
</div>
:
<div className="personal-info-tab w-full flex flex-col justify-between">
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleUpdateUser}>
{(props => {
return (
</div>
) : (
<div className="personal-info-tab w-full flex flex-col justify-between">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleUpdateUser}
>
{(props) => {
return (
<Form>
<div className="flex flex-col-reverse sm:flex-row">
<div className="flex-1 sm:mr-10">
<div className="fields w-full">
@@ -122,6 +136,7 @@ export default function PersonalInfoTab({
{/* username */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="User Name"
type="text"
name="username"
@@ -134,6 +149,7 @@ export default function PersonalInfoTab({
{/* Email */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Email"
type="text"
name="email"
@@ -142,12 +158,17 @@ export default function PersonalInfoTab({
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.email && props.touched.email) && <p className="text-sm text-red-500">{props.errors.email}</p>}
{props.errors.email && props.touched.email && (
<p className="text-sm text-red-500">
{props.errors.email}
</p>
)}
</div>
{/* first name and last name */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
fieldClass="px-6"
label="First Name"
type="text"
name="firstname"
@@ -156,10 +177,15 @@ export default function PersonalInfoTab({
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
{props.errors.firstname && props.touched.firstname && (
<p className="text-sm text-red-500">
{props.errors.firstname}
</p>
)}
</div>
<div className="field w-full">
<InputCom
fieldClass="px-6"
label="Last Name"
type="text"
name="lastname"
@@ -168,13 +194,18 @@ export default function PersonalInfoTab({
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
{props.errors.lastname && props.touched.lastname && (
<p className="text-sm text-red-500">
{props.errors.lastname}
</p>
)}
</div>
</div>
{/* Country */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Country"
type="text"
name="country"
@@ -186,6 +217,7 @@ export default function PersonalInfoTab({
{/* State/Province */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="State/Province"
type="text"
name="state"
@@ -194,12 +226,17 @@ export default function PersonalInfoTab({
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.state && props.touched.state) && <p className="text-sm text-red-500">{props.errors.state}</p>}
{props.errors.state && props.touched.state && (
<p className="text-sm text-red-500">
{props.errors.state}
</p>
)}
</div>
{/* City */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="City"
type="text"
name="city"
@@ -208,34 +245,65 @@ export default function PersonalInfoTab({
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.city && props.touched.city) && <p className="text-sm text-red-500">{props.errors.city}</p>}
{props.errors.city && props.touched.city && (
<p className="text-sm text-red-500">
{props.errors.city}
</p>
)}
</div>
{/* Preferred Communication*/}
<div className='field w-full mb-6 md:flex items-center space-x-4'>
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold'>Pref. Communication</label>
<div className="check-box">
<div className="flex items-center justify-start">
<div className="check-input flex items-center mr-1">
<input className="w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm1" id="" />
<span className="mx-2 text-base text-dark-gray dark:text-white">Email</span>
</div>
<div className="check-input flex items-center">
<input className="w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm2" id="" />
<span className="mx-2 text-base text-dark-gray dark:text-white">Phone</span>
</div>
<div className="field w-full mb-6 md:flex items-center space-x-4">
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold">
Pref. Communication
</label>
<div className="check-box">
<div className="flex items-center justify-start">
<div className="check-input flex items-center mr-1">
<input
className="w-4 h-4 cursor-pointer"
type="checkbox"
name="prefcomm1"
id=""
/>
<span className="mx-2 text-base text-dark-gray dark:text-white">
Email
</span>
</div>
<div className="check-input flex items-center">
<input
className="w-4 h-4 cursor-pointer"
type="checkbox"
name="prefcomm2"
id=""
/>
<span className="mx-2 text-base text-dark-gray dark:text-white">
Phone
</span>
</div>
</div>
</div>
</div>
{/* Allow Promotions */}
<div className='field w-full mb-6 flex items-center space-x-4'>
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold'>Allow Promotions</label>
<div className="cursor-pointer flex items-center" onClick={()=>setTogglePromotion(prev => !prev)}>
<div className={`h-6 w-8 mr-1 p-1 ${togglePromotion ? 'bg-sky-blue flex justify-end items-center': 'bg-slate-200'} rounded-full transition`}>
<div className="w-4 h-full bg-white rounded-full"></div>
</div>
<div className="field w-full mb-6 flex items-center space-x-4">
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold">
Allow Promotions
</label>
<div
className="cursor-pointer flex items-center"
onClick={() => setTogglePromotion((prev) => !prev)}
>
<div
className={`h-6 w-8 mr-1 p-1 ${
togglePromotion
? "bg-sky-blue flex justify-end items-center"
: "bg-slate-200"
} rounded-full transition`}
>
<div className="w-4 h-full bg-white rounded-full"></div>
</div>
</div>
</div>
{/* inputs ends here */}
</div>
@@ -300,11 +368,19 @@ export default function PersonalInfoTab({
</div>
<div className="content-footer w-full">
{requestStatus.message != '' && <p className={`text-center text-base ${requestStatus.status ? 'text-green-800' : 'text-red-600'}`}>{requestStatus.message}</p>}
{requestStatus.message != "" && (
<p
className={`text-center text-base ${
requestStatus.status ? "text-green-800" : "text-red-600"
}`}
>
{requestStatus.message}
</p>
)}
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-9">
<Link
to='/'
to="/"
className="text-18 text-light-red tracking-wide "
>
<span className="border-b dark:border-[#5356fb29] border-light-red">
@@ -313,23 +389,23 @@ export default function PersonalInfoTab({
</span>
</Link>
{requestStatus.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button
type="submit"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Update Profile
</button>
}
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Update Profile
</button>
)}
</div>
</div>
</div>
</Form>
)
})}
</Formik>
</div>
);
}}
</Formik>
</div>
);
}
+1 -1
View File
@@ -4,7 +4,7 @@ function LoadingSpinner({size, color, height}) {
return (
<div className={`flex items-center justify-center ${height ? height : ''}`}>
<div role="status">
<svg aria-hidden="true" className={`w-${size} h-${size} text-gray-200 animate-spin dark:text-gray-600 fill-${color}`} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg aria-hidden="true" className={`w-${size} h-${size} text-gray-200 animate-spin dark:text-gray-600 fill-sky-blue`} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
</svg>
@@ -152,6 +152,7 @@ export default function ProductUploadField({
<h1 className="field-title">Item Name </h1>
<div className="input-field mt-2">
<InputCom
fieldClass="px-6"
type="text"
name="name"
placeholder="RaidParty Fighters"
@@ -164,6 +165,7 @@ export default function ProductUploadField({
<h1 className="field-title">Exter link </h1>
<div className="input-field mt-2">
<InputCom
fieldClass="px-6"
type="text"
name="link"
inputHandler={linkh}
@@ -200,7 +202,9 @@ export default function ProductUploadField({
<div className="w-[1px] h-[33px] bg-light-purple dark:bg-dark-light-purple "></div>
<div className="flex-1 flex h-full justify-center items-center bg-[#FAFAFA] dark:bg-[#11131F] ">
<div className="flex space-x-1 items-center">
<span className="text-dark-gray dark:text-white text-base">ETH</span>
<span className="text-dark-gray dark:text-white text-base">
ETH
</span>
<span>
<svg
width="13"
@@ -235,6 +239,7 @@ export default function ProductUploadField({
<div className="input-field my-2">
<div className="mb-2">
<InputCom
fieldClass="px-6"
type="text"
name="link"
inputHandler={roltsHndlr}
@@ -260,6 +265,7 @@ export default function ProductUploadField({
<div className="sm:flex sm:space-x-8">
<div className="sm:w-1/2 w-full mb-2 sm:mb-0">
<InputCom
fieldClass="px-6"
type="text"
name="link"
inputHandler={keyHndlr}
@@ -269,6 +275,7 @@ export default function ProductUploadField({
</div>
<div className="flex-1">
<InputCom
fieldClass="px-6"
type="text"
name="link"
inputHandler={valueHndlr}
@@ -0,0 +1,149 @@
import React, { useState } from 'react'
import ModalCom from '../Helpers/ModalCom'
import { useNavigate } from 'react-router-dom'
import usersService from '../../services/UsersService'
import LoadingSpinner from '../Spinners/LoadingSpinner'
function DeleteJobPopout({details, onClose, situation}) {
const navigate = useNavigate()
const ApiCall = new usersService()
let [requestStatus, setRequestStatus] = useState({laoding: false, status:false, message: ''}) // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER
// FUNCTION CALLED ONCE USER CONFIRM DELETE JOB
const deleteJob = (details) => {
setRequestStatus({laoding: true, status:false, message: ''})
let reqData = {
job_id: details.job_id,
job_uid: details.job_uid
} // DATA NEEDED BY THE API
// API CALL TO DELETE A JOB
ApiCall.deleteJob(reqData).then(res => {
if(res.data.internal_return < 0){
setRequestStatus({laoding: false, status:false, message: 'Could not perform the request, try again!'})
return
}
setRequestStatus({laoding: false, status:true, message: 'Job deleted successfully'})
setTimeout(()=>{
navigate('/myjobs', {replace: true})
onClose()
window.location.reload()
}, 1000)
}).catch(error => {
setRequestStatus({laoding: false, status:false, message: 'Opps! something went wrong, try again'})
}).finally(()=>{
setTimeout(()=>{
setRequestStatus({laoding: false, status:false, message: ''})
}, 5000)
})
}
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lg:w-[600px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Delete Job
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={onClose}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center px-10 py-8">
<div className="what-icon mb-6 cursor-pointer">
<svg
width="136"
height="136"
viewBox="0 0 136 136"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="68" cy="68" r="68" fill="#5356FB" />
<path
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
fill="white"
/>
<path
d="M67.485 100.21C66.1617 99.9268 64.9041 99.5091 63.803 98.6787C61.3804 96.8484 60.2877 93.7699 61.0386 90.7888C61.7726 87.8747 64.2138 85.6703 67.2089 85.2157C71.273 84.6 75.2024 87.3681 75.8135 91.277C76.4937 95.6153 73.8202 99.3782 69.544 100.103C69.4429 100.12 69.3487 100.172 69.2527 100.209C68.6635 100.21 68.0742 100.21 67.485 100.21Z"
fill="white"
/>
</svg>
</div>
<div className="mb-6">
<p className="text-xl tracking-wide text-dark-gray dark:text-white">
{details.title}
</p>
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
Price: {details.price}
</p>
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
Duration: {details.timeline_days} day(s)
</p>
</div>
<div className="flex space-x-2.5">
<button
onClick={onClose}
type="button"
className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
<span className="text-gradient">Cancel</span>
</button>
{requestStatus.laoding ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button
onClick={() => deleteJob(details)}
type="button"
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
Confirm Delete
</button>
}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
{requestStatus.message != "" && (
!requestStatus.status ?
(<div className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{requestStatus.message}
</div>)
:
requestStatus.status &&
(<div className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{requestStatus.message}
</div>
)
)}
{/* End of error or success display */}
</div>
</div>
</ModalCom>
)
}
export default DeleteJobPopout
+177
View File
@@ -0,0 +1,177 @@
import React, { useState } from 'react'
import Detail from './popoutcomponent/Detail'
import ModalCom from '../Helpers/ModalCom'
import InputCom from '../Helpers/Inputs/InputCom/index'
function JobListPopout({details, onClose, situation}) {
let [inputs, setInputs] = useState({
public: '',
individual: '',
group: '',
})
const handleInputChange = ({target:{name, value}}) => {
setInputs(prev => ({...prev, [name]:value}))
}
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
{details.title}
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={onClose}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className='md:flex bg-white rounded-lg shadow-lg'>
<div className='p-4 w-full md:w-2/4 md:border-r-2'>
{/* <p className='text-lg font-semibold text-slate-900 tracking-wide'>{details.title}</p> */}
{/* INPUT SECTION */}
<div className='my-3 md:flex'>
<Detail
label='Description'
value={details.description}
/>
</div>
<div className='my-3 md:flex'>
<Detail
label='Price'
value={`${details.price*0.01} Naira`}
/>
</div>
<div className='my-3 md:flex'>
<Detail
label='Timeline'
value={`${details.timeline_days} day(s)`}
/>
</div>
<div className='my-3 md:flex'>
<Detail
label='Created'
value={`Dummy, no value found for created!`}
/>
</div>
<div className='my-3'>
<label className='w-full text-slate-900 tracking-wide font-semibold'>Delivery Detail</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
rows='5'
name='details'
style={{resize: 'none'}}
value={details.job_detail}
onChange={handleInputChange}
/>
</div>
</div>
{/* ACTION SECTION */}
<div className='p-4 w-full md:w-2/4 h-full'>
{/* Offer this job to public input */}
<div className="field w-full p-3 mb-6 bg-red-50 rounded-md">
<InputCom
fieldClass="px-6"
label="Offer this job to public"
labelClass='tracking-wide'
type="text"
name="public"
placeholder=""
value={inputs.public}
inputHandler={handleInputChange}
/>
{/* btn */}
<div className='my-1 flex justify-end items-center'>
<button className='px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md'>Show Task to Public</button>
</div>
</div>
{/* Offer this job to individual input */}
<div className="field w-full p-3 mb-6 bg-red-50 rounded-md">
<InputCom
fieldClass="px-6"
label="Offer this job to individual"
labelClass='tracking-wide'
type="text"
name="individual"
placeholder=""
value={inputs.individual}
inputHandler={handleInputChange}
/>
{/* btn */}
<div className='my-1 flex justify-end items-center'>
<button className='px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md'>Send Offer to Individual</button>
</div>
</div>
{/* Offer this job to your group input */}
<div className="field w-full p-3 mb-6 bg-red-50 rounded-md">
<InputCom
fieldClass="px-6"
label="Offer this job to your Group"
labelClass='tracking-wide'
type="text"
name="group"
placeholder=""
value={inputs.group}
inputHandler={handleInputChange}
/>
{/* btn */}
<div className='my-1 flex justify-end items-center'>
<button className='px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md'>Send Order to Group</button>
</div>
</div>
</div>
{/* END OF ACTION SECTION */}
</div>
{/* close button */}
{/* <div className="p-6 flex justify-center">
<button
onClick={onClose}
type="button"
className=" border-gradient text-18 tracking-wide px-2 py-2 rounded-full"
>
<span className="text-gradient">Close</span>
</button>
</div> */}
{/* end of close button */}
</div>
</ModalCom>
)
}
export default JobListPopout
@@ -0,0 +1,142 @@
import React from 'react'
import Detail from './popoutcomponent/Detail'
import ModalCom from '../Helpers/ModalCom'
function PendingJobsPopout({details, onClose, situation}) {
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-end lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
{/* <h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Confirm
</h1> */}
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={onClose}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className='md:flex bg-white rounded-lg shadow-lg'>
<div className='p-4 w-full md:w-3/4 md:border-r-2'>
<p className='text-base font-semibold text-slate-900 tracking-wide'>Opportunity to make some money by introducing 10 of our recent stories from our</p>
<div className='my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300'>
<span className='w-8 h-8 text-center text-sm rounded-full flex justify-center items-center text-red-300 bg-yellow-100'>!</span>
<div className=''>
<p className='text-sm'>This Job have been sent to public view</p>
<p className='text-sm text-slate-600'>This Job will expire</p>
</div>
</div>
{/* INPUT SECTION */}
<div className='my-2 md:flex'>
<Detail
label='Date Added'
value={details.offer_added || 'default'}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Description'
value={details.description}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Offer Expire'
value={details.expire && `${details.expire.split(' ')[0]} ${details.expire.split(' ')[1].split('.')[0]}`}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Price'
value={`${details.price*0.01} ${details.currency}`}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Duration'
value={`${details.timeline_days} day(s)`}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Detail'
value={details.job_description || details.description}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Public Link'
value='https://work.wrenchboard.com/plb/viewjob/218B4BWB83'
bg='bg-slate-200'
/>
</div>
</div>
{/* ACTION SECTION */}
<div className='p-4 w-full md:w-1/4 h-full'>
<p className='mb-6 text-sm'>Actions</p>
<div className='mb-3'>
<p className='px-2 py-1 text-sm bg-slate-100'>Job sent to public view</p>
</div>
<div className='my-3'>
<button className='px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md'>Extend by a week</button>
</div>
<div className='my-3'>
<button className='px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md'>Send to me</button>
</div>
<div className='mt-10 md:mt-32 md:flex md:justify-center'>
<button className='px-2 py-1 text-sm text-white bg-red-500 hover:opacity-90 rounded-md'>Cancel Offer</button>
</div>
</div>
</div>
{/* close button */}
<div className="p-6 flex justify-center">
<button
onClick={onClose}
type="button"
className=" border-gradient text-18 tracking-wide px-2 py-2 rounded-full"
>
<span className="text-gradient">Close</span>
</button>
</div>
{/* end of close button */}
</div>
</ModalCom>
)
}
export default PendingJobsPopout
@@ -0,0 +1,12 @@
import React from 'react'
function Detail({label, value, bg,}) {
return (
<>
<label className='w-full md:w-1/4 text-slate-900 tracking-wide font-semibold'>{label}</label>
<p className={`p-1 w-full md:w-3/4 text-sm text-slate-900 ${bg ? bg : null}`}>{value}</p>
</>
)
}
export default Detail
+38
View File
@@ -105,6 +105,11 @@ input::-webkit-inner-spin-button {
input[type="number"] {
-moz-appearance: textfield;
}
input[type="text"][dir="rtl"] {
text-align: right;
}
.default-border-bottom {
border-bottom: 1px solid #d3d2fe;
}
@@ -364,6 +369,13 @@ input[type="number"] {
margin: 0 16px;
}
.transfer-field, .transfer-field:focus, .transfer-field:focus-within{
background: #FFF !important;
border: none !important;
outline: none !important;
box-shadow: none !important;
}
/* the parent */
.trending-products .slick-list {
margin: 0 -16px;
@@ -468,6 +480,12 @@ input[type="number"] {
overflow: hidden;
}
.job-items{
.job-sub-menu{
background-color: yellow;
}
}
.content-item .inner-list-items {
top: 0;
right: -100%;
@@ -732,4 +750,24 @@ TODO: Responsive ===========================
/* For IE10 */
.content-wrapper select::-ms-expand {
display: none;
}
/* Update table scrollbar */
.update-table::-webkit-scrollbar-track, .update-table > *::-webkit-scrollbar-track{
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
background-color: transparent;
border-radius: 10px;
}
.update-table::-webkit-scrollbar, .update-table > *::-webkit-scrollbar {
width: 10px;
background-color: transparent;
}
.update-table::-webkit-scrollbar-thumb, .update-table > *::-webkit-scrollbar-thumb {
border-radius: 10px;
border-top-right-radius: 50px;
border-bottom-right-radius: 50px;
background-color: #fff;
background: linear-gradient(134.38deg, #f539f8 0%, #c342f9 43.55%, #5356fb 104.51%);
}
+85 -67
View File
@@ -1,84 +1,102 @@
import { useEffect, useState, useCallback } from "react";
import { useEffect, useState, useCallback, useMemo } from "react";
import { Navigate, Outlet, useLocation, useNavigate } from "react-router-dom";
import usersService from '../services/UsersService'
import LoadingSpinner from '../components/Spinners/LoadingSpinner'
import WrenchBoard from "../assets/images/wrenchboard.png"
import usersService from "../services/UsersService";
import LoadingSpinner from "../components/Spinners/LoadingSpinner";
import { useDispatch, useSelector } from "react-redux";
import {updateUserDetails} from '../store/UserDetails'
import { updateUserDetails } from "../store/UserDetails";
import { updateJobs } from "../store/jobLists";
const AuthRoute = ({ redirectPath = "/login", children }) => {
const apiCall = new usersService()
const dispatch = useDispatch()
const apiCall = useMemo(() => new usersService(), []);
const dispatch = useDispatch();
const [lastActivityTime, setLastActivityTime] = useState(Date.now());
let [isLogin, setIsLogin] = useState({loading: true, status: false})
const [isLogin, setIsLogin] = useState({ loading: true, status: false });
const navigate = useNavigate();
//Removing Data stored at localStorage after session expires
const expireSession = () => {
localStorage.removeItem('session_token');
localStorage.removeItem('member_id');
localStorage.removeItem('uid');
localStorage.removeItem('session');
navigate("/login", { replace: true }); // redirects user to login page after session expires
};
// Reset last activity time on user input
const resetTime = () => {
setLastActivityTime(Date.now());
}
window.addEventListener('mousemove', resetTime)
window.addEventListener('keydown', resetTime)
const loadProfile = ()=>{ // function to load user profile
setIsLogin({loading: true, status: false})
apiCall.loadProfile().then((res)=>{
if(res.data.internal_return < 0){
setIsLogin({loading: false, status: false})
return
}
dispatch(updateUserDetails(res.data))
setIsLogin({loading: false, status: true})
}).catch(error =>{
setIsLogin({loading: false, status: false})
})
}
useEffect(() => {
if(!isLogin.status){
loadProfile() // LOADS USER PROFILE DETAILS AND CALLS DISPATCH UPDATEUSERDETAILS TO UPDATE USERDETAILS SLICE IN STORE
}
//Removing Data stored at localStorage after session expires
const expireSession = () => {
localStorage.clear();
navigate("/login", { replace: true }); // redirects user to login page after session expires
};
const checkInactivity = setInterval(() => {
if (Date.now() - lastActivityTime > process.env.REACT_APP_SESSION_EXPIRE_MINUTES) {
expireSession()
if (
Date.now() - lastActivityTime >
process.env.REACT_APP_SESSION_EXPIRE_MINUTES
) {
expireSession();
}
}, process.env.REACT_APP_SESSION_EXPIRE_CHECKER) // Checks for inactivity every minute
}, process.env.REACT_APP_SESSION_EXPIRE_CHECKER); // Checks for inactivity every minute
// cleaning up listeners
return () => {
clearInterval(checkInactivity)
window.removeEventListener('mousemove', resetTime)
window.removeEventListener('keydown', resetTime)
}
}, [lastActivityTime])
clearInterval(checkInactivity);
};
}, [lastActivityTime, navigate]);
return (
isLogin.loading ?
<LoadingSpinner size='32' color='sky-blue' height='h-screen' />
// Stills needs fixing
// <div className="h-screen m-auto">
// <img src={WrenchBoard} alt="wrenchboard" className="h-10" />
// </div>
:
!isLogin.status ?
<Navigate to={redirectPath} replace />
:
(children || <Outlet />)
)
// Reset last activity time on user input
const resetTime = useCallback(() => {
setLastActivityTime(Date.now());
}, []);
useEffect(() => {
window.addEventListener("mousemove", resetTime);
window.addEventListener("keydown", resetTime);
return () => {
window.removeEventListener("mousemove", resetTime);
window.removeEventListener("keydown", resetTime);
};
}, [resetTime]);
useEffect(() => {
if (!isLogin.status) {
const loadProfile = () => {
// function to load user profile
setIsLogin({ loading: true, status: false });
apiCall
.loadProfile()
.then((res) => {
if (res.data.internal_return < 0) {
setIsLogin({ loading: false, status: false });
return;
}
dispatch(updateUserDetails(res.data));
setIsLogin({ loading: false, status: true });
})
.catch((error) => {
setIsLogin({ loading: false, status: false });
});
};
loadProfile();
}
}, []);
useEffect(() => {
// Getting market data
const getMarketActiveJobList = async () => {
try {
const res = await apiCall.getActiveJobList();
dispatch(updateJobs(res.data));
} catch (error) {
console.log("Error getting mode");
}
};
getMarketActiveJobList();
}, [apiCall, dispatch]);
return isLogin.loading ? (
<LoadingSpinner size="32" color="sky-blue" height="h-screen" />
) : // Stills needs fixing
// <div className="h-screen m-auto">
// <img src={WrenchBoard} alt="wrenchboard" className="h-10" />
// </div>
!isLogin.status ? (
<Navigate to={redirectPath} replace />
) : (
children || <Outlet />
);
};
export default AuthRoute;
export default AuthRoute;
+8
View File
@@ -28,6 +28,14 @@ class SiteService {
return this.getAuxEnd("/pricing", null);
}
addFamily(reqData) {
return this.postAuxEnd('/familyadd', reqData)
}
familyListings(reqData) {
return this.postAuxEnd('/familylist', reqData)
}
//---------------------------------------- -----
//---------------------------------------- -----
// Unified call below
+114 -12
View File
@@ -107,17 +107,17 @@ class usersService {
/*
getMyActiveJobList - List of jobs active under this user
*/
getMyActiveJobList(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
offset:0,
limit :100
};
return this.postAuxEnd("/getjobsdata", postData);
}
// getMyActiveJobList(){
// var postData = {
// uuid: localStorage.getItem("uid"),
// member_id: localStorage.getItem("member_id"),
// sessionid: localStorage.getItem("session_token"),
// page:0,
// offset:0,
// limit :100
// };
// return this.postAuxEnd("/getjobsdata", postData);
// }
getHeroJBanners(){
var postData = {
uuid: localStorage.getItem("uid"),
@@ -198,7 +198,31 @@ class usersService {
return this.postAuxEnd("/sendmoneyfee", postData);
}
// Task for the person doing the job
getMyActiveTaskList(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
offset:0,
limit :100
};
return this.postAuxEnd("/activetaskslist", postData);
}
getMyActiveJobList(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
offset:0,
limit :100
};
return this.postAuxEnd("/jobmanageractive", postData);
}
getMyPendingJobList(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
@@ -209,7 +233,6 @@ class usersService {
};
return this.postAuxEnd("/jobmanageroffers", postData);
}
getMyJobList(){
var postData = {
uuid: localStorage.getItem("uid"),
@@ -307,6 +330,50 @@ class usersService {
return this.postAuxEnd("/loadprofile", postData);
}
getFamilyList(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
limit :100
};
return this.postAuxEnd("/familylist", postData);
}
getFamilyAdd(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
limit :100
};
return this.postAuxEnd("/familyadd", postData);
}
getFamilyUpdate(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
limit :100
};
return this.postAuxEnd("/familyupdate", postData);
}
getFamilyManage(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
limit :100
};
return this.postAuxEnd("/familymanage", postData);
}
//END POINT CALL FOR ACCOUNT TOP
startTopUp(post){
var postData = {
@@ -371,6 +438,41 @@ class usersService {
return this.postAuxEnd("/accounttypes", postData);
}
// END POINT TO ACCEPT TERMS AND AGREEMENT
jobManagerAgree() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 13002
};
return this.postAuxEnd("/jobmanageragree", postData);
}
// END POINT TO TO CREATE A JOB
jobManagerCreateJob(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 13010,
...reqData
};
return this.postAuxEnd("/jobmanagercreatejob", postData);
}
// END POINT TO DELETE A JOB
deleteJob(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 13011,
...reqData
};
return this.postAuxEnd("/jobmanagerdeletejob", postData);
}
verifyEmail(code) {
const reqData = {
verify_link: code,
+19
View File
@@ -0,0 +1,19 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
jobLists: {}
};
export const jobSlice = createSlice({
name: "jobLists",
initialState,
reducers: {
updateJobs: (state, payload) => {
state.jobLists = { ...payload.payload };
},
},
});
export const { updateJobs } = jobSlice.actions;
export default jobSlice.reducer;
+2
View File
@@ -2,10 +2,12 @@ import { configureStore } from "@reduxjs/toolkit";
import drawerReducer from "./drawer";
import userDetailReducer from "./UserDetails";
import jobReducer from "./jobLists";
export default configureStore({
reducer: {
drawer: drawerReducer,
userDetails: userDetailReducer,
jobLists: jobReducer
},
});
+14
View File
@@ -0,0 +1,14 @@
import React from 'react'
import AddJob from '../components/AddJob/AddJob'
import Layout from '../components/Partials/Layout'
function AddJobPage() {
return (
<Layout>
<AddJob />
</Layout>
)
}
export default AddJobPage
+1 -20
View File
@@ -1,28 +1,9 @@
import React, { useContext,useState, useEffect } from "react";
import usersService from "../services/UsersService";
import FamilyAcc from "../components/FamilyAcc";
export default function FamilyAccPage() {
const [MyActiveJobList, setMyActiveJobList] = useState([]);
const api = new usersService();
const getMyActiveJobList = async () => {
try {
const res = await api.getMyActiveJobList();
setMyActiveJobList(res.data);
} catch (error) {
console.log("Error getting mode");
}
};
useEffect(() => {
getMyActiveJobList();
}, []);
//debugger;
return (
<>
<FamilyAcc ActiveJobList={MyActiveJobList}/>
<FamilyAcc />
</>
);
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import ActiveJobs from '../components/MyActiveJobs/ActiveJobs'
function ManageActiveJobs() {
return (
<ActiveJobs />
)
}
export default ManageActiveJobs
+1 -21
View File
@@ -1,29 +1,9 @@
import React, {useState, useEffect} from 'react'
import MarketPlace from "../components/MarketPlace";
import usersService from "../services/UsersService";
export default function MarketPlacePage() {
// const userApi = new usersService();
// const activeJobList = userApi.getActiveJobList();
// console.log("activeJobList->",activeJobList);
const [marketActiveJobList, setMarketActiveJobList] = useState([]);
const api = new usersService();
const getMarketActiveJobList = async () => {
try {
const res = await api.getActiveJobList();
setMarketActiveJobList(res.data);
} catch (error) {
console.log("Error getting mode");
}
};
useEffect(() => {
getMarketActiveJobList();
}, []);
return (
<>
<MarketPlace activeJobList={marketActiveJobList} />
<MarketPlace />
</>
);
}
+1 -1
View File
@@ -7,7 +7,7 @@ export default function MyActiveJobsPage() {
const [MyJobList, setMyJobList] = useState([]);
const api = new usersService();
//TARGET ENDPOINT[POST]http://10.204.5.100:9083/en/wrench/api/v1/jobmanageractive
const getMyJobList = async () => {
try {
const res = await api.getMyActiveJobList();
+30
View File
@@ -0,0 +1,30 @@
import React, { useContext,useState, useEffect } from "react";
import usersService from "../services/UsersService";
//import MyJobs from "../components/MyJobs";
import MyActiveJobs from "../components/MyActiveJobs";
import MyPendingJobs from "../components/MyPendingJobs";
export default function MyPendingJobsPage() {
const [MyJobList, setMyJobList] = useState([]);
const api = new usersService();
const getMyJobList = async () => {
try {
const res = await api.getMyPendingJobList();
setMyJobList(res.data);
} catch (error) {
console.log("Error getting mode");
}
};
useEffect(() => {
getMyJobList();
}, []);
// debugger;
return (
<>
<MyPendingJobs MyJobList={MyJobList} />
</>
);
}
+1 -1
View File
@@ -10,7 +10,7 @@ export default function MyTaskPage() {
const getMyActiveJobList = async () => {
try {
const res = await api.getMyActiveJobList();
const res = await api.getMyActiveTaskList();
setMyActiveJobList(res.data);
} catch (error) {
console.log("Error getting mode");
+31 -43
View File
@@ -1596,6 +1596,11 @@
schema-utils "^3.0.0"
source-map "^0.7.3"
"@react-oauth/google@^0.11.0":
version "0.11.0"
resolved "https://registry.npmjs.org/@react-oauth/google/-/google-0.11.0.tgz"
integrity sha512-yeypwdQCcFIAo43OqVOLBfUXuxmxt3xiybfP9h3smtBW4UeFXFVQDsq+d+GlbZFo0TpONPR2+KCk/KT1/pQnvQ==
"@reduxjs/toolkit@^1.8.2":
version "1.9.1"
resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.1.tgz"
@@ -2747,6 +2752,13 @@ axe-core@^4.6.2:
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz"
integrity sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==
axios@^0.21.1:
version "0.21.4"
resolved "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
follow-redirects "^1.14.0"
axios@^0.24.0:
version "0.24.0"
resolved "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz"
@@ -2897,14 +2909,6 @@ babel-preset-react-app@^10.0.1:
babel-plugin-macros "^3.1.0"
babel-plugin-transform-react-remove-prop-types "^0.4.24"
babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz"
integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
@@ -3396,11 +3400,6 @@ core-js-pure@^3.23.3, core-js-pure@^3.25.1:
resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.27.1.tgz"
integrity sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw==
core-js@^2.4.0:
version "2.6.12"
resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
core-js@^3.19.2:
version "3.27.1"
resolved "https://registry.npmjs.org/core-js/-/core-js-3.27.1.tgz"
@@ -4176,7 +4175,7 @@ escodegen@^2.0.0:
optionalDependencies:
source-map "~0.6.1"
eslint-config-react-app@^7.0.0:
eslint-config-react-app@^7.0.1:
version "7.0.1"
resolved "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz"
integrity sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==
@@ -4703,7 +4702,14 @@ flatted@^3.1.0:
resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz"
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
follow-redirects@^1.0.0, follow-redirects@^1.14.4:
flutterwave-react-v3@^1.3.0:
version "1.3.0"
resolved "https://registry.npmjs.org/flutterwave-react-v3/-/flutterwave-react-v3-1.3.0.tgz"
integrity sha512-y0dGSgxh9H/KMSDFurnoPYO3D6DSeOCZHPdLt8DnbtCkjgYgzNdqeXKvxerEaOJyitzXITsmlbzYdrEO/Lju3g==
dependencies:
axios "^0.21.1"
follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.4:
version "1.15.2"
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
@@ -6402,11 +6408,6 @@ loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lottie-web@^5.1.3:
version "5.10.1"
resolved "https://registry.npmjs.org/lottie-web/-/lottie-web-5.10.1.tgz"
integrity sha512-u17bVNf/vA3oK9Wkyb1Vpo83WUIEQwaT0GeEN0qcvaExizyJ/RjmcbjSDj0CnwQCtpGqTgYhqprCC7cTWuXMNw==
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz"
@@ -7760,7 +7761,7 @@ react-countup@^6.2.0:
"@rollup/plugin-babel" "^6.0.2"
countup.js "^2.3.2"
react-dev-utils@^12.0.0:
react-dev-utils@^12.0.1:
version "12.0.1"
resolved "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz"
integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==
@@ -7790,7 +7791,7 @@ react-dev-utils@^12.0.0:
strip-ansi "^6.0.1"
text-table "^0.2.0"
react-dom@^18.0.0:
react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
@@ -7823,15 +7824,7 @@ react-is@^18.0.0:
resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-lottie@^1.2.3:
version "1.2.3"
resolved "https://registry.npmjs.org/react-lottie/-/react-lottie-1.2.3.tgz"
integrity sha512-qLCERxUr8M+4mm1LU0Ruxw5Y5Fn/OmYkGfnA+JDM/dZb3oKwVAJCjwnjkj9TMHtzR2U6sMEUD3ZZ1RaHagM7kA==
dependencies:
babel-runtime "^6.26.0"
lottie-web "^5.1.3"
react-redux@^8.0.2:
react-redux@^8.0.5:
version "8.0.5"
resolved "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz"
integrity sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==
@@ -7863,10 +7856,10 @@ react-router@6.6.2:
dependencies:
"@remix-run/router" "1.2.1"
react-scripts@5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.0.tgz"
integrity sha512-3i0L2CyIlROz7mxETEdfif6Sfhh9Lfpzi10CtcGs1emDQStmZfWjJbAIMtRD0opVUjQuFWqHZyRZ9PPzKCFxWg==
react-scripts@5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz"
integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==
dependencies:
"@babel/core" "^7.16.0"
"@pmmmwh/react-refresh-webpack-plugin" "^0.5.3"
@@ -7884,7 +7877,7 @@ react-scripts@5.0.0:
dotenv "^10.0.0"
dotenv-expand "^5.1.0"
eslint "^8.3.0"
eslint-config-react-app "^7.0.0"
eslint-config-react-app "^7.0.1"
eslint-webpack-plugin "^3.1.1"
file-loader "^6.2.0"
fs-extra "^10.0.0"
@@ -7901,7 +7894,7 @@ react-scripts@5.0.0:
postcss-preset-env "^7.0.1"
prompts "^2.4.2"
react-app-polyfill "^3.0.0"
react-dev-utils "^12.0.0"
react-dev-utils "^12.0.1"
react-refresh "^0.11.0"
resolve "^1.20.0"
resolve-url-loader "^4.0.0"
@@ -7936,7 +7929,7 @@ react-toastify@^9.0.1:
dependencies:
clsx "^1.1.1"
react@^18.0.0:
react@^18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
@@ -8018,11 +8011,6 @@ regenerate@^1.4.2:
resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.9:
version "0.13.11"
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"