Compare commits

..

1 Commits

Author SHA1 Message Date
victorAnumudu 52358ce421 Button Centralized 2023-05-16 17:48:28 +01:00
202 changed files with 5933 additions and 14534 deletions
+5 -21
View File
@@ -9,16 +9,15 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
# REACT_APP_AUX_ENDPOINT="http://10.20.30.32:9083/svs/user"
# REACT_APP_USERS_ENDPOINT="http://10.20.30.32:9083/svs/user"
#REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
#REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=600000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
@@ -35,20 +34,5 @@ REACT_APP_ITEM_PER_PAGE=5
# Empty Listings
REACT_APP_ZERO_STATE=0
#REACT_APP_GOOGLE_CLIENT_ID_RET=234407841224-k5g7f67p908hqtegiokmjqt8qqf3hi2i.apps.googleusercontent.com
REACT_APP_GOOGLE_CLIENT_ID=817021856543-ad9nsjgdpsu2s2jrl63j3ihrv7lbf6ma.apps.googleusercontent.com
REACT_APP_GOOGLE_CLIENT_SECRET=aozK_2G8UjaCmLgPPkv9abIm
REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_FACEBOOK_CLIENT_ID=390204307987009
REACT_APP_FACEBOOK_CLIENT_SECRET=19f778e312f2ab96d147bacb612910c2
REACT_APP_FACEBOOK_CLIENT_SCOPE="email, public_profile"
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
+5 -14
View File
@@ -9,16 +9,15 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
# REACT_APP_AUX_ENDPOINT="http://10.20.30.32:9083/svs/user"
# REACT_APP_USERS_ENDPOINT="http://10.20.30.32:9083/svs/user"
# REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
# REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=600000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
@@ -34,11 +33,3 @@ REACT_APP_ITEM_PER_PAGE=5
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
REACT_APP_GOOGLE_CLIENT_ID=817021856543-ad9nsjgdpsu2s2jrl63j3ihrv7lbf6ma.apps.googleusercontent.com
REACT_APP_GOOGLE_CLIENT_SECRET=aozK_2G8UjaCmLgPPkv9abIm
REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
+5 -16
View File
@@ -9,16 +9,15 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
# REACT_APP_AUX_ENDPOINT="http://10.20.30.32:9083/svs/user"
# REACT_APP_USERS_ENDPOINT="http://10.20.30.32:9083/svs/user"
#REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/svs/user"
#REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/svs/user"
REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=600000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
@@ -34,13 +33,3 @@ REACT_APP_ITEM_PER_PAGE=5
#apigate.orion.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
REACT_APP_GOOGLE_CLIENT_ID=817021856543-ad9nsjgdpsu2s2jrl63j3ihrv7lbf6ma.apps.googleusercontent.com
REACT_APP_GOOGLE_CLIENT_SECRET=aozK_2G8UjaCmLgPPkv9abIm
REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
REACT_APP_GOOGLE_REDIRECT_URL=https://users.wrenchboard.com/login/auth/
DISABLE_ESLINT_PLUGIN=true
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
+6 -8
View File
@@ -14,19 +14,17 @@
"chartjs": "^0.3.24",
"cors": "^2.8.5",
"faker": "^6.6.6",
"flutterwave-react-v3": "^1.3.0",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-chartjs-2": "^4.1.0",
"react-countup": "^6.2.0",
"react-dom": "^18.2.0",
"react-qr-code": "^2.0.11",
"react-redux": "^8.0.5",
"react-router-dom": "^6.0.2",
"react-scripts": "5.0.1",
"react-slick": "^0.29.0",
"react-to-print": "^2.14.12",
"react-toastify": "^9.0.1",
"flutterwave-react-v3": "^1.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-scripts": "5.0.1",
"redux": "^4.2.0",
"slick-carousel": "^1.8.1",
"web-vitals": "^1.0.1",
@@ -56,4 +54,4 @@
"last 1 safari version"
]
}
}
}
+1 -23
View File
@@ -37,16 +37,6 @@ import StartJob from "./components/MyJobs/StartJob";
import AddJobPage from "./views/AddJobPage";
import MyPendingJobsPage from "./views/MyPendingJobsPage";
import ManageActiveJobs from "./views/ManageActiveJobs";
import FamilyManagePage from "./views/FamilyManagePage";
import MyCouponPage from "./views/MyCouponPage";
import AuthRedirect from "./views/AuthRedirect";
import MyPastDueJobsPage from "./views/MyPastDueJobsPage";
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 (
@@ -55,7 +45,6 @@ export default function Routers() {
{/* guest routes */}
<Route exact path="/login" element={<LoginPage />} />
<Route exact path="/signup" element={<SignupPage />} />
<Route exact path="/login/auth" element={<AuthRedirect />} />
<Route
exact
path="/forgot-password"
@@ -84,29 +73,18 @@ export default function Routers() {
<Route exact path="/calendar" element={<CalendarPage />} />
<Route exact path="/resources" element={<ResourcePage />} />
<Route exact path="/my-wallet/*" element={<MyWalletPage />} />
<Route exact path="/my-coupon" element={<MyCouponPage />} />
<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 />} />
{/* <Route exact path="/add-job" element={<AddJobPage />} /> */}
<Route exact path="/add-job" element={<AddJobPage />} />
<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 />} />
<Route exact path="/start-job" element={<StartJob />} />
<Route exact path="/manage-active-job" element={<ManageActiveJobs />} />
<Route exact path="/blog-page" element={<BlogPage />} />
<Route exact path="/offer-interest" element={<OffersInterestPage />} />
<Route exact path="/manage-offer" element={<ManageInterestOfferPage />} />
<Route
exact
path="/my-collection/collection-item"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

-9
View File
@@ -1,9 +0,0 @@
<svg width="905" height="575" viewBox="0 0 905 575" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="905" height="575" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlink:href="#image0_201_3" transform="matrix(0.00849979 0 0 0.0131639 -0.0662984 -0.354783)"/>
</pattern>
<image id="image0_201_3" width="130" height="130" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAACCCAMAAAC93eDPAAAApVBMVEX///82OzgAAAAuMi81OjdVXVfqpQCzs7NCSUSwsbAaIBslKyjk5OQuNDAhJiLZ2tpJT0opNTkvNzloVy31rAC1hRtPV1HNzc34+PgaLztBQUHLkg9UVFTw8PDGxsaioqKampp/f39sbGyIiIgaGho9Qj5MTExeXl5fUi+9vb03Nzd2dnYjIyORkZFjZWMNFQ9CQTWYcyLAjBSsfx12XytSSjEQEBBeBsYmAAAEiklEQVR4nO3a7XaqOBQG4BjoQXRraKc1GUoSPgQaETszZ473f2kTqm0VsKLLYs80b3+UhQgPOwlBESETExMTExMTExMTExMTk/9HQDk9xHUdcgiwmk7HPWQ0Gj0HrQiaWvagh9iWztSiTQH3rD4AW4I19nmDUI77EWwJ1ihpENJeWuGdYE0afXHSN2EMdUI/fXGHMK0Piv6rcJhg39VyadpRwt3g6Y+9PNl3/RLsvx7va3kcXLYOxwh/Ptz/qOX+79t+CY91wY8fD4ZgCIbwvQn/NAT3P/sl3P3bENz/uuwkcXSaun162M/PX5ctQofJ+u62lgtPlL/HLYshGIIhfDGC3chZ65ur7c6EYSN2+/r0wPYvn4/ttH19B4Lt3TRSGexZc316YP3LgZrrZ9sqTK5PsK7fEMcJn90d7eOEz84XIEyuT7CuTrCvT5hcn2BdnWBfnbAj+CaEtyvizrXROpfQOu0fAwyGnucN9X89XeiltPrebnIuwU5nO+n2dbmdbqfH1B6+Le02w4mEvYnX60J4PW61/fukb51PGO4SulWheRehMecTTu8LbTc+NzMvPZ9wctrupW505+yR0NYOelR41yVUgq5VaLnjOvmy0GyIStC5L6RH0okwbBN4g06ExpubFe00JPbKMNsIOl4XWofT6YTB4HU/3mDWLjjpc8RevE4APSF4VSFmQ31VTl8AqdWZcInuuEFUHWczLdgDuw7o637BnjSP/AHh8o9KPwR8fhXslsrXCfUHxpd8bH7k9LdpPDZHyajL+y6XUdQggD/uUzAeNNoBIWpN+xNMJy0/JNF1mD2Pespz0FKDDcJxe4k6BDAxMTExMTH5kunjZ8cfB+Gr53sTluE7YQ0gBSGrBEgEROIcCA0oVnEEkFfbCp44ZUYDAhLjiGAKCiugmASlXAGMa/teEBCLHCCSYZmEofBlqUIcACQ44r4PoJbVZnOk3ghzFPlMujyEbIViH8es4C6LSAKuAP16gaqlAlwomY9DVrCElSjhCVfSAYe6NYLPSq6oCFmohFIhl64kLqYkZEuFogzlqMSZEPo2nr4TijVLQk1YBihYa0IGigMNeZRF+vUcFTiGkiqxTpa45BIWUjIfQs4dh8KiXmGfBZQSqc9EACExsBcCuDHyKXd8hLmu9GY8wvKVADHnKJZIBIis8AoByTnoc4k2Z6hPeYlUKIRUfkXgcxxpQskBqTlhywYh3xB8DkRvByysCE6McghptiGwjYG+EgLMSigkwQHS5xTzAGdQIk2QVUP4q5BlnOVC5PqVqgq+cF+qkCCV64odICCMqEBLvadwW4UYCcj3quC/E1BElS5wjlaLqiFwwHUPAf2ho1jhGCUso2jh8IgFVV9ACSpRxBO2Ig4oShuEgju6ZJrgKraEgEmilrovaHKk/wKUbPsCmb+OCJphEReioDTRG+JAl9tXa7mKiZLSxWtJEpyo+ZwKx8eFwEoPG71XLLKo9Cmtd4aFomrp616gB1Xhrp0sSiQlmSBx4uLqKHK+GRHibUR8mCQ4tsW5mUrcjfD5+QKE/wC0yMO17JCUyAAAAABJRU5ErkJggg=="/>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

-2
View File
@@ -1,2 +0,0 @@
<?xml version="1.0" ?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 52 52" data-name="Layer 1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"><path d="M14,16H2a2,2,0,0,1-2-2V2A2,2,0,0,1,2,0H14a2,2,0,0,1,2,2V14A2,2,0,0,1,14,16ZM4,12h8V4H4Z"/><path d="M14,34H2a2,2,0,0,1-2-2V20a2,2,0,0,1,2-2H14a2,2,0,0,1,2,2V32A2,2,0,0,1,14,34ZM4,30h8V22H4Z"/><path d="M14,52H2a2,2,0,0,1-2-2V38a2,2,0,0,1,2-2H14a2,2,0,0,1,2,2V50A2,2,0,0,1,14,52ZM4,48h8V40H4Z"/><path d="M32,16H20a2,2,0,0,1-2-2V2a2,2,0,0,1,2-2H32a2,2,0,0,1,2,2V14A2,2,0,0,1,32,16ZM22,12h8V4H22Z"/><path d="M32,34H20a2,2,0,0,1-2-2V20a2,2,0,0,1,2-2H32a2,2,0,0,1,2,2V32A2,2,0,0,1,32,34ZM22,30h8V22H22Z"/><path d="M32,52H20a2,2,0,0,1-2-2V38a2,2,0,0,1,2-2H32a2,2,0,0,1,2,2V50A2,2,0,0,1,32,52ZM22,48h8V40H22Z"/><path d="M50,16H38a2,2,0,0,1-2-2V2a2,2,0,0,1,2-2H50a2,2,0,0,1,2,2V14A2,2,0,0,1,50,16ZM40,12h8V4H40Z"/><path d="M50,34H38a2,2,0,0,1-2-2V20a2,2,0,0,1,2-2H50a2,2,0,0,1,2,2V32A2,2,0,0,1,50,34ZM40,30h8V22H40Z"/><path d="M50,52H38a2,2,0,0,1-2-2V38a2,2,0,0,1,2-2H50a2,2,0,0,1,2,2V50A2,2,0,0,1,50,52ZM40,48h8V40H40Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-1
View File
@@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 841 B

-19
View File
@@ -1,19 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.6 KiB

+341 -420
View File
@@ -1,430 +1,351 @@
import { Field, Form, Formik } from "formik";
import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import React, {useState, useEffect} from 'react'
import { Link, useNavigate } from 'react-router-dom';
import InputCom from '../Helpers/Inputs/InputCom';
import LoadingSpinner from '../Spinners/LoadingSpinner';
import usersService from '../../services/UsersService';
import { Form, Formik } from "formik";
import * as Yup from "yup";
import usersService from "../../services/UsersService";
import { tableReload } from "../../store/TableReloads";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
const validationSchema = Yup.object().shape({
country: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Country is required"),
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(5, "Minimum 5 characters")
.max(149, "Maximum 149 characters")
.required("Title is required"),
description: Yup.string()
.min(5, "Minimum 5 characters")
.max(299, "Maximum 299 characters")
.required("Description is required"),
job_detail: Yup.string()
.min(3, "Minimum 3 characters")
.max(1440, "Maximum 1440 characters")
.required("Details is required"),
timeline_days: Yup.number()
country: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("Country is required"),
price: Yup.number()
.typeError("you must specify a number")
.min(1, "Price must be greater than 0")
.required("Price is required"),
title: Yup.string()
.min(3, "Minimum 3 characters")
.max(100, "Maximum 25 characters")
.required("Title is required"),
description: Yup.string()
.min(3, "Minimum 3 characters")
.max(250, "Maximum 250 characters")
.required("Description is required"),
job_detail: Yup.string()
.min(3, "Minimum 3 characters")
.max(250, "Maximum 250 characters")
.required("Details is required"),
timeline_days: Yup.number()
.typeError("you must specify a number")
.min(1, "Price must be greater than 0")
.required("Timeline is required"),
category: Yup.array().min(1, "Select at least one checkbox"),
});
.required("Price is required"),
});
function AddJob({ popUpHandler, categories }) {
const ApiCall = new usersService();
let dispatch = useDispatch();
let [currency, setCurrency] = useState({
loading: true,
status: false,
data: null,
}); // To Hold the array of currency getUserCurrency returns
let initialValues = {
// initial values for formik
country: "",
price: "",
title: "",
description: "",
job_detail: "",
timeline_days: "",
category: [],
};
let [requestStatus, setRequestStatus] = useState({
loading: false,
status: false,
message: "",
}); // Holds state when submit button is pressed
// FUNCTION TO GET Currency
const getUserCurrency = () => {
setCurrency((prev) => ({ ...prev, loading: true }));
ApiCall.getUserWallets()
.then((res) => {
if (res.data.internal_return < 0) {
setCurrency({ loading: false, status: true, data: [] });
return;
}
console.log("Res for currency >> ", res);
setCurrency({
loading: false,
status: true,
data: res.data.result_list,
});
})
.catch((err) => {
setCurrency({ loading: false, status: false, data: [] });
});
};
// FUNCTION TO HANDLE ADD JOB FORM
const handleAddJob = (values, helpers) => {
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(reqData)
.then((res) => {
if (res.data.internal_return < 1) {
setRequestStatus({
loading: false,
status: false,
message: "Could not complete your request at the moment",
});
setTimeout(() => {
popUpHandler();
}, 1500);
return;
}
setRequestStatus({
loading: false,
status: true,
message: "Job Added Successfully",
});
setTimeout(() => {
dispatch(tableReload({ type: "JOBTABLE" }));
popUpHandler();
}, 1000);
})
.catch((err) => {
setRequestStatus({
loading: false,
status: false,
message: "Opps! something went wrong. Try Again",
});
})
.finally(() => {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
useEffect(() => {
getUserCurrency();
}, []);
return (
<div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleAddJob}
>
{(props) => {
return (
<Form>
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
{/* inputs starts here */}
<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 flex item-center gap-1"
>
Currency
{props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>}
</label>
<select
id="country"
name="country"
value={props.values.country}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{currency.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : currency.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select a currency
</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="">
No Options Found! Try Again
</option>
)}
</select>
</div>
{/* Price */}
<div className="field w-full">
<InputCom
fieldClass="px-6 text-right"
label="Price"
labelClass="tracking-wide"
inputBg="bg-slate-100"
type="number"
name="price"
placeholder="0"
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.price && props.touched.price && props.errors.price}
/>
</div>
</div>
{/* Title */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6"
label="Title"
labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.title && props.touched.title && props.errors.title}
/>
</div>
{/* Description */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6"
label="Description"
labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={props.errors.description && props.touched.description && props.errors.description}
/>
</div>
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<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 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-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}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
</div>
<div className="sm:w-[35%] w-full">
<div
htmlFor="Job Categories"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
id="checked-group"
>
Categories
</div>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{Object?.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
</div>
</div>
</div>
<div className="field w-full mb-[5px]">
<div className={`flex items-center justify-between mb-2.5`}>
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
htmlFor="timeline_days"
>
Timeline
<span className="text-green-700 text-sm tracking-wide">
- Expected duration of this task
</span>
</label>
</div>
<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 ${
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>
{publicArray.map(({ name, duration }, idx) => (
<option
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
</div>
{/* inputs ends here */}
</div>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
<div className="w-full h-[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="text-18 text-light-red tracking-wide "
>
<span
className="border-b dark:border-[#5356fb29] border-light-red"
onClick={popUpHandler}
>
{" "}
Cancel
</span>
</button>
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
// className='w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'
>
Add Job
</button>
)}
</div>
</div>
</div>
</Form>
);
}}
</Formik>
</div>
);
let initialValues = { // initial values for formik
country: '',
price: 0,
title: '',
description: '',
job_detail: '',
timeline_days: ''
}
export default AddJob;
function AddJob() {
const ApiCall = new usersService()
const navigate = useNavigate()
const publicArray = [
{ duration: 1, name: "1 day" },
{ duration: 2, name: "2 days" },
{ duration: 3, name: "3 days" },
{ duration: 4, name: "4 days" },
{ duration: 5, name: "5 days" },
{ duration: 6, name: "6 days" },
{ duration: 7, name: "1 week" },
{ duration: 14, name: "2 weeks" },
{ duration: 21, name: "3 weeks" },
{ duration: 28, name: "4 weeks" },
];
let [pageLoading, setPageLoading] = useState(true) // State used for knowing when the page is mounting
// .test("no-e", "Invalid number", (value) => {
// if (value && /\d+e/.test(value)) {
// return false;
// }
// return true;
// })
let [country, setCountry] = useState({loading: false, status: false, data:[]}) // To Hold the array of country getUserCountry returns
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message:''}) // Holds state when submit button is pressed
// FUNCTION TO GET COUNTRY
const getUserCountry = () =>{
setCountry(prev => ({...prev, loading:true}))
ApiCall.getSignupCountryData().then(res => {
if(res.data.internal_return < 1){
setCountry({loading: false, status: true, data:[]})
return
}
setCountry({loading: false, status: true, data:res.data.signup_country})
}).catch(err => {
setCountry({loading: false, status: false, data:[]})
})
}
// FUNCTION TO HANDLE ADD JOB FORM
const handleAddJob = (values, helpers) => {
setRequestStatus({loading: true, status: false, message:''})
ApiCall.jobManagerCreateJob(values).then(res => {
if(res.data.internal_return < 1){
setRequestStatus({loading: false, status: false, message:'Could not complete your request at the moment'})
return
}
setRequestStatus({loading: false, status: true, message:'Job Added Successfully'})
setTimeout(()=>{
navigate('/myjobs', {replace: true})
},1000)
}).catch(err => {
setRequestStatus({loading: false, status: false, message:'Opps! soemthing went wrong. Try Again'})
}).finally(()=>{
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message:''})
}, 5000)
})
}
useEffect(()=>{
setPageLoading(false)
getUserCountry()
},[])
return pageLoading.loading ? (
<div className="personal-info-tab w-full flex flex-col justify-between">
<div className="p-3">
<LoadingSpinner size="32" color="sky-blue" />
</div>
</div>
) : (
<div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleAddJob}
>
{(props) => {
return (
<Form>
<h1 className='py-2 my-4 text-lg md:text-xl font-bold tracking-wide'>Create New Job</h1>
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
{/* inputs starts here */}
{/* country */}
<div className="xl:flex xl:space-x-7 mb-6">
<div className="field w-full mb-6 xl:mb-0">
{/* <InputCom
fieldClass="px-6"
label="Country"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="country"
// placeholder="Select Country"
value={props.values.country}
inputHandler={props.handleChange}
/> */}
<label
htmlFor='country'
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block">
Country
</label>
<select
id='country'
name='country'
value={props.values.country}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{country.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : country.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select...
</option>
{country.data.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item[0]}
>
{item[1]}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
{props.errors.country && props.touched.country && (
<p className="text-sm text-red-500">
{props.errors.country}
</p>
)}
</div>
{/* Price */}
<div className="field w-full">
<InputCom
fieldClass="px-6"
label="Price"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="number"
name="price"
fieldClass='text-right'
// placeholder="Please Enter Amount"
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.price && props.touched.price && (
<p className="text-sm text-red-500">
{props.errors.price}
</p>
)}
</div>
</div>
{/* Title */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Title"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="title"
// placeholder="Enter Job Title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.title && props.touched.title && (
<p className="text-sm text-red-500">
{props.errors.title}
</p>
)}
</div>
{/* Description */}
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Description"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="description"
// placeholder="Enter a description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.description && props.touched.description && (
<p className="text-sm text-red-500">
{props.errors.description}
</p>
)}
</div>
{/* Details */}
<div className="field w-full mb-6">
{/* <InputCom
fieldClass="px-6"
label="Job Delivery Details"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="details"
// placeholder="Please Enter Detail Description of Job"
value={props.values.details}
inputHandler={props.handleChange}
/> */}
<label
htmlFor="Job Delivery Details"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'>
Job Delivery Details
</label>
<textarea name="details" id="Job Delivery Details" rows="7"
className={`input-field p-6 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
style={{resize:'none'}}
name='job_detail'
value={props.values.job_detail}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
{props.errors.job_detail && props.touched.job_detail && (
<p className="text-sm text-red-500">
{props.errors.job_detail}
</p>
)}
</div>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Timeline"
labelClass='tracking-wide'
inputBg = 'bg-slate-100'
type="text"
name="timeline_days"
spanTag = ' - Expected duration of this task'
// placeholder="Please Enter Detail Description of Job"
value={props.values.timeline_days}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.timeline_days && props.touched.timeline_days && (
<p className="text-sm text-red-500">
{props.errors.timeline_days}
</p>
)}
</div>
{/* inputs ends here */}
</div>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full">
{/* error or success display */}
{requestStatus.message != "" && (
!requestStatus.status ?
(<div className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{requestStatus.message}
</div>)
:
requestStatus.status &&
(<div className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
{requestStatus.message}
</div>
)
)}
{/* End of error or success display */}
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-9">
<Link
to="/myjobs"
className="text-18 text-light-red tracking-wide "
>
<span className="border-b dark:border-[#5356fb29] border-light-red">
{" "}
Cancel
</span>
</Link>
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
// className='w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'
>
Add Job
</button>
)}
</div>
</div>
</div>
</Form>
);
}}
</Formik>
</div>
)
}
export default AddJob
+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:px-20 sm:py-5`}>
<div className={`main-wrapper login-wrapper w-full h-screen overflow-y-auto sm:p-20 p-10`}>
<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 px-10 pt-10">
<div className="flex-1 flex justify-center items-center p-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 px-10 py-1">
<div className="flex-1 flex justify-center items-center p-10">
<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,9 +42,7 @@ 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">
@@ -91,7 +89,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,9 +49,7 @@ 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">
@@ -98,7 +96,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} />
@@ -1,23 +0,0 @@
import React, {useState, useEffect} from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
function Redirect() {
const location = useLocation();
const navigate = useNavigate();
const queryParams = new URLSearchParams(location?.search);
const codeResponse = queryParams.get("code");
useEffect(()=>{
if(!codeResponse){
navigate('/login', {replace: true})
return
}
console.log(codeResponse)
},[])
return (
<div>Redirecting ... </div>
)
}
export default Redirect
+133 -337
View File
@@ -1,6 +1,5 @@
import React, { useEffect, useLayoutEffect, useState } from "react";
import React, { 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";
import facebookLogo from "../../../assets/images/facebook-4.svg";
import googleLogo from "../../../assets/images/google-logo.svg";
@@ -8,8 +7,8 @@ import WrenchBoard from "../../../assets/images/wrenchboard.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
// import { GoogleOAuthProvider } from '@react-oauth/google';
import { googleLogout, useGoogleLogin } from "@react-oauth/google";
//import { GoogleOAuthProvider } from '@react-oauth/google';
// import { googleLogout, useGoogleLogin } from '@react-oauth/google';
import { useDispatch } from "react-redux";
import { updateUserDetails } from "../../../store/UserDetails";
@@ -17,8 +16,6 @@ import { updateUserDetails } from "../../../store/UserDetails";
export default function Login() {
const dispatch = useDispatch();
let [loginType, setLoginType] = useState('');
const [checked, setValue] = useState(false);
const [loginLoading, setLoginLoading] = useState(false);
@@ -31,16 +28,6 @@ export default function Login() {
setValue(!checked);
};
//FUNCTION TO DETERMINE/CHANGE LOGIN COMPONENT
const handleLoginType = ({ target: { name } }) => {
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
const [email, setMail] = useState("");
const handleEmail = (e) => {
@@ -54,133 +41,56 @@ export default function Login() {
const navigate = useNavigate();
const userApi = new usersService();
// FUNCTION TO HANDLE USER LOGIN
const doLogin = ({ target: { name } }) => {
setMsgError("");
setLoginError(false);
setLoginLoading(true);
let postData; // Post Data for API
if (!email || !password) {
setLoginLoading(false);
setMsgError("Please fill all the fields");
setTimeout(() => {
setMsgError("");
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
return;
}
if (name == "full") {
// Post Data Info for normal Login
postData = {
username: email,
password: password,
sessionid: "STARTING",
login_mode: 1100,
action: 11025,
};
} else if (name == "family") {
// Post Data Info for family Login
postData = {
username: email,
pin: password,
sessionid: "20067A92714",
login_mode: 1105,
action: 11025,
};
} else {
setLoginLoading(false);
setMsgError("Invalid Login Type. Consider refreshing the page");
setTimeout(() => {
setMsgError("");
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
return;
}
userApi
.logInUser(postData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
// setMsgError("Wrong, email/password");
const doLogin = async () => {
try {
if (email !== "" && password !== "") {
var postData = {
username: email,
password: password,
sessionid: "STARTING",
};
const loginResult = await userApi.logInUser(postData); // just for a test
//debugger;
// if (email === "support@mermsemr.com") {
if (
loginResult.data.status > 0 &&
loginResult.data.internal_return == 100 &&
loginResult.data.session != ""
) {
// just for a start
localStorage.setItem("member_id", `${loginResult.data.member_id}`);
localStorage.setItem("uid", `${loginResult.data.uid}`);
localStorage.setItem("session_token", `${loginResult.data.session}`);
localStorage.setItem("session", `${loginResult.data.session}`);
setLoginLoading(true);
// userApi.getUserReminders(); //testing
dispatch(updateUserDetails(loginResult.data));
setTimeout(() => {
navigate("/", { replace: true });
setLoginLoading(false);
}, 2000);
} else {
// toast.error("Invalid Credential");
setLoginError(true);
setLoginLoading(false);
return;
}
localStorage.setItem("member_id", `${res.data.member_id}`);
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
// localStorage.setItem("session", `${res.data.session}`);
dispatch(updateUserDetails(res.data));
setTimeout(() => {
navigate("/", { replace: true });
setLoginLoading(false);
}, 2000);
})
.catch((error) => {
setMsgError("Unable to login, try again");
setLoginLoading(false);
})
.finally(() => {
setTimeout(() => {
setLoginError(false);
setMsgError("");
setLoginLoading(false);
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
});
};
const googleLogin = useGoogleLogin({
flow: "auth-code",
ux_mode: "redirect",
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
onSuccess: async (codeResponse) => {
console.log("GOOGLE LOGIN GOOD --- ", codeResponse);
},
onError: (errorResponse) => console.log(errorResponse),
});
// In order to update the selected login type whenever the component renders
// useEffect(() => {
// Clear the loginType cookie if the user switches to loginfull
// document.cookie ="loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// }, []);
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);
}
} else {
setMsgError("Please fill in the fields");
}
return 'full'
} catch (error) {
setMsgError("An error occurred");
} finally {
setTimeout(() => {
setLoginError(false);
setMsgError(null);
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
}
let loginValue = readCookie('loginType')
setLoginType(loginValue)
},[loginType])
useEffect(() => {
setMail("");
setPassword("");
}, [loginType]);
};
return (
<>
<AuthLayout slogan="Welcome to WrenchBoard">
<div className="w-full">
<div className="mb-5">
<div className="mb-12">
<Link to="#">
<img
src={WrenchBoard}
@@ -192,9 +102,9 @@ export default function Login() {
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
<div className="w-full">
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
{/* <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
Sign In to WrenchBoard
</h1> */}
</h1>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
New Here?{" "}
<Link
@@ -205,195 +115,80 @@ export default function Login() {
</Link>
</span>
</div>
<div className="input-area">
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
label="Email"
name="email"
type="email"
iconName="message"
/>
</div>
{/* switch login component */}
<div className="flex justify-start items-end">
<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]"
}`}
onClick={handleLoginType}
>
Sign in
</button>
<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]"
}`}
onClick={handleLoginType}
>
Family
</button>
</div>
{/* END of switch login component */}
{/* for login component */}
{
loginType == 'full' ? (
//user login component
<div className="p-2 input-area border-2 border-[#4687ba]">
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
value={email}
inputHandler={handleEmail}
placeholder="Your Email"
label="Email"
name="email"
type="email"
iconName="message"
/>
</div>
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type="password"
iconName="password"
forgotPassword
/>
</div>
{loginError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
Invalid username or password- Please{" "}
<Link to="/#" className="text-[#009ef7]">
reset your password
</Link>{" "}
or{" "}
<Link to="/signup" className="text-[#009ef7]">
create a new account
</Link>
</div>
)}
{msgError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
{msgError}
</div>
)}
<div className="signin-area mb-3.5">
<div className="flex justify-center">
<button
name="full"
onClick={doLogin}
type="button"
disabled={loginLoading}
className={`btn-login rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
>
{loginLoading ? (
<div className="signup btn-loader"></div>
) : (
<>Continue</>
)}
</button>
</div>
<div className="sm:flex sm:justify-between sm:items-center sm:space-x-2">
<BrandBtn
link="#"
imgSrc={googleLogo}
brand="Google"
onClick={googleLogin}
/>
<BrandBtn link="#" imgSrc={appleLogo} brand="Apple" />
</div>
<div className="sm:flex sm:justify-between sm:items-center sm:space-x-2">
<BrandBtn
link="#"
imgSrc={facebookLogo}
brand="Facebook"
/>
<BrandBtn
link="#"
imgSrc={linkedInLogo}
brand="LinkedIn"
/>
</div>
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type="password"
iconName="password"
forgotPassword
/>
</div>
{loginError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
Invalid username or password- Please{" "}
<Link to="/#" className="text-[#009ef7]">
reset your password
</Link>{" "}
or{" "}
<Link to="/signup" className="text-[#009ef7]">
create a new account
</Link>
</div>
) : (
// END of user login compoenent
// family login compoenent
<div className="p-2 input-area border-2 border-[#4687ba]">
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
fieldClass="px-6"
value={email}
inputHandler={handleEmail}
placeholder="Account ID"
label="Username"
name="email"
type="email"
iconName="message"
/>
</div>
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
fieldClass="px-6"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Pin"
name="password"
type="password"
iconName="password"
// forgotPassword
/>
</div>
{loginError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
Invalid username or password{" "}
{/* <Link to="/#" className="text-[#009ef7]">
reset your password
</Link>{" "}
or{" "}
<Link to="/signup" className="text-[#009ef7]">
create a new account
</Link> */}
</div>
)}
{msgError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
{msgError}
</div>
)}
<div className="signin-area mb-1.5">
<div className="flex justify-center">
<button
name="family"
onClick={doLogin}
disabled={loginLoading}
type="button"
className={`btn-login rounded-[0.475rem] text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
>
{loginLoading ? (
<div className="signup btn-loader"></div>
) : (
<>Continue</>
)}
</button>
</div>
</div>
)}
{msgError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
{msgError}
</div>
)
// END of family login compoenent
}
{/* END of login component */}
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by hCaptcha and the our Privacy Policy
and Terms of Service apply.
)}
<div className="signin-area mb-3.5">
<div className="flex justify-center">
<button
onClick={doLogin}
type="button"
className={`btn-login rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
>
{loginLoading ? (
<div className="signup btn-loader"></div>
) : (
<span>Continue</span>
)}
</button>
</div>
<BrandBtn link="#" imgSrc={googleLogo} brand="Google" />
<BrandBtn link="#" imgSrc={facebookLogo} brand="Facebook" />
<BrandBtn link="#" imgSrc={appleLogo} brand="Apple" />
</div>
{/* <div className="signup-area flex justify-center">
<p className="sm:text-lg text-sm text-thin-light-gray font-normal">
Don't have an account ?
<a href="/signup" className="ml-2 text-dark-gray dark:text-white">
Sign up free
</a>
</p>
</div> */}
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by hCaptcha and the our Privacy Policy
and Terms of Service apply.
</div>
</div>
</div>
</div>
@@ -403,10 +198,11 @@ export default function Login() {
);
}
const BrandBtn = ({ link, imgSrc, brand, onClick }) => {
// const doGoogle = async () => {
// alert("start google");
// };
const BrandBtn = ({ link, imgSrc, brand }) => {
const doGoogle = async ()=>{
alert('start google');
}
// onSuccess: (codeResponse) => setUser(codeResponse),
@@ -415,26 +211,26 @@ const BrandBtn = ({ link, imgSrc, brand, onClick }) => {
// onError: (error) => console.log('Login Failed:', error)
// });
// const doApple = async () => {
// alert("start apple");
// };
const doApple = async ()=>{
alert('start apple');
}
// const doFacebook = async () => {
// alert("start facebook");
// };
const doFacebook = async ()=>{
alert('start facebook');
}
return (
<div className="w-full sm:w-1/2 flex justify-center bottomMargin">
<button
onClick={onClick}
// href="#dd"
<div className="flex justify-center bottomMargin">
<a
// onClick={doGoogle}
href="#dd"
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
>
<img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
<span className="text-lg text-thin-light-gray font-normal text-[15px]">
Continue with {brand}
</span>
</button>
</a>
</div>
);
};
+3 -3
View File
@@ -80,7 +80,7 @@ export default function SignUp() {
if (res.status === 200) {
const { data } = res;
if (data && data.acc === "DULPICATE") {
if (data.status === -1 && 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 login-wrapper w-full xl:h-screen h-full xl:py-10 py-12 overflow-y-auto">
<div className="main-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,9 +42,7 @@ 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">
@@ -91,7 +89,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,9 +49,7 @@ 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">
@@ -98,7 +96,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} />
-40
View File
@@ -1,40 +0,0 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
export default function BlogItem(props) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
return (
<Layout>
<CommonHead
commonHeadData={props.commonHeadData}
/>
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Title of this Blog Items
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
</div>
</div>
<div>
Blog Items Details
</div>
</div>
</div>
</Layout>
);
}
+97 -189
View File
@@ -1,210 +1,118 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
import usersService from "../../services/UsersService";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
import Icons from "../Helpers/Icons";
export default function AvailableJobsCard({
className,
datas,
hidden = false,
contentDisplay
}) {
//debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
const [imageUrl, setImageUrl] = useState("");
let thePrice = PriceFormatter(
datas?.price * 0.01,
datas?.currency_code,
datas?.currency
);
useEffect(() => {
const imagePath = require(`../../assets/images/${datas.thumbnil}`); // Replace with your directory path for local images
setImageUrl(imagePath);
}, []);
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 (
<>
{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">
<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-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="flex flex-col justify-between w-full h-full">
<Link to="/shop-details" className="mb-2.5">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.title}
</h1>
</Link>
<div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden 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 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">
{datas?.title}
</h1>
</Link>
<div 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="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div> */}
<div className="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1">
Price: <span className="text-purple">{thePrice}</span>
<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>
<p className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple italic">
{" "}
{datas?.timeline_days} day(s)
</span>
</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-sm text-thin-light-gray">
Code:{" "}
<span className="text-purple">
{" "}
{datas?.offer_code}
</span>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</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 });
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
style={{
background: `url(${localImgLoad(
`images/${datas.thumbnil}`
)}) 0% 0% / cover no-repeat`,
}}
>
View
</button>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{datas.price * 0.01}
{datas.currency} | {datas.timeline_days} day(s)
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code})
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
>
View
</button>
</div>
</div>
</div>
</div>
}
{marketPopUp.show && (
<MarketPopUp
details={datas}
onClose={() => {
setMarketPopUp({ show: false, data: {} });
}}
situation={marketPopUp.show}
/>
)}
</>
</div>
);
}
-78
View File
@@ -1,78 +0,0 @@
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 }}
/>
)}
</>
);
}
+22 -40
View File
@@ -1,44 +1,26 @@
import React, { useEffect, useState } from "react";
import React from "react";
import { Link } from "react-router-dom";
import localImgLoad from "../../lib/localImgLoad";
export default function HomeBannerOffersCard(props) {
const [imageUrl, setImageUrl] = useState("");
const link_result = "/" + props.itemData.link_path;
useEffect(() => {
let { banner, banner_location } = props?.itemData;
if (banner_location === "LOCAL") {
const imagePath = require(`../../assets/images/${banner}`); // Replace with your directory path for local images
setImageUrl(imagePath);
} else if (banner_location === "URL") setImageUrl(banner);
else return null;
}, []);
return (
<Link
to={link_result}
className="item w-full block group banner-630-340 bg-cover bg-center"
style={{
backgroundImage: `url('${imageUrl}')`,
}}
>
<div className="flex flex-col justify-between h-full">
<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="flex flex-col justify-around items-center flex-1">
<div className="siderCardDescription">
{props.itemData.description}
</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>
);
return (
<Link
to="/my-collection/collection-item"
className="item w-full block group banner-630-340"
>
<div className="flex flex-col justify-between h-full">
<div className="content flex justify-between items-center mb-5">
<div>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
<>Ab hshsh jsjsj hshdhhdjjd</>
</h1>
</div>
{/*<SelectBox datas={filterDatas} action={dataSetHandler} />*/}
</div>
<div className="h-[233px]">
BEST IMAGE IN THE WORLLD
</div>
</div>
</Link>
);
}
+1 -4
View File
@@ -1,4 +1,4 @@
import { useState } from "react";
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
@@ -6,7 +6,6 @@ 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 = () => {
@@ -18,8 +17,6 @@ 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
@@ -1,75 +0,0 @@
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>
);
}
-60
View File
@@ -1,60 +0,0 @@
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");
let [pageLoading, setPageLoading] = useState(true);
let location = useLocation();
let navigate = useNavigate();
let accountDetails = location?.state;
// tab handler
const filterHandler = (value) => {
setValue(value);
};
useEffect(() => {
if (!accountDetails) {
navigate("/acc-family", { replace: true });
} else {
setPageLoading(false);
}
}, []);
return (
<Layout>
{/*<CommonHead />*/}
{pageLoading ? (
<LoadingSpinner size={8} color="sky-blue" />
) : (
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Manage Family
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div>
<FamilyManageTabs accountDetails={accountDetails} />
</div>
</div>
)}
</Layout>
);
}
@@ -1,233 +0,0 @@
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,
} 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 },
});
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 },
});
const { family_uid } = accountDetails;
const reqData = { family_uid };
const [familyRes, tasksRes, familyWaitRes] = await Promise.all([
apiCall.ManageFamily(reqData),
apiCall.ManageTasks(reqData),
apiCall.ManageFamilyWaitlist(),
]);
const familyData = familyRes.data;
const tasksData = tasksRes.data;
const familyWaitData = familyWaitRes.data;
if (
familyData?.internal_return < 0 ||
tasksData?.internal_return < 0 ||
familyWaitData?.internal_return < 0
)
return;
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
});
} catch (error) {
setDetails({
familyDetails: { loading: false },
familyTasks: { loading: false },
familyWaitList: { 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: "Account" },
{ id: 4, 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}
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
@@ -1,95 +0,0 @@
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>
);
}
@@ -1,263 +0,0 @@
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
+72 -135
View File
@@ -1,161 +1,98 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { useNavigate, useLocation, Link } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import familyImage from '../../assets/images/no-family-side.png'
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
export default function FamilyTable({ className, familyList, loader }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
const navigate = useNavigate();
// let location = useLocation();
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentFamilyList = familyList?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
return (
<div
className={`update-table w-full h-full p-8 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] ${
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${
className || ""
}`}
>
<div className="relative w-full h-full overflow-x-auto sm:rounded-lg">
{loader ? (
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
)
:
familyList?.length > 0 ?
(
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<div className="relative w-full overflow-x-auto sm:rounded-lg">
{loader ? (
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size='16' color='sky-blue' />
</div>
) : (
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<>
<thead className="sticky top-0">
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
<th className="py-4">Name</th>
<th className="py-4 text-center">Last Login</th>
<th className="py-4 text-center">No of Tasks</th>
<th className="py-4 text-right"></th>
<th className="py-4 text-right">Status</th>
</tr>
</thead>
<tbody className="h-full">
{currentFamilyList?.map((props, idx) => {
let {
firstname,
lastname,
age,
added,
last_login,
task_count,
family_uid,
} = props;
let addedDate = added?.split(" ")[0];
let LoginDate = last_login?.split(" ")[0];
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={family_uid}
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] min-w-[60px]">
<img
src={dataImage1}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
{`${firstname} ${lastname} (${age})`}
</h1>
<span className="text-sm text-thin-light-gray">
Added:{" "}
<span className="text-purple ml-1">
{addedDate}
</span>
</span>
</div>
<tbody className="overflow-y-scroll h-auto">
<>
{familyList?.length > 0 ? (
familyList?.map(({ firstname, lastname, age }, idx) => (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={idx}
>
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage1}
alt="data"
className="w-full h-full"
/>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
{LoginDate}
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
{`${firstname} ${lastname} (${age})`}
</h1>
<span className="text-sm text-thin-light-gray">
Added{" "}
<span className="text-purple">10-10-2029</span>
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
{task_count}
</span>
</div>
</td>
<td className="text-right py-4 px-2 flex items-center justify-center">
<button
onClick={() => {
navigate("/manage-family", {
state: { ...props },
});
}}
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</button>
</td>
</tr>
);
})
}
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
10-10-2019
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
100
</span>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</button>
</td>
</tr>
))
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2" colSpan="4">
No Family Accounts Found!
</td>
</tr>
)}
</>
</tbody>
</table>
)
:
(
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<div className="p-2 w-full md:w-1/2">
<p className="mb-4 p-3 md:p-16">Add your family, assign tasks, and get the whole team engaged.</p>
<button
onClick={popUpHandler}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Add Family
</button>
</div>
<div className="p-2 w-full md:w-1/2">
<img className='w-full' src={familyImage} alt="Add Family" />
</div>
</div>
)
}
</>
</table>
)}
</div>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familyList?.length
? true
: false
}
data={familyList}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
);
}
@@ -1,56 +0,0 @@
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,3 +0,0 @@
export default function FamilyProfile() {
return <>Profile</>;
}
@@ -1,147 +0,0 @@
import React, { useState } from "react";
import dataImage2 from "../../../assets/images/data-table-user-2.png";
import { useNavigate, useLocation } from "react-router-dom";
import { handlePagingFunc } from "../../Pagination/HandlePagination";
import PaginatedList from "../../Pagination/PaginatedList";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import Icons from "../../Helpers/Icons";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import ModalCom from "../../Helpers/ModalCom";
import Detail from "../../jobPopout/popoutcomponent/Detail";
export default function FamilyTasks({ familyData, className, loader, accountDetails }) {
let navigate = useNavigate();
let { pathname } = useLocation();
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentTask = familyData?.result_list.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>
) : (
<>
{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">
<tbody>
{
<>
{familyData &&
familyData?.result_list &&
familyData.result_list.length > 0 &&
currentTask.map((value, index) => {
// find due date
const dueDate = value?.delivery_date.split(" ")[0];
// the price
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] min-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 className="flex gap-4 items-center">
<span className="text-sm text-thin-light-gray flex flex-start gap-1">
Price:{" "}
<span className="text-purple">
{thePrice}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Due Date:{" "}
<span className="text-purple">
{" "}
{dueDate}
</span>
</span>
</div>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={() => {
navigate("/manage-active-job", {
state: {
...value,
pathname,
accountDetails
}
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<Icons name="right-arrow" />
</button>
</td>
</tr>
);
})}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familyData?.result_list.length
? true
: false
}
data={familyData?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
)}
</>
)}
</div>
);
}
@@ -1,107 +0,0 @@
import { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { handlePagingFunc, PaginatedList } from "../../Pagination";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const FamilyWaitlist = ({ familyData, className, loader }) => {
const navigate = useNavigate();
const { pathname } = useLocation();
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = currentPage;
const indexOfLastItem = currentPage + itemsPerPage;
const currentTask = familyData?.result_list?.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>
) : (
<>
{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">
<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}
</p>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})}
</tbody>
</table>
<PaginatedList
onClick={handlePagination}
prev={currentPage === 0}
next={
currentPage + itemsPerPage >= familyData?.result_list.length
}
data={familyData?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
</div>
)}
</>
)}
</div>
);
};
export default FamilyWaitlist;
@@ -1,61 +0,0 @@
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>
);
}
-13
View File
@@ -1,13 +0,0 @@
import FamilyAccount from "./FamilyAccount";
import FamilyProfile from "./FamilyProfile";
import FamilyTasks from "./FamilyTasks";
import FamilyWaitlist from "./FamilyWaitlist";
import ProfileInfo from "./ProfileInfo";
export {
FamilyAccount,
FamilyProfile,
FamilyTasks,
FamilyWaitlist,
ProfileInfo,
};
+5 -7
View File
@@ -73,7 +73,6 @@ export default function FamilyAcc() {
if (data?.internal_return > 0 && data?.status == "OK") {
setLoader(false);
setListReload((prev) => !prev);
popUpHandler()
} else {
setLoader(false);
setMsgErr("Sorry, something went wrong");
@@ -94,7 +93,6 @@ export default function FamilyAcc() {
first_name: "",
last_name: "",
});
setSelectedAge("")
}
};
@@ -158,7 +156,7 @@ export default function FamilyAcc() {
></div>
</div>
</div>
<FamilyTable familyList={familyList} loader={loader} popUpHandler={popUpHandler} />
<FamilyTable familyList={familyList} loader={loader} />
</div>
</div>
{popUp && (
@@ -213,7 +211,7 @@ const FamilyForm = ({
type="text"
parentClass="flex items-center gap-1 w-full"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] input-curve lg border border-[#dce4e9]"
inputClass="flex-[0.8]"
fieldClass="px-2"
value={first_name}
inputHandler={inputHandler}
@@ -225,7 +223,7 @@ const FamilyForm = ({
type="text"
parentClass="flex items-center gap-1 w-full"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] input-curve lg border border-[#dce4e9]"
inputClass="flex-[0.8]"
fieldClass="px-2"
value={last_name}
inputHandler={inputHandler}
@@ -244,11 +242,11 @@ const FamilyForm = ({
<select
name="age-selection"
id="age-selection"
className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-[35px] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent px-4"
className="input-wrapper border border-[#f5f8fa]] dark:border-[#5e6278] w-full rounded-[0.475rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent px-2"
onChange={ageHandler}
value={ageValue}
>
<option value={""}>Select age</option>
<option value={""}>Select your age</option>
{ageRange?.length > 0 &&
ageRange?.map((age) => (
<option value={age} key={age}>
-176
View File
@@ -1,176 +0,0 @@
import React, { useMemo, useState } from "react";
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 [submitTask, setSubmitTask] = useState({
loading: false,
msg: "",
state: "",
});
// default image
const selectedImage = details?.selectedImage || DEFAULT_IMAGE;
const initialValues = {
title: details?.title || "",
description: details?.description || "",
};
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);
}
};
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">
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="px-6"
label="Title"
labelClass="tracking-wide"
inputBg="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 px-3 pt-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[130px] bg-slate-100 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>
<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;
+2 -2
View File
@@ -10,7 +10,7 @@ export default function Accordion({ datas }) {
<>
<div className="accordion-item overflow-hidden relative z-[1]">
<div
className="accordion-title-bar flex items-center space-x-3 py-5 border-b border-light-purple dark:border-[#5356fb29] cursor-pointer"
className="accordion-title-bar flex items-center space-x-3 py-5 border-b border-light-purple dark:border-[#5356fb29] "
onClick={accordionHandler}
>
<div className="accordion-title-icon relative">
@@ -36,7 +36,7 @@ export default function Accordion({ datas }) {
<div className="w-[3px] h-auto bg-purple rounded-[28px]"></div>
<div className="flex-1">
<p className="text-base text-thin-light-gray tracking-wide">
{datas.msg}
{datas.content}
</p>
</div>
</div>
+49 -54
View File
@@ -1,64 +1,59 @@
import { useEffect, useState } from "react";
/* eslint-disable no-underscore-dangle */
import React, { useEffect, useState } from "react";
function CountDown({ lastDate = "" }) {
// State to store the countdown values
const [countdownValues, setCountdownValues] = useState({
showHour: 0,
showMinute: 0,
showSecond: 0,
});
// 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) {
// 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);
if (lastDate !== "") {
startInterval();
}
}, [lastDate]);
// Destructure the countdown values from the state
const { showHour, showMinute, showSecond } = countdownValues;
});
return (
<span>
{showHour < 10 ? "0" + showHour : showHour} :{" "}
{showMinute < 10 ? "0" + showMinute : showMinute} :{" "}
{showSecond < 10 ? "0" + showSecond : showSecond}
{showHour} : {showMinute} : {showSecound}
</span>
);
}
+3 -2
View File
@@ -5,8 +5,9 @@ function DataIteration(props) {
return (
<>
{datas &&
datas?.length >= endLength &&
datas?.slice(startLength, endLength)
datas.length >= endLength &&
datas
.slice(startLength, endLength)
.map((value) => children({ datas: value }))}
</>
);
-25
View File
@@ -1,9 +1,5 @@
import React from "react";
import ATMCard from '../../assets/images/card.svg'
import VisaCard from '../../assets/images/visa.svg'
import MasterCard from '../../assets/images/master.svg'
export default function Icons({ name }) {
return (
<>
@@ -472,27 +468,6 @@ export default function Icons({ name }) {
>
<rect y="0.823242" width="20" height="2.35294" rx="1.17647" />
</svg>
) : name === "right-arrow" ? (
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
// enableBackground="new 0 0 24 24"
viewBox="0 0 24 24"
className="fill-black dark:fill-white"
id="right-arrow"
>
<path
d="M15.5,11.3L9.9,5.6c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l4.9,4.9l-4.9,4.9c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.6,0.4,1,1,1
c0.3,0,0.5-0.1,0.7-0.3l5.7-5.7c0,0,0,0,0,0C15.9,12.3,15.9,11.7,15.5,11.3z"
></path>
</svg>
) : name === "atm-card" ? (
<img className="w-[20px]" src={ATMCard} alt="card" />
) : name === "visa-card" ? (
<img className="w-[20px]" src={VisaCard} alt="card" />
) : name === "master-card" ? (
<img className="w-[20px]" src={MasterCard} alt="card" />
) : (
""
)}
@@ -1,6 +1,6 @@
import React, { useRef } from "react";
import { Link } from "react-router-dom";
import Icons from "../../Icons";
import { Link } from "react-router-dom";
export default function InputCom({
label,
@@ -21,8 +21,7 @@ export default function InputCom({
blurHandler,
spanTag,
inputBg,
direction,
error,
direction
}) {
const inputRef = useRef(null);
// Entry Validation
@@ -41,29 +40,22 @@ 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 flex items-center gap-1"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
htmlFor={name}
>
{label}
{spanTag && spanTag == "*" ? (
<span className="text-red-700 text-sm tracking-wide">
{" "}
{spanTag}
</span>
) : (
{spanTag && (
<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 && (
@@ -76,13 +68,13 @@ export default function InputCom({
)}
</div>
<div
className={`input-wrapper border 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 border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-[0.475rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`}
>
<input
placeholder={placeholder}
value={value}
onChange={inputHandler}
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide ${
className={`input-field placeholder:text-base text-dark-gray w-full h-full ${
inputBg ? inputBg : "bg-[#FAFAFA]"
} dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`}
type={type}
@@ -90,17 +82,15 @@ export default function InputCom({
name={name}
minLength={minLengthValidation()}
maxLength={maxLengthValidation()}
// pattern={inputPatterns()}
pattern={() => inputPatterns}
ref={inputRef}
readOnly={disable}
onBlur={blurHandler}
dir={direction}
/>
{iconName && (
<div className="absolute right-6 bottom-[10px] z-10 flex gap-2">
{iconName.split(" ").map((item, index) => (
<Icons key={index} name={item} />
))}
<div className="absolute right-6 bottom-[10px] z-10">
<Icons name={iconName} />
</div>
)}
{passIcon && (
@@ -117,7 +107,7 @@ export default function InputCom({
}
const inputConfigs = {
email: { minLength: 7, maxLength: 35 },
email: { minLength: 7, maxLength: 30 },
first_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
last_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
address: { minLength: 5, maxLength: 49, pattern: "[a-zA-Z0-9]+" },
@@ -126,9 +116,6 @@ 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
+2 -2
View File
@@ -1,6 +1,6 @@
import React, { useEffect } from "react";
export default function ModalCom({ action, children, situation, isOpen, className }) {
export default function ModalCom({ action, children, situation, isOpen }) {
useEffect(() => {
if (situation) {
document.body.style.overflowY = "hidden";
@@ -16,7 +16,7 @@ export default function ModalCom({ action, children, situation, isOpen, classNam
onClick={action || isOpen}
className="fixed top-0 left-0 w-full lg:h-[100vh] h-full bg-black bg-opacity-40 backdrop-filter backdrop-blur-sm z-50"
></div>
<div className={`children-element fixed lg:h-100vh h-full z-[99999999999999] w-full lg:w-auto ${className}`}>
<div className="children-element fixed lg:h-100vh h-full z-[99999999999999] w-full lg:w-auto ">
{children && children}
</div>
</div>
-51
View File
@@ -1,51 +0,0 @@
import React from "react";
// export const PriceFormatter = (price, currency, currencyName) => {
// const supportedCurrencies = ["USD", "EUR", "GBP"];
// const symbolFormatter = supportedCurrencies.includes(currency)
// ? currency
// : undefined;
// const formatter = new Intl.NumberFormat("en", {
// style: symbolFormatter,
// currencyDisplay: "symbol",
// minimumFractionDigits: 2,
// });
// const displayCurrencyName = symbolFormatter ? "" : currencyName;
// return `${formatter.format(price)} ${displayCurrencyName}`;
// };
export const PriceFormatter = (
price = "00",
currency = "",
currencyName = ""
) => {
// Convert the number to a string
let numStr = String(price);
// 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;
// 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;
// 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>
);
};
+3 -11
View File
@@ -1,13 +1,7 @@
import React, { useState } from "react";
import React from "react";
import Icons from "./Icons";
export default function SearchCom({
className,
inputClasses,
placeholder,
handleSearch,
value,
}) {
export default function SearchCom({ className, inputClasses }) {
return (
<div
className={`w-full h-[48px] pl-8 flex rounded-full overflow-hidden bg-white dark:bg-dark-white ${
@@ -23,9 +17,7 @@ export default function SearchCom({
inputClasses || ""
}`}
type="text"
onInput={handleSearch}
value={value}
placeholder={placeholder || "Search items, collections..."}
placeholder="Search items, collections..."
/>
</div>
</div>
+2 -2
View File
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import useToggle from "../../../hooks/useToggle";
function SelectBox({ datas = [], className, action, contentBodyClasses, position }) {
function SelectBox({ datas = [], className, action, contentBodyClasses }) {
const [item, setItem] = useState(datas[0]);
// custom hook
const [toggle, setToggle] = useToggle(false);
@@ -49,7 +49,7 @@ function SelectBox({ datas = [], className, action, contentBodyClasses, position
<div
style={{ boxShadow: "0px 4px 87px 0px #0000002B" }}
className={`drop-down-content w-[120px] bg-white dark:bg-dark-white rounded-[4px] p-3 absolute ${position =='left' ? 'left-0' : 'right-0'} top-[100%] z-20 ${
className={`drop-down-content w-[120px] bg-white dark:bg-dark-white rounded-[4px] p-3 absolute right-0 top-[100%] z-20 ${
toggle ? "active" : ""
} ${contentBodyClasses || ""}`}
>
+12
View File
@@ -51,6 +51,8 @@ export default function HistoryTable({ className }) {
<td className="py-4 text-center">Value</td>
<td className="py-4 text-center">USD</td>
<td className="py-4 text-center">24H%</td>
<td className="py-4 text-center">Bits</td>
<td className="py-4 text-center">Time</td>
<td className="py-4 text-right">Status</td>
</tr>
@@ -163,6 +165,16 @@ export default function HistoryTable({ className }) {
-24.75 (11.5%)
</span>
</td>
<td className="text-right py-4 px-2">
<span className="text-base text-dark-gray dark:text-white font-medium">
343
</span>
</td>
<td className="text-right py-4 px-2">
<span className="text-base text-thin-light-gray">
2 Hours 1 min 30s
</span>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
+162 -200
View File
@@ -13,9 +13,7 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function History() {
const apiCall = new usersService()
let [tab, setTab] = useState("purchases"); //STATE FOR SWITCHING BETWEEN TABS
const apiCall = new usersService()
let [paymentHistory, setPaymentHistory] = useState({ // FOR PAYMENT HISTORY
loading: true,
@@ -65,209 +63,173 @@ export default function History() {
<>
<Layout>
<div className="history-wrapper w-full mb-10">
<div className="w-full">
<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">
History
</h1>
</div>
<div className="slider-btns flex space-x-4">
</div>
<div className="main-wrapper w-full">
<div className="quick-counters-widget w-full mb-11">
<div className="grid xl:grid-cols-4 lg:grid-cols-2 grid-cols-1 gap-[30px]">
<HistoryAnalyticsCard
title="Total Sells"
numberOfCount={71}
numberOfAnalyse={324.75}
primaryColor="#5356FB"
iconBg="rgba(83, 86, 251, 0.16)"
>
<svg
width="38"
height="31"
viewBox="0 0 38 31"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M33.0451 12.6481C32.5478 14.368 32.1426 16.0074 31.5716 17.5846C31.4311 17.9737 30.7496 18.4066 30.3121 18.4112C25.1937 18.471 20.0754 18.4503 14.957 18.4526C14.1995 18.4526 13.716 18.0796 13.5433 17.3543C12.7328 13.9651 11.9154 10.5759 11.1418 7.17975C10.907 6.15285 11.3744 5.51968 12.3644 5.51277C16.5365 5.48514 20.7085 5.50125 24.9842 5.50125C24.9336 7.71622 25.5368 9.6526 27.2153 11.1285C28.857 12.579 30.7979 13.0142 33.0451 12.6481Z"
fill="#5356FB"
/>
<path
d="M12.4851 19.636C15.9295 19.636 19.3142 19.636 22.6988 19.636C24.9138 19.636 27.1287 19.6314 29.3437 19.6383C30.3752 19.6406 30.96 20.1034 30.9877 20.9024C31.0153 21.7428 30.412 22.2539 29.3391 22.2539C23.4747 22.2585 17.6126 22.2585 11.7483 22.2539C10.5602 22.2539 10.2309 21.9638 9.97077 20.7642C8.85637 15.6113 7.73277 10.4607 6.6391 5.30318C6.51016 4.69763 6.27301 4.35686 5.64904 4.16576C4.21921 3.72829 2.81701 3.19872 1.4056 2.70139C0.219833 2.28234 -0.219938 1.64226 0.102407 0.820278C0.420147 0.00750794 1.10858 -0.199714 2.23449 0.191705C3.98666 0.799556 5.72272 1.45345 7.49332 2.00605C8.38667 2.28464 8.81263 2.78888 9.00143 3.69145C10.0813 8.81904 11.2026 13.9374 12.3147 19.0581C12.3492 19.2101 12.4045 19.362 12.4851 19.636Z"
fill="#5356FB"
/>
<path
d="M25.8048 6.28397C25.7886 3.08815 28.3789 0.490967 31.5747 0.50248C34.7061 0.511689 37.2848 3.11347 37.2802 6.26094C37.2756 9.3992 34.6877 11.9941 31.5494 12.001C28.4112 12.0079 25.8209 9.43144 25.8048 6.28397ZM33.99 3.73514C32.9516 4.84723 31.9339 5.9386 30.7251 7.23489C30.1472 6.44974 29.6798 5.81887 29.1456 5.0959C28.6092 5.6577 28.2546 6.02839 28.0243 6.27245C29.0052 7.28554 29.9423 8.25027 30.808 9.14593C32.2125 7.73682 33.6585 6.28857 35.2264 4.71599C34.9709 4.51337 34.6646 4.26931 34.3561 4.02525C34.2594 3.94466 34.1627 3.86868 33.99 3.73514Z"
fill="#5356FB"
/>
<path
d="M27.9144 23.32C29.9474 23.3016 31.6052 24.8995 31.6443 26.9164C31.6835 28.9679 30.0165 30.651 27.9489 30.651C25.9296 30.651 24.2788 29.0094 24.2696 26.9993C24.2626 24.9801 25.8859 23.3384 27.9144 23.32ZM29.5767 26.974C29.5744 26.0829 28.8745 25.36 27.9949 25.3415C27.0832 25.3208 26.3233 26.0737 26.328 26.9924C26.3326 27.8743 27.044 28.6064 27.9144 28.6295C28.8261 28.6525 29.579 27.8996 29.5767 26.974Z"
fill="#5356FB"
/>
<path
d="M13.0216 30.6485C10.9908 30.6324 9.36064 29 9.36524 26.9853C9.37215 24.9062 11.0184 23.2922 13.1091 23.3152C15.126 23.3382 16.7446 25.0006 16.7216 27.0245C16.6963 29.0506 15.05 30.6647 13.0216 30.6485ZM14.6724 26.9899C14.6747 26.0643 13.9195 25.3206 13.0008 25.3437C12.1351 25.3667 11.396 26.115 11.396 26.9761C11.3937 27.8395 12.1259 28.597 12.987 28.627C13.8988 28.6569 14.6701 27.9086 14.6724 26.9899Z"
fill="#5356FB"
/>
</svg>
</HistoryAnalyticsCard>
<HistoryAnalyticsCard
title="Active Customer"
numberOfCount="7583k+"
numberOfAnalyse={324.75}
primaryColor="#F539F8"
iconBg="#FEEBFE"
>
<svg
width="28"
height="30"
viewBox="0 0 28 30"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M13.8146 13.1935C13.3126 13.0277 12.8406 12.9333 12.4216 12.7261C8.70772 10.891 5.00536 9.03523 1.29839 7.18865C1.0267 7.05281 0.817179 6.87782 0.812574 6.55317C0.80797 6.21471 1.01749 6.02591 1.303 5.88315C4.98464 4.04809 8.66628 2.20842 12.3456 0.368751C13.4048 -0.160815 14.4478 -0.100951 15.4931 0.426313C17.8577 1.61669 20.2316 2.79555 22.6008 3.97901C23.8096 4.58226 25.0161 5.18781 26.2226 5.79336C26.2916 5.82789 26.3607 5.86013 26.4321 5.89467C26.7084 6.0236 26.8995 6.22392 26.8995 6.54396C26.8995 6.86861 26.6946 7.0505 26.4229 7.18405C24.7075 8.03826 22.9945 8.89708 21.2792 9.75129C19.2991 10.7391 17.3282 11.7406 15.3365 12.7031C14.8622 12.931 14.3234 13.0323 13.8146 13.1935Z"
fill="#F539F8"
/>
<path
d="M12.8602 22.8893C12.8602 24.9477 12.8625 27.0061 12.8579 29.0645C12.8556 29.7966 12.4434 30.0545 11.7688 29.7437C8.39339 28.1895 5.01567 26.64 1.64717 25.0743C0.562705 24.5701 0.0101156 23.6882 0.00551066 22.4955C-0.0036992 18.5721 0.000903485 14.6487 0.00320595 10.7253C0.00320595 9.96783 0.429164 9.68692 1.10609 10.0001C4.59662 11.6095 8.08485 13.2281 11.5777 14.8306C12.4641 15.2382 12.874 15.9013 12.8671 16.8706C12.8533 18.8784 12.8625 20.8838 12.8625 22.8916C12.8625 22.8893 12.8602 22.8893 12.8602 22.8893Z"
fill="#F539F8"
/>
<path
d="M14.848 22.8313C14.848 20.8121 14.8526 18.7928 14.8457 16.7736C14.8434 15.8618 15.2602 15.2332 16.0775 14.8556C19.5911 13.2347 23.107 11.6183 26.6205 9.99971C27.2606 9.705 27.7004 9.96978 27.7004 10.6674C27.705 14.63 27.7119 18.5902 27.6958 22.5527C27.6912 23.7661 27.0695 24.6135 25.9758 25.12C23.2451 26.3817 20.5121 27.6412 17.7814 28.9006C17.1965 29.17 16.614 29.4394 16.0315 29.7088C15.2394 30.0726 14.8457 29.8262 14.8457 28.9651C14.8457 26.9205 14.8457 24.8736 14.8457 22.829C14.8457 22.8313 14.8457 22.8313 14.848 22.8313Z"
fill="#F539F8"
/>
</svg>
</HistoryAnalyticsCard>
<HistoryAnalyticsCard
title="Total Prodcuts"
numberOfCount="6753"
numberOfAnalyse={324.75}
primaryColor="#27AE60"
iconBg="#E9F7EF"
>
<svg
width="31"
height="31"
viewBox="0 0 31 31"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.0808 30.1824C10.7113 30.1824 6.3438 30.1824 1.97428 30.1824C0.641347 30.1824 -0.102099 29.364 0.0113425 28.0453C0.163273 26.3032 0.380025 24.5752 0.807456 22.8736C1.18424 21.3725 1.99859 20.3536 3.48345 19.7783C5.65302 18.9355 7.84892 18.182 10.0772 17.5155C10.1805 17.4851 10.3446 17.5358 10.4398 17.6046C11.9105 18.6702 13.3772 19.7398 14.8377 20.8195C15.018 20.9532 15.1355 20.9572 15.3178 20.8215C16.7784 19.7418 18.245 18.6722 19.7157 17.6067C19.8109 17.5378 19.973 17.4831 20.0763 17.5135C22.3694 18.2002 24.6382 18.9558 26.8584 19.8633C28.1306 20.384 28.8862 21.2591 29.2549 22.5596C29.7208 24.2025 29.9477 25.8798 30.1016 27.5733C30.1239 27.8265 30.1523 28.0818 30.1584 28.337C30.1867 29.364 29.421 30.1683 28.3919 30.1804C27.4094 30.1926 26.429 30.1824 25.4465 30.1824C21.9926 30.1824 18.5367 30.1824 15.0808 30.1824Z"
fill="#27AE60"
/>
<path
d="M8.44531 7.35622C8.58509 4.27912 9.72152 2.01232 12.3205 0.671285C15.3146 -0.872326 18.969 0.337039 20.6929 3.36754C21.7443 5.21501 21.8962 7.17795 21.4323 9.21382C21.0008 11.1059 20.2108 12.8338 18.967 14.3389C18.3735 15.056 17.6908 15.6739 16.846 16.0811C15.2498 16.8488 13.7629 16.5774 12.4137 15.5118C10.4366 13.952 9.39133 11.8108 8.78563 9.43057C8.59724 8.6851 8.53444 7.90722 8.44531 7.35622Z"
fill="#27AE60"
/>
</svg>
</HistoryAnalyticsCard>
<HistoryAnalyticsCard
title="Close Offer"
numberOfCount="745"
numberOfAnalyse={-324.75}
primaryColor="#EB5757"
iconBg="#FDEEEE"
>
<svg
width="70"
height="70"
viewBox="0 0 70 70"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle
opacity="0.1"
cx="35"
cy="35"
r="35"
fill="#EB5757"
/>
<path
d="M20.8416 32.9067C24.7077 32.9067 28.5465 32.9067 32.4127 32.9067C32.4127 38.4719 32.4127 44.0165 32.4127 49.616C32.2848 49.616 32.1637 49.616 32.0427 49.616C28.8753 49.616 25.7079 49.6183 22.5406 49.616C21.5084 49.616 20.8233 48.94 20.8233 47.9124C20.821 43.03 20.8233 38.1454 20.8233 33.263C20.8256 33.1465 20.8347 33.0346 20.8416 32.9067Z"
fill="#EB5757"
/>
<path
d="M36.8789 49.6137C36.8789 44.0143 36.8789 38.4696 36.8789 32.9067C40.7154 32.9067 44.529 32.9067 48.3906 32.9067C48.3906 33.062 48.3906 33.1968 48.3906 33.3315C48.3906 38.1796 48.3906 43.0277 48.3906 47.8736C48.3906 48.9377 47.7307 49.6137 46.6802 49.6137C43.5243 49.616 40.3706 49.6137 37.2146 49.6137C37.1118 49.6137 37.0091 49.6137 36.8789 49.6137Z"
fill="#EB5757"
/>
<path
d="M19.002 31.2053C19.002 30.6595 19.002 30.1434 19.002 29.6273C19.002 28.4193 18.9975 27.2089 19.002 26.0009C19.0043 25.0692 19.6734 24.359 20.5983 24.3567C24.4781 24.3453 28.358 24.3521 32.2379 24.3521C32.2836 24.3521 32.3292 24.3613 32.4046 24.3704C32.4046 26.6426 32.4046 28.9125 32.4046 31.2053C27.9515 31.2053 23.503 31.2053 19.002 31.2053Z"
fill="#EB5757"
/>
<path
d="M36.875 31.217C36.875 28.9197 36.875 26.6658 36.875 24.373C37.0052 24.3662 37.1262 24.3502 37.2449 24.3502C40.9878 24.3502 44.7306 24.3479 48.4735 24.3525C49.5719 24.3547 50.2228 25.0307 50.2182 26.1337C50.2136 27.6888 50.2182 29.244 50.2159 30.7968C50.2159 30.9316 50.2159 31.0663 50.2159 31.217C45.7491 31.217 41.3303 31.217 36.875 31.217Z"
fill="#EB5757"
/>
<path
d="M34.6091 21.749C35.8994 19.6001 37.6441 17.9947 39.6651 16.6565C40.8594 15.8664 42.0674 15.7385 43.2686 16.588C44.536 17.4855 45.0407 18.7483 44.7712 20.2669C44.5155 21.7033 43.6454 22.6533 42.241 23.0872C42.1017 23.1306 41.9464 23.1306 41.798 23.1306C37.1006 23.1328 32.4032 23.1214 27.7057 23.142C26.8905 23.1443 26.2145 22.8679 25.6391 22.3427C24.5384 21.3356 24.1661 20.0705 24.5475 18.641C24.9152 17.2617 25.824 16.3802 27.2376 16.0605C27.772 15.9394 28.2881 16.0011 28.7859 16.2363C30.1446 16.8826 31.2819 17.8326 32.3529 18.8693C33.2275 19.7188 34.0314 20.63 34.6091 21.749ZM34.0702 22.4158C34.0793 22.3861 34.0907 22.3564 34.0999 22.3267C33.0357 21.2078 31.903 20.171 30.526 19.4334C29.8295 19.0612 29.0805 19.1662 28.4913 19.7028C27.9798 20.1664 27.8062 20.7579 28.0209 21.3197C28.2607 21.9499 28.9161 22.4181 29.5555 22.4181C30.9371 22.4181 32.3187 22.4181 33.7003 22.4181C33.8258 22.4158 33.9492 22.4158 34.0702 22.4158ZM35.1184 22.3633C35.2166 22.3907 35.2577 22.4135 35.3011 22.4135C36.8197 22.4158 38.3383 22.4432 39.8569 22.4089C40.7681 22.3884 41.4988 21.3379 41.2727 20.4884C41.0284 19.5704 39.6559 18.8145 38.8064 19.3991C37.9752 19.97 37.1462 20.5501 36.3515 21.1689C35.9131 21.5069 35.5477 21.9408 35.1184 22.3633Z"
fill="#EB5757"
/>
</svg>
</HistoryAnalyticsCard>
</div>
{/*<div className="quick-counters-widget w-full mb-11">*/}
{/* <div className="grid xl:grid-cols-4 lg:grid-cols-2 grid-cols-1 gap-[30px]">*/}
{/* <HistoryAnalyticsCard*/}
{/* title="Total Sells"*/}
{/* numberOfCount={71}*/}
{/* numberOfAnalyse={324.75}*/}
{/* primaryColor="#5356FB"*/}
{/* iconBg="rgba(83, 86, 251, 0.16)"*/}
{/* >*/}
{/* <svg*/}
{/* width="38"*/}
{/* height="31"*/}
{/* viewBox="0 0 38 31"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <path*/}
{/* d="M33.0451 12.6481C32.5478 14.368 32.1426 16.0074 31.5716 17.5846C31.4311 17.9737 30.7496 18.4066 30.3121 18.4112C25.1937 18.471 20.0754 18.4503 14.957 18.4526C14.1995 18.4526 13.716 18.0796 13.5433 17.3543C12.7328 13.9651 11.9154 10.5759 11.1418 7.17975C10.907 6.15285 11.3744 5.51968 12.3644 5.51277C16.5365 5.48514 20.7085 5.50125 24.9842 5.50125C24.9336 7.71622 25.5368 9.6526 27.2153 11.1285C28.857 12.579 30.7979 13.0142 33.0451 12.6481Z"*/}
{/* fill="#5356FB"*/}
{/* />*/}
{/* <path*/}
{/* d="M12.4851 19.636C15.9295 19.636 19.3142 19.636 22.6988 19.636C24.9138 19.636 27.1287 19.6314 29.3437 19.6383C30.3752 19.6406 30.96 20.1034 30.9877 20.9024C31.0153 21.7428 30.412 22.2539 29.3391 22.2539C23.4747 22.2585 17.6126 22.2585 11.7483 22.2539C10.5602 22.2539 10.2309 21.9638 9.97077 20.7642C8.85637 15.6113 7.73277 10.4607 6.6391 5.30318C6.51016 4.69763 6.27301 4.35686 5.64904 4.16576C4.21921 3.72829 2.81701 3.19872 1.4056 2.70139C0.219833 2.28234 -0.219938 1.64226 0.102407 0.820278C0.420147 0.00750794 1.10858 -0.199714 2.23449 0.191705C3.98666 0.799556 5.72272 1.45345 7.49332 2.00605C8.38667 2.28464 8.81263 2.78888 9.00143 3.69145C10.0813 8.81904 11.2026 13.9374 12.3147 19.0581C12.3492 19.2101 12.4045 19.362 12.4851 19.636Z"*/}
{/* fill="#5356FB"*/}
{/* />*/}
{/* <path*/}
{/* d="M25.8048 6.28397C25.7886 3.08815 28.3789 0.490967 31.5747 0.50248C34.7061 0.511689 37.2848 3.11347 37.2802 6.26094C37.2756 9.3992 34.6877 11.9941 31.5494 12.001C28.4112 12.0079 25.8209 9.43144 25.8048 6.28397ZM33.99 3.73514C32.9516 4.84723 31.9339 5.9386 30.7251 7.23489C30.1472 6.44974 29.6798 5.81887 29.1456 5.0959C28.6092 5.6577 28.2546 6.02839 28.0243 6.27245C29.0052 7.28554 29.9423 8.25027 30.808 9.14593C32.2125 7.73682 33.6585 6.28857 35.2264 4.71599C34.9709 4.51337 34.6646 4.26931 34.3561 4.02525C34.2594 3.94466 34.1627 3.86868 33.99 3.73514Z"*/}
{/* fill="#5356FB"*/}
{/* />*/}
{/* <path*/}
{/* d="M27.9144 23.32C29.9474 23.3016 31.6052 24.8995 31.6443 26.9164C31.6835 28.9679 30.0165 30.651 27.9489 30.651C25.9296 30.651 24.2788 29.0094 24.2696 26.9993C24.2626 24.9801 25.8859 23.3384 27.9144 23.32ZM29.5767 26.974C29.5744 26.0829 28.8745 25.36 27.9949 25.3415C27.0832 25.3208 26.3233 26.0737 26.328 26.9924C26.3326 27.8743 27.044 28.6064 27.9144 28.6295C28.8261 28.6525 29.579 27.8996 29.5767 26.974Z"*/}
{/* fill="#5356FB"*/}
{/* />*/}
{/* <path*/}
{/* d="M13.0216 30.6485C10.9908 30.6324 9.36064 29 9.36524 26.9853C9.37215 24.9062 11.0184 23.2922 13.1091 23.3152C15.126 23.3382 16.7446 25.0006 16.7216 27.0245C16.6963 29.0506 15.05 30.6647 13.0216 30.6485ZM14.6724 26.9899C14.6747 26.0643 13.9195 25.3206 13.0008 25.3437C12.1351 25.3667 11.396 26.115 11.396 26.9761C11.3937 27.8395 12.1259 28.597 12.987 28.627C13.8988 28.6569 14.6701 27.9086 14.6724 26.9899Z"*/}
{/* fill="#5356FB"*/}
{/* />*/}
{/* </svg>*/}
{/* </HistoryAnalyticsCard>*/}
{/* <HistoryAnalyticsCard*/}
{/* title="Active Customer"*/}
{/* numberOfCount="7583k+"*/}
{/* numberOfAnalyse={324.75}*/}
{/* primaryColor="#F539F8"*/}
{/* iconBg="#FEEBFE"*/}
{/* >*/}
{/* <svg*/}
{/* width="28"*/}
{/* height="30"*/}
{/* viewBox="0 0 28 30"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <path*/}
{/* d="M13.8146 13.1935C13.3126 13.0277 12.8406 12.9333 12.4216 12.7261C8.70772 10.891 5.00536 9.03523 1.29839 7.18865C1.0267 7.05281 0.817179 6.87782 0.812574 6.55317C0.80797 6.21471 1.01749 6.02591 1.303 5.88315C4.98464 4.04809 8.66628 2.20842 12.3456 0.368751C13.4048 -0.160815 14.4478 -0.100951 15.4931 0.426313C17.8577 1.61669 20.2316 2.79555 22.6008 3.97901C23.8096 4.58226 25.0161 5.18781 26.2226 5.79336C26.2916 5.82789 26.3607 5.86013 26.4321 5.89467C26.7084 6.0236 26.8995 6.22392 26.8995 6.54396C26.8995 6.86861 26.6946 7.0505 26.4229 7.18405C24.7075 8.03826 22.9945 8.89708 21.2792 9.75129C19.2991 10.7391 17.3282 11.7406 15.3365 12.7031C14.8622 12.931 14.3234 13.0323 13.8146 13.1935Z"*/}
{/* fill="#F539F8"*/}
{/* />*/}
{/* <path*/}
{/* d="M12.8602 22.8893C12.8602 24.9477 12.8625 27.0061 12.8579 29.0645C12.8556 29.7966 12.4434 30.0545 11.7688 29.7437C8.39339 28.1895 5.01567 26.64 1.64717 25.0743C0.562705 24.5701 0.0101156 23.6882 0.00551066 22.4955C-0.0036992 18.5721 0.000903485 14.6487 0.00320595 10.7253C0.00320595 9.96783 0.429164 9.68692 1.10609 10.0001C4.59662 11.6095 8.08485 13.2281 11.5777 14.8306C12.4641 15.2382 12.874 15.9013 12.8671 16.8706C12.8533 18.8784 12.8625 20.8838 12.8625 22.8916C12.8625 22.8893 12.8602 22.8893 12.8602 22.8893Z"*/}
{/* fill="#F539F8"*/}
{/* />*/}
{/* <path*/}
{/* d="M14.848 22.8313C14.848 20.8121 14.8526 18.7928 14.8457 16.7736C14.8434 15.8618 15.2602 15.2332 16.0775 14.8556C19.5911 13.2347 23.107 11.6183 26.6205 9.99971C27.2606 9.705 27.7004 9.96978 27.7004 10.6674C27.705 14.63 27.7119 18.5902 27.6958 22.5527C27.6912 23.7661 27.0695 24.6135 25.9758 25.12C23.2451 26.3817 20.5121 27.6412 17.7814 28.9006C17.1965 29.17 16.614 29.4394 16.0315 29.7088C15.2394 30.0726 14.8457 29.8262 14.8457 28.9651C14.8457 26.9205 14.8457 24.8736 14.8457 22.829C14.8457 22.8313 14.8457 22.8313 14.848 22.8313Z"*/}
{/* fill="#F539F8"*/}
{/* />*/}
{/* </svg>*/}
{/* </HistoryAnalyticsCard>*/}
{/* <HistoryAnalyticsCard*/}
{/* title="Total Prodcuts"*/}
{/* numberOfCount="6753"*/}
{/* numberOfAnalyse={324.75}*/}
{/* primaryColor="#27AE60"*/}
{/* iconBg="#E9F7EF"*/}
{/* >*/}
{/* <svg*/}
{/* width="31"*/}
{/* height="31"*/}
{/* viewBox="0 0 31 31"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <path*/}
{/* d="M15.0808 30.1824C10.7113 30.1824 6.3438 30.1824 1.97428 30.1824C0.641347 30.1824 -0.102099 29.364 0.0113425 28.0453C0.163273 26.3032 0.380025 24.5752 0.807456 22.8736C1.18424 21.3725 1.99859 20.3536 3.48345 19.7783C5.65302 18.9355 7.84892 18.182 10.0772 17.5155C10.1805 17.4851 10.3446 17.5358 10.4398 17.6046C11.9105 18.6702 13.3772 19.7398 14.8377 20.8195C15.018 20.9532 15.1355 20.9572 15.3178 20.8215C16.7784 19.7418 18.245 18.6722 19.7157 17.6067C19.8109 17.5378 19.973 17.4831 20.0763 17.5135C22.3694 18.2002 24.6382 18.9558 26.8584 19.8633C28.1306 20.384 28.8862 21.2591 29.2549 22.5596C29.7208 24.2025 29.9477 25.8798 30.1016 27.5733C30.1239 27.8265 30.1523 28.0818 30.1584 28.337C30.1867 29.364 29.421 30.1683 28.3919 30.1804C27.4094 30.1926 26.429 30.1824 25.4465 30.1824C21.9926 30.1824 18.5367 30.1824 15.0808 30.1824Z"*/}
{/* fill="#27AE60"*/}
{/* />*/}
{/* <path*/}
{/* d="M8.44531 7.35622C8.58509 4.27912 9.72152 2.01232 12.3205 0.671285C15.3146 -0.872326 18.969 0.337039 20.6929 3.36754C21.7443 5.21501 21.8962 7.17795 21.4323 9.21382C21.0008 11.1059 20.2108 12.8338 18.967 14.3389C18.3735 15.056 17.6908 15.6739 16.846 16.0811C15.2498 16.8488 13.7629 16.5774 12.4137 15.5118C10.4366 13.952 9.39133 11.8108 8.78563 9.43057C8.59724 8.6851 8.53444 7.90722 8.44531 7.35622Z"*/}
{/* fill="#27AE60"*/}
{/* />*/}
{/* </svg>*/}
{/* </HistoryAnalyticsCard>*/}
{/* <HistoryAnalyticsCard*/}
{/* title="Close Offer"*/}
{/* numberOfCount="745"*/}
{/* numberOfAnalyse={-324.75}*/}
{/* primaryColor="#EB5757"*/}
{/* iconBg="#FDEEEE"*/}
{/* >*/}
{/* <svg*/}
{/* width="70"*/}
{/* height="70"*/}
{/* viewBox="0 0 70 70"*/}
{/* fill="none"*/}
{/* xmlns="http://www.w3.org/2000/svg"*/}
{/* >*/}
{/* <circle*/}
{/* opacity="0.1"*/}
{/* cx="35"*/}
{/* cy="35"*/}
{/* r="35"*/}
{/* fill="#EB5757"*/}
{/* />*/}
{/* <path*/}
{/* d="M20.8416 32.9067C24.7077 32.9067 28.5465 32.9067 32.4127 32.9067C32.4127 38.4719 32.4127 44.0165 32.4127 49.616C32.2848 49.616 32.1637 49.616 32.0427 49.616C28.8753 49.616 25.7079 49.6183 22.5406 49.616C21.5084 49.616 20.8233 48.94 20.8233 47.9124C20.821 43.03 20.8233 38.1454 20.8233 33.263C20.8256 33.1465 20.8347 33.0346 20.8416 32.9067Z"*/}
{/* fill="#EB5757"*/}
{/* />*/}
{/* <path*/}
{/* d="M36.8789 49.6137C36.8789 44.0143 36.8789 38.4696 36.8789 32.9067C40.7154 32.9067 44.529 32.9067 48.3906 32.9067C48.3906 33.062 48.3906 33.1968 48.3906 33.3315C48.3906 38.1796 48.3906 43.0277 48.3906 47.8736C48.3906 48.9377 47.7307 49.6137 46.6802 49.6137C43.5243 49.616 40.3706 49.6137 37.2146 49.6137C37.1118 49.6137 37.0091 49.6137 36.8789 49.6137Z"*/}
{/* fill="#EB5757"*/}
{/* />*/}
{/* <path*/}
{/* d="M19.002 31.2053C19.002 30.6595 19.002 30.1434 19.002 29.6273C19.002 28.4193 18.9975 27.2089 19.002 26.0009C19.0043 25.0692 19.6734 24.359 20.5983 24.3567C24.4781 24.3453 28.358 24.3521 32.2379 24.3521C32.2836 24.3521 32.3292 24.3613 32.4046 24.3704C32.4046 26.6426 32.4046 28.9125 32.4046 31.2053C27.9515 31.2053 23.503 31.2053 19.002 31.2053Z"*/}
{/* fill="#EB5757"*/}
{/* />*/}
{/* <path*/}
{/* d="M36.875 31.217C36.875 28.9197 36.875 26.6658 36.875 24.373C37.0052 24.3662 37.1262 24.3502 37.2449 24.3502C40.9878 24.3502 44.7306 24.3479 48.4735 24.3525C49.5719 24.3547 50.2228 25.0307 50.2182 26.1337C50.2136 27.6888 50.2182 29.244 50.2159 30.7968C50.2159 30.9316 50.2159 31.0663 50.2159 31.217C45.7491 31.217 41.3303 31.217 36.875 31.217Z"*/}
{/* fill="#EB5757"*/}
{/* />*/}
{/* <path*/}
{/* d="M34.6091 21.749C35.8994 19.6001 37.6441 17.9947 39.6651 16.6565C40.8594 15.8664 42.0674 15.7385 43.2686 16.588C44.536 17.4855 45.0407 18.7483 44.7712 20.2669C44.5155 21.7033 43.6454 22.6533 42.241 23.0872C42.1017 23.1306 41.9464 23.1306 41.798 23.1306C37.1006 23.1328 32.4032 23.1214 27.7057 23.142C26.8905 23.1443 26.2145 22.8679 25.6391 22.3427C24.5384 21.3356 24.1661 20.0705 24.5475 18.641C24.9152 17.2617 25.824 16.3802 27.2376 16.0605C27.772 15.9394 28.2881 16.0011 28.7859 16.2363C30.1446 16.8826 31.2819 17.8326 32.3529 18.8693C33.2275 19.7188 34.0314 20.63 34.6091 21.749ZM34.0702 22.4158C34.0793 22.3861 34.0907 22.3564 34.0999 22.3267C33.0357 21.2078 31.903 20.171 30.526 19.4334C29.8295 19.0612 29.0805 19.1662 28.4913 19.7028C27.9798 20.1664 27.8062 20.7579 28.0209 21.3197C28.2607 21.9499 28.9161 22.4181 29.5555 22.4181C30.9371 22.4181 32.3187 22.4181 33.7003 22.4181C33.8258 22.4158 33.9492 22.4158 34.0702 22.4158ZM35.1184 22.3633C35.2166 22.3907 35.2577 22.4135 35.3011 22.4135C36.8197 22.4158 38.3383 22.4432 39.8569 22.4089C40.7681 22.3884 41.4988 21.3379 41.2727 20.4884C41.0284 19.5704 39.6559 18.8145 38.8064 19.3991C37.9752 19.97 37.1462 20.5501 36.3515 21.1689C35.9131 21.5069 35.5477 21.9408 35.1184 22.3633Z"*/}
{/* fill="#EB5757"*/}
{/* />*/}
{/* </svg>*/}
{/* </HistoryAnalyticsCard>*/}
{/* </div>*/}
{/*</div>*/}
</div>
{/*<MarketHistorySection />*/}
{/* <TopHxBox className="mb-11" /> */}
<div className='w-full p-4 md:p-8 bg-white dark:bg-dark-white rounded-2xl shadow bottomMargin'>
{/* switch button */}
<div className="my-1 flex items-center border-b border-slate-300">
<button
name="purchases"
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "purchases" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
>
Purchases
</button>
<button
name="recent"
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "recent" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
>
Recent Activity
</button>
</div>
{/* END OF switch button */}
<div className="history-tables w-full">
{/* PURCHASE SECTION */}
{tab == 'purchases' &&
<div className="wallet w-full border-t">
<h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Purchases</h1>
{purchaseHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<PurchasesTable purchase={purchaseHistory} />
}
</div>
}
{/* END OF PURCHASE SECTION */}
{/* RECENT ACTIVITY SECTION */}
{tab == 'recent' &&
<div className="wallet w-full border-t">
<h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Recent Activity</h1>
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
{paymentHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={paymentHistory} />
<div className='w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin'>
{/* PURCHASE SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Purchases</h2>
{purchaseHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<PurchasesTable purchase={purchaseHistory} />
}
</div>
}
{/* END OF RECENT ACTIVITY SECTION */}
</div>
</div>
{/* END OF PURCHASE SECTION */}
{/* RECENT ACTIVITY SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
{paymentHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={paymentHistory} />
}
</div>
</div>
{/* END OF RECENT ACTIVITY SECTION */}
</div>
{/*<HistoryTable />*/}
<HistoryTable />
</div>
</div>
</Layout>
-103
View File
@@ -1,103 +0,0 @@
import React, { useRef } from "react";
import ProductCardStyleOne from "../Cards/ProductCardStyleOne";
import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom";
export default function FamilyActiveLSlde({ className, trending }) {
const settings = {
arrows: false,
slidesToShow: 3,
slidesToScroll: 3,
infinite: true,
responsive: [
{
breakpoint: 1025,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 769,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
},
},
{
breakpoint: 619,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
},
},
],
};
const trendingSlider = useRef(null);
const prevHandler = () => {
trendingSlider.current.slickPrev();
};
const nextHandler = () => {
trendingSlider.current.slickNext();
};
return (
<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">Current Tasks</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 relative w-full">
<SliderCom selector={trendingSlider} settings={settings}>
{trending &&
trending.length > 0 &&
trending.map((item) => (
<ProductCardStyleOne key={item.id} datas={item} />
))}
</SliderCom>
</div>
</div>
);
}
-24
View File
@@ -1,24 +0,0 @@
import React from "react";
import datas from "../../data/product_data.json";
import TopSellerTopBuyerSliderSection from "./TopSellerTopBuyerSliderSection";
import CommonHead from "../UserHeader/CommonHead";
import FamilyActiveLSlde from "./FamilyActiveLSlde";
import ParentWaiting from "../MyPendingJobs/ParentWaiting";
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
export default function FamilyDash({familyOffers}) {
console.log("PROPS IN FAMILY DASH->", familyOffers);
const trending = datas.datas;
return (
<div>
<div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
<MyOffersFamilyTable familyOffers={familyOffers} className="mb-10" />
<FamilyActiveLSlde trending={trending} className="mb-10" />
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
<ParentWaiting className="mb-10" />
</div>
</div>
);
}
-62
View File
@@ -1,62 +0,0 @@
import React from "react";
import datas from "../../data/product_data.json";
import Hero from "./Hero";
// import HomeTaskDisplay from "./HomeTaskDisplay";
import usersService from "../../services/UsersService";
import { useSelector } from "react-redux";
// import SellHistoryMarketVisitorAnalytic from './SellHistoryMarketVisitorAnalytic';
// import TopSellerTopBuyerSliderSection from "./TopSellerTopBuyerSliderSection";
//import UpdateTable from "./UpdateTable";
import HomeActivities from "./HomeActivities";
export default function FullAccountDash(props) {
console.log("PROPS IN HOME->", props);
const trending = datas.datas;
const jobData = datas.datas; // api calls or cache
const userApi = new usersService();
const { userDetails } = useSelector((state) => state?.userDetails);
return (
<div>
<div className="home-page-wrapper">
<Hero
className="mb-10"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
<HomeActivities className="mb-10" />
{/*<UpdateTable className="mb-10"/>*/}
{/*<SellHistoryMarketVisitorAnalytic className="mb-10"/>*/}
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
{/*<HomeTaskDisplay*/}
{/* jobData={jobData}*/}
{/* className="mb-10"*/}
{/* bannerList={props.bannerList}*/}
{/*/>*/}
</div>
</div>
);
}
// /*
// <Layout>
// <div className="home-page-wrapper">
// <Hero className="mb-10" data={userDetails} />
// {/* <CreateNft />
// <TrendingSection trending={trending} className="mb-10" />*/}
// <HomeTaskDisplay
// jobData={jobData}
// className="mb-10"
// bannerList={props.bannerList}
// />
{
/* <SellHistoryMarketVisitorAnalytic className="mb-10"/>
<TopSellerTopBuyerSliderSection className="mb-10" />
<UpdateTable className="mb-10"/>*/
}
// </div>
// </Layout>
+47 -38
View File
@@ -3,11 +3,15 @@ import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import heroBg from "../../assets/images/hero-bg.svg";
import heroUser from "../../assets/images/hero-user.png";
import slider1 from "../../assets/images/slider-1.jpg";
import slider2 from "../../assets/images/slider-2.jpg";
import slider3 from "../../assets/images/slider-3.jpg";
import CountDown from "../Helpers/CountDown";
import SliderCom from "../Helpers/SliderCom";
import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
export default function Hero({ className, bannerList, nextDueTask }) {
export default function Hero({ className }) {
const settings = {
autoplay: true,
dots: true,
@@ -15,12 +19,23 @@ export default function Hero({ className, bannerList, nextDueTask }) {
infinite: true,
swipe: true,
};
const sildeData = null;
const { userDetails } = useSelector((state) => state?.userDetails);
const sildeData =null;
const [addFavorite, setValue] = useState(false);
let loginDate = userDetails?.last_login.split(" ")[0];
let { firstname, lastname, email, profile_pic } = userDetails;
let userEmail = email.split("@")[0];
const {userDetails} = useSelector((state) => state?.userDetails)
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
toast.success("Added to Favorite List");
} else {
setValue(false);
toast.warn("Remove to Favorite List");
}
};
let loginDate = userDetails?.last_login.split(' ')[0]
let {firstname, lastname, email, profile_pic} = userDetails
let userEmail = email.split('@')[0]
return (
<div
@@ -40,13 +55,13 @@ export default function Hero({ className, bannerList, nextDueTask }) {
Welcome
</h1>
<span className="text-[18px] font-thin tracking-wide text-white">
Last Login : {loginDate}
Last Login : {loginDate}
</span>
</div>
{/* user */}
<div className="flex items-center space-x-3">
<div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">
<img src={profile_pic != "" ? profile_pic : heroUser} alt="" />
<img src={profile_pic != '' ? profile_pic : heroUser} alt="" />
</div>
<div>
<p className="text-xl tracking-wide font-bold antise text-white">
@@ -56,35 +71,33 @@ export default function Hero({ className, bannerList, nextDueTask }) {
</div>
</div>
{/* countdown */}
{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).substr(0,4)+'...'}
</p>
<p className="text-base text-white tracking-wide">
{nextDueTask.next_due.price * 0.01} Naira
</p>
</div>
<div className="w-[1px] h-full bg-white-opacity"></div>
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Next due in</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{/* <CountDown lastDate="2023-04-26 4:00:00" /> */}
<CountDown lastDate={nextDueTask.next_due.due_date} />
</p>
<div className="text-base text-white tracking-wide flex gap-[23px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
<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">
ABCDEFGH01
</p>
<p className="text-base text-white tracking-wide">773.69 USD</p>
</div>
<div className="w-[1px] h-full bg-white-opacity"></div>
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Next due in</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
<CountDown lastDate="2023-04-26 4:00:00" />
</p>
<div className="text-base text-white tracking-wide flex gap-[23px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
)}
</div>
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link to="/mytask" className="text-white text-base sm:block hidden">
<Link
to="/mytask"
className="text-white text-base sm:block hidden"
>
<span className=" border-b dark:border-[#5356fb29] border-white">
{" "}
View All Task(s)
@@ -92,11 +105,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
</Link>
</div>
</div>
<HomeSliders
settings={settings}
sideData={sildeData}
bannerList={bannerList}
/>
<HomeSliders settings={settings} sideData={sildeData}/>
</div>
);
}
-267
View File
@@ -1,267 +0,0 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
export default function HomeActivities({ className }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow relative min-h-[520px] ${
className || ""
}`}
>
<div className="header w-full sm:flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center mb-2 sm:mb-0">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
Recent Activities
</h1>
</div>
</div>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{/* table heading */}
{/*<tr className="text-base text-thin-light-gray whitespace-nowrap px-2 border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4 w-[300px] block whitespace-nowrap">*/}
{/* All Product*/}
{/* </td>*/}
{/* <td className="py-4 whitespace-nowrap text-center">.</td>*/}
{/* <td className="py-4 whitespace-nowrap text-center"></td>*/}
{/* <td className="py-4 whitespace-nowrap text-right"></td>*/}
{/*</tr>*/}
<tr className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage1}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
Mullican Computer Joy
</h1>
<span className="text-sm text-thin-light-gray">
Owned by <span className="text-purple">Xoeyam</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18Z"
fill="#627EEA"
/>
<path
d="M9.28125 2.25V7.23937L13.4983 9.12375L9.28125 2.25Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 2.25L5.0625 9.12375L9.28012 7.23937V2.25Z"
fill="white"
/>
<path
d="M9.28125 12.3582V15.7483L13.5011 9.91016L9.28125 12.3582Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 15.7483V12.3576L5.0625 9.91016L9.28012 15.7483Z"
fill="white"
/>
<path
d="M9.28125 11.572L13.4983 9.12348L9.28125 7.24023V11.572Z"
fill="white"
fillOpacity="0.2"
/>
<path
d="M5.0625 9.12348L9.28012 11.572V7.24023L5.0625 9.12348Z"
fill="white"
fillOpacity="0.602"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
7473 ETH
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.55225 0C7.8457 0 8.13914 0 8.43205 0C8.44829 0.026534 8.47537 0.0151623 8.49756 0.0162453C9.28966 0.0649812 10.0606 0.220936 10.8013 0.505229C12.7699 1.26172 14.2323 2.58354 15.183 4.46638C15.5999 5.29218 15.8506 6.16997 15.9561 7.08891C15.9691 7.201 15.9621 7.3158 16 7.42465C16 7.80858 16 8.19251 16 8.57698C15.9778 8.5916 15.9854 8.61543 15.9838 8.63546C15.9475 9.10387 15.8744 9.56686 15.7515 10.0206C15.1787 12.1342 13.9524 13.7603 12.0818 14.8942C11.1516 15.4579 10.1397 15.8002 9.06064 15.941C8.89497 15.9626 8.72875 15.98 8.56308 15.9995C8.17217 15.9995 7.78127 15.9995 7.39036 16C7.3752 15.9789 7.35138 15.9865 7.33135 15.9848C6.96752 15.9545 6.60639 15.9009 6.25068 15.8197C4.77639 15.4829 3.48998 14.793 2.4131 13.7311C0.998917 12.3372 0.204656 10.6461 0.0270709 8.66687C0.0205739 8.59431 0.033568 8.51904 0 8.44972C0 8.15081 0 7.85244 0 7.55352C0.0265295 7.53403 0.0151597 7.50479 0.016784 7.47988C0.0730915 6.64162 0.251218 5.83044 0.564158 5.05066C1.10179 3.71043 1.93774 2.59058 3.07634 1.70142C4.33839 0.715876 5.77098 0.159745 7.36762 0.0270755C7.4288 0.0216604 7.49432 0.0341151 7.55225 0ZM7.24635 9.86252C7.24635 10.2383 7.24526 10.6147 7.24743 10.9905C7.24797 11.0457 7.23389 11.0679 7.17596 11.0593C7.09691 11.0479 7.01678 11.0446 6.93774 11.0338C6.26746 10.9461 5.63563 10.7371 5.03952 10.4192C5.00379 10.4002 4.97834 10.3802 4.9621 10.4425C4.81375 11.0176 4.66324 11.5926 4.51164 12.1666C4.50027 12.2094 4.51272 12.2278 4.54954 12.2473C4.66486 12.3096 4.78235 12.3665 4.90309 12.4152C5.5961 12.6968 6.31998 12.8408 7.06497 12.8842C7.14131 12.8885 7.16134 12.9112 7.1608 12.9865C7.15701 13.4159 7.16026 13.8453 7.15809 14.2747C7.15755 14.3397 7.17488 14.3619 7.2431 14.3614C7.69085 14.3581 8.13914 14.3576 8.5869 14.3614C8.66432 14.3619 8.67731 14.3359 8.67731 14.2666C8.67461 13.8026 8.67677 13.3385 8.67461 12.8744C8.67407 12.8089 8.68544 12.7786 8.76015 12.765C9.09962 12.7049 9.4288 12.6058 9.74228 12.4607C10.3498 12.1802 10.8408 11.7703 11.1603 11.1724C11.4288 10.6699 11.51 10.1327 11.4618 9.56957C11.4158 9.03239 11.2366 8.55207 10.8787 8.14431C10.5506 7.77121 10.1402 7.51129 9.69843 7.29522C9.39145 7.14523 9.07363 7.02284 8.75041 6.91129C8.7098 6.89721 8.67407 6.88693 8.67407 6.82736C8.67623 6.14993 8.67569 5.4725 8.67461 4.79507C8.67461 4.75121 8.68489 4.73117 8.73308 4.73767C8.87547 4.75717 9.01895 4.77016 9.16134 4.79236C9.634 4.86493 10.0796 5.02467 10.5116 5.22395C10.5717 5.25157 10.5945 5.24886 10.6123 5.17684C10.7434 4.6467 10.8771 4.1171 11.0162 3.58913C11.0379 3.5079 11.0244 3.47541 10.948 3.44076C10.2799 3.13751 9.57282 3.01025 8.8457 2.97614C8.78018 2.97289 8.76123 2.95556 8.76178 2.88896C8.76503 2.50232 8.76232 2.11568 8.76448 1.72904C8.76503 1.66785 8.75041 1.64727 8.68489 1.64727C8.23173 1.64998 7.77802 1.64998 7.32485 1.64727C7.26151 1.64673 7.24418 1.66406 7.24418 1.72742C7.24689 2.1433 7.24256 2.55972 7.24797 2.9756C7.24905 3.06116 7.2209 3.08661 7.14239 3.10285C6.73579 3.18679 6.34651 3.32271 5.98646 3.53281C5.20628 3.98822 4.72117 4.64724 4.61938 5.5586C4.51597 6.48837 4.83812 7.2427 5.57661 7.81778C6.05739 8.19251 6.60639 8.43781 7.1738 8.64683C7.2274 8.66633 7.24743 8.68907 7.24689 8.7481C7.24472 9.12066 7.24635 9.49159 7.24635 9.86252Z"
fill="#59BE59"
/>
<path
d="M7.2452 9.86252C7.2452 9.49158 7.24358 9.12119 7.24683 8.75026C7.24737 8.69123 7.22734 8.66903 7.17374 8.64899C6.60687 8.43997 6.05787 8.19467 5.57655 7.81994C4.8386 7.24486 4.51591 6.49053 4.61933 5.56076C4.72057 4.6494 5.20568 3.99092 5.98641 3.53497C6.34645 3.32486 6.73519 3.18894 7.14233 3.10501C7.22084 3.08876 7.24899 3.06277 7.24791 2.97775C7.2425 2.56187 7.24683 2.14545 7.24412 1.72957C7.24358 1.66621 7.2609 1.64888 7.32479 1.64943C7.77796 1.65213 8.23167 1.65213 8.68483 1.64943C8.7498 1.64888 8.76442 1.66946 8.76442 1.73119C8.76171 2.11783 8.76496 2.50447 8.76171 2.89111C8.76117 2.95717 8.78012 2.97504 8.84563 2.97829C9.57276 3.01295 10.2793 3.13966 10.948 3.44291C11.0243 3.47757 11.0373 3.51006 11.0162 3.59128C10.877 4.11926 10.7433 4.64885 10.6123 5.17899C10.5944 5.25156 10.5717 5.25372 10.5116 5.2261C10.079 5.02683 9.63394 4.86708 9.16128 4.79452C9.01889 4.77286 8.87595 4.75932 8.73302 4.73983C8.68483 4.73333 8.67455 4.75337 8.67455 4.79723C8.67563 5.47466 8.67617 6.15209 8.674 6.82952C8.674 6.88908 8.70974 6.89937 8.75034 6.91345C9.07303 7.02446 9.39138 7.14684 9.69837 7.29738C10.1396 7.51344 10.5506 7.77283 10.8787 8.14647C11.2365 8.55369 11.4157 9.03455 11.4618 9.57173C11.51 10.1349 11.4287 10.6726 11.1602 11.1746C10.8408 11.7724 10.3497 12.1818 9.74222 12.4629C9.42874 12.608 9.09956 12.7071 8.76009 12.7672C8.68483 12.7802 8.674 12.811 8.67455 12.8766C8.67671 13.3406 8.67455 13.8047 8.67725 14.2688C8.67779 14.3381 8.66426 14.3646 8.58684 14.3636C8.13908 14.3598 7.69079 14.3608 7.24304 14.3636C7.17536 14.3641 7.15803 14.3424 7.15803 14.2769C7.1602 13.8475 7.15695 13.4181 7.16074 12.9887C7.16128 12.9128 7.14179 12.8906 7.06491 12.8863C6.31992 12.843 5.59658 12.699 4.90303 12.4174C4.78229 12.3681 4.66426 12.3112 4.54948 12.2495C4.51321 12.23 4.50075 12.2116 4.51158 12.1688C4.66318 11.5943 4.81369 11.0197 4.96204 10.4446C4.97829 10.3824 5.00373 10.4024 5.03947 10.4214C5.63557 10.7387 6.2674 10.9477 6.93768 11.036C7.01672 11.0463 7.09685 11.0501 7.1759 11.0614C7.23383 11.0695 7.24737 11.0479 7.24737 10.9927C7.24412 10.6147 7.2452 10.2383 7.2452 9.86252ZM8.68537 9.36325C8.67942 9.37245 8.67455 9.37678 8.67455 9.38112C8.674 9.83978 8.67401 10.2984 8.67292 10.7571C8.67292 10.8177 8.70216 10.7928 8.72598 10.7755C8.82452 10.7046 8.90736 10.619 8.96691 10.5123C9.17698 10.1333 9.05679 9.63725 8.68537 9.36325ZM7.23871 6.11147C7.23871 5.75354 7.23871 5.40589 7.23871 5.05174C6.92522 5.33982 6.92522 5.77249 7.23871 6.11147Z"
fill="#FEFEFE"
/>
<path
d="M8.68433 9.36328C9.05574 9.63729 9.17539 10.1333 8.96586 10.5118C8.90631 10.619 8.82347 10.7046 8.72493 10.775C8.70111 10.7918 8.67188 10.8172 8.67188 10.7566C8.67242 10.2979 8.67296 9.83927 8.6735 9.38061C8.67404 9.37682 8.67891 9.37249 8.68433 9.36328Z"
fill="#59BE59"
/>
<path
d="M7.23882 6.11149C6.92533 5.77305 6.92587 5.33984 7.23882 5.05176C7.23882 5.40591 7.23882 5.75355 7.23882 6.11149Z"
fill="#59BE59"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium">
6392.99$
</span>
</div>
</td>
<td className="text-right py-4">
<button
type="button"
className="text-sm text-white bg-purple px-2.5 py-1.5 rounded-full"
>
Active
</button>
</td>
</tr>
<tr className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
Mullican Computer Joy
</h1>
<span className="text-sm text-thin-light-gray">
Owned by <span className="text-purple">Xoeyam</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18Z"
fill="#627EEA"
/>
<path
d="M9.28125 2.25V7.23937L13.4983 9.12375L9.28125 2.25Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 2.25L5.0625 9.12375L9.28012 7.23937V2.25Z"
fill="white"
/>
<path
d="M9.28125 12.3582V15.7483L13.5011 9.91016L9.28125 12.3582Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 15.7483V12.3576L5.0625 9.91016L9.28012 15.7483Z"
fill="white"
/>
<path
d="M9.28125 11.572L13.4983 9.12348L9.28125 7.24023V11.572Z"
fill="white"
fillOpacity="0.2"
/>
<path
d="M5.0625 9.12348L9.28012 11.572V7.24023L5.0625 9.12348Z"
fill="white"
fillOpacity="0.602"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
7473 ETH
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.55225 0C7.8457 0 8.13914 0 8.43205 0C8.44829 0.026534 8.47537 0.0151623 8.49756 0.0162453C9.28966 0.0649812 10.0606 0.220936 10.8013 0.505229C12.7699 1.26172 14.2323 2.58354 15.183 4.46638C15.5999 5.29218 15.8506 6.16997 15.9561 7.08891C15.9691 7.201 15.9621 7.3158 16 7.42465C16 7.80858 16 8.19251 16 8.57698C15.9778 8.5916 15.9854 8.61543 15.9838 8.63546C15.9475 9.10387 15.8744 9.56686 15.7515 10.0206C15.1787 12.1342 13.9524 13.7603 12.0818 14.8942C11.1516 15.4579 10.1397 15.8002 9.06064 15.941C8.89497 15.9626 8.72875 15.98 8.56308 15.9995C8.17217 15.9995 7.78127 15.9995 7.39036 16C7.3752 15.9789 7.35138 15.9865 7.33135 15.9848C6.96752 15.9545 6.60639 15.9009 6.25068 15.8197C4.77639 15.4829 3.48998 14.793 2.4131 13.7311C0.998917 12.3372 0.204656 10.6461 0.0270709 8.66687C0.0205739 8.59431 0.033568 8.51904 0 8.44972C0 8.15081 0 7.85244 0 7.55352C0.0265295 7.53403 0.0151597 7.50479 0.016784 7.47988C0.0730915 6.64162 0.251218 5.83044 0.564158 5.05066C1.10179 3.71043 1.93774 2.59058 3.07634 1.70142C4.33839 0.715876 5.77098 0.159745 7.36762 0.0270755C7.4288 0.0216604 7.49432 0.0341151 7.55225 0ZM7.24635 9.86252C7.24635 10.2383 7.24526 10.6147 7.24743 10.9905C7.24797 11.0457 7.23389 11.0679 7.17596 11.0593C7.09691 11.0479 7.01678 11.0446 6.93774 11.0338C6.26746 10.9461 5.63563 10.7371 5.03952 10.4192C5.00379 10.4002 4.97834 10.3802 4.9621 10.4425C4.81375 11.0176 4.66324 11.5926 4.51164 12.1666C4.50027 12.2094 4.51272 12.2278 4.54954 12.2473C4.66486 12.3096 4.78235 12.3665 4.90309 12.4152C5.5961 12.6968 6.31998 12.8408 7.06497 12.8842C7.14131 12.8885 7.16134 12.9112 7.1608 12.9865C7.15701 13.4159 7.16026 13.8453 7.15809 14.2747C7.15755 14.3397 7.17488 14.3619 7.2431 14.3614C7.69085 14.3581 8.13914 14.3576 8.5869 14.3614C8.66432 14.3619 8.67731 14.3359 8.67731 14.2666C8.67461 13.8026 8.67677 13.3385 8.67461 12.8744C8.67407 12.8089 8.68544 12.7786 8.76015 12.765C9.09962 12.7049 9.4288 12.6058 9.74228 12.4607C10.3498 12.1802 10.8408 11.7703 11.1603 11.1724C11.4288 10.6699 11.51 10.1327 11.4618 9.56957C11.4158 9.03239 11.2366 8.55207 10.8787 8.14431C10.5506 7.77121 10.1402 7.51129 9.69843 7.29522C9.39145 7.14523 9.07363 7.02284 8.75041 6.91129C8.7098 6.89721 8.67407 6.88693 8.67407 6.82736C8.67623 6.14993 8.67569 5.4725 8.67461 4.79507C8.67461 4.75121 8.68489 4.73117 8.73308 4.73767C8.87547 4.75717 9.01895 4.77016 9.16134 4.79236C9.634 4.86493 10.0796 5.02467 10.5116 5.22395C10.5717 5.25157 10.5945 5.24886 10.6123 5.17684C10.7434 4.6467 10.8771 4.1171 11.0162 3.58913C11.0379 3.5079 11.0244 3.47541 10.948 3.44076C10.2799 3.13751 9.57282 3.01025 8.8457 2.97614C8.78018 2.97289 8.76123 2.95556 8.76178 2.88896C8.76503 2.50232 8.76232 2.11568 8.76448 1.72904C8.76503 1.66785 8.75041 1.64727 8.68489 1.64727C8.23173 1.64998 7.77802 1.64998 7.32485 1.64727C7.26151 1.64673 7.24418 1.66406 7.24418 1.72742C7.24689 2.1433 7.24256 2.55972 7.24797 2.9756C7.24905 3.06116 7.2209 3.08661 7.14239 3.10285C6.73579 3.18679 6.34651 3.32271 5.98646 3.53281C5.20628 3.98822 4.72117 4.64724 4.61938 5.5586C4.51597 6.48837 4.83812 7.2427 5.57661 7.81778C6.05739 8.19251 6.60639 8.43781 7.1738 8.64683C7.2274 8.66633 7.24743 8.68907 7.24689 8.7481C7.24472 9.12066 7.24635 9.49159 7.24635 9.86252Z"
fill="#59BE59"
/>
<path
d="M7.2452 9.86252C7.2452 9.49158 7.24358 9.12119 7.24683 8.75026C7.24737 8.69123 7.22734 8.66903 7.17374 8.64899C6.60687 8.43997 6.05787 8.19467 5.57655 7.81994C4.8386 7.24486 4.51591 6.49053 4.61933 5.56076C4.72057 4.6494 5.20568 3.99092 5.98641 3.53497C6.34645 3.32486 6.73519 3.18894 7.14233 3.10501C7.22084 3.08876 7.24899 3.06277 7.24791 2.97775C7.2425 2.56187 7.24683 2.14545 7.24412 1.72957C7.24358 1.66621 7.2609 1.64888 7.32479 1.64943C7.77796 1.65213 8.23167 1.65213 8.68483 1.64943C8.7498 1.64888 8.76442 1.66946 8.76442 1.73119C8.76171 2.11783 8.76496 2.50447 8.76171 2.89111C8.76117 2.95717 8.78012 2.97504 8.84563 2.97829C9.57276 3.01295 10.2793 3.13966 10.948 3.44291C11.0243 3.47757 11.0373 3.51006 11.0162 3.59128C10.877 4.11926 10.7433 4.64885 10.6123 5.17899C10.5944 5.25156 10.5717 5.25372 10.5116 5.2261C10.079 5.02683 9.63394 4.86708 9.16128 4.79452C9.01889 4.77286 8.87595 4.75932 8.73302 4.73983C8.68483 4.73333 8.67455 4.75337 8.67455 4.79723C8.67563 5.47466 8.67617 6.15209 8.674 6.82952C8.674 6.88908 8.70974 6.89937 8.75034 6.91345C9.07303 7.02446 9.39138 7.14684 9.69837 7.29738C10.1396 7.51344 10.5506 7.77283 10.8787 8.14647C11.2365 8.55369 11.4157 9.03455 11.4618 9.57173C11.51 10.1349 11.4287 10.6726 11.1602 11.1746C10.8408 11.7724 10.3497 12.1818 9.74222 12.4629C9.42874 12.608 9.09956 12.7071 8.76009 12.7672C8.68483 12.7802 8.674 12.811 8.67455 12.8766C8.67671 13.3406 8.67455 13.8047 8.67725 14.2688C8.67779 14.3381 8.66426 14.3646 8.58684 14.3636C8.13908 14.3598 7.69079 14.3608 7.24304 14.3636C7.17536 14.3641 7.15803 14.3424 7.15803 14.2769C7.1602 13.8475 7.15695 13.4181 7.16074 12.9887C7.16128 12.9128 7.14179 12.8906 7.06491 12.8863C6.31992 12.843 5.59658 12.699 4.90303 12.4174C4.78229 12.3681 4.66426 12.3112 4.54948 12.2495C4.51321 12.23 4.50075 12.2116 4.51158 12.1688C4.66318 11.5943 4.81369 11.0197 4.96204 10.4446C4.97829 10.3824 5.00373 10.4024 5.03947 10.4214C5.63557 10.7387 6.2674 10.9477 6.93768 11.036C7.01672 11.0463 7.09685 11.0501 7.1759 11.0614C7.23383 11.0695 7.24737 11.0479 7.24737 10.9927C7.24412 10.6147 7.2452 10.2383 7.2452 9.86252ZM8.68537 9.36325C8.67942 9.37245 8.67455 9.37678 8.67455 9.38112C8.674 9.83978 8.67401 10.2984 8.67292 10.7571C8.67292 10.8177 8.70216 10.7928 8.72598 10.7755C8.82452 10.7046 8.90736 10.619 8.96691 10.5123C9.17698 10.1333 9.05679 9.63725 8.68537 9.36325ZM7.23871 6.11147C7.23871 5.75354 7.23871 5.40589 7.23871 5.05174C6.92522 5.33982 6.92522 5.77249 7.23871 6.11147Z"
fill="#FEFEFE"
/>
<path
d="M8.68433 9.36328C9.05574 9.63729 9.17539 10.1333 8.96586 10.5118C8.90631 10.619 8.82347 10.7046 8.72493 10.775C8.70111 10.7918 8.67188 10.8172 8.67188 10.7566C8.67242 10.2979 8.67296 9.83927 8.6735 9.38061C8.67404 9.37682 8.67891 9.37249 8.68433 9.36328Z"
fill="#59BE59"
/>
<path
d="M7.23882 6.11149C6.92533 5.77305 6.92587 5.33984 7.23882 5.05176C7.23882 5.40591 7.23882 5.75355 7.23882 6.11149Z"
fill="#59BE59"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium">
6392.99$
</span>
</div>
</td>
<td className="text-right py-4">
<button
type="button"
className="text-sm text-white bg-light-green px-2.5 py-1.5 rounded-full"
>
Complated
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
);
}
+25 -24
View File
@@ -1,31 +1,32 @@
import SliderCom from "../Helpers/SliderCom";
import slider1 from "../../assets/images/slider-1.jpg";
import slider2 from "../../assets/images/slider-2.jpg";
import slider3 from "../../assets/images/slider-3.jpg";
import HomeBannerOffersCard from "../Cards/HomeBannerOffersCard";
export default function HomeSliders(props) {
// debugger;
return (
<>
<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 && (
<div className="item w-full h-full bg-white dark:bg-dark-white max-h-80 rounded-2xl overflow-hidden">
<img src={slider2} alt="slider" className="w-full h-full" />
</div>
)}
{props.bannerList?.length > 0 &&
props.bannerList.map((item, index) => (
<div
key={index}
className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden"
>
<HomeBannerOffersCard itemData={item} />
// 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="w-full">
<SliderCom settings={props.settings}>
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<img src={slider1} alt="slider" className="w-full h-full" />
</div>
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<img src={slider2} alt="slider" className="w-full h-full" />
</div>
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<img src={slider3} alt="slider" className="w-full h-full" />
</div>
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<HomeBannerOffersCard />
</div>
</SliderCom>
</div>
))}
</SliderCom>
</div>
</div>
</>
);
</div>
</>
);
}
+30 -83
View File
@@ -1,93 +1,40 @@
import React, { useState, useEffect } from "react";
import React from "react";
import datas from "../../data/product_data.json";
import Layout from "../Partials/Layout";
import CreateNft from "./CreateNft";
import Hero from "./Hero";
import SellHistoryMarketVisitorAnalytic from "./SellHistoryMarketVisitorAnalytic";
import TopSellerTopBuyerSliderSection from "./TopSellerTopBuyerSliderSection";
import TrendingSection from "./TrendingSection";
import UpdateTable from "./UpdateTable";
import HomeTaskDisplay from "./HomeTaskDisplay";
import UsersService from "../../services/UsersService";
import usersService from "../../services/UsersService";
import { useSelector } from "react-redux";
import FamilyDash from "./FamilyDash";
import FullAccountDash from "./FullAccountDash";
export default function Home(props) {
console.log("PROPS IN HOME->", props);
let [nextDueTask, setNextDueTask] = useState({});
const [MyOffersList, setMyOffersList] = useState([]);
export default function Home() {
const trending = datas.datas;
const jobData = datas.datas; // api calls or cache
//getHomeDate
const userApi = new usersService();
const homeData = userApi.getHomeDate();
const userApi = new usersService();
const {userDetails} = useSelector((state) => state?.userDetails)
const { userDetails } = useSelector((state) => state?.userDetails);
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
// FUNCTION TO GET DASH DATA TO DETERMINE CURRENT TASK DUE TIME
const getHomeDate = () => {
userApi
.getHomeDate()
.then((res) => {
if (res.status != 200 || res.internal_return < 0) {
return;
}
setNextDueTask(res.data);
})
.catch((error) => {
console.log(error);
});
};
const getMyOffersList = async () => {
try {
const res = await userApi.getOffersList();
setMyOffersList(res.data?.result_list);
} catch (error) {
console.log("Error getting offers", error);
}
};
useEffect(() => {
const fetchData = async () => {
await Promise.all([getHomeDate(), getMyOffersList()]);
};
fetchData();
}, []);
return (
<Layout>
<div className="home-page-wrapper">
{userDetails && userDetails?.account_type == "FAMILY" ? (
<FamilyDash
account={userDetails}
commonHeadData={props.bannerList}
familyOffers={MyOffersList}
/>
) : 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>
);
}
// /*
// <Layout>
// <div className="home-page-wrapper">
// <Hero className="mb-10" data={userDetails} />
// {/* <CreateNft />
// <TrendingSection trending={trending} className="mb-10" />*/}
// <HomeTaskDisplay
// jobData={jobData}
// className="mb-10"
// bannerList={props.bannerList}
// />
{
/* <SellHistoryMarketVisitorAnalytic className="mb-10"/>
return (
<Layout>
<div className="home-page-wrapper">
<Hero className="mb-10" data={userDetails} />
{/* <CreateNft />
<TrendingSection trending={trending} className="mb-10" />*/}
<HomeTaskDisplay
jobData={jobData}
className="mb-10"/>
{/* <SellHistoryMarketVisitorAnalytic className="mb-10"/>
<TopSellerTopBuyerSliderSection className="mb-10" />
<UpdateTable className="mb-10"/>*/
<UpdateTable className="mb-10"/>*/}
</div>
</Layout>
);
}
// </div>
// </Layout>
+79 -79
View File
@@ -1,105 +1,105 @@
import React, { useEffect, useMemo, useState } from "react";
import React, { useEffect, useState } from "react";
//import ProductCardStyleTwo from "../Cards/ProductCardStyleTwo";
import DataIteration from "../Helpers/DataIteration";
// import SearchCom from "../Helpers/SearchCom";
// import ActiveJobsCard from "../Cards/ActiveJobsCard";
import AvailableJobsCard from "../Cards/AvailableJobsCard";
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({
className,
marketPlaceProduct,
categories,
}) {
// Creating All cart..
let marketCategories = useMemo(
() => ({ All: "All Categories", ...categories }),
[categories]
);
const [tab, setTab] = useState(Object.keys(marketCategories)[0]);
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]) => {
return { key, value };
});
const [products, setProducts] = useState([]);
export default function MainSection({ className, marketPlaceProduct }) {
const [tab, setTab] = useState("explore");
const [products, setProducts] = useState(marketPlaceProduct);
const tabHandler = (value) => {
setTab(value);
};
// Handles the category selection on mobile view
const handleSetCategory = (value) => {
for (let i in marketCategories) {
if (marketCategories[i] == value) {
setTab(i);
}
}
};
useEffect(() => {
if (tab === "All") {
setProducts(marketPlaceProduct);
if (tab === "artist") {
setProducts(marketPlaceProduct.slice(0, 3));
} else if (tab === "market") {
setProducts(marketPlaceProduct.slice(0, 6));
} else if (tab === "shop") {
setProducts(marketPlaceProduct.slice(6, 9));
} else if (tab === "assets") {
setProducts(marketPlaceProduct.slice(3, 6));
} else {
const filteredProducts = marketPlaceProduct.filter((product) =>
product.category.includes(tab)
);
setProducts(filteredProducts);
setProducts(marketPlaceProduct);
}
}, [tab, marketPlaceProduct, categories, marketCategories]);
}, [tab, marketPlaceProduct]);
return (
<div className={`market-place-section w-full ${className || ""}`}>
<div className="market-place-wrapper w-full">
<div className="filter-navigate-area flex justify-between items-center mb-8">
<div className="tab-item w-full flex items-center">
<div className="hidden lg:flex md:space-x-8 space-x-2">
{mappedArray.map(({ key, value }) => (
<span
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
? "text-pink border-pink"
: " border-transparent"
}`}
>
{value}
</span>
))}
</div>
{/* market categories on screen smaller than large screen */}
<div className="w-[80%] lg:hidden">
<SelectBox
action={handleSetCategory}
datas={Object.values(marketCategories)}
className="Update-table-dropdown"
contentBodyClasses="w-auto min-w-max"
position='left'
/>
<div className="filter-navigate-area lg:flex justify-between mb-8 items-center">
<div className="tab-item lg:mb-0 mb-5">
<div className="md:flex md:space-x-8 space-x-2">
<span
onClick={() => tabHandler("explore")}
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 === "explore"
? "text-pink border-pink"
: " border-transparent"
}`}
>
Explore
</span>
<span
onClick={() => tabHandler("artist")}
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 === "artist"
? "text-pink border-pink"
: " border-transparent"
}`}
>
Featured Artist
</span>
<span
onClick={() => tabHandler("market")}
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 === "market"
? "text-pink border-pink"
: " border-transparent"
}`}
>
Open Market
</span>
<span
onClick={() => tabHandler("shop")}
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 === "shop"
? "text-pink border-pink"
: " border-transparent"
}`}
>
Partner Shops
</span>
<span
onClick={() => tabHandler("assets")}
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 === "assets"
? "text-pink border-pink"
: " border-transparent"
}`}
>
Game Assets
</span>
</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"
/>
</div>
{/* end of contentDisplay toggler */}
{/*<div className="search-item flex lg:flex-none justify-end">*/}
{/* <SearchCom*/}
{/* className="lg:bg-transparent"*/}
{/* inputClasses="lg:bg-transparent"*/}
{/* />*/}
{/*</div>*/}
</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="grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]">
<DataIteration
datas={products}
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products?.length}
>
{({ datas }) => (
<AvailableJobsCard contentDisplay={contentDisplay} key={datas.id} datas={datas} />
<AvailableJobsCard key={datas.id} datas={datas} />
)}
</DataIteration>
</div>
@@ -1,12 +0,0 @@
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
@@ -1,321 +0,0 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import ModalCom from "../../Helpers/ModalCom";
import { toast } from "react-toastify";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
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("");
const handleInputChange = ({ target: { value } }) => {
setTextValue(value);
};
const apiCall = useMemo(() => new usersService(), []);
let { manageInt, ManageInterest, MarketDetail, marketMsg } = MarketCalls(details);
let thePrice = PriceFormatter(
details?.price * 0.01,
details?.currency_code,
details?.currency
);
// let addedIntDate = marketInt?.added?.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">
<div className="logout-modal-wrapper md:w-[750px] md:h-[660px] h-full 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]">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{details.offer_code}
</h1>
<CloseIcon onClose={onClose} />
</div>
<div className="md:flex bg-white rounded-lg">
<div className="p-4 w-full md:w-[75%] md:border-r-1">
<div className="min-h-[263px]">
<h2 className="font-semibold text-slate-900 dark:text-black tracking-wide">
{details?.title}
</h2>
{/* INPUT SECTION */}
{[
{
name: "Description",
content: details.description,
},
{
name: "",
content: {
text: `Timeline: ${details.timeline_days} day(s) -- `,
bold: `Budget: ${thePrice}`,
},
},
{
name: "Delivery Detail",
content: cleanedText,
danger: true,
},
].map(({ name, content, danger }, idx) => (
<div className={`my-3 md:flex items-center`} key={idx}>
<label className="w-full md:w-[19%] text-slate-900 tracking-wide font-semibold whitespace-pre-wrap">
{name}
</label>
<div
className={`w-full md:w-3/4 text-slate-900 market-pop ${
name !== "Delivery Detail"
? " h-full max-h-28 flex items-center"
: " overflow-y-auto max-h-[100px]"
}`}
>
{danger ? (
<p
className={``}
dangerouslySetInnerHTML={{
__html: danger && content,
}}
/>
) : (
<p className={`w-full text-slate-900`}>
{name !== "Delivery Detail" ? (
<>
{typeof content !== "object" ? content : null}
{typeof content === "object" && (
<>
<hr className="mb-1" />
<span className="flex items-center gap-2">
{content?.text}
<strong>{thePrice}</strong>
</span>
<hr className="mt-1" />
</>
)}
</>
) : (
""
)}
</p>
)}
</div>
</div>
))}
</div>
<hr />
<div className="my-3 w-full flex flex-col gap-3">
<div className="w-full">
<label className="w-full text-slate-900 tracking-wide">
If you have any questions about this task:
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
placeholder="Enter message here ..."
value={textValue}
onChange={handleInputChange}
/>
</div>
<button
className="self-end w-[150px] h-[52px] rounded-md text-base bg-yellow-500 text-white"
name="market-message"
onClick={MarketDetail}
>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
) : !marketMsg.state ? (
"Send Message"
) : (
"Message Sent"
)}
</button>
</div>
</div>
<div className="w-full md:w-[23%] h-full ">
<div className="mx-auto bg-[#f1f8ff] p-4 rounded-md md:min-h-[498px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center py-4 gap-2">
<p className="w-full text-slate-900 tracking-wide my-1">
Interested in the task?
</p>
<hr />
<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={ManageInterest}
>
{" "}
<span>Send</span>
<span>Interest</span>
<span>Request</span>
</button>
<>
{manageInt.loading ? (
<p className="text-sm italic">please wait...</p>
) : (
<>
{manageInt?.msg !== "" && (
<p
className={`text-sm italic ${
manageInt?.state ? "text-green-500" : "text-red-500"
}`}
>
{manageInt?.msg}
</p>
)}
</>
)}
</>
</div>
<div className="">
<p className="flex items-center tracking-wide">
Interest: <b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1">
Expire: {details.expire}
</p>
</div>
</div>
<button
className="self-end w-[150px] mt-2 h-[52px] rounded-md text-base bg-transparent border border-red-500 text-red-500 mx-auto"
name="cancel"
onClick={onClose}
>
Cancel
</button>
</div>
{/* END OF ACTION SECTION */}
</div>
</div>
</ModalCom>
);
};
export default MarketPopUp;
const CloseIcon = ({ onClose }) => (
<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>
);
+8 -9
View File
@@ -1,23 +1,22 @@
import React from "react";
// import products from "../../data/marketplace_data.json";
//import CreateNft from "../Home/CreateNft";
import Layout from "../Partials/Layout";
import MainSection from "./MainSection";
import CommonHead from "../UserHeader/CommonHead";
import { useSelector } from "react-redux";
export default function MarketPlace({ commonHeadData }) {
export default function MarketPlace() {
let { jobLists } = useSelector((state) => state.jobLists);
const marketData = jobLists?.result_list;
const categories = jobLists?.categories;
// const marketProduct = products.data;
return (
<>
<Layout>
<CommonHead commonHeadData={commonHeadData} />
<MainSection
marketPlaceProduct={marketData}
categories={categories}
className="mb-10"
/>
<CommonHead />
<MainSection marketPlaceProduct={marketData} className="mb-10" />
</Layout>
</>
);
}
}
@@ -1,68 +0,0 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
import PaginatedList from "../Pagination/PaginatedList";
import { handlePagingFunc } from "../Pagination/HandlePagination";
export default function ActiveJobMessage({ activeJobMesList }) {
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentActiveJobMesList = activeJobMesList?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e,setCurrentPage)
}
return (
<div className='flex flex-col justify-between h-full'>
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
<th className="p-2"></th>
</tr>
</thead>
{activeJobMesList.data.length ?
(
<tbody>
{currentActiveJobMesList.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td>
<div className="msg_box">
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
</div>
</td>
</tr>
))}
</tbody>
)
:
activeJobMesList.error ?
(
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
</tr>
</tbody>
)
:
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>No Message Found!</td>
</tr>
</tbody>
}
</table>
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= activeJobMesList?.data?.length ? true : false} data={activeJobMesList?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</div>
)
}
+131 -666
View File
@@ -1,692 +1,157 @@
import React, { useEffect, useState, useRef } from "react";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import Layout from "../Partials/Layout";
import { useNavigate } from "react-router-dom";
import ActiveJobMessage from "./ActiveJobMessage";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import CountDown from "../Helpers/CountDown";
import IndexJobActions from "./JobActions/IndexJobActions";
import ModalCom from "../Helpers/ModalCom";
import { useReactToPrint } from "react-to-print";
import usersService from "../../services/UsersService";
function ActiveJobs(props) {
const ApiCall = new usersService();
let navigate = useNavigate();
import Layout from "../Partials/Layout";
import { useLocation, useNavigate } from "react-router-dom";
function ActiveJobs() {
let { userDetails } = useSelector((state) => state.userDetails);
let navigate = useNavigate()
let {state} = useLocation()
let [passDue, setPassDue] = useState(
new Date() > new Date(props.details?.delivery_date)
); // STATE TO KNOW IF TASK IS PASSED DUE TIME
let [details, setDetails] = useState({})
let [messageToSend, setMessageToSend] = useState(""); // State to hold the value of message to be sent
// console.log(state, userDetails);
let [filesToSend, setFilesToSend] = useState([]); // State to hold the value of files to be sent
let [tab, setTab] = useState("message");
let [requestStatus, setRequestStatus] = useState({
loading: false,
status: false,
message: "",
});
let [popUp, setPopUp] = useState(false); // STATE FOR POPOUT MODAL
const printRef = useRef();
// to handle printing
const handlePrint = useReactToPrint({
content: () => printRef.current,
});
const popUpHandler = () => {
// FUNCTION TO HANDLE POPOUT
setPopUp((prev) => !prev);
};
// FUNCTION TO HANDLE MESSAGE CHANGE
const handleMessageChange = ({ target: { value } }) => {
setMessageToSend(value);
};
// FUNCTION TO HANDLE FILE UPlOAD CHANGE
const handleFileChange = ({ target: { files } }) => {
setRequestStatus({ loading: false, status: false, message: "" }); // State to determine error state
if (!files[0]) {
// IF NO FILE SELECTED RETURN
return;
useEffect(()=>{
if(!state){
navigate('/my-active-jobs', {replace: true})
}
if (files[0].size > Number(process.env.REACT_APP_MAX_FILE_SIZE)) {
setRequestStatus({
loading: false,
status: false,
message: "File must be <= 1mb",
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
}
if (filesToSend.length >= Number(process.env.REACT_APP_TOTAL_NUM_FILE)) {
setRequestStatus({
loading: false,
status: false,
message: `Total number of attachment is ${Number(
process.env.REACT_APP_TOTAL_NUM_FILE
)}`,
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
}
// INCLUDE FILE IF NO ERROR
setFilesToSend((prev) => [...prev, files[0]]);
};
// FUNCTION TO CLEAR ALL TYPED MESSAGE OR FILES
const handleClearAll = ({ target: { name } }) => {
if (tab == "message") {
setMessageToSend("");
} else if (tab == "files") {
setFilesToSend([]);
} else {
return;
}
};
// FUNCTION TO REMOVE AND IMAGE
const handleRemoveImage = (imageToDelete) => {
setFilesToSend((prev) =>
prev.filter((item) => item.name != imageToDelete.name)
);
};
// FUNCTION TO SEND TASK MESSAGE
const sendTaskMessage = () => {
let reqData = {
message: messageToSend,
msg_type: "TEXT",
contract: props.details.contract,
};
if (!reqData.message) {
setRequestStatus({
loading: false,
status: false,
message: "Message is empty",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
setRequestStatus({ loading: true, status: false, message: "" });
ApiCall.sendTaskMessage(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
setRequestStatus({
loading: false,
status: false,
message: "Message could not be sent, try again later",
});
return;
}
setRequestStatus({
loading: false,
status: true,
message: "Message Sent Successfully",
});
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
})
.catch((error) => {
setRequestStatus({
loading: false,
status: false,
message: "Opps! something went wrong",
});
})
.finally(() => {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
// FUNCTION TO SEND FILES
const sendFile = async () => {
setRequestStatus({ loading: true, status: false, message: "" });
if (!filesToSend.length) {
// checks if file to send is empty
setRequestStatus({
loading: false,
status: false,
message: "No File(s) selected",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
for (let i = 0; i <= filesToSend.length - 1; i++) {
// Loops through files to send array and trigger upload API call
const fileToBase64 = async () => {
// Converts file data to base64 string
try {
const base64String = await convertFileToBase64(filesToSend[i]);
return base64String;
} catch (error) {
return false;
}
};
// if(await !fileToBase64()){
// return
// }
let reqData = {
file_name: filesToSend[i].name,
file_size: filesToSend[i].size,
file_type: "image/png",
file_data: await fileToBase64(),
msg_type: "FILE",
contract: props.details.contract,
};
ApiCall.sendFiles(reqData)
.then((res) => {
// if(res.status != 200 || res.data.internal_return < 0){
// setRequestStatus({loading: false, status: false, message: 'Files(s) could not be sent, try again later'})
// return
// }
// setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'})
// props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
// setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
})
.catch((error) => {
// setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'})
})
.finally(() => {
if (i == filesToSend.length - 1) {
setRequestStatus({
loading: false,
status: true,
message: "File(s) Uploaded Successfully",
});
setFilesToSend([]); // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
});
}
};
// FUNCTION TO CHECK IF TASK PASS DUE IS REACHED
let isPassedDue = () => {
// console.log('TESTING',new Date() > new Date(props.details?.delivery_date) )
if (new Date() > new Date(props.details?.delivery_date)) {
setPassDue(true);
} else {
setPassDue(false);
}
};
useEffect(() => {
if (!passDue) {
let passDueInterval = setInterval(() => {
isPassedDue();
}, 1000);
return () => {
clearInterval(passDueInterval);
};
}
}, [passDue]);
console.log("AC JOBS >>", props);
setDetails(state)
},[])
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">
{/* job title */}
<div className="w-full md:w-8/12">
<div className="w-full flex justify-start space-x-3 items-start">
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() =>{
if(props.details.pathname == '/manage-family'){
navigate(props.details.pathname, {state: { ...props.details.accountDetails }}, { replace: true })
}else{
navigate(props.details.pathname, { replace: true })
}
}
}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-xl lg:text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
{props.details?.title && props.details.title}
</h1>
</div>
{/* <div className="logout-modal-wrapper min-w-[850px] h-full lg:h-auto lg:rounded-2xl overflow-y-auto"> */}
<div className="w-full my-2">
<p className="w-full text-base text-right text-sky-blue">
{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="p-2 border border-sky-blue">
{props?.details && props.details.description}
</p>
</div>
</div>
</div>
{/* end of job title */}
{/* job details */}
<div className="w-full md:w-4/12">
<p className="text-base text-sky-blue">Delivery Detail</p>
{passDue ? (
<div className="my-1">
<p className="text-base text-slate-700">
<span className="font-semibold">Due: </span>
{props?.details && props.details.delivery_date.split(" ")[0]}
</p>
<p className="py-2 text-base text-slate-700">
{props?.delivery_date &&
props.details.delivery_date.split(" ")[1]}
</p>
</div>
) : (
<div className="my-1 flex items-start gap-3">
<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 && props.details.delivery_date}
/>
</p>
<div className="text-base text-slate-700 tracking-wide flex gap-[5px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</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">
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="">
{props.details?.contract && props.details.contract}
</span>
</div>
</div>
{/* end of job details */}
</div>
<div className="my-4 py-[20px] bg-white dark:bg-black px-4 rounded-2xl shadow-md lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0">
<div className="w-full lg:w-1/2">
<div className="">
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
Actions
</h1>
{/* <p className="my-3 py-1 text-base">
Waiting for the completion message from the client before you can approve.
</p> */}
<IndexJobActions details={props.details} />
</div>
{/* TEXTAREA SECTION */}
<div className="mt-5">
<div className="">
{/* <p className="relative py-2 my-2 text-lg font-bold text-slate-600 dark:text-black border-b-2 border-slate-300 tracking-wide after:absolute after:-bottom-0.5 after:content-[''] after:w-[100px] after:h-[2px] after:bg-sky-blue after:left-0">Message(s)</p> */}
<div className="my-2 flex items-center border-b border-slate-300">
<button
name="message"
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "message" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
>
Send Message
</button>
<button
name="files"
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
tab == "files" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
>
Send Files
</button>
</div>
{tab == "message" ? (
<textarea
className="p-4 w-full h-[300px] text-base text-slate-600 dark:text-white bg-white dark:bg-black border border-slate-300 outline-none"
// rows="10"
style={{ resize: "none" }}
name="message"
onChange={handleMessageChange}
value={messageToSend}
/>
) : (
<div className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300">
<div className="files">
<label
htmlFor="file"
className="h-20 btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
>
Select Files to Upload
</label>
<input
type="file"
id="file"
accept="image/*"
style={{ display: "none" }}
onChange={handleFileChange}
/>
</div>
<div className="selected_file my-2">
{filesToSend.length > 0 &&
filesToSend.map((item, index) => (
<p key={index} className="flex items-center space-x-2">
<span>{item.name}</span>
<button
name="remove"
onClick={() => handleRemoveImage(item)}
className="px-2 flex justify-center items-center rounded-full border border-red-500 text-red-500"
>
x
</button>
</p>
))}
</div>
</div>
)}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
{/* Buttons Sections */}
<div className="py-2 sm:flex sm:justify-end sm:items-center">
<div className="w-full sm:w-2/4 flex justify-between items-center space-x-2">
<div className="p-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0 rounded-lg shadow-lg bg-slate-100">
<div className="w-full lg:w-3/4">
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
{/* back btn and title */}
<div className="w-full flex justify-start space-x-3 items-center">
<button
type="button"
onClick={handleClearAll}
className="border-gradient text-base tracking-wide px-4 py-3 rounded-full"
className="text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() => navigate('/my-active-jobs', {replace: true})}
>
<span className="text-gradient">Clear</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
{tab == "files" ? (
<button
onClick={sendFile}
type="button"
className="btn-gradient text-base tracking-wide px-4 py-3 rounded-full flex justify-center items-center"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
fill="white"
>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z" />
</svg>
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
{details.title && details.title}
</h1>
</div>
{/* END of back btn and title */}
<span className="text-white">Upload Files</span>
</>
)}
</button>
) : (
<button
onClick={sendTaskMessage}
type="button"
className="btn-gradient text-base text-white tracking-wide px-4 py-3 rounded-full"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<span className="text-white">Send</span>
)}
</button>
)}
<div className="mt-2 w-full lg:flex lg:justify-between lg:items-center lg:space-x-2">
<div className="my-2 lg:my-0">
<p className="text-base text-slate-700 dark:text-black">
{details.contract && details.contract}
</p>
<p className="text-base text-slate-700 dark:text-black">
<span className="font-semibold">Description: </span>
{details.description && details.description}
</p>
<p className="text-base text-sky-blue">Delivery Detail</p>
</div>
<div className="">
<p className="text-base text-sky-blue">
{userDetails.firstname && userDetails.firstname}
</p>
<p className="text-base text-slate-700 dark:text-black">
<span className="font-semibold">Due: </span>
{details.delivery_date &&
details.delivery_date.split(" ")[0]}
</p>
<p className="text-base text-slate-700 dark:text-black">
{details.delivery_date &&
details.delivery_date.split(" ")[1]}
</p>
<p className="text-base text-slate-700 dark:text-black">
{details.timeline_days && details.timeline_days} day(s)
</p>
</div>
</div>
</div>
{/* end of Buttons Sections */}
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
<div className="">
<p className="text-lg font-bold text-slate-600 dark:text-blask tracking-wide">Message(s)</p>
<textarea
className="p-4 w-full text-base text-slate-600 border border-slate-300 outline-none rounded-md"
rows="10"
style={{ resize: "none" }}
/>
</div>
{/* Buttons Sections */}
<div className="py-2 mb-8 sm:flex sm:justify-center sm:items-center">
<div className="w-full sm:w-3/4 mb-5 sm:mb-0">
<button
onClick={()=> console.log('working')}
type="button"
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-md flex justify-center items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill='white'>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z"/>
</svg>
<span className="text-white">Upload Files</span>
</button>
</div>
<div className="w-full sm:w-1/4 flex justify-between items-center space-x-2">
<button
type="button"
className="bg-red-600 text-base text-white tracking-wide px-4 py-2 rounded-md hover:opacity-90"
>
<span className="text-white">Clear</span>
</button>
<button
type="button"
className="btn-gradient text-base text-white tracking-wide px-4 py-2 rounded-md"
>
<span className="text-white">Send</span>
</button>
</div>
</div>
{/* end of Buttons Sections */}
</div>
</div>
{/* ACTION SECTION */}
<div className="w-full lg:w-1/4 h-full">
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">Actions</h1>
<p className="my-3 py-1 text-base">
Waiting for the completion message from the client before you can approve.
</p>
</div>
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
<div className="">
<p className="text-lg font-bold text-dark-gray dark:text-black tracking-wide">Message</p>
<textarea
className="p-4 w-full text-base text-slate-600 border border-slate-300 outline-none rounded-md"
rows="10"
style={{ resize: "none" }}
/>
</div>
</div>
</div>
{/* END OF TEXTAREA */}
</div>
{/* MESSAGE SECTION */}
<div className="w-full lg:w-1/2">
<div className="flex justify-between items-center gap-5">
<p className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
Message
</p>
<button
type="button"
onClick={popUpHandler}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
view all
</button>
</div>
{props.activeJobMesList.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<ActiveJobMessage activeJobMesList={props.activeJobMesList} />
)}
</div>
{/* END OF MESSAGE */}
</div>
{/* POPOUT SECTION */}
{popUp && (
<PopModal
popUpHandler={popUpHandler}
popUp={popUp}
details={props.details}
activeJobMesList={props.activeJobMesList}
handlePrint={handlePrint}
myRef={printRef}
/>
)}
{/* END OF POPOUT SECTION */}
{/* </div> */}
</Layout>
);
}
export default ActiveJobs;
function convertFileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const base64String = reader.result.split(",")[1];
resolve(base64String);
};
reader.onerror = (error) => {
reject(error);
};
reader.readAsDataURL(file);
});
}
//POPOUT COMPONENT FUNCTION
const PopModal = ({
popUpHandler,
popUp,
details,
activeJobMesList,
handlePrint,
myRef,
}) => {
return (
<ModalCom action={popUpHandler} situation={popUp} className="edit-popup">
<div
ref={myRef}
className="message-modal-wrapper min-w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl"
>
<div className="message-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{details?.contract}
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={popUpHandler}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="job-action-modal-body w-full px-10 py-8 gap-4">
<div className="w-full flex flex-col items-center">
{activeJobMesList.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<div className="message-table h-[500px] overflow-y-auto">
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className="border-b-2">
<tr className="text-slate-600">
<th className="p-2"></th>
</tr>
</thead>
{activeJobMesList?.data?.length ? (
<tbody>
{activeJobMesList?.data?.map((item, index) => (
<tr key={index} className="text-slate-500">
<td>
<div className="msg_box">
<div className="msg_header">
{item.msg_date} {item.msg_firstname}
</div>
<span
className="p-2"
dangerouslySetInnerHTML={{
__html: item.message,
}}
></span>
</div>
</td>
</tr>
))}
</tbody>
) : activeJobMesList.error ? (
<tbody>
<tr className="text-slate-500">
<td className="p-2" colSpan={4}>
Opps! an error occurred. Please try again!
</td>
</tr>
</tbody>
) : (
<tbody>
<tr className="text-slate-500">
<td className="p-2" colSpan={4}>
No Message Found!
</td>
</tr>
</tbody>
)}
</table>
</div>
)}
</div>
{/* btn */}
<div className="flex justify-end items-center">
<div className="py-3 w-full lg:w-1/2 flex justify-between items-center">
<button
onClick={handlePrint}
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<span className="text-white">Print</span>
</button>
<button
onClick={popUpHandler}
type="button"
className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white"
>
<span className="text-gradient">Cancel</span>
</button>
</div>
</div>
</div>
</div>
</ModalCom>
);
};
@@ -1,33 +0,0 @@
import React from 'react'
function CurrentJobAction() {
return (
<div className='job-action bg-white dark:bg-black'>
<p className="my-3 py-1 text-base active-owner">
<table className="w-full text-sm text-left text-gray-500">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<h1 className="text-xl text-dark-gray dark:text-white">
Waiting for the completion message from the client before you can approve.
</h1>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</td>
<td className="text-right py-4 px-2">
<div className="flex justify-center items-center">
.
</div>
</td>
</tr>
</tbody>
</table>
</p>
</div>
)
}
export default CurrentJobAction
@@ -1,182 +0,0 @@
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import ModalCom from '../../Helpers/ModalCom'
import LoadingSpinner from '../../Spinners/LoadingSpinner'
import usersService from '../../../services/UsersService'
function CurrentTaskAction({jobDetails}) {
const apiCall = new usersService()
const navigate = useNavigate()
const [checked, setChecked] = useState(false)
const [reqStatus, setReqStatus] = useState({loading:false, status: false, message: ''})
let [popUp, setPopUp] = useState(false)
const popUpHandler = () => {
if(popUp){
setChecked(false)
}
setPopUp(prev => !prev)
}
// FUNCTION TO HANDLE WHEN USER CLICKS ON SEND FOR REVIEW AND ACCEPTANCE
const taskCompletedSubmit = () => {
setReqStatus({loading:true, status: false, message: ''}) // Sets loading spinner active
let reqData = {
contract: jobDetails.contract,
contract_uid: jobDetails.contract_uid,
job_action: 'NOTIFY_COMPLETE',
}
if(!checked){ // checks that checkbox is selected
setReqStatus({loading:false, status: false, message: 'Please check the box above'})
return setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
}
// API CALL TO MARK TASK AS COMPLETED BY WORKER
apiCall.workerJobAction(reqData).then((res)=>{
if(res.status != 200 || res.data.internal_return < 0){
setReqStatus({loading:false, status: false, message: 'unable to complete request. Try again'})
return
}
setReqStatus({loading:false, status: true, message: 'Task marked completed successfully'})
setTimeout(()=>{ // Sets popout to false and navigates user to /mytask after 3 seconds
popUpHandler()
navigate('/mytask', {replace: true})
}, 3000)
}).catch(err => {
setReqStatus({loading:false, status: false, message: 'Opps! Network error. Try again'})
}).finally(()=>{
setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
})
}
return (
<div className='job-action bg-white dark:bg-black'>
<table className="w-full text-sm text-left text-gray-500 active-worker">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<h1 className="text-xl text-dark-gray dark:text-white">
I completed this task and ready for review and acceptance.
</h1>
{/*<div className="flex flex-col flex-[0.9]">*/}
{/*</div>*/}
</div>
</td>
</tr>
<tr>
<td>
<div className="flex justify-center items-center">
<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>
</td>
</tr>
</tbody>
</table>
{popUp && (
<ModalCom action={popUpHandler} situation={popUp}>
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Confirm Completion
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={popUpHandler}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="job-action-modal-body w-full px-10 py-8 gap-4">
<div className="w-full flex flex-col items-center">
<div className="mb-10 flex justify-center items-center gap-2">
<input
type='checkbox'
checked={checked}
onChange={()=>{setChecked(prev => !prev)}}
className='w-6 h-6 text-sky-blue bg-gray-100 focus:ring-sky-blue'
/>
<p className='font-bold text-base tracking-wide text-dark-gray dark:text-white'>If you have completed this task</p>
</div>
<div className="mb-10 flex justify-center items-center">
{reqStatus.loading ?
<LoadingSpinner color='sky-blue' size='10' />
:
<button type="button" onClick={taskCompletedSubmit} className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Send for Review & Acceptance
</button>
}
</div>
{/* FOR SUCCESS/ERROR DISPLAY SECTION*/}
<div className="w-full">
{reqStatus.message != "" &&
(!reqStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
) : (
reqStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
)
))}
</div>
{/* END OF FOR SUCCESS/ERROR DISPLAY SECTION*/}
</div>
{/* cancel btn */}
<div className='flex justify-end items-center'>
<button onClick={popUpHandler} type="button" className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<span className='text-gradient'>Cancel</span>
</button>
</div>
</div>
</div>
</ModalCom>
)}
</div>
)
}
export default CurrentTaskAction
@@ -1,45 +0,0 @@
import React from 'react'
import CurrentJobAction from './CurrentJobAction'
import CurrentTaskAction from './CurrentTaskAction'
import PastDueJobAction from './PastDueJobAction'
import PastDueTaskAction from './PastDueTaskAction'
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
switch(owner) {
case 'OWNER':
return (()=>{
if(description == 'ACTIVE'){
return <CurrentJobAction jobDetails={details} />
}else if(description == 'PASTDUE'){
return <PastDueJobAction jobDetails={details} />
}else if(description == 'REVIEW'){
return <ReviewJobAction jobDetails={details} />
} else {
return null
}
})()
case 'WORKER':
return (()=>{
if(description == 'ACTIVE'){
return <CurrentTaskAction jobDetails={details} />
}else if(description == 'PASTDUE'){
return <PastDueTaskAction jobDetails={details} />
}else if(description == 'REVIEW'){
return <ReviewTaskAction jobDetails={details} />
} else {
return null
}
})()
default:
return null
}
}
export default IndexJobActions
@@ -1,246 +0,0 @@
import React,{useState} from 'react'
import ModalCom from '../../Helpers/ModalCom'
import LoadingSpinner from '../../Spinners/LoadingSpinner'
import { useNavigate } from 'react-router-dom'
import usersService from '../../../services/UsersService'
function PastDueJobAction({jobDetails}) {
const apiCall = new usersService()
const navigate = useNavigate()
const [checked, setChecked] = useState(false)
const [extendedTime, setExtendedTime] = useState('') // VALUE OF NEW EXTENDED TIME
const [action, setAction] = useState('') // VALUE OF NEW EXTENDED TIME
const [reqStatus, setReqStatus] = useState({loading:false, status: false, message: ''})
let [popUp, setPopUp] = useState(false)
const popUpHandler = () => {
if(popUp){
setChecked(false)
}
setPopUp(prev => !prev)
}
// FUNCTION TO HANDLE WHEN OWNER CANCELS JOB
const cancelTask = () => {
setAction('cancel')
setReqStatus({loading:true, status: false, message: ''})
let reqData = { // API PAYLOADS
contract: jobDetails.contract,
contract_uid: jobDetails.contract_uid,
job_action: 'REQUEST_CANCEL',
}
if(!checked){ // CHECKS IF CHECKBOX IS SELECTED
setReqStatus({loading:false, status: false, message: 'Please check the box above'})
return setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
}
// API CALL TO ACCEPT COMPLETION BY OWNER
apiCall.ownerJobAction(reqData).then((res)=>{
if(res.status != 200 || res.data.internal_return < 0){
setReqStatus({loading:false, status: false, message: 'unable to complete request. Try again'})
return
}
setReqStatus({loading:false, status: true, message: 'job cancelled successfully'})
setTimeout(()=>{ // Sets popout to false and navigates user to /my-pastdue-jobs after 3 seconds
popUpHandler()
navigate('/my-pastdue-jobs', {replace: true})
}, 3000)
}).catch(err => {
setReqStatus({loading:false, status: false, message: 'Opps! Network error. Try again'})
}).finally(()=>{
setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
})
}
// FUNCTION TO HANDLE WHEN USER/OWNER CLICKS ON EXTEND TIMELINE FOR A JOB
const extendTime = () => {
setAction('extend')
setReqStatus({loading:true, status: false, message: ''}) // Sets loading spinner active
let reqData = {
contract: jobDetails.contract,
contract_uid: jobDetails.contract_uid,
job_action: 'EXTEND_TIMELINE',
extension: Number(extendedTime)
}
if(!extendedTime){ // checks that timeline duration is selected
setReqStatus({loading:false, status: false, message: 'Please select timeline duration'})
return setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
}
// API CALL EXTEND TIMELINE BY OWNER
apiCall.ownerJobAction(reqData).then((res)=>{
if(res.status != 200 || res.data.internal_return < 0){
setReqStatus({loading:false, status: false, message: 'unable to complete request. Try again'})
return
}
setReqStatus({loading:false, status: true, message: 'Timeline extended successfully'})
setTimeout(()=>{ // Sets popout to false and navigates user to /my-pastdue-jobs after 3 seconds
popUpHandler()
navigate('/my-pastdue-jobs', {replace: true})
}, 3000)
}).catch(err => {
setReqStatus({loading:false, status: false, message: 'Opps! Network error. Try again'})
}).finally(()=>{
setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
})
}
return (
<div className='job-action bg-white dark:bg-black'>
<table className="w-full text-sm text-left text-gray-500 owner-pastdue">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<h1 className="text-xl text-dark-gray dark:text-white">
Time allocated has passed
</h1>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</td>
</tr>
<tr>
<td>
<div className="flex justify-center items-center">
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Cancel or Extend Timeline
</button>
</div>
</td>
</tr>
</tbody>
</table>
{popUp && (
<ModalCom action={popUpHandler} situation={popUp}>
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Past Due Task
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={popUpHandler}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="job-action-modal-body w-full px-10 py-8 gap-4">
<div className="w-full flex flex-col items-center">
<div className="mb-5 flex justify-center items-center gap-2">
<input
type='checkbox'
checked={checked}
onChange={()=>{setChecked(prev => !prev)}}
className='w-6 h-6 text-sky-blue bg-gray-100 focus:ring-sky-blue'
/>
<p className='font-bold text-base tracking-wide text-dark-gray dark:text-white'>I am ready to cancel this task</p>
</div>
<div className="mb-5 flex justify-center items-center">
{reqStatus.loading && action=='cancel'?
<LoadingSpinner color='sky-blue' size='10' />
:
<button disabled={reqStatus.loading} onClick={cancelTask} type="button" className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<span className='text-gradient'>Cancel this task</span>
</button>
}
</div>
{/* EXTEND TIMELINE SECTION */}
<div className='w-full my-3 py-3 border-y flex flex-col items-center'>
<div className='mb-5 flex items-center gap-2'>
<p className='font-bold text-base tracking-wide text-dark-gray dark:text-white'>Extend the timeline by:</p>
<select
onChange={({target})=>{setExtendedTime(target.value)}}
className='text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0'
>
<option className='text-slate-500 text-lg' value=''>select</option>
<option className='text-slate-500 text-lg' value='2'>1 days</option>
<option className='text-slate-500 text-lg' value='3'>3 days</option>
<option className='text-slate-500 text-lg' value='5'>5 days</option>
<option className='text-slate-500 text-lg' value='7'>1 week</option>
</select>
</div>
{reqStatus.loading && action=='extend' ?
<LoadingSpinner color='sky-blue' size='10' />
:
<button disabled={reqStatus.loading} type="button" onClick={extendTime} className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Extend Timeline
</button>
}
</div>
{/* FOR SUCCESS/ERROR DISPLAY SECTION*/}
<div className="w-full">
{reqStatus.message != "" &&
(!reqStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
) : (
reqStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
)
))}
</div>
{/* END OF FOR SUCCESS/ERROR DISPLAY SECTION*/}
</div>
{/* cancel btn */}
<div className='flex justify-end items-center'>
<button onClick={popUpHandler} type="button" className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<span className='text-gradient'>Cancel</span>
</button>
</div>
</div>
</div>
</ModalCom>
)}
</div>
)
}
export default PastDueJobAction
@@ -1,35 +0,0 @@
import React from 'react'
function PastDueTaskAction() {
return (
<div className='job-action bg-white dark:bg-black'>
<table className="w-full text-sm text-left text-gray-500 worker-pastdue">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<h1 className="text-xl text-dark-gray dark:text-white">
You have missed the allocated time
</h1>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</td>
</tr>
<tr>
<td>
<div className="flex justify-center items-center">
<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>
</td>
</tr>
</tbody>
</table>
</div>
)
}
export default PastDueTaskAction
@@ -1,226 +0,0 @@
import React,{useState} from 'react'
import ModalCom from '../../Helpers/ModalCom'
import LoadingSpinner from '../../Spinners/LoadingSpinner'
import { useNavigate } from 'react-router-dom'
import usersService from '../../../services/UsersService'
function ReviewJobAction({jobDetails}) {
const apiCall = new usersService()
const navigate = useNavigate()
const [checked, setChecked] = useState(false)
const [action, setAction] = useState('') // VALUE OF NEW EXTENDED TIME
const [reqStatus, setReqStatus] = useState({loading:false, status: false, message: ''})
let [popUp, setPopUp] = useState(false)
const popUpHandler = () => {
if(popUp){
setChecked(false)
}
setPopUp(prev => !prev)
}
// FUNCTION TO HANDLE WHEN OWNER ACCEPTS COMPLETION OF JOB
const acceptCompletion = () => {
setAction('accept')
setReqStatus({loading:true, status: false, message: ''})
let reqData = { // API PAYLOADS
contract: jobDetails.contract,
contract_uid: jobDetails.contract_uid,
job_action: 'ACCEPT_COMPLETE',
}
if(!checked){ // CHECKS IF CHECKBOX IS SELECTED
setReqStatus({loading:false, status: false, message: 'Please check the box above'})
return setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
}
// API CALL TO ACCEPT COMPLETION BY OWNER
apiCall.ownerJobAction(reqData).then((res)=>{
if(res.status != 200 || res.data.internal_return < 0){
setReqStatus({loading:false, status: false, message: 'unable to complete request. Try again'})
return
}
setReqStatus({loading:false, status: true, message: 'job completion accepted successfully'})
setTimeout(()=>{ // Sets popout to false and navigates user to /my-review-jobs after 3 seconds
popUpHandler()
navigate('/my-review-jobs', {replace: true})
}, 3000)
}).catch(err => {
setReqStatus({loading:false, status: false, message: 'Opps! Network error. Try again'})
}).finally(()=>{
setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
})
}
// FUNCTION TO HANDLE WHEN USER/OWNER CLICKS ON REJECT COMPLETION OF JOB
const rejectCompletion = () => {
setAction('reject')
setReqStatus({loading:true, status: false, message: ''}) // Sets loading spinner active
let reqData = { // API PAYLOADS
contract: jobDetails.contract,
contract_uid: jobDetails.contract_uid,
job_action: 'REJECT_COMPLETE',
}
// API CALL TO REJECT COMPLETION BY OWNER
apiCall.ownerJobAction(reqData).then((res)=>{
if(res.status != 200 || res.data.internal_return < 0){
setReqStatus({loading:false, status: false, message: 'unable to complete request. Try again'})
return
}
setReqStatus({loading:false, status: true, message: 'job completion rejected successfully'})
setTimeout(()=>{ // Sets popout to false and navigates user to /my-review-jobs after 3 seconds
popUpHandler()
navigate('/my-review-jobs', {replace: true})
}, 3000)
}).catch(err => {
setReqStatus({loading:false, status: false, message: 'Opps! Network error. Try again'})
}).finally(()=>{
setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''})
}, 3000)
})
}
return (
<div className='job-action bg-white dark:bg-black'>
<div className="my-3 py-1 text-base">
<table className="w-full text-sm text-left text-gray-500 review-owner">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full">
<h1 className="text-xl text-dark-gray dark:text-white">
This Job is Ready for your review
</h1>
{/*<div className="flex flex-col flex-[0.9]"> </div>*/}
</div>
</td>
</tr>
<tr>
<td>
<div className="flex justify-center items-center">
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Reject or Accept
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
{popUp && (
<ModalCom action={popUpHandler} situation={popUp}>
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Completion
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={popUpHandler}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="job-action-modal-body w-full px-10 py-8 gap-4">
<div className="w-full flex flex-col items-center">
<div className="mb-5 flex justify-center items-center gap-2">
<input
type='checkbox'
checked={checked}
onChange={()=>{setChecked(prev => !prev)}}
className='w-6 h-6 text-sky-blue bg-gray-100 focus:ring-sky-blue'
/>
<p className='font-bold text-base tracking-wide text-dark-gray dark:text-white'>I am ready to accept completion</p>
</div>
<div className="mb-5 flex justify-center items-center">
{reqStatus.loading && action=='accept'?
<LoadingSpinner color='sky-blue' size='10' />
:
<button disabled={reqStatus.loading} onClick={acceptCompletion} type="button" className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<span className='text-gradient'>Accept Completion</span>
</button>
}
</div>
{/* EXTEND TIMELINE SECTION */}
<div className='w-full my-3 py-3 border-y flex flex-col items-center'>
<div className='mb-5 flex items-center gap-2'>
<p className='font-bold text-base tracking-wide text-dark-gray dark:text-white'>I am not ready to accept completion of task</p>
</div>
{reqStatus.loading && action=='reject' ?
<LoadingSpinner color='sky-blue' size='10' />
:
<button disabled={reqStatus.loading} type="button" onClick={rejectCompletion} className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Reject Completion
</button>
}
</div>
{/* FOR SUCCESS/ERROR DISPLAY SECTION*/}
<div className="w-full">
{reqStatus.message != "" &&
(!reqStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
) : (
reqStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
)
))}
</div>
{/* END OF FOR SUCCESS/ERROR DISPLAY SECTION*/}
</div>
{/* cancel btn */}
<div className='flex justify-end items-center'>
<button onClick={popUpHandler} type="button" className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<span className='text-gradient'>Cancel</span>
</button>
</div>
</div>
</div>
</ModalCom>
)}
</div>
)
}
export default ReviewJobAction
@@ -1,13 +0,0 @@
import React from 'react'
function ReviewTaskAction() {
return (
<div className='job-action bg-white dark:bg-black'>
<p className="my-3 py-1 text-base text-dark-gray dark:text-white">
Waiting for the completion message from the client before you can approve. Worker True & Review Job
</p>
</div>
)
}
export default ReviewTaskAction
@@ -1,13 +1,16 @@
import React, { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import { useNavigate } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function MyActiveJobTable({ MyJobList, className }) {
const navigate = useNavigate();
let { pathname } = useLocation();
const navigate = useNavigate()
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
@@ -24,7 +27,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
@@ -40,92 +43,73 @@ export default function MyActiveJobTable({ MyJobList, className }) {
{
<>
{MyJobList &&
MyJobList?.result_list &&
MyJobList.result_list.length > 0 ? (
currentActiveJobList.map((value, index) => {
let deliveryDate = value?.delivery_date?.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 flext-start gap-1">
Price:{" "}
<span className="text-purple">
{thePrice}
</span>
MyJobList?.result_list &&
MyJobList.result_list.length > 0 &&
currentActiveJobList.map((value, index) => (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray">
Price:{" "}
<span className="text-purple">
{value.price * 0.01}
</span>
<div className="flex gap-4 items-center">
<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">
Due:{" "}
<span className="text-purple">
{" "}
{deliveryDate}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Sent to:{" "}
<span className="text-purple">
{" "}
{value.job_to === null
? "public"
: value.job_to}
</span>
</span>
</div>
</div>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire:{" "}
<span className="text-purple">
{" "}
{value.expire}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Send to:{" "}
<span className="text-purple">
{" "}
{value.job_to}
</span>
</span>
</div>
</td>
</div>
</td>
<td className="text-right py-4 px-2">
<div className="flex justify-center items-center">
<button
type="button"
onClick={() => {
navigate("/manage-active-job", {
state: { ...value, pathname },
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</div>
</td>
</tr>
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Active Task!</td>
</tr>
)}
<td className="text-right py-4 px-2">
<div className="flex justify-center items-center">
<button
type="button"
onClick={() => {
navigate('/manage-active-job', {state:value});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</div>
</td>
</tr>
))}
</>
}
</tbody>
@@ -1,40 +0,0 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import MyActiveJobTable from "./MyActiveJobTable";
export default function MyPastDueJobs(props) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
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"}`}
>
Pass Due Job(s)
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div>
<MyActiveJobTable MyJobList={props.MyJobList} />
</div>
</div>
</Layout>
);
}
@@ -1,42 +0,0 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import MyActiveJobTable from "./MyActiveJobTable";
export default function MyReviewDueJobs(props) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
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"}`}
>
Review Due Job(s)
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div>
<MyActiveJobTable MyJobList={props.MyJobList} />
</div>
</div>
</Layout>
);
}

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