Compare commits

...

162 Commits

Author SHA1 Message Date
Ebube a868713ae3 Added family pending component 2023-07-06 15:02:26 +01:00
ameye e68603d836 Merge branch 'family-offer-hidden' of WrenchBoard/Users-Wrench into master 2023-07-06 11:48:40 +00:00
victorAnumudu 67e227c554 hides family offer list when none 2023-07-06 12:39:39 +01:00
ameye f6fc004a06 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-06 10:21:44 +00:00
ameye 1682a2221f Merge branch 'family-dash-revamp' of WrenchBoard/Users-Wrench into master 2023-07-06 10:21:33 +00:00
victorAnumudu b16b356532 family offer new layout 2023-07-06 11:01:54 +01:00
victorAnumudu 62b97d903c family dashboard active and waiting list revamp 2023-07-06 07:06:53 +01:00
Ebube abef3bec01 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-06 06:33:54 +01:00
Ebube 626835e1e0 Parent Waiting View Added & Market Link goes to bad page fixed 2023-07-06 06:33:33 +01:00
ameye a6d68bc856 Merge branch 'family-current-task' of WrenchBoard/Users-Wrench into master 2023-07-05 19:55:29 +00:00
victorAnumudu a674688dce family current task added 2023-07-05 20:52:34 +01:00
ameye ef339b163d Merge branch 'cookie-fixing' of WrenchBoard/Users-Wrench into master 2023-07-05 16:54:23 +00:00
victorAnumudu 1ce154cc06 cookie bug fixing 2023-07-05 17:48:40 +01:00
victorAnumudu 67eb142ae2 cookie bug fixing 2023-07-05 17:47:05 +01:00
ameye e784d84699 Merge branch 'cookie-value-reading' of WrenchBoard/Users-Wrench into master 2023-07-05 16:10:01 +00:00
CHIEFSOFT\ameye cd6d540c4b Family Activer Job 2023-07-05 11:12:08 -04:00
victorAnumudu b2beaa7c2b changed how the value of login type is read from the cookie 2023-07-05 15:40:05 +01:00
ameye b0db896f6b Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-05 14:15:03 +00:00
CHIEFSOFT\ameye fafea8b1ad Task banners 2023-07-05 10:13:19 -04:00
Ebube bbb099d51f Modified status for family waitlist 2023-07-05 14:51:24 +01:00
Ebube bfc0521e54 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-05 14:45:51 +01:00
Ebube 6870c145d7 Added banner name to suggested task payload 2023-07-05 14:45:29 +01:00
ameye c18373f9db Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-05 13:34:21 +00:00
CHIEFSOFT\ameye 24ac0daf29 status_text 2023-07-05 08:58:08 -04:00
Ebube 4dd58b16d8 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-05 13:52:39 +01:00
Ebube cc66ebbbde Family waitlist complete 2023-07-05 13:51:10 +01:00
CHIEFSOFT\ameye 3d61b3259d Status label 2023-07-05 08:32:00 -04:00
CHIEFSOFT\ameye 40b614356f active task spread 2023-07-05 08:17:57 -04:00
ameye dbba6c4014 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-05 11:56:34 +00:00
Ebube ae93de5f25 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-05 12:53:41 +01:00
Ebube 4904f1d398 Added waiting component and rendered the offerlist 2023-07-05 12:53:19 +01:00
ameye 880b084547 Merge branch 'cookie-bug-fix' of WrenchBoard/Users-Wrench into master 2023-07-05 10:26:39 +00:00
victorAnumudu c807a2657b adjusted cookie to check for login type before components mounts 2023-07-05 10:24:01 +01:00
ameye 37a0ffed27 Merge branch 'cookies-family-dash-changes' of WrenchBoard/Users-Wrench into master 2023-07-05 08:17:28 +00:00
victorAnumudu 067d9ca5d1 suggest image position adjusted 2023-07-05 08:50:56 +01:00
victorAnumudu 6e3061b9db cookie bug fix and family dash style changes made 2023-07-05 04:39:39 +01:00
CHIEFSOFT\ameye 4f9ca918c9 more graphics 2023-07-04 18:16:32 -04:00
ameye 12f805f0a7 Merge branch 'login-page-box' of WrenchBoard/Users-Wrench into master 2023-07-04 19:43:14 +00:00
CHIEFSOFT\ameye 175ac7e2b6 coffee added 2023-07-04 15:25:05 -04:00
victorAnumudu bb0796d1e6 login input text changed and padding on login page reduced 2023-07-04 19:22:36 +01:00
CHIEFSOFT\ameye c0d01e05fe defualt 2023-07-04 13:51:38 -04:00
CHIEFSOFT\ameye 38a888a8a1 clean dishes 2023-07-04 13:48:55 -04:00
CHIEFSOFT\ameye 8b0aedcbf2 wash cloth 2023-07-04 13:29:13 -04:00
CHIEFSOFT\ameye dfdccc0287 Clean Room 2023-07-04 13:10:46 -04:00
CHIEFSOFT\ameye 12512cef97 wash cars image 2023-07-04 13:00:28 -04:00
ameye d5d0e64070 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-04 15:27:51 +00:00
Ebube d55f7ce175 Correct layout and button 2023-07-04 15:45:19 +01:00
ameye f81b687f9f Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-04 14:04:17 +00:00
Ebube 3de1ef71c9 Fixed the empty params and fixed broken offer link 2023-07-04 15:00:00 +01:00
ameye fe7d23837c Merge branch 'enable-job-bg-color' of WrenchBoard/Users-Wrench into master 2023-07-04 13:07:44 +00:00
victorAnumudu bdc000fb8e Enable job background color changed to alice blue 2023-07-04 13:57:12 +01:00
ameye 01f8c7b49b Merge branch 'family-dashboard' of WrenchBoard/Users-Wrench into master 2023-07-04 12:26:17 +00:00
ameye 05384fe001 Merge branch 'family-task-page' of WrenchBoard/Users-Wrench into master 2023-07-04 12:26:09 +00:00
ameye 66a43ac636 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-04 12:25:36 +00:00
victorAnumudu 0ff4e5cf1e btn color 2023-07-04 10:56:53 +01:00
Ebube 6c0a107919 . 2023-07-04 10:39:00 +01:00
Ebube 5c8d1e72dd . 2023-07-04 10:38:35 +01:00
Ebube 4b11d7ec77 . 2023-07-04 10:38:22 +01:00
victorAnumudu baf2ca155f common header removed for family account on my task page 2023-07-04 10:33:37 +01:00
CHIEFSOFT\ameye fffc51d77a defualt added 2023-07-04 03:23:40 -04:00
ameye c622d73058 Merge branch 'family-suggest-list' of WrenchBoard/Users-Wrench into master 2023-07-04 07:02:18 +00:00
victorAnumudu d0237872ad added family suggest list API 2023-07-04 07:32:40 +01:00
ameye 4403c8650e Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-04 04:29:04 +00:00
Ebube 2afffb1dc9 Added Popup for suggest task 2023-07-04 03:37:56 +01:00
ameye 3a72ebc7a0 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-03 19:26:19 +00:00
Ebube ecfef0d6e1 modified validation rules 2023-07-03 20:13:45 +01:00
Ebube 7abf4fb7f7 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-03 19:40:55 +01:00
ameye 6c601a605a Merge branch 'input-error-changed' of WrenchBoard/Users-Wrench into master 2023-07-03 18:38:30 +00:00
Ebube 4480e2ebd6 removed validation 2023-07-03 19:34:38 +01:00
victorAnumudu 9f11e8b415 input error position changed 2023-07-03 19:32:18 +01:00
CHIEFSOFT\ameye a1d74b773d family pictures 2023-07-02 19:30:48 -04:00
ameye 7969199584 Merge branch 'blog-count' of WrenchBoard/Users-Wrench into master 2023-07-02 21:44:55 +00:00
victorAnumudu 9dd8f49ff8 blog count implemented 2023-07-02 22:12:28 +01:00
ameye fa5e9b8107 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-02 16:56:36 +00:00
Ebube 3e7ab11e62 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-02 17:40:38 +01:00
Ebube 6f259ad8ad . 2023-07-02 16:24:49 +01:00
ameye a31a20652f Merge branch 'resources-blog-tab' of WrenchBoard/Users-Wrench into master 2023-07-02 11:52:54 +00:00
victorAnumudu e3a5952675 made blog component to show first when resources link is hit 2023-07-02 08:10:10 +01:00
ameye f48297c5c0 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-02 02:07:31 +00:00
Ebube 23e5a9aaa4 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-02 03:03:08 +01:00
Ebube 02d90ebb14 Family market added 2023-07-02 03:02:29 +01:00
ameye 38b979a2e9 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-02 00:49:02 +00:00
Ebube 93d9afa417 Moved Offer Table to Dash 2023-07-02 01:34:27 +01:00
ameye 1e2219fb00 Merge branch 'banner-feedback' of WrenchBoard/Users-Wrench into master 2023-07-01 23:07:43 +00:00
victorAnumudu 560897f6f9 banner feedback fixed 2023-07-01 22:29:28 +01:00
ameye 630a029c6e Merge branch 'radio-btn-fix' of WrenchBoard/Users-Wrench into master 2023-07-01 20:26:41 +00:00
ameye 6e2fdc46d1 Merge branch 'add-task-btn-position' of WrenchBoard/Users-Wrench into master 2023-07-01 20:26:37 +00:00
victorAnumudu d3b2cddd6c radio btn size fixed 2023-07-01 21:24:25 +01:00
CHIEFSOFT\ameye f6bd70fdca Change text 2023-07-01 16:17:48 -04:00
victorAnumudu de3bfa2541 add task btn position changed 2023-07-01 19:36:26 +01:00
CHIEFSOFT\ameye cd60831f76 Blog Respurces 2023-07-01 12:44:31 -04:00
ameye 71152f7a05 Merge branch 'manage-family-active-task' of WrenchBoard/Users-Wrench into master 2023-07-01 15:28:38 +00:00
victorAnumudu 8cbdb1b8a6 manage family active task forward and back btn fixed 2023-07-01 16:25:34 +01:00
ameye abbf60ad48 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-01 10:51:21 +00:00
Ebube c956befed9 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-01 10:38:29 +01:00
Ebube a5dbeaecbf Fixed Offer Popup 2023-07-01 10:37:59 +01:00
CHIEFSOFT\ameye 0b0b563dda parennt waiting 2023-07-01 00:22:08 -04:00
CHIEFSOFT\ameye f8a3e42fe6 Kids waiting 2023-06-30 23:41:09 -04:00
CHIEFSOFT\ameye ced88fa497 no task image 2023-06-30 21:19:59 -04:00
ameye 89e2527ba6 Merge branch 'assign-task-bug-fix' of WrenchBoard/Users-Wrench into master 2023-07-01 00:06:19 +00:00
victorAnumudu 9e6b59624f Delivery detail bug fixed 2023-07-01 01:01:37 +01:00
ameye 1b6b4f17b0 Merge branch 'assign-task-revamp' of WrenchBoard/Users-Wrench into master 2023-06-30 23:12:55 +00:00
victorAnumudu 8a9ec35994 Assign family task API consumed 2023-07-01 00:06:22 +01:00
tokslaw fa2102eb61 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-06-30 18:21:38 +00:00
tokslaw bf73461c64 Merge branch 'price-fix' of WrenchBoard/Users-Wrench into master 2023-06-30 18:21:25 +00:00
victorAnumudu 5ffa6eb691 price fix 2023-06-30 16:01:11 +01:00
Ebube 5a0d8aebdb 1280 width fixed 2023-06-30 13:48:52 +01:00
Ebube e8ed10ddbf Added link to Family Market 2023-06-30 13:28:44 +01:00
ameye cca423a41c Merge branch 'family-assign-task' of WrenchBoard/Users-Wrench into master 2023-06-30 11:08:57 +00:00
victorAnumudu 6a6900a62b family assign task popout added 2023-06-30 11:57:47 +01:00
ameye c6b4fcc43d Merge branch 'delete-edit-icon' of WrenchBoard/Users-Wrench into master 2023-06-29 18:25:39 +00:00
ameye 29510c3b85 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-06-29 18:25:34 +00:00
victorAnumudu 1d8e54c57d delete and edit icon seperator width reduced 2023-06-29 13:56:14 +01:00
victorAnumudu 426599dd1f delete and edit icons added 2023-06-29 13:52:33 +01:00
Ebube c8d6d3d7d4 Removed Bg Img 2023-06-29 13:39:07 +01:00
Ebube 593ea74388 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-06-29 13:37:04 +01:00
Ebube d81b9970b3 Improved folder structure for resources and clean up 2023-06-29 13:18:31 +01:00
ameye 777ff54220 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-06-29 10:37:20 +00:00
Ebube 382a266b9a Resource Page Data Mapping 2023-06-29 09:09:30 +01:00
ameye 2d80dd9450 Merge branch 'no-interest-table-hidden' of WrenchBoard/Users-Wrench into master 2023-06-28 15:56:41 +00:00
victorAnumudu 0eaa72a5ec made others interest table hidden if its empty 2023-06-28 16:42:16 +01:00
CHIEFSOFT\ameye a2e2df867d resource props 2023-06-28 10:41:08 -04:00
ameye 10d4e169d3 Merge branch 'manage-active-job-delivery-date' of WrenchBoard/Users-Wrench into master 2023-06-28 13:38:48 +00:00
Ebube 79ed578483 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into manage-active-job-delivery-date 2023-06-28 14:10:42 +01:00
Ebube 25440a3c06 fixed minor bug 2023-06-28 14:10:14 +01:00
ameye 5f4c40a318 Merge branch 'manage-active-job-delivery-date' of WrenchBoard/Users-Wrench into master 2023-06-28 01:06:13 +00:00
Ebube ff7e8ea1ab Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into manage-active-job-delivery-date 2023-06-28 02:02:27 +01:00
Ebube cba14f4265 Added error borders 2023-06-28 02:01:53 +01:00
ameye 9c342f87f7 Merge branch 'manage-active-job-delivery-date' of WrenchBoard/Users-Wrench into master 2023-06-27 21:01:38 +00:00
Ebube 498966dd23 Fixed bugs in market popup and made changes to Add/edit 2023-06-27 21:57:39 +01:00
ameye b282295924 Merge branch 'manage-active-job-delivery-date' of WrenchBoard/Users-Wrench into master 2023-06-27 18:21:46 +00:00
Ebube 7222a4d750 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into manage-active-job-delivery-date 2023-06-27 17:12:02 +01:00
Ebube 271f5635a0 Fixed Api Parameter, Banner Button Style and Slider header 2023-06-27 17:11:30 +01:00
ameye 86c4283507 Merge branch 'manage-active-job-delivery-date' of WrenchBoard/Users-Wrench into master 2023-06-27 14:19:36 +00:00
Ebube 5e5d953769 Add Job button Fixed 2023-06-27 15:15:41 +01:00
ameye aa7065c5b4 Merge branch 'manage-active-job-delivery-date' of WrenchBoard/Users-Wrench into master 2023-06-27 14:10:27 +00:00
Ebube 29fee11ec3 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into manage-active-job-delivery-date 2023-06-27 13:49:24 +01:00
Ebube 264d7b8501 . 2023-06-27 13:48:54 +01:00
ameye 8f90bcdf10 Merge branch 'manage-active-job-delivery-date' of WrenchBoard/Users-Wrench into master 2023-06-27 10:52:36 +00:00
Ebube 4b897cb3a9 . 2023-06-27 10:06:51 +01:00
ameye 0977650bf4 Merge branch 'faq-display' of WrenchBoard/Users-Wrench into master 2023-06-26 18:07:41 +00:00
Ebube 1f76dd0db8 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into faq-display 2023-06-26 19:01:49 +01:00
Ebube f772cf0a68 . 2023-06-26 18:57:41 +01:00
CHIEFSOFT\ameye c4c5c7967e Resource Starter 2023-06-26 13:36:43 -04:00
Ebube 45ecec24ac Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into faq-display 2023-06-26 17:48:25 +01:00
Ebube 16fd35df83 . 2023-06-26 17:48:00 +01:00
CHIEFSOFT\ameye 3f6a391d30 witing Jobs 2023-06-26 09:23:28 -04:00
CHIEFSOFT\ameye 5eb64f49c0 text style 2023-06-26 07:50:49 -04:00
CHIEFSOFT\ameye 1761150bd3 My wait jobs 2023-06-26 07:44:03 -04:00
ameye a4b15dd06e Merge branch 'faq-display' of WrenchBoard/Users-Wrench into master 2023-06-25 21:38:00 +00:00
Ebube 1a15410e4c . 2023-06-25 20:07:35 +01:00
Ebube da1133ed43 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into faq-display 2023-06-25 20:00:49 +01:00
Ebube 23605bc358 . 2023-06-25 19:58:54 +01:00
ameye 2092682be6 Merge branch 'faq-display' of WrenchBoard/Users-Wrench into master 2023-06-25 11:19:58 +00:00
Ebube 0e270d8efa . 2023-06-25 07:09:17 +01:00
CHIEFSOFT\ameye 3bb4fe6a02 banner waiting 2023-06-25 00:01:44 -04:00
CHIEFSOFT\ameye fa728d3879 Waiting Jobs 2023-06-24 15:43:59 -04:00
ameye a9ce76123b Merge branch 'privacy-policy' of WrenchBoard/Users-Wrench into master 2023-06-24 11:17:42 +00:00
ameye 3ac1be9b89 Merge branch 'AddJob-Link-Fix' of WrenchBoard/Users-Wrench into master 2023-06-24 11:17:37 +00:00
ameye e4be117c90 Merge branch 'offer-interest-msg-list' of WrenchBoard/Users-Wrench into master 2023-06-24 11:17:11 +00:00
Ebube 58834cd7ca privacy policy 2023-06-24 08:52:33 +01:00
victorAnumudu 0feaf42f49 offer interest message list API added 2023-06-23 23:47:46 +01:00
134 changed files with 4331 additions and 1788 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_MINUTES=600000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
+1 -1
View File
@@ -17,7 +17,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_MINUTES=600000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
+1 -1
View File
@@ -17,7 +17,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_MINUTES=600000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
+4
View File
@@ -45,6 +45,8 @@ import BlogPage from "./views/BlogPage";
import MyReviewDueJobsPage from "./views/MyReviewDueJobsPage";
import OffersInterestPage from "./views/OffersInterestPage";
import ManageInterestOfferPage from './views/ManageInterestOfferPage'
import MyWaitingJobsPage from "./views/MyWaitingJobsPage";
import FamilyMarketPage from "./views/FamilyMarketPage";
export default function Routers() {
return (
@@ -86,6 +88,7 @@ export default function Routers() {
<Route exact path="/notification" element={<Notification />} />
<Route exact path="/market-place" element={<MarketPlacePage />} />
<Route exact path="/market" element={<MarketPlacePage />} />
<Route exact path="/familymarket" element={<FamilyMarketPage />} />
<Route exact path="/notification" element={<Notification />} />
<Route exact path="/mytask" element={<MyTaskPage />} />
<Route exact path="/myjobs" element={<MyJobsPage />} />
@@ -93,6 +96,7 @@ export default function Routers() {
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
<Route exact path="/my-pastdue-jobs" element={<MyPastDueJobsPage />} />
<Route exact path="/my-pending-jobs" element={<MyPendingJobsPage />} />
<Route exact path="/pend-interest" element={<MyWaitingJobsPage />} />
<Route exact path="/my-review-jobs" element={<MyReviewDueJobsPage />} />
<Route exact path="/acc-family" element={<FamilyAccPage />} />
<Route exact path="/manage-family" element={<FamilyManagePage />} />
Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" id="delete"><g color="#000"><path fill="#ee4c45" style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;block-progression:tb;white-space:normal;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" d="M12 1028.362c-6.626 0-12 5.374-12 12s5.374 12 12 12 12-5.374 12-12-5.374-12-12-12z" font-family="sans-serif" font-weight="400" overflow="visible" transform="translate(0 -1028.362)"></path><path fill="#fff" style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" d="M10.5 1034.362v1h-3v1h9v-1h-3v-1h-3zm-2 3v9h7v-9h-7zm1 1h1v7h-1v-7zm2 0h1v7h-1v-7zm2 0h1v7h-1v-7z" overflow="visible" transform="translate(0 -1028.362)"></path></g></svg>

After

Width:  |  Height:  |  Size: 841 B

+19
View File
@@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 60 60" viewBox="0 0 60 60" id="edit"><path fill="#3B4652" d="M52.9687347,19.3099976l-2.7999878-2.7999878c-0.9099731-0.9100342-2.3899536-0.9100342-3.2999878,0
l-1.4129639,1.4129639c0.0185547,0.017395,0.0423584,0.0234985,0.0601196,0.0422974l5.7765503,6.1199341
c0.0361328,0.038269,0.0506592,0.0881348,0.0813599,0.1296997l1.5949097-1.5949097
C53.8787689,21.7099609,53.8787689,20.2199707,52.9687347,19.3099976z"></path><path fill="#2B79C2" d="M10.8887787,25.5499878H34.998764l7.5900269-7.5900269l1.7599487-1.75V9c0-1.6500244-1.3499756-3-3-3h-32
c-1.6599731,0-3,1.3499756-3,3v42c0,1.6499634,1.3400269,3,3,3h32c1.6500244,0,3-1.3500366,3-3V34.0700073l-5.8899536,5.8800049
c-0.3099976,0.3199463-0.7000122,0.5599976-1.1199951,0.7099609l-7.2200317,2.5200195
c-0.3099976,0.1099854-0.6500244,0.1699829-0.9899902,0.1699829c-0.7800293,0-1.5200195-0.2999878-2.0900269-0.8399658
c-0.3399658-0.3400269-0.5799561-0.7400513-0.7299805-1.1600342H10.8887787c-0.5599976,0-1-0.4500122-1-1s0.4400024-1,1-1
h15.4199829v-0.0100098l1.7000122-4.8899536H10.8887787c-0.5599976,0-1-0.4500122-1-1c0-0.5500488,0.4400024-1,1-1H28.708786
l0.0999756-0.3000488c0.1699829-0.4699707,0.4400024-0.8800049,0.789978-1.1900024l3.4000244-3.4099731H10.8887787
c-0.5599976,0-1-0.4500122-1-1S10.3287811,25.5499878,10.8887787,25.5499878z M10.8887787,46.25h24.9099731
c0.5599976,0,1,0.4500122,1,1s-0.4400024,1-1,1H10.8887787c-0.5599976,0-1-0.4500122-1-1S10.3287811,46.25,10.8887787,46.25z
M10.8887787,11.75h24.9099731c0.5599976,0,1,0.4500122,1,1s-0.4400024,1-1,1H10.8887787c-0.5599976,0-1-0.4500122-1-1
S10.3287811,11.75,10.8887787,11.75z M10.8887787,18.6499634h24.9099731c0.5599976,0,1,0.4500122,1,1c0,0.5500488-0.4400024,1-1,1
H10.8887787c-0.5599976,0-1-0.4499512-1-1C9.8887787,19.0999756,10.3287811,18.6499634,10.8887787,18.6499634z"></path><path fill="#3B4652" d="M30.9387665,32.4400024c-0.1099854,0.0999756-0.1900024,0.2299805-0.2399902,0.3699951
l-2.5100098,7.2099609c-0.1300049,0.3600464-0.039978,0.7700195,0.2299805,1.0400391
c0.2000122,0.1900024,0.4500122,0.289978,0.710022,0.289978c0.1099854,0,0.2199707-0.0200195,0.3300171-0.0599976
l7.2099609-2.5100098c0.1400146-0.0499878,0.2700195-0.1300049,0.3800049-0.2399902l12.5599976-12.5599976l-5.9299927-6.2799683
L30.9387665,32.4400024z"></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+91 -70
View File
@@ -1,33 +1,38 @@
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { Field, Form, Formik } from "formik";
import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import * as Yup from "yup";
import usersService from "../../services/UsersService";
import { tableReload } from "../../store/TableReloads";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import usersService from "../../services/UsersService";
import { useSelector, useDispatch } from "react-redux";
import { tableReload } from "../../store/TableReloads";
import { Field, Form, Formik } from "formik";
import * as Yup from "yup";
const validationSchema = Yup.object().shape({
country: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Country is required"),
price: Yup.number()
.typeError("you must specify a number")
price: Yup.string()
.typeError("Invalid number")
.min(1, "Price must be greater than 0")
.test("no-e", "Invalid number", (value) => {
if (value && /\d+e/.test(value)) {
return false;
}
return true;
})
.required("Price is required"),
title: Yup.string()
.min(3, "Minimum 3 characters")
.max(100, "Maximum 25 characters")
.min(5, "Minimum 5 characters")
.max(149, "Maximum 149 characters")
.required("Title is required"),
description: Yup.string()
.min(3, "Minimum 3 characters")
.max(250, "Maximum 250 characters")
.min(5, "Minimum 5 characters")
.max(299, "Maximum 299 characters")
.required("Description is required"),
job_detail: Yup.string()
.min(3, "Minimum 3 characters")
.max(250, "Maximum 250 characters")
.max(1440, "Maximum 1440 characters")
.required("Details is required"),
timeline_days: Yup.number()
.typeError("you must specify a number")
@@ -38,19 +43,18 @@ const validationSchema = Yup.object().shape({
function AddJob({ popUpHandler, categories }) {
const ApiCall = new usersService();
let dispatch = useDispatch();
let { userDetails } = useSelector((state) => state.userDetails);
let [country, setCountry] = useState({
let [currency, setCurrency] = useState({
loading: true,
status: false,
data: [],
}); // To Hold the array of country getUserCountry returns
data: null,
}); // To Hold the array of currency getUserCurrency returns
let initialValues = {
// initial values for formik
country: userDetails.country,
country: "",
price: "",
title: "",
description: "",
@@ -65,31 +69,42 @@ function AddJob({ popUpHandler, categories }) {
message: "",
}); // Holds state when submit button is pressed
// FUNCTION TO GET COUNTRY
const getUserCountry = () => {
setCountry((prev) => ({ ...prev, loading: true }));
ApiCall.getSignupCountryData()
// FUNCTION TO GET Currency
const getUserCurrency = () => {
setCurrency((prev) => ({ ...prev, loading: true }));
ApiCall.getUserWallets()
.then((res) => {
if (res.data.internal_return < 1) {
setCountry({ loading: false, status: true, data: [] });
if (res.data.internal_return < 0) {
setCurrency({ loading: false, status: true, data: [] });
return;
}
setCountry({
console.log("Res for currency >> ", res);
setCurrency({
loading: false,
status: true,
data: res.data.signup_country,
data: res.data.result_list,
});
})
.catch((err) => {
setCountry({ loading: false, status: false, data: [] });
setCurrency({ loading: false, status: false, data: [] });
});
};
// FUNCTION TO HANDLE ADD JOB FORM
const handleAddJob = (values, helpers) => {
values.category = values.category?.join("@");
let reqData = {
country: values?.country,
price: Number(values.price) * 100,
title: values?.title,
description: values?.description,
job_detail: values?.job_detail,
timeline_days: values?.timeline_days,
category: values.category?.join("@"),
};
setRequestStatus({ loading: true, status: false, message: "" });
ApiCall.jobManagerCreateJob(values)
ApiCall.jobManagerCreateJob(reqData)
.then((res) => {
if (res.data.internal_return < 1) {
setRequestStatus({
@@ -97,6 +112,9 @@ function AddJob({ popUpHandler, categories }) {
status: false,
message: "Could not complete your request at the moment",
});
setTimeout(() => {
popUpHandler();
}, 1500);
return;
}
setRequestStatus({
@@ -113,7 +131,7 @@ function AddJob({ popUpHandler, categories }) {
setRequestStatus({
loading: false,
status: false,
message: "Opps! soemthing went wrong. Try Again",
message: "Opps! something went wrong. Try Again",
});
})
.finally(() => {
@@ -124,7 +142,7 @@ function AddJob({ popUpHandler, categories }) {
};
useEffect(() => {
getUserCountry();
getUserCurrency();
}, []);
return (
@@ -140,46 +158,41 @@ function AddJob({ popUpHandler, categories }) {
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
{/* inputs starts here */}
{/* country */}
<div className="xl:flex xl:space-x-7 mb-[5px]">
<div className="field w-full mb-6 xl:mb-0">
<label
htmlFor="country"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
>
Country
Currency
{props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>}
</label>
<select
id="country"
name="country"
disabled
value={props.values.country}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{country.loading ? (
{currency.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : country.data.length ? (
) : currency.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select...
Select a currency
</option>
{country.data.map((item, index) => {
if (item[0] == userDetails.country) {
return (
<option
key={index}
className="text-slate-500 text-lg"
value={item[0]}
>
{item[1]}
</option>
);
}
})}
{currency.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.description}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
@@ -202,7 +215,7 @@ function AddJob({ popUpHandler, categories }) {
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
errorBorder={props.errors.price && props.touched.price}
error={props.errors.price && props.touched.price && props.errors.price}
/>
</div>
</div>
@@ -220,7 +233,7 @@ function AddJob({ popUpHandler, categories }) {
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
errorBorder={props.errors.title && props.touched.title}
error={props.errors.title && props.touched.title && props.errors.title}
/>
</div>
@@ -236,9 +249,7 @@ function AddJob({ popUpHandler, categories }) {
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
errorBorder={
props.errors.description && props.touched.description
}
error={props.errors.description && props.touched.description && props.errors.description}
/>
</div>
@@ -247,14 +258,15 @@ function AddJob({ popUpHandler, categories }) {
<div className="sm:w-[60%] w-full">
<label
htmlFor="Job Delivery Details"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1'
>
Job Delivery Details
{props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>}
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-6 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] border border-[#dce4e9] rounded-[10px]`}
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`}
style={{ resize: "none" }}
name="job_detail"
value={props.values.job_detail}
@@ -276,7 +288,7 @@ function AddJob({ popUpHandler, categories }) {
role="group"
aria-labelledby="checked-group"
>
{Object.entries(categories).map(([key, value]) => (
{Object?.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
@@ -289,16 +301,13 @@ function AddJob({ popUpHandler, categories }) {
<span className="text-[13.975px]">{value}</span>
</label>
))}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
</div>
</div>
{/* <div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.job_detail && props.touched.job_detail && (
<p className="text-sm text-red-500">
{props.errors.job_detail}
</p>
)}
</div> */}
</div>
<div className="field w-full mb-[5px]">
@@ -317,7 +326,12 @@ function AddJob({ popUpHandler, categories }) {
<Field
component="select"
name="timeline_days"
className="input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none"
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
@@ -407,3 +421,10 @@ const publicArray = [
{ duration: 21, name: "3 weeks" },
{ duration: 28, name: "4 weeks" },
];
// .test("no-e", "Invalid number", (value) => {
// if (value && /\d+e/.test(value)) {
// return false;
// }
// return true;
// })
+3 -3
View File
@@ -4,12 +4,12 @@ import { Link } from "react-router-dom";
export default function LoginLayout({ slogan, children }) {
return (
<div className={`layout-wrapper login`}>
<div className={`main-wrapper login-wrapper w-full h-screen overflow-y-auto p-2 sm:p-20`}>
<div className={`main-wrapper login-wrapper w-full h-screen overflow-y-auto p-2 sm:px-20 sm:py-5`}>
<div className="w-full h-full">
<div className="flex-1 flex justify-center items-center">
{children && children}
</div>
<div className="flex-1 flex justify-center items-center p-10">
<div className="flex-1 flex justify-center items-center px-10 pt-10">
<div className="flex items-center">
<a
href="https://www.wrenchboard.com/about-us"
@@ -37,7 +37,7 @@ export default function LoginLayout({ slogan, children }) {
</a>
</div>
</div>
<div className="flex-1 flex justify-center items-center p-10">
<div className="flex-1 flex justify-center items-center px-10 py-1">
<p className="text-black text-[15px] px-2 font-medium flex items-center">
<span className="text-3xl mt-2 mr-1">©</span> 2023 - {" "}
<Link to="/" className="text-[#009ef7] ml-1">
@@ -43,7 +43,7 @@ export default function CollectionTab({ className, products }) {
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
endLength={products?.length}
>
{({ datas }) => (
<CollectionCard key={datas.uniqKey} collectionData={datas} />
@@ -42,7 +42,9 @@ export default function CreateSaleSlider({
{/* heading */}
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Sell</h1>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Create for Sell
</h1>
</div>
<div className="slider-btns flex space-x-4">
<button onClick={nextHandler} type="button">
@@ -89,7 +91,7 @@ export default function CreateSaleSlider({
<div className="trending-products relative w-full">
<SliderCom selector={trendingSlider} settings={settings}>
{products &&
products.length > 0 &&
products?.length > 0 &&
products.map((item) => (
<ProductCardStyleTwo
key={item.id}
@@ -49,7 +49,9 @@ export default function CreatedBidsSlider({
{/* heading */}
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Bits</h1>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Create for Bits
</h1>
</div>
<div className="slider-btns flex space-x-4">
<button onClick={nextHandler} type="button">
@@ -96,7 +98,7 @@ export default function CreatedBidsSlider({
<div className="trending-products relative w-full">
<SliderCom selector={trendingSlider} settings={settings}>
{products &&
products.length > 0 &&
products?.length > 0 &&
products.map((item) => (
<ProductCardStyleOne
key={item.id}
@@ -43,7 +43,7 @@ export default function OnSaleTab({ className, products }) {
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
endLength={products?.length}
>
{({ datas }) => (
<ProductCardStyleTwo key={datas.id} datas={datas} />
@@ -43,7 +43,7 @@ export default function OwnTab({ className, products }) {
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
endLength={products?.length}
>
{({ datas }) => (
<ProductCardStyleOne key={datas.id} datas={datas} />
+50 -33
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useLayoutEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import linkedInLogo from "../../../assets/images/Linkedin.png";
import appleLogo from "../../../assets/images/apple-black.svg";
@@ -17,10 +17,7 @@ import { updateUserDetails } from "../../../store/UserDetails";
export default function Login() {
const dispatch = useDispatch();
let [loginType, setLoginType] = useState({ full: true, family: false });
const [selectedLoginType, setSelectedLoginType] = useState(
document.cookie.includes("loginType=family") ? "loginfamily" : "loginfull"
);
let [loginType, setLoginType] = useState('');
const [checked, setValue] = useState(false);
const [loginLoading, setLoginLoading] = useState(false);
@@ -36,11 +33,12 @@ export default function Login() {
//FUNCTION TO DETERMINE/CHANGE LOGIN COMPONENT
const handleLoginType = ({ target: { name } }) => {
if (name == "full") {
setLoginType({ [name]: true, family: false });
} else if ((name = "family")) {
setLoginType({ [name]: false, family: true });
}
setLoginType(name);
let currentDate = new Date();
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=/;`;
};
// email
@@ -71,7 +69,7 @@ export default function Login() {
return;
}
if (name == "loginfull") {
if (name == "full") {
// Post Data Info for normal Login
postData = {
username: email,
@@ -80,11 +78,7 @@ export default function Login() {
login_mode: 1100,
action: 11025,
};
// Clear the loginType cookie if the user switches to loginfull
document.cookie =
"loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
} else if (name == "loginfamily") {
} else if (name == "family") {
// Post Data Info for family Login
postData = {
username: email,
@@ -93,8 +87,6 @@ export default function Login() {
login_mode: 1105,
action: 11025,
};
// Set the loginType cookie to remember the user's selection
document.cookie = "loginType=family; expires=Session; path=/;";
} else {
setLoginLoading(false);
setMsgError("Invalid Login Type. Consider refreshing the page");
@@ -146,24 +138,49 @@ export default function Login() {
});
// In order to update the selected login type whenever the component renders
useEffect(() => {
setSelectedLoginType(
document.cookie.includes("loginType=family") ? "loginfamily" : "loginfull"
);
}, []);
// useEffect(() => {
// Clear the loginType cookie if the user switches to loginfull
// document.cookie ="loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// }, []);
console.log("Looking for the cookies >>", selectedLoginType)
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")){
// setLoginType('full')
// }else{
// setLoginType('full')
// }
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 c = carr[i];
while(c.charAt(0)==' '){
c=c.substring(1);
}
if(c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return 'full'
}
let loginValue = readCookie('loginType')
setLoginType(loginValue)
},[])
useEffect(() => {
setMail("");
setPassword("");
}, [loginType.full, loginType.family]);
}, [loginType]);
return (
<>
<AuthLayout slogan="Welcome to WrenchBoard">
<div className="w-full">
<div className="mb-12">
<div className="mb-5">
<Link to="#">
<img
src={WrenchBoard}
@@ -194,7 +211,7 @@ export default function Login() {
<button
name="full"
className={`px-2 py-1 w-[100px] text-left h-[40px] text-lg font-bold text-[#4687ba] hover:text-[#009ef7] tracking-wide transition outline-none border-2 border-b-0 border-r-0 border-[#4687ba] ${
loginType.full && "border-r-2 h-[45px]"
loginType=='full' && "border-r-2 h-[45px]"
}`}
onClick={handleLoginType}
>
@@ -203,7 +220,7 @@ export default function Login() {
<button
name="family"
className={`px-2 py-1 w-[100px] text-left h-[40px] text-lg font-bold text-[#4687ba] hover:text-[#009ef7] tracking-wide transition outline-none border-2 border-b-0 border-l-0 border-[#4687ba] ${
loginType.family && "border-l-2 h-[45px]"
loginType=='family' && "border-l-2 h-[45px]"
}`}
onClick={handleLoginType}
>
@@ -215,7 +232,7 @@ export default function Login() {
{/* for login component */}
{
loginType.full ? (
loginType == 'full' ? (
//user login component
<div className="p-2 input-area border-2 border-[#4687ba]">
<div className="input-item mb-5">
@@ -224,7 +241,7 @@ export default function Login() {
fieldClass="sm:px-6 px-2"
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
placeholder="Your Email"
label="Email"
name="email"
type="email"
@@ -266,7 +283,7 @@ export default function Login() {
<div className="signin-area mb-3.5">
<div className="flex justify-center">
<button
name="loginfull"
name="full"
onClick={doLogin}
type="button"
disabled={loginLoading}
@@ -312,7 +329,7 @@ export default function Login() {
fieldClass="px-6"
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
placeholder="Account ID"
label="Username"
name="email"
type="email"
@@ -354,7 +371,7 @@ export default function Login() {
<div className="signin-area mb-1.5">
<div className="flex justify-center">
<button
name="loginfamily"
name="family"
onClick={doLogin}
disabled={loginLoading}
type="button"
+3 -3
View File
@@ -80,7 +80,7 @@ export default function SignUp() {
if (res.status === 200) {
const { data } = res;
if (data.status === -1 && data.acc === "DULPICATE") {
if (data && data.acc === "DULPICATE") {
setMsgError("This account has been already created");
setSignUpLoading(false);
}
@@ -108,12 +108,12 @@ export default function SignUp() {
useEffect(() => {
getCountryList();
});
}, []);
return (
<>
<div className="layout-wrapper login">
<div className="main-wrapper w-full xl:h-screen h-full xl:py-10 py-12 overflow-y-auto">
<div className="main-wrapper login-wrapper w-full xl:h-screen h-full xl:py-10 py-12 overflow-y-auto">
<div className=" h-full">
<div className="flex-1 flex justify-center items-center">
<div className="w-full">
@@ -43,7 +43,7 @@ export default function CollectionTab({ className, products }) {
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
endLength={products?.length}
>
{({ datas }) => (
<CollectionCard key={datas.uniqKey} collectionData={datas} />
@@ -42,7 +42,9 @@ export default function CreateSaleSlider({
{/* heading */}
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Sell</h1>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Create for Sell
</h1>
</div>
<div className="slider-btns flex space-x-4">
<button onClick={nextHandler} type="button">
@@ -89,7 +91,7 @@ export default function CreateSaleSlider({
<div className="trending-products relative w-full">
<SliderCom selector={trendingSlider} settings={settings}>
{products &&
products.length > 0 &&
products?.length > 0 &&
products.map((item) => (
<ProductCardStyleTwo
key={item.id}
@@ -49,7 +49,9 @@ export default function CreatedBidsSlider({
{/* heading */}
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Bits</h1>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Create for Bits
</h1>
</div>
<div className="slider-btns flex space-x-4">
<button onClick={nextHandler} type="button">
@@ -96,7 +98,7 @@ export default function CreatedBidsSlider({
<div className="trending-products relative w-full">
<SliderCom selector={trendingSlider} settings={settings}>
{products &&
products.length > 0 &&
products?.length > 0 &&
products.map((item) => (
<ProductCardStyleOne
key={item.id}
@@ -43,7 +43,7 @@ export default function OnSaleTab({ className, products }) {
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
endLength={products?.length}
>
{({ datas }) => (
<ProductCardStyleTwo key={datas.id} datas={datas} />
@@ -43,7 +43,7 @@ export default function OwnTab({ className, products }) {
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products.length}
endLength={products?.length}
>
{({ datas }) => (
<ProductCardStyleOne key={datas.id} datas={datas} />
+143 -156
View File
@@ -9,163 +9,154 @@ export default function AvailableJobsCard({
className,
datas,
hidden = false,
contentDisplay
contentDisplay,
}) {
//debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
const [manageInt, setManageInt] = useState(null);
const [imageUrl, setImageUrl] = useState("");
const navigate = useNavigate();
const apiCall = useMemo(() => new usersService(), []);
const marketInterestData = useCallback(async () => {
let { offer_code } = datas;
let reqData = { offer_code };
try {
const manageInt = await apiCall.MarketInterest(reqData);
const manageIntRes = await manageInt?.data;
setManageInt(manageIntRes);
} catch (error) {
throw new Error(error);
}
}, [apiCall, datas]);
let thePrice = PriceFormatter(
let thePrice = PriceFormatter(
datas?.price * 0.01,
datas?.currency_code,
datas?.currency
);
useEffect(() => {
if (!datas) {
navigate("/market", { replace: true });
}
marketInterestData();
}, []);
useEffect(() => {
const imagePath = require(`../../assets/images/${datas.thumbnil}`); // Replace with your directory path for local images
setImageUrl(imagePath);
}, []);
return (
<>
{contentDisplay == 'grid' ?
<div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="flex flex-col justify-between w-full h-full">
<Link to="/shop-details" className="mb-2.5">
{contentDisplay == "grid" ? (
<div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
className="flex flex-col justify-between w-full h-full"
>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.title}
</h1>
</Link>
<div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden bg-center bg-cover bg-no-repeat"
style={{
backgroundImage: `url('${imageUrl}')`,
}}
>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{/* {thePrice} | {datas.timeline_days} day(s) */}
{thePrice}
<p className="text-thin-light-gray text-sm leading-3">
Added
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code}) |
<span className="italic ml-1">
{datas.timeline_days} day(s)
</span>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden bg-center bg-cover bg-no-repeat"
style={{
backgroundImage: `url('${imageUrl}')`,
}}
>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{/* {thePrice} | {datas.timeline_days} day(s) */}
{thePrice}
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code}) |
<span className="italic ml-1">
{datas.timeline_days} day(s)
</span>
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
</div>
</div>
</div>
</div>
</div>
</div>
:
<div className="card-style-two w-full p-8 my-2 flex items-center gap-4 bg-white dark:bg-dark-white rounded-2xl section-shadow">
<div className="flex gap-5 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] max-w-[60px]">
<img src={dataImage2} alt="data" className="w-full h-full" />
</div>
<div className="flex flex-col flex-[0.9]">
<Link to="/shop-details" className="">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
) : (
<div className="card-style-two w-full p-8 my-2 flex items-center gap-4 bg-white dark:bg-dark-white rounded-2xl section-shadow">
<div className="flex gap-5 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] max-w-[60px]">
<img src={dataImage2} alt="data" className="w-full h-full" />
</div>
<div className="flex flex-col flex-[0.9]">
<h1
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize"
>
{datas?.title}
</h1>
</Link>
<div className="my-2">
<p className="text-dark-gray dark:text-white">{datas?.description}</p>
</div>
<div
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
className="my-2"
>
<p className="text-dark-gray dark:text-white">
{datas?.description}
</p>
</div>
{/* <div className="card-two-info flex gap-2 items-center">
{/* <div className="card-two-info flex gap-2 items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
@@ -186,40 +177,37 @@ export default function AvailableJobsCard({
</div>
</div>
</div> */}
<div className="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1">
Price: <span className="text-purple">{thePrice}</span>
</p>
<p className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple italic">
{" "}
{datas?.timeline_days} day(s)
</span>
</p>
<p className="text-sm text-thin-light-gray">
Code:{" "}
<span className="text-purple">
{" "}
{datas?.offer_code}
</span>
</p>
<div className="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1">
Price: <span className="text-purple">{thePrice}</span>
</p>
<p className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple italic">
{" "}
{datas?.timeline_days} day(s)
</span>
</p>
<p className="text-sm text-thin-light-gray">
Code:{" "}
<span className="text-purple"> {datas?.offer_code}</span>
</p>
</div>
</div>
</div>
<div className="">
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
</div>
</div>
<div className="">
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
</div>
</div>
}
)}
{marketPopUp.show && (
<MarketPopUp
details={datas}
@@ -227,7 +215,6 @@ export default function AvailableJobsCard({
setMarketPopUp({ show: false, data: {} });
}}
situation={marketPopUp.show}
marketInt={manageInt}
/>
)}
</>
@@ -0,0 +1,120 @@
import { useState } from "react";
import { Link, useLocation } from "react-router-dom";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import Icons from "../Helpers/Icons";
export default function FamilyActiveJobsCard({ datas, hidden = false }) {
let { pathname } = useLocation();
console.log('TESTING11111',datas)
const [imageUrl, setImageUrl] = useState("");
const [addFavorite, setValue] = useState(false);
const [options, setOption] = useState(false);
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
toast.success("Added to Favorite List");
} else {
setValue(false);
toast.warn("Remove to Favorite List");
}
};
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
{/* thumbnail */}
<div className="w-full h-40">
{/* thumbnail image */}
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${localImgLoad(
`images/taskbanners/${datas.banner}`
)}) center / contain no-repeat`,
}}
>
{/* <div className="product-options flex justify-between relative">*/}
{/*<span*/}
{/* onClick={favoriteHandler}*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center cursor-pointer ${*/}
{/* addFavorite ? "text-pink" : " text-dark-gray"*/}
{/* }`}*/}
{/*>*/}
{/* <Icons name="love" />*/}
{/*</span>*/}
{/* <span*/}
{/* onClick={() => setOption(!options)}*/}
{/* className="w-7 h-7 flex justify-center items-center bg-white rounded-full cursor-pointer"*/}
{/* >*/}
{/* <Icons name="dots" />*/}
{/*</span>*/}
{/* {options && (*/}
{/* <div*/}
{/* onClick={() => setOption(!options)}*/}
{/* className="w-full h-screen fixed top-0 left-0 z-10"*/}
{/* ></div>*/}
{/* )}*/}
{/* <div*/}
{/* style={{ boxShadow: "0px 4px 87px 0px #0000002B" }}*/}
{/* className={`drop-down-content w-[80px] bg-white dark:bg-dark-white rounded-[4px] p-2.5 absolute right-0 top-[100%] z-20 ${*/}
{/* options ? "active" : ""*/}
{/* }`}*/}
{/* >*/}
{/* </div>*/}
{/* </div>*/}
{hidden && (
<div className="flex justify-center">
</div>
)}
</div>
</div>
{/* details */}
<div className="details">
{/* product title */}
<Link
to="/manage-active-job"
state={{ ...datas, pathname }}
className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1"
>
{datas.title}
</Link>
{/* countdown */}
<div className="w-full h-[54px] flex justify-evenly items-center p-2 rounded-lg border border-[#E3E4FE] dark:border-[#a7a9b533] ">
<div className="flex flex-col justify-between">
<p className="text-sm text-thin-light-gray dark:text-white tracking-wide">
Task Code
</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
{datas.contract}
</p>
</div>
<div className="w-[1px] h-full bg-[#E3E4FE] dark:bg-[#a7a9b533] "></div>
<div className="flex flex-col justify-between">
<p className="text-sm text-thin-light-gray dark:text-white tracking-wide">
Remaining Time
</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
<CountDown lastDate={datas.delivery_date} />
</p>
</div>
</div>
</div>
</div>
<div className="card-buttons flex justify-end items-center space-x-2">
<Link
to="/manage-active-job"
state={{ ...datas, pathname }}
className="btn-shine w-[98px] h-[33px] text-white rounded-full text-sm bg-pink flex justify-center items-center"
>
View
</Link>
</div>
</div>
);
}
+78
View File
@@ -0,0 +1,78 @@
import { useState } from "react";
import SuggestTask from "../FamilyPopup/SuggestTask";
export default function FamilyMarketCard({ className, datas, hidden = false }) {
// debugger;
const [popUp, setPopUp] = useState(false);
const popUpHandler = () => {
setPopUp((prev) => !prev);
};
// Image
let selectedImage = require(`../../assets/images/family/${
datas.banner || "default.jpg"
}`);
return (
<>
<div
className={`card-style-two w-full h-[336px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
key={datas?.uid}
>
<div className="flex flex-col justify-between w-full h-full">
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
onClick={popUpHandler}
style={{
// background: `url(${selectedImage}) 0% 0% / cover no-repeat`,
background: `url(${selectedImage}) center / contain no-repeat`,
}}
>
<div className="product-two-options flex justify-between mb-5 relative">
<div className="status">
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">
Active
</span> */}
</div>
</div>
{hidden && <div className="flex justify-center"></div>}
</div>
</div>
<div className="details-area mt-12 flex justify-between items-center gap-2">
{/* title */}
<button onClick={popUpHandler}>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas?.title}
</h1>
</button>
<div className="flex justify-between">
{/* <div className="flex items-center space-x-2">
<p className="italic text-gray-400">
{getTimeAgo(datas?.added)}
</p>
</div> */}
<div>
<button
type="button"
onClick={popUpHandler}
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
>
View
</button>
</div>
</div>
</div>
</div>
</div>
{popUp && (
<SuggestTask
onClose={popUpHandler}
situation={popUp}
details={{ ...datas, selectedImage }}
/>
)}
</>
);
}
+71
View File
@@ -0,0 +1,71 @@
import { useState } from "react";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import Icons from "../Helpers/Icons";
import {PriceFormatter} from '../Helpers/PriceFormatter'
export default function FamilyOfferCard({ datas, hidden = false, setOfferPopout }) {
let thePrice = PriceFormatter(datas?.price * 0.01,datas?.currency_code,datas?.currency);
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
{/* thumbnail */}
<div className="w-full h-40">
{/* thumbnail image */}
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${localImgLoad(
`images/taskbanners/${datas.banner}`
)}) center / contain no-repeat`,
}}
>
{hidden && (
<div className="flex justify-center">
</div>
)}
</div>
</div>
{/* details */}
<div className="details">
<h1 className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{datas.title}
</h1>
{/* countdown */}
<div className="w-full h-[54px] flex justify-evenly items-center p-2 rounded-lg border border-[#E3E4FE] dark:border-[#a7a9b533] ">
<div className="flex flex-col justify-between">
<p className="text-sm text-thin-light-gray dark:text-white tracking-wide">
Task Code
</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
{datas.contract}
</p>
</div>
<div className="w-[1px] h-full bg-[#E3E4FE] dark:bg-[#a7a9b533] "></div>
<div className="flex flex-col justify-between">
<p className="text-sm text-thin-light-gray dark:text-white tracking-wide">
Remaining Time
</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
<CountDown lastDate={datas.expire} />
</p>
</div>
</div>
</div>
</div>
<div className="card-buttons flex justify-end items-center space-x-2">
<button
type='button'
onClick={()=>setOfferPopout({show: true, data: {...datas, thePrice}})}
className="btn-shine w-[98px] h-[33px] text-white rounded-full text-sm bg-pink flex justify-center items-center"
>
Start Task
</button>
</div>
</div>
);
}
@@ -23,20 +23,20 @@ export default function HomeBannerOffersCard(props) {
}}
>
<div className="flex flex-col justify-between h-full">
<div className="content flex justify-between items-center mb-5">
<div className="content flex justify-between items-center">
<div className="siderCardHeader">
<h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
<span className="heroSilderTitle">{props.itemData.title}</span>
</h1>
</div>
</div>
<div className="h-[233px]">
<div className="flex flex-col justify-around items-center flex-1">
<div className="siderCardDescription">
{props.itemData.description}
</div>
<div className="siderCardButton">
[ {props.itemData.button_text} ]
</div>
<button className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
{props.itemData.button_text}
</button>
</div>
</div>
</Link>
+4 -1
View File
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
@@ -6,6 +6,7 @@ import CountDown from "../Helpers/CountDown";
import Icons from "../Helpers/Icons";
export default function ProductCardStyleOne({ datas, hidden = false }) {
const [imageUrl, setImageUrl] = useState("");
const [addFavorite, setValue] = useState(false);
const [options, setOption] = useState(false);
const favoriteHandler = () => {
@@ -17,6 +18,8 @@ export default function ProductCardStyleOne({ datas, hidden = false }) {
toast.warn("Remove to Favorite List");
}
};
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
+75
View File
@@ -0,0 +1,75 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
export default function ProductCardStyleTwo({
className,
datas,
hidden = false,
bg
}) {
// debugger;
const [addFavorite, setValue] = useState(datas.whishlisted);
const [options, setOption] = useState(false);
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
toast.success("Added to Favorite List");
} else {
setValue(false);
toast.warn("Remove to Favorite List");
}
};
return (
<div
className={`card-style-two w-full h-[336px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="flex flex-col justify-between w-full h-full">
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
style={{
// background: `url(${`https://blog.wrenchboard.com/wp-content/uploads/${datas.meta_value}`}) 0% 0% / cover no-repeat`,
background: `url(${`${bg}${datas.meta_value}`}) 0% 0% / cover no-repeat`,
}}
>
<div className="product-two-options flex justify-between mb-5 relative">
<div className="status">
{datas?.isActive && (
<span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">
Active
</span>
)}
</div>
</div>
{hidden && <div className="flex justify-center"></div>}
</div>
</div>
<div className="details-area">
{/* title */}
<a href={datas.guid} target="_blank" 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>
<div className="flex justify-between">
<div className="flex items-center space-x-2"></div>
<div className="my-1">
<a
href={datas.guid}
target="_blank"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
rel="noreferrer"
>
View
</a>
</div>
</div>
</div>
</div>
</div>
);
}
+4 -3
View File
@@ -1,8 +1,8 @@
import React, { useState, useEffect } from "react";
import Layout from "../Partials/Layout";
import FamilyManageTabs from "./Tabs/FamilyManageTabs";
import React, { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import FamilyManageTabs from "./FamilyManageTabs";
export default function FamilyManage() {
const [selectTab, setValue] = useState("today");
@@ -11,6 +11,7 @@ export default function FamilyManage() {
let location = useLocation();
let navigate = useNavigate();
let accountDetails = location?.state;
// tab handler
const filterHandler = (value) => {
setValue(value);
@@ -0,0 +1,251 @@
import React, {
Suspense,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { useReactToPrint } from "react-to-print";
import profile from "../../assets/images/profile-info-profile.png";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import {
FamilyWaitlist,
FamilyAccount,
FamilyProfile,
FamilyTasks,
ProfileInfo,
FamilyPending,
} from "./Tabs";
export default function FamilyManageTabs({
className,
accountDetails,
listReload,
loader,
}) {
const [details, setDetails] = useState({
familyDetails: { loading: false, data: null },
familyTasks: { loading: false, data: null },
familyWaitList: { loading: false, data: null },
familyPending: { loading: false, data: null },
});
const [errMsg, setErrMsg] = useState("");
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
const familyPopUpHandler = () => {
setFamilyTaskPopout((prev) => !prev);
};
const [profileImg, setProfileImg] = useState(profile);
const profileImgInput = useRef(null);
const browseProfileImg = () => {
profileImgInput.current.click();
};
const profileImgChangeHandler = (e) => {
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
setProfileImg(event.target.result);
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
const apiCall = useMemo(() => new usersService(), []);
const manageFamily = useCallback(async () => {
try {
setDetails({
familyDetails: { loading: true },
familyTasks: { loading: true },
familyWaitList: { loading: true },
familyPending: { loading: true },
});
const { family_uid } = accountDetails;
const reqData = { family_uid };
const [familyRes, tasksRes, familyWaitRes, familyPending] =
await Promise.all([
apiCall.ManageFamily(reqData),
apiCall.ManageTasks(reqData),
apiCall.ManageFamilyWaitlist(),
apiCall.ManageFamilyPending(),
]);
const familyData = familyRes.data;
const tasksData = tasksRes.data;
const familyWaitData = familyWaitRes.data;
const familyPendingData = familyPending.data;
if (
familyData?.internal_return < 0 ||
tasksData?.internal_return < 0 ||
familyWaitData?.internal_return < 0 ||
familyPendingData?.internal_return < 0
)
return;
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
familyPending: { loading: false, data: familyPendingData },
});
} catch (error) {
setDetails({
familyDetails: { loading: false },
familyTasks: { loading: false },
familyWaitList: { loading: false },
familyPending: { loading: false },
});
setErrMsg("An error occurred");
throw new Error(error);
}
}, [apiCall, accountDetails]);
const accountRef = useRef();
const useHandlePrint = useReactToPrint({
content: () => accountRef.current,
});
const tabs = [
{ id: 1, name: "Tasks" },
{ id: 2, name: "Waiting" },
{ id: 3, name: "Pending" },
{ id: 4, name: "Account" },
{ id: 5, name: "Profile" },
];
const [tab, setTab] = useState(tabs[0].name);
const tabHandler = (value) => {
setTab(value);
};
const tabComponents = {
Tasks: (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
accountDetails={accountDetails}
/>
),
Waiting: (
<FamilyWaitlist
familyData={details.familyWaitList.data}
accountDetails={accountDetails}
loader={details.familyWaitList.loading}
/>
),
Pending: (
<FamilyPending
familyData={details.familyPending.data}
accountDetails={accountDetails}
loader={details.familyWaitList.loading}
/>
),
Account: (
<FamilyAccount
familyData={details.familyDetails.data}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
),
Profile: <FamilyProfile />,
};
const defaultTabComponent = (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
accountDetails={accountDetails}
/>
);
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
useEffect(() => {
manageFamily();
}, [tab, manageFamily]);
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 || ""
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<Suspense
fallback={
<div className="h-full min-h-[500px] 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="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full">
<ProfileInfo
profileImg={profileImg}
profileImgInput={profileImgInput}
profileImgChangeHandler={profileImgChangeHandler}
browseProfileImg={browseProfileImg}
accountDetails={accountDetails}
/>
</div>
<div className="col-span-3 justify-self-end 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">
{tabs.map(({ name, id }) => (
<li
onClick={() => tabHandler(name)}
className={`p-4 flex hover:text-purple transition-all ease-in-out items-center cursor-pointer overflow-hidden text-xl relative top-1 ${
tab === name
? "text-purple border-r"
: "text-thin-light-gray"
}`}
key={id}
>
<h1>{name}</h1>
</li>
))}
</ul>
<button
type="button"
onClick={familyPopUpHandler}
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
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">
{selectedTabComponent}
</div>
</div>
</div>
</div>
</div>
</Suspense>
</div>
{familyTaskPopout && (
<AssignTaskPopout
action={familyPopUpHandler}
situation={familyTaskPopout}
familyDetails={details.familyDetails.data}
/>
)}
</div>
);
}
+95
View File
@@ -0,0 +1,95 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import Layout from "../Partials/Layout";
import SearchCom from "../Helpers/SearchCom";
import FamilyMarketCard from "../Cards/FamilyMarketCard";
import usersService from "../../services/UsersService";
import SuggestTask from "../FamilyPopup/SuggestTask";
export default function FamilyMarket() {
const [popUp, setPopUp] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [myFamilySampleTasks, setMyFamilySampleTasks] = useState({
loading: true,
status: false,
data: [],
});
const apiCall = useMemo(() => new usersService(), []);
const getMyFamilySampleTasks = useCallback(async () => {
try {
setMyFamilySampleTasks({ loading: true, status: false, data: [] });
const res = await apiCall.getFamilySampleTasks();
setMyFamilySampleTasks({
loading: false,
status: true,
data: res.data.result_list,
});
} catch (error) {
setMyFamilySampleTasks({ loading: false, status: false, data: [] });
console.log("Error getting tasks:", error);
}
}, [apiCall]);
useEffect(() => {
getMyFamilySampleTasks();
}, [getMyFamilySampleTasks]);
const handleSearch = (event) => {
setSearchQuery(event.target.value);
};
const filteredTasks =
myFamilySampleTasks.data?.filter((task) =>
task.title.toLowerCase().includes(searchQuery.toLowerCase())
) || [];
const popUpHandler = () => {
setPopUp((prev) => !prev);
};
return (
<Layout>
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span>Suggest Task to the Parents</span>
</h1>
</div>
</div>
{/* Body */}
<div className="filter-section w-full items-center sm:flex justify-between mb-6">
{/* filter-search */}
<div className="sm:w-1/2 w-full sm:pr-20 pr-0 mb-5 sm:mb-0">
<SearchCom
placeholder="Search for tasks..."
handleSearch={handleSearch}
value={searchQuery}
/>
</div>
{/* filer-dropdown */}
<div className="flex-1 flex sm:justify-end">
<button
onClick={popUpHandler}
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
>
Any Other Task
</button>
</div>
</div>
<div className="content-section w-full-width">
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
{filteredTasks.map((task) => (
<FamilyMarketCard key={task.id} datas={task} />
))}
</div>
</div>
</div>
</div>
{popUp && <SuggestTask onClose={popUpHandler} situation={popUp} />}
</Layout>
);
}
@@ -0,0 +1,263 @@
import React, {useState, useEffect} from 'react'
import ModalCom from '../../Helpers/ModalCom'
import Detail from '../../jobPopout/popoutcomponent/Detail'
import usersService from '../../../services/UsersService'
import LoadingSpinner from '../../Spinners/LoadingSpinner'
import { PriceFormatter } from '../../Helpers/PriceFormatter'
function AssignTaskPopout({action, situation, familyDetails}) {
const apiCall = new usersService()
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: ''}) // HOLDS RESPONSE FOR SENDING API REQUEST
let [familyTask, setFamilyTask] = useState({loading: true, data: []})
let [taskType, setTaskType] = useState('select') // SWITCHES BTW SELECT TASK AND NEW TASK
let [activeTask, setActiveTask] = useState({id: 0, data: {}}) // HOLDS SELECTED TASK
const switchTaskType = ({target:{value}}) => { // FUNCTION TO CHANGE SELECTED ACTIVE TASK
setTaskType(value)
}
const handleActiveTask = (id=0, data={}) => { // FUNCTION TO CHANGE SELECTED ACTIVE TASK
setActiveTask({id, data})
}
const assignFamilyTask = () => {
setRequestStatus({loading: true, status: false, message: ''})
let reqData = {}
if(taskType == 'select'){ // RUNS HERE IF TASK TYPE IS SELECT
if(!Object.keys(activeTask.data).length){
setRequestStatus({loading: false, status: false, message: 'No Task is seleted'})
return setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 3000)
}
reqData = { // API PAYLOADS
job_id: activeTask.data?.job_id,
job_uid: activeTask.data?.job_uid,
family_uid: familyDetails.uid,
job_description: activeTask.data?.description,
assign_mode: 110011,
}
apiCall.assignFamilyTask(reqData).then(res => {
if(res.status != 200 || res.data.internal_return < 0){
setRequestStatus({loading: false, status: false, message: 'failed to assign task'})
return setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
}
setRequestStatus({loading: false, status: true, message: 'action successful'})
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
action() // FUNCTION THAT CLOSES THE MODAL BOX
}, 5000)
}).catch(err => {
setRequestStatus({loading: false, status: false, message: 'An Error occured, try again'})
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
})
}
if(taskType == 'new'){ // RUNS HERE IF TASK TYPE IS NEW TASK
console.log('TESTING')
}
}
useEffect(()=>{
const reqData = {
limit: 30,
offset: 0,
job_type: 'FAMILY',
action: 13005
}
apiCall.getMyJobList(reqData).then(res => {
setFamilyTask({loading: false, data: res?.data?.result_list})
if(res?.data?.result_list?.length){
setActiveTask(prev => ({...prev, data:res?.data?.result_list[0]}))
}
}).catch(err => {
setFamilyTask({loading: false, data: []})
console.log('Error', err)
})
},[])
return (
<>
<ModalCom
action={action}
situation={situation}
>
<div className="w-full h-full lg:w-[700px] lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Assign task to {familyDetails?.firstname}
</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>
{familyTask.loading ?
<div className='h-[100px] w-full flex justify-center items-center'>
<LoadingSpinner color='sky-blue' size='16' />
</div>
:
<>
<div className="job-action-modal-body w-full md:grid md:grid-cols-2">
<div className="p-4">
<div className="mb-2 w-full flex items-center gap-4">
<div className="flex items-center gap-2 text-sky-blue text-base">
<input type="radio" name='task-type' value='select' className="w-[20px] h-[20px] cursor-pointer" checked={taskType=='select'} onChange={switchTaskType}/>
<span>Select Task</span>
</div>
<div className="flex items-center gap-2 text-sky-blue text-base">
<input type="radio" name='task-type' value='new' className="w-[20px] h-[20px] cursor-pointer" checked={taskType=='new'} onChange={switchTaskType}/>
<span>New Task</span>
</div>
</div>
<div className='p-4 w-full h-[400px] overflow-y-auto bg-slate-100'>
{
taskType == 'select' ?
familyTask?.data?.length ?
familyTask?.data?.map((item, index)=>(
<div key={item.job_uid} className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer" onClick={()=>handleActiveTask(item.job_uid, item)}>
<input
type="radio"
name='task-list'
checked={(activeTask.id == item.job_uid) || (activeTask.id==index)&& true}
onChange={()=>handleActiveTask(item.job_uid, item)}
className="w-[15px] h-[15px] cursor-pointer"
/>
<p className="w-full text-dark-gray tracking-wide">{item?.title}</p>
</div>
))
:
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center">No Task found!</p>
:
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center">SPACE FOR NEW TASK</p>
}
</div>
</div>
{familyTask?.data?.length > 0 ?
<div className="p-4">
<div className="w-full">
<p className="text-lg font-bold text-dark-gray dark:text-white tracking-wide border-b-2">{activeTask?.data?.title}</p>
<div className="my-3">
<Detail label="Description" value={activeTask?.data?.description} />
</div>
<div className='flex items-center'>
<div className="my-3 w-full flex items-center gap-1">
<label className='text-slate-900 dark:text-white tracking-wide font-semibold'>Price</label>
<p className='p-1 text-sm text-slate-900 dark:text-white'>{PriceFormatter(activeTask?.data?.price*0.01, activeTask?.data?.currency, activeTask?.data?.curreny_code)}</p>
</div>
<div className="my-3 w-full flex items-center gap-1">
<label className='text-slate-900 dark:text-white tracking-wide font-semibold'>Timeline</label>
<p className='p-1 text-sm text-slate-900 dark:text-white'>{`${activeTask?.data?.timeline_days} day(s)`}</p>
</div>
</div>
<div className="my-3 sm:flex items-center">
<Detail
label="Created"
value={`Dummy, no value found for created!`}
/>
</div>
<div className="my-3">
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
Delivery Detail
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
value={activeTask?.data?.job_detail}
readOnly
// onChange={handleInputChange}
/>
{/* <p>{}</p> */}
</div>
</div>
</div>
:
<></>
}
</div>
{/* BTN */}
<div className='p-2 border-t-2 flex justify-end items-center gap-3'>
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-2 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
<button
disabled={requestStatus.loading}
onClick={action} type="button"
className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white cursor-pointer"
>
<span className='text-gradient'>Close</span>
</button>
<div className=''>
{requestStatus.loading ?
<LoadingSpinner color='sky-blue' size='8' />
:
<button
type="button"
disabled={requestStatus.loading}
onClick={assignFamilyTask}
className="px-1 w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
>
Assign
</button>
}
</div>
</div>
</>
}
</div>
</ModalCom>
</>
)
}
export default AssignTaskPopout
@@ -0,0 +1,56 @@
import { forwardRef } from 'react'
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"
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 ">
<div className="flex items-center justify-around h-[380px]">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
</span>
</h2>
</div>
<span className="text-5xl text-gray-400 opacity-20 font-bold">
or
</span>
<div className="max-w-[200px]">
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
viewBox={`0 0 256 256`}
/>
</div>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
<button
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
onClick={handlePrint}
>
Print
</button>
</div>
</div>
</div>
);
});
export default FamilyAccount
@@ -1,312 +0,0 @@
import React, {
Suspense,
forwardRef,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import QRCode from "react-qr-code";
import { useReactToPrint } from "react-to-print";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import profile from "../../../assets/images/profile-info-profile.png";
import FamilyTasks from "./FamilyTasks";
export default function FamilyManageTabs({
className,
accountDetails,
listReload,
loader,
}) {
const [details, setDetails] = useState({
familyDetails: {
loading: false,
data: null,
},
familyTasks: {
loading: false,
data: null,
},
});
const [errMsg, setErrMsg] = useState("");
// List of tabs
const tabs = [
{
id: 1,
name: "Tasks",
},
{
id: 2,
name: "Account",
},
{
id: 3,
name: "Profile",
},
];
const [tab, setTab] = useState(tabs[0].name);
const tabHandler = (value) => {
setTab(value);
};
// For profile uploads
const [profileImg, setProfileImg] = useState(profile);
// profile img
const profileImgInput = useRef(null);
const browseProfileImg = () => {
profileImgInput.current.click();
};
const profileImgChangHandler = (e) => {
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
setProfileImg(event.target.result);
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
// Api call
const apiCall = useMemo(() => new usersService(), []);
// function for manage family
const manageFamily = useCallback(async () => {
try {
setDetails({
familyDetails: { loading: true },
familyTasks: { loading: true },
});
let { family_uid } = accountDetails;
let reqData = { family_uid };
// the family response
const familyRes = await apiCall.ManageFamily(reqData);
const familyData = familyRes.data;
// the tasks response
const tasksRes = await apiCall.ManageTasks(reqData);
const tasksData = tasksRes.data;
// checking the internal return
if (familyData?.internal_return < 0 || tasksData?.internal_return < 0)
return;
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
});
} catch (error) {
setDetails({
familyDetails: { loading: false },
familyTasks: { loading: false },
});
setErrMsg("An error occurred");
throw new Error(error);
}
}, [apiCall, accountDetails]);
useEffect(() => {
manageFamily();
}, [tab, manageFamily]);
const accountRef = useRef();
// to handle printing
const useHandlePrint = useReactToPrint({
content: () => accountRef.current,
});
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 || ""
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<Suspense
fallback={
<div className="h-full min-h-[500px] 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="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full">
<ProfileInfo
profileImg={profileImg}
profileImgInput={profileImgInput}
profileImgChangHandler={profileImgChangHandler}
browseProfileImg={browseProfileImg}
accountDetails={accountDetails}
/>
</div>
<div className="col-span-3 justify-self-end h-full w-full">
<div className="flex flex-col w-full">
<ul className="flex-[0.1] flex gap-2 items-center border-b border-b-[#FAFAF] w-full">
{tabs.map(({ name, id }) => (
<li
onClick={() => tabHandler(name)}
className={`p-4 flex hover:text-purple transition-all ease-in-out items-center cursor-pointer overflow-hidden text-xl ${
tab === name
? "text-purple border-r"
: " text-thin-light-gray"
}`}
key={id}
>
<h1>{name}</h1>
</li>
))}
</ul>
<div className="flex-[0.9] lg:min-h-[450px] h-full">
{/* Your content here */}
{tabs.map(({ name, id }) => {
return (
<div
className={`${
tab === name ? "block" : "hidden"
} h-full p-4 border border-[#dbd9d9] relative overflow-y-auto`}
key={id}
>
{name === "Tasks" && (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
/>
)}
{name === "Account" && (
<Account
familyData={details.familyDetails.data}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
)}
{name === "Profile" && <Profile />}
</div>
);
})}
</div>
</div>
</div>
</div>
</Suspense>
</div>
</div>
);
}
function ProfileInfo({
profileImg,
profileImgInput,
profileImgChangHandler,
browseProfileImg,
accountDetails,
}) {
return (
<div className="flex flex-col items-center gap-6">
<div className="flex justify-center">
<div className="w-full relative">
<img
src={profileImg}
alt=""
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
/>
<input
ref={profileImgInput}
onChange={(e) => profileImgChangHandler(e)}
type="file"
className="hidden"
/>
<div
onClick={browseProfileImg}
className="w-[32px] h-[32px] absolute bottom-7 sm:right-2 right-[105px] hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
>
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
fill="white"
/>
<path
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
fill="white"
/>
</svg>
</div>
</div>
</div>
<div className="flex flex-col justify-center gap-3 items-center">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.firstname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.lastname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.age}
</h1>
</div>
</div>
);
}
const Account = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
return (
<div
className="w-full lg:min-h-[500px] 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 ">
<div className="flex items-center justify-around h-[380px]">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
</span>
</h2>
</div>
<span className="text-5xl text-gray-400 opacity-20 font-bold">
or
</span>
<div className="max-w-[200px]">
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
viewBox={`0 0 256 256`}
/>
</div>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
<button
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
onClick={handlePrint}
>
Print
</button>
</div>
</div>
</div>
);
});
function Profile() {
return <>Profile</>;
}
@@ -0,0 +1,154 @@
import { 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";
export default function FamilyPending({
familyData,
className,
accountDetails,
loader,
}) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let filteredFamilyData = familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
);
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentPendingTasks = filteredFamilyData?.slice(
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{currentPendingTasks.length > 0 ? (
currentPendingTasks.map((value, index) => {
let deliveryDate = value?.expire?.split(" ")[0];
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
return (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] max-w-[60px]">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "}
<span className="text-purple">
{thePrice}
</span>
</span>
<div className="flex items-center gap-4">
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire:{" "}
<span className="text-purple">
{" "}
{deliveryDate}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Sent to:{" "}
<span className="text-purple">
{" "}
{value.job_to}
</span>
</span>
</div>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={() => {
setJobPopout({ show: true, data: value });
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Pending Task!</td>
</tr>
)}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0}
next={currentPage + itemsPerPage >= filteredFamilyData.length}
data={filteredFamilyData}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
)}
{/* Active Job Popout */}
{jobPopout.show && (
<PendingJobsPopout
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
situation={jobPopout.show}
/>
)}
{/* End of Active Job Popout */}
</div>
);
}
@@ -0,0 +1,3 @@
export default function FamilyProfile() {
return <>Profile</>;
}
@@ -6,8 +6,11 @@ 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";
export default function FamilyTasks({ familyData, className, loader }) {
export default function FamilyTasks({ familyData, className, loader, accountDetails }) {
let navigate = useNavigate();
let { pathname } = useLocation();
@@ -34,7 +37,6 @@ export default function FamilyTasks({ familyData, className, loader }) {
</div>
) : (
<>
{" "}
{familyData && familyData?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
@@ -105,9 +107,8 @@ export default function FamilyTasks({ familyData, className, loader }) {
state: {
...value,
pathname,
dueDate,
thePrice,
},
accountDetails
}
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
@@ -0,0 +1,119 @@
import { useState } from "react";
import { handlePagingFunc, PaginatedList } from "../../Pagination";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import SuggestTask from "../../FamilyPopup/SuggestTask";
const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
let filteredFamilyData = familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
);
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = currentPage;
const indexOfLastItem = currentPage + itemsPerPage;
const currentTask = filteredFamilyData?.slice(
indexOfFirstItem,
indexOfLastItem
);
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 || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
</div>
) : (
<>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{currentTask.map((value) => {
const addedDate = value?.added.split(" ")[0];
const taskImg = require(`../../../assets/images/family/${
value?.banner || "default.jpg"
}`);
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={value.uid}
>
<td className="py-4">
<div className="w-full flex justify-between items-center">
<div className="account-name flex space-x-4 items-center">
<div className="icon w-14 h-14 flex justify-center items-center">
<img
src={taskImg}
alt="task_img"
className="w-full object-cover"
/>
</div>
<div className="">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{value.title}
</p>
<p className="text-sm text-thin-light-gray font-medium">
{value.description}
</p>
</div>
</div>
<div className="px-2">
<p className="text-sm font-bold text-dark-gray dark:text-white">
{addedDate}
</p>
<p className="text-sm text-dark-gray dark:text-white">
Status: {value.status_text}
</p>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
onClick={() =>
setPopUp({ show: true, data: value })
}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})}
</tbody>
</table>
<PaginatedList
onClick={handlePagination}
prev={currentPage === 0}
next={currentPage + itemsPerPage >= filteredFamilyData?.length}
data={filteredFamilyData}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
</div>
)}
</>
)}
{popUp.show && (
<SuggestTask
details={popUp.data}
onClose={() => {
setPopUp({ show: false, data: {} });
}}
situation={popUp.show}
/>
)}
</div>
);
};
export default FamilyWaitlist;
@@ -0,0 +1,61 @@
import React from "react";
export default function ProfileInfo({
profileImg,
profileImgInput,
profileImgChangHandler,
browseProfileImg,
accountDetails,
}) {
return (
<div className="flex flex-col items-center gap-6">
<div className="flex justify-center">
<div className="w-full relative">
<img
src={profileImg}
alt=""
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
/>
<input
ref={profileImgInput}
onChange={(e) => profileImgChangHandler(e)}
type="file"
className="hidden"
/>
<div
onClick={browseProfileImg}
className="w-[32px] h-[32px] absolute bottom-7 sm:right-2 right-[105px] hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
>
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
fill="white"
/>
<path
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
fill="white"
/>
</svg>
</div>
</div>
</div>
<div className="flex flex-col justify-center gap-3 items-center">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.firstname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.lastname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.age}
</h1>
</div>
</div>
);
}
+15
View File
@@ -0,0 +1,15 @@
import FamilyAccount from "./FamilyAccount";
import FamilyProfile from "./FamilyProfile";
import FamilyTasks from "./FamilyTasks";
import FamilyWaitlist from "./FamilyWaitlist";
import FamilyPending from "./FamilyPending";
import ProfileInfo from "./ProfileInfo";
export {
FamilyAccount,
FamilyProfile,
FamilyTasks,
FamilyWaitlist,
FamilyPending,
ProfileInfo,
};
+193
View File
@@ -0,0 +1,193 @@
import { useState } from "react";
import { useLocation } from "react-router-dom";
import ModalCom from "../Helpers/ModalCom";
import { Form, Formik } from "formik";
import InputCom from "../Helpers/Inputs/InputCom";
import usersService from "../../services/UsersService";
const DEFAULT_IMAGE = require("../../assets/images/family/default.jpg");
const SuggestTask = ({ details, onClose, situation }) => {
const { pathname, state } = useLocation();
const [submitTask, setSubmitTask] = useState({
loading: false,
msg: "",
state: "",
});
// default image
const selectedImage = details?.selectedImage || DEFAULT_IMAGE;
const initialValues = {
title: details?.title || "",
description: details?.description || "",
banner: details?.banner,
};
const apiCall = new usersService();
const handleSubmit = async (values) => {
if (!values.title && !values.description) return;
try {
setSubmitTask({ loading: true });
const reqData = { ...values };
const res = await apiCall.sendFamilySuggestedTasks(reqData);
if (res.internal_return < 0) {
setSubmitTask({ loading: false, msg: res.status, state: "bad" });
return;
}
setSubmitTask({ loading: false, msg: res.status, state: "success" });
setTimeout(() => {
onClose();
}, 2000);
} catch (error) {
setSubmitTask({ loading: false, msg: error, state: "bad" });
throw new Error("Error Occurred", error);
}
};
// console.log("state >-->>", state);
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
{pathname === "/manage-family"
? `${state?.firstname}'s Suggested Task`
: "Suggest to Parent"}
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={onClose}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
{(props) => {
return (
<Form>
<div className="p-5 w-full bg-white rounded-md flex justify-between">
<div className="p-4 w-full md:w-2/4 md:border-r-2">
<div
className="w-full h-[236px] p-6 bg-gray-400 rounded-xl overflow-hidden"
style={{
// background: `url(${selectedImage}) 0% 0% / cover no-repeat`,
background: `url(${selectedImage}) center / contain no-repeat`,
}}
></div>
</div>
{/* ACTION SECTION */}
<div className="p-4 w-full md:w-2/4 h-full">
{/* Title */}
<div className="field w-full mb-[15px]">
<InputCom
fieldClass={
pathname === "/manage-family" ? "px-2" : "px-6"
}
label="Title"
labelClass="tracking-wide"
inputBg={
pathname === "/manage-family"
? "bg-white"
: "bg-slate-100"
}
inputClass="disabled:cursor-default"
type="text"
name="title"
disable={details?.title}
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.title &&
props.touched.title &&
props.errors.title
}
/>
</div>
{/* Description */}
<div className="field w-full mb-[5px]">
<label
htmlFor="description"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1'
>
Description
{props.errors.description &&
props.touched.description && (
<span className="text-[12px] text-red-500">
{props.errors.description}
</span>
)}
</label>
<textarea
id="description"
rows="5"
className={`input-field pt-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[130px] ${
pathname === "/manage-family"
? "px-2"
: "bg-slate-100 px-3 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]"
}`}
style={{ resize: "none" }}
name="description"
value={props.values.description}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
</div>
</div>
</div>
<div className="w-full h-[70px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-9">
<button
type="button"
className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full"
onClick={onClose}
>
<span className="text-gradient"> Cancel</span>
</button>
{pathname !== "/manage-family" && (
<button
type="submit"
disabled={props.isSubmitting}
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
{submitTask.loading
? "Submitting Task"
: submitTask.state == "success"
? "Task Submitted"
: submitTask.state == "bad"
? "An Error Occurred"
: "Send to Parents"}
</button>
)}
</div>
</div>
</Form>
);
}}
</Formik>
</div>
</ModalCom>
);
};
export default SuggestTask;
+56 -51
View File
@@ -1,59 +1,64 @@
/* eslint-disable no-underscore-dangle */
import React, { useEffect, useState } from "react";
import { useEffect, useState } from "react";
function CountDown({ lastDate = "" }) {
// const [showDate, setDate] = useState(0);
const [showHour, setHour] = useState(0);
const [showMinute, setMinute] = useState(0);
const [showSecound, setDateSecound] = useState(0);
// count Down
const provideDate = new Date(lastDate);
// format date
const year = provideDate.getFullYear();
const month = provideDate.getMonth();
// console.log(month);
const date = provideDate.getDate();
// console.log(date);
const hours = provideDate.getHours();
// console.log(hours);
const minutes = provideDate.getMinutes();
// console.log(minutes);
const seconds = provideDate.getSeconds();
// console.log(seconds);
// date calculation logic
const _seconds = 1000;
const _minutes = _seconds * 60;
const _hours = _minutes * 60;
const _date = _hours * 24;
// interval function
const startInterval = () => {
const timer = setInterval(() => {
const now = new Date();
const distance =
new Date(year, month, date, hours, minutes, seconds).getTime() -
now.getTime();
if (distance < 0) {
clearInterval(timer);
return;
}
// setDate(Math.floor(distance / _date));
setMinute(Math.floor((distance % _hours) / _minutes));
setHour(Math.floor((distance % _date) / _hours));
setDateSecound(Math.floor((distance % _minutes) / _seconds));
}, 1000);
};
// effect
useEffect(() => {
if (lastDate !== "") {
startInterval();
}
// State to store the countdown values
const [countdownValues, setCountdownValues] = useState({
showHour: 0,
showMinute: 0,
showSecond: 0,
});
useEffect(() => {
if (lastDate) {
// Interval function to update countdown values
const intervalId = setInterval(() => {
const now = new Date().getTime();
const targetDate = new Date(lastDate).getTime();
const distance = targetDate - now;
if (distance < 0) {
// If the countdown has reached zero or gone past the target date, clear the interval
clearInterval(intervalId);
setCountdownValues({
showHour: 0,
showMinute: 0,
showSecond: 0,
});
return;
}
// Calculate the countdown values (days, hours, minutes, seconds)
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
// since we don't have a slot for days...
const totalHours = days * 24 + hours;
// Update the countdown values in the state
setCountdownValues({
showHour: totalHours,
showMinute: minutes,
showSecond: seconds,
});
}, 1000);
// Clean up the interval on component unmount or when the lastDate prop changes
return () => clearInterval(intervalId);
}
}, [lastDate]);
// Destructure the countdown values from the state
const { showHour, showMinute, showSecond } = countdownValues;
return (
<span>
{showHour} : {showMinute} : {showSecound}
{showHour < 10 ? "0" + showHour : showHour} :{" "}
{showMinute < 10 ? "0" + showMinute : showMinute} :{" "}
{showSecond < 10 ? "0" + showSecond : showSecond}
</span>
);
}
@@ -1,6 +1,6 @@
import React, { useRef } from "react";
import Icons from "../../Icons";
import { Link } from "react-router-dom";
import Icons from "../../Icons";
export default function InputCom({
label,
@@ -22,7 +22,7 @@ export default function InputCom({
spanTag,
inputBg,
direction,
errorBorder
error,
}) {
const inputRef = useRef(null);
// Entry Validation
@@ -41,27 +41,29 @@ export default function InputCom({
// for Patterns
const inputPatterns = () => {
const inputConfig = inputConfigs[inputRef?.current?.name]?.pattern;
return inputConfig || ""
}
return inputConfig || "";
};
return (
<div className={`input-com ${parentClass}`}>
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
{label && (
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
htmlFor={name}
>
{label}
{spanTag &&
spanTag == '*' ?
{spanTag && spanTag == "*" ? (
<span className="text-red-700 text-sm tracking-wide">
{' '}{spanTag}
{" "}
{spanTag}
</span>
:
) : (
<span className="text-green-700 text-sm tracking-wide">
{spanTag}
</span>
}
)}
{/* displays error is any */}
{error && <span className="text-[12px] text-red-500">{error}</span>}
</label>
)}
{forgotPassword && (
@@ -74,7 +76,7 @@ export default function InputCom({
)}
</div>
<div
className={`input-wrapper border ${errorBorder ? "border-red-500 border-[0.5px] animate-shake" : "border border-[#f5f8fa] dark:border-[#5e6278]"} w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`}
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}
@@ -96,11 +98,9 @@ export default function InputCom({
/>
{iconName && (
<div className="absolute right-6 bottom-[10px] z-10 flex gap-2">
{
iconName.split(' ').map((item, index)=>(
<Icons key={index} name={item} />
))
}
{iconName.split(" ").map((item, index) => (
<Icons key={index} name={item} />
))}
</div>
)}
{passIcon && (
@@ -126,6 +126,9 @@ const inputConfigs = {
province: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
city: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" },
description: { minLength: 5, maxLength: 299 },
title: { minLength: 5, maxLength: 149 },
job_detail: { minLength: 4, maxLength: 1440 }
};
/* Numbers Only: <input type="text" pattern="[0-9]*" /> strictly numbers
+25 -22
View File
@@ -1,4 +1,4 @@
import React from 'react'
import React from "react";
// export const PriceFormatter = (price, currency, currencyName) => {
// const supportedCurrencies = ["USD", "EUR", "GBP"];
@@ -17,32 +17,35 @@ import React from 'react'
// return `${formatter.format(price)} ${displayCurrencyName}`;
// };
export const PriceFormatter = (price='00', currency='', currencyName='') => {
export const PriceFormatter = (
price = "00",
currency = "",
currencyName = ""
) => {
// Convert the number to a string
let numStr = String(price);
let numStr = String(price);
// Split the string into integer and decimal parts
let parts = numStr.split('.');
let integerPart = parts[0];
let decimalPart = parts[1] || '';
// Split the string into integer and decimal parts
let parts = numStr.split(".");
let integerPart = parts[0] || "";
let decimalPart = parts[1] || "";
// Add thousands separators to the integer part
// let formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
let formattedInteger = integerPart;
// Add thousands separators to the integer part
// let formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
let formattedInteger = integerPart;
// Truncate or pad the decimal part to two decimal points
let formattedDecimal = decimalPart.slice(0, 2).padEnd(2, '0');
// Truncate or pad the decimal part to two decimal points
let formattedDecimal = decimalPart.slice(0, 2).padEnd(2, "0");
// Combine the formatted integer and decimal parts
// let formattedNumber = formattedInteger + '.' + formattedDecimal;
// Combine the formatted integer and decimal parts
// let formattedNumber = formattedInteger + '.' + formattedDecimal;
// return formattedNumber;
// return formattedNumber;
return (
<span className='text-sm flex items-center'>
<sup>{currency || currencyName || ''}</sup>
<span className='px-1 font-bold text-lg'>{formattedInteger}</span>
<sup>{formattedDecimal}</sup>
<span className="text-sm flex items-center">
<sup>{currency || currencyName || ""}</sup>
<span className="px-1 font-bold text-lg">{formattedInteger || ""}</span>
<sup>{formattedDecimal || ""}</sup>
</span>
)
}
);
};
+11 -3
View File
@@ -1,7 +1,13 @@
import React from "react";
import React, { useState } from "react";
import Icons from "./Icons";
export default function SearchCom({ className, inputClasses }) {
export default function SearchCom({
className,
inputClasses,
placeholder,
handleSearch,
value,
}) {
return (
<div
className={`w-full h-[48px] pl-8 flex rounded-full overflow-hidden bg-white dark:bg-dark-white ${
@@ -17,7 +23,9 @@ export default function SearchCom({ className, inputClasses }) {
inputClasses || ""
}`}
type="text"
placeholder="Search items, collections..."
onInput={handleSearch}
value={value}
placeholder={placeholder || "Search items, collections..."}
/>
</div>
</div>
+10 -6
View File
@@ -1,20 +1,22 @@
import React, { useRef } from "react";
import ProductCardStyleOne from "../Cards/ProductCardStyleOne";
//import ProductCardStyleOne from "../Cards/ProductCardStyleOne";
import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom";
import FamilyActiveJobsCard from "../Cards/FamilyActiveJobsCard";
export default function FamilyActiveLSlde({ className, trending }) {
const settings = {
arrows: false,
slidesToShow: 4,
slidesToScroll: 4,
infinite: true,
slidesToShow: 3,
slidesToScroll: 3,
infinite: trending?.length > 3,
responsive: [
{
breakpoint: 1025,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: trending?.length > 3,
},
},
{
@@ -22,6 +24,7 @@ export default function FamilyActiveLSlde({ className, trending }) {
settings: {
slidesToShow: 2,
slidesToScroll: 2,
infinite: trending?.length > 2,
},
},
{
@@ -29,6 +32,7 @@ export default function FamilyActiveLSlde({ className, trending }) {
settings: {
slidesToShow: 1,
slidesToScroll: 1,
infinite: trending?.length > 1,
},
},
],
@@ -89,12 +93,12 @@ export default function FamilyActiveLSlde({ className, trending }) {
</div>
</div>
{/* trending products */}
<div className="trending-products relative w-full">
<div className="trending-products slider-left relative w-full rounded-2xl p-[10px] bg-alice-blue">
<SliderCom selector={trendingSlider} settings={settings}>
{trending &&
trending.length > 0 &&
trending.map((item) => (
<ProductCardStyleOne key={item.id} datas={item} />
<FamilyActiveJobsCard key={item.id} datas={item} />
))}
</SliderCom>
</div>
+22 -18
View File
@@ -3,23 +3,27 @@ import datas from "../../data/product_data.json";
import TopSellerTopBuyerSliderSection from "./TopSellerTopBuyerSliderSection";
import CommonHead from "../UserHeader/CommonHead";
import FamilyActiveLSlde from "./FamilyActiveLSlde";
import ParentWaiting from "../MyPendingJobs/ParentWaiting";
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
export default function FamilyDash({familyOffers, MyActiveJobList}) {
console.log("PROPS IN FAMILY DASH->", familyOffers);
export default function FamilyDash(props) {
console.log("PROPS IN FAMILY DASH->",props);
const trending = datas.datas;
return (
<div>
<div className="home-page-wrapper">
<CommonHead
commonHeadData={props.commonHeadData}
/>
<FamilyActiveLSlde trending={trending} className="mb-10" />
<TopSellerTopBuyerSliderSection className="mb-10" />
</div>
</div>
);
}
const trending = MyActiveJobList;
return (
<div>
<div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
{familyOffers && familyOffers.length > 0 &&
<MyOffersFamilyTable familyOffers={familyOffers} className="mb-10" />
}
{trending && trending.length > 0 &&
<FamilyActiveLSlde trending={trending} className="mb-10" />
}
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
<ParentWaiting className="mb-10" />
</div>
</div>
);
}
+3 -3
View File
@@ -56,15 +56,15 @@ export default function Hero({ className, bannerList, nextDueTask }) {
</div>
</div>
{/* countdown */}
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length && (
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border border-white-opacity">
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Current Task</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{nextDueTask.next_due.item_code}
{(nextDueTask.next_due.item_code).substr(0,4)+'...'}
</p>
<p className="text-base text-white tracking-wide">
{nextDueTask.next_due.price} Naira
{nextDueTask.next_due.price * 0.01} Naira
</p>
</div>
<div className="w-[1px] h-full bg-white-opacity"></div>
+1 -2
View File
@@ -3,11 +3,10 @@ import slider2 from "../../assets/images/slider-2.jpg";
import HomeBannerOffersCard from "../Cards/HomeBannerOffersCard";
export default function HomeSliders(props) {
// console.log("BANNER LIST IN HomeSliders->", props.bannerList);
// debugger;
return (
<>
<div className="hero-slider relative 2xl:w-[600px] xl:w-[500px] lg:w-[420px] w-full mb-2 lg:mb-0 ">
<div className="hero-slider relative 2xl:w-[600px] xl:w-[400px] lg:w-[420px] w-full mb-2 lg:mb-0 ">
<div className="w-full">
<SliderCom settings={props.settings}>
{props.bannerList?.length <= 0 && (
+45 -8
View File
@@ -8,14 +8,26 @@ import FullAccountDash from "./FullAccountDash";
export default function Home(props) {
console.log("PROPS IN HOME->", props);
const userApi = new usersService();
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
let [nextDueTask, setNextDueTask] = useState({});
const userApi = new usersService();
const [MyOffersList, setMyOffersList] = useState([]);
const { userDetails } = useSelector((state) => state?.userDetails);
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
const [MyActiveJobList, setMyActiveJobList] = useState([]); // STATE TO HOLD ACTIVE/CURRENT TASKS
const getMyActiveJobList = async () => { // FUNCTION TO POPULATE ACTIVE/CURRENT TASK LIST
try {
const res = await userApi.getMyActiveTaskList();
setMyActiveJobList(res?.data?.result_list);
} catch (error) {
setMyActiveJobList([]);
console.log("Error getting tasks");
}
};
// FUNCTION TO GET DASH DATA TO DETERMINE CURRENT TASK DUE TIME
const getHomeDate = () => {
@@ -32,21 +44,46 @@ export default function Home(props) {
});
};
const getMyOffersList = async () => {
try {
const res = await userApi.getOffersList();
setMyOffersList(res.data?.result_list);
} catch (error) {
console.log("Error getting offers", error);
}
};
useEffect(() => {
getHomeDate();
const fetchData = async () => {
await Promise.all([getHomeDate(), getMyOffersList()]);
};
fetchData();
}, []);
useEffect(() => {
getMyActiveJobList();
}, []);
return (
<Layout>
<div className="home-page-wrapper">
{userDetails && userDetails?.account_type == "FAMILY" && (
<FamilyDash commonHeadData={props.bannerList} />
)}
{userDetails && userDetails?.account_type == "FULL" && (
{userDetails && userDetails?.account_type == "FAMILY" ? (
<FamilyDash
account={userDetails}
commonHeadData={props.bannerList}
familyOffers={MyOffersList}
MyActiveJobList={MyActiveJobList}
/>
) : userDetails && userDetails?.account_type == "FULL" ? (
<FullAccountDash
nextDueTask={nextDueTask}
bannerList={props.bannerList}
/>
) : (
<div>
You are not logged in or your account type is not supported.
</div>
)}
</div>
</Layout>
+28 -15
View File
@@ -1,8 +1,8 @@
import React, { useEffect, useMemo, useState } from "react";
import DataIteration from "../Helpers/DataIteration";
import AvailableJobsCard from "../Cards/AvailableJobsCard";
import ListView from '../../assets/images/list-view.png'
import GridView from '../../assets/images/grid-view.svg'
import ListView from "../../assets/images/list-view.png";
import GridView from "../../assets/images/grid-view.svg";
import SelectBox from "../Helpers/SelectBox";
export default function MainSection({
@@ -17,7 +17,7 @@ export default function MainSection({
);
const [tab, setTab] = useState(Object.keys(marketCategories)[0]);
let [contentDisplay, setContentDisplay] = useState('grid') // STATE TO HOLD LIST VIEW STYLE
let [contentDisplay, setContentDisplay] = useState("grid"); // STATE TO HOLD LIST VIEW STYLE
// Convert to array in order to map
const mappedArray = Object.entries(marketCategories).map(([key, value]) => {
@@ -29,8 +29,8 @@ export default function MainSection({
setTab(value);
};
// Handles the category selection on mobile view
const handleSetCategory = (value) => {
// Handles the category selection on mobile view
const handleSetCategory = (value) => {
for (let i in marketCategories) {
if (marketCategories[i] == value) {
setTab(i);
@@ -57,7 +57,7 @@ export default function MainSection({
<div className="hidden lg:flex md:space-x-8 space-x-2">
{mappedArray.map(({ key, value }) => (
<span
key={key}
key={key}
onClick={() => tabHandler(key)}
className={`md:text-[18px] text-md text-dark-gray dark:text-white hover:text-pink border-b hover:border-pink font-medium cursor-pointer ${
tab === key
@@ -76,30 +76,43 @@ export default function MainSection({
datas={Object.values(marketCategories)}
className="Update-table-dropdown"
contentBodyClasses="w-auto min-w-max"
position='left'
position="left"
/>
</div>
</div>
{/* contentDisplay toggler */}
<div className="p-2 w-[35px] h-[35px] bg-white dark:bg-slate-200 rounded-lg">
<img
title={contentDisplay=='grid'? 'list view' : 'grid view'}
onClick={()=>setContentDisplay((prev)=>prev=='grid'? 'list' : 'grid')}
src={contentDisplay=='grid'? ListView : GridView}
className="w-full h-full cursor-pointer" alt="view"
/>
<img
title={contentDisplay == "grid" ? "list view" : "grid view"}
onClick={() =>
setContentDisplay((prev) => (prev == "grid" ? "list" : "grid"))
}
src={contentDisplay == "grid" ? ListView : GridView}
className="w-full h-full cursor-pointer"
alt="view"
/>
</div>
{/* end of contentDisplay toggler */}
</div>
<div className="filter-navigate-content w-full min-h-screen">
<div className={contentDisplay == 'grid' ? 'grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]' : 'w-full'}>
<div
className={
contentDisplay == "grid"
? "grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]"
: "w-full"
}
>
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products?.length}
>
{({ datas }) => (
<AvailableJobsCard contentDisplay={contentDisplay} key={datas.id} datas={datas} />
<AvailableJobsCard
contentDisplay={contentDisplay}
key={datas.id}
datas={datas}
/>
)}
</DataIteration>
</div>
@@ -0,0 +1,12 @@
import React from 'react'
function Detail({label, value, bg,}) {
return (
<>
<label className='w-full md:w-1/4 text-slate-900 tracking-wide font-semibold'>{label}</label>
<p className={`p-1 w-full md:w-3/4 text-sm text-slate-900 ${bg ? bg : null}`}>{value}</p>
</>
)
}
export default Detail
+103 -88
View File
@@ -1,23 +1,98 @@
import React, { useCallback, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import ModalCom from "../../Helpers/ModalCom";
import { toast } from "react-toastify";
import { Form, Formik } from "formik";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
const [marketMsg, setMarketMsg] = useState({
loading: false,
data: {},
state: undefined,
});
const [manageInt, setManageInt] = useState({
loading: false,
data: {},
state: undefined,
msg: "",
});
const MarketCalls = (details) => {
const [marketMsg, setMarketMsg] = useState({
loading: false,
data: {},
state: undefined,
});
const [manageInt, setManageInt] = useState({
loading: false,
data: {},
state: undefined,
msg: "",
});
const { offer_code } = details;
const reqData = { offer_code };
const MarketDetail = async () => {
try {
setMarketMsg({ loading: true });
if (!textValue) return;
reqData.yourmessage = textValue;
const marketMessage = await apiCall.MarketMessage(reqData);
const marketMessageRes = marketMessage?.data;
if (marketMessageRes?.internal_return < 0) {
toast.warn("Something wrong happened", {
autoClose: 2000,
hideProgressBar: true,
});
onClose();
return;
}
toast.success("Message sent", {
autoClose: 2500,
hideProgressBar: true,
});
setMarketMsg({ data: marketMessageRes, state: true });
setTimeout(() => onClose(), 2000);
} catch (error) {
throw new Error(error);
} finally {
setTimeout(() => {
setTextValue("");
setMarketMsg({ loading: false });
}, 2000);
}
};
const ManageInterest = async () => {
try {
setManageInt({ loading: true });
const manageInt = await apiCall.MarketInterest(reqData);
const manageIntRes = manageInt?.data;
if (manageIntRes?.internal_return < 0) {
setManageInt({
loading: false,
msg: manageIntRes?.status,
data: manageIntRes,
state: false,
});
} else {
setManageInt({
loading: false,
msg: manageIntRes?.status,
data: manageIntRes,
state: true,
});
}
setTimeout(() => setManageInt({ msg: "" }), 3000);
} catch (error) {
throw new Error(error);
}
};
// useEffect(() => {
// ManageInterest();
// }, []);
return { MarketDetail, ManageInterest, manageInt, marketMsg };
};
const [textValue, setTextValue] = useState("");
@@ -27,75 +102,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
const apiCall = useMemo(() => new usersService(), []);
const marketCalls = useCallback(
async (e) => {
try {
const nameOfCall = e?.target?.name;
const { offer_code } = details;
const reqData = { offer_code };
if (nameOfCall === "market-message") {
setMarketMsg({ loading: true });
if (!textValue) return;
reqData.yourmessage = textValue;
const marketMessage = await apiCall.MarketMessage(reqData);
const marketMessageRes = marketMessage?.data;
if (marketMessageRes?.internal_return < 0) {
toast.warn("Something wrong happened", {
autoClose: 2000,
hideProgressBar: true,
});
onClose();
return;
}
toast.success("Message sent", {
autoClose: 2500,
hideProgressBar: true,
});
setMarketMsg({ data: marketMessageRes, state: true });
setTimeout(() => onClose(), 2000);
} else {
setManageInt({ loading: true });
const manageInt = await apiCall.MarketInterest(reqData);
const manageIntRes = manageInt?.data;
if (manageIntRes?.internal_return < 0) {
setManageInt({
loading: false,
msg: `Error - ${manageIntRes?.status}`,
data: manageIntRes,
state: false,
});
} else {
setManageInt({
loading: false,
msg: manageIntRes?.status,
data: manageIntRes,
state: true,
});
}
setTimeout(() => setManageInt({ msg: "" }), 3000);
return;
}
} catch (error) {
throw new Error(error);
} finally {
setTimeout(() => {
setTextValue("");
setMarketMsg({ loading: false });
}, 2000);
}
},
[apiCall, details, onClose, textValue]
);
let { manageInt, ManageInterest, MarketDetail, marketMsg } = MarketCalls(details);
let thePrice = PriceFormatter(
details?.price * 0.01,
@@ -104,7 +111,13 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
);
// let addedIntDate = marketInt?.added?.split(" ")[0];
let expireIntDate = marketInt?.expire?.split(" ")[0];
// let expireIntDate = marketInt?.expire?.split(" ")[0];
let cleanedText = details?.job_description
?.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&amp;/g, "&");
return (
<ModalCom action={onClose} situation={situation} className="edit-popup">
@@ -138,7 +151,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
},
{
name: "Delivery Detail",
content: details.job_description,
content: cleanedText,
danger: true,
},
].map(({ name, content, danger }, idx) => (
@@ -157,7 +170,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
<p
className={``}
dangerouslySetInnerHTML={{
__html: danger && content?.replace(/"/g, ""),
__html: danger && content,
}}
/>
) : (
@@ -203,7 +216,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
<button
className="self-end w-[150px] h-[52px] rounded-md text-base bg-yellow-500 text-white"
name="market-message"
onClick={marketCalls}
onClick={MarketDetail}
>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
@@ -226,7 +239,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
<button
className="bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md inline-flex sm:flex-col flex-row sm:gap-0 gap-1 items-center justify-center"
name="market-interest"
onClick={marketCalls}
onClick={ManageInterest}
>
{" "}
<span>Send</span>
@@ -257,7 +270,9 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
Interest: <b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1">Expire: {expireIntDate}</p>
<p className="my-1">
Expire: {details.expire}
</p>
</div>
</div>
<button
+25 -11
View File
@@ -248,6 +248,8 @@ function ActiveJobs(props) {
}
}, [passDue]);
console.log("AC JOBS >>", props);
return (
<Layout>
<div className="py-[20px] bg-white dark:bg-black dark:text-white px-4 rounded-2xl shadow-md md:flex justify-between items-start gap-16">
@@ -257,8 +259,13 @@ function ActiveJobs(props) {
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() =>
navigate(props.details.pathname, { replace: true })
onClick={() =>{
if(props.details.pathname == '/manage-family'){
navigate(props.details.pathname, {state: { ...props.details.accountDetails }}, { replace: true })
}else{
navigate(props.details.pathname, { replace: true })
}
}
}
>
<svg
@@ -278,12 +285,14 @@ function ActiveJobs(props) {
<div className="w-full my-2">
<p className="w-full text-base text-right text-sky-blue">
{props.details.job_to && props.details.job_to}
{props?.details && props.details.job_to}
</p>
<div className="text-base text-slate-700 dark:text-white tracking-wide">
<p className="font-semibold text-black dark:text-white">Description: </p>
<p className="font-semibold text-black dark:text-white">
Description:{" "}
</p>
<p className="p-2 border border-sky-blue">
{props.details?.description && props.details.description}
{props?.details && props.details.description}
</p>
</div>
</div>
@@ -297,11 +306,10 @@ function ActiveJobs(props) {
<div className="my-1">
<p className="text-base text-slate-700">
<span className="font-semibold">Due: </span>
{props.details?.delivery_date &&
props.details.delivery_date.split(" ")[0]}
{props?.details && props.details.delivery_date.split(" ")[0]}
</p>
<p className="py-2 text-base text-slate-700">
{props.details?.delivery_date &&
{props?.delivery_date &&
props.details.delivery_date.split(" ")[1]}
</p>
</div>
@@ -310,7 +318,9 @@ function ActiveJobs(props) {
<p className="font-semibold">Due: </p>
<div className="flex flex-col justify-between">
<p className="text-base text-slate-700 tracking-wide">
<CountDown lastDate={props.details.delivery_date} />
<CountDown
lastDate={props?.details && props.details.delivery_date}
/>
</p>
<div className="text-base text-slate-700 tracking-wide flex gap-[5px]">
<span>Hrs</span>
@@ -322,14 +332,18 @@ function ActiveJobs(props) {
)}
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">Duration: </span>
<span className="font-semibold text-black dark:text-white">
Duration:{" "}
</span>
<span className="">
{props.details?.timeline_days && props.details.timeline_days}{" "}
day(s)
</span>
</div>
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">No: </span>
<span className="font-semibold text-black dark:text-white">
No:{" "}
</span>
<span className="">
{props.details?.contract && props.details.contract}
</span>
@@ -79,7 +79,7 @@ function CurrentTaskAction({jobDetails}) {
<tr>
<td>
<div className="flex justify-center items-center">
<button onClick={popUpHandler} type="button" className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
<button onClick={popUpHandler} type="button" className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Send of Review
</button>
</div>
@@ -10,8 +10,8 @@ import ReviewJobAction from './ReviewJobAction'
import ReviewTaskAction from './ReviewTaskAction'
function IndexJobActions({details}) { // FUNCTION TO RENDER SPECIFIC JOB ACTION DEPENDING ON OWNER STATUS & STATUS DESCRIPTION
let owner = details.owner_status
let description = details.status_description
let owner = details?.owner_status
let description = details?.status_description
switch(owner) {
case 'OWNER':
return (()=>{
@@ -119,7 +119,7 @@ function PastDueJobAction({jobDetails}) {
<tr>
<td>
<div className="flex justify-center items-center">
<button type="button" onClick={popUpHandler} className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Cancel or Extend Timeline
</button>
</div>
@@ -20,7 +20,7 @@ function PastDueTaskAction() {
<tr>
<td>
<div className="flex justify-center items-center">
<button type="button" className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
<button type="button" className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Request Extension
</button>
</div>
@@ -108,7 +108,7 @@ function ReviewJobAction({jobDetails}) {
<tr>
<td>
<div className="flex justify-center items-center">
<button type="button" onClick={popUpHandler} className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Reject or Accept
</button>
</div>
+1
View File
@@ -10,6 +10,7 @@ export default function MyActiveJobs(props) {
setValue(value);
};
console.log("AMEYE LOC1", props.MyJobList);
return (
<Layout>
<CommonHead commonHeadData={props.commonHeadData} />
+10 -6
View File
@@ -11,6 +11,9 @@ import PaginatedList from "../Pagination/PaginatedList";
import EditJobPopOut from "../jobPopout/EditJobPopout";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import EditIcon from '../../assets/images/icon-edit.svg'
import DeleteIcon from '../../assets/images/icon-delete.svg'
export default function MyJobTable({ MyJobList, reloadJobList, className }) {
// Getting the categories
const currentJobCart = MyJobList?.data?.categories;
@@ -132,10 +135,10 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
</div>
</div>
<div className="min-w-[110px] max-w-[110px] bg-yellow-300 mx-2 rounded-md flex flex-nowrap space-x-2 justify-center items-center self-end">
<div className="h-[33px] w-[150px] flex flex-nowrap items-center self-end">
<button
type="button"
className="p-2 w-[60px] h-11"
className="p-1 border-2 border-red-400 rounded-md"
onClick={() => {
setDeleteJobPopout({
show: true,
@@ -143,12 +146,12 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
});
}}
>
[Delete]
<img className="w-[21px] h-[21px]" src={DeleteIcon} alt='delete-icon' />
</button>
<span>|</span>
<div className="mx-[4px] h-full w-[1px] bg-black dark:bg-dark-gray"></div>
<button
type="button"
className="p-2 w-[40px] h-11"
className="p-1 border-2 border-sky-blue rounded-md flex items-center"
onClick={() => {
setEditJob({
show: true,
@@ -156,7 +159,8 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
});
}}
>
Edit
<img className="w-[21px] h-[21px]" src={EditIcon} alt='edit-icon' />
<span className="text-sm text-sky-blue">Edit</span>
</button>
</div>
</div>
+2 -3
View File
@@ -9,12 +9,11 @@ export default function MyJobs(props) {
let { state } = useLocation();
const navigate = useNavigate();
const [popUp, setPopUp] = useState(false);
console.log(state)
const popUpHandler = () => {
setPopUp((prev) => !prev);
if (state?.popup) navigate("/", { replace: true });
if (state?.popup) navigate("/", { replace: true })
else return
};
const categoryOptions = props.MyJobList?.data?.categories;
@@ -0,0 +1,72 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import activeAidsBanner from "../../assets/images/kids-waiting.jpg";
import ParentWaitingTable from "./ParentWaitingTable";
export default function ParentWaiting({ className }) {
const [addFavorite, setValue] = useState(false);
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
toast.success("Added to Favorite List");
} else {
setValue(false);
toast.warn("Remove to Favorite List");
}
};
return (
<>
<div className={`overview-section w-full ${className || ""}`}>
<div className="w-full mb-3 flex justify-between items-center gap-1">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
Waiting for Parent to Get Started...
</h1>
<Link
to='/familymarket'
className="px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
More Task
</Link>
</div>
{/* <div className="overview-section-wrapper py-2 min-h-[450px] lg:flex lg:space-x-2 flex-1 lg:gap-8"> */}
<div className="overview-section-wrapper py-2 min-h-[400px] lg:grid grid-cols-2 gap-4">
<div className="mb-10 lg:mb-0 h-full w-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<img
src={activeAidsBanner}
alt="banner"
className="w-full h-full"
/>
</div>
<div className="overview-countdown h-full w-full flex flex-col justify-between p-4 rounded-2xl bg-white dark:bg-dark-white">
{<ParentWaitingTable />}
{/* <div className="lg:mb-0 mb-3">*/}
{/* <h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
{/* Lock and Lob x Fiesta Spurs*/}
{/* </h1>*/}
{/* <span className="text-[18px] font-thin tracking-wide text-dark-gray dark:text-white">*/}
{/* ID : 2320382*/}
{/*</span>*/}
{/* </div>*/}
{/* /!* user *!/*/}
{/* <div className="flex items-center space-x-3 lg:mb-0 mb-3">*/}
{/* <div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">*/}
{/* <img src={HeroUser} alt="" />*/}
{/* </div>*/}
{/* <div>*/}
{/* <p className="text-xl tracking-wide font-bold antise text-dark-gray dark:text-white">*/}
{/* Brokln Simons*/}
{/* </p>*/}
{/* <p className="text-sm tracking-wide text-dark-gray dark:text-white">*/}
{/* @broklinslam_75*/}
{/* </p>*/}
{/* </div>*/}
{/* </div>*/}
</div>
</div>
</div>
</>
);
}
@@ -0,0 +1,145 @@
import React, { useState, useEffect } from "react";
import transaction1 from "../../assets/images/recent-transation-1.png";
import transaction2 from "../../assets/images/recent-transation-2.png";
import transaction3 from "../../assets/images/recent-transation-3.png";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import usersService from "../../services/UsersService";
export default function ParentWaitingTable() {
// const transationFilterData = [
// {
// id: 1,
// name: "all",
// uniqueId: Math.random(),
// },
// {
// id: 2,
// name: "send",
// uniqueId: Math.random(),
// },
// {
// id: 3,
// name: "recent",
// uniqueId: Math.random(),
// },
// ];
// const [filterActive, setValue] = useState(transationFilterData[0].id);
// const filterHander = (value) => {
// setValue(value);
// };
const apiCall = new usersService()
let [familySuggestList, setFamilySuggestList] = useState({loading: true, data:[]})
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentList = familySuggestList?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
useEffect(()=>{
apiCall.getFamilySuggestList().then(res => {
setFamilySuggestList({loading: false, data:res.data?.result_list})
}).catch(err => {
setFamilySuggestList({loading: false, data:[]})
console.log('ERROR==>Familysuggestlist', err)
})
},[])
return (
<div className="rounded-2xl bg-white dark:bg-dark-white flex flex-col justify-between">
{/* heading */}
{/* <div className="heading sm:flex justify-between items-center">
<div>
<ul className="flex space-x-5 items-center">
{transationFilterData.map((value) => (
<li
onClick={() => filterHander(value.id)}
key={value.uniqueId}
className={`text-base text-thin-light-gray hover:text-purple border-b dark:border-[#5356fb29] border-transparent hover:border-purple uppercase ${
filterActive === value.id ? "border-purple text-purple" : ""
}`}
>
{value.name}
</li>
))}
</ul>
</div>
</div> */}
{/* content */}
<div className="content min-h-[400px]">
{familySuggestList.loading ?
<div className="h-full flex justify-center items-center">
<LoadingSpinner size='16' color='sky-blue' />
</div>
:
familySuggestList && familySuggestList.length != 0?
<ul>
{currentList.map((item)=>{
// Image
let Image = require(`../../assets/images/family/${
item.banner || "default.jpg"
}`);
return (
<li key={item.uid} className="content-item py-2 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple">
<div className="w-full flex justify-between items-center">
<div className="account-name flex space-x-4 items-center">
<div className="icon w-14 h-14 flex justify-center items-center">
<img src={Image} alt="" className="w-full h-full" />
</div>
<div className="">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{item.title}
</p>
<p className="text-sm text-thin-light-gray font-medium">
{item.description}
</p>
</div>
</div>
<div className="px-2 self-end">
<p className="text-sm font-bold text-dark-gray dark:text-white">
{new Date(item.added).toLocaleString().split(',')[0]}
</p>
<p className="text-xs py-1.5 w-[50px] tracking-wide rounded-full bg-gold text-white flex justify-center items-center">{item.status_text}</p>
</div>
</div>
</li>
)
})}
</ul>
:
<p className="w-full flex items-center justify-center text-xl text-dark-gray dark:text-white">No List Found!</p>
}
</div>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familySuggestList?.data?.length
? true
: false
}
data={familySuggestList?.data}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
);
}
+48 -22
View File
@@ -5,10 +5,12 @@ import { handlePagingFunc } from "../Pagination/HandlePagination";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { useNavigate, useLocation } from "react-router-dom";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import localImgLoad from "../../lib/localImgLoad";
const noTasksBg = require("../../assets/images/no-task-background.jpg");
const noFamilyTasksBg = require("../../assets/images/family-no-task-background.jpg");
export default function MyJobTable({ className, ActiveJobList }) {
export default function MyJobTable({ className, ActiveJobList, Account }) {
let navigate = useNavigate();
let { pathname } = useLocation();
@@ -25,14 +27,17 @@ export default function MyJobTable({ className, ActiveJobList }) {
handlePagingFunc(e, setCurrentPage);
};
let accountType = Account?.account_type == "FULL"
// To navigate to task
const [btnLoader, setBtnLoader] = useState(false);
const navigateMarket = () => {
setBtnLoader(true);
setTimeout(() => {
navigate("/market", { replace: true });
const timeoutId = setTimeout(() => {
navigate(accountType ? "/market" : "/familymarket", { replace: true });
setBtnLoader(false);
}, 2500);
return () => clearTimeout(timeoutId);
};
return (
@@ -42,12 +47,12 @@ export default function MyJobTable({ className, ActiveJobList }) {
} bg-cover bg-center`}
style={{
backgroundImage: !ActiveJobList?.data.length
? `url('${noTasksBg}')`
? `url('${accountType ? noTasksBg : noFamilyTasksBg}')`
: "none",
}}
>
{/* Adding this dark overlay in order to see the texts properly */}
{!ActiveJobList?.data.length && (
{!ActiveJobList?.data.length && accountType && (
<div class="absolute inset-0 bg-black opacity-30"></div>
)}
{ActiveJobList?.data.length > 0 && ActiveJobList.loading && (
@@ -60,6 +65,8 @@ export default function MyJobTable({ className, ActiveJobList }) {
<div className="h-auto w-full">
{ActiveJobList?.data?.length > 0 &&
currentTask?.map((task, idx) => {
// find due date
const dueDate = task?.delivery_date.split(" ")[0];
let thePrice = PriceFormatter(
task?.price * 0.01,
task?.currency_code,
@@ -74,7 +81,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
<div className="flex space-x-2 items-center">
<div className="w-full min-w-[60px] max-w-[60px] flex-[0.1] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage1}
src={localImgLoad(`images/taskbanners/${task?.banner}`)}
alt="data"
className="w-full h-full"
/>
@@ -101,9 +108,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
</span>
<span className="text-sm text-thin-light-gray">
Due Date:
<span className="text-purple ml-1">
{task?.delivery_date}
</span>
<span className="text-purple ml-1">{dueDate}</span>
</span>
<span className="text-sm text-thin-light-gray">
Confirmation:
@@ -134,20 +139,41 @@ export default function MyJobTable({ className, ActiveJobList }) {
})}
{ActiveJobList?.data?.length <= 0 && (
<div className="flex flex-col items-center justify-center gap-9 my-5">
<div className="p-2 font-bold text-3xl text-white whitespace-nowrap">
You currently have "0" task
</div>
<button
className="w-[115px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={navigateMarket}
<div
className={`flex flex-col ${
accountType ? "items-center" : "items-end"
} justify-center gap-9 my-5`}
>
<div
className={`p-2 font-bold text-3xl ${
accountType ? "text-white" : "text-sky-blue"
} whitespace-nowrap`}
>
{btnLoader ? (
<div className="signup btn-loader"></div>
) : (
"Find Task"
)}
</button>
You currently have {accountType ? '"0"' : "no"} task
</div>
<div
className={
!accountType &&
"bg-[#f0f8ff] h-[17rem] p-5 rounded-md -translate-x-20"
}
>
<button
className={`${
!accountType
? "w-[150px] h-20 bg-[#22b14c] text-lg font-semibold rounded-md py-2 px-4"
: "w-[115px] h-11 btn-gradient rounded-full"
} flex justify-center items-center text-base text-white`}
onClick={navigateMarket}
>
{btnLoader ? (
<div className="signup btn-loader"></div>
) : accountType ? (
"Find Task"
) : (
"Suggest tasks to your parent"
)}
</button>
</div>
</div>
)}
{ActiveJobList?.internal_return < 0 && (
@@ -0,0 +1,134 @@
import { useRef, useState } from "react";
import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom";
import OfferJobPopout from "../jobPopout/OfferJobPopout";
import FamilyOfferCard from "../Cards/FamilyOfferCard";
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
const settings = {
arrows: false,
slidesToShow: 3,
slidesToScroll: 3,
infinite: familyOffers?.length > 3,
responsive: [
{
breakpoint: 1025,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: familyOffers?.length > 3,
},
},
{
breakpoint: 769,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
infinite: familyOffers?.length > 2,
},
},
{
breakpoint: 619,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
infinite: familyOffers?.length > 1,
},
},
],
};
console.log("YES WE SEE OFFERS", familyOffers);
const trendingSlider = useRef(null);
const prevHandler = () => {
trendingSlider.current.slickPrev();
};
const nextHandler = () => {
trendingSlider.current.slickNext();
};
if (!familyOffers || familyOffers?.result_list?.length == 0) {
return ""; // want blank or no appear when no items
}
return (
<>
<div className={`top-seller-top-buyer-wrapper ${className || ""}`}>
<div className={`trending-section w-full px-2 sm:px-0 ${className || ""}`}>
{/* heading */}
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Ready to Start?</h1>
</div>
<div className="slider-btns flex space-x-3">
<button onClick={nextHandler} type="button">
<div className="trending-slider-left-btn relative text-white w-10 h-10 flex justify-center items-center rounded-full overflow-hidden">
<svg
width="11"
height="19"
viewBox="0 0 11 19"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.09766 1.1499L1.13307 9.11449L9.09766 17.0791"
stroke="url(#paint0_linear_220_23410)"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<defs>
<linearGradient
id="paint0_linear_220_23410"
x1="9.09766"
y1="1.1499"
x2="-4.2474"
y2="7.96749"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F539F8" />
<stop offset="0.416763" stopColor="#C342F9" />
<stop offset="1" stopColor="#5356FB" />
</linearGradient>
</defs>
</svg>
</div>
</button>
<button onClick={prevHandler} type="button">
<div className="trending-slider-right-btn primary-gradient text-white w-10 h-10 relative flex justify-center items-center rounded-full ">
<Icons name="arrows" />
</div>
</button>
</div>
</div>
{/* trending products */}
<div className="trending-products slider-left relative w-full rounded-2xl p-[10px] bg-alice-blue">
<SliderCom selector={trendingSlider} settings={settings}>
{familyOffers &&
familyOffers.length > 0 &&
familyOffers.map((item) => {
return (
<FamilyOfferCard key={item.id} datas={item} setOfferPopout={setOfferPopout} />
)
})}
</SliderCom>
</div>
</div>
{/* Offer Job Popout */}
{offerPopout.show && (
<OfferJobPopout
details={offerPopout.data}
onClose={() => {
setOfferPopout({ show: false, data: {} });
}}
situation={offerPopout.show}
/>
)}
{/* End of Offer Job Popout */}
</div>
</>
);
}
+4 -1
View File
@@ -143,7 +143,10 @@ export default function MyOffersTable({ className, MyActiveOffersList }) {
<button
type="button"
onClick={() => {
setOfferPopout({ show: true, data: value });
setOfferPopout({
show: true,
data: {...value, thePrice },
});
}}
className="w-20 h-11 self-center btn-gradient text-base rounded-full text-white"
>
+32 -6
View File
@@ -1,28 +1,43 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import MyJobTable from "./MyJobTable";
import CommonHead from "../UserHeader/CommonHead";
import TopSellerTopBuyerSliderSection from "../Home/TopSellerTopBuyerSliderSection";
// import TopSellerTopBuyerSliderSection from "../Home/TopSellerTopBuyerSliderSection";
import MyOffersTable from "./MyOffersTable";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
export default function MyTasks({
MyActiveOffersList,
ActiveJobList,
commonHeadData,
}) {
const { userDetails } = useSelector(
(state) => state?.userDetails
);
const navigate = useNavigate()
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
let accountType = userDetails?.account_type == "FULL"
console.log("Active something >>", MyActiveOffersList)
return (
<Layout>
<CommonHead commonHeadData={commonHeadData} />
{userDetails?.account_type == 'FULL' &&
<CommonHead commonHeadData={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">
<div className="w-full mb-5 sm:mb-0 flex justify-between items-center gap-1">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
@@ -30,6 +45,17 @@ export default function MyTasks({
My Tasks
</span>
</h1>
{ActiveJobList?.data?.length > 0 && userDetails.account_type == 'FAMILY' &&
<button
type="button"
onClick={() => {
navigate("/familymarket");
}}
className="px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
More Task
</button>
}
</div>
<div className="slider-btns flex space-x-4">
<div
@@ -38,14 +64,14 @@ export default function MyTasks({
></div>
</div>
</div>
{MyActiveOffersList &&
{MyActiveOffersList && accountType &&
MyActiveOffersList?.result_list?.length >= 0 && (
<MyOffersTable
MyActiveOffersList={MyActiveOffersList}
className="mb-10"
/>
)}
<MyJobTable ActiveJobList={ActiveJobList} />
<MyJobTable ActiveJobList={ActiveJobList} Account={userDetails} />
</div>
</div>
</Layout>
@@ -0,0 +1,152 @@
import { useState } from "react";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
export default function MyWaitingJobTable({ MyJobList, className }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentActiveJobList = MyJobList?.result_list?.slice(
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
{MyJobList && MyJobList?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{MyJobList &&
MyJobList?.result_list &&
MyJobList.result_list.length > 0 ? (
currentActiveJobList.map((value, index) => {
// let deliveryDate = value?.expire?.split(" ")[0];
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
return (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] max-w-[60px]">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "}
<span className="text-purple">
{thePrice}
</span>
</span>
<div className="flex items-center gap-4">
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value?.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire:{" "}
<span className="text-purple">
{" "}
{value?.expire}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Sent :{" "}
<span className="text-purple">
{" "}
{value?.sent}
</span>
</span>
</div>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={() => {
setJobPopout({ show: true, data: value });
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Pending Task!</td>
</tr>
)}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
MyJobList?.result_list.length
? true
: false
}
data={MyJobList?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
)}
{/* Active Job Popout */}
{jobPopout.show && (
<MarketPopUp
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
situation={jobPopout.show}
/>
)}
{/* End of Active Job Popout */}
</div>
);
}
+43
View File
@@ -0,0 +1,43 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import MyWaitingJobTable from "./MyWaitingJobTable";
export default function MyWaitingJobs(props) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
console.log("AMEYE LOC1", props.MyJobList);
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"}`}
>
Waiting Job(s)
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div>
<MyWaitingJobTable MyJobList={props.MyJobList} />
</div>
</div>
</Layout>
);
}
+1 -1
View File
@@ -14,7 +14,7 @@ export default function WalletHeader(props) {
let navigate = useNavigate();
return (
<>
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-purple pr-1.5 pl-4">
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
<div
onClick={() => props.handlerBalance()}
className="flex items-center lg:justify-between justify-center w-full h-full"
@@ -4,8 +4,6 @@ import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import usersService from "../../services/UsersService";
// import { handlePagingFunc } from "../Pagination/HandlePagination";
// import PaginatedList from "../Pagination/PaginatedList";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import OthersInterestedTable from "./OthersInterestedTable";
@@ -23,15 +21,7 @@ export default function ManageInterestOffer(props) {
let [messageListReload, setMessageListReload] = useState(false) // STATE TO DETERMINE WHEN MESSAGE LIST WILL RELOAD
const [messageList, setMessageList] = useState({loading: true, data: [1,2,3,4,5,6,7,8,95,6,7,8,9]}) // TO BE REMOVED AND REPLACE WITH REAL MESSAGE FROM API CALL
// const [currentPage, setCurrentPage] = useState(0);
// const indexOfFirstItem = Number(currentPage);
// const indexOfLastItem = Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
// const currentMessageList = messageList?.data?.slice(indexOfFirstItem, indexOfLastItem);
// const handlePagination = (e) => {
// handlePagingFunc(e, setCurrentPage);
// };
const [messageList, setMessageList] = useState({loading: true, data: []}) // TO BE REMOVED AND REPLACE WITH REAL MESSAGE FROM API CALL
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
@@ -112,14 +102,17 @@ export default function ManageInterestOffer(props) {
})
}
useEffect(()=>{
// run API to get message to replace message array above, add reload variable as dependence array. CODE IS DUMMY FOR NOW
setMessageList({loading: true, data: []})
apiCall.offerInterestMsg().then(res=>{
console.log('Data', res.data)
setMessageList({loading: false, data:[1,2,3,6,7,8,9]})
useEffect(()=>{ //API to get Offer Interest message list
let reqData = { // API PAYLOADS
msg_type: 'MRKTINT',
offer_uid: props.offerDetails?.offer_uid,
interest_uid: props.offerDetails?.interest_uid
}
setMessageList(prev => ({...prev, loading: true}))
apiCall.offerInterestListMsg(reqData).then(res=>{
setMessageList({loading: false, data:res?.data?.result_list})
}).catch(err => {
setMessageList({loading: false, data:[1,2,3,6,7,8,9]})
setMessageList(prev => ({...prev, loading: false}))
console.log('Failed', err)
})
},[messageListReload])
@@ -288,36 +281,14 @@ export default function ManageInterestOffer(props) {
<div className="my-1 min-h-[100px] max-h-[200px] border-t overflow-y-scroll">
{ messageList.loading ?
<LoadingSpinner color='sky-blue' size='16' />
: messageList.data.map((item, index)=>(
: messageList?.data?.map((item, index)=>(
<div key={index} className="my-2 w-full flex items-center gap-1">
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">2023-04-06-from { }<span className="font-normal">Dummy name</span></p>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">I am testing message</p>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">{item.added.split(' ')[0]}-from { }<span className="font-normal">{item.sender || 'Dummy name'}</span></p>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">{item.msg}</p>
</div>
))
}
{/* {messageList.data.map((item, index)=>(
<div key={index} className="my-2 w-full flex items-center gap-1">
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">2023-04-06-from { }<span className="font-normal">Dummy name</span></p>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">I am testing message</p>
</div>
))} */}
</div>
{/* PAGINATION BUTTON */}
{/* <PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
messageList?.data?.length
? true
: false
}
data={messageList?.data}
start={indexOfFirstItem}
stop={indexOfLastItem}
/> */}
{/* END OF PAGINATION BUTTON */}
</div>
}
</div>
@@ -388,6 +359,7 @@ export default function ManageInterestOffer(props) {
{/* END OF manage offer section */}
</div>
{props.othersInterestedList?.data?.length ?
<div className="w-full overflow-x-auto">
{/* heading */}
<div className="sm:flex justify-between items-center mb-3">
@@ -399,6 +371,9 @@ export default function ManageInterestOffer(props) {
</div>
<OthersInterestedTable othersInterestedList={props.othersInterestedList} />
</div>
:
null
}
</div>
</Layout>
);
@@ -107,19 +107,7 @@ export default function OffersInterestTable({offerInterestList, className}) {
:
(
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<div className="p-2 w-full md:w-1/2">
<p className="mb-4 p-3 md:p-16">No Offer list avaliable.</p>
<button
onClick={()=>{navigate('/market', {replace: true})}}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Goto Market
</button>
</div>
<div className="p-2 w-full md:w-1/2">
<img className='w-full' src={familyImage && familyImage} alt="Add Family" />
</div>
<p className="mb-4 p-3">No list avaliable.</p>
</div>
)
}
+4
View File
@@ -0,0 +1,4 @@
import { handlePagingFunc } from "./HandlePagination";
import PaginatedList from "./PaginatedList";
export { handlePagingFunc, PaginatedList };
+1 -1
View File
@@ -487,7 +487,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
</div>
<div className="lg:block hidden">
<h1 className="text-xl font-bold text-dark-gray dark:text-white">
{`${firstname} ${lastname}`}
{firstname}
</h1>
{userDetails && userDetails?.account_type !== "FAMILY" && <p className="text-sm text-thin-light-gray">@{userEmail}</p>}
</div>
+3 -5
View File
@@ -1,7 +1,6 @@
import React, {useEffect, useState} from "react";
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import useToggle from "../../hooks/useToggle";
import { drawerToggle } from "../../store/drawer";
import ModalCom from "../Helpers/ModalCom";
@@ -11,10 +10,9 @@ import RightSideBar from "./RightSideBar";
import Sidebar from "./Sidebar";
import usersService from "../../services/UsersService";
export default function Layout({ children }) {
const { drawer } = useSelector((state) => state.drawer);
const {userJobList} = useSelector((state) => state.userJobList)
const { userJobList } = useSelector((state) => state.userJobList);
const dispatch = useDispatch();
const [MobileSideBar, setMobileSidebar] = useToggle(false);
const [logoutModal, setLogoutModal] = useState(false);
@@ -197,4 +195,4 @@ export default function Layout({ children }) {
)}
</>
);
}
}
+9 -9
View File
@@ -78,7 +78,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
{/* menus item */}
<div className="menu-item transition-all duration-300 ease-in-out mb-5">
<div className="heading mb-5 active">
<h1 className="title text-xl font-bold text-purple">Menu</h1>
<h1 className="title text-xl font-bold text-sky-blue">Menu</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
@@ -116,7 +116,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
<h1 className="title text-xl font-bold text-sky-blue">
Family
</h1>
</div>
@@ -137,12 +137,12 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
<>
{!userDetails?.post_jobs ? (
<div
className={`menu-item transition-all duration-300 ease-in-out bg-pink dark:bg-dark-white rounded-2xl p-3 ${
className={`menu-item transition-all duration-300 ease-in-out bg-[#f0f8ff] dark:bg-dark-white rounded-2xl p-3 ${
sidebar ? "mb-5" : "mb-2 rounded-none p-0"
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
<h1 className="title text-xl font-bold text-sky-blue">
Job Post
</h1>
</div>
@@ -162,7 +162,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
className={`item-content group-hover:text-sky-blue text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
@@ -180,7 +180,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
<h1 className="title text-xl font-bold text-sky-blue">
My Jobs
</h1>
</div>
@@ -217,7 +217,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
<h1 className="title text-xl font-bold text-sky-blue">
My Jobs
</h1>
</div>
@@ -242,7 +242,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
<button
onClick={logoutModalHandler}
type="button"
className="signout-btn flex items-center space-x-1 p-2.5 w-2/3 h-[52px] bg-purple transition duration-300 ease-in-out hover:bg-gray-900 rounded-full"
className="signout-btn flex items-center space-x-1 p-2.5 w-2/3 h-[52px] bg-sky-blue transition duration-300 ease-in-out hover:bg-gray-900 rounded-full"
>
<span>
<svg
@@ -317,7 +317,7 @@ const ListItem = ({ sidebar, route, title, bubble, popup }) => {
<Icons name="market" />
</span>
<span
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
className={`item-content relative group-hover:text-sky-blue text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
+10 -9
View File
@@ -104,7 +104,7 @@ export default function Sidebar({
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">Menu</h1>
<h1 className="title text-xl font-bold text-sky-blue">Menu</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
@@ -124,6 +124,7 @@ export default function Sidebar({
iconName="market"
/>
)}
<ListItem
title="My Task(s)"
route="/mytask"
@@ -142,7 +143,7 @@ export default function Sidebar({
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">Family</h1>
<h1 className="title text-xl font-bold text-sky-blue">Family</h1>
</div>
<div className="items">
<ul className="flex flex-col space-y-6">
@@ -160,12 +161,12 @@ export default function Sidebar({
<>
{!userDetails?.post_jobs ? (
<div
className={`menu-item transition-all duration-300 ease-in-out bg-pink dark:bg-dark-white rounded-2xl p-3 ${
className={`menu-item transition-all duration-300 ease-in-out bg-[#f0f8ff] dark:bg-dark-white rounded-2xl p-3 ${
sidebar ? "mb-5" : "mb-2 rounded-none p-0"
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
<h1 className="title text-xl font-bold text-sky-blue">
Job Post
</h1>
</div>
@@ -185,7 +186,7 @@ export default function Sidebar({
<Icons name="people-two" />
</span>
<span
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
className={`item-content group-hover:text-sky-blue text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
@@ -203,7 +204,7 @@ export default function Sidebar({
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
<h1 className="title text-xl font-bold text-sky-blue">
My Jobs
</h1>
</div>
@@ -244,7 +245,7 @@ export default function Sidebar({
}`}
>
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
<h1 className="title text-xl font-bold text-sky-blue">
My Jobs
</h1>
</div>
@@ -269,7 +270,7 @@ export default function Sidebar({
<button
onClick={logoutModalHandler}
type="button"
className="signout-btn flex items-center space-x-1 p-2.5 w-2/3 h-[52px] bg-purple transition duration-300 ease-in-out hover:bg-gray-900 rounded-full"
className="signout-btn flex items-center space-x-1 p-2.5 w-2/3 h-[52px] bg-sky-blue transition duration-300 ease-in-out hover:bg-gray-900 rounded-full"
>
<span>
<svg
@@ -344,7 +345,7 @@ const ListItem = ({ sidebar, route, title, bubble, iconName, popup }) => {
<Icons name={iconName} />
</span>
<span
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
className={`item-content relative group-hover:text-sky-blue text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${
sidebar ? "active flex-1" : "w-0"
}`}
>
+134 -118
View File
@@ -1,140 +1,156 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import authProfilePic from "../../assets/images/auth-profile-picture.png";
import profileBanner from "../../assets/images/profile-cover.png";
import collections from "../../data/collectionplan_data.json";
import marketPlace from "../../data/marketplace_data.json";
// import authProfilePic from "../../assets/images/auth-profile-picture.png";
// import profileBanner from "../../assets/images/profile-cover.png";
// import collections from "../../data/collectionplan_data.json"; Should this be cleaned off?
// import marketPlace from "../../data/marketplace_data.json";
import LoadingSpinner from "../../components/Spinners/LoadingSpinner";
import products from "../../data/product_data.json";
import Layout from "../Partials/Layout";
import ActivitiesTab from "./ActivitiesTab";
import CollectionTab from "./CollectionTab";
import CreatedTab from "./CreatedTab";
import HiddenProductsTab from "./HiddenProductsTab";
import OnSaleTab from "./OnSaleTab";
import OwnTab from "./OwnTab";
import {
ActivitiesTab, BlogTab,
CollectionTab,
CreatedTab,
HiddenProductsTab,
OnSaleTab,
OwnTab,
} from "./tabs";
export default function Resources() {
const onSaleProducts = marketPlace.data;
const CreatedSell = marketPlace.data;
const CreatedBits = products.datas;
// const mainProducts = products.datas;
export default function Resources(props) {
// console.log("RESOURCES=>", props);
const ownProducts = products.datas;
const collectionProducts = collections.data;
// Resource Props
const __resources = props.MyResourceData;
//debugger;
// Collection Items
const CreatedSell = __resources?.marketdata?.data;
const tab_categories = __resources?.tab_categories?.data;
const collectionProducts = __resources?.collectiondata?.data;
const onSaleProducts = __resources?.marketdata?.data;
const CreatedBits = __resources?.productdata?.datas;
const blogItems = __resources?.blogdata?.payload;
const tabs = [
{
id: 1,
name: "onsale",
content: "On Sale",
},
{
id: 2,
name: "owned",
content: "Owned",
},
{
id: 3,
name: "created",
content: "Created",
},
{
id: 4,
name: "hidden",
content: "Hidden",
},
{
id: 5,
name: "collection",
content: "Collection",
},
{
id: 6,
name: "activity",
content: "Activity",
},
];
const [tab, setTab] = useState(tab_categories ? tab_categories[0]?.name : "");
const [tab, setTab] = useState(tabs[0].name);
const tabHandler = (value) => {
setTab(value);
};
// Category Components
const tabComponents = {
blog: <BlogTab blogdata={blogItems} />,
onsale: <OnSaleTab products={onSaleProducts} />,
owned: <OwnTab products={ownProducts} />,
created: (
<CreatedTab marketProducts={CreatedSell} mainProducts={CreatedBits} />
),
hidden: (
<HiddenProductsTab
marketProducts={CreatedSell}
mainProducts={CreatedBits}
/>
),
collection: <CollectionTab products={collectionProducts} />,
activity: <ActivitiesTab />,
};
const defaultTabComponent = <BlogTab blogdata={blogItems} />;
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
// Tab Item Component
const TabItem = ({ tabValue, isActive }) => {
let countNumber = (name) => { // FUNCTION TO DETERMINE THE COUNT NUMBER
if(name == 'blog'){
return blogItems?.blogdata?.length
}else if(name == 'onsale'){
return onSaleProducts?.length
}else if(name == 'owned'){
return ownProducts?.length
}else if(name == 'created'){
return CreatedSell?.length + CreatedBits?.length
}else{
return 0
}
}
return (
<li
className={`relative group inline`}
onClick={() => tabHandler(tabValue.name)}
>
<span
className={`py-4 sm:border-b-none border-b group-hover:border-purple border-transparent lg:text-xl text-sm tracking-wide font-bold group-hover:text-purple text-dark-gray dark:text-white relative z-10 cursor-pointer ${
isActive
? "text-purple border-purple"
: "text-dark-gray dark:text-white border-transparent"
}`}
>
{tabValue.content}
</span>
<span
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
isActive
? "text-white bg-pink"
: "text-thin-light-gray bg-[#F2B8FD]"
}`}
>
{/* 16 blog, onsale, owned,created */}
{countNumber(tabValue.name)}
</span>
</li>
);
};
// Tab List Component
const TabList = ({ tabCategories }) => {
return (
<ul className="lg:flex lg:space-x-14 space-x-8">
{tabCategories?.length > 0 &&
tabCategories?.map((tabValue, idx) => (
<TabItem
key={tabValue.id}
tabValue={tabValue}
isActive={tab === tabValue.name || (idx === 0 && tab === "")}
/>
))}
</ul>
);
};
return (
<>
<Layout>
<div className="nft-authprofile-wrapper w-full">
<div className="main-wrapper w-full">
<div className="content-wrapper-profile-only w-full mb-6">
<div className="auth-tab-content relative mb-10">
<div className="lg:flex justify-between">
<div className="tab-items">
<ul className="lg:flex lg:space-x-14 space-x-8">
{tabs &&
tabs.length > 0 &&
tabs.map((tabValue) => (
<li
key={tabValue.id}
className="relative group inline"
onClick={() => tabHandler(tabValue.name)}
>
<span
className={`py-4 sm:border-b-none border-b group-hover:border-purple border-transparent lg:text-xl text-sm tracking-wide font-bold group-hover:text-purple text-dark-gray dark:text-white relative z-10 cursor-pointer ${
tab === tabValue.name
? "text-purple border-purple "
: "text-dark-gray dark:text-white border-transparent "
}`}
>
{tabValue.content}
</span>
<span
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
tab === tabValue.name
? "text-white bg-pink"
: "text-thin-light-gray bg-[#F2B8FD]"
}`}
>
16
</span>
</li>
))}
</ul>
</div>
<div style={{ transform: "translateY(-22px)" }}>
<Link
to="/upload-product"
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
>
Upload Product
</Link>
{__resources.length == 0 || Object.keys(__resources).length == 0 ? (
<div className="w-full h-full flex items-center justify-center">
<LoadingSpinner size={16} color="sky-blue" />
</div>
) : (
<div className="main-wrapper w-full">
<div className="content-wrapper-profile-only w-full mb-6">
<div className="auth-tab-content relative mb-10">
<div className="lg:flex justify-between">
<div className="tab-items">
<TabList tabCategories={tab_categories} />
</div>
<div style={{ transform: "translateY(-22px)" }}>
<Link
to="/upload-product"
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
>
Add My Item
</Link>
</div>
</div>
<div className="hidden lg:block w-full h-[1px] bg-[#DCD5FE] dark:bg-[#5356fb29] absolute top-[42px] left-0"></div>
</div>
<div className="hidden lg:block w-full h-[1px] bg-[#DCD5FE] dark:bg-[#5356fb29] absolute top-[42px] left-0"></div>
</div>
<div className="tab-cotainer w-full mb-10">
{selectedTabComponent}
</div>
</div>
<div className="tab-cotainer w-full mb-10">
{tab === "onsale" ? (
<OnSaleTab products={onSaleProducts} />
) : tab === "owned" ? (
<OwnTab products={ownProducts} />
) : tab === "created" ? (
<CreatedTab
marketProducts={CreatedSell}
mainProducts={CreatedBits}
/>
) : tab === "hidden" ? (
<HiddenProductsTab
marketProducts={CreatedSell}
mainProducts={CreatedBits}
/>
) : tab === "collection" ? (
<CollectionTab products={collectionProducts} />
) : tab === "activity" ? (
<ActivitiesTab />
) : (
""
)}
</div>
</div>
)}
</div>
</Layout>
</>

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