Compare commits

...

223 Commits

Author SHA1 Message Date
victorAnumudu bce00b5c0e request message changed 2023-08-01 16:10:56 +01:00
ameye 312cd54f87 Merge branch 'pending-wrong-assign' of WrenchBoard/Users-Wrench into master 2023-08-01 14:47:44 +00:00
victorAnumudu a0c3437eae pending assign value changed 2023-08-01 15:42:28 +01:00
ameye 711226f913 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-08-01 11:07:16 +00:00
Ebube f46c6232b0 updated error scenario for the modal header 2023-08-01 12:05:27 +01:00
Ebube 172f0ccbce cleanup 2 2023-08-01 11:46:33 +01:00
Ebube a2047cc2de clean up 2023-08-01 11:41:57 +01:00
Ebube 6ea52e6481 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-08-01 11:38:26 +01:00
Ebube a7bbcfdc1b complete popup fixed 2023-08-01 11:37:56 +01:00
ameye ff28be3e70 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-08-01 09:24:46 +00:00
Ebube e91b4a4424 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-31 23:58:36 +01:00
Ebube 9960033b72 debounced success payment and and fixed credit refresh 2023-07-31 23:55:23 +01:00
ameye ef135f1a9b Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-31 17:56:15 +00:00
Ebube 1df6380c4a Correct Drop Down Style for naira withdrawal 2023-07-31 15:09:12 +01:00
Ebube fc8cf551e5 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-31 14:47:15 +01:00
Ebube b1feb0438a still testing 2023-07-31 14:46:29 +01:00
ameye a89649f774 Merge branch 'amount-alignment' of WrenchBoard/Users-Wrench into master 2023-07-31 13:36:56 +00:00
victorAnumudu b96e8a3ed5 Merged master into amount-alignment 2023-07-31 14:23:57 +01:00
victorAnumudu f3226a6cfc amount alignment changed 2023-07-31 14:22:55 +01:00
ameye ff4c503100 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-31 12:04:22 +00:00
Ebube f543a2d893 testing topupResult 2023-07-31 13:02:31 +01:00
ameye 41badd52be Merge branch 'list-alignment-fix' of WrenchBoard/Users-Wrench into master 2023-07-30 16:29:28 +00:00
victorAnumudu eeddd4e0a5 list alignment fixed 2023-07-30 06:10:44 +01:00
tokslaw ee4d136834 wrenchboard-logo-text + image added 2023-07-29 19:04:08 -04:00
tokslaw 283efa42b3 social comment added 2023-07-29 12:16:57 -04:00
tokslaw 5cbab4933c Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench 2023-07-29 12:13:14 -04:00
ameye 4de2181c18 Merge branch 'family-login-no-captcha' of WrenchBoard/Users-Wrench into master 2023-07-29 15:45:31 +00:00
ameye c8f0161a29 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-29 15:45:26 +00:00
tokslaw 60222b6d88 text error correction 2023-07-29 11:11:23 -04:00
victorAnumudu 9ea3963239 family login captcha removed 2023-07-29 12:25:25 +01:00
Ebube a87592623b Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-29 07:01:22 +01:00
Ebube bfcf53f763 Not selected should appear not selected 2023-07-29 07:00:50 +01:00
CHIEFSOFT\ameye df4489c6f2 removed start top up 2023-07-29 00:09:59 -04:00
CHIEFSOFT\ameye 37185812b4 Result added 2023-07-28 16:55:45 -04:00
ameye eb3e78244d Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-28 13:25:00 +00:00
Ebube b302d7ba57 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-28 14:22:18 +01:00
ameye d6c16169d9 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-28 13:18:31 +00:00
Ebube 57129da0bd changed tx_ref number 2023-07-28 13:58:10 +01:00
Ebube 9eaf7123d4 reverse 2023-07-28 13:56:23 +01:00
Ebube 096da29149 Changed tx_ref no 2023-07-28 13:51:48 +01:00
CHIEFSOFT\ameye c8331c51cf removed debugger 2023-07-28 08:20:04 -04:00
tokslaw 3b7618702b env text-spell error 2023-07-27 17:04:57 -04:00
Ebube 84968b4435 balance refresh bug for withdraw 2023-07-27 16:28:21 +01:00
Ebube 98f11a3d80 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Family-Tabs-Size-Fix 2023-07-27 16:18:29 +01:00
CHIEFSOFT\ameye 98d734e869 Post data 2023-07-27 11:17:15 -04:00
Ebube 47004fec8c Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Family-Tabs-Size-Fix 2023-07-27 16:05:17 +01:00
CHIEFSOFT\ameye 48ce89489e console log 2023-07-27 11:04:01 -04:00
CHIEFSOFT\ameye 1ce05a3be3 add fund page 2023-07-27 11:01:22 -04:00
Ebube 28ab1116e9 Added Credit Limit & Pending Jobs Bug & removed reload for credit 2023-07-27 11:34:27 +01:00
ameye 994060d929 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-26 15:57:24 +00:00
Ebube a5c62564b7 Fixed tasks banner breaking 2023-07-26 16:54:31 +01:00
Ebube 22e61d2b41 Enforced send limit 2023-07-26 15:49:04 +01:00
ameye 6ab5eae0c0 Merge branch 'email-input-size' of WrenchBoard/Users-Wrench into master 2023-07-26 14:26:05 +00:00
victorAnumudu 3fbb47ee82 email input character size increased 2023-07-26 14:39:16 +01:00
ameye 3327b2b0df Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-25 20:13:46 +00:00
Ebube ec204d0389 . 2023-07-25 20:50:56 +01:00
Ebube cb1259d2c8 Added loading height 2023-07-25 20:46:46 +01:00
Ebube 706cf141e7 Add Result Page 2023-07-25 20:26:33 +01:00
ameye 2229ebb9a0 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-25 11:17:32 +00:00
Ebube 05022c29b2 Remove the cause for the login error 2023-07-25 12:12:49 +01:00
ameye 9718cfc574 Merge branch 'job-listing-bug' of WrenchBoard/Users-Wrench into master 2023-07-25 10:39:59 +00:00
ameye aef082ac60 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-25 10:39:45 +00:00
victorAnumudu 754340fcba Merged master into job-listing-bug 2023-07-25 10:14:29 +01:00
Ebube 16afd4f90c Family Tab Sizes Fixed 2023-07-25 08:53:04 +01:00
ameye b69e2ff53b Merge branch 'blog-page' of WrenchBoard/Users-Wrench into master 2023-07-24 19:29:08 +00:00
victorAnumudu 4ac799f8c9 links to blog page added 2023-07-24 20:06:25 +01:00
ameye c93d3b61a6 Merge branch 'resource-ask-question' of WrenchBoard/Users-Wrench into master 2023-07-24 16:31:16 +00:00
ameye 4fb6dbf30f Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-24 16:31:10 +00:00
victorAnumudu 11dc8fc659 resource ask question implemented 2023-07-24 15:34:29 +01:00
Ebube 4876ba80c1 Changed name to back 2023-07-24 15:07:22 +01:00
Ebube 71f799d157 Checked Errors in Wallet Page and made some tiny fixes 2023-07-24 15:01:03 +01:00
ameye 77c538ca79 Merge branch 'balance-refresh' of WrenchBoard/Users-Wrench into master 2023-07-24 11:07:41 +00:00
victorAnumudu 6b473b5dc6 wallet refresh 2023-07-24 11:58:09 +01:00
ameye 6aa11793a5 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-24 10:14:18 +00:00
victorAnumudu e098eb4626 job listing pagination bug fixed 2023-07-24 07:46:41 +01:00
Ebube 4f8edc3998 Improved solution for the credit refresh bug 2023-07-24 06:28:48 +01:00
Ebube 7dd805b804 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-24 06:15:43 +01:00
Ebube 2aa1219ea9 updated payload for new account 2023-07-24 06:15:22 +01:00
ameye c1a17949f7 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-23 23:40:59 +00:00
Ebube 24302c7435 Added New Login 2023-07-23 23:59:20 +01:00
CHIEFSOFT\ameye 27f4fda129 Added images 2023-07-23 07:47:54 -04:00
ameye 7ddef6d52d Merge branch 'notification-menu-close' of WrenchBoard/Users-Wrench into master 2023-07-23 10:20:40 +00:00
victorAnumudu 187ac61396 logged information removed 2023-07-23 07:18:56 +01:00
victorAnumudu 31297efb5b closes notification menu when see all notifications is clicked 2023-07-23 07:15:25 +01:00
ameye f8d6475ff8 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-22 23:21:04 +00:00
Ebube 22a45ac15e Added some fixes 2023-07-23 00:12:26 +01:00
ameye 0489be5e69 Merge branch 'notifications' of WrenchBoard/Users-Wrench into master 2023-07-22 22:44:03 +00:00
victorAnumudu 0f8ef167bb Merge master into notifications 2023-07-22 23:15:30 +01:00
victorAnumudu aa6e3f4b94 notification bug fixed 2023-07-22 23:12:29 +01:00
ameye 68beda891b Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-22 21:20:55 +00:00
Ebube 61bef08a24 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-22 20:53:04 +01:00
Ebube a6409a037f ConfirmNairaWithdraw layout, payload adjustment and other style fixes 2023-07-22 20:52:39 +01:00
ameye f3ab8241a3 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-22 11:27:18 +00:00
Ebube f3defdca85 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-22 12:23:41 +01:00
Ebube f3b1a42819 Bug Fixes..Notification load, Withdraw css fix 2023-07-22 12:23:14 +01:00
ameye e65d538709 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-21 10:48:59 +00:00
Ebube 98aef302de Updated Layout for Withdraw Pop UP 2023-07-21 11:45:42 +01:00
ameye b3bbf11f0a Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-20 19:43:23 +00:00
Ebube 973517215f Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-20 20:25:32 +01:00
Ebube a3782e2dfc Added Notification and Started Wallet Withdraw 2023-07-20 20:24:54 +01:00
CHIEFSOFT\ameye 25830d5bf3 Resolve conflict 2023-07-20 06:25:51 -04:00
CHIEFSOFT\ameye 1615a7ac8a Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench
# Conflicts:
#	src/middleware/AuthRoute.jsx
2023-07-20 06:24:49 -04:00
CHIEFSOFT\ameye 232211a297 home recent 2023-07-20 06:18:56 -04:00
ameye eda3d76d4c Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-20 10:17:46 +00:00
Ebube 87f1a1e3e8 Notification for header 2023-07-20 10:22:10 +01:00
ameye 5257f89acb Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-18 20:20:31 +00:00
Ebube d4cf7419bf . 2023-07-18 20:28:30 +01:00
Ebube 1ffb732bfa . 2023-07-18 19:47:23 +01:00
Ebube 9007463f6d Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-18 19:00:21 +01:00
CHIEFSOFT\ameye a4b6b9e493 notification icons 2023-07-18 11:00:40 -04:00
CHIEFSOFT\ameye ccf820da7c bank icon 2023-07-18 07:52:58 -04:00
Ebube 7c51896bbf Wallet update 2023-07-18 10:38:58 +01:00
ameye aa80bab930 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-17 23:30:44 +00:00
Ebube 1704fc60b4 removed hidden abilities for cvv 2023-07-18 00:20:15 +01:00
ameye c3e6c90c49 Merge branch 'collapse-icon' of WrenchBoard/Users-Wrench into master 2023-07-17 19:57:36 +00:00
victorAnumudu 1a65b1daa3 collapse-icon fixed, family icon fixed 2023-07-17 19:21:43 +01:00
ameye ba2c009896 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-17 17:03:29 +00:00
Ebube bc2b71ecda Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-17 17:47:31 +01:00
Ebube 1d315018a4 Added error msg for card and updated password text display 2023-07-17 17:47:03 +01:00
CHIEFSOFT\ameye 56f8b75525 wrong end point on production - Ebubes error 2023-07-17 12:12:14 -04:00
Ebube 59531df377 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-17 17:03:39 +01:00
Ebube 06a7386211 another fix 2023-07-17 17:00:59 +01:00
Ebube 4bb3a11261 correction to .env production 2023-07-17 16:22:25 +01:00
Ebube f308eeca8d Corrections made on AddFund and text variable for Header 2023-07-17 16:20:57 +01:00
ameye 8e562ed1a5 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-17 15:07:58 +00:00
Ebube 23dd7571a3 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-17 15:52:53 +01:00
Ebube 8530b2d1a0 Digits Fixed and SignOut text variable 2023-07-17 15:52:28 +01:00
ameye acdbddbc79 Merge branch 'family-icon' of WrenchBoard/Users-Wrench into master 2023-07-17 14:48:17 +00:00
victorAnumudu 15fc5f4f14 family icon added 2023-07-17 15:31:39 +01:00
ameye 2ba3b01646 Merge branch 'resource-question-page' of WrenchBoard/Users-Wrench into master 2023-07-17 12:50:09 +00:00
ameye 4e960a2f53 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-17 12:49:59 +00:00
victorAnumudu ab700edcf2 resources question page added 2023-07-17 13:42:21 +01:00
Ebube 42e80c7a11 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-17 12:59:32 +01:00
Ebube d4472a881a Fixed digits 2023-07-17 12:59:05 +01:00
Ebube 5d12ab4f62 Made a few changes 2023-07-17 11:48:03 +01:00
ameye 8b3c586456 Merge branch 'withdrwal-popup' of WrenchBoard/Users-Wrench into master 2023-07-17 10:38:48 +00:00
ameye e456b55e16 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-17 10:38:41 +00:00
Ebube 89c5936212 Some fixes 2023-07-17 11:29:50 +01:00
victorAnumudu 7bedf76945 made confirm withdrawal a pop up 2023-07-17 11:07:11 +01:00
Ebube 54bf020c55 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-17 11:04:59 +01:00
Ebube 78145eee77 Paying using new card 2023-07-17 11:04:31 +01:00
victorAnumudu d75b6ee26c made withdrawal a pop up 2023-07-17 11:03:27 +01:00
ameye bf5c9d4671 Merge branch 'profile-bug' of WrenchBoard/Users-Wrench into master 2023-07-17 08:06:43 +00:00
victorAnumudu d2db38ba21 profile bug fixed 2023-07-17 02:01:37 +01:00
ameye eecbca6b0e Merge branch 'withdraw-page' of WrenchBoard/Users-Wrench into master 2023-07-17 00:33:24 +00:00
victorAnumudu dd1430a350 confirm naira withdrawal added 2023-07-17 01:22:12 +01:00
victorAnumudu 0eca0c52ce withdraw page added 2023-07-17 01:15:16 +01:00
ameye c2c7ad7bb4 Merge branch 'family-start-task-layout' of WrenchBoard/Users-Wrench into master 2023-07-16 23:09:30 +00:00
victorAnumudu 98ccbce4c0 family start task layout changed 2023-07-16 23:38:25 +01:00
ameye 6484640e1a Merge branch 'assign-task-layout' of WrenchBoard/Users-Wrench into master 2023-07-16 22:28:28 +00:00
victorAnumudu ba3c4e1918 assign task layout btns fixed 2023-07-16 22:41:58 +01:00
ameye fa4fe35bdf Merge branch 'assign-task-bug-fixed' of WrenchBoard/Users-Wrench into master 2023-07-16 21:31:23 +00:00
victorAnumudu c106e66f44 assign task bug fixed 2023-07-16 22:13:47 +01:00
ameye 222c739663 Merge branch 'notification-bug' of WrenchBoard/Users-Wrench into master 2023-07-16 11:04:22 +00:00
victorAnumudu 96972dbe2f notification bug fixed 2023-07-16 06:51:38 +01:00
CHIEFSOFT\ameye 7146048aee style 2023-07-15 22:16:29 -04:00
CHIEFSOFT\ameye 39f1f5bc73 Resource Question page starter 2023-07-15 21:39:53 -04:00
Ebube fb7913c563 Another fix 2023-07-16 01:36:27 +01:00
Ebube feb301c3c0 . 2023-07-16 01:08:37 +01:00
ameye 752fc6a4a8 Merge branch 'history-page-tab' of WrenchBoard/Users-Wrench into master 2023-07-15 21:39:05 +00:00
victorAnumudu 608d5b92f1 history tab style changed 2023-07-15 22:24:38 +01:00
ameye 45563cc59b Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-15 19:32:37 +00:00
ameye b027e20c20 Merge branch 'job-message-tab' of WrenchBoard/Users-Wrench into master 2023-07-15 19:32:33 +00:00
ameye bbe0777496 Merge branch 'assign-family-hidden' of WrenchBoard/Users-Wrench into master 2023-07-15 19:32:28 +00:00
Ebube 27efbe362b Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-15 20:02:15 +01:00
Ebube 878539a56a Confirm Credit Popup Modifications 2023-07-15 19:47:06 +01:00
victorAnumudu 6ae408029d changed job message tab 2023-07-15 19:21:28 +01:00
victorAnumudu 8016d1bd12 assign to family hidden 2023-07-15 18:59:22 +01:00
ameye 0e9fef218f Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-15 16:19:29 +00:00
CHIEFSOFT\ameye 8116665045 removed yarn lock 2023-07-15 12:13:47 -04:00
Ebube e4addc47d9 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-15 17:10:43 +01:00
Ebube 1682f11efd Confirm Credit Popup 2023-07-15 17:08:52 +01:00
CHIEFSOFT\ameye 80b2abf9e3 glog page 2023-07-15 12:07:42 -04:00
CHIEFSOFT\ameye 5edecb6464 jib actions 2023-07-15 11:46:55 -04:00
CHIEFSOFT\ameye 3a479b3573 action txt 2023-07-15 11:06:04 -04:00
ameye 4034909836 Merge branch 'set-account-settings' of WrenchBoard/Users-Wrench into master 2023-07-15 13:56:30 +00:00
victorAnumudu 8fc61a6289 API for set account settings added 2023-07-15 14:53:34 +01:00
CHIEFSOFT\ameye 940a12a2e9 actio panel 2023-07-15 09:51:53 -04:00
CHIEFSOFT\ameye a9f671eeaa active task messaghe 2023-07-15 08:55:48 -04:00
ameye 481924fa02 Merge branch 'delete-card' of WrenchBoard/Users-Wrench into master 2023-07-15 10:22:24 +00:00
victorAnumudu 6b712089d1 notification icons added 2023-07-15 10:49:46 +01:00
victorAnumudu 85ca2cb15a reloads card list on successful card delete 2023-07-15 10:15:14 +01:00
victorAnumudu d01c4928ff Merge master into delete-card 2023-07-15 09:52:03 +01:00
victorAnumudu b81e62988c delete popout added 2023-07-15 09:48:14 +01:00
ameye a8b63917fb Merge branch 'account-settings' of WrenchBoard/Users-Wrench into master 2023-07-15 08:38:13 +00:00
CHIEFSOFT\ameye 9cf6d13716 images 2023-07-15 04:37:52 -04:00
victorAnumudu c1af2b7fc9 logged info removed 2023-07-15 08:06:44 +01:00
victorAnumudu 494c1f3271 account settings API added 2023-07-15 08:00:25 +01:00
ameye 9f0c33521f Merge branch 'reset-profile-password' of WrenchBoard/Users-Wrench into master 2023-07-14 19:56:14 +00:00
victorAnumudu 1d5875d4e2 reset profile password implemented 2023-07-14 20:28:22 +01:00
ameye 6f6b12f4b5 Merge branch 'card-list-image-added' of WrenchBoard/Users-Wrench into master 2023-07-14 17:46:44 +00:00
victorAnumudu f3ad4d576e card list image added 2023-07-14 18:42:28 +01:00
CHIEFSOFT\ameye e01d0106ad cards images 2023-07-14 13:19:41 -04:00
ameye 68472f8c66 Merge branch 'card-list-page' of WrenchBoard/Users-Wrench into master 2023-07-14 17:00:38 +00:00
victorAnumudu 8def463d80 card listing added 2023-07-14 17:54:44 +01:00
ameye 0320999f72 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-14 13:42:01 +00:00
Ebube 78a97d8b0b Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-14 13:48:25 +01:00
Ebube 6bf6c5d2d4 Added PaidPrevCard api 2023-07-14 13:48:03 +01:00
ameye 33284600e5 Merge branch 'change-passage-mac' of WrenchBoard/Users-Wrench into master 2023-07-14 12:37:26 +00:00
ameye 68bf995078 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-14 12:37:18 +00:00
Ebube fa05f47941 . 2023-07-14 13:30:50 +01:00
victorAnumudu 2391857309 flex display changed to suit mac screen 2023-07-14 12:58:49 +01:00
Ebube ed38cadcee Start credit Api for Dollar acc 2023-07-14 12:53:05 +01:00
ameye ea447a9366 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-13 23:09:01 +00:00
Ebube 4e2f120ab5 Few changes 2023-07-13 23:12:29 +01:00
Ebube 20ce9bf749 Consumed Start credit Api 2023-07-13 22:34:09 +01:00
ameye 04e1bcc5f1 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-13 19:38:17 +00:00
Ebube cbaa8b6f7b Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-13 20:14:54 +01:00
ameye f6bdb1c299 Merge branch 'wallet-card' of WrenchBoard/Users-Wrench into master 2023-07-13 19:11:32 +00:00
Ebube d4061d72da . 2023-07-13 18:20:20 +01:00
Ebube 2d9a8b55b5 . 2023-07-13 18:16:52 +01:00
Ebube 920eafed29 . 2023-07-13 18:10:19 +01:00
Ebube 21d926eb5c Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-13 18:08:23 +01:00
Ebube ec9d793d6b . 2023-07-13 18:07:05 +01:00
victorAnumudu 2fd04dc86d wallet card adjustment 2023-07-13 16:44:05 +01:00
ameye d7752cb70b Merge branch 'wallet-layout-fix' of WrenchBoard/Users-Wrench into master 2023-07-13 13:05:32 +00:00
victorAnumudu dc592f60db layout fix 2023-07-13 14:02:27 +01:00
victorAnumudu 675ba2989e layout fix 2023-07-13 14:00:02 +01:00
ameye b201224fd6 Merge branch 'wallet-size' of WrenchBoard/Users-Wrench into master 2023-07-13 12:45:17 +00:00
ameye c24013eefd Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-13 12:45:12 +00:00
Ebube 5f222a2d88 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-13 12:37:32 +01:00
Ebube 258434a109 Applied corrections and changes to the wallet 2023-07-13 12:34:39 +01:00
CHIEFSOFT\ameye ed148612a7 more banners 2023-07-13 07:21:37 -04:00
142 changed files with 4998 additions and 13432 deletions
+3 -1
View File
@@ -46,7 +46,7 @@ REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_FACEBOOK_CLIENT_ID2=390204307987009
REACT_APP_FACEBOOK_CLIENT_SECRET2=19f778e312f2ab96d147bacb612910c2
#developenet Account
#development Account Social
REACT_APP_FACEBOOK_CLIENT_ID=677857427521030
REACT_APP_FACEBOOK_CLIENT_SECRET=4801375f22072d8a75f64483fdd89829
@@ -68,6 +68,8 @@ REACT_APP_APPLE_REDIRECT_URL='http://localhost:9082/login/auth/apple'
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
REACT_APP_LOGOUT_TEXT="Sign Out"
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
+3 -1
View File
@@ -41,4 +41,6 @@ REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https:
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
REACT_APP_TOTAL_NUM_FILE=4
REACT_APP_LOGOUT_TEXT="Sign Out"
+3 -1
View File
@@ -48,4 +48,6 @@ REACT_APP_FACEBOOK_REDIRECT_URL="https://users.wrenchboard.com/login/auth/flogin
DISABLE_ESLINT_PLUGIN=true
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
REACT_APP_TOTAL_NUM_FILE=4
REACT_APP_LOGOUT_TEXT="Sign Out"
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+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"}
Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+2
View File
@@ -56,6 +56,8 @@ export default function Routers() {
<Routes>
{/* guest routes */}
<Route exact path="/login" element={<LoginPage />} />
<Route exact path="/eoffer" element={<LoginPage />} />
<Route exact path="/signup" element={<SignupPage />} />
<Route exact path="/login/auth" element={<AuthRedirect />} />
<Route exact path="/login/auth/flogin" element={<FacebookRedirect />} />
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1792 1792" id="Bank"><path d="m896 78.526 896 358.4v119.466h-119.467q0 24.267-19.133 42-19.133 17.734-45.267 17.734H183.867q-26.134 0-45.267-17.734-19.133-17.733-19.133-42H0V436.926ZM238.933 675.859h238.934v716.8h119.466v-716.8h238.934v716.8h119.466v-716.8h238.934v716.8h119.466v-716.8h238.934v716.8h55.066q26.134 0 45.267 17.733 19.133 17.734 19.133 42v59.734H119.467v-59.734q0-24.266 19.133-42 19.133-17.733 45.267-17.733h55.066v-716.8zm1488.667 896q26.133 0 45.267 17.733 19.133 17.734 19.133 42v119.467H0v-119.467q0-24.266 19.133-42 19.134-17.733 45.267-17.733h1663.2z" fill="#4687ba" class="color000000 svgShape"></path></svg>

After

Width:  |  Height:  |  Size: 684 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 128 128" viewBox="0 0 128 128" id="Alert"><path fill="#f34093" d="M122.9,100.2L74.3,15.9c-4.6-7.9-16-7.9-20.6,0L5.1,100.2C0.5,108.1,6.2,118,15.4,118h97.3
C121.8,118,127.5,108.1,122.9,100.2z M63.9,101c-3.5-0.1-6.7-3.3-6.6-6.8c0.1-3.5,3.3-6.7,6.8-6.6c3.5,0.1,6.7,3.3,6.6,6.8
C70.6,98,67.4,101.1,63.9,101z M71.3,51.8c-0.7,7.8-1.5,15.6-2.3,23.4c-0.5,4.4-3.2,6.1-7.3,4.5c-1-0.4-2-2-2.2-3.2
C58.6,70,58,63.4,57.3,56.8c-0.3-2.8-0.5-5.6-0.8-8.5c-0.4-3.3,0.6-4.5,4-4.5c1.1,0,2.3,0,3.4,0C72,43.8,72,43.8,71.3,51.8z" class="color343433 svgShape"></path></svg>

After

Width:  |  Height:  |  Size: 621 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="Messages"><path fill="#4687ba" d="m447.372 413.112-17.544-52.629c-1-3.002-.674-6.23.775-9.043 13.184-25.615 18.629-55.858 12.925-87.736-8.746-48.868-44.53-89.475-90.943-105.048 11.976 28.924 15.628 61.084 9.645 92.984-12.155 64.837-64.074 116.246-129.191 127.924-8.429 1.512-16.945 2.248-25.396 2.463 19.776 21.336 46.173 36.503 75.619 41.784 31.682 5.682 61.784.393 87.322-12.594 2.802-1.425 6.007-1.742 8.99-.748l52.83 17.61c9.251 3.084 18.052-5.716 14.968-14.967z" class="color173042 svgShape"></path><path fill="#4687ba" d="M177.161 85.744C122.283 95.941 78.306 140.526 68.472 195.47c-5.704 31.878-.259 62.121 12.925 87.736 1.449 2.813 1.775 6.041.776 9.043l-17.545 52.629c-3.083 9.251 5.717 18.051 14.968 14.968l52.83-17.61c2.984-.994 6.19-.677 8.991.748 25.537 12.987 55.638 18.276 87.321 12.594 54.809-9.829 99.281-53.698 109.541-108.428 18.078-96.414-64.733-179.316-161.118-161.406zm34.938 177.536h-68.234c-6.73 0-12.185-5.454-12.185-12.185 0-6.73 5.455-12.185 12.185-12.185h68.234c6.731 0 12.185 5.455 12.185 12.185 0 6.731-5.454 12.185-12.185 12.185zm48.739-48.739H143.864c-6.73 0-12.185-5.454-12.185-12.185 0-6.73 5.455-12.185 12.185-12.185h116.973c6.731 0 12.185 5.455 12.185 12.185.001 6.731-5.453 12.185-12.184 12.185z" class="color173042 svgShape"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="phone" x="0" y="0" version="1.1" viewBox="0 0 29 29" xml:space="preserve"><path d="M5.661 23.339c4.882 4.882 12.796 4.882 17.678 0 4.882-4.882 4.882-12.796 0-17.678s-12.796-4.882-17.678 0C.78 10.543.78 18.457 5.661 23.339zm5.545-16.613l1.86 1.86c.372.372.451.947.193 1.406l-.699 1.241a.781.781 0 0 0 .129.937l4.141 4.141a.781.781 0 0 0 .937.128l1.241-.699a1.173 1.173 0 0 1 1.406.193l1.861 1.861a1.175 1.175 0 0 1 0 1.66l-.881.881a3.135 3.135 0 0 1-3.786.493l-.084-.048a24.54 24.54 0 0 1-8.868-8.681l-.423-.706a3.128 3.128 0 0 1 .469-3.823l.844-.844a1.173 1.173 0 0 1 1.66 0z" fill="#4687ba" class="color000000 svgShape"></path></svg>

After

Width:  |  Height:  |  Size: 678 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 512 512" id="Sms"><circle cx="256" cy="256" r="256" fill="#4687ba" class="color00aebb svgShape"></circle><path fill="#ffffff" d="M256 129.3c-88.4 0-160 52-160 116.2 0 26.6 12.3 51.1 33 70.7-11.6 26.2-22.6 66.2-22.6 66.2 6.1 3.1 60.9-23.9 78.4-32.8 21.4 7.7 45.6 12.1 71.2 12.1 88.4 0 160-52 160-116.2s-71.6-116.2-160-116.2zm-59.2 148.9c-5.2 3.8-12 5.7-20.4 5.7-8.3 0-15.4-2.1-21.4-6.2-6-4.1-8.8-10.3-8.7-18.5l.1-.3h15c0 4.6 1.3 7.9 4 10.1 2.7 2.2 6.3 3.2 10.9 3.2 4.1 0 7.3-.9 9.5-2.6 2.2-1.7 3.3-4 3.3-6.9 0-3-1-5.3-3.1-7.1-2.1-1.8-5.7-3.5-10.9-5.1-8.9-2.7-15.6-5.8-20.3-9.5-4.6-3.6-6.9-8.6-6.9-14.9 0-6.3 2.6-11.5 7.8-15.5 5.2-4 11.8-6 19.9-6 8.5 0 15.4 2.2 20.6 6.5 5.2 4.3 7.7 10 7.5 16.9l-.1.3h-15c0-3.8-1.2-6.8-3.5-8.9-2.3-2.1-5.6-3.1-9.8-3.1-3.8 0-6.8.9-8.8 2.8-2.1 1.8-3.1 4.2-3.1 7 0 2.6 1.1 4.8 3.4 6.4 2.3 1.7 6.2 3.5 11.7 5.3 8.5 2.4 14.9 5.5 19.4 9.4 4.4 3.9 6.7 9 6.7 15.3-.1 6.7-2.7 11.9-7.8 15.7zm99.3 4.7h-15.5v-52.6l-.3-.1-19.1 52.7h-10.5l-19.1-52.8-.3.1v52.7h-15.5v-77.1h20.3l19.6 56.8h.3l19.8-56.8H296v77.1zm62.1-4.7c-5.2 3.8-12 5.7-20.4 5.7-8.3 0-15.4-2.1-21.4-6.2-5.9-4.1-8.8-10.3-8.7-18.5l.1-.3h15c0 4.6 1.3 7.9 4 10.1 2.7 2.2 6.3 3.2 10.9 3.2 4.1 0 7.3-.9 9.5-2.6 2.2-1.7 3.3-4 3.3-6.9 0-3-1-5.3-3.1-7.1-2.1-1.8-5.7-3.5-10.9-5.1-8.9-2.7-15.7-5.8-20.3-9.5-4.6-3.6-6.9-8.6-6.9-14.9 0-6.3 2.6-11.5 7.8-15.5 5.2-4 11.8-6 19.9-6 8.5 0 15.4 2.2 20.6 6.5 5.2 4.3 7.7 10 7.5 16.9l-.1.3h-15c0-3.8-1.2-6.8-3.5-8.9-2.3-2.1-5.6-3.1-9.8-3.1-3.8 0-6.8.9-8.8 2.8-2.1 1.8-3.1 4.2-3.1 7 0 2.6 1.1 4.8 3.4 6.4 2.3 1.7 6.2 3.5 11.7 5.3 8.5 2.4 14.9 5.5 19.4 9.4 4.4 3.9 6.7 9 6.7 15.3-.1 6.7-2.6 11.9-7.8 15.7z" class="colorffffff svgShape"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.0 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" id="Visacard"><g fill="#767fad" class="color303c42 svgShape"><path d="M28 4H2C.897 4 0 4.897 0 6v18c0 1.103.897 2 2 2h26c1.103 0 2-.897 2-2V6c0-1.103-.897-2-2-2zm1 20c0 .551-.449 1-1 1H2c-.551 0-1-.449-1-1V6c0-.551.449-1 1-1h26c.551 0 1 .449 1 1v18z" fill="#5218ed" class="color000000 svgShape"></path><path d="M7.677 14.266a.2.2 0 0 0 .228.053.17.17 0 0 0 .106-.194l-.314-1.368a.121.121 0 0 0-.002-.009c-.113-.39-.47-.449-.729-.459H6.96l-1.768-.002c-.091 0-.17.06-.185.143a.172.172 0 0 0 .121.193c1.078.358 1.96.926 2.55 1.643zM23.535 12.303h-1.15c-.46 0-.724.141-.883.473l-2.383 4.981a.162.162 0 0 0 .014.165c.035.05.094.079.158.079h1.35a.189.189 0 0 0 .176-.112c.165-.404.272-.661.307-.744h.974l1.183.002c.039.151.134.552.173.717.019.08.095.137.184.137h1.177c.057 0 .11-.024.146-.065s.05-.095.038-.146l-1.28-5.351a.185.185 0 0 0-.184-.136zm-1.926 3.675.895-2.138.114.492.39 1.646h-1.4z" fill="#5218ed" class="color000000 svgShape"></path><path d="M11.816 12.38a.193.193 0 0 0-.157-.078h-1.37a.188.188 0 0 0-.175.11L8.511 16.19l-.172-.575a.142.142 0 0 0-.009-.023c-.253-.542-.933-1.39-1.881-2.062-.065-.046-.154-.048-.221-.006s-.097.12-.074.192L7.47 17.87a.187.187 0 0 0 .18.124l1.518-.002a.19.19 0 0 0 .173-.104l2.49-5.344a.162.162 0 0 0-.016-.164zM14.088 12.297h-1.303a.184.184 0 0 0-.186.144l-.989 5.355a.165.165 0 0 0 .042.141c.036.04.088.062.144.062h1.302c.092 0 .17-.061.186-.145l.99-5.354a.164.164 0 0 0-.042-.141.195.195 0 0 0-.144-.062zM17.696 13.452h.05c.51 0 .87.107 1.097.187a.202.202 0 0 0 .16-.011.175.175 0 0 0 .093-.122l.152-.826c.016-.085-.039-.168-.128-.194a4.634 4.634 0 0 0-1.3-.182c-1.607 0-2.735.746-2.744 1.814-.01.79.807 1.231 1.422 1.494.632.269.844.441.841.682-.004.369-.506.536-.97.536a3.676 3.676 0 0 1-1.522-.285.202.202 0 0 0-.163.008.175.175 0 0 0-.095.123l-.161.87a.173.173 0 0 0 .123.193c.444.144 1.064.233 1.66.24h.001c1.705-.001 2.815-.739 2.827-1.88.006-.627-.427-1.1-1.36-1.49-.57-.256-.92-.426-.917-.686 0-.234.32-.47.934-.47z" fill="#5218ed" class="color000000 svgShape"></path></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

@@ -1,6 +1,6 @@
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
+97 -91
View File
@@ -1,26 +1,25 @@
import React, { useEffect, useLayoutEffect, useState } from "react";
import { Link, useNavigate, useLocation } from "react-router-dom";
import { Link, useLocation, useNavigate } from "react-router-dom";
import linkedInLogo from "../../../assets/images/Linkedin.png";
import appleLogo from "../../../assets/images/apple-black.svg";
import facebookLogo from "../../../assets/images/facebook-4.svg";
import googleLogo from "../../../assets/images/google-logo.svg";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
// import { GoogleOAuthProvider } from '@react-oauth/google';
import { googleLogout, useGoogleLogin } from "@react-oauth/google";
import { useGoogleLogin } from "@react-oauth/google";
import { useDispatch } from "react-redux";
import { updateUserDetails } from "../../../store/UserDetails";
export default function Login() {
const dispatch = useDispatch();
const {state} = useLocation()
const { state } = useLocation();
let [loginType, setLoginType] = useState('');
let [loginType, setLoginType] = useState("");
const [checked, setValue] = useState(false);
const [loginLoading, setLoginLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
@@ -30,12 +29,8 @@ export default function Login() {
// for the catch error
const [msgError, setMsgError] = useState("");
const rememberMe = () => {
setValue(!checked);
};
// To Show and Hide Password
const togglePasswordVisibility = () => {
// To Show and Hide Password
const togglePasswordVisibility = () => {
setShowPassword(!showPassword);
};
@@ -43,7 +38,7 @@ export default function Login() {
const handleLoginType = ({ target: { name } }) => {
setLoginType(name);
let currentDate = new Date();
let expirationDate = new Date(currentDate.getTime() + (24 * 60 * 60 * 1000));
let expirationDate = new Date(currentDate.getTime() + 24 * 60 * 60 * 1000);
// Convert the expiration date to the appropriate format
let expirationDateString = expirationDate.toUTCString();
document.cookie = `loginType=${name}; expires=${expirationDateString}; path=/;`;
@@ -83,7 +78,9 @@ export default function Login() {
if (regEx.test(email) == false) {
setLoginLoading(false);
setMsgError("Invalid Email");
return setTimeout(()=>{setMsgError("");},3000)
return setTimeout(() => {
setMsgError("");
}, 3000);
}
// Post Data Info for normal Login
postData = {
@@ -113,7 +110,13 @@ export default function Login() {
userApi
.logInUser(postData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0 || !res.data.member_id || !res.data.uid || !res.data.session) {
if (
res.status != 200 ||
res.data.internal_return < 0 ||
!res.data.member_id ||
!res.data.uid ||
!res.data.session
) {
// setMsgError("Wrong, email/password");
setLoginError(true);
setLoginLoading(false);
@@ -123,7 +126,7 @@ export default function Login() {
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
// localStorage.setItem("session", `${res.data.session}`);
dispatch(updateUserDetails({...res.data}));
dispatch(updateUserDetails({ ...res.data }));
setTimeout(() => {
navigate("/", { replace: true });
setLoginLoading(false);
@@ -154,11 +157,12 @@ export default function Login() {
// In order to update the selected login type whenever the component renders
// useEffect(() => {
// Clear the loginType cookie if the user switches to loginfull
// document.cookie ="loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// Clear the loginType cookie if the user switches to loginfull
// document.cookie ="loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// }, []);
useLayoutEffect(()=>{ // checks the cookie in order to set the login type before components mounts
useLayoutEffect(() => {
// checks the cookie in order to set the login type before components mounts
// if(document.cookie.includes("loginType=family")){
// setLoginType('family')
// }else if(document.cookie.includes("loginType=full")){
@@ -166,33 +170,34 @@ export default function Login() {
// }else{
// setLoginType('full')
// }
function readCookie(cname) { // checks the cookie in order to set the login type before components mounts
function readCookie(cname) {
// checks the cookie in order to set the login type before components mounts
let name = cname + "=";
let decoded_cookie = decodeURIComponent(document.cookie);
let carr = decoded_cookie.split(';');
for(let i=0; i<carr.length;i++){
let carr = decoded_cookie.split(";");
for (let i = 0; i < carr.length; i++) {
let c = carr[i];
while(c.charAt(0)==' '){
c=c.substring(1);
while (c.charAt(0) == " ") {
c = c.substring(1);
}
if(c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return 'full'
return "full";
}
let loginValue = readCookie('loginType')
setLoginType(loginValue)
let loginValue = readCookie("loginType");
setLoginType(loginValue);
if(state?.error){ //check if the login path has an error state indicating any social handle login with error
if (state?.error) {
//check if the login path has an error state indicating any social handle login with error
setMsgError("Unexpected Error, Please try again soon.");
setTimeout(()=>{
setTimeout(() => {
setMsgError("");
navigate('/login', {replace: true})
},4000)
navigate("/login", { replace: true });
}, 4000);
}
},[])
}, []);
useEffect(() => {
setMail("");
@@ -234,7 +239,9 @@ export default function Login() {
<button
name="full"
className={`login-type-btn px-4 py-1 rounded-t-2xl ${
loginType=='full' ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
loginType == "full"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
onClick={handleLoginType}
>
@@ -243,7 +250,9 @@ export default function Login() {
<button
name="family"
className={`login-type-btn px-4 py-1 rounded-t-2xl ${
loginType=='family' ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
loginType == "family"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
onClick={handleLoginType}
>
@@ -255,7 +264,7 @@ export default function Login() {
{/* for login component */}
{
loginType == 'full' ? (
loginType == "full" ? (
//user login component
<div className="p-6 input-area login-area border-2 border-[#4687ba] rounded-2xl">
<div className="input-item mb-5">
@@ -275,7 +284,7 @@ export default function Login() {
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
@@ -321,33 +330,33 @@ 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}
/>
<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}
/>
<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>
</div>
</div>
@@ -423,10 +432,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>
}
</div>
</div>
</div>
@@ -435,7 +446,7 @@ export default function Login() {
);
}
const BrandBtn = ({ link, imgSrc, brand, onClick, isAnchor=false }) => {
const BrandBtn = ({ link, imgSrc, brand, onClick, isAnchor = false }) => {
// const doGoogle = async () => {
// alert("start google");
// };
@@ -456,33 +467,28 @@ const BrandBtn = ({ link, imgSrc, brand, onClick, isAnchor=false }) => {
// };
return (
<div className="w-full sm:w-1/2 flex justify-center bottomMargin">
{isAnchor ?
(
{isAnchor ? (
<a
href={link}
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
>
<img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
<span className="text-lg text-thin-light-gray font-normal text-[15px]">
Continue with {brand}
</span>
</a>
)
:
(
href={link}
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
>
<img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
<span className="text-lg text-thin-light-gray font-normal text-[15px]">
Continue with {brand}
</span>
</a>
) : (
<button
onClick={onClick}
// href="#dd"
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
>
<img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
<span className="text-lg text-thin-light-gray font-normal text-[15px]">
Continue with {brand}
</span>
</button>
)
}
onClick={onClick}
// href="#dd"
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
>
<img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
<span className="text-lg text-thin-light-gray font-normal text-[15px]">
Continue with {brand}
</span>
</button>
)}
</div>
)
);
};
+54 -10
View File
@@ -1,7 +1,6 @@
import React, { useCallback, useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import facebookLogo from "../../../assets/images/facebook-4.svg";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
@@ -69,13 +68,17 @@ export default function SignUp() {
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
if (regEx.test(email) == false) {
setMsgError("Invalid Email");
return setTimeout(()=>{setMsgError("");},3000)
return setTimeout(() => {
setMsgError("");
}, 3000);
}
//checks if terms and condition is checked
if (!checked) {
setMsgError("Terms and condition required");
return setTimeout(()=>{setMsgError("");},3000)
return setTimeout(() => {
setMsgError("");
}, 3000);
}
setSignUpLoading(true);
@@ -95,7 +98,9 @@ export default function SignUp() {
if (res.status === 200) {
const { data } = res;
if (data && data.acc === "DULPICATE") {
setMsgError("Unable to use this username. Please try another username.");
setMsgError(
"Unable to use this username. Please try another username."
);
setSignUpLoading(false);
}
if (data && data.status === "1") {
@@ -205,15 +210,13 @@ export default function SignUp() {
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type={showPassword ? "text" : "password"}
onClick={togglePasswordVisibility}
passIcon={
showPassword ? "show-password" : "hide-password"
}
passIcon={showPassword ? "show-password" : "hide-password"}
value={formData.password}
inputHandler={handleInputChange}
/>
@@ -223,7 +226,48 @@ export default function SignUp() {
{msgError}
</div>
)}
<div className="forgot-password-area flex justify-between items-center mb-6">
<div className="remember-checkbox flex items-center space-x-2.5 group cursor-pointer">
<button
onClick={rememberMe}
type="button"
className={`w-6 h-6 border-[#4687ba] text-white flex justify-center items-center border rounded-[.45em] group-checked:text-white transition-all duration-200 group-checked:cursor-default ${
checked && "text-white bg-[#4687ba]"
}`}
>
{checked && (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
)}
</button>
<span
onClick={rememberMe}
className="cursor-default text-dark-gray dark:text-white text-[15px] group-checked:text-white transition-all duration-200 group-checked:cursor-default"
>
I agree with all
<Link
href="#"
className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block"
>
terms and condition
</Link>
</span>
</div>
</div>
{/* Forgot Password */}
{/* <div className="forgot-password-area flex justify-between items-center mb-6">
<div className="remember-checkbox flex items-center space-x-2.5">
<button
onClick={rememberMe}
@@ -258,7 +302,7 @@ export default function SignUp() {
</Link>
</span>
</div>
</div>
</div> */}
<div className="signin-area mb-1">
<div className="flex justify-center">
<button
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import debounce from "../../../hooks/debounce";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
@@ -1,6 +1,6 @@
import { useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
@@ -158,8 +158,8 @@ const SuccessfulComponent = ({
{/* INPUT */}
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={password}
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={password?.replace(/./g, "●")}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Password"
@@ -171,8 +171,8 @@ const SuccessfulComponent = ({
</div>
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={confirmPassword}
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={confirmPassword?.replace(/./g, "●")}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Confirm Password"
+1 -1
View File
@@ -1,6 +1,6 @@
import { useNavigate, Link } from "react-router-dom";
import AuthLayout from "../AuthLayout";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
export default function VerifyYou() {
const navigate = useNavigate();
+58 -20
View File
@@ -1,38 +1,76 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import React, { useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function BlogItem(props) {
const apiCall = new usersService()
const navigate = useNavigate()
const [blogdata, setBlogdata] = useState({loading: true, data:{}})
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
const queryParams = new URLSearchParams(location?.search);
const blog_id = queryParams.get("blog_id");
useEffect(()=>{
if(!blog_id){
navigate('/',{replace:true})
}
apiCall.getSingleBlogData({blog_id}).then(res => {
setBlogdata({loading: false, data:res.data})
}).catch(error => {
setBlogdata({loading: false, data:{}})
console.log('ERROR', error)
})
},[blog_id])
return (
<Layout>
<CommonHead
commonHeadData={props.commonHeadData}
/>
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Title of this Blog Items
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
</div>
<div className="mb-5">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
{blogdata.data?.blogdata?.[0]?.post_title}
</span>
</h1>
</div>
<div className="notification-wrapper w-full bg-white p-8 rounded-2xl">
{blogdata.loading ?
<LoadingSpinner size='8' color='sky-blue' height='h-[100px]' />
:
blogdata?.data?.blogdata && blogdata.data?.blogdata.length ?
<div className="w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
{/* <div className="mb-5">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
{blogdata.data?.blogdata?.[0]?.post_title}
</span>
</h1>
</div> */}
{/* <div className="slider-btns flex space-x-4">
</div> */}
</div>
<div dangerouslySetInnerHTML={{__html: blogdata.data?.blogdata?.[0]?.post_content}}>
</div>
</div>
<div>
Blog Items Details
</div>
:
<h1 className="text-26 font-bold text-dark-gray dark:text-white">No Blog Found!</h1>
}
</div>
</div>
</Layout>
@@ -16,7 +16,8 @@ export default function HomeBannerOffersCard(props) {
return (
<Link
to={link_result}
// to={link_result}
to={link_result == '/blog-page' ? `${link_result}?blog_id=${props.itemData.blog_id}` : `${link_result}`}
className="item p-2 w-full flex items-center min-h-[340px] bg-alice-blue bg-cover bg-center"
style={{
backgroundImage: `url('${imageUrl}')`,
+1 -1
View File
@@ -19,7 +19,7 @@ export default function OfferCard({ datas, hidden = false, setOfferPopout }) {
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${localImgLoad(
`images/taskbanners/${datas.banner}`
`images/taskbanners/${datas?.banner || "default.jpg"}`
)}) center / contain no-repeat`,
}}
>
+7 -6
View File
@@ -50,22 +50,23 @@ export default function ProductCardStyleTwo({
</div>
<div className="details-area">
{/* title */}
<a href={datas.guid} target="_blank" className="mb-2.5" rel="noreferrer">
<Link to={`/blog-page?blog_id=${datas.ID}`} className="mb-2.5" rel="noreferrer">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.post_title || "dummy title..."}
</h1>
</a>
</Link>
<div className="flex justify-between">
<div className="flex items-center space-x-2"></div>
<div className="my-1">
<a
href={datas.guid}
target="_blank"
<Link
// href={datas.guid}
// target="_blank"
to={`/blog-page?blog_id=${datas.ID}`}
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
rel="noreferrer"
>
View
</a>
</Link>
</div>
</div>
</div>
+11 -10
View File
@@ -10,10 +10,10 @@ import React, {
} from "react";
import { useReactToPrint } from "react-to-print";
import profile from "../../assets/images/profile-info-profile.png";
import localImgLoad from "../../lib/localImgLoad";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import localImgLoad from "../../lib/localImgLoad";
// Lazy Imports for components
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
@@ -193,19 +193,19 @@ export default function FamilyManageTabs({
return (
<div
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full ${
className || ""
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<div className="relative w-full sm:rounded-lg overflow-x-auto">
<Suspense
fallback={
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<div className="h-full min-h-[609px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
}
>
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[520px]">
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[575px]">
<div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full flex flex-col justify-between">
<ProfileInfo
profileImg={profileImg}
@@ -239,10 +239,10 @@ export default function FamilyManageTabs({
</button>
</div>
</div>
<div className="col-span-3 justify-self-end h-full w-full">
<div className="col-span-3 h-full w-full">
<div className="flex flex-col w-full">
<div className="w-full pr-8 flex items-center gap-1">
<ul className="flex gap-2 items-center border-b border-b-[#FAFAF] w-full">
<div className="w-full pr-8 flex items-center gap-1 border-b border-b-[#FAFAF]">
<ul className="flex gap-2 items-center w-full">
{tabs.map(({ name, id }) => (
<li
onClick={() => tabHandler(name)}
@@ -265,8 +265,9 @@ export default function FamilyManageTabs({
Add task
</button>
</div>
<div className="flex-[0.9] lg:min-h-[450px] h-full">
<div className="h-full p-4 border border-[#dbd9d9] relative overflow-y-auto">
<div className="flex-[0.9] h-full">
<div className="h-full relative overflow-y-auto">
<Suspense
fallback={<LoadingSpinner size="16" color="sky-blue" />}
>
@@ -63,7 +63,7 @@ const AssignTaskPopout = React.memo(({ action, details, situation, familyDetail
// API PAYLOADS
job_id: activeTask.data?.job_id,
job_uid: activeTask.data?.job_uid,
family_uid: familyDetails.uid,
family_uid: familyDetails?.uid || details?.family_uid,
job_description: activeTask.data?.description,
assign_mode: 110011,
};
+6 -3
View File
@@ -6,6 +6,7 @@ import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import familyImage from '../../assets/images/no-family-side.png'
import localImgLoad from "../../lib/localImgLoad";
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
const navigate = useNavigate();
@@ -22,7 +23,7 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
return (
<div
className={`update-table w-full h-full p-8 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] ${
className || ""
}`}
>
@@ -54,6 +55,7 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
last_login,
task_count,
family_uid,
banner
} = props;
let addedDate = added?.split(" ")[0];
let LoginDate = last_login?.split(" ")[0];
@@ -64,9 +66,10 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] min-w-[60px]">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1]">
<img
src={dataImage1}
// src={dataImage1}
src={localImgLoad(`images/icons/${banner}`)}
alt="data"
className="w-full h-full"
/>
@@ -4,7 +4,7 @@ import QRCode from "react-qr-code";
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
return (
<div
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
className="w-full lg:min-h-[538px] p-3 h-full flex flex-col items-center justify-center"
ref={myRef}
>
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
@@ -53,4 +53,4 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
);
});
export default FamilyAccount;
export default FamilyAccount;
@@ -1,9 +1,8 @@
import { useMemo, useState } from "react";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import dataImage2 from "../../../assets/images/data-table-user-2.png";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
import localImgLoad from "../../../lib/localImgLoad";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
export default function FamilyPending({
familyData,
@@ -37,7 +36,7 @@ export default function FamilyPending({
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className={`update-table w-full p-3 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px] ${
className || ""
}`}
>
@@ -125,8 +124,10 @@ export default function FamilyPending({
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Pending Task!</td>
<tr>
<td className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap text-center py-4 px-2">
No Pending Task!
</td>
</tr>
)}
</>
@@ -1,3 +1,11 @@
export default function FamilyProfile() {
return <>Profile</>;
}
export default function FamilyProfile({ className }) {
return (
<div
className={`update-table w-full bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px] p-3 ${
className || ""
}`}
>
<h1>Profile</h1>
</div>
);
}
+40 -18
View File
@@ -1,20 +1,30 @@
import React, { useState } from "react";
import dataImage2 from "../../../assets/images/data-table-user-2.png";
import { useNavigate, useLocation } from "react-router-dom";
import React, { useMemo, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import localImgLoad from "../../../lib/localImgLoad";
import Icons from "../../Helpers/Icons";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { handlePagingFunc } from "../../Pagination/HandlePagination";
import PaginatedList from "../../Pagination/PaginatedList";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import Icons from "../../Helpers/Icons";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import ModalCom from "../../Helpers/ModalCom";
import Detail from "../../jobPopout/popoutcomponent/Detail";
import localImgLoad from "../../../lib/localImgLoad";
export default function FamilyTasks({ familyData, className, loader, accountDetails }) {
export default function FamilyTasks({
familyData,
className,
loader,
accountDetails,
}) {
let navigate = useNavigate();
let { pathname } = useLocation();
// ...
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
);
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
@@ -26,9 +36,10 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
return (
<div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] overflow-hidden rounded-2xl section-shadow p-3 ${
className || ""
}`}
>
@@ -45,8 +56,8 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
{
<>
{familyData &&
familyData?.result_list &&
familyData.result_list.length > 0 &&
familyData?.result_list &&
familyData.result_list.length > 0 ? (
currentTask.map((value, index) => {
// find due date
const dueDate = value?.delivery_date.split(" ")[0];
@@ -56,7 +67,9 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
value?.currency_code,
value?.currency
);
let image = value.banner ? value.banner : 'default.jpg'
let image = value.banner
? value.banner
: "default.jpg";
return (
<tr
key={index}
@@ -66,7 +79,9 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
<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/taskbanners/${image}`)}
src={localImgLoad(
`images/taskbanners/${image}`
)}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -109,8 +124,8 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
state: {
...value,
pathname,
accountDetails
}
accountDetails,
},
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
@@ -120,7 +135,14 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
</td>
</tr>
);
})}
})
) : (
<tr>
<td colSpan="2" className="text-center py-4 font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
No Family Task
</td>
</tr>
)}
</>
}
</tbody>
@@ -48,7 +48,7 @@ const FamilyWaitlist = memo(
return (
<div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] p-3 overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
@@ -1,4 +1,6 @@
import React from "react";
import localImgLoad from "../../../lib/localImgLoad";
export default function ProfileInfo({
profileImg,
@@ -12,7 +14,7 @@ export default function ProfileInfo({
<div className="flex justify-center">
<div className="w-full relative">
<img
src={profileImg}
src={localImgLoad(`images/icons/${accountDetails.banner}`)}
alt=""
className="sm:w-[180px] sm:h-[180px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
/>
+3 -3
View File
@@ -504,11 +504,11 @@ export default function Icons({ name }) {
></path>
</svg>
) : name === "atm-card" ? (
<img className="w-[20px]" src={ATMCard} alt="card" />
<img className="w-[30px]" src={ATMCard} alt="card" />
) : name === "visa-card" ? (
<img className="w-[20px]" src={VisaCard} alt="card" />
<img className="w-[30px]" src={VisaCard} alt="card" />
) : name === "master-card" ? (
<img className="w-[20px]" src={MasterCard} alt="card" />
<img className="w-[30px]" src={MasterCard} alt="card" />
) : name === "new-dashboard" ? (
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/dashboard.svg')} alt="dashboard" />
) : name === "new-family" ? (
@@ -21,6 +21,9 @@ export default function InputCom({
blurHandler,
spanTag,
inputBg,
onInput,
maxLength = 45,
minLength = 0,
direction,
error,
}) {
@@ -29,13 +32,13 @@ export default function InputCom({
// for Min Length:
const minLengthValidation = () => {
const inputConfig = inputConfigs[inputRef?.current?.name]?.minLength;
return inputConfig || 0;
return inputConfig || minLength;
};
// for MaxLength
const maxLengthValidation = () => {
const inputConfig = inputConfigs[inputRef?.current?.name]?.maxLength;
return inputConfig || 30;
return inputConfig || maxLength;
};
// for Patterns
@@ -63,7 +66,9 @@ export default function InputCom({
</span>
)}
{/* displays error is any */}
{error && <span className="text-[12px] text-red-500 italic">{error}</span>}
{error && (
<span className="text-[12px] text-red-500 italic">{error}</span>
)}
</label>
)}
{forgotPassword && (
@@ -76,18 +81,23 @@ export default function InputCom({
)}
</div>
<div
className={`input-wrapper w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-base ${inputClass ? inputClass : "text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] border"}`}
className={`input-wrapper w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-base ${
inputClass
? inputClass
: "text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] border"
}`}
>
<input
placeholder={placeholder}
value={value}
onChange={inputHandler}
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide ${
inputBg ? inputBg : "bg-[#FAFAFA]"
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}`}
type={type}
id={name}
name={name}
onInput={onInput}
minLength={minLengthValidation()}
maxLength={maxLengthValidation()}
// pattern={inputPatterns()}
@@ -104,10 +114,7 @@ export default function InputCom({
</div>
)}
{passIcon && (
<div
className="absolute right-6 bottom-3 z-10"
onClick={onClick}
>
<div className="absolute right-6 bottom-3 z-10" onClick={onClick}>
<Icons name={passIcon} />
</div>
)}
@@ -117,7 +124,7 @@ export default function InputCom({
}
const inputConfigs = {
email: { minLength: 7, maxLength: 35 },
email: { minLength: 7, maxLength: 45 },
first_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
last_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
address: { minLength: 5, maxLength: 49, pattern: "[a-zA-Z0-9]+" },
@@ -128,7 +135,8 @@ const inputConfigs = {
amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" },
description: { minLength: 5, maxLength: 299 },
title: { minLength: 5, maxLength: 149 },
job_detail: { minLength: 4, maxLength: 1440 }
job_detail: { minLength: 4, maxLength: 1440 },
cardNum: { minLength: 4, maxLength: 19 },
};
/* Numbers Only: <input type="text" pattern="[0-9]*" /> strictly numbers
+2
View File
@@ -7,6 +7,7 @@ export default function SearchCom({
placeholder,
handleSearch,
value,
name,
}) {
return (
<div
@@ -22,6 +23,7 @@ export default function SearchCom({
className={`w-full h-full focus:outline-0 focus:ring-0 dark:bg-dark-white dark:text-white ${
inputClasses || ""
}`}
name={name}
type="text"
onInput={handleSearch}
value={value}
+36
View File
@@ -0,0 +1,36 @@
const TimeDifference = ({ time }) => {
const currentTime = new Date();
const providedTime = new Date(time);
const timeDifference = currentTime - providedTime; // Difference in milliseconds
const minutes = Math.floor(timeDifference / (1000 * 60));
const hours = Math.floor(timeDifference / (1000 * 60 * 60));
const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
const months = Math.floor(timeDifference / (1000 * 60 * 60 * 24 * 30));
if (minutes < 1) {
return "Just now";
} else if (minutes < 60) {
return `${minutes} ${minutes === 1 ? "minute" : "minutes"} ago`;
} else if (hours < 12) {
return `${hours} ${hours === 1 ? "hour" : "hours"} ago`;
} else if (hours < 24) {
return "Today";
} else if (days < 2) {
return "Tomorrow";
} else if (days < 7) {
return `${days} ${days === 1 ? "day" : "days"} ago`;
} else if (months < 1) {
const weeks = Math.floor(days / 7);
return `${weeks} ${weeks === 1 ? "week" : "weeks"} ago`;
} else if (months < 6) {
return `${months} ${months === 1 ? "month" : "months"} ago`;
}else if (months < 8) {
return `"More than 6 months ago"`;
} else {
return time?.split(" ")[0];
}
};
export default TimeDifference;
+7 -7
View File
@@ -217,22 +217,22 @@ export default function History() {
{/* <TopHxBox className="mb-11" /> */}
<div className='w-full p-4 md:p-8 bg-white dark:bg-dark-white rounded-2xl shadow bottomMargin'>
{/* switch button */}
<div className="my-1 flex items-center border-b border-slate-300">
<div className="pl-7 my-2 flex items-center border-b border-slate-300 gap-3">
<button
name="purchases"
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "purchases" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
className={`px-4 py-1 rounded-t-2xl ${
tab == "purchases" ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
}`}
>
Purchases
</button>
<button
name="recent"
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "recent" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
className={`px-4 py-1 rounded-t-2xl ${
tab == "recent" ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
}`}
>
Recent Activity
</button>
@@ -1,11 +1,18 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import ModalCom from "../../Helpers/ModalCom";
import { useMemo, useState } from "react";
import { toast } from "react-toastify";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import ModalCom from "../../Helpers/ModalCom";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
const [textValue, setTextValue] = useState("");
const apiCall = useMemo(() => new usersService(), []);
const handleInputChange = ({ target: { value } }) => {
setTextValue(value);
};
const MarketCalls = (details) => {
const [marketMsg, setMarketMsg] = useState({
loading: false,
@@ -24,8 +31,8 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
const MarketDetail = async () => {
try {
setMarketMsg({ loading: true });
if (!textValue) return;
setMarketMsg({ loading: true });
reqData.yourmessage = textValue;
@@ -87,22 +94,11 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
}
};
// useEffect(() => {
// ManageInterest();
// }, []);
return { MarketDetail, ManageInterest, manageInt, marketMsg };
};
const [textValue, setTextValue] = useState("");
const handleInputChange = ({ target: { value } }) => {
setTextValue(value);
};
const apiCall = useMemo(() => new usersService(), []);
let { manageInt, ManageInterest, MarketDetail, marketMsg } = MarketCalls(details);
let { manageInt, ManageInterest, MarketDetail, marketMsg } =
MarketCalls(details);
let thePrice = PriceFormatter(
details?.price * 0.01,
@@ -270,9 +266,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
Interest: <b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1">
Expire: {details.expire}
</p>
<p className="my-1">Expire: {details.expire}</p>
</div>
</div>
<button
@@ -9,59 +9,61 @@ import PaginatedList from "../Pagination/PaginatedList";
import { handlePagingFunc } from "../Pagination/HandlePagination";
export default function ActiveJobMessage({ activeJobMesList }) {
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentActiveJobMesList = activeJobMesList?.data?.slice(indexOfFirstItem, indexOfLastItem);
// const [currentPage, setCurrentPage] = useState(0);
// const indexOfFirstItem = Number(currentPage);
// const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
// const currentActiveJobMesList = activeJobMesList?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e,setCurrentPage)
}
// const handlePagination = (e) => {
// handlePagingFunc(e,setCurrentPage)
// }
return (
<div className='flex flex-col justify-between h-full'>
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
<th className="p-2"></th>
</tr>
</thead>
{activeJobMesList.data.length ?
(
<tbody>
{currentActiveJobMesList.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td>
<div className="msg_box">
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
</div>
<div className='flex flex-col justify-between'>
<div className="w-full min-h-[450px] max-h-[450px] overflow-y-scroll">
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
<th className="p-2"></th>
</tr>
</thead>
{activeJobMesList?.data?.length ?
(
<tbody>
{activeJobMesList.data.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td>
<div className={`msg_box ${item.who}`}>
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
</div>
</td>
</tr>
))}
</tbody>
)
:
activeJobMesList.error ?
(
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
</tr>
</tbody>
)
:
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>No Message Found!</td>
</tr>
</tbody>
}
</table>
</td>
</tr>
))}
</tbody>
)
:
activeJobMesList.error ?
(
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
</tr>
</tbody>
)
:
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>No Message Found!</td>
</tr>
</tbody>
}
</table>
</div>
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= activeJobMesList?.data?.length ? true : false} data={activeJobMesList?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* <PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= activeJobMesList?.data?.length ? true : false} data={activeJobMesList?.data} start={indexOfFirstItem} stop={indexOfLastItem} /> */}
{/* END OF PAGINATION BUTTON */}
</div>
)
+18 -16
View File
@@ -353,7 +353,7 @@ function ActiveJobs(props) {
</div>
<div className="my-4 py-[20px] bg-white dark:bg-black px-4 rounded-2xl shadow-md lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0">
<div className="w-full lg:w-1/2">
<div className="w-full lg:w-1/2 mb-4 border-b pb-4 lg:pb-0 lg:mb-0 lg:border-b-0">
<div className="">
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
Actions
@@ -367,23 +367,25 @@ function ActiveJobs(props) {
{/* TEXTAREA SECTION */}
<div className="mt-5">
<div className="">
{/* <p className="relative py-2 my-2 text-lg font-bold text-slate-600 dark:text-black border-b-2 border-slate-300 tracking-wide after:absolute after:-bottom-0.5 after:content-[''] after:w-[100px] after:h-[2px] after:bg-sky-blue after:left-0">Message(s)</p> */}
<div className="my-2 flex items-center border-b border-slate-300">
<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={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "message" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
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]"
}`}
>
Send Message
</button>
<button
name="files"
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "files" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
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]"
}`}
>
Send Files
</button>
@@ -402,7 +404,7 @@ function ActiveJobs(props) {
<div className="files">
<label
htmlFor="file"
className="h-20 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"
>
Select Files to Upload
</label>
@@ -457,11 +459,11 @@ function ActiveJobs(props) {
{/* Buttons Sections */}
<div className="py-2 sm:flex sm:justify-end sm:items-center">
<div className="w-full sm:w-2/4 flex justify-between items-center space-x-2">
<div className="w-full sm:w-3/4 flex justify-between items-center space-x-2">
<button
type="button"
onClick={handleClearAll}
className="border-gradient text-base tracking-wide px-4 py-3 rounded-full"
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
>
<span className="text-gradient">Clear</span>
</button>
@@ -469,7 +471,7 @@ function ActiveJobs(props) {
<button
onClick={sendFile}
type="button"
className="btn-gradient text-base tracking-wide px-4 py-3 rounded-full 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" />
@@ -493,7 +495,7 @@ function ActiveJobs(props) {
<button
onClick={sendTaskMessage}
type="button"
className="btn-gradient text-base text-white tracking-wide px-4 py-3 rounded-full"
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" />
@@ -518,9 +520,9 @@ function ActiveJobs(props) {
<button
type="button"
onClick={popUpHandler}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer flex justify-center items-center"
>
view all
View all
</button>
</div>
{props.activeJobMesList.loading ? (
@@ -4,15 +4,15 @@ function CurrentJobAction() {
return (
<div className='job-action dark:bg-black'>
<p className="my-3 py-1 text-base active-owner">
<table className="w-full text-sm text-left text-gray-500">
<table className="w-full text-sm text-left text-gray-500 ">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<div className="flex space-x-2 items-center w-full task_action_panel">
<h1 className="text-xl text-dark-gray dark:text-white">
<div>
Waiting for the completion message from the client before you can approve.
</h1>
</div>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</td>
@@ -62,14 +62,14 @@ function CurrentTaskAction({jobDetails}) {
return (
<div className='job-action dark:bg-black'>
<table className="w-full text-sm text-left text-gray-500 active-worker">
<table className="w-full text-sm text-left text-gray-500 active-worker ">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<h1 className="text-xl text-dark-gray dark:text-white">
<div className="flex space-x-2 items-center w-full task_action_panel">
<div>
I completed this task and ready for review and acceptance.
</h1>
</div>
{/*<div className="flex flex-col flex-[0.9]">*/}
{/*</div>*/}
@@ -107,19 +107,18 @@ function PastDueJobAction({jobDetails}) {
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<div className="flex space-x-2 items-center w-full task_action_panel">
<h1 className="text-xl text-dark-gray dark:text-white">
<div className="dark:text-red-700">
Time allocated has passed
</h1>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</div>
</td>
</tr>
<tr>
<td>
<div className="flex justify-center items-center">
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
<button type="button" onClick={popUpHandler} className="w-[180px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Cancel or Extend Timeline
</button>
</div>
@@ -8,11 +8,11 @@ function PastDueTaskAction() {
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<div className="flex space-x-2 items-center w-full task_action_panel">
<h1 className="text-xl text-dark-gray dark:text-white">
<div>
You have missed the allocated time
</h1>
</div>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</td>
@@ -96,11 +96,11 @@ function ReviewJobAction({jobDetails}) {
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<div className="flex space-x-2 items-center w-full task_action_panel">
<h1 className="text-xl text-dark-gray dark:text-white">
<div>
This Job is Ready for your review
</h1>
</div>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</td>
@@ -2,7 +2,7 @@ import React from 'react'
function ReviewTaskAction() {
return (
<div className='job-action dark:bg-black'>
<div className='job-action dark:bg-black task_action_panel'>
<p className="my-3 py-1 text-base text-dark-gray dark:text-white">
Waiting for the completion message from the client before you can approve. Worker True & Review Job
</p>
+4 -4
View File
@@ -110,13 +110,13 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
return (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className="py-9">
<div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items">
<div className="flex space-x-2 items-center job-items 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/taskbanners/${value.banner}`)} alt="data" className="w-full h-full rounded-full" />
<img src={localImgLoad(`images/taskbanners/${value.banner ? value.banner : 'default.jpg'}`)} 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">
@@ -175,7 +175,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
Assign
</button>
</td>
</tr>
@@ -204,7 +204,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
{MyJobList.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[520px]">
<table className="table-auto min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<>
@@ -6,6 +6,7 @@ import PendingJobsPopout from "../jobPopout/PendingJobsPopout";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import localImgLoad from "../../lib/localImgLoad";
export default function MyPendingJobTable({ MyJobList, className }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
@@ -58,7 +59,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
<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/taskbanners/${value.banner}`)}
src={localImgLoad(`images/taskbanners/${value.banner || "default.jpg"}`)}
alt="data"
className="w-full h-full rounded-full"
/>
+9 -2
View File
@@ -3,13 +3,14 @@ import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import MyPendingJobTable from "./MyPendingJobTable";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function MyPendingJobs(props) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
console.log("AMEYE LOC1", props.MyJobList);
// console.log("AMEYE LOC1", props.MyJobList);
return (
<Layout>
<CommonHead
@@ -35,7 +36,13 @@ export default function MyPendingJobs(props) {
></div>
</div>
</div>
<MyPendingJobTable MyJobList={props.MyJobList} />
{props.MyJobList.loading ?
<div className="bg-white">
<LoadingSpinner size='16' color='sky-blue' height='min-h-[300px]' />
</div>
:
<MyPendingJobTable MyJobList={props.MyJobList.data} />
}
</div>
</div>
</Layout>
@@ -2,7 +2,7 @@ import { useRef, useState } from "react";
import OfferCard from "../Cards/OfferCard";
import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom";
import OfferJobPopout from "../jobPopout/OfferJobPopout";
import FamilyOfferJobPopout from "../jobPopout/FamilyOfferJobPopout";
export default function MyOffersFamilyTable({ className, familyOffers }) {
let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
@@ -127,7 +127,7 @@ export default function MyOffersFamilyTable({ className, familyOffers }) {
{/* Offer Job Popout */}
{offerPopout.show && (
<OfferJobPopout
<FamilyOfferJobPopout
details={offerPopout.data}
onClose={() => {
setOfferPopout({ show: false, data: {} });
-140
View File
@@ -1,140 +0,0 @@
import React, {useState} from 'react'
import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import { useNavigate, useLocation } from 'react-router-dom'
import InputCom from '../Helpers/Inputs/InputCom'
import AddFundDollars from './AddFundDollars'
function AddFund({payment}) {
const navigate = useNavigate()
const {currency} = useLocation()?.state //GETS THE USER CURRENCY FOR ADD FUND
//STATE FOR CONTROLLED INPUT
let [input, setInput] = useState('')
let [inputError, setInputError] = useState('')
// FUNCTION TO HANDLE INPUT CHANGE
const handleChange = ({target:{name, value}}) => {
setInput(value)
}
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = () => {
setInputError('')
if(!input || input == '0'){
setInputError('Please Enter Amount')
return setTimeout(()=>{setInputError('')}, 5000)
}
if(isNaN(input)){
setInputError('Amount must be a Number')
return setTimeout(()=>{setInputError('')}, 5000)
}
const stateData = {amount: Number(input), currency: 'naira'}
navigate('confirm-add-fund', {state: stateData})
setInput('')
}
return (
<div>
{/* heading */}
{/* <div className="sm:flex justify-between items-center mb-6">
<div className="w-full flex justify-start space-x-3 items-center">
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() =>
navigate('/my-wallet', { replace: true })
}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
Add Credit
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div> */}
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
{/*<h2 className='md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Add Credit with Account Deposit</h2>*/}
{/*<hr />*/}
<form className='md:p-8 p-4 add-fund-info'>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label={currency == 'US Dollars' ? "Amount (USD)" : "Amount (Naira)"}
type="text"
name="amount"
placeholder="0"
value={input}
inputHandler={handleChange}
/>
{inputError && <p className='text-base text-red-500'>{inputError}</p>}
</div>
</form>
<hr />
{/* SHOWS THIS IF USER CURRENCY IS DOLLARS */}
{currency == 'US Dollars' &&
<div className='w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow'>
<AddFundDollars setInputError={setInputError} input={input} setInput={setInput} />
</div>
}
{/* HIDES THIS BUTTON IF CURENCY IS NAIRA */}
{currency != 'US Dollars' &&
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
<button
onClick={handleSubmit}
type="button"
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<span className="text-white">Continue</span>
</button>
</div>
}
</div>
</div>
</div>
{/* HIDES THIS SECTION IF CURENCY IS NAIRA */}
{currency != 'US Dollars' &&
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full min-h-[590px] bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={payment}/>
}
</div>
</div>
</div>
}
</div>
)
}
export default AddFund
-137
View File
@@ -1,137 +0,0 @@
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import InputCom from "../Helpers/Inputs/InputCom";
import AddFundDollars from "./AddFundDollars";
function AddFundPop({ _payment, input, setInput, onClose, setConfirmCredit }) {
const navigate = useNavigate();
// const { currency } = useLocation()?.state; //GETS THE USER CURRENCY FOR ADD FUND
let { payment, currency } = _payment;
//STATE FOR CONTROLLED INPUT
let [inputError, setInputError] = useState("");
// FUNCTION TO HANDLE INPUT CHANGE
const handleChange = ({ target: { name, value } }) => {
setInput(value);
};
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = (e) => {
e.preventDefault();
setInputError("");
if (!input || input == "0") {
setInputError("Please Enter Amount");
return setTimeout(() => {
setInputError("");
}, 5000);
}
if (isNaN(input)) {
setInputError("Amount must be a Number");
return setTimeout(() => {
setInputError("");
}, 5000);
}
const stateData = {
amount: Number(input),
currency: currency,
};
return setTimeout(
() =>
setConfirmCredit({
show: true,
data: stateData,
}),
1500
);
};
return (
<div className="h-[33rem] w-full">
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
{/*<h2 className='md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Add Credit with Account Deposit</h2>*/}
{/*<hr />*/}
<form className="md:px-8 md:pt-4 px-4 pt-2 add-fund-info flex items-center gap-[2.1rem]">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{currency == "US Dollars" ? "Amount (USD)" : "Amount (Naira)"}
</h1>
<div className="field w-full max-w-[250px]">
<InputCom
fieldClass="px-6"
type="text"
name="amount"
placeholder="0"
value={input}
inputHandler={handleChange}
/>
<p className="text-base text-red-500 h-5">
{inputError && inputError}
</p>
</div>
</form>
{/* SHOWS THIS IF USER CURRENCY IS DOLLARS */}
{currency == "US Dollars" && (
<div className="w-full md:px-8 md:pt-4 px-4 pt-2 bg-white dark:bg-dark-white rounded-2xl">
<AddFundDollars
setInputError={setInputError}
input={input}
setInput={setInput}
currency={currency}
onClose={onClose}
setConfirmCredit={setConfirmCredit}
/>
</div>
)}
{/* HIDES THIS BUTTON IF CURENCY IS NAIRA */}
{currency != "US Dollars" && (
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={onClose}
>
Cancel
</button>
<button
onClick={handleSubmit}
type="button"
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<span className="text-white">Continue</span>
</button>
</div>
)}
</div>
</div>
</div>
{/* HIDES THIS SECTION IF CURENCY IS NAIRA */}
{currency != "US Dollars" &&
// <div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
// <div className="lg:w-2/2 w-full mb-10 lg:mb-0">
// <div className="wallet w-full md:p-8 p-4 h-full min-h-[590px] bg-white dark:bg-dark-white rounded-2xl shadow">
// <h2 className="text-gray-900 dark:text-white text-xl lg:text-2xl font-medium">
// Recent Activity
// </h2>
// {/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
// {payment?.loading ? (
// <LoadingSpinner size="16" color="sky-blue" />
// ) : (
// <RecentActivityTable payment={payment} />
// )}
// </div>
// </div>
// </div>
null}
</div>
);
}
export default AddFundPop;
+125 -111
View File
@@ -1,115 +1,129 @@
import React, {useState} from 'react'
import { Link } from 'react-router-dom'
import RecentActivityTable from './WalletComponent/RecentActivityTable'
import PurchasesTable from './WalletComponent/PurchasesTable'
import CouponTable from './WalletComponent/CouponTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import { PriceFormatter } from '../Helpers/PriceFormatter'
import React from "react";
import { Link } from "react-router-dom";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import LoadingSpinner from "../Spinners/LoadingSpinner";
function Balance({wallet, coupon}) {
return (
<div className="content-wrapper">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Wallet
</h1>
</div>
<div className="slider-btns flex space-x-4">
</div>
</div>
<div className='w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin'>
{/* WALLET SECTION */}
<div className="lg:w-4/4 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow min-h-[520px]">
<div className='flex items-baseline justify-between'>
{/*<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Wallet</h2>*/}
{/*<p className='text-base text-slate-500 dark:text-white'>Add New Wallet</p>*/}
</div>
{/* wallet balance */}
{wallet.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
wallet.data.length ?
wallet.data.map((item, index)=> (
<div key={index} className="p-3 md:flex items-center flex-wrap my-3 border-t-2 border-slate-400 wallet-box">
<div className='text-slate-900 w-full md:w-1/2 flex space-x-3 items-start justify-start'>
<div className='balance-info bal-col1'>
<p className='py-2'></p>
<span className='text-xl text-dark-gray dark:text-white'><b>{item.description}</b></span>
<p className='text-base text-slate-500'>{item.symbol}</p>
</div>
<div className='balance-info'>
<p className='py-2'>Balance</p>
<span className='py-1 px-2 bg-green-100 text-green-500 rounded-lg flex flex-start gap-1'>{PriceFormatter(item.amount * 0.01, item.code)}</span>
</div>
<div className='balance-info'>
<p className='py-2'>Escrow</p>
<span className='py-1 px-2 bg-red-100 text-red-500 rounded-lg flex flex-start gap-1'>{PriceFormatter(item.escrow * 0.01, item.code)}</span>
</div>
</div>
<div className='w-full my-2 md:my-0 md:w-1/2 flex space-x-2 items-center justify-start md:justify-end'>
{
item.action_type != 'AC_AD_FD_ONLY' ?
<Link to='transfer-fund' className='px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[48px] rounded-full relative bg-purple lg:text-xl text-lg font-bold text-white'>Transfer</Link>:''
}
<Link to='add-fund' state={{currency:item.description}} className='px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[48px] rounded-full relative bg-green lg:text-xl text-lg font-bold text-white'>
<span className="">
<svg xmlns="http://www.w3.org/2000/svg" width="38"
height="38" viewBox="0 0 42 42" fill="none"><path
d="M21 0C16.8466 0 12.7865 1.23163 9.33303 3.53914C5.8796 5.84665 3.18798 9.1264 1.59854 12.9636C0.00909901 16.8009 -0.406771 21.0233 0.403518 25.0969C1.21381 29.1705 3.21386 32.9123 6.15077 35.8492C9.08767 38.7861 12.8295 40.7862 16.9031 41.5965C20.9767 42.4068 25.1991 41.9909 29.0364 40.4015C32.8736 38.812 36.1534 36.1204 38.4609 32.667C40.7684 29.2135 42 25.1534 42 21C41.994 15.4323 39.7796 10.0944 35.8426 6.15741C31.9056 2.22045 26.5677 0.00602189 21 0ZM28 22.75H22.75V28C22.75 28.4641 22.5656 28.9092 22.2374 29.2374C21.9093 29.5656 21.4641 29.75 21 29.75C20.5359 29.75 20.0908 29.5656 19.7626 29.2374C19.4344 28.9092 19.25 28.4641 19.25 28V22.75H14C13.5359 22.75 13.0908 22.5656 12.7626 22.2374C12.4344 21.9092 12.25 21.4641 12.25 21C12.25 20.5359 12.4344 20.0907 12.7626 19.7626C13.0908 19.4344 13.5359 19.25 14 19.25H19.25V14C19.25 13.5359 19.4344 13.0908 19.7626 12.7626C20.0908 12.4344 20.5359 12.25 21 12.25C21.4641 12.25 21.9093 12.4344 22.2374 12.7626C22.5656 13.0908 22.75 13.5359 22.75 14V19.25H28C28.4641 19.25 28.9093 19.4344 29.2374 19.7626C29.5656 20.0907 29.75 20.5359 29.75 21C29.75 21.4641 29.5656 21.9092 29.2374 22.2374C28.9093 22.5656 28.4641 22.75 28 22.75Z"
fill="white"></path>
</svg>
</span>
<span className='text-white'>Add Credit</span>
</Link>
</div>
</div>
))
:
wallet.error ?
(
<div className="md:flex items-center flex-wrap mt-3">
<p className='text-base'>Opps! An Error occurred, please try again</p>
</div>
)
:
(
<div className="md:flex items-center flex-wrap mt-3">
<p className='text-base'>No Wallets Found!</p>
</div>
)
}
{/* end of wallet balance */}
</div>
</div>
{/* END OF WALLET SECTION */}
</div>
{/*<div className='w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin'>*/}
{/* /!* COUPON SECTION *!/*/}
{/* <div className="lg:w-3/4 w-full mb-10 lg:mb-0">*/}
{/* <div className="wallet w-full md:p-8 p-4 h-full max-h-[500px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">*/}
{/* <h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Coupons</h2>*/}
{/* {coupon.loading ?*/}
{/* <LoadingSpinner size='16' color='sky-blue' />*/}
{/* :*/}
{/* <CouponTable coupon={coupon} />*/}
{/* }*/}
{/* </div>*/}
{/* </div>*/}
{/* /!* END OF COUPON SECTION *!/*/}
{/*</div>*/}
function Balance({ wallet, coupon }) {
return (
<div className="content-wrapper">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Wallet
</h1>
</div>
)
<div className="slider-btns flex space-x-4"></div>
</div>
<div className="w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{/* WALLET SECTION */}
<div className="lg:w-4/4 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow min-h-[520px]">
<div className="flex items-baseline justify-between">
{/*<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Wallet</h2>*/}
{/*<p className='text-base text-slate-500 dark:text-white'>Add New Wallet</p>*/}
</div>
{/* wallet balance */}
{wallet.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : wallet.data.length ? (
wallet.data.map((item, index) => (
<div
key={index}
className="p-3 md:flex items-center flex-wrap my-3 border-t-2 border-slate-400 wallet-box"
>
<div className="text-slate-900 w-full md:w-1/2 flex space-x-3 items-start justify-start">
<div className="balance-info bal-col1">
<p className="py-2"></p>
<span className="text-xl text-dark-gray dark:text-white">
<b>{item.description}</b>
</span>
<p className="text-base text-slate-500">{item.symbol}</p>
</div>
<div className="balance-info">
<p className="py-2">Balance</p>
<span className="py-1 px-2 bg-green-100 text-green-500 rounded-lg flex flex-start gap-1">
{PriceFormatter(item.amount * 0.01, item.code)}
</span>
</div>
<div className="balance-info">
<p className="py-2">Escrow</p>
<span className="py-1 px-2 bg-red-100 text-red-500 rounded-lg flex flex-start gap-1">
{PriceFormatter(item.escrow * 0.01, item.code)}
</span>
</div>
</div>
<div className="w-full my-2 md:my-0 md:w-1/2 flex space-x-2 items-center justify-start md:justify-end">
{item.action_type != "AC_AD_FD_ONLY" ? (
<Link
to="transfer-fund"
className="px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[48px] rounded-full relative bg-purple lg:text-xl text-lg font-bold text-white"
>
Transfer
</Link>
) : (
""
)}
<Link
to="add-fund"
state={{ currency: item.description }}
className="px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[48px] rounded-full relative bg-green lg:text-xl text-lg font-bold text-white"
>
<span className="">
<svg
xmlns="http://www.w3.org/2000/svg"
width="38"
height="38"
viewBox="0 0 42 42"
fill="none"
>
<path
d="M21 0C16.8466 0 12.7865 1.23163 9.33303 3.53914C5.8796 5.84665 3.18798 9.1264 1.59854 12.9636C0.00909901 16.8009 -0.406771 21.0233 0.403518 25.0969C1.21381 29.1705 3.21386 32.9123 6.15077 35.8492C9.08767 38.7861 12.8295 40.7862 16.9031 41.5965C20.9767 42.4068 25.1991 41.9909 29.0364 40.4015C32.8736 38.812 36.1534 36.1204 38.4609 32.667C40.7684 29.2135 42 25.1534 42 21C41.994 15.4323 39.7796 10.0944 35.8426 6.15741C31.9056 2.22045 26.5677 0.00602189 21 0ZM28 22.75H22.75V28C22.75 28.4641 22.5656 28.9092 22.2374 29.2374C21.9093 29.5656 21.4641 29.75 21 29.75C20.5359 29.75 20.0908 29.5656 19.7626 29.2374C19.4344 28.9092 19.25 28.4641 19.25 28V22.75H14C13.5359 22.75 13.0908 22.5656 12.7626 22.2374C12.4344 21.9092 12.25 21.4641 12.25 21C12.25 20.5359 12.4344 20.0907 12.7626 19.7626C13.0908 19.4344 13.5359 19.25 14 19.25H19.25V14C19.25 13.5359 19.4344 13.0908 19.7626 12.7626C20.0908 12.4344 20.5359 12.25 21 12.25C21.4641 12.25 21.9093 12.4344 22.2374 12.7626C22.5656 13.0908 22.75 13.5359 22.75 14V19.25H28C28.4641 19.25 28.9093 19.4344 29.2374 19.7626C29.5656 20.0907 29.75 20.5359 29.75 21C29.75 21.4641 29.5656 21.9092 29.2374 22.2374C28.9093 22.5656 28.4641 22.75 28 22.75Z"
fill="white"
></path>
</svg>
</span>
<span className="text-white">Add Credit</span>
</Link>
</div>
</div>
))
) : wallet.error ? (
<div className="md:flex items-center flex-wrap mt-3">
<p className="text-base">
Opps! An Error occurred, please try again
</p>
</div>
) : (
<div className="md:flex items-center flex-wrap mt-3">
<p className="text-base">No Wallets Found!</p>
</div>
)}
{/* end of wallet balance */}
</div>
</div>
{/* END OF WALLET SECTION */}
</div>
{/*<div className='w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin'>*/}
{/* /!* COUPON SECTION *!/*/}
{/* <div className="lg:w-3/4 w-full mb-10 lg:mb-0">*/}
{/* <div className="wallet w-full md:p-8 p-4 h-full max-h-[500px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">*/}
{/* <h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Coupons</h2>*/}
{/* {coupon.loading ?*/}
{/* <LoadingSpinner size='16' color='sky-blue' />*/}
{/* :*/}
{/* <CouponTable coupon={coupon} />*/}
{/* }*/}
{/* </div>*/}
{/* </div>*/}
{/* /!* END OF COUPON SECTION *!/*/}
{/*</div>*/}
</div>
);
}
export default Balance
export default Balance;
-215
View File
@@ -1,215 +0,0 @@
import React, { useState } from "react";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import InputCom from "../Helpers/Inputs/InputCom";
import usersService from "../../services/UsersService";
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
function ConfirmAddFund({ confirmCredit, onClose, walletItem }) {
let { userDetails } = useSelector((state) => state.userDetails); // TO GET LOGGEDIN USER DETAILS
let [pageLoading, setPageLoading] = useState(true);
let [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
status: false,
}); // STATE FOR API REQUEST
const apiURL = new usersService();
const navigate = useNavigate();
//FUNCTION TO HANDLE SUBMIT
const onSuccessPayment = () => {
setRequestStatus({ message: "", loading: true, status: false });
let reqData = { amount: confirmCredit?.data?.account, currency: "NGN" };
apiURL
.startTopUp(reqData)
.then((res) => {
if (res.data.internal_return < 0) {
setRequestStatus({
message: "Could not finish transaction",
loading: false,
status: false,
});
toast.success("Opps! something went wrong");
}
// do something
setRequestStatus({
message: "Topup successful",
loading: false,
status: true,
});
toast.success("Account Topup was sucessful");
setTimeout(() => {
navigate("/my-wallet", { replace: true });
}, 1000);
})
.catch((err) => {
// do something
setRequestStatus({
message: "Opps! An Error Occured",
loading: false,
status: false,
});
toast.success("Opps! something went wrong");
});
};
const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: Date.now(),
amount: confirmCredit?.data?.amount,
currency: "NGN",
payment_options: "card,mobilemoney,ussd",
customer: {
email: `${userDetails.email}`,
phone_number: userDetails.phone,
name: `${userDetails.lastname} ${userDetails.firstname}`,
},
customizations: {
title: "WrenchBoard",
description: "Topup Payment",
logo: "https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg",
},
};
const fwConfig = {
...config,
text: "Proceed",
callback: (response) => {
onSuccessPayment();
closePaymentModal(); // this will close the modal programmatically
},
onClose: () => {},
};
// useEffect(() => {
// // what happens if not data redirect user
// if (!data) {
// navigate("/my-wallet/add-fund", { replace: true });
// } else {
// setPageLoading(false);
// }
// }, []);
let __confirmCard = JSON.parse(confirmCredit?.data.card) || "";
const ThePaymentText = ({ value }) => (
<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">
{value.description} Card
</h1>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
Bank **************{value.digits}
</p>
</div>
</div>
);
return (
<div className="content-wrapper w-full h-[32rem]">
<div className="w-full mb-10">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
{/* <h2 className="md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Confirm Add Fund To Account
</h2>
<hr /> */}
<div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[45px]">
{confirmCredit?.show ? (
<div className="flex flex-col gap-4">
<div className="flex items-center gap-4">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{confirmCredit?.data?.currency == "naira"
? "Amount (Naira):"
: "Amount (Dollars):"}
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{`${walletItem?.symbol} ${
Number(confirmCredit?.data?.amount).toLocaleString() ||
""
}`}
</span>
</div>
<div className="flex items-center gap-4">
{/* <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"> */}
<label
htmlFor="payment"
className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"
>
{confirmCredit?.data?.currency && "Payment Method:"}
</label>
<span className="text-[#181c32] dark:text-white ">
{__confirmCard && (
<ThePaymentText value={__confirmCard} />
)}
</span>
</div>
</div>
) : (
<InputCom
fieldClass="px-6"
label={
confirmCredit?.data?.currency == "naira"
? "Amount (Naira):"
: "Amount (Dollars):"
}
type="text"
name="amount"
value={confirmCredit?.data?.amount || ""}
disable={true}
/>
)}
</div>
</div>
{/* <h1 className="mb-2 text-xl font-bold text-dark-gray dark:text-white px-4 h-5">
{confirmCredit?.data?.currency && "Payment Method"}
</h1> */}
{/* <hr /> */}
<div className="min-h-[220px]"></div>
<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"
onClick={onClose}
>
Cancel
</button>
{confirmCredit?.data?.currency == "naira" ? (
<FlutterWaveButton
{...fwConfig}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
/>
) : (
<button
className="px-4 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={() => console.log("WORKING")}
>
Continue
</button>
)}
</div>
</div>
</div>
{/* <div className="w-full mb-10">
<div className="wallet w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="text-gray-900 dark:text-white text-xl lg:text-2xl font-medium">
Recent Activity
</h2>
<p className='text-base text-gray-600 dark:text-white'>Activity Report</p>
{payment.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<RecentActivityTable payment={payment} />
)}
</div>
</div> */}
</div>
);
}
export default ConfirmAddFund;
+154
View File
@@ -0,0 +1,154 @@
import React, { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
import AddFundDollars from "./AddFundDollars";
function AddFund({ payment }) {
const navigate = useNavigate();
const { currency } = useLocation()?.state; //GETS THE USER CURRENCY FOR ADD FUND
//STATE FOR CONTROLLED INPUT
let [input, setInput] = useState("");
let [inputError, setInputError] = useState("");
// FUNCTION TO HANDLE INPUT CHANGE
const handleChange = ({ target: { name, value } }) => {
setInput(value);
};
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = () => {
setInputError("");
if (!input || input == "0") {
setInputError("Please Enter Amount");
return setTimeout(() => {
setInputError("");
}, 5000);
}
if (isNaN(input)) {
setInputError("Amount must be a Number");
return setTimeout(() => {
setInputError("");
}, 5000);
}
const stateData = { amount: Number(input), currency: "naira" };
navigate("confirm-add-fund", { state: stateData });
setInput("");
};
return (
<div>
{/* heading */}
{/* <div className="sm:flex justify-between items-center mb-6">
<div className="w-full flex justify-start space-x-3 items-center">
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() =>
navigate('/my-wallet', { replace: true })
}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
Add Credit
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div> */}
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
{/*<h2 className='md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Add Credit with Account Deposit</h2>*/}
{/*<hr />*/}
<form className="md:p-8 p-4 add-fund-info">
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label={
currency == "US Dollars" ? "Amount (USD)" : "Amount (Naira)"
}
type="text"
name="amount"
placeholder="0"
value={input}
inputHandler={handleChange}
/>
{inputError && (
<p className="text-base text-red-500">{inputError}</p>
)}
</div>
</form>
<hr />
{/* SHOWS THIS IF USER CURRENCY IS DOLLARS */}
{currency == "US Dollars" && (
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<AddFundDollars
setInputError={setInputError}
input={input}
setInput={setInput}
/>
</div>
)}
{/* HIDES THIS BUTTON IF CURENCY IS NAIRA */}
{currency != "US Dollars" && (
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4">
<button
onClick={handleSubmit}
type="button"
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<span className="text-white">Continue</span>
</button>
</div>
)}
</div>
</div>
</div>
{/* HIDES THIS SECTION IF CURENCY IS NAIRA */}
{currency != "US Dollars" && (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full min-h-[590px] bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="text-gray-900 dark:text-white text-xl lg:text-2xl font-medium">
Recent Activity
</h2>
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
{payment.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<RecentActivityTable payment={payment} />
)}
</div>
</div>
</div>
)}
</div>
);
}
export default AddFund;
@@ -1,29 +1,38 @@
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import usersService from "../../services/UsersService";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { Form, Formik } from "formik";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import * as Yup from "yup";
import Icons from "../Helpers/Icons";
import usersService from "../../../services/UsersService";
import Icons from "../../Helpers/Icons";
import InputCom from "../../Helpers/Inputs/InputCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const validationSchema = Yup.object().shape({
name: Yup.string()
.min(3, "3 chars min.")
.max(50, "50 chars max.")
.required("required"),
cardNum: Yup.string()
.min(3, "3 chars min.")
.max(25, "25 chars max.")
.min(6, "not a card number")
.max(19, "16 chars max.") //16 chars + 3 spaces
.test("luhn-validation", "Invalid Card Number", (value) => {
const sanitizedNumber = value?.replace(/\D/g, "");
const digits = Array?.from(sanitizedNumber, Number);
for (let i = digits.length - 2; i >= 0; i -= 2) {
digits[i] *= 2;
if (digits[i] > 9) {
digits[i] -= 9;
}
}
const sum = digits.reduce((acc, digit) => acc + digit, 0);
return sum % 10 === 0;
})
.required("required"),
code: Yup.string()
.min(3, "3 chars min.")
.max(25, "25 chars max.")
.required("required"),
state: Yup.string()
.min(3, "3 chars min.")
.min(2, "2 chars min.")
.max(25, "25 chars max.")
.required("required"),
address: Yup.string()
@@ -45,7 +54,6 @@ const validationSchema = Yup.object().shape({
});
const initialValues = {
name: "",
cardNum: "",
code: "",
state: "",
@@ -56,24 +64,54 @@ const initialValues = {
};
function AddFundDollars(props) {
const navigate = useNavigate();
const apiCall = new usersService();
let countryWallet = props.walletItem.country;
const [tab, setTab] = useState("previous");
const [loader, setLoader] = useState(false);
const { userDetails } = useSelector((state) => state?.userDetails);
const { firstname, lastname } = userDetails;
const [prevCardDetails, setPrevCardDetails] = useState({});
const [payListCards, setPayListCards] = useState({ loading: true, data: [] });
const [cardIcons, setCardIcons] = useState("atm-card");
const [prevCardError, setPrevCardError] = useState("");
const { firstname, lastname } = userDetails;
// Handling Card Icons
const handleCards = (event) => {
const { name, value } = event.target;
if (name == "cardNum") {
// Check if the first character is 4 or 5 and set the card icon accordingly
const cardIcon =
value.length > 0
? value[0] === "4"
? "visa-card"
: value[0] === "5"
? "master-card"
: "atm-card"
: "atm-card";
setCardIcons(cardIcon);
}
};
// Handling card change
const handleInputChange = (event) => {
const { name, value } = event.target;
setPrevCardDetails((prevState) => ({
...prevState,
[name]: value,
}));
};
// Handling card number grouping
const handleCardNumberChange = (value) => {
return value
?.replace(/\s/g, "") // Remove existing spaces
.match(/.{1,4}/g) // Group every four characters
?.join(" ");
};
// card slicer
const indexOfFirstItem = 0;
const indexOfLastItem =
indexOfFirstItem + Number(process.env.REACT_APP_ITEM_PER_PAGE);
@@ -82,41 +120,80 @@ function AddFundDollars(props) {
indexOfLastItem
);
const handleSubmit = (values, helpers) => {
// Submission for both prev and new cards
const handleSubmit = async (values, helpers) => {
props.setInputError("");
if (!props.input || props.input === "0") {
props.setInputError("Please Enter Amount");
setTimeout(() => props.setInputError(""), 5000);
return;
}
if (isNaN(props.input)) {
props.setInputError("Amount must be a Number");
setTimeout(() => props.setInputError(""), 5000);
return;
}
if (Number(props.input) * 100 > Number(props.walletItem?.transfer_limit)) {
props.setInputError("Credit limit has been exceeded");
setTimeout(() => props.setInputError(""), 5000);
return;
}
if (tab === "previous") {
if (!prevCardDetails) {
// To check if card is empty
if (Object.keys(prevCardDetails).length === 0) {
setPrevCardError("No card selected!");
setTimeout(() => setPrevCardError(""), 5000);
return;
}
setLoader(true);
const stateData = {
amount: Number(props.input),
currency: props.currency,
card: prevCardDetails["payment-card"],
};
return setTimeout(() => {
props.setConfirmCredit({ show: true, data: stateData });
setLoader(false);
}, 1500);
}
if (tab === "new") {
const stateData = {
amount: Number(props.input),
currency: props.currency,
...values,
};
props.setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: true } },
}));
let stateData = {
amount: Number(props.input) * 100,
currency: props.walletItem?.code,
};
try {
const res = await apiCall.getStartCredit(stateData);
if (res.data.internal_return < 0) {
props.setInputError("An Error Occurred");
throw new Error("An Error Occurred");
}
const _response = res.data;
stateData.amount = Number(props.input);
stateData.card =
tab === "previous"
? prevCardDetails["payment-card"]
: { ...values, cvv: values.cvv };
stateData.cardType = tab === "previous" ? "prev" : "new";
stateData = { ...stateData, ..._response };
setTimeout(() => {
props.setConfirmCredit({
show: {
awaitConfirm: { loader: false, state: true },
acceptConfirm: { loader: false, state: false },
},
data: stateData,
});
}, 1500);
} catch (error) {
props.setInputError(error.message);
setTimeout(() => props.setInputError(""), 5000);
props.setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
console.log(error);
}
};
@@ -132,9 +209,7 @@ function AddFundDollars(props) {
});
}, []);
console.log(props)
const handleClose = props.onClose
const handleClose = props.onClose;
return (
<>
@@ -143,7 +218,7 @@ function AddFundDollars(props) {
<div className="flex">
<form className="add-fund-info flex items-center gap-3">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{props.currency == "US Dollars" && "Payment Method"}
{countryWallet == "US" && "Payment Method"}
</h1>
<div className="my-1 flex items-center gap-2">
<label
@@ -185,13 +260,13 @@ function AddFundDollars(props) {
{/* END OF switch button */}
{/* previous tab */}
{tab === "previous" ? (
<div className="p-4 previous-details w-full min-h-[16rem] flex flex-col justify-between items-center">
{tab === "previous" && (
<div className="p-4 previous-details w-full min-h-[16rem] flex flex-col">
{payListCards.loading ? (
<LoadingSpinner size="10" color="sky-blue" />
) : payListCards?.data?.length ? (
<select
className="my-3 w-full rounded-full p-4 outline-none text-base text-black dark:text-gray-100 bg-[#FAFAFA] dark:bg-[#11131F] border"
className="my-3 w-full rounded-full p-2 outline-none text-base text-black dark:text-gray-100 bg-[#FAFAFA] dark:bg-[#11131F] border"
value={prevCardDetails["payment-card"]?.card_uid}
id="payment-card"
name="payment-card"
@@ -231,9 +306,14 @@ function AddFundDollars(props) {
</button>
</div>
)}
<p className="text-base italic text-red-500 h-5">
{prevCardError && prevCardError}
</p>
</div>
) : (
<div className="new-details w-full max-h-[23rem] overflow-y-scroll">
)}
{tab === "new" && (
<div className="new-details w-full max-h-[23rem]">
<div className="w-full flex flex-col justify-between">
<Formik
initialValues={initialValues}
@@ -255,23 +335,27 @@ function AddFundDollars(props) {
<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-[10px]">
<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="master-card visa-card atm-card"
iconName={cardIcons}
label="Card Number"
type="text"
name="cardNum"
onInput={handleCards}
placeholder="Enter Card Number"
value={props.values.cardNum}
value={handleCardNumberChange(
props.values.cardNum
)}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.cardNum}
/>
</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">
@@ -312,7 +396,11 @@ function AddFundDollars(props) {
expireMonth.map((item, index) => (
<option
key={index}
value={item.value}
value={
Number(item.value) < 10
? "0" + item.value
: item.value
}
>
{item.name}
</option>
@@ -321,6 +409,7 @@ function AddFundDollars(props) {
</div>
</div>
</div>
<div className="field w-full mb-6 xl:mb-0 col-span-1">
<div className="select-option">
<div
@@ -368,17 +457,18 @@ function AddFundDollars(props) {
</div>
</div>
<div className="flex items-center flex-1 gap-3 my-[10px]">
{/* Address and 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="atm-card"
iconName={cardIcons}
label="CVV"
type="text"
name="cvv"
placeholder="CVV"
maxLength={3}
value={props.values.cvv}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
@@ -402,16 +492,17 @@ function AddFundDollars(props) {
</div>
{/* Postal Code and State */}
<div className="sm:grid gap-5 grid-cols-3 my-[10px]">
<div className="field w-full mb-6 xl:mb-0 col-span-1">
<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="text"
type="number"
name="code"
placeholder="Postal Code"
value={props.values.code}
maxLength={6}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.code}
@@ -425,7 +516,7 @@ function AddFundDollars(props) {
type="text"
name="state"
placeholder="State"
value={props.values.state}
value={props.values.state.toUpperCase()}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.state}
@@ -436,7 +527,7 @@ function AddFundDollars(props) {
</div>
</div>
<div className="md:px-8 md:pt-4 px-4 pt-2 add-fund-btn flex justify-end items-center gap-3">
<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}
@@ -445,9 +536,9 @@ function AddFundDollars(props) {
</button>
<button
type="submit"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
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"
>
{loader ? (
{props.confirmCredit?.show?.awaitConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
@@ -465,6 +556,7 @@ function AddFundDollars(props) {
</div>
)}
</div>
{tab == "previous" && (
<div className="md:py-8 px-[38px] add-fund-btn flex justify-end items-center gap-4 py-4">
<button
@@ -475,10 +567,11 @@ function AddFundDollars(props) {
</button>
<button
onClick={handleSubmit}
name="previous"
type="button"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
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"
>
{loader ? (
{props.confirmCredit?.show?.awaitConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<span className="text-white">Continue</span>
@@ -0,0 +1,174 @@
import React, { useState } from "react";
import usersService from "../../../services/UsersService";
import Icons from "../../Helpers/Icons";
import InputCom from "../../Helpers/Inputs/InputCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import AddFundDollars from "./AddFundDollars";
function AddFundPop({
_payment,
input,
setInput,
onClose,
confirmCredit,
setConfirmCredit,
walletItem,
}) {
const apiCall = new usersService();
let countryWallet = walletItem?.country;
const { currency } = _payment;
const [inputError, setInputError] = useState("");
let __awaitComponent = confirmCredit.show.awaitConfirm;
const handleChange = ({ target: { name, value } }) => {
setInput(value);
};
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 {
const res = await apiCall.getStartCredit(stateData);
if (res.data.internal_return < 0) {
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
setInputError("An Error Occurred");
setTimeout(() => setInputError(""), 5000);
return;
}
const _response = res.data;
stateData.amount = Number(input);
stateData.currency = currency;
stateData = { ...stateData, ..._response };
setTimeout(() => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: true },
acceptConfirm: { loader: false, state: false },
},
data: stateData,
}));
}, 1500);
} catch (error) {
setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: false } },
}));
console.log(error);
}
};
return (
<div className="h-[33rem] w-full">
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
<form className="md:px-8 md:pt-4 px-4 pt-2 add-fund-info flex items-center gap-[2.1rem]">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Amount({currency})
</h1>
<div className="field w-full max-w-[250px]">
<InputCom
fieldClass="px-6 text-right"
type="text"
name="amount"
placeholder="0"
value={input}
inputHandler={handleChange}
/>
<p className="text-base text-red-500 italic h-5">
{inputError && inputError}
</p>
</div>
</form>
{countryWallet === "US" && (
<div className="w-full md:px-8 md:pt-4 px-4 pt-2 bg-white dark:bg-dark-white rounded-2xl">
<AddFundDollars
setInputError={setInputError}
walletItem={walletItem}
input={input}
setInput={setInput}
currency={currency}
onClose={onClose}
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
/>
</div>
)}
{countryWallet == "NG" && <div className="h-[18rem]"></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"
onClick={onClose}
>
Cancel
</button>
<button
onClick={handleSubmit}
type="button"
className="px-4 py-1 h-11 flex justify-center space-x-1 items-center btn-gradient text-base rounded-full text-white max-w-[100px] w-full"
>
{__awaitComponent.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</>
)}
</button>
</div>
)}
</div>
</div>
</div>
</div>
);
}
export default AddFundPop;
@@ -0,0 +1,116 @@
import React from "react";
function CompleteConfirmCredit({ onClose, confirmCredit }) {
const { data } = confirmCredit;
return (
<div className="logout-modal-body w-full flex flex-col items-center">
<div className="content-wrapper w-full h-[32rem]">
<div className="w-full mb-10">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
<div className="px-4 md:p-8 py-4 add-fund-info">
<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"
}`}
>
{/* 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>
)}
</div>
<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"
? "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>
<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">
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>
</div>
</div>
<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-white text-base rounded-full w-[100px]"
onClick={onClose}
>
Ok
</button>
</div>
</div>
</div>
</div>
</div>
);
}
export default CompleteConfirmCredit;
@@ -0,0 +1,416 @@
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
import React, { useState } from "react";
import { useDispatch, 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";
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;
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>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
Bank **************{value.digits}
</p>
</div>
</div>
);
}
function AmountSection({ currency, amount, country }) {
const formattedAmount = Number(amount).toFixed(2);
return (
<div
className={`flex items-center ${country == "US" ? "gap-14" : "gap-4"}`}
>
<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">
{formattedAmount}
</span>
</div>
);
}
function TransactionFeeSection({ currency, fee, country }) {
const formattedFee = Number(fee).toFixed(2);
return (
<div
className={`flex items-center border-b border-gray-600 ${
country == "US" ? "gap-[2.7rem]" : "gap-4"
}`}
>
<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">
{formattedFee}
</span>
</div>
);
}
function TotalSection({ currency, amount, fee, country }) {
const total = Number(amount) + Number(fee);
const formattedTotal = total.toFixed(2);
return (
<div
className={`flex items-center ${
country == "US" ? "gap-[8rem]" : "gap-[6.3rem]"
}`}
>
<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">
{formattedTotal}
</span>
</div>
);
}
function ConfirmAddFund({
confirmCredit,
onClose,
walletItem,
setConfirmCredit,
}) {
const __confirmData = confirmCredit?.data;
const __confirmCountry = walletItem?.country;
const __confirmCardDetails =
__confirmData.cardType === "prev"
? JSON.parse(__confirmData.card)
: __confirmData.card;
const apiURL = new usersService();
const { userDetails } = useSelector((state) => state?.userDetails);
const dispatch = useDispatch();
const [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
status: false,
});
const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: __confirmData?.credit_reference,
currency: "NGN",
amount: Number(__confirmData.amount),
payment_options: "card,mobilemoney,ussd",
customer: {
email: userDetails.email,
phone_number: userDetails.phone,
name: `${userDetails.lastname} ${userDetails.firstname}`,
},
customizations: {
title: "WrenchBoard",
description: "Add Credit Payment",
logo: "https://www.wrenchboard.com/assets/images/wrench-500-500-icon.png",
},
};
//debugger;
const fwConfig = {
...config,
text: "Proceed",
callback: (response) => {
debouncedSuccessPayment(); //delays the call for 5 secs
setTimeout(() => {
closePaymentModal();
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: response,
}));
}, 1500);
},
};
const onSuccessPayment = () => {
setRequestStatus({ message: "", loading: true, status: false });
const reqData = { tx_ref: __confirmData?.credit_reference };
console.log("**** onSuccessPayment **** THIS WAS REACHED");
apiURL
.resultTopUp(reqData)
.then((res) => {
if (res.data.internal_return < 0) {
setRequestStatus({
message: "Could not finish transaction",
loading: false,
status: false,
});
}
return dispatch(tableReload({ type: "WALLETTABLE" }));
})
.catch((err) => {
setRequestStatus({
message: "Opps! An Error Occured",
loading: false,
status: false,
});
setTimeout(() => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: err,
}));
}, 1500);
toast.success("Opps! something went wrong");
});
};
const debouncedSuccessPayment = debounce(onSuccessPayment, 5000);
const handlePrevCard = async () => {
const { amount, credit_reference, currency } = __confirmData;
const { card_uid } = __confirmCardDetails;
const reqData = {
amount: amount * 100,
card_uid,
credit_reference,
currency,
};
try {
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: true },
},
}));
const res = await apiURL.getPaidPrevCard(reqData);
const _response = res.data;
if (res.data.internal_return < 0) {
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: false },
},
}));
return;
}
setTimeout(() => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: _response,
}));
dispatch(tableReload({ type: "WALLETTABLE" }));
}, 1500);
} catch (error) {
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: false },
},
}));
console.log(error);
}
};
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 {
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: true },
},
}));
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(() => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: _response,
}));
dispatch(tableReload({ type: "WALLETTABLE" }));
}, 1500);
} catch (error) {
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: false },
},
}));
setTimeout(() => onClose, 10000);
console.log(error);
}
};
const getBack = () => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: false },
},
data: {},
}));
};
return (
<div className="content-wrapper w-full h-[32rem]">
<div className="w-full mb-10">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
<div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[45px]">
{confirmCredit?.show?.awaitConfirm?.state && (
<div className="flex flex-col gap-2">
<AmountSection
currency={__confirmData?.currency}
amount={__confirmData?.amount}
country={__confirmCountry}
/>
<TransactionFeeSection
currency={__confirmData?.currency}
fee={__confirmData?.fee}
country={__confirmCountry}
/>
<TotalSection
currency={__confirmData?.currency}
amount={__confirmData?.amount}
fee={__confirmData?.fee}
country={__confirmCountry}
/>
{__confirmCountry === "US" && (
<div className="flex items-center gap-8">
<label
htmlFor="payment"
className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"
>
Payment Method
</label>
<span className="text-[#181c32] dark:text-white">
<ThePaymentText
value={__confirmCardDetails}
type={__confirmData?.cardType}
/>
</span>
</div>
)}
<div
className={`${
__confirmCountry === "US"
? "gap-[3.7rem]"
: "gap-[1.81rem]"
} flex items-center`}
>
<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">
{__confirmData?.credit_reference}
</span>
</div>
</div>
)}
</div>
</div>
<div
className={
__confirmCountry === "US" ? "min-h-[96px]" : "min-h-[157px]"
}
></div>
<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"
onClick={getBack}
>
Back
</button>
{__confirmCountry === "US" && (
<button
className="px-4 h-11 flex justify-center items-center btn-gradient text-white text-base rounded-full"
onClick={
__confirmData?.cardType === "prev"
? handlePrevCard
: handleNewCard
}
>
{confirmCredit?.show?.acceptConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
"Proceed"
)}
</button>
)}
{__confirmCountry === "NG" && (
<FlutterWaveButton
{...fwConfig}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
/>
)}
</div>
</div>
</div>
</div>
);
}
export default ConfirmAddFund;
@@ -0,0 +1,432 @@
import { useState } from "react";
import usersService from "../../../services/UsersService";
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,
wallet,
action,
situation,
state,
setShowNairaWithdraw,
}) {
const apiURL = new usersService();
const dispatch = useDispatch();
let [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
status: false,
});
const [completeNairaWithdraw, setShowCompleteNairaWithdraw] = useState({
show: false,
load: false,
state: {},
}); // DETERMINES WHEN CONFIRM NAIRA WITHDRAWAL POPS UP
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = () => {
setRequestStatus({ message: "", loading: true, status: false });
setShowCompleteNairaWithdraw({ load: true });
let reqData = {
amount: Number(state.amount * 100),
Fee: Number(state.fee),
wallet_uid: wallet.wallet_uid,
};
if (state?.choice === "prev") {
reqData.recipient_uid = state.details?.recipient_uid;
reqData.mode = 100;
}
if (state?.choice === "new") {
reqData.account_no = state?.details?.accountNumber;
reqData.account_type = Number(state?.details?.accountType);
reqData.bank_uid = state?.details?.bank_uid;
reqData.country = state?.details?.country;
reqData.state = state?.details?.state;
reqData.city = state?.details?.city;
reqData.mode = 500;
}
apiURL
.sendMoney(reqData)
.then((res) => {
if (res.data.internal_return < 0) {
// if (res.data?.status_message?.toLowerCase().includes("limit")) {
// setRequestStatus({
// message: ,
// loading: false,
// status: false,
// });
// }
return setTimeout(() => {
setRequestStatus({
message: "",
loading: false,
status: false,
});
setShowCompleteNairaWithdraw({
show: true,
load: false,
state: res.data,
});
}, 5000);
}
setTimeout(() => {
setRequestStatus({
message: "",
loading: false,
status: false,
});
setShowCompleteNairaWithdraw({
show: true,
load: false,
state: res.data,
});
}, 5000);
dispatch(tableReload({ type: "WALLETTABLE" }));
return;
})
.catch((error) => {
setRequestStatus({
message: "Opps! something went wrong! Try Again",
loading: false,
status: false,
});
});
};
return (
<ModalCom action={action} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="w-full">
<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">
<h2 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{completeNairaWithdraw.load ? (
"Confirming..."
) : (
<>
{" "}
{completeNairaWithdraw.show
? completeNairaWithdraw?.state?.internal_return >= 0
? "Transfer Success"
: "Transfer Error"
: `Withdraw from ${wallet.description} Wallet : ${
wallet.symbol
}${(wallet.amount * 0.01).toFixed(2)}`}
</>
)}
</h2>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={action}
>
<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>
<hr />
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
{completeNairaWithdraw.load ? (
<div className="h-[35rem] flex items-center justify-center">
<LoadingSpinner size="12" color="sky-blue" />
</div>
) : completeNairaWithdraw.show ? (
<div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[23rem]">
<div className="flex items-center w-full justify-center mb-3">
{completeNairaWithdraw.state?.sendmoney_message
?.toLowerCase()
?.includes("completed") ? (
<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>
)}
</div>
{completeNairaWithdraw.state?.internal_return >= 0 ? (
<>
<div className={`flex items-center`}>
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.sendmoney_message || ""}
</h1>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Amount(
{completeNairaWithdraw.state
?.terminatingcountrycode || ""}
)
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{Number(
completeNairaWithdraw.state?.TerminatingAmount *
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">
Recipient
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.recitient}
</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">
{completeNairaWithdraw.state?.confirmation}
</span>
</div>{" "}
</>
) : (
<>
<div className={`flex items-center`}>
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("not_found")
? "Wallet Error Occurred"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("recipient_add_error")
? "Recipient Error Occurred"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("limit")
? "Transfer limit Error"
: completeNairaWithdraw.state?.bad_param
?.toLowerCase()
.includes("balance")
? "Insufficient Balance"
: "An Error Occurred"}{" "}
</h1>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Message:
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("not_found")
? "This Wallet is not Found"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("recipient_add_error")
? "No Recipient Found"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("limit")
? "The transfer limit has been exceeded"
: completeNairaWithdraw.state?.bad_param
?.toLowerCase()
.includes("balance")
? "Insufficient Balance for Transaction"
: "Could not perform transaction"}
</span>
</div>
</>
)}
</div>
</div>
) : (
<div className="px-4 md:px-8 py-4 add-fund-info">
<h2 className="my-2 text-slate-900 dark:text-white text-sm xl:text-xl font-medium">
{/* Confirm Withdraw to Account */}
</h2>
{/* AMOUNT */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Amount:"
type="text"
name="amount"
value={state?.amount || ""}
disable={true}
/>
</div>
{state?.choice === "prev" && (
<>
{/* RECIPIENT ACC: */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Recipient Acc:"
type="text"
name="recipient"
value={state?.details?.recipient || ""}
disable={true}
/>
</div>
</>
)}
{state?.choice === "new" && (
<>
{/* RECIPIENT ACC: */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Bank Acc:"
type="text"
name="bank"
value={
`${state?.details?.name} ${state?.details?.country}` ||
""
}
disable={true}
/>
</div>
</>
)}
{/* PROCESSING FEE: */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Processing Fee:"
type="text"
name="processingFee"
value={(state?.fee * 0.01).toFixed(2) || ""}
disable={true}
/>
</div>
{/* TOTAL */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Total"
type="text"
name="total"
value={(state?.total * 0.01).toFixed(2) || ""}
disable={true}
/>
</div>
{/* COMMENT/NOTE */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Comment/Note:"
type="text"
name="comment"
value={state?.comment || ""}
disable={true}
/>
</div>
</div>
)}
{!completeNairaWithdraw.load && (
<>
{" "}
<hr />
<p
className={`text-base ${
requestStatus.status ? "text-green-500" : "text-red-500"
} px-4 md:px-8 py-4 h-5`}
>
{requestStatus.message && requestStatus.message}
</p>
<div className="px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center gap-2">
{!completeNairaWithdraw.show && (
<button
type="button"
onClick={action}
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
>
<span className="text-gradient">Cancel</span>
</button>
)}
<button
onClick={
completeNairaWithdraw.show
? action
: completeNairaWithdraw?.state?.internal_return < 0
? action
: handleSubmit
}
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer min-w-[100px]"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : completeNairaWithdraw.show ? (
"Okay"
) : completeNairaWithdraw?.state?.internal_return < 0 ? (
"Cancel"
) : (
"Transfer"
)}
</button>
</div>
</>
)}
</div>
</div>
</div>
</ModalCom>
);
}
export default ConfirmNairaWithdraw;
@@ -1,8 +1,8 @@
import React, { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import InputCom from "../../Helpers/Inputs/InputCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
import usersService from "../../services/UsersService";
@@ -60,14 +60,6 @@ function ConfirmTransfer({ payment, wallet }) {
});
};
useEffect(() => {
// what happens if not state redirect user
if (!state) {
navigate("/my-wallet/transfer-fund", { replace: true });
} else {
setPageLoading(false);
}
}, []);
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ? (
+53 -57
View File
@@ -1,54 +1,20 @@
import { useState } from "react";
import { useLocation } from "react-router-dom";
import usersService from "../../../services/UsersService";
import ModalCom from "../../Helpers/ModalCom";
import AddFundPop from "../AddFundPop";
import ConfirmAddFund from "../ConfirmAddFund";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import AddFundPop from "./AddFundPop";
import CompleteConfirmCredit from "./CompleteConfirmCredit";
import ConfirmAddFund from "./ConfirmAddFund";
const CreditPopup = ({ details, onClose, situation, walletItem }) => {
const { pathname, state } = useLocation();
const [submitTask, setSubmitTask] = useState({
loading: false,
msg: "",
state: "",
});
const [suggestedNextStep, setSuggestedNextStep] = useState("Send Task");
let [input, setInput] = useState("");
const [confirmCredit, setConfirmCredit] = useState({
show: false,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: false },
},
data: {},
});
// const openConfirmCredit = (value) => {
// setConfirmCredit({ show: true, data: { ...value } });
// };
// const closeConfirmCredit = () => {
// setConfirmCredit({ show: false, data: {} });
// };
// const handleConfirmCredit = useMemo((input) => {
// if (input) {
// setConfirmCredit(true);
// } else setConfirmCredit(false);
// }, []);
const switchNextStep = ({ target: value }) => {
setSuggestedNextStep(value);
};
const apiCall = new usersService();
const handleParentSuggestion = (values) => {
if (suggestedNextStep == "Send Task") {
let firstName = state?.firstname;
let family_uid = state?.family_uid;
// continuePopupData({ ...details, firstName, family_uid });
}
onClose();
};
console.log("prop drills >> ", state);
return (
<ModalCom
action={onClose}
@@ -58,7 +24,21 @@ 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 ? "Add Credit" : "Confirm Credit Add"}
{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"}
</>
)}
</h1>
<button
type="button"
@@ -87,21 +67,37 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center">
{confirmCredit.show ? (
<ConfirmAddFund
confirmCredit={confirmCredit}
walletItem={walletItem}
onClose={onClose}
/>
{confirmCredit?.show?.acceptConfirm?.loader ? (
<div className="h-[32rem] flex items-center justify-center">
<LoadingSpinner size="12" color="sky-blue" />
</div>
) : (
<AddFundPop
_payment={details}
input={input}
setInput={setInput}
onClose={onClose}
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
/>
<>
{confirmCredit?.show?.awaitConfirm?.state ? (
<ConfirmAddFund
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
walletItem={walletItem}
onClose={onClose}
/>
) : confirmCredit?.show?.acceptConfirm?.state ? (
<CompleteConfirmCredit
walletItem={walletItem}
confirmCredit={confirmCredit}
onClose={onClose}
/>
) : (
<AddFundPop
_payment={details}
walletItem={walletItem}
input={input}
setInput={setInput}
onClose={onClose}
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
/>
)}
</>
)}
</div>
</div>
@@ -0,0 +1,831 @@
import { Form, Formik } from "formik";
import React, { useEffect, useState } from "react";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import ModalCom from "../../Helpers/ModalCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
function NairaWithdraw({
wallet,
action,
situation,
state,
setShowConfirmNairaWithdraw,
}) {
const apiCall = new usersService();
const [tab, setTab] = useState("previous");
let [requestStatus, setRequestStatus] = useState(false);
const initialValues = {
amount: state?.amount || "",
comment: state?.comment || "",
previousAccount: {
recipientID: state?.previousAccount?.recipientID || "",
},
newAccount: {
country: state?.newAccount?.amount || "",
bank: state?.newAccount?.amount || "",
accountNumber: state?.newAccount?.amount || "",
accountType: state?.newAccount?.amount || "",
state: state?.newAccount?.amount || "",
city: state?.newAccount?.amount || "",
},
};
const [errorMsgs, setErrorMsgs] = useState(initialValues);
let [sendMoneyFee, setSendMoneyFee] = useState({
loading: false,
fee: 0,
total: 0,
}); // HOLD THE VALUE FOR walletSEND MONEY FEE
// Previous Account
let [recipients, setRecipients] = useState({
// FOR COUPON HISTORY
loading: true,
data: [],
error: false,
});
// New Account
let [allCountries, setAllCountries] = useState({
// STATE TO HOLD LIST OF COUNTRIES
loading: true,
data: [],
});
let [bankName, setBankName] = useState({
// STATE TO HOLD LIST OF BANK NAME
loading: false,
data: [],
});
let [accType, setAccType] = useState({
// STATE TO HOLD LIST ACCOUNT TYPE
loading: true,
data: [],
});
// Handling card change
const handleBankOptions = (event) => {
const { value } = event.target;
setBankName((prev) => ({ loading: true, data: [] }));
apiCall
.getCountryBank({ country: value })
.then((res) => {
if (res.data.internal_return < 0) {
setBankName((prev) => ({ loading: false, data: [] }));
return;
}
setBankName((prev) => ({ loading: false, data: res.data.result_list }));
})
.catch((error) => {
setBankName((prev) => ({ loading: false, data: [] }));
});
};
//FUNCTION TO GET RECIPIENT LIST
const getRecipients = () => {
apiCall
.getRecipient()
.then((res) => {
if (res.data.internal_return < 0) {
// success but no data
setRecipients((prev) => ({ ...prev, loading: false }));
return;
}
setRecipients((prev) => ({
...prev,
loading: false,
data: res.data.result_list,
}));
})
.catch((error) => {
setRecipients((prev) => ({ ...prev, loading: false, error: true }));
});
};
// FUNCTION TO GET COUNTRIES
const getCountry = () => {
apiCall
.getSignupCountryData()
.then((res) => {
if (res.data.internal_return < 0) {
setAllCountries((prev) => ({ loading: false, data: [] }));
return;
}
setAllCountries((prev) => ({
loading: false,
data: res.data.signup_country,
}));
})
.catch((error) => {
setAllCountries((prev) => ({ loading: false, data: [] }));
});
};
// FUNCTION TO GET ACCOUNT TYPES
const getAccountTypes = () => {
apiCall
.getAccountTypes()
.then((res) => {
if (res.data.internal_return < 0) {
setAccType((prev) => ({ loading: false, data: [] }));
return;
}
setAccType((prev) => ({ loading: false, data: res.data.result_list }));
})
.catch((error) => {
setAccType((prev) => ({ loading: false, data: [] }));
});
};
useEffect(() => {
getCountry(); // TO LOAD LIST COUNTRY
getAccountTypes(); // TO LOAD LIST ACCOUNT TYPES
}, []);
//FUNCTION TO GET SEND MONEY FEE
const getSendMoneyFee = ({ target: { value } }) => {
setSendMoneyFee({ loading: true, fee: 0, total: 0 });
let amount = value;
if (Number(amount) <= 0 || amount == "" || isNaN(amount)) {
setSendMoneyFee({ loading: false, fee: 0, total: 0 });
return;
}
apiCall
.getSendMoneyFee(Number(amount * 100))
.then((res) => {
setSendMoneyFee({
loading: false,
fee: res.data.processing_fee,
total: res.data.total_amount,
});
})
.catch((error) => {
setSendMoneyFee({ loading: false, fee: 0, total: 0 });
});
};
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = async (values, helpers) => {
try {
if (!values?.amount) {
setErrorMsgs({ amount: "amount required" });
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
return;
}else if (Number(values.amount * 100) > Number(wallet?.transfer_limit)) {
setErrorMsgs({ amount: "Withdraw limit has been exceeded" });
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
return;
}
if (values?.comment?.length >= 50) {
setErrorMsgs({ comment: "50 chars max" });
setTimeout(() => setErrorMsgs({ comment: "" }), 1000);
}
// form submission logic here
if (tab === "previous") {
if (!values?.previousAccount?.recipientID) {
setErrorMsgs({
previousAccount: { recipientID: "Please select an option" },
});
setTimeout(
() => setErrorMsgs({ previousAccount: { recipientID: "" } }),
1000
);
}
setRequestStatus(true);
// Ensure recipientDetails is an array and not undefined
const recipientDetails = recipients.data?.filter(
(item) => item.recipient_uid === values.previousAccount?.recipientID
);
// Ensure recipientDetails is not empty
if (!recipientDetails || recipientDetails.length === 0) {
// Handle the case when recipientDetails is empty or undefined
setRequestStatus(false);
return;
}
const stateData = {
amount: values.amount,
comment: values.comment,
choice: "prev",
wallet_uid: wallet.wallet_uid,
...sendMoneyFee,
details: { ...recipientDetails[0] },
};
return setTimeout(() => {
setRequestStatus(false);
// navigate("confirm-withdraw-naira", { state: stateData });
action();
setShowConfirmNairaWithdraw({ show: true, state: stateData });
}, 1000);
}
if (tab === "new") {
const { accountNumber, accountType, bank, city, country, state } =
values?.newAccount;
if (
!accountNumber ||
!accountType ||
!bank ||
!city ||
!country ||
!state
) {
return;
}
setRequestStatus(true);
// Ensure bankDetails is an array and not undefined
const bankDetails = bankName.data?.filter(
(item) => item.bank_uid === bank
);
// Ensure bankDetails is not empty
if (!bankDetails || bankDetails.length === 0) {
// Handle the case when bankDetails is empty or undefined
setRequestStatus(false);
return;
}
const stateData = {
amount: values.amount,
comment: values.comment,
choice: "new",
wallet_uid: wallet.wallet_uid,
...sendMoneyFee,
details: { ...bankDetails[0], ...values?.newAccount },
};
return setTimeout(() => {
setRequestStatus(false);
action();
setShowConfirmNairaWithdraw({ show: true, state: stateData });
}, 1000);
}
} catch (errors) {
// If validation fails, handle the validation errors
throw new Error("Validation errors:", errors);
}
};
useEffect(() => {
getRecipients();
}, []);
return (
<ModalCom action={action} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="w-full">
<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">
{`Withdraw from ${wallet.description} Wallet : ${wallet.symbol}${(
wallet.amount * 0.01
).toFixed(2)}`}
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={action}
>
<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="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white h-full rounded-2xl">
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
{(props) => {
return (
<Form className="transfer-fund-info">
{/* Amount Form */}
<div className="flex flex-col">
<div className="field w-full">
<InputCom
fieldClass="px-4 text-end"
parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.4] mb-0"
inputClass="flex-[0.6] max-w-[12rem]"
label="Amount:"
type="number"
name="amount"
placeholder="0"
value={props.values.amount}
inputHandler={props.handleChange}
blurHandler={(e) => {
getSendMoneyFee(e);
}}
error={errorMsgs.amount && errorMsgs.amount}
/>
</div>
<div className="field w-full">
<InputCom
fieldClass="px-4 transfer-field"
parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
label="Fee:"
type="text"
name="fee"
direction="rtl"
value={
sendMoneyFee.loading
? "loading"
: (sendMoneyFee.fee * 0.01).toFixed(2)
}
disable={true}
/>
</div>
<div className="field w-full">
<InputCom
fieldClass="px-4 transfer-field"
parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
label="Total:"
type="text"
name="total"
direction="rtl"
value={
sendMoneyFee.loading
? "loading"
: (sendMoneyFee.total * 0.01).toFixed(2)
}
disable={true}
/>
</div>
<div className="field w-full mb-3 flex gap-1 justify-between">
<label className="text-[#181c32] dark:text-white text-base font-semibold flex flex-[0.2] mt-2.5">
Comment:
</label>
<textarea
style={{ resize: "none" }}
className="text-base px-4 py-2 rounded-md sm:max-w-[550px] max-w-[250px] text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none flex-[0.8]"
name="comment"
value={props.values.comment}
onChange={props.handleChange}
onBlur={props.handleBlur}
cols="30"
rows="2"
/>
</div>
</div>
{/* Account Selector */}
<div className=" flex items-center gap-[8rem]">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
To:
</h1>
<div className="my-1 flex items-center gap-2">
<label
onClick={() => setTab("previous")}
htmlFor="previous"
className="cursor-pointer flex items-center gap-1"
>
<input
type="radio"
id="previous"
name="choice"
value="previous"
checked={tab === "previous"}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border pointer-events-none w-7 h-7 ${
tab == "previous" ? "" : ""
} tracking-wide transition duration-200`}
/>
Previous Account
</label>
<label
onClick={() => setTab("new")}
htmlFor="new"
className="cursor-pointer flex items-center gap-1"
>
<input
id="new"
type="radio"
name="choice"
value="new"
checked={tab === "new"}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border pointer-events-none w-7 h-7 ${
tab == "new" ? "" : ""
} tracking-wide transition duration-200`}
/>
New Account{" "}
</label>
</div>
</div>
<div className="">
{tab == "previous" && (
<>
<div className="w-full">
<div className="relative my-3 md:flex items-center px-4">
<div className="transfer-input w-full flex items-center justify-end">
{/* <label className="text-[#181c32] dark:text-white text-base font-semibold block flex-[0.2] mb-0 mt-3"></label> */}
<div className="flex flex-col gap-3 flex-[0.8] items-center">
<select
className="sm:w-full w-48 text-dark-gray border-slate-300 outline-0 flex-[0.8] my-3 rounded-full p-2 outline-none text-base dark:text-gray-100 bg-[#FAFAFA] dark:bg-[#11131F] border appearance-none"
value={
props.values.previousAccount?.recipientID
}
name="previousAccount.recipientID"
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{recipients.loading ? (
<option
className="text-slate-500 text-lg"
value=""
>
Loading...
</option>
) : recipients.data.length ? (
<>
<option
className="text-slate-500 text-lg"
value=""
>
{errorMsgs.previousAccount
?.recipientID
? errorMsgs.previousAccount
.recipientID
: "Select an account"}
</option>
{recipients.data.map((item, index) => (
<option
key={index}
value={item.recipient_uid}
className="text-slate-500 text-lg"
>
{item.recipient}
</option>
))}
</>
) : recipients.error ? (
<option
className="text-slate-500 text-lg"
value=""
>
Could'nt load, !
</option>
) : (
<option
className="text-slate-500 text-lg"
value=""
>
No Recipient Found!
</option>
)}
</select>
<div className="flex justify-end relative w-full">
{errorMsgs.previousAccount?.recipientID &&
errorMsgs.previousAccount
?.recipientID && (
<p className="sm:text-sm text-[12px] text-red-500 absolute sm:top-1 -top-20 sm:left-0 left-[160px]">
{
errorMsgs.previousAccount
?.recipientID
}
</p>
)}
</div>
</div>
</div>
</div>
</div>
<div className="h-[7.8rem]"></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 */}
</div>
</div>
)}
</div>
<div className="transfer-fund-btn flex justify-end items-center gap-2 py-4">
<button
type="button"
onClick={action}
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
>
<span className="text-gradient">Cancel</span>
</button>
<button
type="submit"
disabled={
props.isSubmitting || sendMoneyFee.loading
? true
: false
}
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer min-w-[100px] flex justify-center items-center"
>
{requestStatus ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
"Continue"
)}
</button>
</div>
</Form>
);
}}
</Formik>
</div>
</div>
</div>
</ModalCom>
);
}
export default NairaWithdraw;

Some files were not shown because too many files have changed in this diff Show More