Compare commits

..

142 Commits

Author SHA1 Message Date
victorAnumudu 084370b641 added the correct last time reminded 2023-09-25 05:00:24 +01:00
ameye c2a6cff3eb Merge branch 'send-reminder' of WrenchBoard/Users-Wrench into master 2023-09-24 10:21:07 +00:00
victorAnumudu d45e533d91 Merged master into send-reminder 2023-09-24 07:46:33 +01:00
victorAnumudu c89de2559a added send reminder popout 2023-09-24 07:45:05 +01:00
ameye a5a267927a Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-23 21:02:25 +00:00
ameye 557e0acba4 Merge branch 'add_job_detail' of WrenchBoard/Users-Wrench into master 2023-09-23 21:02:21 +00:00
Ebube 3e4dfadb41 .env 2023-09-22 15:09:18 +01:00
Ebube b480d49096 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Recent-Activities 2023-09-22 15:05:07 +01:00
Ebube ece7bf41d3 Added Max 8 for family, added responsive breakpoints for wallet and layout 2023-09-22 15:03:57 +01:00
victorAnumudu 250dd0b171 Add job delivery details textarea tag size increased 2023-09-22 13:26:19 +01:00
victorAnumudu f2475ddd88 Add job delivery details expanded to accept 499 characters 2023-09-22 13:17:45 +01:00
ameye f302ca80d7 Merge branch 'recent-activities-height' of WrenchBoard/Users-Wrench into master 2023-09-19 07:55:39 +00:00
victorAnumudu 11b96e56da reduced the height of each activity and image removed 2023-09-19 06:03:12 +01:00
ameye daad9d18ec Merge branch 'card-adding-limit' of WrenchBoard/Users-Wrench into master 2023-09-18 22:06:47 +00:00
ameye 3c842f6606 Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-18 22:06:40 +00:00
Ebube 23ef007bb1 wallet card sizes and others 2023-09-18 22:45:51 +01:00
Ebube a9b9a17381 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Recent-Activities 2023-09-18 22:42:29 +01:00
victorAnumudu d5e66618aa added limit to card and account adding 2023-09-18 20:46:17 +01:00
CHIEFSOFT\ameye 2e89f07ee2 env add 2023-09-18 12:17:54 -04:00
Ebube 1a51bcf0b5 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Recent-Activities 2023-09-13 18:16:31 +01:00
Ebube f1ee5150a9 Fixed confirmation page and added comments 2023-09-13 18:16:04 +01:00
ameye 9db7f5c985 Merge branch 'signup-page-pathname-fix' of WrenchBoard/Users-Wrench into master 2023-09-13 06:21:36 +00:00
victorAnumudu d56363276b made the pathname to retain the country query param 2023-09-13 05:12:27 +01:00
ameye 5a9b49559b Merge branch 'signup-page-modification' of WrenchBoard/Users-Wrench into master 2023-09-12 19:14:16 +00:00
victorAnumudu fbc8228977 modified signup page to show select country list or defaults to country passed on search param 2023-09-12 20:05:56 +01:00
victorAnumudu a1140f7006 modified signup page to show select country list or defaults to country passed on search param 2023-09-12 20:05:22 +01:00
ameye f3561ff0fb Merge branch 'signup-country-param' of WrenchBoard/Users-Wrench into master 2023-09-12 15:58:35 +00:00
victorAnumudu 42b792ab9d made country auto filled if pathname contains country value 2023-09-12 15:24:30 +01:00
ameye 1e3a166172 Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-12 10:22:34 +00:00
ameye e1c6cb357e Merge branch 'wallet-fix' of WrenchBoard/Users-Wrench into master 2023-09-12 10:22:26 +00:00
Ebube 1aa64fba1f Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Recent-Activities 2023-09-12 09:51:01 +01:00
Ebube 4f0a6f67c3 Fixed Layout for confirm add and added comments 2023-09-12 09:50:36 +01:00
victorAnumudu 4f863f7b1d increase the wallet font and made it navigable 2023-09-12 06:28:01 +01:00
ameye b66f9d7ced Merge branch 'job-created-value' of WrenchBoard/Users-Wrench into master 2023-09-11 15:30:21 +00:00
ameye 493f209162 Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-11 15:30:17 +00:00
victorAnumudu 0aa109e280 added job created value to add job popout 2023-09-11 14:45:45 +01:00
Ebube b0a287c6a8 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Recent-Activities 2023-09-11 14:29:34 +01:00
Ebube 8c00b157ad Modified the content layout and added formatted date 2023-09-11 14:29:11 +01:00
ameye 85bbd25bbb Merge branch 'add-job-dark-theme' of WrenchBoard/Users-Wrench into master 2023-09-11 11:51:23 +00:00
victorAnumudu 4d7e42fba8 dark theme for add jop popout fixed 2023-09-11 04:28:07 +01:00
ameye f91e8e9910 Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-10 06:00:27 +00:00
ameye 9e9b0b5557 Merge branch 'QR-value-update' of WrenchBoard/Users-Wrench into master 2023-09-10 06:00:17 +00:00
Ebube bfcfcdbf16 added variable for hiding social links 2023-09-10 06:25:36 +01:00
victorAnumudu 7e99e7ccab QR value updated 2023-09-10 05:19:19 +01:00
ameye fd9adb1c08 Merge branch 'QR-value' of WrenchBoard/Users-Wrench into master 2023-09-09 21:15:23 +00:00
victorAnumudu 7f2448efff family QR scan value changed 2023-09-09 21:29:24 +01:00
ameye 82ec224d66 Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-09 06:07:32 +00:00
Ebube 35ea200de5 change btn type to submit 2023-09-09 07:00:18 +01:00
ameye 7cdd387045 Merge branch 'resource_upload' of WrenchBoard/Users-Wrench into master 2023-09-08 19:54:33 +00:00
ameye 6b568ff56c Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-08 19:54:23 +00:00
ameye 8808a2f81c Merge branch 'twitter-logos-added' of WrenchBoard/Users-Wrench into master 2023-09-08 19:54:17 +00:00
Ebube 1991bab675 added active animations for job list popup 2023-09-07 16:53:16 +01:00
victorAnumudu f650097db2 implemented resource video and pdf upload 2023-09-07 12:21:05 +01:00
Ebube c427521ac3 dark mode styles added 2023-09-05 09:51:54 +01:00
victorAnumudu 2412059fd0 added new twitter logo in image folder 2023-09-05 06:36:43 +01:00
ameye 34dc467e8b Merge branch 'Recent-Activities' of WrenchBoard/Users-Wrench into master 2023-09-04 14:37:01 +00:00
Ebube 9fa16278ab Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Recent-Activities 2023-09-04 14:31:54 +01:00
Ebube cae02d1dc6 . 2023-09-04 14:31:28 +01:00
ameye abbd7b3993 Merge branch 'add-job-bug' of WrenchBoard/Users-Wrench into master 2023-09-04 12:44:22 +00:00
victorAnumudu 5523511524 Add Job Bug fixed 2023-09-04 10:49:04 +01:00
CHIEFSOFT\ameye 35db8ca7ec activities 2023-09-03 17:57:14 -04:00
CHIEFSOFT\ameye 51e0482a16 Hoe activities 2023-09-03 16:34:19 -04:00
ameye a615e25fcb Merge branch 'resources-tab-visibility' of WrenchBoard/Users-Wrench into master 2023-09-03 13:01:03 +00:00
victorAnumudu addede388e made resources tab visible if enabled 2023-09-03 06:26:19 +01:00
CHIEFSOFT\ameye 76474bb3b5 invite 2023-09-02 16:37:29 -04:00
tokslaw 6337c82374 Merge branch 'coupon-wallet-reload' of WrenchBoard/Users-Wrench into master 2023-08-29 16:57:03 +00:00
victorAnumudu a970411719 made wallet to reload on coupon redeem 2023-08-29 09:47:35 +01:00
ameye 10967acf9e Merge branch 'my-uploads-page' of WrenchBoard/Users-Wrench into master 2023-08-22 10:58:13 +00:00
Ebube fb6831d44f An Optimized version 2023-08-21 23:28:32 +01:00
Ebube 7dcae39320 BUG - Assign Job with less than amount 2023-08-21 22:41:21 +01:00
ameye a0ba60a2bc Merge branch 'flutter_key_removal' of WrenchBoard/Users-Wrench into master 2023-08-21 13:12:38 +00:00
victorAnumudu f377326b48 removed flutter api key from env variables 2023-08-21 11:38:51 +01:00
CHIEFSOFT\ameye feb8bd718d all status 2023-08-20 17:07:25 -04:00
ameye a2a2dbfc24 Merge branch 'my-uploads-page' of WrenchBoard/Users-Wrench into master 2023-08-18 10:46:24 +00:00
Ebube 1c0cb6c97f added the session parameter 2023-08-15 21:02:51 +01:00
ameye 41c9c60fd1 Merge branch 'terms-of-use-update' of WrenchBoard/Users-Wrench into master 2023-08-15 11:45:12 +00:00
victorAnumudu ba5646fe2c Merge master into terms-of-use-update 2023-08-13 07:59:40 +01:00
victorAnumudu 1f9ab45206 updated terms of use 2023-08-13 07:58:37 +01:00
tolik 0ffa1123d2 Hide Apple button 2023-08-13 10:56:42 +08:00
ameye 9420a201e4 Merge branch 'image-anchor-added' of WrenchBoard/Users-Wrench into master 2023-08-11 18:59:57 +00:00
ameye 1b7ea7321e Merge branch 'my-uploads-page' of WrenchBoard/Users-Wrench into master 2023-08-11 18:59:50 +00:00
victorAnumudu b3e273d712 file messages wrapped with anthor 2023-08-11 19:37:01 +01:00
Ebube 7fa74d6fd3 added img 2023-08-11 18:13:34 +01:00
CHIEFSOFT\ameye 02c195500a myfiles 2023-08-11 12:11:31 -04:00
ameye ca8e56c6dd Merge branch 'cancel-popout-removed' of WrenchBoard/Users-Wrench into master 2023-08-10 22:42:31 +00:00
victorAnumudu c265e9db33 popout removed 2023-08-10 22:06:30 +01:00
ameye 2861473ea3 Merge branch 'cancel-upload' of WrenchBoard/Users-Wrench into master 2023-08-10 19:41:46 +00:00
victorAnumudu a598aa3898 on cancel, takes user back to my item 2023-08-10 12:51:54 +01:00
ameye 9d190916a8 Merge branch 'wallet-styles' of WrenchBoard/Users-Wrench into master 2023-08-09 21:14:17 +00:00
Ebube eca9455f0f Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into wallet-styles 2023-08-09 22:00:11 +01:00
Ebube a1bf0bad0f added uploaded files 2023-08-09 21:59:46 +01:00
ameye e236ad20f7 Merge branch 'upload-payload-fix' of WrenchBoard/Users-Wrench into master 2023-08-09 20:36:46 +00:00
victorAnumudu 330f47baa7 updated upload payloads 2023-08-09 21:23:51 +01:00
ameye 5088aa3ead Merge branch 'bug-fix' of WrenchBoard/Users-Wrench into master 2023-08-09 19:52:37 +00:00
victorAnumudu 07a443d082 file upload size validation initiated 2023-08-09 20:28:19 +01:00
victorAnumudu 59a370d763 enforces user upload supported file before proceeding to upload 2023-08-09 19:34:35 +01:00
victorAnumudu 68e709f34b list of supported uploads add 2023-08-09 18:19:34 +01:00
victorAnumudu b1bb730c7d made file name in upload not to have spaces 2023-08-09 17:01:38 +01:00
ameye 20a86f4802 Merge branch 'upload-action' of WrenchBoard/Users-Wrench into master 2023-08-09 14:28:05 +00:00
victorAnumudu 2d918517f8 upload action implemented 2023-08-09 12:52:46 +01:00
tolik a0c0cbdc98 Merge branch 'master' of ssh://gitlab.chiefsoft.net:10222/WrenchBoard/Users-Wrench 2023-08-09 10:39:47 +08:00
tolik ed309007e5 Implemented Facebook login 2023-08-09 10:39:37 +08:00
ameye 594c072806 Merge branch 'add-item-btn-moved' of WrenchBoard/Users-Wrench into master 2023-08-09 01:13:02 +00:00
victorAnumudu 4b9289cb8e bug fix 2023-08-08 22:15:09 +01:00
victorAnumudu 5b39e75119 Add item button moved down 2023-08-08 22:06:44 +01:00
CHIEFSOFT\ameye e61b2c8f43 my files page 2023-08-08 08:55:12 -04:00
CHIEFSOFT\ameye 4c6952c4b3 Page format 2023-08-08 08:23:48 -04:00
CHIEFSOFT\ameye 6a5cebed5b Upload new item 2023-08-08 08:16:32 -04:00
CHIEFSOFT\ameye 663e3e8bb7 fix text 2023-08-08 08:15:26 -04:00
CHIEFSOFT\ameye aaa5b9e8ff Resource Upload My Files 2023-08-08 06:38:03 -04:00
ameye 90ec033b34 Merge branch 'wallet-styles' of WrenchBoard/Users-Wrench into master 2023-08-07 16:22:27 +00:00
Ebube c3c359cfc8 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into wallet-styles 2023-08-07 16:27:26 +01:00
Ebube 68b4031752 added online_name 2023-08-07 16:26:25 +01:00
ameye 8a2559571f Merge branch 'wallet-styles' of WrenchBoard/Users-Wrench into master 2023-08-07 08:50:16 +00:00
ameye ccae5000ee Merge branch 'reset-pwd-validation' of WrenchBoard/Users-Wrench into master 2023-08-07 08:50:12 +00:00
Ebube 5f01cb14f9 updated payload 2023-08-07 08:10:51 +01:00
Ebube 9f62345a2e Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into wallet-styles 2023-08-06 23:46:26 +01:00
Ebube b9096117bc updateprofile payload updated 2023-08-06 23:46:03 +01:00
victorAnumudu f70659901c valid pwd text added 2023-08-06 21:15:18 +01:00
tolik 451e4624b1 Merge branch 'master' of ssh://gitlab.chiefsoft.net:10222/WrenchBoard/Users-Wrench 2023-08-06 10:14:17 +08:00
tolik 1557ba1040 Fix crash 2023-08-06 10:13:15 +08:00
ameye 7133ad8de3 Merge branch 'reset-pwd-icon' of WrenchBoard/Users-Wrench into master 2023-08-05 16:33:25 +00:00
victorAnumudu 9fd8944987 pwd validation msg changed 2023-08-05 16:52:20 +01:00
victorAnumudu 874276dcba reset pwd icons added 2023-08-05 16:35:23 +01:00
ameye be1454f1b8 Merge branch 'reset-pwd-second-phase' of WrenchBoard/Users-Wrench into master 2023-08-05 14:16:16 +00:00
victorAnumudu 6a34ca6c18 reser pwd second phase implemented 2023-08-05 15:12:46 +01:00
ameye fc09771b8d Merge branch 'password-reset-first-stage' of WrenchBoard/Users-Wrench into master 2023-08-05 07:16:30 +00:00
victorAnumudu cab5ed0ece password reset first phase done 2023-08-05 05:41:46 +01:00
ameye 8d3dca96b4 Merge branch 'logo-sizing-and-alignment' of WrenchBoard/Users-Wrench into master 2023-08-04 14:26:23 +00:00
ameye e71a25630d Merge branch 'wallet-styles' of WrenchBoard/Users-Wrench into master 2023-08-04 14:26:14 +00:00
Ebube cf79a15837 size in dollar acc 2023-08-04 13:53:49 +01:00
victorAnumudu 042e8c2c17 site logo size reduced and aligned 2023-08-04 13:50:59 +01:00
Ebube 46d286e8f3 size again 2023-08-04 13:49:11 +01:00
Ebube c2bfcc81ea adjusted size 2023-08-04 13:46:43 +01:00
Ebube 654ed3741c added cancel btn style in withdraw 2023-08-04 13:41:53 +01:00
Ebube 6cccd1c372 changed font-color of naira withdraw cancel btn 2023-08-04 13:39:09 +01:00
Ebube 1e6be76449 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into wallet-styles 2023-08-04 13:29:39 +01:00
Ebube 476ca04f5f Added profile img 2023-08-04 13:29:14 +01:00
ameye ce41db474d Merge branch 'wallet-styles' of WrenchBoard/Users-Wrench into master 2023-08-04 02:32:07 +00:00
Ebube 7ace7e5b5d Added btn styles the of the credit and withdraw popup 2023-08-04 03:18:51 +01:00
ameye 51e829f7b4 Merge branch 'wallet-styles' of WrenchBoard/Users-Wrench into master 2023-08-01 19:53:51 +00:00
Ebube 173b2adc66 css fixes for uniform btn 2023-08-01 19:50:52 +01:00
90 changed files with 3843 additions and 2787 deletions
+12 -2
View File
@@ -24,7 +24,6 @@ REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
REACT_APP_FLUTTERWAVE_APIKEY=FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X
# Had to change the error time to 3sec cause it took too long
REACT_APP_RESET_START_ERROR_TIMEOUT=3000
@@ -64,12 +63,23 @@ REACT_APP_APPLE_REDIRECT_URL='http://localhost:9082/login/auth/apple'
# /* 'client_id' => */ 'com.wrenchboard.users.client',
# /* 'client_secret' => */ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ilc1V1RXQzlEVEoifQ.eyJpc3MiOiJKUjM2M0ZFWThSIiwiaWF0IjoxNjU0MDgzODQxLCJleHAiOjE2NTkyNjc4NDEsImF1ZCI6Imh0dHBzOi8vYXBwbGVpZC5hcHBsZS5jb20iLCJzdWIiOiJjb20ud3JlbmNoYm9hcmQudXNlcnMuY2xpZW50In0.TIPMwjS2MgSysqEuw3yu1nrOcrH-6omzerDhx0CadjWn2yCO8wZhQiAlhIFs7F-WPektIJ6h-2BT62yGrILiTA',
# /* 'redirect_uri' => */ site_url('login/auth/apple')
#SOCIALS Links Display
REACT_APP_APPLE_SOCIAL_LOGIN=0
REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
#File Handling
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
#Auth Text(s)
REACT_APP_LOGOUT_TEXT="Sign Out"
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
#Cards Handling
REACT_APP_MAX_CREDIT_CARDS=4
REACT_APP_MAX_CREDIT_BANK_ACCOUNT=4
#Family
REACT_APP_MAX_FAMILY_MEMBERS=8
+9 -2
View File
@@ -24,7 +24,6 @@ REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
REACT_APP_FLUTTERWAVE_APIKEY=FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X
# Had to change the error time to 3sec cause it took too long
REACT_APP_RESET_START_ERROR_TIMEOUT=3000
@@ -43,4 +42,12 @@ REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
REACT_APP_LOGOUT_TEXT="Sign Out"
REACT_APP_LOGOUT_TEXT="Sign Out"
REACT_APP_APPLE_SOCIAL_LOGIN=0
REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
REACT_APP_MAX_CREDIT_CARDS=4
REACT_APP_MAX_CREDIT_BANK_ACCOUNT=4
REACT_APP_MAX_FAMILY_MEMBERS=8
+8 -2
View File
@@ -24,7 +24,6 @@ REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
REACT_APP_FLUTTERWAVE_APIKEY=FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X
# Had to change the error time to 3sec cause it took too long
REACT_APP_RESET_START_ERROR_TIMEOUT=3000
@@ -50,4 +49,11 @@ DISABLE_ESLINT_PLUGIN=true
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
REACT_APP_LOGOUT_TEXT="Sign Out"
REACT_APP_LOGOUT_TEXT="Sign Out"
REACT_APP_APPLE_SOCIAL_LOGIN=0
REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
REACT_APP_MAX_CREDIT_CARDS=4
REACT_APP_MAX_CREDIT_BANK_ACCOUNT=4
REACT_APP_MAX_FAMILY_MEMBERS=8
+1
View File
@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
+3 -1
View File
@@ -57,6 +57,7 @@ export default function Routers() {
{/* guest routes */}
<Route exact path="/login" element={<LoginPage />} />
<Route exact path="/eoffer" element={<LoginPage />} />
<Route exact path="/invite" element={<LoginPage />} />
<Route exact path="/signup" element={<SignupPage />} />
<Route exact path="/login/auth" element={<AuthRedirect />} />
@@ -121,7 +122,8 @@ export default function Routers() {
<Route exact path="/sell" element={<SellPage />} />
<Route exact path="/saved" element={<SavedPage />} />
<Route exact path="/history" element={<HistoryPage />} />
<Route exact path="/upload-product" element={<UploadProductPage />} />
{/*<Route exact path="/upload-product" element={<UploadProductPage />} />*/}
<Route exact path="/my-uploads" element={<UploadProductPage />} />
<Route exact path="/profile" element={<AuthProfilePage />} />
<Route exact path="/user-profile" element={<UserProfilePage />} />
<Route exact path="/settings" element={<SettingsPage />} />
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" id="error"><path fill="#ff1d25" d="M29.75,25.73,18.68,3.59a3,3,0,0,0-4-1.33,3.05,3.05,0,0,0-1.33,1.33L2.25,25.73a3,3,0,0,0,2.68,4.34H27.07a3,3,0,0,0,3-3A2.88,2.88,0,0,0,29.75,25.73ZM16,25.38a.94.94,0,1,1,.94-.94A.94.94,0,0,1,16,25.38Zm.94-4.69a.94.94,0,1,1-1.88,0V11.31a.94.94,0,1,1,1.88,0Z"></path></svg>

After

Width:  |  Height:  |  Size: 365 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" id="success"><path fill="#80af52" d="M256 26c127.03 0 230 102.97 230 230S383.03 486 256 486 26 383.03 26 256 128.97 26 256 26z"></path><path fill="#fff" d="M215.999 386a9.998 9.998 0 0 1-7.525-3.415l-70-80c-3.637-4.156-3.215-10.474.941-14.11s10.475-3.217 14.111.94l60.961 69.67 142.938-238.23c2.842-4.736 8.983-6.273 13.72-3.43 4.736 2.841 6.271 8.984 3.431 13.72l-150 250a9.998 9.998 0 0 1-8.577 4.855z"></path></svg>

After

Width:  |  Height:  |  Size: 483 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" id="files"><circle cx="64" cy="64" r="64" fill="#EF4C45"></circle><path fill="#CD2E30" d="M128 64v-2L92.4 26.5l-63.1 74 27.2 27c2.4.3 4.9.4 7.4.4C99.3 128 128 99.3 128 64z"></path><path fill="#E5E8EC" d="M93.5 78.4V29c0-1.9-1.5-3.4-3.4-3.4H41.8c-1.9 0-3.4 1.5-3.4 3.4v49.4h55.1z"></path><path fill="#FFF" d="M89.5 78.4V44.6H78.1c-1.9 0-3.4-1.5-3.4-3.4V29.9H37.8c-1.9 0-3.4 1.5-3.4 3.4v45.1h55.1z"></path><path fill="#FFCC04" d="m79.3 65.9-1.5 4c-.5 1.2-1.6 2-2.9 2H53.1c-1.3 0-2.4-.8-2.9-2l-1.5-4c-.5-1.3-1.7-2.2-3.1-2.2H30.9c-1.9 0-3.4 1.5-3.4 3.4v28.8c0 3.5 2.9 6.4 6.4 6.4H94c3.5 0 6.4-2.9 6.4-6.4V67.1c0-1.9-1.5-3.4-3.4-3.4H82.5c-1.4 0-2.7.9-3.2 2.2z"></path><path fill="#CED4DF" d="m74.9 45.8-.1-.1.1.1z"></path><path fill="#22D2FC" d="M74.7 29.9v11.4c0 1.9 1.5 3.4 3.4 3.4h11.4L74.7 29.9z"></path><path fill="#FFF" d="M74.1 81.6H53.9c-2 0-3.7 1.6-3.7 3.7 0 2 1.6 3.7 3.7 3.7h20.2c2 0 3.7-1.6 3.7-3.7 0-2-1.7-3.7-3.7-3.7z"></path></svg>

After

Width:  |  Height:  |  Size: 1003 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51 51" id="jpg"><circle cx="25.5" cy="25.5" r="24" fill="#FED000"></circle><path fill="#F39F03" d="M37.462 16.607v4.741a.924.924 0 0 1-.877.924v16.361c0 1.027-.84 1.867-1.867 1.867H18.282a1.866 1.866 0 0 1-1.867-1.867V22.272a.924.924 0 0 1-.877-.924v-4.741c0-.495.392-.906.877-.924v-1.316a1.86 1.86 0 0 1 1.867-1.867h16.436c1.027 0 1.867.83 1.867 1.867v1.316c.485.018.877.43.877.924z"></path><path fill="#FFF" d="M35.585 13.367v24.266c0 1.031-.836 1.867-1.867 1.867H17.282a1.867 1.867 0 0 1-1.867-1.867V13.367c0-1.031.836-1.867 1.867-1.867h16.436c1.03 0 1.867.836 1.867 1.867z" opacity=".96"></path><path fill="#33ACFE" d="M18.143 25.5h14.715v9.894H18.143z"></path><path fill="#273E56" d="M32.859 35.394h-7.622l3.959-4.357z"></path><path fill="#334861" d="M29.048 35.394H18.143l5.664-7.357z"></path><circle cx="27.697" cy="28.037" r="1.094" fill="#FED000"></circle><path fill="#EB4B33" d="M35.462 21.28H15.538a1 1 0 0 1-1-1v-4.604a1 1 0 0 1 1-1h19.924a1 1 0 0 1 1 1v4.605a1 1 0 0 1-1 1z"></path><path fill="#FFF" d="M22.511 18.797c0 .57-.155 1.499-1.475 1.499-.737 0-1.456-.403-1.456-1.37v-.384h.88v.199c0 .427.105.737.564.737.514 0 .514-.409.514-.725v-2.987h.973v3.03zm.857-3.031h1.996c1.109 0 1.53.7 1.53 1.42 0 .718-.421 1.418-1.53 1.418H24.34v1.587h-.973v-4.425zm.973 2.082h.756c.446 0 .855-.099.855-.663 0-.564-.409-.663-.855-.663h-.756v1.326zm6.36 1.84a1.49 1.49 0 0 1-1.214.608c-1.364 0-2.176-1.023-2.176-2.299 0-1.314.812-2.336 2.176-2.336.905 0 1.766.552 1.865 1.561h-.93c-.117-.496-.47-.743-.935-.743-.874 0-1.202.743-1.202 1.518 0 .738.328 1.48 1.202 1.48.638 0 .997-.334 1.053-.953h-.98V17.8h1.86v2.392h-.62l-.099-.502z"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 512 512" id="mp4-file"><circle cx="256" cy="256" r="256" fill="#8ABE4F"></circle><path fill="#7BA840" d="M511.9 262.5 346.6 96.8c-1.1-1.1-3.1-1.1-4.3 0l-37.4 43.4c-.6.6-.8 1.2-.7 1.9l-3.4-6.1H159.2c-13.1 0-23.7 10.6-23.7 23.7v145.6l7.9 5.9h-16.2v66.6l8.3 7.9v6.6c0 7.6 3.5 14.3 9 18.6.7.9 58.1 58.3 100.6 100.9 3.6.1 7.2.2 10.8.2 139.3 0 252.5-111.1 256-249.5z"></path><g fill="#FFF"><path d="M169.1 193.7h145.4V206H169.1zM169.1 213.5h145.4v12.3H169.1zM169.1 233.4h145.4v12.3H169.1zM169.1 253.3h145.4v12.3H169.1zM169.1 273.1H282v12.3H169.1zM384.1 140.2l-37.4-43.4c-1.1-1.1-3.1-1.1-4.3 0L305 140.2c-1.7 1.6-.4 4.3 2.1 4.3h17.6v34h39.8v-34h17.6c2.3 0 3.6-2.6 2-4.3zM324.6 184.7h39.8v15.5h-39.8zM324.6 212c0 1.4 1.3 2.6 2.9 2.6h34c1.6 0 2.9-1.1 2.9-2.6v-5.7h-39.8v5.7z"></path><path d="M339.7 389.3c0 10.1-8.2 18.3-18.3 18.3H162.2c-10.1 0-18.3-8.2-18.3-18.3v-5.6h-8.4v8.6c0 13.1 10.6 23.7 23.7 23.7h165.2c13.1 0 23.7-10.6 23.7-23.7V220.4h-8.4v168.9zM143.9 162.7c0-10.1 8.2-18.3 18.3-18.3h136.4c-.9-2.8-.2-6 1.9-8.2l.2-.3H159.2c-13.1 0-23.7 10.6-23.7 23.7v145.6h8.4V162.7z"></path><path d="M313.2 344.5c0-18.4-14.9-33.3-33.3-33.3H127.2v66.6h152.7c18.4 0 33.3-14.9 33.3-33.3zm-109 19.2h-6.4v-27.6h-.2L187 363.7h-4.4l-10.8-28.1-.2.1v28.1h-6.4v-38.4h8.4l11 29.5h.2l11.1-29.5h8.2v38.3zm34.4-17.8c-2.4 2.2-5.7 3.3-10 3.3h-8.3v14.6h-6.4v-38.4h14.7c4.2 0 7.6 1.1 10 3.3 2.4 2.2 3.6 5.1 3.6 8.6s-1.2 6.4-3.6 8.6zm36.5 9.3h-4.9v8.5h-6.4v-8.5h-16.1l-.2-3.9 16-26h6.6V350h4.9v5.2z"></path><path d="m263.1 335.8-9.2 14.2h9.9v-15.7h-.1zM228.6 330.4h-8.3V344h8.3c2.4 0 4.2-.6 5.4-1.9 1.2-1.3 1.8-2.9 1.8-4.8s-.6-3.6-1.8-4.9c-1.2-1.3-3-2-5.4-2z"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 90 90" viewBox="0 0 90 90" id="pdf"><circle cx="45" cy="45" r="44.5" fill="#84D2ED"></circle><polygon fill="#EFC41C" stroke="#010101" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.978" points="35.6 18.8 35.6 31.9 22.5 31.9 22.5 71.2 62.8 71.2 62.8 18.8"></polygon><polygon fill="#8CC749" stroke="#010101" stroke-miterlimit="10" stroke-width="1.978" points="22.5 31.9 22.5 31.9 22.5 31.9"></polygon><polygon fill="#EB665F" stroke="#010101" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.978" points="35.6 18.8 22.5 31.9 22.5 31.9 35.6 31.9"></polygon><rect width="35.9" height="15.7" x="31.6" y="40.2" fill="#F2DFD5" stroke="#010101" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.978"></rect><path fill="#010101" d="M43 44c.7.6 1 1.5 1 2.7 0 1.2-.4 2.1-1.1 2.7-.7.6-1.8.9-3.3.9h-1.3v2.8h-2.2v-9.9h3.5C41.2 43.1 42.3 43.4 43 44zM41.4 47.9c.3-.3.4-.7.4-1.3 0-.6-.2-1-.5-1.2C41 45.2 40.4 45 39.7 45h-1.3v3.3h1.5C40.6 48.4 41.2 48.2 41.4 47.9zM53.4 44.4c.9.9 1.4 2.1 1.4 3.6 0 1.5-.5 2.8-1.4 3.7-.9.9-2.3 1.3-4.2 1.3h-3.4v-9.9h3.5C51.1 43.1 52.5 43.6 53.4 44.4zM51.8 50.3c.5-.5.8-1.3.8-2.2s-.3-1.7-.8-2.3c-.5-.5-1.4-.8-2.5-.8H48v6h1.4C50.5 51.1 51.2 50.9 51.8 50.3zM63.6 43.1v1.9H59v2.1h4.4v1.9H59v3.9h-2.2v-9.9H63.6z"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="655.359" height="655.359" fill-rule="evenodd" clip-rule="evenodd" image-rendering="optimizeQuality" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" viewBox="0 0 6.827 6.827" id="png-file"><circle cx="3.413" cy="3.413" r="3.413" fill="#42a5f5"></circle><path fill="#fffffe" d="M1.744 4.074h.27V1.75a.164.164 0 0 1 .164-.164H4.3l.023.022.544.545.023.023v1.898h.191a.198.198 0 0 1 .198.199v.77a.198.198 0 0 1-.198.198H1.744a.198.198 0 0 1-.198-.199v-.769a.198.198 0 0 1 .198-.199zm.425 0h2.567V2.24l-.004-.004h-.498v-.495H2.178a.009.009 0 0 0-.007.003.009.009 0 0 0-.002.006v2.324zm.389-.7h1.789v.156h-1.79v-.156zm0-.544h1.789v.156h-1.79V2.83zm.07 2.094V4.37h.179c.068 0 .112.003.132.009a.145.145 0 0 1 .08.054.172.172 0 0 1 .032.107.18.18 0 0 1-.018.086.152.152 0 0 1-.047.055.162.162 0 0 1-.058.026.637.637 0 0 1-.116.008h-.073v.209h-.111zm.111-.46v.157H2.8a.29.29 0 0 0 .089-.009.074.074 0 0 0 .034-.027.075.075 0 0 0 .013-.043.072.072 0 0 0-.018-.05.077.077 0 0 0-.044-.024.532.532 0 0 0-.08-.004h-.055zm.405.46V4.37h.109l.226.37v-.37h.104v.554h-.112l-.223-.361v.36h-.104zm.814-.204v-.093H4.2v.22a.372.372 0 0 1-.237.086.304.304 0 0 1-.15-.036.232.232 0 0 1-.098-.105.337.337 0 0 1-.032-.147.32.32 0 0 1 .036-.154.244.244 0 0 1 .106-.102.285.285 0 0 1 .132-.028.26.26 0 0 1 .161.043.195.195 0 0 1 .075.12l-.111.02a.118.118 0 0 0-.044-.064.133.133 0 0 0-.08-.024.152.152 0 0 0-.117.047c-.029.03-.043.077-.043.138 0 .065.014.114.044.147.029.033.067.05.114.05a.194.194 0 0 0 .07-.014.244.244 0 0 0 .061-.034v-.07h-.128z"></path><path fill="none" d="M1.547 1.547H5.28V5.28H1.547z"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="1200" height="1227" viewBox="0 0 1200 1227" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 430 B

+105 -88
View File
@@ -1,6 +1,6 @@
import { Field, Form, Formik } from "formik";
import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import * as Yup from "yup";
import usersService from "../../services/UsersService";
import { tableReload } from "../../store/TableReloads";
@@ -11,7 +11,7 @@ const validationSchema = Yup.object().shape({
country: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Country is required"),
.required("Currency is required"),
price: Yup.string()
.typeError("Invalid number")
.min(1, "Price must be greater than 0")
@@ -32,7 +32,7 @@ const validationSchema = Yup.object().shape({
.required("Description is required"),
job_detail: Yup.string()
.min(3, "Minimum 3 characters")
.max(1440, "Maximum 1440 characters")
.max(499, "Maximum 499 characters")
.required("Details is required"),
timeline_days: Yup.number()
.typeError("you must specify a number")
@@ -43,15 +43,9 @@ const validationSchema = Yup.object().shape({
function AddJob({ popUpHandler, categories }) {
const ApiCall = new usersService();
const { walletDetails } = useSelector((state) => state.walletDetails);
let dispatch = useDispatch();
let [currency, setCurrency] = useState({
loading: true,
status: false,
data: null,
}); // To Hold the array of currency getUserCurrency returns
let initialValues = {
// initial values for formik
country: "",
@@ -69,30 +63,15 @@ function AddJob({ popUpHandler, categories }) {
message: "",
}); // Holds state when submit button is pressed
// FUNCTION TO GET Currency
const getUserCurrency = () => {
setCurrency((prev) => ({ ...prev, loading: true }));
ApiCall.getUserWallets()
.then((res) => {
if (res.data.internal_return < 0) {
setCurrency({ loading: false, status: true, data: [] });
return;
}
setCurrency({
loading: false,
status: true,
data: res.data.result_list,
});
})
.catch((err) => {
setCurrency({ loading: false, status: false, data: [] });
});
const getWalletDetail = (country) => { // A FUNCTION TO GET USER BALANCE BASED ON COUNTRY SELECTED
const walletChecker = walletDetails?.data.find(
(item) => item.country === country
);
return walletChecker ? walletChecker.amount : 0;
};
// FUNCTION TO HANDLE ADD JOB FORM
const handleAddJob = (values, helpers) => {
let reqData = {
const handleAddJob = async (values, helpers) => {
const reqData = {
country: values?.country,
price: Number(values.price) * 100,
title: values?.title,
@@ -102,20 +81,35 @@ function AddJob({ popUpHandler, categories }) {
category: values.category?.join("@"),
};
const walletAmount = getWalletDetail(reqData.country); // GETTING USER BALANCE BASED ON COUNTRY SELECTED
if (reqData.price > walletAmount) {
setRequestStatus({
loading: false,
status: false,
message: "Insufficient Balance",
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 1500);
return;
}
setRequestStatus({ loading: true, status: false, message: "" });
ApiCall.jobManagerCreateJob(reqData)
.then((res) => {
if (res.data.internal_return < 1) {
setRequestStatus({
loading: false,
status: false,
message: "Could not complete your request at the moment",
});
setTimeout(() => {
popUpHandler();
}, 1500);
return;
}
try {
const res = await ApiCall.jobManagerCreateJob(reqData);
if (res.data.internal_return < 1) {
setRequestStatus({
loading: false,
status: false,
message: "Could not complete your request at the moment",
});
setTimeout(() => {
popUpHandler();
}, 1500);
} else {
setRequestStatus({
loading: false,
status: true,
@@ -125,27 +119,22 @@ function AddJob({ popUpHandler, categories }) {
dispatch(tableReload({ type: "JOBTABLE" }));
popUpHandler();
}, 1000);
})
.catch((err) => {
setRequestStatus({
loading: false,
status: false,
message: "Opps! something went wrong. Try Again",
});
})
.finally(() => {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
} catch (err) {
setRequestStatus({
loading: false,
status: false,
message: "Oops! Something went wrong. Try Again",
});
} finally {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
};
useEffect(() => {
getUserCurrency();
}, []);
return (
<div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between">
<div className="add-job p-5 w-full bg-white dark:bg-dark-white dark:text-white rounded-md flex flex-col justify-between">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
@@ -164,26 +153,30 @@ function AddJob({ popUpHandler, categories }) {
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
>
Currency
{props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>}
{props.errors.country && props.touched.country && (
<span className="text-[12px] text-red-500">
{props.errors.country}
</span>
)}
</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`}
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 border`}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{currency.loading ? (
{walletDetails.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : currency.data.length ? (
) : walletDetails.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select a currency
</option>
{currency.data?.map((item, index) => (
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
@@ -207,14 +200,17 @@ function AddJob({ popUpHandler, categories }) {
fieldClass="px-6 text-right"
label="Price"
labelClass="tracking-wide"
inputBg="bg-slate-100"
type="number"
name="price"
placeholder="0"
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.price && props.touched.price && props.errors.price}
error={
props.errors.price &&
props.touched.price &&
props.errors.price
}
/>
</div>
</div>
@@ -225,13 +221,16 @@ function AddJob({ popUpHandler, categories }) {
fieldClass="px-6"
label="Title"
labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.title && props.touched.title && props.errors.title}
error={
props.errors.title &&
props.touched.title &&
props.errors.title
}
/>
</div>
@@ -241,13 +240,16 @@ function AddJob({ popUpHandler, categories }) {
fieldClass="px-6"
label="Description"
labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.description && props.touched.description && props.errors.description}
error={
props.errors.description &&
props.touched.description &&
props.errors.description
}
/>
</div>
@@ -259,12 +261,17 @@ function AddJob({ popUpHandler, categories }) {
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1'
>
Job Delivery Details
{props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>}
{props.errors.job_detail &&
props.touched.job_detail && (
<span className="text-[12px] text-red-500">
{props.errors.job_detail}
</span>
)}
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`}
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px] border`}
style={{ resize: "none" }}
name="job_detail"
value={props.values.job_detail}
@@ -286,19 +293,28 @@ function AddJob({ popUpHandler, categories }) {
role="group"
aria-labelledby="checked-group"
>
{Object?.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
{categories ? (
<>
{Object?.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
</>
) : (
<label className="flex gap-1 w-full items-center">
<Field type="checkbox" name="category" />
<span className="text-[13.975px]">null</span>
</label>
))}
)}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
@@ -324,7 +340,7 @@ function AddJob({ popUpHandler, categories }) {
<Field
component="select"
name="timeline_days"
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 ${
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 border ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
@@ -335,6 +351,7 @@ function AddJob({ popUpHandler, categories }) {
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-lg"
value={duration}
>
@@ -1,8 +1,8 @@
import React, { useEffect } from 'react';
import { useDispatch } from "react-redux";
import { useLocation, useNavigate } from 'react-router-dom';
import usersService from '../../../services/UsersService';
import {updateUserDetails} from "../../../store/UserDetails";
import { useDispatch } from "react-redux";
import { updateUserDetails } from "../../../store/UserDetails";
import AuthLayout from "../AuthLayout";
function FbookRedirect() {
@@ -22,38 +22,50 @@ function FbookRedirect() {
console.log(codeResponse);
/*
POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/#exchangecode
Step 1. Get access token by code
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code
GET https://graph.facebook.com/v17.0/oauth/access_token?
client_id={app-id}
&redirect_uri={redirect-uri}
&client_secret={app-secret}
&code={code-parameter}
https://developers.facebook.com/docs/facebook-login/guides/access-tokens/get-long-lived
Step 2. Get long-lived token by access token
curl -i -X GET "https://graph.facebook.com/{graph-api-version}/oauth/access_token?
grant_type=fb_exchange_token&
client_id={app-id}&
client_secret={app-secret}&
fb_exchange_token={your-access-token}"
*/
// process.env.REACT_APP_FACEBOOK_CLIENT_ID
// process.env.REACT_APP_FACEBOOK_CLIENT_SCOPE
var reqData = {
auth_type: "FACEBOOK",
code: codeResponse,
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
redirect_uri: process.env.REACT_APP_FACEBOOK_REDIRECT_URL,
};
// userApi
// .authStart(reqData)
// .then((res) => {
// if (res.status == 200 && res.data.internal_return >= 0 && res.data.member_id && res.data.uid && res.data.session) {
// localStorage.setItem("member_id", `${res.data.member_id}`);
// localStorage.setItem("uid", `${res.data.uid}`);
// localStorage.setItem("session_token", `${res.data.session}`);
// dispatch(updateUserDetails({...res.data}));
// navigate('/', {replace: true})
// return
// }
// navigate('/login', {state: {error: true}})
// })
// .catch((error) => {
// navigate('/login', {state: {error: true}})
// console.log(error);
// });
userApi
.authStart(reqData)
.then((res) => {
if (res.status == 200 && res.data.internal_return >= 0 && res.data.member_id && res.data.uid && res.data.session) {
localStorage.setItem("member_id", `${res.data.member_id}`);
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
dispatch(updateUserDetails({...res.data}));
navigate('/', {replace: true})
return
}
navigate('/login', {state: {error: true}})
})
.catch((error) => {
navigate('/login', {state: {error: true}})
console.log(error);
});
},[])
return (
<AuthLayout>
@@ -1,26 +1,26 @@
import React, { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import usersService from '../../../services/UsersService';
import {updateUserDetails} from "../../../store/UserDetails";
import React, { useEffect } from "react";
import { useDispatch } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
import usersService from "../../../services/UsersService";
import { updateUserDetails } from "../../../store/UserDetails";
import AuthLayout from "../AuthLayout";
function Redirect() {
const location = useLocation();
const navigate = useNavigate();
const userApi = new usersService();
const dispatch = useDispatch()
const location = useLocation();
const navigate = useNavigate();
const userApi = new usersService();
const dispatch = useDispatch();
const queryParams = new URLSearchParams(location?.search);
const codeResponse = queryParams.get("code");
const queryParams = new URLSearchParams(location?.search);
const codeResponse = queryParams.get("code");
useEffect(()=>{
if(!codeResponse){
navigate('/login', {state: {error: true}})
return
}
console.log(codeResponse);
/*
useEffect(() => {
if (!codeResponse) {
navigate("/login", { state: { error: true } });
return;
}
console.log(codeResponse);
/*
POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
@@ -31,34 +31,40 @@ function Redirect() {
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code
*/
var reqData = {
auth_type: "GOOGLE",
code: codeResponse,
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
};
userApi
.authStart(reqData)
.then((res) => {
if (res.status == 200 && res.data.internal_return >= 0 && res.data.member_id && res.data.uid && res.data.session) {
localStorage.setItem("member_id", `${res.data.member_id}`);
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
dispatch(updateUserDetails({...res.data}));
navigate('/', {replace: true})
return
}
navigate('/login', {state: {error: true}})
})
.catch((error) => {
navigate('/login', {state: {error: true}})
console.log(error);
});
},[])
var reqData = {
auth_type: "GOOGLE",
code: codeResponse,
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
};
userApi
.authStart(reqData)
.then((res) => {
if (
res.status == 200 &&
res.data.internal_return >= 0 &&
res.data.member_id &&
res.data.uid &&
res.data.session
) {
localStorage.setItem("member_id", `${res.data.member_id}`);
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
dispatch(updateUserDetails({ ...res.data }));
navigate("/", { replace: true });
return;
}
navigate("/login", { state: { error: true } });
})
.catch((error) => {
navigate("/login", { state: { error: true } });
console.log(error);
});
}, []);
return (
<AuthLayout>
<div className='min-h-[70vh]'>Redirecting ... </div>
</AuthLayout>
)
<div className="min-h-[70vh]">Redirecting ... </div>
</AuthLayout>
);
}
export default Redirect
export default Redirect;
@@ -0,0 +1,37 @@
import React from 'react'
import { useNavigate } from 'react-router-dom'
import localImgLoad from '../../lib/localImgLoad'
const ForgetPwdResponse = ({title, message, type}) => {
const navigate = useNavigate()
return (
<>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<h1 className={`${type ? 'text-black' : 'text-red-500'}text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]`}>
{title}
</h1>
</div>
<div className="title-area w-[100px] h-[100px] mx-auto flex flex-col justify-center items-center relative text-center mb-7">
<img className='w-full h-full' src={`${type ? localImgLoad('images/icons/success.svg') : localImgLoad('images/icons/error.svg')}`} alt='alert-banner' />
</div>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<p className={`${type ? 'text-sky-blue' : 'text-red-500'} font-semibold dark:text-white mb-3 leading-[27.3px] text-[18px]`}>
{message}
</p>
</div>
<div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2">
<button
type="button"
onClick={() => navigate("/login")}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
<span>Home</span>
</button>
</div>
</div>
</>
)
}
export default ForgetPwdResponse
+108 -96
View File
@@ -4,6 +4,8 @@ import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
import EmailValidator from "../../../lib/EmailValidator";
import ForgetPwdResponse from "../ForgetPwdResponse";
export default function ForgotPassword() {
const [checked, setValue] = useState(false);
@@ -11,7 +13,7 @@ export default function ForgotPassword() {
// email
const [email, setMail] = useState("");
const [msgError, setMsgError] = useState("");
const [msgSuccess, setMsgSuccess] = useState(false);
const [msgSuccess, setMsgSuccess] = useState(null);
const navigate = useNavigate();
const userApi = new usersService();
@@ -27,12 +29,26 @@ export default function ForgotPassword() {
const resetHandler = async () => {
if (email == "") {
setMsgError("An email is required");
} else if (!checked) {
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if (!checked) {
setMsgError("Check if you are human");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(!EmailValidator(email)){ // CHECKS IF EMAIL IS VALID
setMsgError("Invalid Email");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if (email !== "" && checked) {
const reqData = { email };
const reqData = { email, action:11013 };
setResetLoading(true);
try {
const res = await userApi.StartResetPassword(reqData);
@@ -41,8 +57,11 @@ export default function ForgotPassword() {
setMail("");
setValue(false);
setResetLoading(false);
}else{
setMsgSuccess(false);
}
} catch (error) {
setMsgSuccess(false);
setResetLoading(false);
setMail("");
setMsgError("An error occurred");
@@ -53,9 +72,6 @@ export default function ForgotPassword() {
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
}
setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
};
return (
@@ -73,106 +89,102 @@ export default function ForgotPassword() {
</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">
<div className="flex flex-col justify-center w-full h-full px-5">
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<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>
</div>
<div className="input-area">
<div className="input-item mb-10">
<InputCom
fieldClass="px-6"
placeholder="Your Username/Email"
label="Email"
name="email"
type="email"
value={email}
inputHandler={handleEmail}
iconName="message"
/>
{msgSuccess == null ?
<>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<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>
</div>
{/* hCaptha clone for the time being */}
<div className="mb-10">
<div className="w-[303px] h-[78px] mx-auto overflow-hidden">
<div className="w-[300px] h-[74px] bg-white bottom-[1px] rounded border-gray-100 overflow-hidden cursor-pointer">
{/* Checkbox */}
<div className="h-full relative inline-block">
<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}
/>
<div className="input-area">
<div className="input-item mb-10">
<InputCom
fieldClass="px-6"
placeholder="Your Username/Email"
label="Email"
name="email"
type="email"
value={email}
inputHandler={handleEmail}
iconName="message"
/>
</div>
{/* hCaptha clone for the time being */}
<div className="mb-10">
<div className="w-[303px] h-[78px] mx-auto overflow-hidden">
<div className="w-[300px] h-[74px] bg-white bottom-[1px] rounded border-gray-100 overflow-hidden cursor-pointer">
{/* Checkbox */}
<div className="h-full relative inline-block">
<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}
/>
</div>
</div>
</div>
</div>
</div>
<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"
>
I am human
<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"
>
I am human
</label>
</label>
</label>
</label>
</div>
<div className="h-full relative inline-block w-16"></div>
</div>
<div className="h-full relative inline-block w-16"></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>
)}
<div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2">
<button
type="button"
onClick={resetHandler}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
{resetLoading ? (
<div className="signup btn-loader"></div>
) : (
<span>Send Code</span>
)}
</button>
<button
type="button"
onClick={() => navigate("/login")}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
>
Cancel
</button>
</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>
)}
<div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2">
<button
type="button"
onClick={resetHandler}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
{resetLoading ? (
<div className="signup btn-loader"></div>
) : (
<span>Send Code</span>
)}
</button>
<button
type="button"
onClick={() => navigate("/login")}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
>
Cancel
</button>
</div>
</div>
</div>
</>
:
<ForgetPwdResponse
title={'Forget Password'}
message={msgSuccess? `Check your email for the link to continue password reset. Note the reset link will expire short time` : 'We are unable to continue with your request. Please try another username or contact us for help'}
type={msgSuccess}
/>
}
</div>
</div>
</div>
+60 -36
View File
@@ -329,34 +329,51 @@ export default function Login() {
)}
</button>
</div>
<div className="sm:flex sm:justify-between sm:items-center sm:space-x-2">
<BrandBtn
link="#"
imgSrc={googleLogo}
brand="Google"
onClick={googleLogin}
/>
<BrandBtn
// link={`https://appleid.apple.com/auth/authorize?response_type=code&response_mode=form_post&client_id=${process.env.REACT_APP_APPLE_CLIENT_ID}&redirect_uri=https%3A%2F%2Fwork.wrenchboard.com%2Flogin%2Fauth%2Fapple&state=4b2c4456b7&scope=name+email`}
link={`https://appleid.apple.com/auth/authorize?response_type=code&response_mode=form_post&client_id=${process.env.REACT_APP_APPLE_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_APPLE_REDIRECT_URL}&state=4b2c4456b7&scope=name+email`}
imgSrc={appleLogo}
brand="Apple"
isAnchor={true}
/>
</div>
<div className="sm:flex sm:justify-between sm:items-center sm:space-x-2">
<BrandBtn
link={`https://www.facebook.com/v14.0/dialog/oauth?client_id=${process.env.REACT_APP_FACEBOOK_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_FACEBOOK_REDIRECT_URL}&scope=${process.env.REACT_APP_FACEBOOK_CLIENT_SCOPE}`}
imgSrc={facebookLogo}
brand="Facebook"
isAnchor={true}
/>
<BrandBtn
// link="https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=comma-separated-list-of-scopes&state=YOUR_STATE_VALUE"
imgSrc={linkedInLogo}
brand="LinkedIn"
isAnchor={true}
/>
<div className="sm:grid grid-cols-2 gap-1">
<div className="w-full">
<BrandBtn
link="#"
imgSrc={googleLogo}
brand="Google"
onClick={googleLogin}
/>
</div>
<div
className={`w-full ${
process.env.REACT_APP_APPLE_SOCIAL_LOGIN !== 0 &&
"hidden"
}`}
>
<BrandBtn
// link={`https://appleid.apple.com/auth/authorize?response_type=code&response_mode=form_post&client_id=${process.env.REACT_APP_APPLE_CLIENT_ID}&redirect_uri=https%3A%2F%2Fwork.wrenchboard.com%2Flogin%2Fauth%2Fapple&state=4b2c4456b7&scope=name+email`}
link={`https://appleid.apple.com/auth/authorize?response_type=code&response_mode=form_post&client_id=${process.env.REACT_APP_APPLE_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_APPLE_REDIRECT_URL}&state=4b2c4456b7&scope=name+email`}
imgSrc={appleLogo}
brand="Apple"
isAnchor={true}
// style={{visibility: 'hidden'}}
/>
</div>
<div className="w-full">
<BrandBtn
link={`https://www.facebook.com/v14.0/dialog/oauth?client_id=${process.env.REACT_APP_FACEBOOK_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_FACEBOOK_REDIRECT_URL}&scope=${process.env.REACT_APP_FACEBOOK_CLIENT_SCOPE}`}
imgSrc={facebookLogo}
brand="Facebook"
isAnchor={true}
/>
</div>
<div
className={`w-full ${
process.env.REACT_APP_LINKEDIN_SOCIAL_LOGIN !== 0 &&
"hidden"
}`}
>
<BrandBtn
// link="https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=comma-separated-list-of-scopes&state=YOUR_STATE_VALUE"
imgSrc={linkedInLogo}
brand="LinkedIn"
isAnchor={true}
/>
</div>
</div>
</div>
</div>
@@ -432,12 +449,12 @@ export default function Login() {
}
{/* END of login component */}
{loginType == "full" &&
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by hCaptcha and the our Privacy Policy
and Terms of Service apply.
</div>
}
{loginType == "full" && (
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by hCaptcha and the our Privacy Policy
and Terms of Service apply.
</div>
)}
</div>
</div>
</div>
@@ -446,7 +463,14 @@ export default function Login() {
);
}
const BrandBtn = ({ link, imgSrc, brand, onClick, isAnchor = false }) => {
const BrandBtn = ({
link,
imgSrc,
brand,
onClick,
isAnchor = false,
style = { visibility: "visible" },
}) => {
// const doGoogle = async () => {
// alert("start google");
// };
@@ -466,7 +490,7 @@ const BrandBtn = ({ link, imgSrc, brand, onClick, isAnchor = false }) => {
// alert("start facebook");
// };
return (
<div className="w-full sm:w-1/2 flex justify-center bottomMargin">
<div className="w-full flex justify-center bottomMargin" style={style}>
{isAnchor ? (
<a
href={link}
+47 -9
View File
@@ -1,20 +1,26 @@
import React, { useCallback, useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
export default function SignUp() {
const queryParams = new URLSearchParams(location?.search);
const country = queryParams.get("cnt")?.toUpperCase();
const {pathname} = useLocation()
const currentPath = country ? `${pathname}?cnt=${country.toLowerCase()}`:pathname // Determines the new pathname is country query params exist
const [signUpLoading, setSignUpLoading] = useState(false);
const [checked, setValue] = useState(false);
// for the catch error
const [msgError, setMsgError] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [countries, setCountries] = useState([]);
const [countries, setCountries] = useState({loading:true, data:[]});
const [formData, setFormData] = useState({
country: "",
country: country? country : "",
first_name: "",
last_name: "",
email: "",
@@ -45,9 +51,18 @@ export default function SignUp() {
try {
if (res.status === 200) {
const { signup_country } = await res.data;
setCountries(signup_country);
// setCountries(signup_country);
if(country){ // IF LINK/PATHNAME HAS CNT QUERY VALUE
let cnt = signup_country.filter(item => item[0]==country) // test to see country passed in query param exist from list of countries supplied by API
if(!cnt.length){ // IF CNT EMPTY, SET FORMDATA COUNTRY BACK TO EMPTY STRING: RE: THIS IS BCOS WE INITAIL SET COUNTRY VALUE IN FORMDATA, IF COUNTRY PARAM IS PRESENT IN LINK
setFormData(prev => ({...prev, country: ''}))
return setCountries({loading: false, data: signup_country});
}
return setCountries({loading: false, data: cnt});
}
setCountries({loading: false, data:signup_country});
} else if (res.data.result !== 100) {
setCountries("Nothing see here!");
setCountries({loading: false, data:[]});
}
} catch (error) {
throw new Error(error);
@@ -134,7 +149,7 @@ export default function SignUp() {
<AuthLayout slogan="Welcome to WrenchBoard">
<div className="w-full">
<div className="mb-5">
<Link to="#">
<Link to={currentPath}>
<img
src={WrenchBoard}
alt="wrenchboard"
@@ -172,6 +187,7 @@ export default function SignUp() {
name="country"
value={formData.country}
inputHandler={handleInputChange}
disable={country && countries?.data?.length <= 1 ? true : false}
/>
<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">
@@ -306,6 +322,7 @@ export default function SignUp() {
<div className="signin-area mb-1">
<div className="flex justify-center">
<button
disabled={countries.loading}
type="button"
onClick={handleSignUp}
className={`rounded-[0.475rem] mb-6 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`}
@@ -333,6 +350,7 @@ const SelectOption = ({
inputHandler,
value,
data, // passing the data from parent
disable
}) => {
return (
<div className="input-com mb-7">
@@ -346,19 +364,39 @@ const SelectOption = ({
</div>
<div>
<select
disabled={disable}
name={name}
id={name}
className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full 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 "
onChange={inputHandler}
value={value}
>
<option value={""}>Select your Country</option>
{data?.length > 0 &&
data?.map((item, idx) => (
{data?.data?.length > 1 ?
<>
<option value={""}>Select your Country</option>
{data?.data?.map((item, idx) => (
<option value={item[0]} key={idx}>
{item[1]}
</option>
))}
</>
:
data?.data?.length == 1 ?
data?.data?.map((item, idx) => (
<option value={item[0]} key={idx}>
{item[1]}
</option>
))
:
data?.data?.length < 1 && data.loading ?
<option value=''>
Loading...
</option>
:
<option value=''>
No Country Found!
</option>
}
</select>
</div>
</div>
+118 -82
View File
@@ -1,16 +1,20 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
import ForgetPwdResponse from "../ForgetPwdResponse";
import PasswordValidator from "../../../lib/PasswordValidator";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const VerifyPassword = () => {
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [requestStatus, setRequestStatus] = useState({loading: true, status:false, data: []})
const [msgError, setMsgError] = useState("");
const [linkLoader, setLinkLoader] = useState(false);
const [linkSuccess, setLinkSuccess] = useState(true);
const [linkSuccess, setLinkSuccess] = useState(null);
const [showPassword, setShowPassword] = useState(false);
const navigate = useNavigate();
const location = useLocation();
@@ -23,11 +27,6 @@ const VerifyPassword = () => {
setShowPassword(!showPassword);
};
// little checker for the validity of the token
if (token?.length != 64) {
setLinkSuccess(false);
}
// Password
const handlePassword = (e) => {
let { name, value } = e?.target;
@@ -36,46 +35,60 @@ const VerifyPassword = () => {
};
const completeReset = async () => {
if(!password || !confirmPassword){ // CHECKS IF PASSWORD IS EMPTY
setMsgError("Please fill in fields");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(password != confirmPassword){ // CHECKS IF PASSWORD EQUALS CONFIRM PASSWORD
setMsgError("Passwords does not match");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(password.length < 6){ // CHECKS IF PASSWORD LENGTH IS UPTO 6 CHARACTERS
setMsgError("Password must be upto six characters");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(!PasswordValidator(password)){ // CHECKS IF PASSWORD IS VALID
setMsgError("Password must contain alphanumeric, uppercase and special character: eg: Password1@");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
try {
if (password !== "" && confirmPassword !== "") {
if (password === confirmPassword) {
setLinkLoader(true);
var reqData = {
sessionid: "DUMMY-CANNOT_BE_EMPTY",
reset_link: token,
newpass: password,
m_uid: requestStatus.data?.m_uid || '',
reset_uid: requestStatus.data?.reset_uid || '',
step: 300,
action: 730,
};
const res = await userApi?.CompleteResetPassword(reqData);
if (res.status === 200) {
if (res.status == 200) {
const { data } = res;
if (data?.status > 0 && data?.email) {
setTimeout(() => {
navigate("/login", { replace: true });
setLinkLoader(false);
}, 2000);
} else if (data && data?.status == "Invalid Request") {
setLinkLoader(false);
setLinkSuccess(false);
if (data?.internal_return >= 0) {
// setTimeout(() => {
// navigate("/login", { replace: true });
// setLinkLoader(false);
// }, 2000);
setLinkSuccess(true);
} else {
setLinkLoader(false);
setMsgError("An error occurred");
setLinkSuccess(false);
}
} else {
setLinkLoader(false);
setLinkSuccess(false);
}
} else {
setLinkLoader(false);
setMsgError("Passwords does not match");
}
} else {
setMsgError("Please fill in fields");
}
} catch (error) {
setLinkLoader(false);
setLinkSuccess(false);
@@ -87,6 +100,31 @@ const VerifyPassword = () => {
}
};
const verifyResetPwd = () => { // FUNCTION TO VERIFY RESET PASSWORD LINK
setRequestStatus({loading: true, status:false, data: []})
var reqData = {
sessionid: "DUMMY-CANNOT_BE_EMPTY",
reset_link: token,
step: 200,
action: 730,
};
userApi.CompleteResetPassword(reqData).then(res => {
if(res.status != 200 || res.data.internal_return < 0){
return setRequestStatus({loading: false, status:false, data: []})
}
setRequestStatus({loading: false, status:true, data: res.data})
}).catch(error => {
setRequestStatus({loading: false, status:false, data: []})
})
}
useEffect(()=>{
// little checker for the validity of the token
if (token==null || token?.length != 64) {
return setRequestStatus({loading: false, status:false, data: []});
}
verifyResetPwd()
},[])
return (
<>
<AuthLayout slogan="Welcome to WrenchBoard">
@@ -101,39 +139,59 @@ const VerifyPassword = () => {
</Link>
</div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
{requestStatus.loading ?
<LoadingSpinner color='sky-blue' size='16' height='h-300px' />
:
!requestStatus.loading && requestStatus.status ?
<div className="w-full">
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
{linkSuccess ? "Password Reset" : "Invalid verification link"}
</h1>
{linkSuccess && (
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
Enter a new password to reset
</span>
)}
{linkSuccess && (
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
We'll send an email to confirm reset
</span>
)}
</div>
{/* If the verification was a success */}
{linkSuccess ? (
<SuccessfulComponent
password={password}
confirmPassword={confirmPassword}
handlePassword={handlePassword}
onSubmit={completeReset}
msgErr={msgError}
loader={linkLoader}
showPassword={showPassword}
onClick={togglePasswordVisibility}
navigateHandler={() => navigate("/login")}
/>
) : (
<ErrorComponent onClick={() => navigate("/login")} />
)}
{linkSuccess == null ?
<>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
Password Reset
</h1>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
Enter a new password to reset
</span>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
We'll send an email to confirm reset
</span>
</div>
<div>
<p className="text-red-500 font-semibold mb-3 leading-[27.3px] text-[13px]">
Must include a special, numeric, uppercase and lowercase character
</p>
</div>
<SuccessfulComponent
password={password}
confirmPassword={confirmPassword}
handlePassword={handlePassword}
onSubmit={completeReset}
msgErr={msgError}
loader={linkLoader}
showPassword={showPassword}
onClick={togglePasswordVisibility}
navigateHandler={() => navigate("/login")}
/>
</>
:
<ForgetPwdResponse
title={linkSuccess? 'Password Reset Complete' : 'Password Reset Error'}
message={linkSuccess? 'Password Reset Complete. You can login now with your new credentials' : 'Password Reset Error. Please get in touch with support for further support'
}
type={linkSuccess}
/>
}
</div>
:
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<ForgetPwdResponse
title={'Forget Password'}
message={'We are unable to continue to reset process. This error is usually due to expired links. Please start all over or contact us'}
type={requestStatus.status}
/>
</div>
}
</div>
</div>
</AuthLayout>
@@ -159,7 +217,7 @@ const SuccessfulComponent = ({
<div className="mb-5">
<InputCom
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={password?.replace(/./g, "●")}
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Password"
@@ -172,7 +230,7 @@ const SuccessfulComponent = ({
<div className="mb-5">
<InputCom
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={confirmPassword?.replace(/./g, "●")}
value={confirmPassword}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Confirm Password"
@@ -209,25 +267,3 @@ const SuccessfulComponent = ({
</div>
</div>
);
const ErrorComponent = ({ onClick }) => (
<div className="input-area">
<div className="my-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
This error occurs because you have already used this link or the link
has broken/expired. Start with the reset process again. If it doesn't
work, try to create the account from the start.
</p>
</div>
<div className="signin-area flex justify-center mb-3.5">
<button
onClick={onClick}
type="button"
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
<span>Return Home</span>
</button>
</div>
</div>
);
+4 -3
View File
@@ -1,9 +1,9 @@
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import { useNavigate } from "react-router-dom";
import usersService from "../../services/UsersService";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import CommonHead from "../UserHeader/CommonHead";
export default function BlogItem(props) {
@@ -16,6 +16,7 @@ export default function BlogItem(props) {
const filterHandler = (value) => {
setValue(value);
};
// eslint-disable-next-line no-restricted-globals
const queryParams = new URLSearchParams(location?.search);
const blog_id = queryParams.get("blog_id");
+3 -26
View File
@@ -1,9 +1,7 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
import usersService from "../../services/UsersService";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import { useEffect, useState } from "react";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
export default function AvailableJobsCard({
className,
@@ -156,27 +154,6 @@ export default function AvailableJobsCard({
</p>
</div>
{/* <div className="card-two-info flex gap-2 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="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1">
Price: <span className="text-purple">{thePrice}</span>
@@ -197,7 +197,7 @@ const AssignTaskPopout = React.memo(({ action, details, situation, familyDetail
<div className="w-full h-full lg:w-[700px] lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="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">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Assign task to {familyDetails?.firstname || details.firstName}
Assign task to {familyDetails?.firstname || details?.firstName}
</h1>
<button
type="button"
@@ -263,7 +263,7 @@ const AssignTaskPopout = React.memo(({ action, details, situation, familyDetail
</div>
{/* Task Type === select */}
{taskType == "select" && (
<div className="p-4 w-full h-[400px] overflow-y-auto bg-slate-100">
<div className="p-4 w-full h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
{familyTask?.data?.length ? (
familyTask?.data?.map((item, index) => (
<div
@@ -283,7 +283,7 @@ const AssignTaskPopout = React.memo(({ action, details, situation, familyDetail
}
className="w-[15px] h-[15px] cursor-pointer"
/>
<p className="w-full text-dark-gray tracking-wide">
<p className="w-full text-dark-gray dark:text-white tracking-wide">
{item?.title}
</p>
</div>
@@ -354,7 +354,7 @@ const AssignTaskPopout = React.memo(({ action, details, situation, familyDetail
Delivery Detail
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
value={activeTask?.data?.job_detail}
+145 -124
View File
@@ -1,29 +1,124 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { useNavigate } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import familyImage from '../../assets/images/no-family-side.png'
import familyImage from "../../assets/images/no-family-side.png";
import { formatDateString } from "../../lib";
import localImgLoad from "../../lib/localImgLoad";
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
const navigate = useNavigate();
/**
* Renders a list of family members that can be managed.
* It has its current maximum members at 8 and it comes with pagination and loading spinner functionality.
* @returns {JSX.Element} - The rendered component.
*/
export default function FamilyTable({
className,
familyList,
loader,
popUpHandler,
}) {
const navigate = useNavigate();
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentFamilyList = familyList?.slice(indexOfFirstItem, indexOfLastItem);
const currentFamilyList = familyList?.slice(
indexOfFirstItem,
indexOfLastItem
);
const handleManageClick = (familyMember) => {
navigate("/manage-family", { state: familyMember });
};
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
/**
* Renders a table row for a family member.
* @returns {JSX.Element} - The table row component.
*/
const FamilyRow = ({
firstname,
lastname,
age,
added,
last_login,
task_count,
family_uid,
banner,
}) => {
// Check for valid dates
const addedDate = added ? added.split(" ")[0] : "N/A";
const loginDate = last_login ? formatDateString(last_login) : "N/A";
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={family_uid}
>
<td className="py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1]">
<img
src={localImgLoad(`images/icons/${banner}`)}
alt={`Avatar of ${firstname} ${lastname}`}
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<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 ml-1">{addedDate}</span>
</span>
<span className="text-sm text-thin-light-gray">
Last Login:{" "}
<span className="text-purple ml-1">{loginDate}</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">
{task_count}
</span>
</div>
</td>
<td className="text-right py-4 px-2 flex items-center justify-center">
<button
onClick={() =>
handleManageClick({
firstname,
lastname,
age,
added,
last_login,
task_count,
family_uid,
banner,
})
}
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</button>
</td>
</tr>
);
};
return (
<div
className={`update-table w-full h-full p-4 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] ${
className={`update-table w-full h-full p-4 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] flex flex-col justify-between ${
className || ""
}`}
>
@@ -32,125 +127,51 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
)
:
familyList?.length > 0 ?
(
<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"></th>
</tr>
</thead>
<tbody className="h-full">
{currentFamilyList?.map((props, idx) => {
let {
firstname,
lastname,
age,
added,
last_login,
task_count,
family_uid,
banner
} = props;
let addedDate = added?.split(" ")[0];
let LoginDate = last_login?.split(" ")[0];
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={family_uid}
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1]">
<img
// src={dataImage1}
src={localImgLoad(`images/icons/${banner}`)}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<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 ml-1">
{addedDate}
</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">
{LoginDate}
</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">
{task_count}
</span>
</div>
</td>
<td className="text-right py-4 px-2 flex items-center justify-center">
<button
onClick={() => {
navigate("/manage-family", {
state: { ...props },
});
}}
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>
)
:
(
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<div className="p-2 w-full md:w-1/2">
<p className="mb-4 p-3 md:p-16">Add your family, assign tasks, and get the whole team engaged.</p>
<button
onClick={popUpHandler}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Add Family
</button>
</div>
<div className="p-2 w-full md:w-1/2">
<img className='w-full' src={familyImage} alt="Add Family" />
</div>
</div>
)
}
) : (
<>
{familyList?.length > 0 ? (
<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">No of Tasks</th>
<th className="py-4 text-right"></th>
</tr>
</thead>
<tbody className="h-full">
{currentFamilyList?.map((familyMember) => {
return <FamilyRow {...familyMember} />;
})}
</tbody>
</table>
) : (
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<div className="p-2 w-full md:w-1/2">
<p className="mb-4 p-3 md:p-16">
Add your family, assign tasks, and get the whole team
engaged.
</p>
<button
onClick={popUpHandler}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Add Family
</button>
</div>
<div className="p-2 w-full md:w-1/2">
<img className="w-full" src={familyImage} alt="Add Family" />
</div>
</div>
)}
</>
)}
</div>
{/* PAGINATION BUTTON */}
<PaginatedList
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familyList?.length
? true
: false
}
prev={currentPage == 0}
next={currentPage + itemsPerPage >= familyList.length}
data={familyList}
start={indexOfFirstItem}
stop={indexOfLastItem}
@@ -1,7 +1,10 @@
import { forwardRef } from "react";
import QRCode from "react-qr-code";
import { useSelector } from "react-redux";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, ref) => {
const { userDetails } = useSelector((state) => state.userDetails);
return (
<div
className="w-full lg:min-h-[538px] p-3 h-full flex flex-col items-center justify-center"
@@ -32,12 +35,19 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
{loader ?
<div className="w-full">
<LoadingSpinner size='8' color='sky-blue' />
</div>
:
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
// value={`https://www.google.com`}
value={`${userDetails?.uid}@${familyData?.username}@${familyData?.uid}`}
viewBox={`0 0 256 256`}
/>
}
</div>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
+15 -10
View File
@@ -5,12 +5,12 @@ import React, {
useMemo,
useState,
} from "react";
import InputCom from "../Helpers/Inputs/InputCom";
import Layout from "../Partials/Layout";
import FamilyTable from "./FamilyTable";
import SiteService from "../../services/SiteService";
import InputCom from "../Helpers/Inputs/InputCom";
import ModalCom from "../Helpers/ModalCom";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import FamilyTable from "./FamilyTable";
export default function FamilyAcc() {
const [selectTab, setValue] = useState("today");
@@ -129,6 +129,8 @@ export default function FamilyAcc() {
};
}, [listReload, memberList]);
console.log("Family List ====>", familyList.length);
return (
<Layout>
{/*<CommonHead />*/}
@@ -143,13 +145,16 @@ export default function FamilyAcc() {
>
Family Accounts
</span>
<button
onClick={popUpHandler}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Add
</button>
{(familyList.length <
process.env.REACT_APP_MAX_FAMILY_MEMBERS && !loader) && (
<button
onClick={popUpHandler}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Add
</button>
)}
</h1>
</div>
<div className="slider-btns flex space-x-4">
@@ -25,6 +25,7 @@ export default function InputCom({
maxLength = 45,
minLength = 0,
direction,
tabIndex,
error,
}) {
const inputRef = useRef(null);
@@ -92,14 +93,15 @@ export default function InputCom({
value={value}
onChange={inputHandler}
className={`input-field placeholder:text-base text-dark-gray w-full h-full ${
inputBg ? inputBg : "bg-[#FAFAFA] tracking-wide"
} dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`}
inputBg ? inputBg : "bg-[#FAFAFA] dark:bg-[#11131F] dark:text-white tracking-wide"
} focus:ring-0 focus:outline-none ${fieldClass}`}
type={type}
id={name}
name={name}
onInput={onInput}
minLength={minLengthValidation()}
maxLength={maxLengthValidation()}
tabIndex={tabIndex}
// pattern={inputPatterns()}
ref={inputRef}
readOnly={disable}
+9 -12
View File
@@ -1,12 +1,9 @@
import React from "react";
import datas from "../../data/product_data.json";
import TopSellerTopBuyerSliderSection from "./TopSellerTopBuyerSliderSection";
import CommonHead from "../UserHeader/CommonHead";
import FamilyActiveLSlde from "./FamilyActiveLSlde";
import ParentWaiting from "../MyPendingJobs/ParentWaiting";
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
import FamilyActiveLSlde from "./FamilyActiveLSlde";
export default function FamilyDash({familyOffers, MyActiveJobList}) {
export default function FamilyDash({ familyOffers, MyActiveJobList }) {
console.log("PROPS IN FAMILY DASH->", familyOffers);
const trending = MyActiveJobList;
@@ -14,13 +11,13 @@ export default function FamilyDash({familyOffers, MyActiveJobList}) {
<div>
<div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
{familyOffers && familyOffers.length > 0 &&
<MyOffersFamilyTable familyOffers={familyOffers} className="mb-10" />
}
{trending && trending.length > 0 &&
<FamilyActiveLSlde trending={trending} className="mb-10" />
}
{familyOffers && familyOffers.length > 0 && (
<MyOffersFamilyTable familyOffers={familyOffers} className="mb-10" />
)}
{trending && trending.length > 0 && (
<FamilyActiveLSlde trending={trending} className="mb-10" />
)}
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
<ParentWaiting className="mb-10" />
</div>
+124 -258
View File
@@ -1,267 +1,133 @@
import React, { useState } from "react";
import React, { useEffect, 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 usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function HomeActivities({ 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 relative min-h-[520px] ${
className || ""
}`}
>
<div className="header w-full sm:flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center mb-2 sm:mb-0">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
Recent Activities
</h1>
const [recentActivitiesData, setRecentActivitiesData] = useState({
loading: false,
status: false,
msg: "",
data: null,
});
</div>
</div>
<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>
{/* table heading */}
{/*<tr className="text-base text-thin-light-gray whitespace-nowrap px-2 border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4 w-[300px] block whitespace-nowrap">*/}
{/* All Product*/}
{/* </td>*/}
{/* <td className="py-4 whitespace-nowrap text-center">.</td>*/}
{/* <td className="py-4 whitespace-nowrap text-center"></td>*/}
const _apiCall = new usersService();
{/* <td className="py-4 whitespace-nowrap text-right"></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">
Mullican Computer Joy
</h1>
<span className="text-sm text-thin-light-gray">
Owned by <span className="text-purple">Xoeyam</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18Z"
fill="#627EEA"
/>
<path
d="M9.28125 2.25V7.23937L13.4983 9.12375L9.28125 2.25Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 2.25L5.0625 9.12375L9.28012 7.23937V2.25Z"
fill="white"
/>
<path
d="M9.28125 12.3582V15.7483L13.5011 9.91016L9.28125 12.3582Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 15.7483V12.3576L5.0625 9.91016L9.28012 15.7483Z"
fill="white"
/>
<path
d="M9.28125 11.572L13.4983 9.12348L9.28125 7.24023V11.572Z"
fill="white"
fillOpacity="0.2"
/>
<path
d="M5.0625 9.12348L9.28012 11.572V7.24023L5.0625 9.12348Z"
fill="white"
fillOpacity="0.602"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
7473 ETH
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.55225 0C7.8457 0 8.13914 0 8.43205 0C8.44829 0.026534 8.47537 0.0151623 8.49756 0.0162453C9.28966 0.0649812 10.0606 0.220936 10.8013 0.505229C12.7699 1.26172 14.2323 2.58354 15.183 4.46638C15.5999 5.29218 15.8506 6.16997 15.9561 7.08891C15.9691 7.201 15.9621 7.3158 16 7.42465C16 7.80858 16 8.19251 16 8.57698C15.9778 8.5916 15.9854 8.61543 15.9838 8.63546C15.9475 9.10387 15.8744 9.56686 15.7515 10.0206C15.1787 12.1342 13.9524 13.7603 12.0818 14.8942C11.1516 15.4579 10.1397 15.8002 9.06064 15.941C8.89497 15.9626 8.72875 15.98 8.56308 15.9995C8.17217 15.9995 7.78127 15.9995 7.39036 16C7.3752 15.9789 7.35138 15.9865 7.33135 15.9848C6.96752 15.9545 6.60639 15.9009 6.25068 15.8197C4.77639 15.4829 3.48998 14.793 2.4131 13.7311C0.998917 12.3372 0.204656 10.6461 0.0270709 8.66687C0.0205739 8.59431 0.033568 8.51904 0 8.44972C0 8.15081 0 7.85244 0 7.55352C0.0265295 7.53403 0.0151597 7.50479 0.016784 7.47988C0.0730915 6.64162 0.251218 5.83044 0.564158 5.05066C1.10179 3.71043 1.93774 2.59058 3.07634 1.70142C4.33839 0.715876 5.77098 0.159745 7.36762 0.0270755C7.4288 0.0216604 7.49432 0.0341151 7.55225 0ZM7.24635 9.86252C7.24635 10.2383 7.24526 10.6147 7.24743 10.9905C7.24797 11.0457 7.23389 11.0679 7.17596 11.0593C7.09691 11.0479 7.01678 11.0446 6.93774 11.0338C6.26746 10.9461 5.63563 10.7371 5.03952 10.4192C5.00379 10.4002 4.97834 10.3802 4.9621 10.4425C4.81375 11.0176 4.66324 11.5926 4.51164 12.1666C4.50027 12.2094 4.51272 12.2278 4.54954 12.2473C4.66486 12.3096 4.78235 12.3665 4.90309 12.4152C5.5961 12.6968 6.31998 12.8408 7.06497 12.8842C7.14131 12.8885 7.16134 12.9112 7.1608 12.9865C7.15701 13.4159 7.16026 13.8453 7.15809 14.2747C7.15755 14.3397 7.17488 14.3619 7.2431 14.3614C7.69085 14.3581 8.13914 14.3576 8.5869 14.3614C8.66432 14.3619 8.67731 14.3359 8.67731 14.2666C8.67461 13.8026 8.67677 13.3385 8.67461 12.8744C8.67407 12.8089 8.68544 12.7786 8.76015 12.765C9.09962 12.7049 9.4288 12.6058 9.74228 12.4607C10.3498 12.1802 10.8408 11.7703 11.1603 11.1724C11.4288 10.6699 11.51 10.1327 11.4618 9.56957C11.4158 9.03239 11.2366 8.55207 10.8787 8.14431C10.5506 7.77121 10.1402 7.51129 9.69843 7.29522C9.39145 7.14523 9.07363 7.02284 8.75041 6.91129C8.7098 6.89721 8.67407 6.88693 8.67407 6.82736C8.67623 6.14993 8.67569 5.4725 8.67461 4.79507C8.67461 4.75121 8.68489 4.73117 8.73308 4.73767C8.87547 4.75717 9.01895 4.77016 9.16134 4.79236C9.634 4.86493 10.0796 5.02467 10.5116 5.22395C10.5717 5.25157 10.5945 5.24886 10.6123 5.17684C10.7434 4.6467 10.8771 4.1171 11.0162 3.58913C11.0379 3.5079 11.0244 3.47541 10.948 3.44076C10.2799 3.13751 9.57282 3.01025 8.8457 2.97614C8.78018 2.97289 8.76123 2.95556 8.76178 2.88896C8.76503 2.50232 8.76232 2.11568 8.76448 1.72904C8.76503 1.66785 8.75041 1.64727 8.68489 1.64727C8.23173 1.64998 7.77802 1.64998 7.32485 1.64727C7.26151 1.64673 7.24418 1.66406 7.24418 1.72742C7.24689 2.1433 7.24256 2.55972 7.24797 2.9756C7.24905 3.06116 7.2209 3.08661 7.14239 3.10285C6.73579 3.18679 6.34651 3.32271 5.98646 3.53281C5.20628 3.98822 4.72117 4.64724 4.61938 5.5586C4.51597 6.48837 4.83812 7.2427 5.57661 7.81778C6.05739 8.19251 6.60639 8.43781 7.1738 8.64683C7.2274 8.66633 7.24743 8.68907 7.24689 8.7481C7.24472 9.12066 7.24635 9.49159 7.24635 9.86252Z"
fill="#59BE59"
/>
<path
d="M7.2452 9.86252C7.2452 9.49158 7.24358 9.12119 7.24683 8.75026C7.24737 8.69123 7.22734 8.66903 7.17374 8.64899C6.60687 8.43997 6.05787 8.19467 5.57655 7.81994C4.8386 7.24486 4.51591 6.49053 4.61933 5.56076C4.72057 4.6494 5.20568 3.99092 5.98641 3.53497C6.34645 3.32486 6.73519 3.18894 7.14233 3.10501C7.22084 3.08876 7.24899 3.06277 7.24791 2.97775C7.2425 2.56187 7.24683 2.14545 7.24412 1.72957C7.24358 1.66621 7.2609 1.64888 7.32479 1.64943C7.77796 1.65213 8.23167 1.65213 8.68483 1.64943C8.7498 1.64888 8.76442 1.66946 8.76442 1.73119C8.76171 2.11783 8.76496 2.50447 8.76171 2.89111C8.76117 2.95717 8.78012 2.97504 8.84563 2.97829C9.57276 3.01295 10.2793 3.13966 10.948 3.44291C11.0243 3.47757 11.0373 3.51006 11.0162 3.59128C10.877 4.11926 10.7433 4.64885 10.6123 5.17899C10.5944 5.25156 10.5717 5.25372 10.5116 5.2261C10.079 5.02683 9.63394 4.86708 9.16128 4.79452C9.01889 4.77286 8.87595 4.75932 8.73302 4.73983C8.68483 4.73333 8.67455 4.75337 8.67455 4.79723C8.67563 5.47466 8.67617 6.15209 8.674 6.82952C8.674 6.88908 8.70974 6.89937 8.75034 6.91345C9.07303 7.02446 9.39138 7.14684 9.69837 7.29738C10.1396 7.51344 10.5506 7.77283 10.8787 8.14647C11.2365 8.55369 11.4157 9.03455 11.4618 9.57173C11.51 10.1349 11.4287 10.6726 11.1602 11.1746C10.8408 11.7724 10.3497 12.1818 9.74222 12.4629C9.42874 12.608 9.09956 12.7071 8.76009 12.7672C8.68483 12.7802 8.674 12.811 8.67455 12.8766C8.67671 13.3406 8.67455 13.8047 8.67725 14.2688C8.67779 14.3381 8.66426 14.3646 8.58684 14.3636C8.13908 14.3598 7.69079 14.3608 7.24304 14.3636C7.17536 14.3641 7.15803 14.3424 7.15803 14.2769C7.1602 13.8475 7.15695 13.4181 7.16074 12.9887C7.16128 12.9128 7.14179 12.8906 7.06491 12.8863C6.31992 12.843 5.59658 12.699 4.90303 12.4174C4.78229 12.3681 4.66426 12.3112 4.54948 12.2495C4.51321 12.23 4.50075 12.2116 4.51158 12.1688C4.66318 11.5943 4.81369 11.0197 4.96204 10.4446C4.97829 10.3824 5.00373 10.4024 5.03947 10.4214C5.63557 10.7387 6.2674 10.9477 6.93768 11.036C7.01672 11.0463 7.09685 11.0501 7.1759 11.0614C7.23383 11.0695 7.24737 11.0479 7.24737 10.9927C7.24412 10.6147 7.2452 10.2383 7.2452 9.86252ZM8.68537 9.36325C8.67942 9.37245 8.67455 9.37678 8.67455 9.38112C8.674 9.83978 8.67401 10.2984 8.67292 10.7571C8.67292 10.8177 8.70216 10.7928 8.72598 10.7755C8.82452 10.7046 8.90736 10.619 8.96691 10.5123C9.17698 10.1333 9.05679 9.63725 8.68537 9.36325ZM7.23871 6.11147C7.23871 5.75354 7.23871 5.40589 7.23871 5.05174C6.92522 5.33982 6.92522 5.77249 7.23871 6.11147Z"
fill="#FEFEFE"
/>
<path
d="M8.68433 9.36328C9.05574 9.63729 9.17539 10.1333 8.96586 10.5118C8.90631 10.619 8.82347 10.7046 8.72493 10.775C8.70111 10.7918 8.67188 10.8172 8.67188 10.7566C8.67242 10.2979 8.67296 9.83927 8.6735 9.38061C8.67404 9.37682 8.67891 9.37249 8.68433 9.36328Z"
fill="#59BE59"
/>
<path
d="M7.23882 6.11149C6.92533 5.77305 6.92587 5.33984 7.23882 5.05176C7.23882 5.40591 7.23882 5.75355 7.23882 6.11149Z"
fill="#59BE59"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium">
6392.99$
</span>
</div>
</td>
const getRecentActivities = async () => {
setRecentActivitiesData((prev) => ({ ...prev, loading: true }));
let res;
try {
res = await _apiCall.getRecentActivities(null);
res = res.data;
if (res?.internal_return >= 0) {
setRecentActivitiesData((prev) => ({
...prev,
loading: false,
status: true,
data: res.result_list,
}));
} else {
setRecentActivitiesData((prev) => ({
...prev,
loading: false,
status: false,
msg: "Something went wrong",
}));
}
} catch (error) {
setRecentActivitiesData((prev) => ({
...prev,
loading: false,
status: false,
msg: "Unable to see this",
}));
throw new Error(`Unable to see this because: ${error}`);
}
};
<td className="text-right py-4">
<button
type="button"
className="text-sm text-white bg-purple px-2.5 py-1.5 rounded-full"
>
Active
</button>
</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={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">
Mullican Computer Joy
</h1>
<span className="text-sm text-thin-light-gray">
Owned by <span className="text-purple">Xoeyam</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18Z"
fill="#627EEA"
/>
<path
d="M9.28125 2.25V7.23937L13.4983 9.12375L9.28125 2.25Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 2.25L5.0625 9.12375L9.28012 7.23937V2.25Z"
fill="white"
/>
<path
d="M9.28125 12.3582V15.7483L13.5011 9.91016L9.28125 12.3582Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 15.7483V12.3576L5.0625 9.91016L9.28012 15.7483Z"
fill="white"
/>
<path
d="M9.28125 11.572L13.4983 9.12348L9.28125 7.24023V11.572Z"
fill="white"
fillOpacity="0.2"
/>
<path
d="M5.0625 9.12348L9.28012 11.572V7.24023L5.0625 9.12348Z"
fill="white"
fillOpacity="0.602"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
7473 ETH
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.55225 0C7.8457 0 8.13914 0 8.43205 0C8.44829 0.026534 8.47537 0.0151623 8.49756 0.0162453C9.28966 0.0649812 10.0606 0.220936 10.8013 0.505229C12.7699 1.26172 14.2323 2.58354 15.183 4.46638C15.5999 5.29218 15.8506 6.16997 15.9561 7.08891C15.9691 7.201 15.9621 7.3158 16 7.42465C16 7.80858 16 8.19251 16 8.57698C15.9778 8.5916 15.9854 8.61543 15.9838 8.63546C15.9475 9.10387 15.8744 9.56686 15.7515 10.0206C15.1787 12.1342 13.9524 13.7603 12.0818 14.8942C11.1516 15.4579 10.1397 15.8002 9.06064 15.941C8.89497 15.9626 8.72875 15.98 8.56308 15.9995C8.17217 15.9995 7.78127 15.9995 7.39036 16C7.3752 15.9789 7.35138 15.9865 7.33135 15.9848C6.96752 15.9545 6.60639 15.9009 6.25068 15.8197C4.77639 15.4829 3.48998 14.793 2.4131 13.7311C0.998917 12.3372 0.204656 10.6461 0.0270709 8.66687C0.0205739 8.59431 0.033568 8.51904 0 8.44972C0 8.15081 0 7.85244 0 7.55352C0.0265295 7.53403 0.0151597 7.50479 0.016784 7.47988C0.0730915 6.64162 0.251218 5.83044 0.564158 5.05066C1.10179 3.71043 1.93774 2.59058 3.07634 1.70142C4.33839 0.715876 5.77098 0.159745 7.36762 0.0270755C7.4288 0.0216604 7.49432 0.0341151 7.55225 0ZM7.24635 9.86252C7.24635 10.2383 7.24526 10.6147 7.24743 10.9905C7.24797 11.0457 7.23389 11.0679 7.17596 11.0593C7.09691 11.0479 7.01678 11.0446 6.93774 11.0338C6.26746 10.9461 5.63563 10.7371 5.03952 10.4192C5.00379 10.4002 4.97834 10.3802 4.9621 10.4425C4.81375 11.0176 4.66324 11.5926 4.51164 12.1666C4.50027 12.2094 4.51272 12.2278 4.54954 12.2473C4.66486 12.3096 4.78235 12.3665 4.90309 12.4152C5.5961 12.6968 6.31998 12.8408 7.06497 12.8842C7.14131 12.8885 7.16134 12.9112 7.1608 12.9865C7.15701 13.4159 7.16026 13.8453 7.15809 14.2747C7.15755 14.3397 7.17488 14.3619 7.2431 14.3614C7.69085 14.3581 8.13914 14.3576 8.5869 14.3614C8.66432 14.3619 8.67731 14.3359 8.67731 14.2666C8.67461 13.8026 8.67677 13.3385 8.67461 12.8744C8.67407 12.8089 8.68544 12.7786 8.76015 12.765C9.09962 12.7049 9.4288 12.6058 9.74228 12.4607C10.3498 12.1802 10.8408 11.7703 11.1603 11.1724C11.4288 10.6699 11.51 10.1327 11.4618 9.56957C11.4158 9.03239 11.2366 8.55207 10.8787 8.14431C10.5506 7.77121 10.1402 7.51129 9.69843 7.29522C9.39145 7.14523 9.07363 7.02284 8.75041 6.91129C8.7098 6.89721 8.67407 6.88693 8.67407 6.82736C8.67623 6.14993 8.67569 5.4725 8.67461 4.79507C8.67461 4.75121 8.68489 4.73117 8.73308 4.73767C8.87547 4.75717 9.01895 4.77016 9.16134 4.79236C9.634 4.86493 10.0796 5.02467 10.5116 5.22395C10.5717 5.25157 10.5945 5.24886 10.6123 5.17684C10.7434 4.6467 10.8771 4.1171 11.0162 3.58913C11.0379 3.5079 11.0244 3.47541 10.948 3.44076C10.2799 3.13751 9.57282 3.01025 8.8457 2.97614C8.78018 2.97289 8.76123 2.95556 8.76178 2.88896C8.76503 2.50232 8.76232 2.11568 8.76448 1.72904C8.76503 1.66785 8.75041 1.64727 8.68489 1.64727C8.23173 1.64998 7.77802 1.64998 7.32485 1.64727C7.26151 1.64673 7.24418 1.66406 7.24418 1.72742C7.24689 2.1433 7.24256 2.55972 7.24797 2.9756C7.24905 3.06116 7.2209 3.08661 7.14239 3.10285C6.73579 3.18679 6.34651 3.32271 5.98646 3.53281C5.20628 3.98822 4.72117 4.64724 4.61938 5.5586C4.51597 6.48837 4.83812 7.2427 5.57661 7.81778C6.05739 8.19251 6.60639 8.43781 7.1738 8.64683C7.2274 8.66633 7.24743 8.68907 7.24689 8.7481C7.24472 9.12066 7.24635 9.49159 7.24635 9.86252Z"
fill="#59BE59"
/>
<path
d="M7.2452 9.86252C7.2452 9.49158 7.24358 9.12119 7.24683 8.75026C7.24737 8.69123 7.22734 8.66903 7.17374 8.64899C6.60687 8.43997 6.05787 8.19467 5.57655 7.81994C4.8386 7.24486 4.51591 6.49053 4.61933 5.56076C4.72057 4.6494 5.20568 3.99092 5.98641 3.53497C6.34645 3.32486 6.73519 3.18894 7.14233 3.10501C7.22084 3.08876 7.24899 3.06277 7.24791 2.97775C7.2425 2.56187 7.24683 2.14545 7.24412 1.72957C7.24358 1.66621 7.2609 1.64888 7.32479 1.64943C7.77796 1.65213 8.23167 1.65213 8.68483 1.64943C8.7498 1.64888 8.76442 1.66946 8.76442 1.73119C8.76171 2.11783 8.76496 2.50447 8.76171 2.89111C8.76117 2.95717 8.78012 2.97504 8.84563 2.97829C9.57276 3.01295 10.2793 3.13966 10.948 3.44291C11.0243 3.47757 11.0373 3.51006 11.0162 3.59128C10.877 4.11926 10.7433 4.64885 10.6123 5.17899C10.5944 5.25156 10.5717 5.25372 10.5116 5.2261C10.079 5.02683 9.63394 4.86708 9.16128 4.79452C9.01889 4.77286 8.87595 4.75932 8.73302 4.73983C8.68483 4.73333 8.67455 4.75337 8.67455 4.79723C8.67563 5.47466 8.67617 6.15209 8.674 6.82952C8.674 6.88908 8.70974 6.89937 8.75034 6.91345C9.07303 7.02446 9.39138 7.14684 9.69837 7.29738C10.1396 7.51344 10.5506 7.77283 10.8787 8.14647C11.2365 8.55369 11.4157 9.03455 11.4618 9.57173C11.51 10.1349 11.4287 10.6726 11.1602 11.1746C10.8408 11.7724 10.3497 12.1818 9.74222 12.4629C9.42874 12.608 9.09956 12.7071 8.76009 12.7672C8.68483 12.7802 8.674 12.811 8.67455 12.8766C8.67671 13.3406 8.67455 13.8047 8.67725 14.2688C8.67779 14.3381 8.66426 14.3646 8.58684 14.3636C8.13908 14.3598 7.69079 14.3608 7.24304 14.3636C7.17536 14.3641 7.15803 14.3424 7.15803 14.2769C7.1602 13.8475 7.15695 13.4181 7.16074 12.9887C7.16128 12.9128 7.14179 12.8906 7.06491 12.8863C6.31992 12.843 5.59658 12.699 4.90303 12.4174C4.78229 12.3681 4.66426 12.3112 4.54948 12.2495C4.51321 12.23 4.50075 12.2116 4.51158 12.1688C4.66318 11.5943 4.81369 11.0197 4.96204 10.4446C4.97829 10.3824 5.00373 10.4024 5.03947 10.4214C5.63557 10.7387 6.2674 10.9477 6.93768 11.036C7.01672 11.0463 7.09685 11.0501 7.1759 11.0614C7.23383 11.0695 7.24737 11.0479 7.24737 10.9927C7.24412 10.6147 7.2452 10.2383 7.2452 9.86252ZM8.68537 9.36325C8.67942 9.37245 8.67455 9.37678 8.67455 9.38112C8.674 9.83978 8.67401 10.2984 8.67292 10.7571C8.67292 10.8177 8.70216 10.7928 8.72598 10.7755C8.82452 10.7046 8.90736 10.619 8.96691 10.5123C9.17698 10.1333 9.05679 9.63725 8.68537 9.36325ZM7.23871 6.11147C7.23871 5.75354 7.23871 5.40589 7.23871 5.05174C6.92522 5.33982 6.92522 5.77249 7.23871 6.11147Z"
fill="#FEFEFE"
/>
<path
d="M8.68433 9.36328C9.05574 9.63729 9.17539 10.1333 8.96586 10.5118C8.90631 10.619 8.82347 10.7046 8.72493 10.775C8.70111 10.7918 8.67188 10.8172 8.67188 10.7566C8.67242 10.2979 8.67296 9.83927 8.6735 9.38061C8.67404 9.37682 8.67891 9.37249 8.68433 9.36328Z"
fill="#59BE59"
/>
<path
d="M7.23882 6.11149C6.92533 5.77305 6.92587 5.33984 7.23882 5.05176C7.23882 5.40591 7.23882 5.75355 7.23882 6.11149Z"
fill="#59BE59"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium">
6392.99$
</span>
</div>
</td>
useEffect(() => {
getRecentActivities();
}, []);
<td className="text-right py-4">
<button
type="button"
className="text-sm text-white bg-light-green px-2.5 py-1.5 rounded-full"
>
Complated
</button>
</td>
</tr>
</tbody>
</table>
</div>
console.log(recentActivitiesData);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow relative min-h-[520px] ${
className || ""
}`}
>
<div className="header w-full sm:flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center mb-4 sm:mb-0">
<h1 className="text-center text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
Recent Activities
</h1>
</div>
);
</div>
<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>
{/* table heading */}
{/*<tr className="text-base text-thin-light-gray whitespace-nowrap px-2 border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4 w-[300px] block whitespace-nowrap">*/}
{/* All Product*/}
{/* </td>*/}
{/* <td className="py-4 whitespace-nowrap text-center">.</td>*/}
{/* <td className="py-4 whitespace-nowrap text-center"></td>*/}
{/* <td className="py-4 whitespace-nowrap text-right"></td>*/}
{/*</tr>*/}
{recentActivitiesData.loading ? (
<tr>
<td>
<div className="h-[100px] w-full flex justify-center items-center">
<LoadingSpinner color="sky-blue" size="16" />
</div>
</td>
</tr>
) : recentActivitiesData.data ? (
recentActivitiesData.data?.map((item) => {
let addedDate = item?.added?.split(" ")[0];
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={item.uid}
>
<td className="py-3">
<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">
{item.title ? item.title : "Title"}
</h1>
<span className="text-sm text-thin-light-gray">
{item.description ? item.description : ""}
</span>
</div>
</div>
</td>
<td className="text-right py-3">
<div className="flex space-x-1 items-center justify-end">
<span className="text-base text-dark-gray dark:text-white font-medium">
{item.added ? addedDate : ""}
</span>
</div>
</td>
</tr>
);
})
) : null}
</tbody>
</table>
</div>
</div>
);
}
+1 -1
View File
@@ -7,7 +7,7 @@ import FamilyDash from "./FamilyDash";
import FullAccountDash from "./FullAccountDash";
export default function Home(props) {
console.log("PROPS IN HOME->", props);
// console.log("PROPS IN HOME->", props);
const userApi = new usersService();
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
+3 -3
View File
@@ -1,8 +1,8 @@
import React, { useEffect, useMemo, useState } from "react";
import DataIteration from "../Helpers/DataIteration";
import AvailableJobsCard from "../Cards/AvailableJobsCard";
import ListView from "../../assets/images/list-view.png";
import GridView from "../../assets/images/grid-view.svg";
import ListView from "../../assets/images/list-view.png";
import AvailableJobsCard from "../Cards/AvailableJobsCard";
import DataIteration from "../Helpers/DataIteration";
import SelectBox from "../Helpers/SelectBox";
export default function MainSection({
@@ -125,10 +125,10 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
<CloseIcon onClose={onClose} />
</div>
<div className="md:flex bg-white rounded-lg">
<div className="md:flex bg-white dark:bg-dark-white text-slate-900 dark:text-white rounded-lg">
<div className="p-4 w-full md:w-[75%] md:border-r-1">
<div className="min-h-[263px]">
<h2 className="font-semibold text-slate-900 dark:text-black tracking-wide">
<h2 className="font-semibold text-slate-900 dark:text-white tracking-wide">
{details?.title}
</h2>
@@ -152,11 +152,11 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
},
].map(({ name, content, danger }, idx) => (
<div className={`my-3 md:flex items-center`} key={idx}>
<label className="w-full md:w-[19%] text-slate-900 tracking-wide font-semibold whitespace-pre-wrap">
<label className="w-full md:w-[19%] tracking-wide font-semibold whitespace-pre-wrap">
{name}
</label>
<div
className={`w-full md:w-3/4 text-slate-900 market-pop ${
className={`w-full md:w-3/4 text-slate-900 dark:text-white market-pop ${
name !== "Delivery Detail"
? " h-full max-h-28 flex items-center"
: " overflow-y-auto max-h-[100px]"
@@ -164,20 +164,20 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
>
{danger ? (
<p
className={``}
className={`dark:text-white`}
dangerouslySetInnerHTML={{
__html: danger && content,
}}
/>
) : (
<p className={`w-full text-slate-900`}>
<p className={`w-full text-slate-900 dark:text-white`}>
{name !== "Delivery Detail" ? (
<>
{typeof content !== "object" ? content : null}
{typeof content === "object" && (
<>
<hr className="mb-1" />
<span className="flex items-center gap-2">
<span className="flex items-center gap-2 dark:text-white">
{content?.text}
<strong>{thePrice}</strong>
</span>
@@ -197,11 +197,11 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
<hr />
<div className="my-3 w-full flex flex-col gap-3">
<div className="w-full">
<label className="w-full text-slate-900 tracking-wide">
<label className="w-full text-slate-900 dark:text-white tracking-wide">
If you have any questions about this task:
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
placeholder="Enter message here ..."
@@ -226,7 +226,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
</div>
<div className="w-full md:w-[23%] h-full ">
<div className="mx-auto bg-[#f1f8ff] p-4 rounded-md md:min-h-[498px] flex flex-col justify-between">
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] p-4 rounded-md md:min-h-[498px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center py-4 gap-2">
<p className="w-full text-slate-900 tracking-wide my-1">
Interested in the task?
@@ -261,7 +261,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
</>
</div>
<div className="">
<div className="text-slate-900">
<p className="flex items-center tracking-wide">
Interest: <b className="ml-1">{details.interest_count}</b>
</p>
+4 -4
View File
@@ -1,7 +1,7 @@
import Layout from "../Partials/Layout";
import MainSection from "./MainSection";
import CommonHead from "../UserHeader/CommonHead";
import { useSelector } from "react-redux";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import MainSection from "./MainSection";
export default function MarketPlace({ commonHeadData }) {
let { jobLists } = useSelector((state) => state.jobLists);
@@ -20,4 +20,4 @@ export default function MarketPlace({ commonHeadData }) {
</Layout>
</>
);
}
}
@@ -35,7 +35,11 @@ export default function ActiveJobMessage({ activeJobMesList }) {
<td>
<div className={`msg_box ${item.who}`}>
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
{item.msg_type == 'FILE' ?
<a href='' className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></a>
:
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
}
</div>
</td>
+27 -20
View File
@@ -1,13 +1,13 @@
import React, { useEffect, useState, useRef } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useSelector } from "react-redux";
import Layout from "../Partials/Layout";
import { useNavigate } from "react-router-dom";
import ActiveJobMessage from "./ActiveJobMessage";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import CountDown from "../Helpers/CountDown";
import IndexJobActions from "./JobActions/IndexJobActions";
import ModalCom from "../Helpers/ModalCom";
import { useReactToPrint } from "react-to-print";
import CountDown from "../Helpers/CountDown";
import ModalCom from "../Helpers/ModalCom";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import ActiveJobMessage from "./ActiveJobMessage";
import IndexJobActions from "./JobActions/IndexJobActions";
import usersService from "../../services/UsersService";
@@ -259,14 +259,17 @@ function ActiveJobs(props) {
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() =>{
if(props.details.pathname == '/manage-family'){
navigate(props.details.pathname, {state: { ...props.details.accountDetails }}, { replace: true })
}else{
navigate(props.details.pathname, { replace: true })
}
onClick={() => {
if (props.details.pathname == "/manage-family") {
navigate(
props.details.pathname,
{ state: { ...props.details.accountDetails } },
{ replace: true }
);
} else {
navigate(props.details.pathname, { replace: true });
}
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -367,15 +370,17 @@ function ActiveJobs(props) {
{/* TEXTAREA SECTION */}
<div className="mt-5">
<div className="">
<div
<div
className="pl-7 my-2 flex items-center border-b border-slate-300 gap-3"
// className='ml-7 flex justify-start items-center gap-3'
>
>
<button
name="message"
onClick={(e) => setTab(e.target.name)}
className={`px-4 py-1 rounded-t-2xl ${
tab == "message" ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
tab == "message"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
>
Send Message
@@ -384,7 +389,9 @@ function ActiveJobs(props) {
name="files"
onClick={(e) => setTab(e.target.name)}
className={`px-4 py-1 rounded-t-2xl ${
tab == "files" ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
tab == "files"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
>
Send Files
@@ -471,7 +478,7 @@ function ActiveJobs(props) {
<button
onClick={sendFile}
type="button"
className='btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer flex justify-center items-center'
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer flex justify-center items-center"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
@@ -495,7 +502,7 @@ function ActiveJobs(props) {
<button
onClick={sendTaskMessage}
type="button"
className='btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer'
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
+2 -1
View File
@@ -26,7 +26,8 @@ const CouponPopup = ({ popUpHandler, data }) => {
setStatusMsg({ error: "An error occurred" });
else setStatusMsg({ success: res.data?.status_text });
dispatch(tableReload({ type: "COUPONTABLE" }));
// dispatch(tableReload({ type: "COUPONTABLE" }));
dispatch(tableReload({ type: "WALLETTABLE" }));
setTimeout(() => {
popUpHandler();
setLoader(false);
+2 -2
View File
@@ -7,7 +7,7 @@ import { useSelector } from "react-redux";
export default function MyCoupons() {
const apiCall = useMemo(() => new usersService(), []);
const {couponTable} = useSelector(state => state.tableReload)
const {couponTable, walletTable} = useSelector(state => state.tableReload)
let [couponHistory, setCouponHistory] = useState({
// FOR COUPON HISTORY
loading: true,
@@ -38,7 +38,7 @@ export default function MyCoupons() {
useEffect(() => {
getCouponHistory();
}, [couponTable]);
}, [couponTable, walletTable]);
return (
<>
@@ -0,0 +1,131 @@
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";
import { useDispatch } from "react-redux";
function DeleteTaskModal({ details, onClose, situation }) {
let dispatch = useDispatch();
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 TO DELETE TASK
const deleteTask = () => {
setRequestStatus(prev => ({...prev, loading:true, message: 'No API Yet'}))
setTimeout(()=>{
setRequestStatus(prev => ({...prev, loading:false, message: ''}))
},3000)
}
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lg:w-[500px] 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 Task
</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="#4687ba" />
<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>
</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={() => deleteTask(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 DeleteTaskModal;
@@ -33,11 +33,6 @@ export default function MyPendingJobTable({ MyJobList, className }) {
<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 &&
@@ -7,7 +7,9 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import usersService from "../../services/UsersService";
import DeleteIcon from '../../assets/images/icon-delete.svg'
import DeleteTaskModal from "./DeleteTaskModal";
import SendReminderModal from "./SendReminderModal";
export default function ParentWaitingTable() {
// const transationFilterData = [
@@ -34,6 +36,9 @@ export default function ParentWaitingTable() {
const apiCall = new usersService()
let [deleteTaskPopout, setDeleteTaskPopout] = useState({show:false, data:{}}) // HOLDS THE INFO OF DELETE TASK POPOUT
let [sendReminderPopout, setSendReminderPopout] = useState({show:false, data:{}}) // HOLDS THE INFO OF SEND REMINDER POPOUT
let [familySuggestList, setFamilySuggestList] = useState({loading: true, data:[]})
const [currentPage, setCurrentPage] = useState(0);
@@ -97,7 +102,7 @@ export default function ParentWaitingTable() {
<div className="icon w-14 h-14 flex justify-center items-center">
<img src={Image} alt="" className="w-full h-full" />
</div>
<div className="">
<div className="w-full">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{item.title}
</p>
@@ -107,12 +112,35 @@ export default function ParentWaitingTable() {
</p>
</div>
</div>
<div className="px-2 self-end">
<p className="text-sm font-bold text-dark-gray dark:text-white">
{new Date(item.added).toLocaleString().split(',')[0]}
</p>
<p className="text-xs py-1.5 w-[50px] tracking-wide rounded-full bg-gold text-white flex justify-center items-center">{item.status_text}</p>
<div className="min-w-[100px] flex justify-start items-end px-2 gap-1">
<button
type="button"
className="p-1 border-2 border-red-400 rounded-md"
onClick={() => {
setDeleteTaskPopout({
show: true,
data: { ...item },
});
}}
>
<img className="min-w-[21px] h-[21px]" src={DeleteIcon} alt='delete-icon' />
</button>
<div className="">
<p className="text-sm font-bold text-dark-gray dark:text-white">
{new Date(item.added).toLocaleString().split(',')[0]}
</p>
<p
className="text-xs py-1.5 w-[50px] tracking-wide rounded-full bg-gold text-white flex justify-center items-center cursor-pointer"
onClick={() => {
setSendReminderPopout({
show: true,
data: { ...item },
});
}}
>{item.status_text}</p>
</div>
</div>
</div>
</li>
@@ -122,6 +150,30 @@ export default function ParentWaitingTable() {
:
<p className="w-full flex items-center justify-center text-xl text-dark-gray dark:text-white">No List Found!</p>
}
{/* Delete Task Popout */}
{deleteTaskPopout.show && (
<DeleteTaskModal
details={deleteTaskPopout.data}
onClose={() => {
setDeleteTaskPopout({ show: false, data: {} });
}}
situation={deleteTaskPopout.show}
/>
)}
{/* END of Delete Task Popout */}
{/* Send Reminder Popout */}
{sendReminderPopout.show && (
<SendReminderModal
details={sendReminderPopout.data}
onClose={() => {
setSendReminderPopout({ show: false, data: {} });
}}
situation={sendReminderPopout.show}
/>
)}
{/* END of Send Reminder Popout */}
</div>
{/* PAGINATION BUTTON */}
@@ -0,0 +1,130 @@
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";
import { useDispatch } from "react-redux";
function SendReminderModal({ details, onClose, situation }) {
console.log('details',details)
let dispatch = useDispatch();
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 TO SEND REMINDER
const sendReminder = () => {
setRequestStatus(prev => ({...prev, loading:true, message: 'No API Yet'}))
setTimeout(()=>{
setRequestStatus(prev => ({...prev, loading:false, message: ''}))
},3000)
}
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lg:w-[500px] 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">
Send Reminder
</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 p-8">
<div className="mb-6 w-full flex gap-4 items-center">
<div className="icon max-w-[150px] min-w-[150px] max-h-[150px] min-h-[150px] flex justify-center items-center">
<img src={require(`../../assets/images/family/${details.banner || "default.jpg"}`)} alt="" className="w-full h-full" />
</div>
<div className="w-full">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{details.title}
</p>
<p className="text-sm mb-2 text-thin-light-gray font-medium">
{details.description}
</p>
{
details.remind &&
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
Last Remind: {new Date(details.remind).toLocaleString().split(',')[0]}
</p>
}
</div>
</div>
<div className="w-full flex justify-end">
{/* <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={() => sendReminder(details)}
type="button"
className="text-white bg-sky-blue text-18 tracking-wide px-4 py-3 rounded-full"
>
Send Reminder
</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 SendReminderModal;
@@ -38,8 +38,7 @@ export default function MyOffersFamilyTable({ className, familyOffers }) {
},
],
};
console.log("YES WE SEE OFFERS", familyOffers);
// console.log("YES WE SEE OFFERS", familyOffers);
const trendingSlider = useRef(null);
const prevHandler = () => {
+237 -227
View File
@@ -64,6 +64,8 @@ const initialValues = {
};
function AddFundDollars(props) {
let MaxNoOfCards = process.env.REACT_APP_MAX_CREDIT_CARDS // HOLDS THE VALUE OF THE MAX NUMBER OF CARDS USER CAN ADD
const apiCall = new usersService();
let countryWallet = props.walletItem.country;
const [tab, setTab] = useState("previous");
@@ -240,7 +242,7 @@ function AddFundDollars(props) {
<label
onClick={() => setTab("new")}
htmlFor="new"
className="cursor-pointer flex items-center gap-1"
className={`cursor-pointer flex items-center gap-1 ${payListCards.data.length >= MaxNoOfCards ? 'pointer-events-none':''}`}
>
<input
id="new"
@@ -251,7 +253,7 @@ function AddFundDollars(props) {
tab == "new" ? "" : ""
} tracking-wide transition duration-200`}
/>
Add New Card
Add New Card {payListCards.data.length >= MaxNoOfCards && <span className="text-[14px] text-red-500">Max Reached</span>}
</label>
</div>
</form>
@@ -261,7 +263,7 @@ function AddFundDollars(props) {
{/* previous tab */}
{tab === "previous" && (
<div className="p-4 previous-details w-full min-h-[16rem] flex flex-col">
<div className="p-4 previous-details w-full min-h-[16.5rem] flex flex-col">
{payListCards.loading ? (
<LoadingSpinner size="10" color="sky-blue" />
) : payListCards?.data?.length ? (
@@ -313,254 +315,262 @@ function AddFundDollars(props) {
)}
{tab === "new" && (
<div className="new-details w-full max-h-[23rem]">
<div className="w-full flex flex-col justify-between">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => {
return (
<Form className="md:pl-8">
<div className="flex flex-col-reverse sm:flex-row">
<div className="flex-1 sm:mr-10">
<div className="fields w-full">
{/* Inputs */}
{/* Name */}
<div className="flex items-center field w-full my-2 flex-[0.4] gap-3">
<label className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1">
Name:
</label>
<p className="input-label text-[#181c32] dark:text-white text-[16px] leading-[20.9625px] font-semibold flex items-center gap-1">{`${firstname} ${lastname}`}</p>
</div>
<div className="flex items-center flex-1 gap-3 my-2">
{/* Card Number */}
<div className="field w-full flex-[0.6]">
<InputCom
fieldClass="px-6"
spanTag="*"
iconName={cardIcons}
label="Card Number"
type="text"
name="cardNum"
onInput={handleCards}
placeholder="Enter Card Number"
value={handleCardNumberChange(
props.values.cardNum
)}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.cardNum}
/>
<div className="new-details w-full max-h-[22rem]">
{payListCards.loading ?
<div className="pt-10 flex w-full h-full justify-center items-center">
<LoadingSpinner size='10' color='sky-blue' />
</div>
:payListCards.data.length < MaxNoOfCards ?
<div className="w-full flex flex-col justify-between">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => {
return (
<Form className="md:pl-8">
<div className="flex flex-col-reverse sm:flex-row">
<div className="flex-1 sm:mr-10">
<div className="fields w-full">
{/* Inputs */}
{/* Name */}
<div className="flex items-center field w-full my-2 flex-[0.4] gap-3">
<label className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1">
Name:
</label>
<p className="input-label text-[#181c32] dark:text-white text-[16px] leading-[20.9625px] font-semibold flex items-center gap-1">{`${firstname} ${lastname}`}</p>
</div>
{/* Expire Year, Year */}
<div className="sm:grid gap-5 grid-cols-2 flex-[0.4]">
<div className="field w-full mb-6 xl:mb-0 col-span-1">
<div className="select-option">
<div
className={`flex items-center justify-between mb-2.5`}
>
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold line-clamp-3 flex items-center"
htmlFor="expiration"
>
Exp Month{" "}
<span className="text-red-700 text-sm italic">
*
</span>
<span className="text-[12px] text-red-500 ml-1">
{props.errors.expirationMonth && "**"}
</span>
</label>
</div>
<div
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full 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`}
>
<select
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none`}
value={props.values.expirationMonth}
onChange={props.handleChange}
onBlur={props.handleBlur}
name="expirationMonth"
>
<option
value=""
className="text-dark-gray"
>
Month
</option>
{expireMonth?.length &&
expireMonth.map((item, index) => (
<option
key={index}
value={
Number(item.value) < 10
? "0" + item.value
: item.value
}
>
{item.name}
</option>
))}
</select>
</div>
</div>
<div className="flex items-center flex-1 gap-3 my-2">
{/* Card Number */}
<div className="field w-full flex-[0.6]">
<InputCom
fieldClass="px-6"
spanTag="*"
iconName={cardIcons}
label="Card Number"
type="text"
name="cardNum"
onInput={handleCards}
placeholder="Enter Card Number"
value={handleCardNumberChange(
props.values.cardNum
)}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.cardNum}
/>
</div>
<div className="field w-full mb-6 xl:mb-0 col-span-1">
<div className="select-option">
<div
className={`flex items-center justify-between mb-2.5`}
>
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center line-clamp-3"
htmlFor="expiration"
{/* Expire Year, Year */}
<div className="sm:grid gap-5 grid-cols-2 flex-[0.4]">
<div className="field w-full mb-6 xl:mb-0 col-span-1">
<div className="select-option">
<div
className={`flex items-center justify-between mb-2.5`}
>
Exp Year{" "}
<span className="text-red-700 text-sm tracking-wide">
*
</span>
<span className="text-[12px] text-red-500 italic">
{props.errors.expirationYear && "**"}
</span>
</label>
</div>
<div
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full 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`}
>
<select
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none`}
value={props.values.expirationYear}
onChange={props.handleChange}
onBlur={props.handleBlur}
name="expirationYear"
>
<option
value=""
className="text-dark-gray"
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold line-clamp-3 flex items-center"
htmlFor="expiration"
>
Year
</option>
{expireYear?.length &&
expireYear.map((item, index) => (
<option key={index} value={item}>
{item}
</option>
))}
</select>
Exp Month{" "}
<span className="text-red-700 text-sm italic">
*
</span>
<span className="text-[12px] text-red-500 ml-1">
{props.errors.expirationMonth && "**"}
</span>
</label>
</div>
<div
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full 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`}
>
<select
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none`}
value={props.values.expirationMonth}
onChange={props.handleChange}
onBlur={props.handleBlur}
name="expirationMonth"
>
<option
value=""
className="text-dark-gray"
>
Month
</option>
{expireMonth?.length &&
expireMonth.map((item, index) => (
<option
key={index}
value={
Number(item.value) < 10
? "0" + item.value
: item.value
}
>
{item.name}
</option>
))}
</select>
</div>
</div>
</div>
<div className="field w-full mb-6 xl:mb-0 col-span-1">
<div className="select-option">
<div
className={`flex items-center justify-between mb-2.5`}
>
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center line-clamp-3"
htmlFor="expiration"
>
Exp Year{" "}
<span className="text-red-700 text-sm tracking-wide">
*
</span>
<span className="text-[12px] text-red-500 italic">
{props.errors.expirationYear && "**"}
</span>
</label>
</div>
<div
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full 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`}
>
<select
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none`}
value={props.values.expirationYear}
onChange={props.handleChange}
onBlur={props.handleBlur}
name="expirationYear"
>
<option
value=""
className="text-dark-gray"
>
Year
</option>
{expireYear?.length &&
expireYear.map((item, index) => (
<option key={index} value={item}>
{item}
</option>
))}
</select>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Address and CVV */}
<div className="flex items-center flex-1 gap-3 my-2">
<div className="field w-full col-span-1 flex-[0.4]">
<InputCom
fieldClass="px-6"
spanTag="*"
iconName={cardIcons}
label="CVV"
type="text"
name="cvv"
placeholder="CVV"
maxLength={3}
value={props.values.cvv}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.cvv}
/>
{/* Address and CVV */}
<div className="flex items-center flex-1 gap-3 my-2">
<div className="field w-full col-span-1 flex-[0.4]">
<InputCom
fieldClass="px-6"
spanTag="*"
iconName={cardIcons}
label="CVV"
type="text"
name="cvv"
placeholder="CVV"
maxLength={3}
value={props.values.cvv}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.cvv}
/>
</div>
<div className="field w-full flex-[0.6]">
<InputCom
fieldClass="px-6"
spanTag="*"
label="Billing Address"
type="text"
name="address"
placeholder="Billing Address"
value={props.values.Address}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.address}
/>
</div>
</div>
<div className="field w-full flex-[0.6]">
<InputCom
fieldClass="px-6"
spanTag="*"
label="Billing Address"
type="text"
name="address"
placeholder="Billing Address"
value={props.values.Address}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.address}
/>
</div>
</div>
{/* Postal Code and State */}
<div className="sm:grid gap-5 grid-cols-3 my-2">
<div className="field w-full xl:mb-0 col-span-1">
<InputCom
fieldClass="px-6"
spanTag="*"
label="Postal Code"
type="number"
name="code"
placeholder="Postal Code"
value={props.values.code}
maxLength={6}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.code}
/>
</div>
<div className="field w-full col-span-1">
<InputCom
fieldClass="px-6"
spanTag="*"
label="State"
type="text"
name="state"
placeholder="State"
value={props.values.state.toUpperCase()}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.state}
/>
{/* Postal Code and State */}
<div className="sm:grid gap-5 grid-cols-3 my-2">
<div className="field w-full xl:mb-0 col-span-1">
<InputCom
fieldClass="px-6"
spanTag="*"
label="Postal Code"
type="number"
name="code"
placeholder="Postal Code"
value={props.values.code}
maxLength={6}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.code}
/>
</div>
<div className="field w-full col-span-1">
<InputCom
fieldClass="px-6"
spanTag="*"
label="State"
type="text"
name="state"
placeholder="State"
value={props.values.state.toUpperCase()}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.state}
/>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="md:px-8 add-fund-btn flex justify-end items-center gap-3">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center border-gradient text-base rounded-full"
onClick={handleClose}
>
Cancel
</button>
<button
type="submit"
className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
{props.confirmCredit?.show?.awaitConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</>
)}
</button>
</div>
</Form>
);
}}
</Formik>
</div>
<div className="add-fund-btn flex justify-end items-center gap-2 mt-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
onClick={handleClose}
>
Cancel
</button>
<button
type="submit"
className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
{props.confirmCredit?.show?.awaitConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</>
)}
</button>
</div>
</Form>
);
}}
</Formik>
</div>
:
null
}
</div>
)}
</div>
{tab == "previous" && (
<div className="md:py-8 px-[38px] add-fund-btn flex justify-end items-center gap-4 py-4">
<div className="md:py-8 add-fund-btn flex justify-end items-center gap-2 py-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center border-gradient text-base rounded-full"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
onClick={props.onClose}
>
Cancel
+55 -39
View File
@@ -26,46 +26,59 @@ function AddFundPop({
};
const handleSubmit = async () => {
setInputError("");
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: true } },
}));
if (!input || input === "0") {
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
setInputError("Please Enter Amount");
setTimeout(() => setInputError(""), 5000);
return;
}
if (Number(input) * 100 > Number(walletItem?.transfer_limit)) {
setInputError("Credit limit has been exceeded");
setTimeout(() => setInputError(""), 5000);
return;
}
if (isNaN(input)) {
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
setInputError("Amount must be a Number");
setTimeout(() => setInputError(""), 5000);
return;
}
let stateData = {
amount: Number(input) * 100,
currency: walletItem?.code,
};
try {
// Clear any previous input error and set the loading spinner to be shown
setInputError("");
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: true } },
}));
// Perform validation checks on the input amount
if (!input || input === "0") {
// Handle input validation error
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
setInputError("Please Enter Amount");
setTimeout(() => setInputError(""), 5000);
return;
}
if (Number(input) * 100 > Number(walletItem?.transfer_limit)) {
// Handle credit limit exceeded error
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
setInputError("Credit limit has been exceeded");
setTimeout(() => setInputError(""), 5000);
return;
}
if (isNaN(input)) {
// Handle invalid input error
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
setInputError("Amount must be a Number");
setTimeout(() => setInputError(""), 5000);
return;
}
// Prepare state data for API call
let stateData = {
amount: Number(input) * 100,
currency: walletItem?.code,
};
// Make API call to start credit process
const res = await apiCall.getStartCredit(stateData);
if (res.data.internal_return < 0) {
// Handle API error
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
@@ -75,6 +88,7 @@ function AddFundPop({
return;
}
// Update state with response data
const _response = res.data;
stateData.amount = Number(input);
stateData.currency = currency;
@@ -91,6 +105,7 @@ function AddFundPop({
}));
}, 1500);
} catch (error) {
// Handle API call error
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
@@ -116,6 +131,7 @@ function AddFundPop({
placeholder="0"
value={input}
inputHandler={handleChange}
tabIndex={0}
/>
<p className="text-base text-red-500 italic h-5">
{inputError && inputError}
@@ -138,12 +154,12 @@ function AddFundPop({
</div>
)}
{countryWallet == "NG" && <div className="h-[18rem]"></div>}
{countryWallet == "NG" && <div className="h-[19rem]"></div>}
{countryWallet == "NG" && (
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button
className="px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center bg-[#f5a430] text-black text-base rounded-full"
onClick={onClose}
>
Cancel
@@ -1,7 +1,12 @@
import React from "react";
/**
* Renders a modal with information about a credit transaction.
* @returns {JSX.Element} - The rendered modal component.
*/
function CompleteConfirmCredit({ onClose, confirmCredit }) {
const { data } = confirmCredit;
const isSuccess =
data?.result === "Charge success" || data?.status === "successful";
return (
<div className="logout-modal-body w-full flex flex-col items-center">
<div className="content-wrapper w-full h-[32rem]">
@@ -11,90 +16,80 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
<div className="field w-full mb-3 min-h-[45px]">
<div
className={`flex flex-col gap-4 ${
data?.result !== "Charge success" &&
"h-[328px] items-center justify-center"
!isSuccess && "h-[328px] items-center justify-center"
}`}
>
{/* Success Icon for now */}
<div className="flex items-center w-full justify-center">
{data?.result == "Charge success" ||
data?.status == "successful" ? (
<svg
xmlns="http://www.w3.org/2000/svg"
width="100"
height="100"
viewBox="0 0 24 24"
fill="none"
stroke="green"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
className="feather feather-check-circle"
>
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
width="100"
height="100"
stroke="red"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
className="feather feather-x-circle"
>
<circle cx="12" cy="12" r="10"></circle>
<line x1="15" y1="9" x2="9" y2="15"></line>
<line x1="9" y1="9" x2="15" y2="15"></line>
</svg>
)}
<svg
xmlns="http://www.w3.org/2000/svg"
width="100"
height="100"
viewBox="0 0 24 24"
fill="none"
stroke={isSuccess ? "green" : "red"}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={`feather ${
isSuccess ? "feather-check-circle" : "feather-x-circle"
}`}
>
{isSuccess ? (
<>
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</>
) : (
<>
<circle cx="12" cy="12" r="10"></circle>
<line x1="15" y1="9" x2="9" y2="15"></line>
<line x1="9" y1="9" x2="15" y2="15"></line>
</>
)}
</svg>
</div>
<div className={`flex items-center`}>
<div className="flex items-center">
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.result == "Charge success" ||
data?.status == "successful"
{isSuccess
? "Credit was Successful!"
: "Credit was Unsuccessful"}
</h1>
</div>
{data?.internal_return >= 0 ? (
<>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Amount({data?.currency || ""})
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{`${data?.symbol || ""} ${
Number(data?.amount * 0.01).toLocaleString() || ""
}`}
</span>
</div>
{data?.internal_return >= 0 &&
data?.result !== "Charge failed" && (
<>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Amount({data?.currency || ""})
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{`${data?.symbol || ""} ${
Number(data?.amount * 0.01).toLocaleString() || ""
}`}
</span>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Wallet Balance
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.curr_balance}
</span>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Wallet Balance
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.curr_balance * 0.01}
</span>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Confirmation Number
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.confirmation}
</span>
</div>
</>
) : null}
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Confirmation Number
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.confirmation}
</span>
</div>
</>
)}
</div>
</div>
</div>
+124 -84
View File
@@ -1,84 +1,102 @@
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useSelector } from "react-redux";
import { toast } from "react-toastify";
import debounce from "../../../hooks/debounce";
import usersService from "../../../services/UsersService";
import { tableReload } from "../../../store/TableReloads";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
/**
* Renders a React component that displays the description and last four digits of a payment card.
*/
function ThePaymentText({ value, type }) {
const cardDetails = value;
value.description =
type === "new"
? cardDetails.cardNum[0] === "4"
? "Visa"
: cardDetails.cardNum[0] == "5"
? "Master"
: "ATM"
: value.description;
value.digits = type === "new" ? cardDetails.cardNum.slice(-4) : value.digits;
const { cardNum } = value;
let description = value.description;
let digits = value.digits;
if (type === "new") {
const firstDigit = cardNum[0];
if (firstDigit === "4") {
description = "Visa";
} else if (firstDigit === "5") {
description = "Master";
} else {
description = "ATM";
}
digits = cardNum.slice(-4);
}
return (
<div className="my-2 flex items-center gap-5">
<div className="card-details flex items-center gap-3">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1 space-x-1">
{value.description} Card
<h1 className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1 space-x-1">
{description} Card
</h1>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
Bank **************{value.digits}
<p className="text-xl font-normal text-dark-gray dark:text-white tracking-wide">
Bank **************{digits}
</p>
</div>
</div>
);
}
/**
* Renders the amount of a transaction in a specific currency.
* @returns {JSX.Element} - The rendered component.
*/
function AmountSection({ currency, amount, country }) {
const formattedAmount = Number(amount).toFixed(2);
const formattedAmount = amount?.toFixed(2);
const gapClassName = country === "US" ? "gap-14" : "gap-4";
return (
<div
className={`flex items-center ${country == "US" ? "gap-14" : "gap-4"}`}
>
<div className={`flex items-center ${gapClassName}`}>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Amount({currency})
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{formattedAmount}
</span>
</div>
);
}
/**
* Renders the transaction fee for a payment.
* @returns {JSX.Element} - Rendered JSX displaying the transaction fee with the label "Transaction Fee".
*/
function TransactionFeeSection({ currency, fee, country }) {
const formattedFee = Number(fee).toFixed(2);
const formattedFee = (+fee).toFixed(2);
const gapClass = country === "US" ? "gap-[2.7rem]" : "gap-4";
return (
<div
className={`flex items-center border-b border-gray-600 ${
country == "US" ? "gap-[2.7rem]" : "gap-4"
}`}
>
<div className={`flex items-center border-b border-gray-600 ${gapClass}`}>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Transaction Fee
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{formattedFee}
</span>
</div>
);
}
/**
* Calculates the total amount by adding the `amount` and `fee` values together.
* Formats the total amount to two decimal places and displays it.
* @returns {JSX.Element} - The TotalSection component.
*/
function TotalSection({ currency, amount, fee, country }) {
const total = Number(amount) + Number(fee);
const formattedTotal = total.toFixed(2);
const formattedTotal = total?.toFixed(2);
const gap = country === "US" ? "gap-[8rem]" : "gap-[6.3rem]";
return (
<div
className={`flex items-center ${
country == "US" ? "gap-[8rem]" : "gap-[6.3rem]"
}`}
>
<div className={`flex items-center ${gap}`}>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Total
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{formattedTotal}
</span>
</div>
@@ -102,8 +120,6 @@ function ConfirmAddFund({
const { userDetails } = useSelector((state) => state?.userDetails);
const dispatch = useDispatch();
const [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
@@ -127,7 +143,7 @@ function ConfirmAddFund({
logo: "https://www.wrenchboard.com/assets/images/wrench-500-500-icon.png",
},
};
//debugger;
const fwConfig = {
...config,
text: "Proceed",
@@ -162,8 +178,6 @@ function ConfirmAddFund({
status: false,
});
}
return dispatch(tableReload({ type: "WALLETTABLE" }));
})
.catch((err) => {
setRequestStatus({
@@ -188,27 +202,40 @@ function ConfirmAddFund({
const debouncedSuccessPayment = debounce(onSuccessPayment, 5000);
/**
* Handles the process of making a payment using a previously saved card.
* Updates the state to show a loader while the payment is being processed,
* sends a request to the server to make the payment, and updates the state with the response.
* If the payment is successful, it also dispatches an action to reload the wallet table.
*/
const handlePrevCard = async () => {
const { amount, credit_reference, currency } = __confirmData;
const { card_uid } = __confirmCardDetails;
const reqData = {
amount: amount * 100,
card_uid,
credit_reference,
currency,
};
try {
// Show loader while the payment is being processed
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: true },
},
}));
// Extract necessary data from confirmCredit and confirmCardDetails objects
const { amount, credit_reference, currency } = __confirmData;
const { card_uid } = __confirmCardDetails;
// Create request data object with required parameters for making the payment
const reqData = {
amount: amount * 100,
card_uid,
credit_reference,
currency,
};
// Send request to server to make the payment using getPaidPrevCard method of usersService
const res = await apiURL.getPaidPrevCard(reqData);
const _response = res.data;
if (res.data.internal_return < 0) {
// If internal_return value in the response is less than 0, hide the loader and return
if (_response.internal_return < 0) {
setConfirmCredit((prev) => ({
...prev,
show: {
@@ -218,6 +245,7 @@ function ConfirmAddFund({
return;
}
// Update state to show the acceptConfirm state and the response data
setTimeout(() => {
setConfirmCredit((prev) => ({
...prev,
@@ -227,9 +255,9 @@ function ConfirmAddFund({
},
data: _response,
}));
dispatch(tableReload({ type: "WALLETTABLE" }));
}, 1500);
} catch (error) {
// Handle error and hide the loader
setConfirmCredit((prev) => ({
...prev,
show: {
@@ -240,45 +268,45 @@ function ConfirmAddFund({
}
};
/**
* Handles the payment process when a new card is used.
* @async
*/
const handleNewCard = async () => {
const { amount, credit_reference, uid } = __confirmData;
const { address, cardNum, cvv, expirationMonth, expirationYear } =
__confirmCardDetails;
const reqData = {
amount: amount * 100,
cardnumber: cardNum.replace(/\s/g, ""),
credit_reference,
cvc: cvv,
description: address,
exp_month: expirationMonth,
exp_year: expirationYear,
paymenttype: 100,
uid,
};
try {
// Extract necessary data from __confirmData and __confirmCardDetails
const { amount, credit_reference, uid } = __confirmData;
const { address, cardNum, cvv, expirationMonth, expirationYear } =
__confirmCardDetails;
// Set loading state to indicate payment is being processed
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: true },
},
}));
// Prepare request data
const reqData = {
amount: amount * 100,
cardnumber: cardNum.replace(/\s/g, ""),
credit_reference,
cvc: cvv,
description: address,
exp_month: expirationMonth,
exp_year: expirationYear,
paymenttype: 100,
uid,
};
// Send request to server to process payment
const res = await apiURL.getPaidNewCard(reqData);
const _response = res.data;
if (res.data.internal_return < 0) {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: _response,
}));
return;
}
setTimeout(() => {
// Handle response from server
if (res.data.internal_return < 0) {
// Payment could not be completed
setConfirmCredit((prev) => ({
...prev,
show: {
@@ -287,9 +315,21 @@ function ConfirmAddFund({
},
data: _response,
}));
dispatch(tableReload({ type: "WALLETTABLE" }));
}, 1500);
} else {
// Payment was successful
setTimeout(() => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: _response,
}));
}, 1500);
}
} catch (error) {
// Handle error during payment process
setConfirmCredit((prev) => ({
...prev,
show: {
@@ -362,7 +402,7 @@ function ConfirmAddFund({
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Reference No
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{__confirmData?.credit_reference}
</span>
</div>
@@ -379,7 +419,7 @@ function ConfirmAddFund({
<hr />
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button
className="px-4 h-11 flex justify-center items-center border-gradient text-base rounded-full"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
onClick={getBack}
>
Back
@@ -1,10 +1,10 @@
import { useState } from "react";
import { useDispatch } from "react-redux";
import usersService from "../../../services/UsersService";
import { tableReload } from "../../../store/TableReloads";
import InputCom from "../../Helpers/Inputs/InputCom";
import ModalCom from "../../Helpers/ModalCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { useDispatch } from "react-redux";
import { tableReload } from "../../../store/TableReloads";
function ConfirmNairaWithdraw({
payment,
@@ -393,9 +393,9 @@ function ConfirmNairaWithdraw({
<button
type="button"
onClick={action}
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center bg-[#f5a430] text-black text-base rounded-full"
>
<span className="text-gradient">Cancel</span>
Cancel
</button>
)}
+18 -16
View File
@@ -6,7 +6,7 @@ import CompleteConfirmCredit from "./CompleteConfirmCredit";
import ConfirmAddFund from "./ConfirmAddFund";
const CreditPopup = ({ details, onClose, situation, walletItem }) => {
let [input, setInput] = useState("");
const [input, setInput] = useState("");
const [confirmCredit, setConfirmCredit] = useState({
show: {
awaitConfirm: { loader: false, state: false },
@@ -15,6 +15,20 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
data: {},
});
const getTitle = () => {
if (confirmCredit?.show?.acceptConfirm?.state) {
if (confirmCredit?.data?.internal_return < 0) {
return "Credit Unsuccessful";
} else {
return "Credit Add Completed";
}
} else if (confirmCredit?.show?.awaitConfirm?.state) {
return "Confirm Credit Add";
} else {
return "Add Credit";
}
};
return (
<ModalCom
action={onClose}
@@ -24,21 +38,9 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
<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-26 font-bold text-dark-gray dark:text-white tracking-wide">
{confirmCredit?.show?.acceptConfirm?.state &&
(confirmCredit?.data?.internal_return < 0 ||
confirmCredit?.data?.status !== "successful") ? (
"Credit Unsuccessful"
) : (
<>
{confirmCredit?.show?.acceptConfirm?.loader
? "Confirming Credit..."
: confirmCredit?.show?.awaitConfirm?.state
? "Confirm Credit Add"
: confirmCredit?.show?.acceptConfirm?.state
? "Credit Add Completed"
: "Add Credit"}
</>
)}
{confirmCredit?.show?.acceptConfirm?.loader
? "Confirming Credit..."
: getTitle()}
</h1>
<button
type="button"
+281 -272
View File
@@ -12,6 +12,8 @@ function NairaWithdraw({
state,
setShowConfirmNairaWithdraw,
}) {
let MaxNoOfBanks = process.env.REACT_APP_MAX_CREDIT_BANK_ACCOUNT // HOLDS THE VALUE OF THE MAX NUMBER OF BANKS USER CAN ADD
const apiCall = new usersService();
const [tab, setTab] = useState("previous");
let [requestStatus, setRequestStatus] = useState(false);
@@ -171,7 +173,7 @@ function NairaWithdraw({
setErrorMsgs({ amount: "amount required" });
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
return;
}else if (Number(values.amount * 100) > Number(wallet?.transfer_limit)) {
} else if (Number(values.amount * 100) > Number(wallet?.transfer_limit)) {
setErrorMsgs({ amount: "Withdraw limit has been exceeded" });
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
return;
@@ -422,7 +424,7 @@ function NairaWithdraw({
<label
onClick={() => setTab("new")}
htmlFor="new"
className="cursor-pointer flex items-center gap-1"
className={`cursor-pointer flex items-center gap-1 ${recipients.data.length >= MaxNoOfBanks ? 'pointer-events-none':''}`}
>
<input
id="new"
@@ -434,7 +436,7 @@ function NairaWithdraw({
tab == "new" ? "" : ""
} tracking-wide transition duration-200`}
/>
New Account{" "}
New Account{" "} {recipients.data.length >= MaxNoOfBanks && <span className="text-[14px] text-red-500">Max Reached</span>}
</label>
</div>
</div>
@@ -517,278 +519,285 @@ function NairaWithdraw({
</div>
</div>
</div>
<div className="h-[7.8rem]"></div>
<div className="h-[6.1rem]"></div>
</>
)}
{tab == "new" && (
<div className="w-full mt-3 rounded-md bg-slate-100">
<div className="relative fields w-full flex flex-col p-4">
<div className="flex flex-[2] min-h-[52px]">
{/* country */}
<div className="add-recipient w-full flex items-center flex-1 xl:mb-0">
<label
htmlFor="newAccount.country"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.3]"
>
Country{" "}
<span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding tracking-[1.5px]"
name="newAccount.country"
value={props.values.newAccount?.country}
onChange={(e) => {
props.handleChange(e);
handleBankOptions(e);
}}
>
{allCountries.loading ? (
<option
className="text-slate-500 text-lg"
value=""
>
Loading...
</option>
) : allCountries.data?.length ? (
<>
<option
className="text-slate-500 text-lg"
value=""
>
{errorMsgs.newAccount?.country
? errorMsgs.newAccount.country
: "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!
</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 flex items-center flex-1">
<label
htmlFor="newAccount.bank"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4] tracking-[1.5px]"
>
Bank Name{" "}
<span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding "
name="newAccount.bank"
value={props.values.newAccount?.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.bank_uid}
>
{item.name}
</option>
))}
</>
) : (
<option
className="text-slate-500 text-lg"
value=""
>
{allCountries.data?.length
? "Select..."
: "No Options Found!"}
</option>
)}
</select>
{/* {props.errors.bank && props.touched.bank && (
<p className="text-sm text-red-500">
{props.errors.bank}
</p>
)} */}
</div>
</div>
<div className="flex flex-[2] gap-4">
{/* ACCOUNT NUMBER */}
<div className="field w-full flex-[1.4] flex items-center gap-2">
<label
htmlFor="newAccount.accountNumber"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex items-center flex-1"
>
Account Number{" "}
<span className="text-red-500">*</span>
</label>
<InputCom
fieldClass="px-6 tracking-[1.5px]"
inputClass="flex items-center max-w-[15rem]"
type="text"
name="newAccount.accountNumber"
placeholder="Account No"
maxLength={10}
value={props.values.newAccount?.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>
{/* Account Type */}
<div className="add-recipient w-full flex flex-1 items-center">
<label
htmlFor="newAccount.accountType"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.3]"
>
Type <span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding flex-grow tracking-[1.5px]"
name="newAccount.accountType"
value={props.values.newAccount?.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!
</option>
)}
</select>
{/* {props.errors.accountType &&
props.touched.accountType && (
<p className="text-sm text-red-500">
{props.errors.accountType}
</p>
)} */}
</div>
</div>
<div className="flex items-center flex-1">
{/* state */}
<div className="field w-full flex items-center gap-4 flex-[0.4]">
<label
htmlFor="newAccount.state"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4]"
>
State <span className="text-red-500">*</span>
</label>
<InputCom
fieldClass="px-6 tracking-[1.5px]"
inputClass="max-w-[10rem]"
type="text"
name="newAccount.state"
placeholder="State/Province"
value={props.values.newAccount?.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 flex items-center flex-[0.4]">
<label
htmlFor="newAccount.city"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4]"
>
City <span className="text-red-500">*</span>
</label>
<InputCom
fieldClass="px-6 tracking-[1.5px]"
type="text"
inputClass="max-w-[10rem]"
name="newAccount.city"
placeholder="City"
value={props.values.newAccount?.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 for new accounts */}
recipients.loading ?
<div className="mt-3 flex flex-col w-full h-[188px] justify-center items-center">
<LoadingSpinner size='10' color='sky-blue' />
</div>
</div>
:recipients.data.length < MaxNoOfBanks ?
<div className="w-full mt-3 rounded-md bg-slate-100">
<div className="relative fields w-full flex flex-col p-4">
<div className="flex flex-[2] min-h-[52px]">
{/* country */}
<div className="add-recipient w-full flex items-center flex-1 xl:mb-0">
<label
htmlFor="newAccount.country"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.3]"
>
Country{" "}
<span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding tracking-[1.5px]"
name="newAccount.country"
value={props.values.newAccount?.country}
onChange={(e) => {
props.handleChange(e);
handleBankOptions(e);
}}
>
{allCountries.loading ? (
<option
className="text-slate-500 text-lg"
value=""
>
Loading...
</option>
) : allCountries.data?.length ? (
<>
<option
className="text-slate-500 text-lg"
value=""
>
{errorMsgs.newAccount?.country
? errorMsgs.newAccount.country
: "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!
</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 flex items-center flex-1">
<label
htmlFor="newAccount.bank"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4] tracking-[1.5px]"
>
Bank Name{" "}
<span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding "
name="newAccount.bank"
value={props.values.newAccount?.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.bank_uid}
>
{item.name}
</option>
))}
</>
) : (
<option
className="text-slate-500 text-lg"
value=""
>
{allCountries.data?.length
? "Select..."
: "No Options Found!"}
</option>
)}
</select>
{/* {props.errors.bank && props.touched.bank && (
<p className="text-sm text-red-500">
{props.errors.bank}
</p>
)} */}
</div>
</div>
<div className="flex flex-[2] gap-4">
{/* ACCOUNT NUMBER */}
<div className="field w-full flex-[1.4] flex items-center gap-2">
<label
htmlFor="newAccount.accountNumber"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex items-center flex-1"
>
Account Number{" "}
<span className="text-red-500">*</span>
</label>
<InputCom
fieldClass="px-6 tracking-[1.5px]"
inputClass="flex items-center max-w-[15rem]"
type="text"
name="newAccount.accountNumber"
placeholder="Account No"
maxLength={10}
value={props.values.newAccount?.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>
{/* Account Type */}
<div className="add-recipient w-full flex flex-1 items-center">
<label
htmlFor="newAccount.accountType"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.3]"
>
Type <span className="text-red-500">*</span>
</label>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding flex-grow tracking-[1.5px]"
name="newAccount.accountType"
value={props.values.newAccount?.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!
</option>
)}
</select>
{/* {props.errors.accountType &&
props.touched.accountType && (
<p className="text-sm text-red-500">
{props.errors.accountType}
</p>
)} */}
</div>
</div>
<div className="flex items-center flex-1">
{/* state */}
<div className="field w-full flex items-center gap-4 flex-[0.4]">
<label
htmlFor="newAccount.state"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4]"
>
State <span className="text-red-500">*</span>
</label>
<InputCom
fieldClass="px-6 tracking-[1.5px]"
inputClass="max-w-[10rem]"
type="text"
name="newAccount.state"
placeholder="State/Province"
value={props.values.newAccount?.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 flex items-center flex-[0.4]">
<label
htmlFor="newAccount.city"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4]"
>
City <span className="text-red-500">*</span>
</label>
<InputCom
fieldClass="px-6 tracking-[1.5px]"
type="text"
inputClass="max-w-[10rem]"
name="newAccount.city"
placeholder="City"
value={props.values.newAccount?.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 for new accounts */}
</div>
</div>
:
<div className="mt-3 flex w-full h-[188px] justify-center items-center"></div>
)}
</div>
@@ -796,9 +805,9 @@ function NairaWithdraw({
<button
type="button"
onClick={action}
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
>
<span className="text-gradient">Cancel</span>
Cancel
</button>
<button
+7 -39
View File
@@ -1,45 +1,21 @@
import React, {
Suspense,
lazy,
useCallback,
useEffect,
useMemo,
useState,
} from "react";
import React, { Suspense, lazy, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import usersService from "../../services/UsersService";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
const WalletBox = lazy(() => import("./WalletBox"));
const WalletRoutes = () => {
const apiCall = new usersService();
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
const { walletTable } = useSelector((state) => state.tableReload);
const [walletList, setWalletList] = useState({
loading: true,
data: [],
reload: false,
});
const [paymentHistory, setPaymentHistory] = useState({
loading: true,
data: [],
});
const getWalletList = () => {
apiCall
.getUserWallets()
.then((res) => {
if (res.data.internal_return < 0) {
setWalletList({ loading: false, data: [] });
} else {
setWalletList({ loading: false, data: res.data?.result_list });
}
})
.catch(() => {
setWalletList({ loading: false, data: [] });
});
}
const getPaymentHistory = () => {
apiCall
.getPaymentHx()
@@ -53,24 +29,16 @@ const WalletRoutes = () => {
.catch(() => {
setPaymentHistory({ loading: false, data: [] });
});
}
};
useEffect(() => {
// const fetchData = async () => {
// await Promise.all([getWalletList(), getPaymentHistory()]);
// };
// if (walletList.loading) {
// fetchData();
// }
getWalletList()
getPaymentHistory()
getPaymentHistory();
}, [walletTable]);
return (
<Layout>
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
<WalletBox wallet={walletList} payment={paymentHistory} />
<WalletBox wallet={walletDetails} payment={paymentHistory} />
</Suspense>
</Layout>
);
+19 -16
View File
@@ -1,26 +1,29 @@
import LoadingSpinner from "../Spinners/LoadingSpinner";
import WalletItemCard from "./WalletItemCard";
/**
* Renders a list of wallet items or a loading spinner depending on the state of the `wallet` object.
*/
export default function WalletBox({ wallet, payment }) {
const { loading, data } = wallet;
return (
<>
<div className="my-wallet-wrapper w-full mb-10">
<div className="main-wrapper w-full">
<div className="balance-inquery w-full lg:grid grid-cols-[repeat(auto-fill,_minmax(325px,_1fr))] gap-5 mb-11 h-[22rem]">
{wallet.loading ? (
<div className="w-full h-full flex items-center justify-center">
<LoadingSpinner size="16" color="sky-blue" />
<div className="my-wallet-wrapper w-full mb-10">
<div className="main-wrapper w-full">
<div className="balance-inquery w-auto grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-[repeat(auto-fill,_minmax(354px,_1fr))] min-[1440px]:grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-auto">
{loading ? (
<div className="w-full h-full flex items-center justify-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
) : (
data.length > 0 && data.map((item) => (
<div key={item.wallet_uid} className="lg:w-full h-full mb-10 lg:mb-0">
<WalletItemCard walletItem={item} payment={payment} />
</div>
) : wallet.data.length ? (
wallet.data.map((item, index) => (
<div className="lg:w-full h-full mb-10 lg:mb-0">
<WalletItemCard walletItem={item} payment={payment} />
</div>
))
) : null}
</div>
))
)}
</div>
</div>
</>
</div>
);
}
+11 -8
View File
@@ -13,6 +13,12 @@ export default function WalletHeader(props) {
//props.myWalletList.result_list
let { pathname } = useLocation();
let navigate = useNavigate();
const onWalletClick = () => {
if (pathname == "/my-wallet")
props.setBalanceDropdown.toggle();
else navigate("/my-wallet", { replace: true });
}
return (
<>
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
@@ -41,14 +47,15 @@ export default function WalletHeader(props) {
<div className="content px-7 pb-7">
<ul>
{props.myWalletList &&
props.myWalletList?.result_list?.length > 0 &&
props.myWalletList.result_list.map((value, index) =>
props.myWalletList?.length > 0 &&
props.myWalletList.map((value, index) =>
{
let image = value.code ? `${value.code.toLocaleLowerCase()}.svg` : 'default.png'
return(
<li
key={index}
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
onClick={onWalletClick}
>
<div className="sm:flex justify-between items-center">
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
@@ -56,7 +63,7 @@ export default function WalletHeader(props) {
<img src={localImgLoad(`images/currency/${image}`)} className="w-14 h-14" alt="" />
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium">
<p className="text-2xl font-bold text-dark-gray dark:text-white">
{value.description}
</p>
</div>
@@ -178,11 +185,7 @@ export default function WalletHeader(props) {
</button> */}
<Link
to="/my-wallet"
onClick={() => {
if (pathname == "/my-wallet")
props.setBalanceDropdown.toggle();
else navigate("/my-wallet", { replace: true });
}}
onClick={onWalletClick}
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
+31 -24
View File
@@ -1,21 +1,25 @@
import React, { useState } from "react";
import { useSelector } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import background from "../../assets/images/bg-sky-blue.jpg"; //shape/balance-bg.svg";
import localImgLoad from "../../lib/localImgLoad";
import { tableReload } from "../../store/TableReloads";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import CreditPopup from "./Popup/CreditPopup";
import WalletAction from "./WalletAction";
/**
* Renders a card displaying information about a wallet item.
*/
export default function WalletItemCard({ walletItem, payment }) {
// const [eth] = useState(90);
// const [btc] = useState(85);
// const [ltc] = useState(20);
const { userDetails } = useSelector((state) => state?.userDetails);
let accountType = userDetails?.account_type == "FAMILY";
// Credit popup
const { userDetails } = useSelector((state) => state.userDetails);
const accountType = userDetails?.account_type === "FAMILY";
const dispatch = useDispatch();
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
/**
* Opens the credit popup.
* @param {Object} value - The value object.
*/
const openPopUp = (value) => {
setCreditPopup({
show: true,
@@ -23,37 +27,40 @@ export default function WalletItemCard({ walletItem, payment }) {
});
};
/**
* Closes the credit popup and dispatches a table reload action.
*/
const closePopUp = () => {
setCreditPopup({ show: false, data: {} });
dispatch(tableReload({ type: "WALLETTABLE" }));
};
let image = walletItem.code
? `${walletItem.code.toLocaleLowerCase()}.svg`
: "default.png"; // HOLDS THE VALUE NAME PROPERTY FOR IMAGE ICON
const image = walletItem.code
? `${walletItem.code.toLowerCase()}.svg`
: "default.png";
return (
<>
<div
className={`current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 px-8 pt-9 pb-20`}
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between"
style={{
background: `url(${background}) 0% 0% / cover no-repeat`,
}}
>
{/* <div className="w-[350px]"> */}
<div className="wallet w-full flex justify-between items-start gap-3">
<div className="min-w-[100px] min-h-[100px] max-w-[100px] max-h-[100px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
<div className="min-w-[100px] min-h-[100px] max-w-min md:max-w-[150px] max-h-min md:max-h-[150px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
<img
src={localImgLoad(`images/currency/${image}`)}
className="w-full h-full"
alt="curreny-icon"
alt="currency-icon"
/>
</div>
<div className="balance w-full mt-2 flex justify-center">
<div className="">
<p className="text-lg text-white opacity-[70%] tracking-wide mb-6">
<p className="text-base sm:text-lg text-white opacity-[70%] tracking-wide mb-2 sm:mb-6">
Current Balance
</p>
<p className="text-[44px] font-bold text-white tracking-wide leading-10 mb-2">
<p className="text-[44px] lg:text-[62px] font-bold text-white tracking-wide leading-10 xxs:scale-100 lg:scale-100 xl:scale-125">
{PriceFormatter(
walletItem.amount * 0.01,
walletItem.code,
@@ -65,9 +72,9 @@ export default function WalletItemCard({ walletItem, payment }) {
</div>
</div>
<p className="my-5 text-lg text-white tracking-wide flex justify-center items-center gap-2">
<p className="text-lg text-white tracking-wide flex justify-center items-center gap-8">
HOLDINGS :{" "}
<span className="mt-1">
<span className="xxs:scale-100 lg:scale-100 xl:scale-125">
{PriceFormatter(
walletItem.escrow * 0.01,
walletItem.code,
@@ -76,18 +83,18 @@ export default function WalletItemCard({ walletItem, payment }) {
)}
</span>
</p>
{/* for white underline */}
<div className="my-2 w-full h-[1px] bg-white"></div>
{!accountType ? (
{!accountType && (
<WalletAction
walletItem={walletItem}
payment={payment}
openPopUp={openPopUp}
/>
) : null}
{/* </div> */}
)}
</div>
{creditPopup.show && (
<CreditPopup
details={creditPopup.data}
+50 -65
View File
@@ -4,7 +4,7 @@ import bank1 from "../../assets/images/bank-1.png";
import bank2 from "../../assets/images/bank-2.png";
import bank3 from "../../assets/images/bank-3.png";
import bank4 from "../../assets/images/bank-4.png";
import profileImg from "../../assets/images/profile-pic.jpg";
import profileImg from "../../assets/images/profile.jpg";
import useToggle from "../../hooks/useToggle";
import usersService from "../../services/UsersService";
import DarkModeContext from "../Contexts/DarkModeContext";
@@ -15,10 +15,11 @@ import WalletHeader from "../MyWallet/WalletHeader";
import { useDispatch, useSelector } from "react-redux";
import Flag from "../../assets/images/united-states.svg";
import siteLogo from "../../assets/images/wrenchboard-logo-text.png";
import formattedDate from "../../lib/fomattedDate";
import { updateNotifications } from "../../store/notifications";
// import { updateWalletDetails } from "../../store/walletDetails";
import TimeDifference from "../Helpers/TimeDifference";
const DEFAULT_PROFILE_IMAGE = require("../../assets/images/profile.jpg");
export default function Header({ logoutModalHandler, sidebarHandler }) {
const [balanceDropdown, setbalanceValue] = useToggle(false);
const [notificationDropdown, setNotificationValue] = useToggle(false);
@@ -30,22 +31,10 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
const [myWalletList, setMyWalletList] = useState([]);
const api = useMemo(() => new usersService(), []);
const dispatch = useDispatch();
const navigate = useNavigate()
const navigate = useNavigate();
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
const getMyWalletList = async () => {
try {
const res = await api.getUserWallets(null);
console.log("wallet - > ", res.data);
setMyWalletList(res.data);
} catch (error) {
console.log("Error getting mode");
}
};
useEffect(() => {
getMyWalletList();
}, [walletTable]);
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
const handlerBalance = () => {
setbalanceValue.toggle();
@@ -100,10 +89,9 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
};
// User Profile
let { firstname, lastname, email, profile_pic } = userDetails;
let { firstname, lastname, email, profile_pic_url } = userDetails;
let userEmail = email?.split("@")[0];
// console.log("Notify: ", notifications?.data?.raw);
const userProfileImage = profile_pic_url || DEFAULT_PROFILE_IMAGE;
return (
<>
@@ -241,7 +229,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
{/*<div className="lg:hidden block"></div>*/}
<WalletHeader
myWalletList={myWalletList}
myWalletList={walletDetails.data}
handlerBalance={handlerBalance}
balanceDropdown={balanceDropdown}
addMoneyHandler={addMoneyHandler}
@@ -255,9 +243,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
>
<Icons name="notification" />
<span className="absolute right-2 top-2 z-10 text-xs lg:w-5 lg:h-5 w-4 h-4 flex justify-center items-center rounded-full primary-gradient text-white cursor-default">
{notifications?.loading
? "●"
: notifications?.data?.length}
{notifications?.loading ? "●" : notifications?.data?.length}
</span>
</div>
<div
@@ -273,46 +259,45 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
<div className="content px-7 pb-7">
<ul>
{notifications?.data?.length && notifications?.data?.map((item, idx) =>
{
if(idx < 5){
return (
<li
className={`content-item ${
idx == 4
? "py-5 "
: "py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
}`}
key={idx}
>
<div className="notifications flex space-x-4 items-center">
<div className="icon max-w-[52px] max-h-[52px] w-full h-full rounded-full object-cover">
<img
src={require(`../../assets/images/notifications/${item?.icon}`)}
alt="icon"
className="w-full h-full"
/>
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium mb-2">
{item?.title}
{/* <span className="ml-1 font-bold">
{notifications?.data?.length &&
notifications?.data?.map((item, idx) => {
if (idx < 5) {
return (
<li
className={`content-item ${
idx == 4
? "py-5 "
: "py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
}`}
key={idx}
>
<div className="notifications flex space-x-4 items-center">
<div className="icon max-w-[52px] max-h-[52px] w-full h-full rounded-full object-cover">
<img
src={require(`../../assets/images/notifications/${item?.icon}`)}
alt="icon"
className="w-full h-full"
/>
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium mb-2">
{item?.title}
{/* <span className="ml-1 font-bold">
successfully done
</span> */}
</p>
<p className="text-sm text-thin-light-gray font-medium">
<TimeDifference
time={item?.date}
key={item?.uid}
/>
</p>
</div>
</div>
</li>
)
}
})
}
</p>
<p className="text-sm text-thin-light-gray font-medium">
<TimeDifference
time={item?.date}
key={item?.uid}
/>
</p>
</div>
</div>
</li>
);
}
})}
</ul>
<div className="add-money-btn flex justify-center items-center">
@@ -351,9 +336,9 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
{/* profile-image */}
<div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden">
<img
src={profile_pic != "" ? profile_pic : profileImg}
src={userProfileImage}
alt="profile"
className="w-full h-full"
className="w-full h-full object-cover"
/>
</div>
<div className="lg:block hidden">
@@ -375,7 +360,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
<img
src={profileImg}
alt="profile"
className="w-full h-full"
className="w-full h-full object-cover object-center"
/>
</div>
</div>
+22 -91
View File
@@ -55,59 +55,29 @@ export default function Layout({ children }) {
return (
<>
<div className="nft-main-wrapper-layout">
<div className="nft-wrapper-layout-container 2xl:pr-20 md:pr-10 pr-2 pl-2 md:pl-0 w-full min-h-screen flex">
<div className={`nft-wrapper-layout-container 2xl:pr-20 md:pr-10 pr-2 pl-2 md:pl-0 w-full min-h-screen flex`}>
{/* sidebar */}
<div
className={`nft-sidebar xl:block hidden section-shadow ${
drawer
? "2xl:w-[335px] w-[280px] 2xl:pl-20 pl-10 pr-6 "
: "w-[70px]"
} bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed left-0 top-0 pt-8`}
>
<Sidebar
logoutModalHandler={logoutModalHandler}
sidebar={drawer}
action={() => dispatch(drawerToggle())}
myJobList={userJobList}
/>
<div className={`nft-sidebar xl:block hidden section-shadow ${drawer ? "2xl:w-[335px] w-[280px] 2xl:pl-20 pl-10 pr-6 " : "w-[70px]"} bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed left-0 top-0 pt-[30px]`}>
<Sidebar logoutModalHandler={logoutModalHandler} sidebar={drawer} action={() => dispatch(drawerToggle())} myJobList={userJobList} />
</div>
{MobileSideBar && (
<div
onClick={() => setMobileSidebar.toggle()}
className="bg-black bg-opacity-20 fixed left-0 top-0 w-full h-full z-[50] block xl:hidden"
></div>
<div onClick={() => setMobileSidebar.toggle()} className="bg-black bg-opacity-20 fixed left-0 top-0 w-full h-full z-[50] block xl:hidden"></div>
)}
<div
className={`nft-sidebar block xl:hidden section-shadow w-[280px] pl-3 bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed z-[60] top-0 pt-8 ${
MobileSideBar ? "left-0" : "-left-[290px]"
}`}
>
<MobileSidebar
logoutModalHandler={logoutModalHandler}
sidebar={MobileSideBar}
action={() => setMobileSidebar.toggle()}
myJobList={userJobList}
/>
<div className={`nft-sidebar block xl:hidden section-shadow w-[280px] pl-3 bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed z-[60] top-0 pt-8 ${MobileSideBar ? "left-0" : "-left-[290px]"}`}>
<MobileSidebar logoutModalHandler={logoutModalHandler} sidebar={MobileSideBar} action={() => setMobileSidebar.toggle()} myJobList={userJobList} />
</div>
{/* end sidebar */}
<div
className={`nft-header-container-wrapper flex-1 md:ml-10 ${
drawer ? "2xl:ml-[375px] xl:ml-[310px]" : "xl:ml-[110px]"
} h-full`}
>
<div className={`nft-header-container-wrapper flex-1 md:ml-10 ${drawer ? "2xl:ml-[375px] xl:ml-[310px]" : "xl:ml-[110px]"} h-full`}>
{/* header */}
<div className="nft-header w-full lg:h-[100px] h-[70px] default-border-bottom dark:border-[#292967] z-40 xl:sticky fixed top-0 left-0 ">
<Header
sidebarHandler={() => setMobileSidebar.toggle()}
logoutModalHandler={logoutModalHandler}
/>
<div className="nft-header w-full lg:h-[100px] h-[70px] default-border-bottom dark:border-[#292967] z-40 xl:sticky fixed top-0 left-0 ">
<Header sidebarHandler={() => setMobileSidebar.toggle()} logoutModalHandler={logoutModalHandler} />
</div>
{/* container */}
<div className="nft-container 2xl:flex 2xl:space-x-8 h-full mb-12 lg:mt-[140px] mt-24 xl:mt-10">
<div className="nft-main-container flex-1">
<div className="nft-container 2xl:flex 2xl:space-x-8 h-full mb-12 lg:mt-[140px] mt-24 xl:mt-10 flex flex-col xl:flex-row items-start justify-center gap-4">
<div className="nft-main-container flex-[80%]">
{children && children}
</div>
<div className="nft-right-side-content 2xl:w-[270px] w-full h-full 2xl:flex justify-center relative">
<div className="nft-right-side-content 2xl:w-[270px] w-full h-full 2xl:flex justify-center relative flex-[20%]">
<RightSideBar />
</div>
</div>
@@ -121,50 +91,19 @@ export default function Layout({ children }) {
<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={logoutModalHandler}
>
<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"
/>
<button type="button" className="text-[#374557] dark:text-red-500" onClick={logoutModalHandler}>
<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="white" 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 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="#4687ba" />
<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">
@@ -173,18 +112,10 @@ export default function Layout({ children }) {
</p>
</div>
<div className="flex space-x-2.5">
<button
onClick={logOut}
type="button"
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
<button onClick={logOut} type="button" className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full">
{`Yes ${process.env.REACT_APP_LOGOUT_TEXT}`}
</button>
<button
onClick={logoutModalHandler}
type="button"
className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
<button onClick={logoutModalHandler} type="button" className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full">
<span className="text-gradient">Not Now</span>
</button>
</div>
+81 -29
View File
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import { NavLink } from "react-router-dom";
import { useSelector } from "react-redux";
import { NavLink } from "react-router-dom";
//import SideStatistics from "./SideStatistics";
export default function RightSideBar() {
@@ -35,8 +35,8 @@ export default function RightSideBar() {
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">
<div className="top-platform bg-white dark:bg-dark-white rounded-2xl p-8 2xl:w-[268px] w-full 2xl:mb-10 2xl:border-none border ">
<div className="right-sidebar-wrapper overflow-y-scroll overflow-style-none 2xl:fixed h-full 2xl:pb-96">
<div className="top-platform bg-white dark:bg-dark-white rounded-2xl p-8 2xl:w-[268px] w-full 2xl:mb-10 2xl:border-none border ">
{/* heading */}
<div className="heading flex justify-between items-center mb-3.5">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
@@ -47,31 +47,62 @@ export default function RightSideBar() {
<div className="platform-list">
{userDetails && userDetails?.account_type !== "FAMILY" && (
<>
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="history">
<g data-name="14"><circle cx="9" cy="14" r="7" fill="#ffd54f"></circle>
<path fill="#ef6c00" d="M21 9H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zM21 5H3A1 1 0 0 1 3 3H21a1 1 0 0 1 0 2zM21 13H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 17H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 21H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"></path><path fill="#ff8f00" d="M10,10a1,1,0,0,0-2,0v3.59L6.29,15.29a1,1,0,1,0,1.41,1.41l2-2A1,1,0,0,0,10,14Z">
</path>
</g>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/history">History</NavLink>
</p>
</div>
{/* action */}
</div>
<>
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
id="history"
>
<g data-name="14">
<circle cx="9" cy="14" r="7" fill="#ffd54f"></circle>
<path
fill="#ef6c00"
d="M21 9H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zM21 5H3A1 1 0 0 1 3 3H21a1 1 0 0 1 0 2zM21 13H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 17H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 21H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"
></path>
<path
fill="#ff8f00"
d="M10,10a1,1,0,0,0-2,0v3.59L6.29,15.29a1,1,0,1,0,1.41,1.41l2-2A1,1,0,0,0,10,14Z"
></path>
</g>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/history">History</NavLink>
</p>
</div>
{/* action */}
</div>
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="add-user">
<path fill="#9bcb5b" d="M12 13.4c-2 0-3.7-1.6-3.7-3.6s1.6-3.7 3.6-3.7 3.7 1.6 3.7 3.6-1.6 3.6-3.6 3.7zm0-6.2c-1.4 0-2.6 1.1-2.6 2.6 0 1.4 1.1 2.6 2.6 2.6s2.6-1.1 2.6-2.6c-.1-1.5-1.2-2.6-2.6-2.6z"></path><path fill="#9bcb5b" d="M16.6 17.9c-.3 0-.5-.2-.6-.5 0-2.2-1.8-4-4-4s-4 1.8-4 4c0 .3-.3.5-.6.5-.2 0-.4-.2-.5-.5 0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1c0 .3-.2.5-.5.5z"></path><path fill="#0376bc" d="M12 23.7C5.5 23.7.3 18.4.3 12 .3 5.5 5.6.3 12 .3c2.6 0 5.1.9 7.2 2.5.2.2.2.6 0 .8-.2.2-.4.2-.7.1-1.9-1.4-4.1-2.2-6.5-2.2C6.2 1.4 1.4 6.2 1.4 12S6.2 22.6 12 22.6 22.6 17.8 22.6 12c0-2.4-.8-4.6-2.2-6.5-.2-.3-.1-.6.2-.8.2-.1.5-.1.7.1 1.6 2 2.5 4.6 2.4 7.2 0 6.4-5.3 11.7-11.7 11.7z"></path><circle cx="20.2" cy="20.3" r="2.4" fill="#fff"></circle><path fill="#9bcb5b" d="M18 18.1c.6-.6 1.4-.9 2.2-.9.8 0 1.6.3 2.2.9s1 1.4.9 2.2c0 .8-.3 1.6-.9 2.2s-1.4 1-2.2.9c-.8 0-1.6-.3-2.2-.9s-1-1.4-.9-2.2c-.1-.8.3-1.7.9-2.2zm3.8 2.5V20h-1.3v-1.3h-.6V20h-1.3v.6h1.3v1.3h.6v-1.3h1.3z"></path>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
id="add-user"
>
<path
fill="#9bcb5b"
d="M12 13.4c-2 0-3.7-1.6-3.7-3.6s1.6-3.7 3.6-3.7 3.7 1.6 3.7 3.6-1.6 3.6-3.6 3.7zm0-6.2c-1.4 0-2.6 1.1-2.6 2.6 0 1.4 1.1 2.6 2.6 2.6s2.6-1.1 2.6-2.6c-.1-1.5-1.2-2.6-2.6-2.6z"
></path>
<path
fill="#9bcb5b"
d="M16.6 17.9c-.3 0-.5-.2-.6-.5 0-2.2-1.8-4-4-4s-4 1.8-4 4c0 .3-.3.5-.6.5-.2 0-.4-.2-.5-.5 0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1c0 .3-.2.5-.5.5z"
></path>
<path
fill="#0376bc"
d="M12 23.7C5.5 23.7.3 18.4.3 12 .3 5.5 5.6.3 12 .3c2.6 0 5.1.9 7.2 2.5.2.2.2.6 0 .8-.2.2-.4.2-.7.1-1.9-1.4-4.1-2.2-6.5-2.2C6.2 1.4 1.4 6.2 1.4 12S6.2 22.6 12 22.6 22.6 17.8 22.6 12c0-2.4-.8-4.6-2.2-6.5-.2-.3-.1-.6.2-.8.2-.1.5-.1.7.1 1.6 2 2.5 4.6 2.4 7.2 0 6.4-5.3 11.7-11.7 11.7z"
></path>
<circle cx="20.2" cy="20.3" r="2.4" fill="#fff"></circle>
<path
fill="#9bcb5b"
d="M18 18.1c.6-.6 1.4-.9 2.2-.9.8 0 1.6.3 2.2.9s1 1.4.9 2.2c0 .8-.3 1.6-.9 2.2s-1.4 1-2.2.9c-.8 0-1.6-.3-2.2-.9s-1-1.4-.9-2.2c-.1-.8.3-1.7.9-2.2zm3.8 2.5V20h-1.3v-1.3h-.6V20h-1.3v.6h1.3v1.3h.6v-1.3h1.3z"
></path>
</svg>
</div>
{/* name */}
@@ -81,16 +112,38 @@ export default function RightSideBar() {
</p>
</div>
</div>
</>
)}
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" id="InternationalUser">
<path fill="#e6e7f9" d="M38.5 31.1c2.1-1.1 3.9-2.5 5.4-4.4h-3.2c-.6 1.6-1.3 3.1-2.2 4.4zm-5.8 1.4c2-.7 3.7-2.8 4.9-5.8h-4.9v5.8zm8.8-8.6h4.2c.9-1.8 1.5-3.7 1.7-5.8h-5.1c-.1 2-.4 4-.8 5.8zm2.4-17.3c-1.5-1.8-3.3-3.3-5.4-4.4.8 1.2 1.6 2.7 2.2 4.4h3.2zm-5.3 2.9h-5.9v5.8h6.7c-.1-2.1-.4-4.1-.8-5.8zm3.7 5.8h5.1c-.2-2.1-.8-4-1.7-5.8h-4.2c.4 1.8.7 3.7.8 5.8zM32.7.8v5.8h4.9c-1.2-2.9-2.9-5.1-4.9-5.8zm6.7 17.3h-6.7v5.8h5.9c.4-1.8.7-3.8.8-5.8zM25 6.6h4.9V.8c-2 .7-3.7 2.9-4.9 5.8zm-1.8 8.7h6.7V9.5H24c-.4 1.7-.7 3.7-.8 5.8zm6.7 17.2v-5.8H25c1.2 3 2.9 5.1 4.9 5.8zM24.1 2.3c-2.1 1.1-3.9 2.5-5.4 4.4H22c.5-1.7 1.3-3.2 2.1-4.4zM24 23.9h5.9v-5.8h-6.7c.1 2 .4 4 .8 5.8z" className="colorc1e5ff svgShape"></path><path fill="#ff6699" d="M3.7 44.7c0 1.6 1.2 2.8 2.8 2.8 1.3 0 2.4-.9 2.7-2.2.3 1.3 1.4 2.2 2.7 2.2 1.5 0 2.8-1.3 2.8-2.8V30.1h3.1V18.8c0-4.2-3.3-7.5-7.4-7.5H8c-4.1 0-7.4 3.4-7.4 7.5v11.3h3.1v14.6z" className="colorff99b0 svgShape"></path><path fill="#998da0" d="M9.2 10.3c2.4 0 4.4-2.2 4.4-4.9S11.6.5 9.2.5C6.8.5 4.8 2.7 4.8 5.4s2 4.9 4.4 4.9z" className="colorffd499 svgShape"></path><path fill="#e6e7f9" d="M16.9 9.5c-.3.6-.5 1.2-.8 1.8 1.3 1 2.3 2.4 2.9 4h1.3c.1-2 .3-4 .8-5.8h-4.2zm2.9 9.3v5.1h1.4c-.4-1.8-.7-3.8-.8-5.8h-.6c-.1.2 0 .4 0 .7zm2.2 7.9h-2.2v1.2c1.3 1.3 2.7 2.4 4.4 3.2-.9-1.3-1.7-2.8-2.2-4.4z" className="colorc1e5ff svgShape"></path>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 48 48"
id="InternationalUser"
>
<path
fill="#e6e7f9"
d="M38.5 31.1c2.1-1.1 3.9-2.5 5.4-4.4h-3.2c-.6 1.6-1.3 3.1-2.2 4.4zm-5.8 1.4c2-.7 3.7-2.8 4.9-5.8h-4.9v5.8zm8.8-8.6h4.2c.9-1.8 1.5-3.7 1.7-5.8h-5.1c-.1 2-.4 4-.8 5.8zm2.4-17.3c-1.5-1.8-3.3-3.3-5.4-4.4.8 1.2 1.6 2.7 2.2 4.4h3.2zm-5.3 2.9h-5.9v5.8h6.7c-.1-2.1-.4-4.1-.8-5.8zm3.7 5.8h5.1c-.2-2.1-.8-4-1.7-5.8h-4.2c.4 1.8.7 3.7.8 5.8zM32.7.8v5.8h4.9c-1.2-2.9-2.9-5.1-4.9-5.8zm6.7 17.3h-6.7v5.8h5.9c.4-1.8.7-3.8.8-5.8zM25 6.6h4.9V.8c-2 .7-3.7 2.9-4.9 5.8zm-1.8 8.7h6.7V9.5H24c-.4 1.7-.7 3.7-.8 5.8zm6.7 17.2v-5.8H25c1.2 3 2.9 5.1 4.9 5.8zM24.1 2.3c-2.1 1.1-3.9 2.5-5.4 4.4H22c.5-1.7 1.3-3.2 2.1-4.4zM24 23.9h5.9v-5.8h-6.7c.1 2 .4 4 .8 5.8z"
className="colorc1e5ff svgShape"
></path>
<path
fill="#ff6699"
d="M3.7 44.7c0 1.6 1.2 2.8 2.8 2.8 1.3 0 2.4-.9 2.7-2.2.3 1.3 1.4 2.2 2.7 2.2 1.5 0 2.8-1.3 2.8-2.8V30.1h3.1V18.8c0-4.2-3.3-7.5-7.4-7.5H8c-4.1 0-7.4 3.4-7.4 7.5v11.3h3.1v14.6z"
className="colorff99b0 svgShape"
></path>
<path
fill="#998da0"
d="M9.2 10.3c2.4 0 4.4-2.2 4.4-4.9S11.6.5 9.2.5C6.8.5 4.8 2.7 4.8 5.4s2 4.9 4.4 4.9z"
className="colorffd499 svgShape"
></path>
<path
fill="#e6e7f9"
d="M16.9 9.5c-.3.6-.5 1.2-.8 1.8 1.3 1 2.3 2.4 2.9 4h1.3c.1-2 .3-4 .8-5.8h-4.2zm2.9 9.3v5.1h1.4c-.4-1.8-.7-3.8-.8-5.8h-.6c-.1.2 0 .4 0 .7zm2.2 7.9h-2.2v1.2c1.3 1.3 2.7 2.4 4.4 3.2-.9-1.3-1.7-2.8-2.2-4.4z"
className="colorc1e5ff svgShape"
></path>
</svg>
</div>
{/* name */}
<div>
@@ -99,7 +152,6 @@ export default function RightSideBar() {
</p>
</div>
</div>
</div>
</div>
{/*<SideStatistics />*/}
+1 -1
View File
@@ -39,7 +39,7 @@ export default function Sidebar({
{/* logo-area */}
<div
className={`w-full flex items-center transition-all duration-300 ease-in-out ${
sidebar ? "justify-between mb-14" : "justify-center"
sidebar ? "justify-start gap-3 mb-14" : "justify-center"
}`}
>
<div className={`sidebar-logo ${sidebar ? "enter" : ""}`}>
+98 -52
View File
@@ -1,37 +1,84 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import React, { useEffect, useState } from "react";
// import authProfilePic from "../../assets/images/auth-profile-picture.png";
// import profileBanner from "../../assets/images/profile-cover.png";
// import collections from "../../data/collectionplan_data.json"; Should this be cleaned off?
// import marketPlace from "../../data/marketplace_data.json";
import { useSelector } from "react-redux";
import LoadingSpinner from "../../components/Spinners/LoadingSpinner";
import products from "../../data/product_data.json";
import usersService from "../../services/UsersService";
import Layout from "../Partials/Layout";
import {
ActivitiesTab, BlogTab,
QuestionsTab,
ActivitiesTab,
BlogTab,
CollectionTab,
CreatedTab,
HiddenProductsTab,
OnSaleTab,
MyUploadedFiles,
OwnTab,
QuestionsTab,
} from "./tabs";
//import MyUploadedFiles from "./tabs/MyUploadedFiles";
export default function Resources(props) {
// console.log("RESOURCES=>", props);
const ownProducts = products.datas;
// Resource Props
const __resources = props.MyResourceData;
//debugger;
//debugger;
// Collection Items
const CreatedSell = __resources?.marketdata?.data;
const tab_categories = __resources?.tab_categories?.data;
const collectionProducts = __resources?.collectiondata?.data;
const onSaleProducts = __resources?.marketdata?.data;
const CreatedBits = __resources?.productdata?.datas;
const blogItems = __resources?.blogdata?.payload;
const blogItems = __resources?.blogdata?.payload;
const [tab, setTab] = useState(tab_categories ? tab_categories[0]?.name : "");
// My Items Data
const [uploadedFiles, setUploadedFiles] = useState({
loading: false,
msg: "",
data: null,
});
const { uploadsTable } = useSelector((state) => state.tableReload);
const apiCall = new usersService();
const getUploadedFiles = async () => {
setUploadedFiles((prev) => ({ ...prev, loading: true }));
let res;
try {
res = await apiCall.getUploadedList();
res = res.data;
if (res?.internal_return < 0) {
setUploadedFiles((prev) => ({
...prev,
loading: false,
msg: "something went wrong",
}));
}
setUploadedFiles((prev) => ({
...prev,
loading: false,
msg: "success",
data: res?.result_list,
}));
} catch (error) {
setUploadedFiles((prev) => ({
...prev,
loading: false,
msg: "An error occurred",
}));
}
};
useEffect(() => {
getUploadedFiles();
}, [uploadsTable]);
// const [tab, setTab] = useState(tab_categories ? tab_categories[0]?.name : "");
const [tab, setTab] = useState(props.activeTab? props.activeTab : tab_categories ? tab_categories[0]?.name : "");
const tabHandler = (value) => {
setTab(value);
@@ -42,9 +89,7 @@ export default function Resources(props) {
blog: <BlogTab blogdata={blogItems} />,
onsale: <QuestionsTab products={onSaleProducts} />,
owned: <OwnTab products={ownProducts} />,
created: (
<CreatedTab marketProducts={CreatedSell} mainProducts={CreatedBits} />
),
created: <MyUploadedFiles uploadedFiles={uploadedFiles} />,
hidden: (
<HiddenProductsTab
marketProducts={CreatedSell}
@@ -55,26 +100,30 @@ export default function Resources(props) {
activity: <ActivitiesTab />,
};
const defaultTabComponent = <BlogTab blogdata={blogItems} />;
// const defaultTabComponent = <BlogTab blogdata={blogItems} />;
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
// const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
const defaultTabComponent = props.activeTab ? tabComponents[props.activeTab] : <BlogTab blogdata={blogItems} />;
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
// Tab Item Component
const TabItem = ({ tabValue, isActive }) => {
let countNumber = (name) => { // FUNCTION TO DETERMINE THE COUNT NUMBER
if(name == 'blog'){
return blogItems?.blogdata?.length
}else if(name == 'onsale'){
return onSaleProducts?.length
let countNumber = (name) => {
// FUNCTION TO DETERMINE THE COUNT NUMBER
if (name == "blog") {
return blogItems?.blogdata?.length;
} else if (name == "onsale") {
return onSaleProducts?.length;
// return null
}else if(name == 'owned'){
return ownProducts?.length
}else if(name == 'created'){
return CreatedSell?.length + CreatedBits?.length
}else{
return 0
} else if (name == "owned") {
return ownProducts?.length;
} else if (name == "created") {
return uploadedFiles?.data?.length;
} else {
return 0;
}
}
};
return (
<li
className={`relative group inline`}
@@ -89,17 +138,17 @@ export default function Resources(props) {
>
{tabValue.content}
</span>
{tabValue.name != 'onsale' &&
<span
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
isActive
? "text-white bg-pink"
: "text-thin-light-gray bg-[#F2B8FD]"
}`}
>
{countNumber(tabValue.name)}
</span>
}
{tabValue.name != "onsale" && (
<span
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
isActive
? "text-white bg-pink"
: "text-thin-light-gray bg-[#F2B8FD]"
}`}
>
{countNumber(tabValue.name)}
</span>
)}
</li>
);
};
@@ -109,13 +158,18 @@ export default function Resources(props) {
return (
<ul className="lg:flex lg:space-x-14 space-x-8">
{tabCategories?.length > 0 &&
tabCategories?.map((tabValue, idx) => (
<TabItem
key={tabValue.id}
tabValue={tabValue}
isActive={tab === tabValue.name || (idx === 0 && tab === "")}
/>
))}
tabCategories?.map((tabValue, idx) => {
if(tabValue.enabled){
return (
<TabItem
key={tabValue.id}
tabValue={tabValue}
isActive={tab === tabValue.name || (idx === 0 && tab === "")}
/>
)
}
}
)}
</ul>
);
};
@@ -136,14 +190,6 @@ export default function Resources(props) {
<div className="tab-items">
<TabList tabCategories={tab_categories} />
</div>
<div style={{ transform: "translateY(-22px)" }}>
<Link
to="/upload-product"
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
>
Add My Item
</Link>
</div>
</div>
<div className="hidden lg:block w-full h-[1px] bg-[#DCD5FE] dark:bg-[#5356fb29] absolute top-[42px] left-0"></div>
</div>
+27 -27
View File
@@ -18,36 +18,36 @@ export default function CreatedTab({
</div>
{/* filer-dropdown */}
<div className="flex-1 flex sm:justify-end">
<div className="flex space-x-1 items-center">
<span className="text-18 text-thin-light-gray">
Recently Received
</span>
<span>
<svg
width="20"
height="10"
viewBox="0 0 13 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
opacity="0.7"
d="M12.4124 0.247421C12.3327 0.169022 12.2379 0.106794 12.1335 0.0643287C12.0291 0.0218632 11.917 0 11.8039 0C11.6908 0 11.5787 0.0218632 11.4743 0.0643287C11.3699 0.106794 11.2751 0.169022 11.1954 0.247421L7.27012 4.07837C7.19045 4.15677 7.09566 4.219 6.99122 4.26146C6.88678 4.30393 6.77476 4.32579 6.66162 4.32579C6.54848 4.32579 6.43646 4.30393 6.33202 4.26146C6.22758 4.219 6.13279 4.15677 6.05312 4.07837L2.12785 0.247421C2.04818 0.169022 1.95338 0.106794 1.84895 0.0643287C1.74451 0.0218632 1.63249 0 1.51935 0C1.40621 0 1.29419 0.0218632 1.18975 0.0643287C1.08531 0.106794 0.990517 0.169022 0.910844 0.247421C0.751218 0.404141 0.661621 0.616141 0.661621 0.837119C0.661621 1.0581 0.751218 1.2701 0.910844 1.42682L4.84468 5.26613C5.32677 5.73605 5.98027 6 6.66162 6C7.34297 6 7.99647 5.73605 8.47856 5.26613L12.4124 1.42682C12.572 1.2701 12.6616 1.0581 12.6616 0.837119C12.6616 0.616141 12.572 0.404141 12.4124 0.247421Z"
fill="#374557"
fillOpacity="0.6"
/>
</svg>
</span>
</div>
{/*<div className="flex space-x-1 items-center">*/}
{/* <span className="text-18 text-thin-light-gray">*/}
{/* Recently Received*/}
{/* </span>*/}
{/* <span>*/}
{/* <svg*/}
{/* width="20"*/}
{/* height="10"*/}
{/* viewBox="0 0 13 6"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <path*/}
{/* opacity="0.7"*/}
{/* d="M12.4124 0.247421C12.3327 0.169022 12.2379 0.106794 12.1335 0.0643287C12.0291 0.0218632 11.917 0 11.8039 0C11.6908 0 11.5787 0.0218632 11.4743 0.0643287C11.3699 0.106794 11.2751 0.169022 11.1954 0.247421L7.27012 4.07837C7.19045 4.15677 7.09566 4.219 6.99122 4.26146C6.88678 4.30393 6.77476 4.32579 6.66162 4.32579C6.54848 4.32579 6.43646 4.30393 6.33202 4.26146C6.22758 4.219 6.13279 4.15677 6.05312 4.07837L2.12785 0.247421C2.04818 0.169022 1.95338 0.106794 1.84895 0.0643287C1.74451 0.0218632 1.63249 0 1.51935 0C1.40621 0 1.29419 0.0218632 1.18975 0.0643287C1.08531 0.106794 0.990517 0.169022 0.910844 0.247421C0.751218 0.404141 0.661621 0.616141 0.661621 0.837119C0.661621 1.0581 0.751218 1.2701 0.910844 1.42682L4.84468 5.26613C5.32677 5.73605 5.98027 6 6.66162 6C7.34297 6 7.99647 5.73605 8.47856 5.26613L12.4124 1.42682C12.572 1.2701 12.6616 1.0581 12.6616 0.837119C12.6616 0.616141 12.572 0.404141 12.4124 0.247421Z"*/}
{/* fill="#374557"*/}
{/* fillOpacity="0.6"*/}
{/* />*/}
{/* </svg>*/}
{/* </span>*/}
{/*</div>*/}
</div>
</div>
<div className="content-section w-full">
<div className="marketplace-products-widgets mb-16">
<CreateSaleSlider products={marketProducts} />
</div>
<div className="main-products-widgets">
<CreatedBidsSlider products={mainProducts} />
</div>
{/*<div className="marketplace-products-widgets mb-16">*/}
{/* <CreateSaleSlider products={marketProducts} />*/}
{/*</div>*/}
{/*<div className="main-products-widgets">*/}
{/* <CreatedBidsSlider products={mainProducts} />*/}
{/*</div>*/}
</div>
</div>
</div>
@@ -0,0 +1,162 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import defaultImg from "../../../assets/images/myfiles/default.svg";
import localImgLoad from "../../../lib/localImgLoad";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
export default function MyUploadedFiles({ uploadedFiles }) {
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentFiles = uploadedFiles?.data?.slice(
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
return (
<>
<div className="mb-4 w-full flex justify-end item-center">
<Link
to="/my-uploads"
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
>
Add My Item
</Link>
</div>
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow relative min-h-[520px]`}
>
<div className="header w-full sm:flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center mb-2 sm:mb-0">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
My Uploads
</h1>
</div>
</div>
<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>
<>
{uploadedFiles?.data && uploadedFiles?.data.length ? (
currentFiles.map((value, idx) => {
let addedDate = value?.added?.split(" ")[0];
let formattedSize = formatFileSize(value?.file_size);
return (
<tr
key={value?.file_uid}
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 w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={
localImgLoad(
`images/myfiles/${value.banner}`
) || defaultImg
}
alt="data"
className="w-full h-full rounded-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title || "Dummy Text"}
</h1>
<div>
{value.description || "Dummy Description"}
</div>
<span className="text-sm text-thin-light-gray flex flext-start gap-1">
Added:{" "}
<span className="text-purple">{addedDate}</span>
</span>
<div className="flex gap-4 items-center">
<span className="text-sm text-thin-light-gray">
File Name:{" "}
<span className="text-purple">
{" "}
{value.file_name}
</span>
</span>
<span className="text-sm text-thin-light-gray">
File Size:{" "}
<span className="text-purple">
{" "}
{formattedSize}
</span>
</span>
<span className="text-sm text-thin-light-gray">
File Type:{" "}
<span className="text-purple">
{" "}
{value?.file_type}
</span>
</span>
</div>
</div>
</div>
</td>
<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, pathname },
// });
// }}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</div>
</td>
</tr>
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2" colSpan={3}>
No Files Currently!
</td>
</tr>
)}
</>
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
uploadedFiles?.data.length
? true
: false
}
data={uploadedFiles?.data}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
</div>
</>
);
}
const formatFileSize = (sizeInBytes) => {
if (sizeInBytes < 1024) {
return `${sizeInBytes} bytes`;
} else if (sizeInBytes < 1024 * 1024) {
const sizeInKB = (sizeInBytes / 1024).toFixed(2);
return `${sizeInKB} KB`;
} else {
const sizeInMB = (sizeInBytes / (1024 * 1024)).toFixed(2);
return `${sizeInMB} MB`;
}
};
+2
View File
@@ -6,6 +6,7 @@ import OnSaleTab from "./OnSaleTab";
import OwnTab from "./OwnTab";
import BlogTab from "./BlogTab";
import QuestionsTab from "./QuestionsTab";
import MyUploadedFiles from "./MyUploadedFiles";
export {
BlogTab,
@@ -16,4 +17,5 @@ export {
HiddenProductsTab,
OnSaleTab,
OwnTab,
MyUploadedFiles,
};
@@ -69,7 +69,7 @@ function DeleteCardPopout({action, situation, data, setReloadCardList}) {
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="68" cy="68" r="68" fill="#5356FB" />
<circle cx="68" cy="68" r="68" fill="#4687ba" />
<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"
@@ -1,13 +1,11 @@
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Link, useNavigate } from "react-router-dom";
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 { Form, Formik } from "formik";
import * as Yup from "yup";
@@ -60,14 +58,17 @@ export default function PersonalInfoTab({
let navigate = useNavigate();
let [togglePromotion, setTogglePromotion] = useState(false);
const initialValues = {
firstname: userDetails?.firstname,
lastname: userDetails?.lastname,
state: userDetails?.state,
city: userDetails?.city,
email: userDetails?.email,
profile: userDetails?.profile_pic,
pref_email: 0,
pref_phone: 0,
accept_promo: false,
online_name: "",
};
let [profile, setProfile] = useState({
@@ -86,8 +87,17 @@ export default function PersonalInfoTab({
const handleUpdateUser = (values, helpers) => {
setRequestState({ message: "", loading: true, status: false });
// there is no profile accommodation on the payload
delete values?.profile;
const reqData = {
...values,
pref_email: Number(values.pref_email?.toString()),
pref_phone: Number(values.pref_phone?.toString()),
};
apiCall
.updateProfile(values)
.updateProfile(reqData)
.then((res) => {
// API CALL TO UPDATE USER DETAILS
if (res.data.internal_return < 0) {
@@ -98,10 +108,14 @@ export default function PersonalInfoTab({
});
return;
}
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
toast.success("Update Successful");
setRequestState({
message: "Profile update successfully",
loading: false,
status: true,
});
// toast.success("Update Successful");
setTimeout(() => {
// navigate("/", { replace: true });
navigate("/", { replace: true });
window.location.reload(true);
}, 1000);
})
@@ -144,9 +158,9 @@ export default function PersonalInfoTab({
fieldClass="px-6"
label="User Name"
type="text"
name="username"
placeholder=""
value={userDetails.username}
name="online_name"
placeholder="Username"
value={userDetails?.username}
disable={true}
/>
</div>
@@ -206,6 +220,25 @@ export default function PersonalInfoTab({
)}
</div>
</div>
{/* Online Name */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Online Name (optional)"
type="text"
name="online_name"
placeholder=""
value={props.values.online_name}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.online_name &&
props.touched.online_name && (
<p className="text-sm text-red-500">
{props.errors.online_name}
</p>
)}
</div>
{/* Country */}
<div className="field w-full mb-6">
@@ -263,13 +296,17 @@ export default function PersonalInfoTab({
Pref. Communication
</label>
<div className="check-box">
<div className="flex items-center justify-start">
<div
role="group"
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=""
name="pref_email"
value={1}
onChange={props.handleChange}
/>
<span className="mx-2 text-base text-dark-gray dark:text-white">
Email
@@ -279,8 +316,9 @@ export default function PersonalInfoTab({
<input
className="w-4 h-4 cursor-pointer"
type="checkbox"
name="prefcomm2"
id=""
name="pref_phone"
value={1}
onChange={props.handleChange}
/>
<span className="mx-2 text-base text-dark-gray dark:text-white">
Phone
@@ -292,22 +330,32 @@ export default function PersonalInfoTab({
{/* 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">
<label
htmlFor="accept_promo"
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
<div>
<input
type="checkbox"
id="accept_promo"
name="accept_promo"
value={props.values.accept_promo}
checked={props.values.accept_promo}
onChange={props.handleChange}
className="hidden"
/>
<label
htmlFor="accept_promo"
className={`cursor-pointer flex items-center h-6 w-8 mr-1 p-1 ${
props.values.accept_promo
? "bg-sky-blue flex justify-end items-center"
: "bg-slate-200"
} rounded-full transition`}
} rounded-full transition duration-200`}
>
<div className="w-4 h-full bg-white rounded-full"></div>
</div>
</label>
</div>
</div>
{/* inputs ends here */}
@@ -336,8 +384,8 @@ export default function PersonalInfoTab({
<div className="w-full relative">
<img
src={profileImg}
alt=""
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
alt="profile"
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-contain object-center"
/>
<input
ref={profileImgInput}
@@ -384,7 +432,7 @@ export default function PersonalInfoTab({
)}
<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
{/* <Link
to="/"
className="text-18 text-light-red tracking-wide "
>
@@ -392,7 +440,7 @@ export default function PersonalInfoTab({
{" "}
Cancel
</span>
</Link>
</Link> */}
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
+178 -150
View File
@@ -8,13 +8,16 @@ export default function TermsConditionTab() {
<h1 className="text-3xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
Terms of use
</h1>
<p className="text-base text-thin-light-gray leading-[28px] ">
<p className="text-base text-thin-light-gray leading-[28px]">
(updated August 10, 2023)
</p>
<p className="text-base text-thin-light-gray leading-[28px]">
These Website Terms & Conditions (T&Cs) apply to your access and
use of www.wrenchboard.com,dashboard.wrenchboard.com (the Site),
including all software, data, reports, text, images, sounds, video,
and all contents made available through any portion of the Site
(collectively, the Content). Content includes all such elements as
a whole, as well as individual elements and portions thereof.
use of www.wrenchboard.com,users.wrenchboard.com (the Site),
native apps, including all software, data, reports, text, images,
sounds, video, and all contents made available through any portion
of the Site (collectively, the Content). The range includes all
such elements as whole, individual, and parts.
</p>
</div>
<hr />
@@ -37,103 +40,138 @@ export default function TermsConditionTab() {
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
General Conditions of Use
</h1>
<p className="text-base text-thin-light-gray leading-[28px] ">
<b> Authorization to Access and Use Site and Content.</b> Subject to
your compliance with these T&Cs and the provisions hereof, you may
access or use the Site and Content solely for the purpose of your
evaluation of WRENCHBOARD and WRENCHBOARDs products and services.
You may only link to the Site or Content, or any portion thereof, as
expressly permitted by WRENCHBOARD.
<br />
<b> Ownership and Restrictions.</b> All rights, title, and interest
in and to the Site and Content will remain with and belong
exclusively to WRENCHBOARD. You will not (a) sublicense, resell,
rent, lease, transfer, assign, time share or otherwise commercially
exploit or make the Site and any Content available to any third
party, (b) use the Site and Content in any unlawful manner
(including without limitation in violation of any data, privacy or
export control laws) or in any manner that interferes with or
disrupts the integrity or performance of the Site and Content or
their related components, or (c) modify, adapt or hack the Site and
Content to, or try to, gain unauthorized access to the restricted
portions of the Site and Content or related systems or networks
(i.e., circumvent any encryption or other security measures, gain
access to any source code or any other underlying form of technology
or information, and gain access to any part of the Site and Content,
or any other products or services of WRENCHBOARD that are not
readily made available to the general public). You are not permitted
to copy, modify, frame, repost, publicly perform or display, sell,
reproduce, distribute, or create derivative works of the Site and
Content, except that you may download, display, and print one copy
of the publicly available materials (i.e., the Content that does not
require an Account name or password to access) on any single
computer solely for your personal, non-commercial use, provided that
you do not modify the material in any way and you keep intact all
copyright, trademark, and other proprietary notices. You agree not
to access the Site or Content by any means other than through the
interface that is provided by WRENCHBOARD to access the same. You
may not use any page-scrape, deep-link, spider, or robot or
other automatic program, device, algorithm or methodology, or any
similar manual process, to access, copy, acquire, or monitor any
portion of the Site or any Content, or in any way reproduce or
circumvent the presentation or navigational structure of the Site or
any Content, to obtain or attempt to obtain any Content or other
information through any means not made generally available through
the Site by WRENCHBOARD. WRENCHBOARD reserves the right to take any
lawful measures to prevent any such activity. You may not forge
headers or otherwise manipulate identifiers in order to disguise the
origin of any message or transmittal you send to WRENCHBOARD on or
through the Site or any service offered on or through the Site. You
may not pretend that you are, or that you represent, someone else,
or impersonate any other individual or entity.
<b> Responsibility for Your Data.</b> You are solely responsible for
all data, information, and other content, that you upload, post, or
otherwise provide or store (hereafter post(ing)) in connection
with or relating to the Site.
</p>
</div>
<hr />
<div className="my-8">
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
Use of Intellectual Property.
</h1>
<p className="text-base text-thin-light-gray leading-[28px] ">
<b> Rights in User Content.</b> By posting your information and
other content (User Content) on or through the Site and Content,
you grant WRENCHBOARD a worldwide, non-exclusive, perpetual,
irrevocable, royalty-free, fully paid, sublicensable and
transferable license to use, modify, reproduce, distribute, display,
publish and perform User Content in connection with the Site and
Content. WRENCHBOARD has the right, but not the obligation, to
monitor the Site and Content and User Content. WRENCHBOARD may
remove or disable any User Content at any time for any reason, or
for no reason at all. You, the user, acknowledge that you bear sole
responsibility for adequate security, protection, and backup of User
Content. WRENCHBOARD will have no liability to you for any
unauthorized access or use of any of User Content, or any
corruption, deletion, destruction, or loss of any of User Content.
</p>
</div>
<hr />
<div className="my-8">
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
Feedback
</h1>
<p className="text-base text-thin-light-gray leading-[28px] ">
You may submit ideas, suggestions, or comments (Feedback)
regarding the Site and Content or WRENCHBOARDs business, products,
or services. By submitting any Feedback, you acknowledge and agree
that (a) your Feedback is provided by you voluntarily and
WRENCHBOARD may, without any obligations or limitation, use and
exploit such Feedback in any manner and for any purpose, (b) you
will not seek and are not entitled to any money or other form of
compensation, consideration, or attribution with respect to your
Feedback regardless of whether WRENCHBOARD considered or used your
Feedback in any manner, and (c) your Feedback is not the
confidential or proprietary information of you or any third party.
</p>
<ul className="ml-8">
<li className="text-base text-thin-light-gray leading-[28px]">
<h1 className="text-lg tracking-wide font-bold text-dark-gray dark:text-white my-4">
Authorization to Access and Use Site and Content.
</h1>
<p className="text-base font-bold text-thin-light-gray leading-[28px]">
Subject to your compliance with these T&Cs and the provisions
hereof, you may access or use the Site and Content solely to
evaluate WRENCHBOARD and WRENCHBOARDs products and services.
You may only link to the Site or Content, or any portion
thereof, as expressly permitted by WRENCHBOARD.
</p>
</li>
<li className="text-base font-bold text-thin-light-gray leading-[28px]">
<h1 className="text-lg tracking-wide font-bold text-dark-gray dark:text-white my-4">
Ownership and Restrictions
</h1>
<p className="text-base text-thin-light-gray leading-[28px]">
All rights, title, and interest in and to the Site and Content
will remain exclusive to WRENCHBOARD. You will not:
</p>
<ol className="ml-8 list-decimal">
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Sublicense, resell, rent, lease, transfer, assign, timeshare,
or commercially exploit or make the Site and any Content
available to any third party.
</li>
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Use the Site and Content in any unlawful manner (including
without limitation in violation of any data, privacy, or
export control laws) or in any way that interferes with or
disrupts the integrity or performance of the Site and Content
or their related components.
</li>
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Modify, adapt, or hack the Site and Content to, or try to,
gain unauthorized access to the restricted portions of the
Site and Content or related systems or networks (i.e.,
circumvent any encryption or other security measures, gain
access to any source code or any other underlying form of
technology or information, and gain access to any part of the
Site and Content, or any other products or services of
WRENCHBOARD that are not readily made available to the general
public).
</li>
</ol>
<p className="my-4 text-base font-bold text-thin-light-gray leading-[28px]">
You are not permitted to copy, modify, frame, repost, publicly
perform or display, sell, reproduce, distribute, or create
derivative works of the Site and Content, except that you may
download and print one copy of the publicly available materials
(i.e., the Content that does not require an Account name or
password to access) on any single computer solely for your
personal, non-commercial use, provided that you do not modify
the material in any way. You keep intact all copyright,
trademark, and other proprietary notices.
</p>
<p className="my-4 text-base font-bold text-thin-light-gray leading-[28px]">
You agree not to access the Site or Content by any means other
than through the interface that WRENCHBOARD provides to access
the same. You may not use any page-scrape, deep-link,
spider, or robot or other automatic program, device,
algorithm or methodology, or any similar manual process, to
access, copy, acquire, or monitor any portion of the Site or any
Content, or in any way reproduce or circumvent the presentation
or navigational structure of the Site or any Content, to obtain
or attempt to obtain any Content or other information through
any means not made generally available through the Site by
WRENCHBOARD.
</p>
<p className="my-4 text-base font-bold text-thin-light-gray leading-[28px]">
WRENCHBOARD reserves the right to take lawful measures to
prevent such activity. You may not forge headers or otherwise
manipulate identifiers to disguise the origin of any message or
transmittal you send to WRENCHBOARD on or through the Site or
any service offered on or through the Site. You may not pretend
that you are, or that you represent, someone else or impersonate
any other individual or entity.
</p>
</li>
<li className="text-base text-thin-light-gray leading-[28px]">
<h1 className="text-lg tracking-wide font-bold text-dark-gray dark:text-white my-4">
Responsibility for Your Data
</h1>
<p className="text-base font-bold text-thin-light-gray leading-[28px]">
You are solely responsible for all data, information, and other
Content, that you upload, post, or otherwise provide or store
(hereafter post(ing)) in connection with or relating to the
Site. By posting your information and other Content (User
Content) on or through the Site and Content, you grant
WRENCHBOARD a worldwide, non-exclusive, perpetual, irrevocable,
royalty-free, sublicensable, and transferable license to use,
modify, reproduce, distribute, display, publish and perform User
Content in connection with the Site and Content. WRENCHBOARD has
the right, but not the obligation, to monitor the Site and
Content and User Content. <br />
WRENCHBOARD may remove or turn off any User Content at any time
for any reason or no reason. WRENCHBOARD will have no liability
to you for any unauthorized access or use of any of User Content
or any corruption, deletion, destruction, or loss of any of User
Content.
</p>
</li>
<li className="text-base text-thin-light-gray leading-[28px]">
<h1 className="text-lg tracking-wide font-bold text-dark-gray dark:text-white my-4">
Feedback
</h1>
<p className="text-base font-bold text-thin-light-gray leading-[28px]">
You may submit ideas, suggestions, or comments (Feedback)
regarding the Site and Content or WRENCHBOARDs business,
products, or services. By submitting any Feedback, you
acknowledge and agree that:{" "}
</p>
<ol className="ml-8 list-decimal">
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Your Feedback is provided by you voluntarily, and WRENCHBOARD
may, without any obligations or limitations, use and exploit
such Feedback in any manner and for any purpose.
</li>
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
You will not seek and are not entitled to any money or other
form of compensation, consideration, or attribution concerning
your Feedback, regardless of whether WRENCHBOARD considered or
used your Feedback in any manner.
</li>
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Your Feedback is not confidential or proprietary information
of you or any third party.
</li>
</ol>
</li>
</ul>
</div>
<hr />
@@ -141,36 +179,32 @@ export default function TermsConditionTab() {
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
Termination of Access Due to Violations
</h1>
<p className="text-base text-thin-light-gray leading-[28px] ">
<p className="font-bold text-base text-thin-light-gray leading-[28px] ">
WRENCHBOARD may, in its sole discretion and without prior notice,
terminate your access to the Site and/or block your future access to
terminate your access to the Site and block your future access to
the Site if we determine that you have violated these T&Cs or other
agreements or guidelines which may be associated with your use of
the Site. You also agree that any violation by you of these T&Cs
will cause irreparable harm to WRENCHBOARD, for which monetary
damages would be inadequate, and you consent to WRENCHBOARD
obtaining any injunctive or equitable relief that WRENCHBOARD deems
necessary or appropriate in such circumstances, without limiting
WRENCHBOARDs other available remedies. Further, WRENCHBOARD may, in
its sole discretion and without prior notice, terminate your access
to the Site, for cause, which includes (but is not limited to) (1)
requests by law enforcement or other government agencies, (2)
discontinuance or material modification of the Site or any service
offered on or through the Site, or (3) unexpected technical issues
or problems.
the Site. Further, WRENCHBOARD may, in its sole discretion and
without prior notice, terminate your access to the Site for cause,
which includes (but is not limited to):
</p>
</div>
<hr />
<div className="my-8">
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
T&Cs Updates
</h1>
<ol className="ml-8 list-decimal font-bold">
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Requests by law enforcement or other government agencies
</li>
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Discontinuance or material modification of the Site or any service
offered on or through the Site
</li>
<li className="my-2 text-base font-bold text-thin-light-gray leading-[28px]">
Unexpected technical issues or problems.T&Cs Updates
</li>
</ol>
<p className="text-base text-thin-light-gray leading-[28px] ">
WRENCHBOARD reserves the right, at its sole discretion, to change or
modify portions of these T&Cs at any time. WRENCHBOARD will post the
changes to these T&Cs on the Site and will indicate at the top of
this page the date these terms were last revised. It is your
changes to these T&Cs on the Site and indicate at the top of this
page the date these terms were last revised. It is your
responsibility to check the T&Cs periodically for changes. Your
continued use of the Site and Content after the date any such
changes become effective constitutes your acceptance of the new or
@@ -193,42 +227,36 @@ export default function TermsConditionTab() {
REPRESENTATIONS OR WARRANTIES ARISING FROM COURSE OF DEALING, COURSE
OF PERFORMANCE OR USAGE OF TRADE. YOU ACKNOWLEDGE THAT WRENCHBOARD
DOES NOT WARRANT THAT YOUR ACCESS OR USE OR BOTH OF THE SITE AND
CONTENT WILL BE UNINTERRUPTED, TIMELY, SECURE, ERROR-FREE OR
CONTENT WILL BE UNINTERRUPTED, TIMELY, SECURE, ERROR-FREE, OR
VIRUS-FREE, AND WRENCHBOARD DOES NOT MAKE ANY WARRANTY AS TO THE
RESULTS THAT MAY BE OBTAINED FROM USE OF THE SITE AND CONTENT. NO
INFORMATION, ADVICE OR SERVICES OBTAINED BY YOU FROM WRENCHBOARD OR
THROUGH THE SITE WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN
THESE TERMS and CONDITIONS AND YOU SHOULD NOT RELY ON THE SITE AND
RESULTS THAT MAY BE OBTAINED FROM THE USE OF THE SITE AND CONTENT.
NO INFORMATION, ADVICE, OR SERVICES OBTAINED BY YOU FROM WRENCHBOARD
OR THROUGH THE SITE WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN
THESE TERMS and CONDITIONS, AND YOU SHOULD NOT RELY ON THE SITE AND
THE GENERAL CONTENT ALONE AS THE BASIS FOR YOUR BUSINESS DECISIONS.
</p>
</div>
<hr />
<div className="my-8">
<p className="text-base text-thin-light-gray leading-[28px] ">
<p className="font-bold text-base text-thin-light-gray leading-[28px] ">
WRENCHBOARD reserves the right to do any of the following, at any
time, without notice: (1) to modify, suspend or terminate operation
time, without notice: ( 1 ); to modify, suspend or terminate operation
of or access to the Site, or any portion of the Site, for any
reason; (2) to modify or change the Site, or any portion of the
Site, for any reason; and (3) to interrupt the operation of the
reason; ( 2 ) to modify or change the Site, or any portion of the
Site, for any reason; and ( 3 ) to interrupt the operation of the
Site, or any portion of the Site, as necessary to perform routine or
non-routine maintenance, error correction, or other changes..
non-routine maintenance, error correction, or other changes. Changes
to the Policy
</p>
</div>
<hr />
<div className="mt-8">
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
Changes To the Policy
</h1>
<p className="text-base text-thin-light-gray leading-[28px] ">
We reserve the rights to update and make changes to this Privacy
policy at anytime. Changes will become effective once posted.
However, we will notify you by email or when you log on to the
service or website about any changes that fundamentally affect how
we manage your personal information. Contacting Us: You may contact
us about this policy through our email address anytime :
support@wrenchboard.com
<p className="my-4 text-base text-thin-light-gray leading-[28px] ">
We reserve the right to update and change this Privacy policy at any
time. Changes will become effective once posted. However, we will
notify you by email or when you log on to the service or website
about any changes that fundamentally affect how we manage your
personal information. Contacting Us: You may contact us about this
policy through our email address anytime: support@wrenchboard.com
</p>
</div>
</div>
+9 -4
View File
@@ -5,8 +5,9 @@ import React, {
useRef,
useState,
} from "react";
import { useSelector } from "react-redux";
import cover from "../../assets/images/profile-info-cover.png";
import profile from "../../assets/images/profile-info-profile.png";
import profile from "../../assets/images/profile.jpg";
import usersService from "../../services/UsersService";
import Icons from "../Helpers/Icons";
import Layout from "../Partials/Layout";
@@ -23,15 +24,19 @@ import {
import RecipientAccountTab from "./Tabs/RecipientAccountTab";
export default function Settings({ faq }) {
const [profileImg, setProfileImg] = useState(profile);
const { userDetails } = useSelector((state) => state?.userDetails);
const [profileImg, setProfileImg] = useState(
userDetails?.profile_pic_url ? userDetails.profile_pic_url : profile
);
const [coverImg, setCoverImg] = useState(cover);
const [reloadCardList, setReloadCardList] = useState(false) // STATE TO DETERMINE WHEN CARD LIST RELOADS. EG: WHEN USER DELETES A CARD
const [reloadCardList, setReloadCardList] = useState(false); // STATE TO DETERMINE WHEN CARD LIST RELOADS. EG: WHEN USER DELETES A CARD
// profile img
const profileImgInput = useRef(null);
const browseProfileImg = () => {
profileImgInput.current.click();
};
const profileImgChangHandler = (e) => {
if (e.target.value !== "") {
const imgReader = new FileReader();
@@ -22,132 +22,134 @@ export default function ProductUploadField({
<div className="w-full lg:pl-[41px]">
<div className="fields w-full">
<form onSubmit={(e) => e.preventDefault()}>
<div className="field w-full mb-6">
<h1 className="field-title">Put on marketplace</h1>
<p className="text-thin-light-gray text-base tracking-wide font-medium mb-3">
Enter price to allow users instantly purchase your NFT
</p>
{/*<div className="field w-full mb-6">*/}
{/* <h1 className="field-title">Put on marketplace</h1>*/}
{/* <p className="text-thin-light-gray text-base tracking-wide font-medium mb-3">*/}
{/* Enter price to allow users instantly purchase your NFT*/}
{/* </p>*/}
{/* <div className="items sm:flex sm:space-x-5">*/}
{/* <div*/}
{/* className="item sm:w-[120px] w-full h-[130px] relative mb-5 sm:mb-0"*/}
{/* onClick={() => cpt("fixed")}*/}
{/* >*/}
{/* <div*/}
{/* className={`w-full h-full bg-white dark:bg-dark-white rounded-md z-20 relative flex justify-center items-center ${*/}
{/* datas.priceType === "fixed"*/}
{/* ? ""*/}
{/* : "border border-light-purple dark:border-[#5356fb29] "*/}
{/* }`}*/}
{/* >*/}
{/* <div className="flex flex-col justify-center items-center">*/}
{/* <div*/}
{/* className={`w-[68px] h-[68px] rounded-full flex justify-center items-center ${*/}
{/* datas.priceType === "fixed"*/}
{/* ? "primary-gradient"*/}
{/* : "bg-[#F2E8FA]"*/}
{/* }`}*/}
{/* >*/}
{/* <GradientIcons*/}
{/* name={`${*/}
{/* datas.priceType === "fixed"*/}
{/* ? "doller"*/}
{/* : "gradient-doller"*/}
{/* }`}*/}
{/* />*/}
{/* </div>*/}
{/* <p className="text-center text-base tracking-wide mt-1 text-dark-gray dark:text-white">*/}
{/* Fixed price*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* {datas.priceType === "fixed" && (*/}
{/* <div*/}
{/* className="sm:w-[122px] w-full h-[132px] primary-gradient rounded-md absolute z-10"*/}
{/* style={{ top: "-1px", left: "-1px" }}*/}
{/* ></div>*/}
{/* )}*/}
{/* </div>*/}
{/* <div*/}
{/* className="item sm:w-[120px] w-full h-[130px] relative mb-5 sm:mb-0"*/}
{/* onClick={() => cpt("bids")}*/}
{/* >*/}
{/* <div*/}
{/* className={`w-full h-full bg-white dark:bg-dark-white rounded-md z-20 relative flex justify-center items-center ${*/}
{/* datas.priceType === "bids"*/}
{/* ? ""*/}
{/* : "border border-light-purple dark:border-[#5356fb29] "*/}
{/* }`}*/}
{/* >*/}
{/* <div className="flex flex-col justify-center items-center">*/}
{/* <div*/}
{/* className={`w-[68px] h-[68px] rounded-full flex justify-center items-center ${*/}
{/* datas.priceType === "bids"*/}
{/* ? "primary-gradient"*/}
{/* : "bg-[#F2E8FA]"*/}
{/* }`}*/}
{/* >*/}
{/* <GradientIcons*/}
{/* name={`${*/}
{/* datas.priceType === "bids"*/}
{/* ? "hammer"*/}
{/* : "gradient-hammer"*/}
{/* }`}*/}
{/* />*/}
{/* </div>*/}
{/* <p className="text-center text-base tracking-wide mt-1 text-dark-gray dark:text-white">*/}
{/* Open for bids*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* {datas.priceType === "bids" && (*/}
{/* <div*/}
{/* className="sm:w-[122px] w-full h-[132px] primary-gradient rounded-md absolute z-10"*/}
{/* style={{ top: "-1px", left: "-1px" }}*/}
{/* ></div>*/}
{/* )}*/}
{/* </div>*/}
{/* <div*/}
{/* className="item sm:w-[120px] w-full h-[130px] relative mb-5 sm:mb-0"*/}
{/* onClick={() => cpt("auction")}*/}
{/* >*/}
{/* <div*/}
{/* className={`w-full h-full bg-white dark:bg-dark-white rounded-md z-20 relative flex justify-center items-center ${*/}
{/* datas.priceType === "auction"*/}
{/* ? ""*/}
{/* : "border border-light-purple dark:border-[#5356fb29] "*/}
{/* }`}*/}
{/* >*/}
{/* <div className="flex flex-col justify-center items-center">*/}
{/* <div*/}
{/* className={`w-[68px] h-[68px] rounded-full flex justify-center items-center ${*/}
{/* datas.priceType === "auction"*/}
{/* ? "primary-gradient"*/}
{/* : "bg-[#F2E8FA]"*/}
{/* }`}*/}
{/* >*/}
{/* <GradientIcons*/}
{/* name={`${*/}
{/* datas.priceType === "auction"*/}
{/* ? "timeout"*/}
{/* : "gradient-timeout"*/}
{/* }`}*/}
{/* />*/}
{/* </div>*/}
{/* <p className="text-center text-base tracking-wide mt-1 text-dark-gray dark:text-white">*/}
{/* Timed auction*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* {datas.priceType === "auction" && (*/}
{/* <div*/}
{/* className="sm:w-[122px] w-full h-[132px] primary-gradient rounded-md absolute z-10"*/}
{/* style={{ top: "-1px", left: "-1px" }}*/}
{/* ></div>*/}
{/* )}*/}
{/* </div>*/}
{/* </div>*/}
{/*</div>*/}
<div className="items sm:flex sm:space-x-5">
<div
className="item sm:w-[120px] w-full h-[130px] relative mb-5 sm:mb-0"
onClick={() => cpt("fixed")}
>
<div
className={`w-full h-full bg-white dark:bg-dark-white rounded-md z-20 relative flex justify-center items-center ${
datas.priceType === "fixed"
? ""
: "border border-light-purple dark:border-[#5356fb29] "
}`}
>
<div className="flex flex-col justify-center items-center">
<div
className={`w-[68px] h-[68px] rounded-full flex justify-center items-center ${
datas.priceType === "fixed"
? "primary-gradient"
: "bg-[#F2E8FA]"
}`}
>
<GradientIcons
name={`${
datas.priceType === "fixed"
? "doller"
: "gradient-doller"
}`}
/>
</div>
<p className="text-center text-base tracking-wide mt-1 text-dark-gray dark:text-white">
Fixed price
</p>
</div>
</div>
{datas.priceType === "fixed" && (
<div
className="sm:w-[122px] w-full h-[132px] primary-gradient rounded-md absolute z-10"
style={{ top: "-1px", left: "-1px" }}
></div>
)}
</div>
<div
className="item sm:w-[120px] w-full h-[130px] relative mb-5 sm:mb-0"
onClick={() => cpt("bids")}
>
<div
className={`w-full h-full bg-white dark:bg-dark-white rounded-md z-20 relative flex justify-center items-center ${
datas.priceType === "bids"
? ""
: "border border-light-purple dark:border-[#5356fb29] "
}`}
>
<div className="flex flex-col justify-center items-center">
<div
className={`w-[68px] h-[68px] rounded-full flex justify-center items-center ${
datas.priceType === "bids"
? "primary-gradient"
: "bg-[#F2E8FA]"
}`}
>
<GradientIcons
name={`${
datas.priceType === "bids"
? "hammer"
: "gradient-hammer"
}`}
/>
</div>
<p className="text-center text-base tracking-wide mt-1 text-dark-gray dark:text-white">
Open for bids
</p>
</div>
</div>
{datas.priceType === "bids" && (
<div
className="sm:w-[122px] w-full h-[132px] primary-gradient rounded-md absolute z-10"
style={{ top: "-1px", left: "-1px" }}
></div>
)}
</div>
<div
className="item sm:w-[120px] w-full h-[130px] relative mb-5 sm:mb-0"
onClick={() => cpt("auction")}
>
<div
className={`w-full h-full bg-white dark:bg-dark-white rounded-md z-20 relative flex justify-center items-center ${
datas.priceType === "auction"
? ""
: "border border-light-purple dark:border-[#5356fb29] "
}`}
>
<div className="flex flex-col justify-center items-center">
<div
className={`w-[68px] h-[68px] rounded-full flex justify-center items-center ${
datas.priceType === "auction"
? "primary-gradient"
: "bg-[#F2E8FA]"
}`}
>
<GradientIcons
name={`${
datas.priceType === "auction"
? "timeout"
: "gradient-timeout"
}`}
/>
</div>
<p className="text-center text-base tracking-wide mt-1 text-dark-gray dark:text-white">
Timed auction
</p>
</div>
</div>
{datas.priceType === "auction" && (
<div
className="sm:w-[122px] w-full h-[132px] primary-gradient rounded-md absolute z-10"
style={{ top: "-1px", left: "-1px" }}
></div>
)}
</div>
</div>
</div>
<div className="field w-full mb-6">
<h1 className="field-title">Item Name </h1>
<div className="input-field mt-2">
@@ -161,19 +163,22 @@ export default function ProductUploadField({
/>
</div>
</div>
<div className="field w-full mb-6">
<h1 className="field-title">Exter link </h1>
<div className="input-field mt-2">
<InputCom
fieldClass="px-6"
type="text"
name="link"
inputHandler={linkh}
value={datas.link}
placeholder="https:yoursite.lo/imte/item_name123"
/>
</div>
</div>
{/*<div className="field w-full mb-6">*/}
{/* <h1 className="field-title">Exter link </h1>*/}
{/* <div className="input-field mt-2">*/}
{/* <InputCom*/}
{/* fieldClass="px-6"*/}
{/* type="text"*/}
{/* name="link"*/}
{/* inputHandler={linkh}*/}
{/* value={datas.link}*/}
{/* placeholder="https:yoursite.lo/imte/item_name123"*/}
{/* />*/}
{/* </div>*/}
{/*</div>*/}
<div className="field w-full mb-6">
<h1 className="field-title">Description </h1>
<div className="input-field mt-2">
@@ -188,219 +193,222 @@ export default function ProductUploadField({
</div>
</div>
</div>
<div className="field w-full mb-6">
<h1 className="field-title">Instant sale price </h1>
<div className="input-field my-2">
<div className="input-wrapper border border-light-purple dark:border-[#5356fb29] w-full rounded-[50px] h-[58px] flex items-center overflow-hidden">
<input
value={datas.price}
onChange={(e) => priceHndlr(e)}
placeholder="enter the price for which the item will be instantly sold"
className="input-field placeholder:text-base text-bese px-6 text-dark-gray dark:text-white w-10/12 h-full bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none"
type="number"
/>
<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>
<svg
width="13"
height="6"
viewBox="0 0 13 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
opacity="0.7"
d="M12.7488 0.247421C12.6691 0.169022 12.5744 0.106794 12.4699 0.0643287C12.3655 0.0218632 12.2535 0 12.1403 0C12.0272 0 11.9152 0.0218632 11.8107 0.0643287C11.7063 0.106794 11.6115 0.169022 11.5318 0.247421L7.60655 4.07837C7.52688 4.15677 7.43209 4.219 7.32765 4.26146C7.22321 4.30393 7.11119 4.32579 6.99805 4.32579C6.88491 4.32579 6.77289 4.30393 6.66845 4.26146C6.56401 4.219 6.46922 4.15677 6.38954 4.07837L2.46427 0.247421C2.3846 0.169022 2.28981 0.106794 2.18537 0.0643287C2.08093 0.0218632 1.96891 0 1.85577 0C1.74263 0 1.63061 0.0218632 1.52617 0.0643287C1.42173 0.106794 1.32694 0.169022 1.24727 0.247421C1.08764 0.404141 0.998047 0.616141 0.998047 0.837119C0.998047 1.0581 1.08764 1.2701 1.24727 1.42682L5.18111 5.26613C5.6632 5.73605 6.31669 6 6.99805 6C7.6794 6 8.33289 5.73605 8.81498 5.26613L12.7488 1.42682C12.9084 1.2701 12.998 1.0581 12.998 0.837119C12.998 0.616141 12.9084 0.404141 12.7488 0.247421Z"
fill="#374557"
/>
</svg>
</span>
</div>
</div>
</div>
</div>
<div className="text-base tracking-wide text-dark-gray dark:text-white">
<p>
<span className="text-thin-light-gray">Service fee :</span> 1.5%
</p>
<p>
<span className="text-thin-light-gray">You will Receive :</span>
.29 ETH $120.56
</p>
</div>
</div>
<div className="field w-full mb-6">
<h1 className="field-title">Royalties</h1>
<div className="input-field my-2">
<div className="mb-2">
<InputCom
fieldClass="px-6"
type="text"
name="link"
inputHandler={roltsHndlr}
value={datas.royalties}
placeholder="0%"
/>
</div>
<p className="text-thin-light-gray text-sm tracking-wide">
Suggested: 10%, 20%, 30%
</p>
</div>
</div>
<div className="field w-full mb-6">
<h1 className="field-title">
Properties
<span className="text-thin-light-gray font-normal ml-2">
(Optional)
</span>
</h1>
<div className="input-field my-2">
<div className="mb-2">
<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}
value={datas.propertiesKey}
placeholder="Enter key"
/>
</div>
<div className="flex-1">
<InputCom
fieldClass="px-6"
type="text"
name="link"
inputHandler={valueHndlr}
value={datas.propertiesValue}
placeholder="Enter Value"
/>
</div>
</div>
</div>
</div>
</div>
<div className="field w-full mb-6">
<h1 className="field-title">Choose collection</h1>
<div className="input-field mt-2">
<div className="sm:flex sm:space-x-5">
{/* create collection */}
<div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border border-light-purple dark:border-[#5356fb29] flex justify-center items-center cursor-pointer">
<div>
<span className="mb-1 flex justify-center">
<svg
width="25"
height="25"
viewBox="0 0 25 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M25 12.5125C25.019 19.39 19.3853 24.9989 12.5054 25.0001C5.6017 25.0012 -0.0153836 19.3615 3.1653e-05 12.471C0.0154469 5.59949 5.63965 -0.0224583 12.5469 6.7456e-05C19.396 0.0225932 25.0297 5.61846 25 12.5125ZM14.3007 17.2097C14.3007 16.3324 14.3007 15.4551 14.3007 14.5778C14.3007 14.3525 14.3007 14.3525 14.5224 14.3525C16.2299 14.3525 17.9387 14.3525 19.6462 14.3513C19.7339 14.3513 19.8241 14.349 19.9106 14.3335C20.832 14.1711 21.4581 13.327 21.3798 12.356C21.3099 11.4775 20.4988 10.733 19.6011 10.7306C17.9031 10.7271 16.2062 10.7294 14.5082 10.7294C14.2995 10.7294 14.2995 10.7294 14.2995 10.5243C14.2995 8.7851 14.2995 7.04588 14.2983 5.30784C14.2983 5.22959 14.2983 5.15016 14.2805 5.07547C14.0588 4.16021 13.218 3.59588 12.3465 3.68599C11.3836 3.78676 10.697 4.55026 10.697 5.48212C10.697 7.14309 10.697 8.80288 10.697 10.4639C10.697 10.7555 10.7243 10.7294 10.4243 10.7294C8.79504 10.7294 7.16457 10.7401 5.5353 10.7259C4.40524 10.7152 3.60483 11.6293 3.63922 12.6216C3.67242 13.5451 4.45623 14.3513 5.37996 14.3513C7.08275 14.3513 8.78555 14.3513 10.4883 14.3513C10.697 14.3513 10.697 14.3525 10.697 14.5576C10.697 16.2387 10.697 17.9211 10.697 19.6022C10.697 19.6757 10.6935 19.7492 10.703 19.8215C10.8761 21.1256 12.2884 21.8358 13.4255 21.1719C13.9817 20.847 14.3066 20.3586 14.3018 19.684C14.2947 18.86 14.3007 18.0349 14.3007 17.2097Z"
fill="#374557"
fillOpacity="0.6"
/>
</svg>
</span>
<span className="text-thin-light-gray text-center">
Crteate
</span>
</div>
</div>
{/* saved collection list */}
<div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border-gradient flex justify-center items-center cursor-pointer">
<div>
<div className="mb-1 flex justify-center ">
<div className="w-[50px] h-[50px] rounded-full overflow-hidden">
<img
src={collection1}
alt=""
className="w-full h-full object-cover"
/>
</div>
</div>
<span className="text-thin-light-gray text-center">
Name 1
</span>
</div>
</div>
<div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border border-light-purple dark:border-[#5356fb29] flex justify-center items-center cursor-pointer">
<div>
<div className="mb-1 flex justify-center ">
<div className="w-[50px] h-[50px] rounded-full overflow-hidden">
<img
src={collection2}
alt=""
className="w-full h-full object-cover"
/>
</div>
</div>
<span className="text-thin-light-gray text-center">
Name 2
</span>
</div>
</div>
<div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border border-light-purple dark:border-[#5356fb29] flex justify-center items-center cursor-pointer">
<div>
<div className="mb-1 flex justify-center ">
<div className="w-[50px] h-[50px] rounded-full overflow-hidden">
<img
src={collection3}
alt=""
className="w-full h-full object-cover"
/>
</div>
</div>
<span className="text-thin-light-gray text-center">
Name 3
</span>
</div>
</div>
</div>
</div>
</div>
{/*<div className="field w-full mb-6">*/}
{/* <h1 className="field-title">Instant sale price </h1>*/}
{/* <div className="input-field my-2">*/}
{/* <div className="input-wrapper border border-light-purple dark:border-[#5356fb29] w-full rounded-[50px] h-[58px] flex items-center overflow-hidden">*/}
{/* <input*/}
{/* value={datas.price}*/}
{/* onChange={(e) => priceHndlr(e)}*/}
{/* placeholder="enter the price for which the item will be instantly sold"*/}
{/* className="input-field placeholder:text-base text-bese px-6 text-dark-gray dark:text-white w-10/12 h-full bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none"*/}
{/* type="number"*/}
{/* />*/}
{/* <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>*/}
{/* <svg*/}
{/* width="13"*/}
{/* height="6"*/}
{/* viewBox="0 0 13 6"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <path*/}
{/* opacity="0.7"*/}
{/* d="M12.7488 0.247421C12.6691 0.169022 12.5744 0.106794 12.4699 0.0643287C12.3655 0.0218632 12.2535 0 12.1403 0C12.0272 0 11.9152 0.0218632 11.8107 0.0643287C11.7063 0.106794 11.6115 0.169022 11.5318 0.247421L7.60655 4.07837C7.52688 4.15677 7.43209 4.219 7.32765 4.26146C7.22321 4.30393 7.11119 4.32579 6.99805 4.32579C6.88491 4.32579 6.77289 4.30393 6.66845 4.26146C6.56401 4.219 6.46922 4.15677 6.38954 4.07837L2.46427 0.247421C2.3846 0.169022 2.28981 0.106794 2.18537 0.0643287C2.08093 0.0218632 1.96891 0 1.85577 0C1.74263 0 1.63061 0.0218632 1.52617 0.0643287C1.42173 0.106794 1.32694 0.169022 1.24727 0.247421C1.08764 0.404141 0.998047 0.616141 0.998047 0.837119C0.998047 1.0581 1.08764 1.2701 1.24727 1.42682L5.18111 5.26613C5.6632 5.73605 6.31669 6 6.99805 6C7.6794 6 8.33289 5.73605 8.81498 5.26613L12.7488 1.42682C12.9084 1.2701 12.998 1.0581 12.998 0.837119C12.998 0.616141 12.9084 0.404141 12.7488 0.247421Z"*/}
{/* fill="#374557"*/}
{/* />*/}
{/* </svg>*/}
{/* </span>*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div className="text-base tracking-wide text-dark-gray dark:text-white">*/}
{/* <p>*/}
{/* <span className="text-thin-light-gray">Service fee :</span> 1.5%*/}
{/* </p>*/}
{/* <p>*/}
{/* <span className="text-thin-light-gray">You will Receive :</span>*/}
{/* .29 ETH $120.56*/}
{/* </p>*/}
{/* </div>*/}
{/*</div>*/}
{/*<div className="field w-full mb-6">*/}
{/* <h1 className="field-title">Royalties</h1>*/}
{/* <div className="input-field my-2">*/}
{/* <div className="mb-2">*/}
{/* <InputCom*/}
{/* fieldClass="px-6"*/}
{/* type="text"*/}
{/* name="link"*/}
{/* inputHandler={roltsHndlr}*/}
{/* value={datas.royalties}*/}
{/* placeholder="0%"*/}
{/* />*/}
{/* </div>*/}
{/* <p className="text-thin-light-gray text-sm tracking-wide">*/}
{/* Suggested: 10%, 20%, 30%*/}
{/* </p>*/}
{/* </div>*/}
{/*</div>*/}
{/*<div className="field w-full mb-6">*/}
{/* <h1 className="field-title">*/}
{/* Properties*/}
{/* <span className="text-thin-light-gray font-normal ml-2">*/}
{/* (Optional)*/}
{/* </span>*/}
{/* </h1>*/}
{/* <div className="input-field my-2">*/}
{/* <div className="mb-2">*/}
{/* <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}*/}
{/* value={datas.propertiesKey}*/}
{/* placeholder="Enter key"*/}
{/* />*/}
{/* </div>*/}
{/* <div className="flex-1">*/}
{/* <InputCom*/}
{/* fieldClass="px-6"*/}
{/* type="text"*/}
{/* name="link"*/}
{/* inputHandler={valueHndlr}*/}
{/* value={datas.propertiesValue}*/}
{/* placeholder="Enter Value"*/}
{/* />*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/*</div>*/}
{/*<div className="field w-full mb-6">*/}
{/* <h1 className="field-title">Choose collection</h1>*/}
{/* <div className="input-field mt-2">*/}
{/* <div className="sm:flex sm:space-x-5">*/}
{/* /!* create collection *!/*/}
{/* <div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border border-light-purple dark:border-[#5356fb29] flex justify-center items-center cursor-pointer">*/}
{/* <div>*/}
{/* <span className="mb-1 flex justify-center">*/}
{/* <svg*/}
{/* width="25"*/}
{/* height="25"*/}
{/* viewBox="0 0 25 25"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <path*/}
{/* d="M25 12.5125C25.019 19.39 19.3853 24.9989 12.5054 25.0001C5.6017 25.0012 -0.0153836 19.3615 3.1653e-05 12.471C0.0154469 5.59949 5.63965 -0.0224583 12.5469 6.7456e-05C19.396 0.0225932 25.0297 5.61846 25 12.5125ZM14.3007 17.2097C14.3007 16.3324 14.3007 15.4551 14.3007 14.5778C14.3007 14.3525 14.3007 14.3525 14.5224 14.3525C16.2299 14.3525 17.9387 14.3525 19.6462 14.3513C19.7339 14.3513 19.8241 14.349 19.9106 14.3335C20.832 14.1711 21.4581 13.327 21.3798 12.356C21.3099 11.4775 20.4988 10.733 19.6011 10.7306C17.9031 10.7271 16.2062 10.7294 14.5082 10.7294C14.2995 10.7294 14.2995 10.7294 14.2995 10.5243C14.2995 8.7851 14.2995 7.04588 14.2983 5.30784C14.2983 5.22959 14.2983 5.15016 14.2805 5.07547C14.0588 4.16021 13.218 3.59588 12.3465 3.68599C11.3836 3.78676 10.697 4.55026 10.697 5.48212C10.697 7.14309 10.697 8.80288 10.697 10.4639C10.697 10.7555 10.7243 10.7294 10.4243 10.7294C8.79504 10.7294 7.16457 10.7401 5.5353 10.7259C4.40524 10.7152 3.60483 11.6293 3.63922 12.6216C3.67242 13.5451 4.45623 14.3513 5.37996 14.3513C7.08275 14.3513 8.78555 14.3513 10.4883 14.3513C10.697 14.3513 10.697 14.3525 10.697 14.5576C10.697 16.2387 10.697 17.9211 10.697 19.6022C10.697 19.6757 10.6935 19.7492 10.703 19.8215C10.8761 21.1256 12.2884 21.8358 13.4255 21.1719C13.9817 20.847 14.3066 20.3586 14.3018 19.684C14.2947 18.86 14.3007 18.0349 14.3007 17.2097Z"*/}
{/* fill="#374557"*/}
{/* fillOpacity="0.6"*/}
{/* />*/}
{/* </svg>*/}
{/* </span>*/}
{/* <span className="text-thin-light-gray text-center">*/}
{/* Crteate*/}
{/* </span>*/}
{/* </div>*/}
{/* </div>*/}
{/* /!* saved collection list *!/*/}
{/* <div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border-gradient flex justify-center items-center cursor-pointer">*/}
{/* <div>*/}
{/* <div className="mb-1 flex justify-center ">*/}
{/* <div className="w-[50px] h-[50px] rounded-full overflow-hidden">*/}
{/* <img*/}
{/* src={collection1}*/}
{/* alt=""*/}
{/* className="w-full h-full object-cover"*/}
{/* />*/}
{/* </div>*/}
{/* </div>*/}
{/* <span className="text-thin-light-gray text-center">*/}
{/* Name 1*/}
{/* </span>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border border-light-purple dark:border-[#5356fb29] flex justify-center items-center cursor-pointer">*/}
{/* <div>*/}
{/* <div className="mb-1 flex justify-center ">*/}
{/* <div className="w-[50px] h-[50px] rounded-full overflow-hidden">*/}
{/* <img*/}
{/* src={collection2}*/}
{/* alt=""*/}
{/* className="w-full h-full object-cover"*/}
{/* />*/}
{/* </div>*/}
{/* </div>*/}
{/* <span className="text-thin-light-gray text-center">*/}
{/* Name 2*/}
{/* </span>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div className="sm:w-[100px] h-[100px] w-full mb-2 sm:mb-0 rounded-[4px] bg-[#FAFAFA] dark:bg-[#11131F] border border-light-purple dark:border-[#5356fb29] flex justify-center items-center cursor-pointer">*/}
{/* <div>*/}
{/* <div className="mb-1 flex justify-center ">*/}
{/* <div className="w-[50px] h-[50px] rounded-full overflow-hidden">*/}
{/* <img*/}
{/* src={collection3}*/}
{/* alt=""*/}
{/* className="w-full h-full object-cover"*/}
{/* />*/}
{/* </div>*/}
{/* </div>*/}
{/* <span className="text-thin-light-gray text-center">*/}
{/* Name 3*/}
{/* </span>*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/*</div>*/}
{/* unlock purchase */}
<div className="sm:flex justify-between items-center mb-5">
<div className="sm:flex sm:space-x-3 items-center mb-5 sm:mb-0">
<div className="w-[60px] h-[60px] rounded-full flex justify-center items-center bg-light-gray">
<svg
width="22"
height="28"
viewBox="0 0 22 28"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.9703 27.9959C8.44944 27.9959 5.92858 28.0078 3.40773 27.9919C1.27205 27.9799 0.0338085 26.7656 0.0196917 24.6347C-0.00450854 21.2735 -0.00854192 17.9123 0.0196917 14.5511C0.0378419 12.4521 1.3265 11.2158 3.44806 11.2118C8.42121 11.2019 13.3964 11.2039 18.3695 11.2118C20.604 11.2158 21.8564 12.4641 21.8644 14.6909C21.8745 17.9862 21.8786 21.2815 21.8644 24.5767C21.8544 26.7616 20.6242 27.9819 18.43 27.9939C15.9434 28.0058 13.4569 27.9959 10.9703 27.9959ZM8.53213 17.9722C8.61078 18.1699 8.65918 18.789 8.99193 19.0466C9.89541 19.7476 9.75424 20.6544 9.75626 21.567C9.75626 21.9984 9.62719 22.5057 9.81071 22.8412C10.0467 23.2706 10.5367 23.8358 10.9219 23.8398C11.3131 23.8438 11.8496 23.3026 12.0613 22.8752C12.261 22.4698 12.1319 21.9006 12.1319 21.4053C12.1319 20.5525 12.0936 19.7716 12.868 19.0706C13.6041 18.4036 13.4871 17.1354 12.8841 16.3086C12.2811 15.4817 11.2002 15.1262 10.2019 15.4258C9.25208 15.7114 8.54826 16.6621 8.53213 17.9722Z"
fill="black"
/>
<path
d="M18.5315 10.2691C17.3356 10.2691 16.2466 10.2691 15.0345 10.2691C15.0345 9.40439 15.0446 8.58556 15.0325 7.76473C14.9982 5.32022 13.2397 3.47086 10.9467 3.45888C8.64969 3.4469 6.88509 5.28028 6.84476 7.73677C6.83064 8.55959 6.84274 9.38441 6.84274 10.2672C5.64483 10.2672 4.55582 10.2672 3.47286 10.2672C2.71257 5.3322 4.5054 1.66744 8.75456 0.347323C13.5603 -1.14654 18.3984 2.36244 18.5274 7.34932C18.5516 8.30396 18.5315 9.26059 18.5315 10.2691Z"
fill="black"
/>
</svg>
</div>
<div>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
Unlock once purchased
</h1>
<p className="text-base text-thin-light-gray tracking-wide">
Unlockable content, only revealed by the owner of the item.
</p>
</div>
</div>
<div>
<SwitchCom value={datas.purchase} handler={unlckPrchesHndlr} />
</div>
</div>
{/*<div className="sm:flex justify-between items-center mb-5">*/}
{/* <div className="sm:flex sm:space-x-3 items-center mb-5 sm:mb-0">*/}
{/* <div className="w-[60px] h-[60px] rounded-full flex justify-center items-center bg-light-gray">*/}
{/* <svg*/}
{/* width="22"*/}
{/* height="28"*/}
{/* viewBox="0 0 22 28"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <path*/}
{/* d="M10.9703 27.9959C8.44944 27.9959 5.92858 28.0078 3.40773 27.9919C1.27205 27.9799 0.0338085 26.7656 0.0196917 24.6347C-0.00450854 21.2735 -0.00854192 17.9123 0.0196917 14.5511C0.0378419 12.4521 1.3265 11.2158 3.44806 11.2118C8.42121 11.2019 13.3964 11.2039 18.3695 11.2118C20.604 11.2158 21.8564 12.4641 21.8644 14.6909C21.8745 17.9862 21.8786 21.2815 21.8644 24.5767C21.8544 26.7616 20.6242 27.9819 18.43 27.9939C15.9434 28.0058 13.4569 27.9959 10.9703 27.9959ZM8.53213 17.9722C8.61078 18.1699 8.65918 18.789 8.99193 19.0466C9.89541 19.7476 9.75424 20.6544 9.75626 21.567C9.75626 21.9984 9.62719 22.5057 9.81071 22.8412C10.0467 23.2706 10.5367 23.8358 10.9219 23.8398C11.3131 23.8438 11.8496 23.3026 12.0613 22.8752C12.261 22.4698 12.1319 21.9006 12.1319 21.4053C12.1319 20.5525 12.0936 19.7716 12.868 19.0706C13.6041 18.4036 13.4871 17.1354 12.8841 16.3086C12.2811 15.4817 11.2002 15.1262 10.2019 15.4258C9.25208 15.7114 8.54826 16.6621 8.53213 17.9722Z"*/}
{/* fill="black"*/}
{/* />*/}
{/* <path*/}
{/* d="M18.5315 10.2691C17.3356 10.2691 16.2466 10.2691 15.0345 10.2691C15.0345 9.40439 15.0446 8.58556 15.0325 7.76473C14.9982 5.32022 13.2397 3.47086 10.9467 3.45888C8.64969 3.4469 6.88509 5.28028 6.84476 7.73677C6.83064 8.55959 6.84274 9.38441 6.84274 10.2672C5.64483 10.2672 4.55582 10.2672 3.47286 10.2672C2.71257 5.3322 4.5054 1.66744 8.75456 0.347323C13.5603 -1.14654 18.3984 2.36244 18.5274 7.34932C18.5516 8.30396 18.5315 9.26059 18.5315 10.2691Z"*/}
{/* fill="black"*/}
{/* />*/}
{/* </svg>*/}
{/* </div>*/}
{/* <div>*/}
{/* <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
{/* Unlock once purchased*/}
{/* </h1>*/}
{/* <p className="text-base text-thin-light-gray tracking-wide">*/}
{/* Unlockable content, only revealed by the owner of the item.*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div>*/}
{/* <SwitchCom value={datas.purchase} handler={unlckPrchesHndlr} />*/}
{/* </div>*/}
{/*</div>*/}
</form>
</div>
</div>
+188 -31
View File
@@ -5,8 +5,15 @@ import ModalCom from "../Helpers/ModalCom";
import Layout from "../Partials/Layout";
// import DropFileWidget from "./DropFileWidget";
import ProductUploadField from "./ProductUploadField";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import usersService from "../../services/UsersService";
import { useNavigate } from "react-router-dom";
export default function UploadProduct({uploadTypes}) {
const apiCall = new usersService()
const [requestStatus, setRequestStatus] = useState({loading: false, status: null, message: ''}) // DETERMINES THE STATUS OF UPLOAD
const navigate = useNavigate()
export default function UploadProduct() {
// preview modal
const [previewProductModal, setPreviewProductModal] = useState(false);
// cancelUploadModal
@@ -68,23 +75,34 @@ export default function UploadProduct() {
};
const fileSelect = useRef(null);
const fileRef = useRef(null);
const [selectedFile, setSelectedFile] = useState("");
const [selectedFile, setSelectedFile] = useState('');
// const [selectedFile, setSelectedFile] = useState({name: '', size: ''});
const [img, setImg] = useState(null);
const [imgDetails, setImgDetails] = useState('')
const changeFile = (e, file) => {
if (e) {
let uploadedFileType = e.target.files[0].type.split("/")[0].toLowerCase();
setSelectedFile(e.target.files[0].name);
setImgDetails(e?.target?.files[0])
const imgRead = new FileReader();
imgRead.onload = (event) => {
setImg(event.target.result);
// setImg(event.target.result);
setImg({ type: uploadedFileType, file: event.target.result });
};
// most importend
imgRead.readAsDataURL(e.target.files[0]);
}
if (file) {
if (file?.length) {
let uploadedFileType = file[0].type.split("/")[0].toLowerCase();
if (file[0].name) {
setSelectedFile(file[0].name);
setSelectedFile(file?.[0].name);
setImgDetails(file?.[0])
const imgRead = new FileReader();
imgRead.onload = (event) => {
setImg(event.target.result);
// setImg(event.target.result);
setImg({ type: uploadedFileType, file: event.target.result });
};
// most importend
imgRead.readAsDataURL(file[0]);
@@ -92,6 +110,85 @@ export default function UploadProduct() {
}
};
//FUNCTION TO UPLOAD ITEM
const uploadItem = () => {
let errorArr = []
let uploadInfo = { // SUBMITTED DETAILS FROM USER
img,
itemName,
description
}
//LOOPS THROUGH ITEM DETAILS FOR EMPTINESS
for(let info in uploadInfo){
if(!uploadInfo[info]){
errorArr.push(info)
}
}
// TEST TO SEE IF FIELDS ARE EMPTY
if(errorArr.length){
let message = ''
if(errorArr.length == 1 && errorArr.includes('img')){
message='Please select file to upload'
}else if (errorArr.length == 1 && !errorArr.includes('img')){
message='Item name or description cannot be empty'
}else if (errorArr.length > 1 && errorArr.includes('img')){
message='Please select file to upload & Item name/description cannot be empty'
}else {
message='Item name/description cannot be empty'
}
setRequestStatus({loading: false, status: null, message})
return setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
},5000)
}
let reqData = { // PAYLOAD FOR API CALL
file_name: selectedFile.substring(0,21).replace(/ /gi, ""),//selectedFile.replace(/[ -]/gi, ""),
file_size: imgDetails.size,
file_type: imgDetails.type,
file_data: img.file,
title: itemName,
description: description,
msg_type: 'FILE',
// action: 'WRENCHBOARD_RESOURCE_MYFILES',
action: 11307
}
if(!isValidFile(imgDetails, uploadTypes?.data)){ // FUNCTION TO CHECK IF FILE TYPE IS VALID
setRequestStatus({loading: false, status: null, message: 'File type not supported'})
return setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
},5000)
}
let validSize = isValidFileSize(imgDetails, uploadTypes?.data) // FUNCTION TO CHECK IF FILE SIZE IS VALID
if(!validSize.status){
setRequestStatus({loading: false, status: null, message: validSize.message})
return setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
},5000)
}
// API CALL TO UPLOAD COMES HERE
setRequestStatus({loading: true, status: null, message: ''}) // SETS REQUEST LOADING TRUE
apiCall.sendFiles(reqData).then(res=>{
if(res.status != 200 || res.data.internal_return < 0){
return setRequestStatus({loading: false, status: false, message: 'Something went wrong, try again'})
}
setRequestStatus({loading: false, status: true, message: 'Uploaded successfully'})
setImg('')
setItemName('')
setDescription('')
}).catch(error=>{
setRequestStatus({loading: false, status: false, message: 'Network error, try again'})
}).finally(()=>{
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
},5000)
})
}
// drop event
function handleDrop(e) {
const dt = e.dataTransfer;
@@ -167,7 +264,7 @@ export default function UploadProduct() {
{/* heading */}
<div className="mb-6">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Create new item
{requestStatus.status == null ? 'Create new item' : 'Upload new item'}
</h1>
</div>
{/**
@@ -178,11 +275,18 @@ export default function UploadProduct() {
{/* section-heading */}
<div className="section-heading w-full mb-5 lg:px-9 px-4 lg:pt-9 pt-5 ">
<h1 className="text-dark-gray dark:text-white lg:text-26 text-18 font-bold tracking-wide mb-1">
Image,Video,Audio or 3D Model
Image,Video,Audio or Documents
</h1>
<p className="text-thin-light-gray text-base tracking-wide font-medium">
File types suppported: JPG, PNG, GIP, SVG, MP4, MP3, WEBM,
OGG, GLB, GLTF. Max Size : 100 MB
File types supported: {uploadTypes.loading && <span className="italic">loading...</span>}
{/* JPG, PNG, GIP, SVG, MP4, MP3, WEBM, OGG, GLB, GLTF */}
{uploadTypes?.data?.length ?
uploadTypes?.data?.map((item, index) => {
return index != uploadTypes.data.length-1 ? `${item.name}, ` : `${item.name}`
})
:
null
}
</p>
</div>
<div className="main-content w-full lg:flex justify-between lg:px-9 px-4">
@@ -193,17 +297,29 @@ export default function UploadProduct() {
>
{img ? (
<div className="w-full h-full">
<img
src={img}
alt=""
className="w-full h-full object-cover"
/>
{img.type === "image" ? (
<img
src={img.file}
alt=""
className="w-full h-full object-cover"
/>
) : img.type === "video" ? (
<video
type=""
src={img.file}
className="w-full h-full object-cover"
controls
></video>
) : img.type != null ? (
<p>{selectedFile}</p>
) : null}
<input
type="file"
id="fileElem"
name="file"
className="hidden"
accept="image/*"
// accept="image/*"
ref={fileRef}
value={selectedFile.name}
onChange={(e) => changeFile(e)}
@@ -260,7 +376,7 @@ export default function UploadProduct() {
id="fileElem"
name="file"
className="hidden"
accept="image/*"
// accept="image/*"
ref={fileRef}
value={selectedFile.name}
onChange={(e) => changeFile(e)}
@@ -289,31 +405,38 @@ export default function UploadProduct() {
</div>
</div>
{/* bottom action */}
<div className="w-full h-[120px] bg-red border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="w-full h-[120px] bg-red border-t border-light-purple dark:border-[#5356fb29] flex justify-between items-center">
<p className={`px-4 text-sm sm:text-lg ${requestStatus.status ? 'text-green-500' : 'text-red-500'} tracking-wide`}>{requestStatus.message && requestStatus.message}</p>
<div className="flex sm:space-x-4 space-x-2 sm:mr-9 mr-2">
<button
type="button"
onClick={cancelUploadModalHandler}
// onClick={cancelUploadModalHandler}
onClick={()=>navigate('/resources', {state:{tab:'created'}})}
className="sm:text-18 text-sm text-light-red tracking-wide "
>
<span className="border-b dark:border-[#5356fb29] border-light-red">
{" "}
Cancel
{requestStatus.status == null ? 'Cancel' : 'Return'}
</span>
</button>
{/*<button*/}
{/* onClick={() => previewUploadProduct(data)}*/}
{/* type="button"*/}
{/* className="sm:w-[126px] h-[46px] w-[100px] flex justify-center items-center border-gradient sm:text-18 text-sm rounded-full text-back"*/}
{/*>*/}
{/* <span className="text-gradient"> Preview</span>*/}
{/*</button>*/}
{requestStatus.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button
onClick={() => previewUploadProduct(data)}
type="button"
className="sm:w-[126px] h-[46px] w-[100px] flex justify-center items-center border-gradient sm:text-18 text-sm rounded-full text-back"
>
<span className="text-gradient"> Preview</span>
</button>
<Link
to="/"
// to="/"
onClick={uploadItem}
className="sm:w-[126px] h-[46px] w-[100px] flex justify-center items-center btn-gradient sm:text-18 text-sm rounded-full text-white"
>
Create Now
</Link>
Upload
</button>
}
</div>
</div>
@@ -327,7 +450,7 @@ export default function UploadProduct() {
<div className="preview-upload-product lg:w-[580px] lg:h-[622px] w-full h-full bg-white dark:bg-[#11131F] lg:rounded-2xl">
<div className="w-full h-full flex flex-col justify-between">
{/* heading */}
<div className="lg:px-[40px] lg:py-[33px] px-[30px] py-[23px] flex justify-between border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] mb-4 lg:mb-0">
<div className="lg:px-[40px] lg:py-[33px] px-[30px] py-[23px] flex justify-between border-b border-light-purple dark:border-[#5356fb29] mb-4 lg:mb-0">
<h1 className="text-dark-gray dark:text-white tracking-wide text-26 font-bold">
Item Privew
</h1>
@@ -473,3 +596,37 @@ export default function UploadProduct() {
</>
);
}
//FUNCTIONS to check if file upload type is valid
const isValidFile = (file, supportedFile=[]) => {
let fileType = file.type.split("/")[1];
let valid = supportedFile.filter(item => (
item.name.toLowerCase() == fileType.toLowerCase()
))
if(valid.length){
return true
}else{
return false
}
}
//FUNCTIONS TO CHECK IF FILE SIZE IS VALID
const isValidFileSize = (file, supportedFile=[]) => {
let fileType = file.type.split("/")[1];
let fileSize = file.size;
let valid = supportedFile.filter(item => (
item.name.toLowerCase() == fileType.toLowerCase()
))
if(valid.length){
if((Number(valid[0].max_size_mb) * 1048576) >= fileSize){
return {status: true}
}else{
return {status: false, message: `File must not exceed ${valid[0].max_size_mb}MB`}
}
}else{
return false
}
}
+1 -1
View File
@@ -103,7 +103,7 @@ function DeleteJobPopout({ details, onClose, situation }) {
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="68" cy="68" r="68" fill="#5356FB" />
<circle cx="68" cy="68" r="68" fill="#4687ba" />
<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"
+17 -14
View File
@@ -1,11 +1,11 @@
import { Field, Form, Formik } from "formik";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import Detail from "./popoutcomponent/Detail";
import ModalCom from "../Helpers/ModalCom";
import InputCom from "../Helpers/Inputs/InputCom/index";
import SiteService from "../../services/SiteService";
import { Form, Formik, Field } from "formik";
import * as Yup from "yup";
import SiteService from "../../services/SiteService";
import InputCom from "../Helpers/Inputs/InputCom/index";
import ModalCom from "../Helpers/ModalCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import Detail from "./popoutcomponent/Detail";
const validationSchema = Yup.object().shape({
family: Yup.string().required("This is required "),
@@ -202,7 +202,7 @@ function JobListPopout({ details, onClose, situation }) {
</svg>
</button>
</div>
<div className="md:flex bg-white rounded-lg shadow-lg">
<div className="md:flex bg-white dark:bg-dark-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> */}
@@ -225,17 +225,17 @@ function JobListPopout({ details, onClose, situation }) {
<div className="my-3 md:flex">
<Detail
label="Created"
value={`Dummy, no value found for created!`}
/>
value={new Date(details?.created).toDateString()}
/>
</div>
<div className="my-3">
<label className="w-full text-slate-900 tracking-wide font-semibold">
<label className="w-full text-slate-900 dark:text-white 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"
className={`p-2 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="7"
style={{ resize: "none" }}
value={textArea}
onChange={handleInputChange}
@@ -322,7 +322,7 @@ function JobListPopout({ details, onClose, situation }) {
input={true}
inputName="individual"
value={props?.values.individual}
placeholder="enter email of individual"
placeholder="Enter email of individual"
inputHandler={props?.handleChange}
btnText="Send Offer to Individual"
loader={loader?.jobFields.individual}
@@ -396,7 +396,7 @@ const JobFieldInput = ({
data,
}) => {
return (
<div className="field w-full p-3 mb-2 bg-red-50 rounded-md">
<div className="field w-full p-3 mb-2 bg-red-50 dark:bg-[#D85A5A] rounded-md">
{select && (
<>
<div className={`input-com ${parentClass}`}>
@@ -468,7 +468,10 @@ const JobFieldInput = ({
type="submit"
name={inputName}
onClick={errorHandler}
className="px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md"
className={`px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md ${
!value && "disabled:grayscale-[65%] transition duration-300"
}`}
disabled={!value}
>
{loader ? <LoadingSpinner size={5} /> : btnText}
</button>
+89 -75
View File
@@ -1,11 +1,11 @@
import React, { useMemo, useState } from "react";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import usersService from "../../services/UsersService";
import ModalCom from "../Helpers/ModalCom";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import Detail from "./popoutcomponent/Detail";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { tableReload } from "../../store/TableReloads";
@@ -18,85 +18,95 @@ const showSuccessToast = (message) => {
};
function PendingJobsPopout({ details, onClose, situation }) {
const dispatch = useDispatch()
const navigate = useNavigate()
const dispatch = useDispatch();
const navigate = useNavigate();
const [pendingJobLoader, setPendingJobLoader] = useState({
extend: false,
offer: false,
});
let [requestMessage, setRequestMessage] = useState({status: false, message: ''})
let [requestMessage, setRequestMessage] = useState({
status: false,
message: "",
});
const apiCall = new usersService();
const handlePendingJobsBtn = ({ target: { name } }) => {
let { job_uid, offer_code } = details;
let { job_uid, offer_code } = details;
let reqData;
let reqData;
let pendingData = { job_uid, offer_code };
if(name=='extend'){ // RUNS THIS TO EXTEND JOB EXPIRY BY ONE WEEK
reqData = { ...pendingData };
setPendingJobLoader({ extend: true });
apiCall.pendingJobExtend(reqData).then(res => {
setRequestMessage({status: true, message: res.data.status})
let pendingData = { job_uid, offer_code };
if (name == "extend") {
// RUNS THIS TO EXTEND JOB EXPIRY BY ONE WEEK
reqData = { ...pendingData };
setPendingJobLoader({ extend: true });
apiCall
.pendingJobExtend(reqData)
.then((res) => {
setRequestMessage({ status: true, message: res.data.status });
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
setRequestMessage({ status: false, message: "" });
onClose();
dispatch(tableReload({ type: "PENDINGTABLE" }));
}, 4000);
}).catch(error => {
setRequestMessage({status: false, message:'Try Again'})
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
}, 3000);
})
}else if(name=='offer'){ // RUNS THIS IF JOB IS SENT TO USER
reqData = { ...pendingData };
setPendingJobLoader({ offer: true });
apiCall.pendingJobSendTome(reqData).then(res => {
setRequestMessage({status: true, message: res.data.status})
.catch((error) => {
setRequestMessage({ status: false, message: "Try Again" });
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
setRequestMessage({ status: false, message: "" });
}, 3000);
});
} else if (name == "offer") {
// RUNS THIS IF JOB IS SENT TO USER
reqData = { ...pendingData };
setPendingJobLoader({ offer: true });
apiCall
.pendingJobSendTome(reqData)
.then((res) => {
setRequestMessage({ status: true, message: res.data.status });
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({ status: false, message: "" });
}, 4000);
}).catch(error => {
setRequestMessage('Try Again')
})
.catch((error) => {
setRequestMessage("Try Again");
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
setRequestMessage({ status: false, message: "" });
}, 3000);
})
} else return
// try {
// if (name === "extend") {
// setPendingJobLoader({ extend: true });
// reqData = { ...pendingData };
// // let { data } =
// await apiCall.pendingJobExtend(reqData);
// showSuccessToast("Job has been extended by a week!");
// dispatch(tableReload({ type: "PENDINGTABLE" }));
// } else if (name === "offer") {
// setPendingJobLoader({ offer: true });
// reqData = { ...pendingData };
// // let { data } =
// await apiCall.pendingJobSendTome(reqData);
// showSuccessToast("Offer sent, check your email");
// } else return;
});
} else return;
// try {
// if (name === "extend") {
// setPendingJobLoader({ extend: true });
// reqData = { ...pendingData };
// // let { data } =
// await apiCall.pendingJobExtend(reqData);
// showSuccessToast("Job has been extended by a week!");
// dispatch(tableReload({ type: "PENDINGTABLE" }));
// } else if (name === "offer") {
// setPendingJobLoader({ offer: true });
// reqData = { ...pendingData };
// // let { data } =
// await apiCall.pendingJobSendTome(reqData);
// showSuccessToast("Offer sent, check your email");
// } else return;
// setTimeout(() => {
// setPendingJobLoader({ extend: false, offer: false });
// onClose();
// }, 2700);
// } catch (error) {
// setPendingJobLoader({ extend: false, offer: false });
// throw new Error(error);
// }
}
// setTimeout(() => {
// setPendingJobLoader({ extend: false, offer: false });
// onClose();
// }, 2700);
// } catch (error) {
// setPendingJobLoader({ extend: false, offer: false });
// throw new Error(error);
// }
};
return (
<ModalCom action={onClose} situation={situation} className="edit-popup">
@@ -131,9 +141,9 @@ function PendingJobsPopout({ details, onClose, situation }) {
</svg>
</button>
</div>
<div className="md:flex bg-white rounded-lg shadow-lg">
<div className="md:flex bg-white dark:bg-dark-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">
<p className="text-base font-semibold text-slate-900 dark:text-white tracking-wide">
{details.title}
</p>
<div className="my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300">
@@ -177,7 +187,11 @@ function PendingJobsPopout({ details, onClose, situation }) {
<Detail
label="Price"
// value={`${details.price * 0.01} ${details.currency}`}
value={PriceFormatter(details.price * 0.01, details?.currency_code, details.currency)}
value={PriceFormatter(
details.price * 0.01,
details?.currency_code,
details.currency
)}
/>
</div>
@@ -194,19 +208,11 @@ function PendingJobsPopout({ details, onClose, situation }) {
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>
<p className="mb-6 text-sm dark:text-white">Actions</p>
<div className="mb-3">
<p className="px-2 py-1 text-sm bg-slate-100">
@@ -229,11 +235,15 @@ function PendingJobsPopout({ details, onClose, situation }) {
)}
</button>
</div>
{pendingJobLoader.extend && requestMessage.message &&
<div className={`p-1 ${requestMessage.status ? 'bg-green-500':'bg-red-500'} text-white rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{pendingJobLoader.extend && requestMessage.message && (
<div
className={`p-1 ${
requestMessage.status ? "bg-green-500" : "bg-red-500"
} text-white rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
<p>{requestMessage.message}</p>
</div>
}
)}
<div className="my-3">
<button
@@ -251,11 +261,15 @@ function PendingJobsPopout({ details, onClose, situation }) {
</button>
</div>
{pendingJobLoader.offer && requestMessage.message &&
<div className={`p-1 ${requestMessage.status ? 'bg-green-500':'bg-red-500'} text-white rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{pendingJobLoader.offer && requestMessage.message && (
<div
className={`p-1 ${
requestMessage.status ? "bg-green-500" : "bg-red-500"
} text-white rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
<p>{requestMessage.message}</p>
</div>
}
)}
<div className="mt-10 md:mt-32 md:flex md:justify-center">
<button
@@ -284,4 +298,4 @@ function PendingJobsPopout({ details, onClose, situation }) {
);
}
export default PendingJobsPopout;
export default PendingJobsPopout;
+1 -1
View File
@@ -303,7 +303,7 @@ input[type="text"][dir="rtl"] {
.sidebar-logo.enter {
transform: scale(1);
width: 100%;
width: 80%;
}
.sidebar-logo {
transform: scale(0);
+9
View File
@@ -0,0 +1,9 @@
export default function EmailValidator(email) {
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
if (regEx.test(email) == false) {
return false
}else{
return true
}
}
+9
View File
@@ -0,0 +1,9 @@
export default function PasswordValidator(password) {
const regEx = /^[a-zA-Z0-9!@#$%^&*()_+{}\[\]:;<>,.?~\\/\-='"`|]+$/;
if (/[!@#$%^&*()_+{}\[\]:;<>,.?~\\/\-='"`|]/.test(password) == false || /[0-9]/.test(password)==false || /[A-Z]/.test(password)==false || /[a-z]/.test(password)==false) {
return false
}else{
return true
}
}
+24 -1
View File
@@ -1,4 +1,4 @@
export default function formattedDate(dateString) {
export function formattedDate(dateString) {
const parts = dateString.split(" ");
const datePart = parts[0];
const timePart = parts[1];
@@ -15,3 +15,26 @@ export default function formattedDate(dateString) {
return new Date(year, month - 1, day, hour, minute);
}
export function formatDateString(inputDateString) {
// Parse the input date string
const parsedDate = new Date(inputDateString);
// Get day, month, year, and time components
const day = parsedDate.toLocaleDateString(undefined, { weekday: "long" });
const month = parsedDate.toLocaleDateString(undefined, { month: "short" });
const date = parsedDate.toLocaleDateString(undefined, { day: "numeric" });
const year = parsedDate.toLocaleDateString(undefined, { year: "numeric" });
// Get the time in 12-hour format with 'AM' or 'PM'
const hours = parsedDate.getHours();
const minutes = parsedDate.getMinutes();
const time = `${hours % 12 || 12}:${minutes.toString().padStart(2, "0")} ${
hours < 12 ? "AM" : "PM"
}`;
// Combine the components into the desired format
const formattedDate = `${day}, ${month} ${date} ${year} - ${time}`;
return formattedDate;
}
+2 -1
View File
@@ -1,12 +1,13 @@
import ClearCookies from "./ClearCookies";
import checkAndSetError from "./checkAndSetError";
import formattedDate from "./fomattedDate";
import { formatDateString, formattedDate } from "./fomattedDate";
import getTimeAgo from "./getTimeAgo";
import localImgLoad from "./localImgLoad";
export {
ClearCookies,
checkAndSetError,
formatDateString,
formattedDate,
getTimeAgo,
localImgLoad,
+22 -6
View File
@@ -2,7 +2,6 @@ import { useCallback, useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Navigate, Outlet, useNavigate } from "react-router-dom";
import LoadingSpinner from "../components/Spinners/LoadingSpinner";
import formattedDate from "../lib/fomattedDate";
import usersService from "../services/UsersService";
import { commonHeadBanner } from "../store/CommonHeadBanner";
import { recentActivitiesData } from "../store/RecentActivitiesData";
@@ -10,6 +9,8 @@ import { updateUserDetails } from "../store/UserDetails";
import { updateJobs } from "../store/jobLists";
import { updateNotifications } from "../store/notifications";
import { updateUserJobList } from "../store/userJobList";
import { updateWalletDetails } from "../store/walletDetails";
import { formattedDate } from "../lib";
const AuthRoute = ({ redirectPath = "/login", children }) => {
const apiCall = useMemo(() => new usersService(), []);
@@ -19,13 +20,13 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
const [loadProfileDetails, setLoadProfileDetails] = useState([]);
const navigate = useNavigate();
const { jobListTable } = useSelector((state) => state.tableReload);
const { jobListTable, walletTable } = useSelector((state) => state.tableReload);
const {
userDetails: { username, uid },
userDetails: { username, uid, session },
} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
let loggedIn = username && uid ? true : false; // variable to determine if user is logged in
let loggedIn = username && session && uid ? true : false; // variable to determine if user is logged in
useEffect(() => {
//Removing Data stored at localStorage after session expires
@@ -149,7 +150,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
// sort: _sorted,
// header: _header,
// },
data: _sorted
data: _sorted,
})
);
})
@@ -177,6 +178,21 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
getMyJobList();
}, [jobListTable]);
useEffect(() => {
const getMyWalletList = async () => {
dispatch(updateWalletDetails({ loading: true, data:[] }));
try {
const res = await apiCall.getUserWallets();
console.log("wallet - >", res.data);
dispatch(updateWalletDetails({ loading: false, data:res.data?.result_list }));
} catch (error) {
dispatch(updateWalletDetails({ loading: false, data:[] }));
console.log("Error getting mode");
}
};
getMyWalletList();
}, [walletTable]);
useEffect(() => {
// Getting market data
const getMarketActiveJobList = async () => {
@@ -211,7 +227,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
.getRecentActivitiedData()
.then((res) => {
// debugger;
if (res.data?.internal_return < 0) {
if (res?.data?.internal_return < 0) {
return;
}
dispatch(recentActivitiesData(res.data));
+98 -92
View File
@@ -1,107 +1,113 @@
import React from "react";
import Axios from "axios";
class SiteService {
constructor() {
console.log("Er are here anyway");
}
// Blog Data {Get}
blogData() {
return this.getAuxEnd("/blogdata", null);
}
constructor() {
console.log("Er are here anyway");
}
// Blog Data {Get}
blogData() {
return this.getAuxEnd("/blogdata", null);
}
// Country Data {GET}
countryData() {
return this.getAuxEnd("/country", null);
}
// Country Data {GET}
countryData() {
return this.getAuxEnd("/country", null);
}
// Contact Data{POST}
contactData() {
return this.postAuxEnd("/contact", null)
}
// Contact Data{POST}
contactData() {
return this.postAuxEnd("/contact", null);
}
faqData() {
return this.getAuxEnd("/faq", null);
}
faqData() {
return this.getAuxEnd("/faq", null);
}
priceData() {
return this.getAuxEnd("/pricing", null);
}
priceData() {
return this.getAuxEnd("/pricing", null);
}
addFamily(reqData) {
return this.postAuxEnd('/familyadd', reqData)
}
addFamily(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 22015,
...reqData,
};
return this.postAuxEnd("/familyadd", postData);
}
familyListings(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData
};
return this.postAuxEnd('/familylist', postData)
}
familyListings(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/familylist", postData);
}
assignJobTask(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData
};
return this.postAuxEnd('/assigntask', postData)
}
assignJobTask(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/assigntask", postData);
}
//---------------------------------------- -----
//---------------------------------------- -----
// Unified call below
//---------------------------------------- -----
//---------------------------------------- -----
getAuxEnd(uri, reqData) {
const endPoint = process.env.REACT_APP_AUX_ENDPOINT + uri;
return Axios.get(endPoint)
.then((response) => {
// console.log(response);
// res = response;
// console.log("~~~~~~~ Toks2 GET ~~~~~~~~");
return response;
})
.catch((error) => {
if (error.response) {
//response status is an error code
console.log(error.response.status);
} else if (error.request) {
//response not received though the request was sent
console.log(error.request);
} else {
//an error occurred when setting up the request
console.log(error.message);
}
});
}
//---------------------------------------- -----
//---------------------------------------- -----
// Unified call below
//---------------------------------------- -----
//---------------------------------------- -----
getAuxEnd(uri, reqData) {
const endPoint = process.env.REACT_APP_AUX_ENDPOINT + uri;
return Axios.get(endPoint)
.then((response) => {
// console.log(response);
// res = response;
// console.log("~~~~~~~ Toks2 GET ~~~~~~~~");
return response;
})
.catch((error) => {
if (error.response) {
//response status is an error code
console.log(error.response.status);
} else if (error.request) {
//response not received though the request was sent
console.log(error.request);
} else {
//an error occurred when setting up the request
console.log(error.message);
}
});
}
postAuxEnd(uri, reqData) {
const endPoint = process.env.REACT_APP_AUX_ENDPOINT + uri;
return Axios.post(endPoint, reqData)
.then((response) => {
console.log(response);
// res = response;
console.log("~~~~~~~ Toks2 POST ~~~~~~~~");
return response;
})
.catch((error) => {
if (error.response) {
//response status is an error code
console.log(error.response.status);
} else if (error.request) {
//response not received though the request was sent
console.log(error.request);
} else {
//an error occurred when setting up the request
console.log(error.message);
}
});
}
postAuxEnd(uri, reqData) {
const endPoint = process.env.REACT_APP_AUX_ENDPOINT + uri;
return Axios.post(endPoint, reqData)
.then((response) => {
console.log(response);
// res = response;
console.log("~~~~~~~ Toks2 POST ~~~~~~~~");
return response;
})
.catch((error) => {
if (error.response) {
//response status is an error code
console.log(error.response.status);
} else if (error.request) {
//response not received though the request was sent
console.log(error.request);
} else {
//an error occurred when setting up the request
console.log(error.message);
}
});
}
}
export default SiteService;
+91 -58
View File
@@ -30,6 +30,16 @@ class usersService {
return this.postAuxEnd("/dashdata", postData);
}
getRecentActivities(){
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11202
};
return this.postAuxEnd("/recentactivities", postData);
}
logInUser(reqData) {
localStorage.setItem("session_token", ``);
return this.postAuxEnd("/userlogin", reqData);
@@ -86,6 +96,18 @@ class usersService {
return this.postAuxEnd("/loadprofile", null);
}
getUploadedList() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page: 1,
limit: 20,
action: 11309,
};
return this.postAuxEnd("/myfiles", postData);
}
getOffersList() {
var postData = {
uuid: localStorage.getItem("uid"),
@@ -226,7 +248,7 @@ class usersService {
return this.postAuxEnd("/sendmoneyfee", postData);
}
// Start Credit for Cards
// Start Credit for Cards
getStartCredit(value) {
var postData = {
uid: localStorage.getItem("uid"),
@@ -346,6 +368,7 @@ class usersService {
page: 0,
offset: 0,
limit: 100,
allstatus: 0
};
return this.postAuxEnd("/activetaskslist", postData);
}
@@ -577,7 +600,7 @@ class usersService {
return this.postAuxEnd("/familymanage", postData);
}
// END POINT CALL FOR ACCOUNT TOP
// END POINT CALL FOR ACCOUNT TOP
startTopUp(post) {
alert("WHY ARE WE CALLING THIS ?");
// var postData = {
@@ -591,7 +614,6 @@ class usersService {
// return this.postAuxEnd("/starttopup", postData);
}
resultTopUp(post) {
var postData = {
uid: localStorage.getItem("uid"),
@@ -600,7 +622,7 @@ class usersService {
action: 11061,
...post,
};
console.log("topupresult",postData);
console.log("topupresult", postData);
return this.postAuxEnd("/topupresult", postData);
}
@@ -972,64 +994,75 @@ class usersService {
return this.postAuxEnd("/familysuggestlist", postData);
}
// FUNCTION TO CHANGE PROFILE PASSWORD
profilePassChange(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11005,
...reqData,
};
return this.postAuxEnd("/profilepasschange", postData);
}
// FUNCTION TO CHANGE PROFILE PASSWORD
profilePassChange(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11005,
...reqData,
};
return this.postAuxEnd("/profilepasschange", postData);
}
// FUNCTION TO GET ACCOUNT SETTINGS
getAccSettings() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11059,
};
return this.postAuxEnd("/getaccsettings", postData);
}
// FUNCTION TO GET ACCOUNT SETTINGS
getAccSettings() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11059,
};
return this.postAuxEnd("/getaccsettings", postData);
}
// FUNCTION TO SET ACCOUNT SETTINGS
setAccSettings(reqdata) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11058,
...reqdata,
};
return this.postAuxEnd("/setaccsettings", postData);
}
// FUNCTION TO SET ACCOUNT SETTINGS
setAccSettings(reqdata) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11058,
...reqdata,
};
return this.postAuxEnd("/setaccsettings", postData);
}
// FUNCTION TO DELETE PAY CARD
payRemCard(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11057,
...reqData,
};
return this.postAuxEnd("/payremcard", postData);
}
// FUNCTION TO DELETE PAY CARD
payRemCard(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11057,
...reqData,
};
return this.postAuxEnd("/payremcard", postData);
}
// FUNCTION TO GET SINGLE BLOG ITEM
getSingleBlogData(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
limit: 4,
...reqData,
};
return this.postAuxEnd("/blogdata", postData);
}
getHomeRecent() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
limit: 30,
offset: 0,
action: 11202,
};
return this.postAuxEnd("/recentactivities", postData);
}
// FUNCTION TO GET SINGLE BLOG ITEM
getSingleBlogData(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
limit: 4,
...reqData,
};
return this.postAuxEnd("/blogdata", postData);
}
/*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
+4
View File
@@ -7,6 +7,7 @@ const initialState = {
othersInterestedTable: false,
couponTable: false,
walletTable: false,
uploadsTable: false,
};
export const tableReloadSlice = createSlice({
@@ -33,6 +34,9 @@ export const tableReloadSlice = createSlice({
case "WALLETTABLE":
state.walletTable = !state.walletTable;
return;
case "UPLOADSTABLE":
state.uploadsTable = !state.uploadsTable;
return;
default:
return state;
}
+4 -4
View File
@@ -1,15 +1,15 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
userDetails: {}
userDetails: {},
};
export const userSlice = createSlice({
name: "userDetails",
initialState,
reducers: {
updateUserDetails: (state,action) => {
state.userDetails = {...action.payload}
updateUserDetails: (state, action) => {
state.userDetails = { ...action.payload };
},
},
});
@@ -17,4 +17,4 @@ export const userSlice = createSlice({
// Action creators are generated for each case reducer function
export const { updateUserDetails } = userSlice.actions;
export default userSlice.reducer;
export default userSlice.reducer;
+2
View File
@@ -7,6 +7,7 @@ import userDetailReducer from "./UserDetails";
import jobReducer from "./jobLists";
import notificationsReducer from "./notifications";
import userJobListReducer from "./userJobList";
import walletDetails from "./walletDetails";
export default configureStore({
reducer: {
@@ -17,5 +18,6 @@ export default configureStore({
userJobList: userJobListReducer,
commonHeadBanner: commonHeadBannerReducer,
notifications: notificationsReducer,
walletDetails: walletDetails
},
});
+21
View File
@@ -0,0 +1,21 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
walletDetails: {
loading: true,
data: []
},
};
export const walletSlice = createSlice({
name: "walletDetails",
initialState,
reducers: {
updateWalletDetails: (state, action) => {
state.walletDetails = { ...action.payload };
},
},
});
export const { updateWalletDetails } = walletSlice.actions;
export default walletSlice.reducer;
+15 -10
View File
@@ -5,27 +5,32 @@ import ModalCom from "../components/Helpers/ModalCom";
function AddJobPage({ action, situation, categories }) {
return (
<ModalCom action={action} situation={situation} className="edit-popup">
<div className="lg:w-[600px] w-full lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white ">
<div className="heading flex justify-between items-center py-6 md:px-[30px] px-[23px] border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] ">
<div className="lg:w-[600px] w-full lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white dark:text-white">
<div className="heading flex justify-between items-center py-6 md:px-[30px] px-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<p className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Create New Job
</p>
<button type="button" onClick={action}>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={action}
>
<svg
width="32"
height="32"
viewBox="0 0 32 32"
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M32 14.3645C32 15.5022 32 16.6399 32 17.7779C31.8143 17.8408 31.8787 18.0048 31.8565 18.1334C30.6952 24.8402 26.8853 29.2664 20.4091 31.362C19.4672 31.6668 18.4669 31.7917 17.4935 31.9997C16.3558 31.9997 15.2181 31.9997 14.0801 31.9997C13.8574 31.741 13.5279 31.7984 13.2475 31.7416C6.90872 30.4552 2.74424 26.7311 0.684152 20.6107C0.386668 19.7268 0.396442 18.7733 0 17.9199C0 16.6399 0 15.3598 0 14.0798C0.259 13.884 0.190585 13.5694 0.240675 13.3162C1.52285 6.84244 5.35655 2.66392 11.5936 0.623067C12.4549 0.34116 13.3785 0.343909 14.2221 0C15.3125 0 16.4029 0 17.4932 0C17.525 0.110258 17.6111 0.120948 17.7089 0.130417C24.2666 0.77242 29.8064 5.52819 31.449 11.9351C31.6552 12.739 31.8174 13.5542 32 14.3645ZM29.3431 16.0699C29.3718 8.68538 23.4154 2.66942 16.0684 2.66178C8.69759 2.65445 2.66972 8.58489 2.65353 15.8601C2.63704 23.2563 8.52319 29.2979 15.7868 29.3404C23.2862 29.3846 29.3144 23.4832 29.3431 16.0699Z"
fill="#374557"
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="M14.1604 16.0221C12.3843 14.2567 10.6724 12.5534 8.95837 10.8525C8.53353 10.431 8.23421 9.97162 8.46175 9.34031C8.83956 8.29209 9.95101 8.07371 10.794 8.906C12.3611 10.4536 13.9344 11.9963 15.4529 13.5909C15.9202 14.0817 16.1447 14.0005 16.5662 13.5643C18.0961 11.9804 19.6617 10.4307 21.2282 8.88248C22.0596 8.06058 23.208 8.30064 23.5522 9.35008C23.7584 9.97865 23.459 10.4383 23.0336 10.8619C21.489 12.3991 19.9531 13.9443 18.4088 15.4815C18.2421 15.6476 18.0408 15.779 17.8188 15.9558C19.629 17.7563 21.366 19.4676 23.0831 21.1987C23.934 22.0567 23.6875 23.2106 22.6072 23.556C21.9658 23.761 21.5223 23.4186 21.1067 23.0023C19.5502 21.444 17.9757 19.9031 16.448 18.3171C16.0616 17.9157 15.8854 17.9811 15.5375 18.3378C13.9835 19.9318 12.399 21.4956 10.8242 23.0692C10.4015 23.4916 9.94887 23.7768 9.30961 23.516C8.27819 23.0948 8.06073 22.0814 8.87591 21.2418C10.0307 20.0528 11.2118 18.8891 12.3895 17.7221C12.9588 17.1577 13.5462 16.6106 14.1604 16.0221Z"
fill="#374557"
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>
-1
View File
@@ -1,5 +1,4 @@
import MarketPlace from "../components/MarketPlace";
import { useSelector } from "react-redux";
export default function MarketPlacePage() {
+3 -1
View File
@@ -1,7 +1,9 @@
import React, { useState, useEffect } from "react";
import Resources from "../components/Resources";
import usersService from "../services/UsersService";
import { useLocation } from "react-router-dom";
export default function ResourcePage() {
const {state, pathname} = useLocation() // CHECKS IF THERE IS AN ACTIVE TAB WITH LINK BACK TO RESOURCES
const [MyResourceData, setMyResourceData] = useState([]);
const api = new usersService();
@@ -17,5 +19,5 @@ export default function ResourcePage() {
getMyResourceData();
}, []);
return <Resources MyResourceData={MyResourceData} />;
return <Resources MyResourceData={MyResourceData} activeTab={state ? state.tab : ''} />;
}
+18 -2
View File
@@ -1,6 +1,22 @@
import React from "react";
import React, { useEffect, useState } from "react";
import UploadProduct from "../components/UploadProduct";
import usersService from "../services/UsersService";
export default function UploadProductPage() {
return <UploadProduct />;
const [uploadTypes, setUploadTypes] = useState({loading: true, data: []});
const api = new usersService();
const getUploadTypes = async () => {
try {
const res = await api.getResourceList();
setUploadTypes({loading: false, data: res?.data?.upload_types.data});
} catch (error) {
setUploadTypes({loading: false, data: []});
throw new Error("Error getting mode");
}
};
useEffect(() => {
getUploadTypes();
}, []);
return <UploadProduct uploadTypes={uploadTypes} />;
}