Compare commits
168 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c64d372193 | |||
| abff42e0a8 | |||
| d5c342a57a | |||
| 60d6629526 | |||
| b1fbf89f10 | |||
| ae346d5ac5 | |||
| 75b5102766 | |||
| 9b12ffe0cd | |||
| 408165e718 | |||
| f7a0594447 | |||
| c733b006fb | |||
| 5a6b60578e | |||
| cdd998235e | |||
| 6e9efd7f43 | |||
| 07e9520774 | |||
| c1600a2a13 | |||
| 58e1745ac5 | |||
| 35db4fe536 | |||
| dfdbf404a5 | |||
| 985afa3c7b | |||
| 70d82d89b3 | |||
| 7f5eccb3b7 | |||
| 6729b780bd | |||
| 06224f121a | |||
| dc91649114 | |||
| 22f6eb436d | |||
| f2ab0cd6c9 | |||
| a2819786ae | |||
| 6cd92f6372 | |||
| 7173901c9b | |||
| 380d014964 | |||
| 9032b36b13 | |||
| f291382786 | |||
| 69dcee859d | |||
| fe295dc775 | |||
| 044c8edf7d | |||
| c22cffd167 | |||
| 6d77bfa1b0 | |||
| 60cc6f375e | |||
| e6684c56fd | |||
| 4f675b30ef | |||
| 00c7f65092 | |||
| 9a978b1913 | |||
| 23f8346734 | |||
| 585632c1e1 | |||
| 11ee1195c2 | |||
| c44f456cc1 | |||
| b769e4a4ba | |||
| a6ff06e2b4 | |||
| 0f801b2408 | |||
| c26f2b725a | |||
| ee94cbc92c | |||
| dccbe76c5b | |||
| 735d13b440 | |||
| 7f83cd5cc6 | |||
| 71ee75072d | |||
| 265f2b7655 | |||
| 4d264fa18e | |||
| cd6ab8b504 | |||
| 8c81073443 | |||
| 14566de037 | |||
| 69d711eddc | |||
| 159623eb69 | |||
| da26d5c24a | |||
| 40850b7342 | |||
| 28098169b9 | |||
| 2ff6ed777f | |||
| 723a2a09ab | |||
| 68482c7956 | |||
| 225e3ae34c | |||
| 251d5abf10 | |||
| 22314a61c5 | |||
| a9cf3c9d22 | |||
| 01bf8a4c52 | |||
| 68ab094bf6 | |||
| d938202f7a | |||
| c9f66bdacb | |||
| 5854ad194a | |||
| 0f25a92b88 | |||
| 9d7bcd91f4 | |||
| 68115e79fa | |||
| de379c2bbc | |||
| 2c11a0755d | |||
| f4ed892c5c | |||
| 30403f27c5 | |||
| cf2df7529d | |||
| b3695324b3 | |||
| cf8f32ed64 | |||
| bd59f26146 | |||
| 3a397aad86 | |||
| 0f548e216d | |||
| 50fd9711e0 | |||
| f4d9eb65c6 | |||
| 774224ba6d | |||
| 9eae733755 | |||
| 0aee3b9d6f | |||
| b676a2a4f3 | |||
| 0baacb3057 | |||
| 9737c02d45 | |||
| 1048e51ddf | |||
| 6545c32326 | |||
| 6ea9078848 | |||
| 735cc0b296 | |||
| 29e058828b | |||
| 5d5542c221 | |||
| b59f92c89f | |||
| e01bfa369b | |||
| 3d150f7a6b | |||
| bbd100d04e | |||
| fcb340007c | |||
| 95a10cf795 | |||
| 5b5a083987 | |||
| 1564f29a4c | |||
| 2b73191741 | |||
| fee5c20fe2 | |||
| 2d2b184291 | |||
| 5abd3665d1 | |||
| a603a9eaff | |||
| 5bd74b3ca4 | |||
| 60cc290004 | |||
| 12f30ec1e8 | |||
| 2521fbc1d8 | |||
| 29812e9265 | |||
| 271180932c | |||
| 0a2e291013 | |||
| 8be09a9f9f | |||
| 78aa4fe58b | |||
| 154ea29504 | |||
| 4f670fa3ba | |||
| 8d48435705 | |||
| 76109dc458 | |||
| 05a7b3ec12 | |||
| 0a3805ddf8 | |||
| 059fdaf294 | |||
| 353c372284 | |||
| 26e5248a0f | |||
| ae6a677b25 | |||
| cab5debfb7 | |||
| c4c1bf6ca1 | |||
| fc2a78dde7 | |||
| 1249685c41 | |||
| 3c422d9036 | |||
| 264511dfb2 | |||
| d8c5b3ff07 | |||
| 624f97df8d | |||
| 4dfb442a80 | |||
| 50f675e82b | |||
| a0584a26fe | |||
| 0d3025c4d0 | |||
| ed24fea513 | |||
| e6d83be4d9 | |||
| 36e3154933 | |||
| 5d59ff1b30 | |||
| 33832fdd96 | |||
| 9f02395214 | |||
| 9cc88eebf6 | |||
| 2390670d8c | |||
| d908b1e10e | |||
| d91a3bf9f0 | |||
| 880c223834 | |||
| e7bf07d09e | |||
| e1de701ea6 | |||
| 3403210fe8 | |||
| 03a897829c | |||
| d884b2a43d | |||
| 3b86c6cd0e | |||
| 2b5de9c95f | |||
| 3a8a980660 |
@@ -15,6 +15,9 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
|
||||
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"
|
||||
|
||||
#SOCKETS ENDS
|
||||
REACT_APP_PRIMARY_SOCKET="https://socket-dev.wrenchboard.com"
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
@@ -108,4 +111,7 @@ REACT_APP_APPLE_APP='https://itunes.apple.com/us/app/wrenchboard/id1435718367?ls
|
||||
REACT_APP_SHOW_NEW_FAMILY_DASH=1
|
||||
|
||||
# Displays the account dashboard
|
||||
REACT_APP_SHOW_ACCOUNT_DASH=1
|
||||
REACT_APP_SHOW_ACCOUNT_DASH=1
|
||||
|
||||
# Displays the slider banners
|
||||
REACT_APP_SHOW_SLIDER_BANNERS=0
|
||||
+7
-1
@@ -15,6 +15,9 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
|
||||
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"
|
||||
|
||||
#SOCKETS ENDS
|
||||
REACT_APP_PRIMARY_SOCKET="https://socket-dev.wrenchboard.com"
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
@@ -76,4 +79,7 @@ REACT_APP_APPLE_APP='https://itunes.apple.com/us/app/wrenchboard/id1435718367?ls
|
||||
REACT_APP_SHOW_NEW_FAMILY_DASH=1
|
||||
|
||||
# Displays the account dashboard
|
||||
REACT_APP_SHOW_ACCOUNT_DASH=1
|
||||
REACT_APP_SHOW_ACCOUNT_DASH=1
|
||||
|
||||
# Displays the slider banners
|
||||
REACT_APP_SHOW_SLIDER_BANNERS=0
|
||||
+8
-2
@@ -15,6 +15,9 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
|
||||
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"
|
||||
|
||||
#SOCKETS ENDS
|
||||
REACT_APP_PRIMARY_SOCKET="https://socket.wrenchboard.com"
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
@@ -79,7 +82,10 @@ REACT_APP_ANDROID_APP='https://play.google.com/store/apps/details?id=com.wrenchb
|
||||
REACT_APP_APPLE_APP='https://itunes.apple.com/us/app/wrenchboard/id1435718367?ls=1&mt=8'
|
||||
|
||||
# Displays the new family dashboard with boxes
|
||||
REACT_APP_SHOW_NEW_FAMILY_DASH=0
|
||||
REACT_APP_SHOW_NEW_FAMILY_DASH=1
|
||||
|
||||
# Displays the account dashboard
|
||||
REACT_APP_SHOW_ACCOUNT_DASH=0
|
||||
REACT_APP_SHOW_ACCOUNT_DASH=1
|
||||
|
||||
# Displays the slider banners
|
||||
REACT_APP_SHOW_SLIDER_BANNERS=0
|
||||
+3
-2
@@ -21,9 +21,10 @@ services:
|
||||
- backend.wrenchboard.api.live:10.10.33.15
|
||||
- backend.wrenchboard.api.test:10.10.33.15
|
||||
- apigate.lotus.g1.wrenchboard.com:10.10.33.15
|
||||
- apigate.nebula.g1.wrenchboard.com:10.10.33.15
|
||||
- apigate.orion.g1.wrenchboard.com:10.10.33.15
|
||||
# #- backend.wrenchboard.api.live:172.31.4.27
|
||||
# #- backend.wrenchboard.api.test:10.20.30.27
|
||||
- socket-dev.wrenchboard.com:10.10.33.15
|
||||
- socket.wrenchboard.com:10.10.33.15
|
||||
- apigateway.wrenchboard.app.dev.fluxtra.net:10.20.30.19
|
||||
- apigateway.wrenchboard.app.lotus.fluxtra.net:172.31.4.19
|
||||
environment:
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"react-to-print": "^2.14.12",
|
||||
"react-toastify": "^9.0.1",
|
||||
"redux": "^4.2.0",
|
||||
"socket.io-client": "^4.4.1",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"web-vitals": "^1.0.1",
|
||||
"yup": "^1.1.1"
|
||||
|
||||
+11
-8
@@ -2,19 +2,22 @@ import { Navigate, useLocation } from "react-router-dom";
|
||||
import Routers from "./Routers";
|
||||
import Toaster from "./components/Helpers/Toaster";
|
||||
import Default from "./components/Partials/Default";
|
||||
import SocketIOContextProvider from "./components/Contexts/SocketIOContext";
|
||||
|
||||
function App() {
|
||||
const { pathname } = useLocation();
|
||||
return (
|
||||
<Default>
|
||||
<>
|
||||
{pathname.startsWith("/@") ? (
|
||||
<Navigate to="/app" replace={true} />
|
||||
) : (
|
||||
<Routers />
|
||||
)}
|
||||
<Toaster />
|
||||
</>
|
||||
<SocketIOContextProvider>
|
||||
<>
|
||||
{pathname.startsWith("/@") ? (
|
||||
<Navigate to="/app" replace={true} />
|
||||
) : (
|
||||
<Routers />
|
||||
)}
|
||||
<Toaster />
|
||||
</>
|
||||
</SocketIOContextProvider>
|
||||
</Default>
|
||||
);
|
||||
}
|
||||
|
||||
+20
-2
@@ -57,6 +57,15 @@ import VerifyPasswordPagesTwo from "./views/VerifyPasswordPagesTwo";
|
||||
import VerifyYouPages from "./views/VerifyYouPages";
|
||||
import VerifyYouPagesTwo from "./views/VerifyYouPagesTwo";
|
||||
import YourPages from "./views/YourPage_";
|
||||
import ParentWaitingPage from "./views/ParentWaitingPage";
|
||||
import FamilyPendingOfferPage from "./views/FamilyPendingOfferPage";
|
||||
import FamBlogPage from "./views/FamBlogPage"
|
||||
import FamAIQuestionPage from "./views/FamAIQuestionPage"
|
||||
import FamMyFilesPage from "./views/FamMyFilesPage"
|
||||
import FamWorkInProgressPage from "./views/FamWorkInProgressPage";
|
||||
import MyPastDueTasksPage from "./views/MyPastDueTasksPage";
|
||||
import FamilyWalletPage from "./views/FamilyWalletPage";
|
||||
import FamilyActivitiesPage from "./views/FamilyActivitiesPage";
|
||||
|
||||
export default function Routers() {
|
||||
return (
|
||||
@@ -117,23 +126,31 @@ export default function Routers() {
|
||||
<Route exact path="/notification" element={<Notification />} />
|
||||
<Route exact path="/market-place" element={<MarketPlacePage />} />
|
||||
<Route exact path="/shop-details" element={<ShopDetailsPage />} />
|
||||
<Route exact path="/my-wallet" element={<MyWalletPage />} />
|
||||
<Route exact path="/my-collection" element={<MyCollection />} />*/}
|
||||
<Route exact path="/my-collection" element={<MyCollection />} />*/}
|
||||
<Route exact path="/reminders" element={<RemindersPage />} />
|
||||
<Route exact path="/tracking" element={<TrackingPage />} />
|
||||
<Route exact path="/calendar" element={<CalendarPage />} />
|
||||
<Route exact path="/resources" element={<ResourcePage />} />
|
||||
<Route exact path="/my-wallet/*" element={<MyWalletPage />} />
|
||||
<Route exact path="/family-wallet" element={<FamilyWalletPage />} />
|
||||
<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="/suggested" element={<ParentWaitingPage />} />
|
||||
<Route exact path="/pending" element={<FamilyPendingOfferPage />} />
|
||||
<Route exact path="/fam-blog" element={<FamBlogPage />} />
|
||||
<Route exact path="/ai-question" element={<FamAIQuestionPage />} />
|
||||
<Route exact path="/myfiles" element={<FamMyFilesPage />} />
|
||||
<Route exact path="/ai-lab" element={<FamAIQuestionPage />} />
|
||||
<Route exact path="/work-in-progress" element={<FamWorkInProgressPage />} />
|
||||
<Route
|
||||
exact
|
||||
path="/familysettings"
|
||||
element={<FamilySettingsPage />}
|
||||
/>
|
||||
<Route exact path="/pastdue" element={<MyPastDueTasksPage />} />
|
||||
<Route exact path="/notification" element={<Notification />} />
|
||||
<Route exact path="/mytask" element={<MyTaskPage />} />
|
||||
<Route exact path="/myjobs" element={<MyJobsPage />} />
|
||||
@@ -152,6 +169,7 @@ export default function Routers() {
|
||||
element={<MyReviewDueJobsPage />}
|
||||
/>
|
||||
<Route exact path="/acc-family" element={<FamilyAccPage />} />
|
||||
<Route exact path="/acc-family/activities" element={<FamilyActivitiesPage />} />
|
||||
<Route exact path="/manage-family" element={<FamilyManagePage />} />
|
||||
<Route exact path="/start-job" element={<StartJob />} />
|
||||
<Route exact path="/yourpage" element={<YourPages />} />
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import React, { lazy, useContext } from "react";
|
||||
import React, { useContext } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { localImgLoad } from "../../lib";
|
||||
|
||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||
|
||||
export default function LoginLayout({ slogan, children }) {
|
||||
const bgImg = localImgLoad('images/left-wrenchboard.jpg')
|
||||
const bgImgNig = localImgLoad('images/wrench-home-back-nigeria.jpg')
|
||||
const bgImgCom = localImgLoad('images/wrench-home-back-common.jpg')
|
||||
const bgImg = localImgLoad("images/left-wrenchboard.jpg");
|
||||
const bgImgNig = localImgLoad("images/wrench-home-back-nigeria.jpg");
|
||||
const bgImgCom = localImgLoad("images/wrench-home-back-common.jpg");
|
||||
|
||||
const {countryMode} = useContext(DarkModeContext);
|
||||
const { countryMode } = useContext(DarkModeContext);
|
||||
|
||||
return (
|
||||
<div className={`h-screen overflow-y-auto bg-cover bg-center`}
|
||||
style={{backgroundImage: `url(${ countryMode == 'NG' ? bgImgNig : bgImgCom})`}}
|
||||
<div
|
||||
className={`h-screen overflow-y-auto bg-cover bg-center`}
|
||||
style={{
|
||||
backgroundImage: `url(${countryMode == "NG" ? bgImgNig : bgImgCom})`,
|
||||
}}
|
||||
>
|
||||
<div className={`w-full grid grid-cols-1 lg:grid-cols-2`}>
|
||||
{/* <div
|
||||
@@ -22,41 +25,43 @@ export default function LoginLayout({ slogan, children }) {
|
||||
>
|
||||
</div> */}
|
||||
<div className="p-5 sm:p-7 flex place-content-center lg:col-start-2">
|
||||
<div className="py-5 w-full sm:w-11/12 max-w-2xl shadow-md bg-slate-50 dark:bg-dark-white rounded-[0.475rem]">
|
||||
<div className="py-5 w-full sm:w-11/12 max-w-[550px] shadow-md bg-slate-50 rounded-[0.475rem]">
|
||||
<div className="w-full flex justify-center items-center">
|
||||
{children && children}
|
||||
</div>
|
||||
<div className="w-full flex flex-col justify-center items-center px-10">
|
||||
<div className="w-full flex justify-center items-center pt-5">
|
||||
<div className="flex items-center">
|
||||
<a
|
||||
href="https://www.wrenchboard.com/about-us"
|
||||
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
About
|
||||
</a>
|
||||
<a
|
||||
href="https://www.wrenchboard.com/service"
|
||||
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Services
|
||||
</a>
|
||||
<a
|
||||
href="https://www.wrenchboard.com/contact"
|
||||
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Contact Us
|
||||
</a>
|
||||
<a
|
||||
href="https://www.wrenchboard.com/about-us"
|
||||
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
About
|
||||
</a>
|
||||
<a
|
||||
href="https://www.wrenchboard.com/service"
|
||||
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Services
|
||||
</a>
|
||||
<a
|
||||
href="https://www.wrenchboard.com/contact"
|
||||
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Contact Us
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<p className="py-1 text-black text-[15px] px-2 font-medium flex items-center gap-1">
|
||||
<span className="dark:text-white">© {new Date().getFullYear()} -</span>
|
||||
<span className="dark:text-white">
|
||||
© {new Date().getFullYear()} -
|
||||
</span>
|
||||
<Link to="/" className="text-[#009ef7] ml-1">
|
||||
WrenchBoard
|
||||
</Link>{" "}
|
||||
|
||||
@@ -24,7 +24,9 @@ export default function Login() {
|
||||
const dispatch = useDispatch();
|
||||
const { state } = useLocation();
|
||||
|
||||
const [sessionExpired, setSessionExpired] = useState(queryParams.get("sessionExpired"))
|
||||
const [sessionExpired, setSessionExpired] = useState(
|
||||
queryParams.get("sessionExpired")
|
||||
);
|
||||
|
||||
const [validCaptcha, setValidCaptcha] = useState({ show: false, valid: "" }); // FOR CAPTCHA
|
||||
|
||||
@@ -97,7 +99,7 @@ export default function Login() {
|
||||
username: email,
|
||||
password: password,
|
||||
sessionid: "STARTING",
|
||||
login_mode: 1100
|
||||
login_mode: 1100,
|
||||
};
|
||||
} else if (name == "family") {
|
||||
// Post Data Info for family Login
|
||||
@@ -105,7 +107,7 @@ export default function Login() {
|
||||
username: email,
|
||||
pin: password,
|
||||
sessionid: "20067A92714",
|
||||
login_mode: 1105
|
||||
login_mode: 1105,
|
||||
};
|
||||
} else {
|
||||
setLoginLoading(false);
|
||||
@@ -143,8 +145,9 @@ export default function Login() {
|
||||
localStorage.setItem("member_id", `${res.data.member_id}`);
|
||||
localStorage.setItem("uid", `${res.data.uid}`);
|
||||
localStorage.setItem("session_token", `${res.data.session}`);
|
||||
if (name === "family") {
|
||||
if (res.data?.account_type == "FAMILY") {
|
||||
sessionStorage.setItem("family_uid", res.data?.family_uid);
|
||||
sessionStorage.setItem("parent_uid", res.data?.parent_uid);
|
||||
}
|
||||
// localStorage.setItem("session", `${res.data.session}`);
|
||||
dispatch(updateUserDetails({ ...res.data }));
|
||||
@@ -235,19 +238,18 @@ export default function Login() {
|
||||
setPassword("");
|
||||
}, [loginType]);
|
||||
|
||||
|
||||
// EFFECT TO CLEAR SESSION EXPIRY IF IT EXISTS AFTER SOME SECONDS
|
||||
useEffect(()=>{
|
||||
useEffect(() => {
|
||||
let timer;
|
||||
if(sessionExpired == "true"){
|
||||
timer = setTimeout(()=>{
|
||||
setSessionExpired(false)
|
||||
},5000)
|
||||
if (sessionExpired == "true") {
|
||||
timer = setTimeout(() => {
|
||||
setSessionExpired(false);
|
||||
}, 5000);
|
||||
}
|
||||
return () => {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
}, [])
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -523,25 +525,39 @@ export default function Login() {
|
||||
{/* APP DOWNLOAD STORE */}
|
||||
<div className="w-full mt-4">
|
||||
<div className="w-full flex justify-center items-center gap-4">
|
||||
<div className='w-28 lg:w-32'>
|
||||
<a className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300" target='_blank' href={process.env.REACT_APP_APPLE_APP}>
|
||||
<i className="fa-brands fa-apple text-3xl"></i>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-[11px]">Available on the</span>
|
||||
<span className="text-[12px] lg:text-base">App Store</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className='w-28 lg:w-32'>
|
||||
<a className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300" target='_blank' href={process.env.REACT_APP_ANDROID_APP}>
|
||||
<i className="fa-brands fa-google-play text-2xl"></i>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-[11px]">Available on the</span>
|
||||
<span className="text-[12px] lg:text-base">Google Play</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="w-28 lg:w-32">
|
||||
<a
|
||||
className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={process.env.REACT_APP_APPLE_APP}
|
||||
>
|
||||
<i className="fa-brands fa-apple text-3xl"></i>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-[11px]">Available on the</span>
|
||||
<span className="text-[12px] lg:text-base">
|
||||
App Store
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="w-28 lg:w-32">
|
||||
<a
|
||||
className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={process.env.REACT_APP_ANDROID_APP}
|
||||
>
|
||||
<i className="fa-brands fa-google-play text-2xl"></i>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-[11px]">Available on the</span>
|
||||
<span className="text-[12px] lg:text-base">
|
||||
Google Play
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{loginType == "full" && (
|
||||
<>
|
||||
@@ -590,7 +606,7 @@ const BrandBtn = ({
|
||||
{isAnchor ? (
|
||||
<a
|
||||
href={link}
|
||||
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
|
||||
className="w-full border border-light-purple rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 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]">
|
||||
@@ -601,7 +617,7 @@ const BrandBtn = ({
|
||||
<button
|
||||
onClick={onClick}
|
||||
// href="#dd"
|
||||
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
|
||||
className="w-full border border-light-purple rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 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]">
|
||||
|
||||
@@ -4,9 +4,15 @@ import usersService from "../../services/UsersService";
|
||||
import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import { useSelector } from "react-redux";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function BlogItem(props) {
|
||||
|
||||
const {
|
||||
userDetails: { account_type },
|
||||
} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details account type
|
||||
|
||||
const apiCall = new usersService()
|
||||
const navigate = useNavigate()
|
||||
|
||||
@@ -33,11 +39,26 @@ export default function BlogItem(props) {
|
||||
},[blog_id])
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead
|
||||
commonHeadData={props.commonHeadData}
|
||||
/>
|
||||
{account_type == 'FULL' &&
|
||||
<CommonHead
|
||||
commonHeadData={props.commonHeadData}
|
||||
/>
|
||||
}
|
||||
{ account_type == 'FAMILY' &&
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {blogdata?.data?.blogdata?.length > 0 ? blogdata?.data?.blogdata[0]?.post_title : 'Blog'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/fam-blog", title: "Blogs", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<div className="notification-page w-full mb-10">
|
||||
<div className="mb-5">
|
||||
{/* <div className="mb-5">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
<span
|
||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||
@@ -45,7 +66,7 @@ export default function BlogItem(props) {
|
||||
{blogdata.data?.blogdata?.[0]?.post_title}
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="notification-wrapper w-full bg-white p-8 rounded-2xl">
|
||||
{blogdata?.loading ?
|
||||
<LoadingSpinner size='8' color='sky-blue' height='h-[100px]' />
|
||||
@@ -53,8 +74,8 @@ export default function BlogItem(props) {
|
||||
blogdata?.data?.blogdata && blogdata.data?.blogdata.length ?
|
||||
<div className="w-full">
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
{/* <div className="mb-5">
|
||||
{/* <div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
<span
|
||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||
@@ -62,10 +83,10 @@ export default function BlogItem(props) {
|
||||
{blogdata.data?.blogdata?.[0]?.post_title}
|
||||
</span>
|
||||
</h1>
|
||||
</div> */}
|
||||
{/* <div className="slider-btns flex space-x-4">
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
</div>
|
||||
</div> */}
|
||||
<div dangerouslySetInnerHTML={{__html: blogdata.data?.blogdata?.[0]?.post_content}}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export default function CustomBreadcrumb({ title, breadcrumb }) {
|
||||
return (
|
||||
<div className="">
|
||||
<h3 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
{title}
|
||||
</h3>
|
||||
<nav
|
||||
aria-label="breadcrumb"
|
||||
className="text-base text-dark-gray dark:text-white flex items-center"
|
||||
>
|
||||
{breadcrumb.map((value, index) => (
|
||||
<React.Fragment key={index}>
|
||||
<Link className={value.active ? "opacity-60" : ""} to={value.link}>
|
||||
{value.title}
|
||||
</Link>
|
||||
{index !== breadcrumb.length - 1 && <span className="px-1">\</span>}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
|
||||
export default function AvailableJobsCard({
|
||||
className,
|
||||
datas,
|
||||
key,
|
||||
hidden = false,
|
||||
contentDisplay,
|
||||
image_server,
|
||||
@@ -38,7 +37,6 @@ export default function AvailableJobsCard({
|
||||
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
|
||||
className || ""
|
||||
}`}
|
||||
key={key}
|
||||
>
|
||||
<div
|
||||
onClick={() => {
|
||||
@@ -57,7 +55,7 @@ export default function AvailableJobsCard({
|
||||
Added
|
||||
</p>
|
||||
<p className="text-base text-dark-gray dark:text-white">
|
||||
{datas.offer_added}
|
||||
{new Date(datas.offer_added).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,7 +66,7 @@ export default function AvailableJobsCard({
|
||||
Expires
|
||||
</p>
|
||||
<p className="text-base text-dark-gray dark:text-white text-right">
|
||||
{datas.expire}
|
||||
{new Date(datas.expire).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,7 +117,7 @@ export default function AvailableJobsCard({
|
||||
</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="card-style-two w-full px-4 py-[0.4rem] 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={image} alt="data" className="w-full h-full" />
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import io from "socket.io-client";
|
||||
|
||||
let SocketIOContext = createContext({})
|
||||
|
||||
export default function SocketIOContextProvider({children}) {
|
||||
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER UID, to determine if user is active
|
||||
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const socket = io.connect(process.env.REACT_APP_PRIMARY_SOCKET);
|
||||
|
||||
// //Room State
|
||||
// const [room, setRoom] = useState("");
|
||||
|
||||
// // Messages States
|
||||
// const [message, setMessage] = useState("");
|
||||
const [socketMsgReceived, setSocketMsgReceived] = useState("");
|
||||
|
||||
const joinRoom = (room) => {
|
||||
if (room !== "") {
|
||||
socket.emit("join_room", room);
|
||||
}
|
||||
};
|
||||
|
||||
const sendMessage = (message, room) => {
|
||||
if(message && room){
|
||||
socket.emit("send_message", { message, room });
|
||||
}
|
||||
};
|
||||
|
||||
const marketUpdate = (message, room) => {
|
||||
if(message && room){
|
||||
socket.emit("marketjob_addded", { message, room });
|
||||
}
|
||||
};
|
||||
|
||||
const parentAssignJobToKid = (message, room) => {
|
||||
if(message && room){
|
||||
socket.emit("family", { message:{...message}, room });
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
socket.on("receive_message", (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
dispatch(tableReload({type:'CHATMESSAGELIST'}))
|
||||
});
|
||||
socket.on("received_refreshmarket_jobs", (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
dispatch(tableReload({type:'MARKETTABLELIST'}))
|
||||
});
|
||||
socket.on("family_actions", (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
let user_uid = userDetails.account_type == 'FULL' ? userDetails.uid : sessionStorage.getItem('family_uid')
|
||||
let {message} = data
|
||||
if(message.action == "REFRESH_OFFER" && message.family_uid == user_uid && message.audience == "MEMBER"){
|
||||
dispatch(tableReload({type:'FAMILYOFFERLIST'}))
|
||||
}
|
||||
});
|
||||
}, [socket]);
|
||||
|
||||
let values = {
|
||||
socket,
|
||||
sendMessage,
|
||||
joinRoom,
|
||||
setSocketMsgReceived,
|
||||
marketUpdate,
|
||||
parentAssignJobToKid,
|
||||
socketMsgReceived,
|
||||
// room,
|
||||
// setRoom,
|
||||
// message,
|
||||
// setMessage,
|
||||
}
|
||||
|
||||
return (
|
||||
<SocketIOContext.Provider value={values}>
|
||||
{children}
|
||||
</SocketIOContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export const SocketValues = () => {
|
||||
return useContext(SocketIOContext)
|
||||
}
|
||||
@@ -1,20 +1,63 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
const AccountDashboard = ({ className }) => {
|
||||
const AccountDashboard = ({ className, bannerList }) => {
|
||||
// getting the upper three banners for the home layout
|
||||
const getUpperBanner = bannerList?.filter((value, idx) => idx <= 2);
|
||||
const getLowerBanner = bannerList?.filter((value, idx) => idx > 2);
|
||||
|
||||
let getImage = ({ banner_location, banner }) => {
|
||||
if (banner_location == "LOCAL") {
|
||||
return require(`../../assets/images/${banner}`);
|
||||
} else {
|
||||
return banner;
|
||||
}
|
||||
};
|
||||
|
||||
console.log(getLowerBanner);
|
||||
return (
|
||||
<div
|
||||
className={`w-full min-h-[450px] flex flex-col justify-between items-center gap-4 rounded-2xl overflow-hidden ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
<div className="w-full h-[300px] md:grid grid-cols-3 items-center justify-center gap-2">
|
||||
<TopBanner />
|
||||
<TopBanner />
|
||||
<TopBanner />
|
||||
<div className="w-full grid xxs:grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 items-center justify-center gap-2 md:gap-4">
|
||||
{getUpperBanner?.map((props, idx) => {
|
||||
let image = getImage(props);
|
||||
|
||||
let { short_title, short_description, short_button_text, link_path } =
|
||||
props;
|
||||
|
||||
return (
|
||||
<TopBanner
|
||||
btn={short_button_text}
|
||||
image={image}
|
||||
title={short_title}
|
||||
desc={short_description}
|
||||
link_path={link_path}
|
||||
key={idx}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="w-full h-[150px] md:grid grid-cols-2 items-center justify-center gap-4">
|
||||
<LowerBanner />
|
||||
<LowerBanner />
|
||||
<div className="w-full grid-cols-1 md:grid-cols-2 2xl::grid-cols-3 grid items-center justify-center gap-2 md:gap-4">
|
||||
{getLowerBanner?.map((props, idx) => {
|
||||
let image = getImage(props);
|
||||
|
||||
let { short_title, short_description, short_button_text, link_path } =
|
||||
props;
|
||||
|
||||
return (
|
||||
<LowerBanner
|
||||
btn={short_button_text}
|
||||
image={image}
|
||||
title={short_title}
|
||||
desc={short_description}
|
||||
link_path={link_path}
|
||||
key={idx}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -22,24 +65,30 @@ const AccountDashboard = ({ className }) => {
|
||||
|
||||
export default AccountDashboard;
|
||||
|
||||
const TopBanner = () => {
|
||||
let Image = require(`../../assets/images/offer.jpg`);
|
||||
const TopBanner = ({ image, title = "", desc = "", btn, link_path, key }) => {
|
||||
return (
|
||||
<div className="flex flex-col shadow-md rounded-xl">
|
||||
<div className="h-[12rem] rounded-t-xl">
|
||||
<div className="flex flex-col shadow-md rounded-xl dark:border-[#5356fb29]" key={key}>
|
||||
<Link to={link_path} className="h-[12rem] rounded-t-xl">
|
||||
<img
|
||||
src={Image}
|
||||
src={image}
|
||||
alt="banner-img"
|
||||
className="w-full h-full rounded-t-xl"
|
||||
loading="lazy"
|
||||
className="w-full h-full rounded-t-xl object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="h-[7rem] rounded-b-xl bg-white">
|
||||
<div className="border-b border-slate-300 px-2 py-1 h-[5.4rem]">
|
||||
<h3 className="font-bold text-lg">Banner Title</h3>
|
||||
<p>Banner description text will come follow</p>
|
||||
</Link>
|
||||
<div className="h-[7rem] rounded-b-xl bg-white dark:bg-dark-white">
|
||||
<div className="border-b border-slate-300 px-2 py-1 h-[5.4rem] flex flex-col gap-2 dark:text-white">
|
||||
<Link to={link_path} className="font-bold text-lg">
|
||||
{title}
|
||||
</Link>
|
||||
<Link to={link_path} className="text-sm">
|
||||
{desc}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex justify-between w-full px-2 items-center">
|
||||
<span className="text-slate-300 font-semibold">follow up text</span>
|
||||
<div className="flex justify-between w-full px-2 items-center pt-[0.2rem]">
|
||||
<Link to={link_path} className="text-slate-300 font-semibold text-sm">
|
||||
{btn}
|
||||
</Link>
|
||||
<button className="flex items-center justify-center gap-2">
|
||||
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
|
||||
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
|
||||
@@ -51,27 +100,36 @@ const TopBanner = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const LowerBanner = () => {
|
||||
let Image = require(`../../assets/images/offer.jpg`);
|
||||
const LowerBanner = ({ image, title = "", desc = "", btn, link_path, key }) => {
|
||||
return (
|
||||
<div className="flex flex-col bg-white shadow-md h-full rounded-xl">
|
||||
<div
|
||||
key={key}
|
||||
className="flex flex-col bg-white shadow-md h-full rounded-xl dark:border-[#5356fb29] dark:bg-dark-white"
|
||||
>
|
||||
<div className="w-full flex justify-between border-b border-slate-300 p-2">
|
||||
<div className="h-[130px] flex justify-between items-center">
|
||||
<div className="px-2">
|
||||
<h3 className="text-lg font-bold">Banner Title</h3>
|
||||
<p className="text-sm">Banner description text will come follow</p>
|
||||
<div className="px-2 flex flex-col gap-2 dark:text-white">
|
||||
<Link to={link_path} className="text-lg font-bold">
|
||||
{title}
|
||||
</Link>
|
||||
<p to={link_path} className="text-sm">
|
||||
{desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-[150px] h-[100px]">
|
||||
<Link to={link_path} className="w-[150px] h-[100px]">
|
||||
<img
|
||||
src={Image}
|
||||
src={image}
|
||||
alt="banner-img"
|
||||
loading="lazy"
|
||||
className="w-full h-full rounded-xl"
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex justify-between w-full px-2 items-center">
|
||||
<span className="text-slate-300 font-semibold">follow up text</span>
|
||||
<Link to={link_path} className="text-slate-300 font-semibold text-sm">
|
||||
{btn}
|
||||
</Link>
|
||||
<button className="flex items-center justify-center gap-2">
|
||||
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
|
||||
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
|
||||
@@ -81,3 +139,66 @@ const LowerBanner = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const BannerSection = ({ banners, variant }) => {
|
||||
const getImage = ({ banner_location, banner }) => {
|
||||
return banner_location === "LOCAL"
|
||||
? require(`../../assets/images/${banner}`)
|
||||
: banner;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{banners?.map((props, idx) => {
|
||||
const { short_title, short_description, short_button_text, link_path } =
|
||||
props;
|
||||
const image = getImage(props);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={idx}
|
||||
className={`flex flex-col shadow-md rounded-xl ${
|
||||
variant === "top" ? "" : "bg-white"
|
||||
}`}
|
||||
>
|
||||
<div className={`${variant === "top" ? "rounded-t-xl" : ""}`}>
|
||||
<Link to={link_path}>
|
||||
<img
|
||||
src={image}
|
||||
alt="banner-img"
|
||||
className="w-full h-full rounded-t-xl object-cover"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
<div
|
||||
className={`${
|
||||
variant === "top"
|
||||
? "rounded-b-xl bg-white"
|
||||
: "border-b border-slate-300"
|
||||
} h-[7rem]`}
|
||||
>
|
||||
<div className="border-b border-slate-300 px-2 py-1 h-[5.4rem] flex flex-col gap-2">
|
||||
<Link to={link_path} className="font-bold text-lg">
|
||||
{short_title}
|
||||
</Link>
|
||||
<Link to={link_path} className="text-sm">
|
||||
{short_description}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex justify-between w-full px-2 items-center">
|
||||
<Link to={link_path} className="text-slate-300 font-semibold">
|
||||
{short_button_text}
|
||||
</Link>
|
||||
<button className="flex items-center justify-center gap-2">
|
||||
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
|
||||
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
|
||||
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,31 +1,21 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
|
||||
import heroUser from "../../assets/images/hero-user.png";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
import React from "react";
|
||||
// import HomeSliders from "./HomeSliders";
|
||||
import { useSelector } from "react-redux";
|
||||
import HomeSliders from "../Home/HomeSliders";
|
||||
|
||||
export default function FamilyParentDashboard({ className, bannerList, nextDueTask }) {
|
||||
const settings = {
|
||||
autoplay: true,
|
||||
dots: true,
|
||||
arrows: false,
|
||||
infinite: true,
|
||||
swipe: true,
|
||||
};
|
||||
const sildeData = null;
|
||||
export default function FamilyParentDashboard({
|
||||
className,
|
||||
bannerList,
|
||||
nextDueTask,
|
||||
}) {
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
|
||||
let loginDate = userDetails?.last_login.split(" ")[0];
|
||||
let { firstname, lastname, email, profile_pic } = userDetails;
|
||||
let { firstname, lastname, email } = userDetails;
|
||||
let userEmail = email.split("@")[0];
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden bg-blue-500 ${
|
||||
className={`w-full md:h-[47px] xxs:h-[74px] flex px-[1.05rem] py-[0.35rem] flex-wrap justify-between items-center gap-2 rounded-2xl overflow-hidden bg-sky-blue ${
|
||||
className || ""
|
||||
}`}
|
||||
style={{
|
||||
@@ -34,70 +24,26 @@ export default function FamilyParentDashboard({ className, bannerList, nextDueTa
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
>
|
||||
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
|
||||
<div className="h-full flex flex-wrap w-full justify-between mb-5 lg:mb-0">
|
||||
{/* heading */}
|
||||
<div>
|
||||
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
|
||||
<div className="flex gap-8">
|
||||
<h1 className="text-base font-medium text-white tracking-wide">
|
||||
Welcome
|
||||
</h1>
|
||||
<span className="text-[18px] font-thin tracking-wide text-white">
|
||||
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="" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xl tracking-wide font-bold antise text-white">
|
||||
{/* user */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-base tracking-wide font-bold antise text-white leading-[1]">
|
||||
{`${firstname} ${lastname}`}
|
||||
</p>
|
||||
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
|
||||
<p className="text-sm tracking-wide text-white leading-[1]">
|
||||
@{userEmail}
|
||||
</p>
|
||||
</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 back-dark1 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>
|
||||
</div>
|
||||
)}
|
||||
{/* action */}
|
||||
<div className="flex lg:space-x-3 space-x-1 items-center">
|
||||
<Link to="/mytask" className="text-white text-base">
|
||||
<span className=" border-b dark:border-[#5356fb29] border-white">
|
||||
{" "}
|
||||
View All Task(s)
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
<span className="text-base font-thin tracking-wide text-white flex items-end">
|
||||
Last Login : {loginDate}
|
||||
</span>
|
||||
</div>
|
||||
<HomeSliders
|
||||
settings={settings}
|
||||
sideData={sildeData}
|
||||
bannerList={bannerList}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,103 +1,46 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
|
||||
import heroUser from "../../assets/images/hero-user.png";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
import React from "react";
|
||||
// import HomeSliders from "./HomeSliders";
|
||||
import { useSelector } from "react-redux";
|
||||
import HomeSliders from "../Home/HomeSliders";
|
||||
|
||||
export default function HomeDashboard({ className, bannerList, nextDueTask }) {
|
||||
const settings = {
|
||||
autoplay: true,
|
||||
dots: true,
|
||||
arrows: false,
|
||||
infinite: true,
|
||||
swipe: true,
|
||||
};
|
||||
const sildeData = null;
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
|
||||
let loginDate = userDetails?.last_login.split(" ")[0];
|
||||
let { firstname, lastname, email, profile_pic } = userDetails;
|
||||
let { firstname, lastname, email } = userDetails;
|
||||
let userEmail = email.split("@")[0];
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden ${
|
||||
className={`w-full md:h-[47px] xxs:h-[74px] flex px-[1.05rem] py-[0.35rem] flex-wrap justify-between items-center gap-2 rounded-2xl overflow-hidden bg-sky-blue ${
|
||||
className || ""
|
||||
}`}
|
||||
style={{
|
||||
background: `url(${heroBg})`,
|
||||
// background: `url(${heroBg})`,
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
>
|
||||
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
|
||||
<div className="h-full flex flex-wrap w-full justify-between mb-5 lg:mb-0">
|
||||
{/* heading */}
|
||||
<div>
|
||||
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
|
||||
<div className="flex gap-8">
|
||||
<h1 className="text-base font-medium text-white tracking-wide">
|
||||
Welcome
|
||||
</h1>
|
||||
<span className="text-[18px] font-thin tracking-wide text-white">
|
||||
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="" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xl tracking-wide font-bold antise text-white">
|
||||
{/* user */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-base tracking-wide font-bold antise text-white leading-[1]">
|
||||
{`${firstname} ${lastname}`}
|
||||
</p>
|
||||
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
|
||||
<p className="text-sm tracking-wide text-white leading-[1]">
|
||||
@{userEmail}
|
||||
</p>
|
||||
</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 back-dark1 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>
|
||||
</div>
|
||||
)}
|
||||
{/* action */}
|
||||
<div className="flex lg:space-x-3 space-x-1 items-center">
|
||||
<Link to="/mytask" className="text-white text-base">
|
||||
<span className=" border-b dark:border-[#5356fb29] border-white">
|
||||
{" "}
|
||||
View All Task(s)
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<span className="text-base font-thin tracking-wide text-white flex items-end">
|
||||
Last Login : {loginDate}
|
||||
</span>
|
||||
</div>
|
||||
<HomeSliders
|
||||
settings={settings}
|
||||
sideData={sildeData}
|
||||
bannerList={bannerList}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,21 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
|
||||
import heroUser from "../../assets/images/hero-user.png";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
import React from "react";
|
||||
// import HomeSliders from "./HomeSliders";
|
||||
import { useSelector } from "react-redux";
|
||||
import HomeSliders from "../Home/HomeSliders";
|
||||
|
||||
export default function JobOwnerDashboard({ className, bannerList, nextDueTask }) {
|
||||
const settings = {
|
||||
autoplay: true,
|
||||
dots: true,
|
||||
arrows: false,
|
||||
infinite: true,
|
||||
swipe: true,
|
||||
};
|
||||
const sildeData = null;
|
||||
export default function JobOwnerDashboard({
|
||||
className,
|
||||
bannerList,
|
||||
nextDueTask,
|
||||
}) {
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
|
||||
let loginDate = userDetails?.last_login.split(" ")[0];
|
||||
let { firstname, lastname, email, profile_pic } = userDetails;
|
||||
let { firstname, lastname, email } = userDetails;
|
||||
let userEmail = email.split("@")[0];
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden bg-blue-800 ${
|
||||
className={`w-full md:h-[47px] xxs:h-[74px] flex px-[1.05rem] py-[0.35rem] flex-wrap justify-between items-center gap-2 rounded-2xl overflow-hidden bg-sky-blue ${
|
||||
className || ""
|
||||
}`}
|
||||
style={{
|
||||
@@ -34,70 +24,27 @@ export default function JobOwnerDashboard({ className, bannerList, nextDueTask }
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
>
|
||||
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
|
||||
<div className="h-full flex flex-wrap w-full justify-between mb-5 lg:mb-0">
|
||||
{/* heading */}
|
||||
<div>
|
||||
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
|
||||
<div className="flex gap-8">
|
||||
<h1 className="text-base font-medium text-white tracking-wide">
|
||||
Welcome
|
||||
</h1>
|
||||
<span className="text-[18px] font-thin tracking-wide text-white">
|
||||
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="" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xl tracking-wide font-bold antise text-white">
|
||||
{/* user */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-base tracking-wide font-bold antise text-white leading-[1]">
|
||||
{`${firstname} ${lastname}`}
|
||||
</p>
|
||||
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
|
||||
<p className="text-sm tracking-wide text-white leading-[1]">
|
||||
@{userEmail}
|
||||
</p>
|
||||
</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 back-dark1 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>
|
||||
</div>
|
||||
)}
|
||||
{/* action */}
|
||||
<div className="flex lg:space-x-3 space-x-1 items-center">
|
||||
<Link to="/mytask" className="text-white text-base">
|
||||
<span className=" border-b dark:border-[#5356fb29] border-white">
|
||||
{" "}
|
||||
View All Task(s)
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<span className="text-base font-thin tracking-wide text-white flex items-end">
|
||||
Last Login : {loginDate}
|
||||
</span>
|
||||
</div>
|
||||
<HomeSliders
|
||||
settings={settings}
|
||||
sideData={sildeData}
|
||||
bannerList={bannerList}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import heroUser from "../../assets/images/hero-user.png";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
// import HomeSliders from "./HomeSliders";
|
||||
import { useSelector } from "react-redux";
|
||||
import HomeSliders from "../Home/HomeSliders";
|
||||
|
||||
export default function WorkerDashboard({
|
||||
className,
|
||||
bannerList,
|
||||
nextDueTask,
|
||||
}) {
|
||||
const settings = {
|
||||
autoplay: true,
|
||||
dots: true,
|
||||
arrows: false,
|
||||
infinite: true,
|
||||
swipe: true,
|
||||
};
|
||||
const sildeData = null;
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
|
||||
let loginDate = userDetails?.last_login.split(" ")[0];
|
||||
let { firstname, lastname, email, profile_pic } = userDetails;
|
||||
let userEmail = email.split("@")[0];
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden bg-blue-900 ${
|
||||
className || ""
|
||||
}`}
|
||||
style={{
|
||||
// background: `url(${heroBg})`,
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
>
|
||||
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
|
||||
{/* heading */}
|
||||
<div>
|
||||
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
|
||||
Welcome
|
||||
</h1>
|
||||
<span className="text-[18px] font-thin tracking-wide text-white">
|
||||
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="" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xl tracking-wide font-bold antise text-white">
|
||||
{`${firstname} ${lastname}`}
|
||||
</p>
|
||||
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
|
||||
</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 back-dark1 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>
|
||||
</div>
|
||||
)}
|
||||
{/* action */}
|
||||
<div className="flex lg:space-x-3 space-x-1 items-center">
|
||||
<Link to="/mytask" className="text-white text-base">
|
||||
<span className=" border-b dark:border-[#5356fb29] border-white">
|
||||
{" "}
|
||||
View All Task(s)
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<HomeSliders
|
||||
settings={settings}
|
||||
sideData={sildeData}
|
||||
bannerList={bannerList}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,31 +1,21 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
|
||||
import heroUser from "../../assets/images/hero-user.png";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
import React from "react";
|
||||
// import HomeSliders from "./HomeSliders";
|
||||
import { useSelector } from "react-redux";
|
||||
import HomeSliders from "../Home/HomeSliders";
|
||||
|
||||
export default function WorkerDashboard({ className, bannerList, nextDueTask }) {
|
||||
const settings = {
|
||||
autoplay: true,
|
||||
dots: true,
|
||||
arrows: false,
|
||||
infinite: true,
|
||||
swipe: true,
|
||||
};
|
||||
const sildeData = null;
|
||||
export default function WorkerDashboard({
|
||||
className,
|
||||
bannerList,
|
||||
nextDueTask,
|
||||
}) {
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
|
||||
let loginDate = userDetails?.last_login.split(" ")[0];
|
||||
let { firstname, lastname, email, profile_pic } = userDetails;
|
||||
let { firstname, lastname, email } = userDetails;
|
||||
let userEmail = email.split("@")[0];
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden bg-blue-900 ${
|
||||
className={`w-full md:h-[47px] xxs:h-[74px] flex px-[1.05rem] py-[0.35rem] flex-wrap justify-between items-center gap-2 rounded-2xl overflow-hidden bg-sky-blue ${
|
||||
className || ""
|
||||
}`}
|
||||
style={{
|
||||
@@ -34,70 +24,26 @@ export default function WorkerDashboard({ className, bannerList, nextDueTask })
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
>
|
||||
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
|
||||
<div className="h-full flex flex-wrap w-full justify-between mb-5 lg:mb-0">
|
||||
{/* heading */}
|
||||
<div>
|
||||
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
|
||||
<div className="flex gap-8">
|
||||
<h1 className="text-base font-medium text-white tracking-wide">
|
||||
Welcome
|
||||
</h1>
|
||||
<span className="text-[18px] font-thin tracking-wide text-white">
|
||||
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="" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xl tracking-wide font-bold antise text-white">
|
||||
{/* user */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-base tracking-wide font-bold antise text-white leading-[1]">
|
||||
{`${firstname} ${lastname}`}
|
||||
</p>
|
||||
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
|
||||
<p className="text-sm tracking-wide text-white leading-[1]">
|
||||
@{userEmail}
|
||||
</p>
|
||||
</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 back-dark1 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>
|
||||
</div>
|
||||
)}
|
||||
{/* action */}
|
||||
<div className="flex lg:space-x-3 space-x-1 items-center">
|
||||
<Link to="/mytask" className="text-white text-base">
|
||||
<span className=" border-b dark:border-[#5356fb29] border-white">
|
||||
{" "}
|
||||
View All Task(s)
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
<span className="text-base font-thin tracking-wide text-white flex items-end">
|
||||
Last Login : {loginDate}
|
||||
</span>
|
||||
</div>
|
||||
<HomeSliders
|
||||
settings={settings}
|
||||
sideData={sildeData}
|
||||
bannerList={bannerList}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import React, { Suspense } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import FamilyTableNew from "./FamilyTableNew";
|
||||
|
||||
export default function FamilyActivities() {
|
||||
return (
|
||||
<Layout>
|
||||
{/*<CommonHead />*/}
|
||||
<div className="notification-page w-full mb-10">
|
||||
<div className="notification-wrapper w-full">
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<CustomBreadcrumb
|
||||
title={"Tasks & Chores"}
|
||||
breadcrumb={[
|
||||
{ link: "/", title: "Home" },
|
||||
{
|
||||
link: "/acc-family",
|
||||
title: "Family Account",
|
||||
},
|
||||
{
|
||||
link: "/acc-family/activities",
|
||||
title: "Tasks & Chores",
|
||||
active: true,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<Link
|
||||
className="item-content relative text-[18px] transition-all duration-300 ease-in-out bg-[#76a5df] text-white font-medium dark:text-white h-12 px-2 flex items-center gap-2 rounded-md shadow-sm justify-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
|
||||
to="/acc-family"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span>Family</span>
|
||||
</Link>
|
||||
</div>
|
||||
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
|
||||
<FamilyTableNew />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
const CloseIcon = () => (
|
||||
<svg
|
||||
width="36"
|
||||
height="36"
|
||||
viewBox="0 0 36 36"
|
||||
fill="none"
|
||||
className="fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
|
||||
fill=""
|
||||
fillOpacity="0.6"
|
||||
/>
|
||||
<path
|
||||
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
|
||||
fill="#"
|
||||
fillOpacity="0.6"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
@@ -187,6 +187,7 @@ export default function FamilyManageTabs({
|
||||
familyData={details.familyWaitList.data}
|
||||
accountDetails={accountDetails}
|
||||
loader={details.familyWaitList.loading}
|
||||
setUpdatePage={setUpdatePage}
|
||||
/>
|
||||
),
|
||||
Pending: (
|
||||
|
||||
@@ -4,6 +4,7 @@ import SearchCom from "../Helpers/SearchCom";
|
||||
import FamilyMarketCard from "../Cards/FamilyMarketCard";
|
||||
import usersService from "../../services/UsersService";
|
||||
import SuggestTask from "../FamilyPopup/SuggestTask";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function FamilyMarket() {
|
||||
const [popUp, setPopUp] = useState(false);
|
||||
@@ -53,12 +54,23 @@ export default function FamilyMarket() {
|
||||
<div className="notification-page w-full mb-10">
|
||||
<div className="notification-wrapper w-full">
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
{/* <div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
|
||||
<span>Suggest Task to the Parents</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {'Suggest Task to the Parents'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/familymarket", title: "Family Market", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{/* Body */}
|
||||
<div className="filter-section w-full items-center sm:flex justify-between mb-6">
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Layout from '../Partials/Layout'
|
||||
import MyOffersFamilyTable from '../MyTasks/MyOffersFamilyTable'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
||||
import usersService from '../../services/UsersService';
|
||||
import CustomBreadcrumb from '../Breadcrumb/CustomBreadcrumb';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
export default function FamilyPendingOffer() {
|
||||
const userApi = new usersService();
|
||||
|
||||
const {familyOfferList} = useSelector((state) => state.tableReload)
|
||||
|
||||
const [myOffersList, setMyOffersList] = useState({loading: true, data: []});
|
||||
|
||||
const getMyOffersList = async () => {
|
||||
try {
|
||||
const res = await userApi.getOffersList();
|
||||
setMyOffersList({loading:false, data:res.data});
|
||||
} catch (error) {
|
||||
setMyOffersList({loading:false, data:[]});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
getMyOffersList()
|
||||
},[familyOfferList])
|
||||
return (
|
||||
<Layout>
|
||||
{myOffersList.loading ?
|
||||
<div className='w-full flex justify-center items-center rounded-2xl bg-white'>
|
||||
<LoadingSpinner size='10' color='sky-blue' height='h-[20rem]' />
|
||||
</div>
|
||||
:
|
||||
myOffersList?.data?.result_list && myOffersList?.data?.result_list.length > 0 ?
|
||||
<MyOffersFamilyTable
|
||||
familyOffers={myOffersList?.data?.result_list}
|
||||
image_server={myOffersList?.data?.session_image_server}
|
||||
className="mb-10"
|
||||
/>
|
||||
:
|
||||
<>
|
||||
<div className="mb-6">
|
||||
<CustomBreadcrumb
|
||||
title = {'Ready to Start'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/pending", title: "Pending", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className='w-full h-[30rem] bg-white dark:bg-dark-white flex justify-center items-center rounded-2xl'>
|
||||
<p className='text-black dark:text-white'>No Record Found!</p>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -1,424 +1,508 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import usersService from "../../../services/UsersService";
|
||||
import { tableReload } from "../../../store/TableReloads";
|
||||
import ModalCom from "../../Helpers/ModalCom";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import Detail from "../../jobPopout/popoutcomponent/Detail";
|
||||
import { NewTasks } from "./forms";
|
||||
import { tableReload } from "../../../store/TableReloads";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { SocketValues } from "../../Contexts/SocketIOContext";
|
||||
|
||||
const AssignTaskPopout = React.memo(
|
||||
({
|
||||
action,
|
||||
details,
|
||||
situation,
|
||||
familyDetailsData,
|
||||
familyTask,
|
||||
activeTask,
|
||||
setActiveTask,
|
||||
setUpdatePage
|
||||
}) => {
|
||||
const apiCall = new usersService();
|
||||
const AssignTaskPopout = ({
|
||||
action,
|
||||
details,
|
||||
situation,
|
||||
familyDetailsData,
|
||||
familyTask,
|
||||
activeTask,
|
||||
setActiveTask,
|
||||
setUpdatePage,
|
||||
assignTaskChecker,
|
||||
|
||||
}) => {
|
||||
const {parentAssignJobToKid} = SocketValues()
|
||||
const apiCall = new usersService();
|
||||
let { pathname, state } = useLocation();
|
||||
|
||||
const dispatch = useDispatch()
|
||||
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
}); // HOLDS RESPONSE FOR SENDING API REQUEST
|
||||
const [selectedFamilyUid, setSelectedFamilyUid] = useState('');
|
||||
|
||||
let [taskType, setTaskType] = useState(details ? "new" : "select"); // SWITCHES BTW SELECT TASK AND NEW TASK
|
||||
const handleFamChange = (event) => {
|
||||
setSelectedFamilyUid(event.target.value);
|
||||
};
|
||||
|
||||
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 dispatch = useDispatch();
|
||||
|
||||
// New Task
|
||||
const [formState, setFormState] = useState({
|
||||
// Initialize form state with desired fields
|
||||
banner: details?.banner || "default.jpg",
|
||||
country: details?.country || "",
|
||||
price: details?.price || "",
|
||||
title: details?.title || "",
|
||||
description: details?.description || "",
|
||||
job_detail: details?.job_detail || "",
|
||||
timeline_days: details?.timeline_days || "",
|
||||
category: details?.category || "",
|
||||
});
|
||||
const getFamilySession = JSON.parse(sessionStorage.getItem("family_list"));
|
||||
|
||||
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) {
|
||||
const familyList = getFamilySession?.map((member) => (
|
||||
<option key={member?.family_uid} value={member?.family_uid}>
|
||||
{member?.firstname} {member?.lastname}
|
||||
</option>
|
||||
));
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
}); // HOLDS RESPONSE FOR SENDING API REQUEST
|
||||
|
||||
let [taskType, setTaskType] = useState(details ? "new" : "select"); // SWITCHES BTW SELECT TASK AND NEW 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 });
|
||||
};
|
||||
|
||||
// New Task
|
||||
const [formState, setFormState] = useState({
|
||||
// Initialize form state with desired fields
|
||||
banner: details?.banner || "default.jpg",
|
||||
country: details?.country || "",
|
||||
price: details?.price || "",
|
||||
title: details?.title || "",
|
||||
description: details?.description || "",
|
||||
job_detail: details?.job_detail || "",
|
||||
timeline_days: details?.timeline_days || "",
|
||||
category: details?.category || "",
|
||||
});
|
||||
|
||||
const assignFamilyTask = () => {
|
||||
setRequestStatus({ loading: true, status: false, message: "" });
|
||||
|
||||
if(!selectedFamilyUid){ // If no family found, throw error
|
||||
setRequestStatus({ loading: false, status: false, message: "Please Select Family Member" });
|
||||
return setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
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: selectedFamilyUid
|
||||
? selectedFamilyUid
|
||||
: familyDetailsData?.uid || details?.family_uid,
|
||||
job_description: activeTask.data?.description,
|
||||
assign_mode: 110011,
|
||||
};
|
||||
}
|
||||
|
||||
if (taskType === "new") {
|
||||
const {
|
||||
banner,
|
||||
category,
|
||||
country,
|
||||
description,
|
||||
job_detail,
|
||||
price,
|
||||
timeline_days,
|
||||
title,
|
||||
} = formState;
|
||||
|
||||
const requiredFields = {
|
||||
banner,
|
||||
// category,
|
||||
currency: country,
|
||||
description,
|
||||
"job detail": job_detail,
|
||||
price,
|
||||
timeline: timeline_days,
|
||||
title,
|
||||
};
|
||||
|
||||
for (let field in requiredFields) {
|
||||
if (requiredFields[field] == "") {
|
||||
// let currencyErrMsg = field == "country" && "currency"
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "No Task is seleted",
|
||||
message: `${
|
||||
field[0].toUpperCase() + field.slice(1).toLowerCase()
|
||||
} is empty`,
|
||||
});
|
||||
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: familyDetailsData?.uid || details?.family_uid,
|
||||
job_description: activeTask.data?.description,
|
||||
assign_mode: 110011,
|
||||
};
|
||||
}
|
||||
|
||||
if (taskType === "new") {
|
||||
const {
|
||||
banner,
|
||||
category,
|
||||
country,
|
||||
description,
|
||||
job_detail,
|
||||
price,
|
||||
timeline_days,
|
||||
title,
|
||||
} = formState;
|
||||
reqData = {
|
||||
banner,
|
||||
category,
|
||||
country,
|
||||
description,
|
||||
job_detail,
|
||||
price: price * 100,
|
||||
timeline_days,
|
||||
title,
|
||||
assign_mode: 110055,
|
||||
family_uid: selectedFamilyUid
|
||||
? selectedFamilyUid
|
||||
: familyDetailsData?.uid || details?.family_uid,
|
||||
};
|
||||
}
|
||||
|
||||
const requiredFields = {
|
||||
banner,
|
||||
// category,
|
||||
currency:country,
|
||||
description,
|
||||
'job detail':job_detail,
|
||||
price,
|
||||
timeline:timeline_days,
|
||||
title,
|
||||
};
|
||||
apiCall
|
||||
.assignFamilyTask(reqData)
|
||||
.then((res) => {
|
||||
if (res.status != 200 || res.data.internal_return < 0) {
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "failed to assign task",
|
||||
});
|
||||
|
||||
for (let field in requiredFields) {
|
||||
if (requiredFields[field] == "") {
|
||||
// let currencyErrMsg = field == "country" && "currency"
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: `${field[0].toUpperCase()+field.slice(1).toLowerCase()} is empty`,
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
}, 3000);
|
||||
}
|
||||
return setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
}, 5000);
|
||||
}
|
||||
if (res.status === 200) {
|
||||
|
||||
reqData = {
|
||||
banner,
|
||||
category,
|
||||
country,
|
||||
description,
|
||||
job_detail,
|
||||
price: price * 100,
|
||||
timeline_days,
|
||||
title,
|
||||
assign_mode: 110055,
|
||||
family_uid: details?.family_uid || familyDetailsData?.uid,
|
||||
};
|
||||
}
|
||||
|
||||
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",
|
||||
});
|
||||
setUpdatePage(prev => !prev) // Updates family task page by calling the useeffect hook
|
||||
|
||||
setUpdatePage(prev => !prev); // Updates family task page by calling the useeffect hook
|
||||
|
||||
dispatch(tableReload({ type: "WALLETTABLE" })); // RELOADS USER WALLET
|
||||
|
||||
//SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||
// message, room
|
||||
let socketMsg = {
|
||||
"audience": "MEMBER",
|
||||
"action": "REFRESH_OFFER",
|
||||
"family_uid": reqData.family_uid,
|
||||
}
|
||||
let socketRoom = `FAMILY-${userDetails.uid}`
|
||||
parentAssignJobToKid(socketMsg, socketRoom) //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||
|
||||
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);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "An Error occured, try again",
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalCom
|
||||
action={action}
|
||||
situation={situation}
|
||||
>
|
||||
<div className="w-11/12 lg:w-[700px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<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{" "}
|
||||
{familyDetailsData?.firstname || details?.firstName}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
onClick={action}
|
||||
setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
}, 5000);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(()=>{ // effect to update family UID when components mounts
|
||||
if(familyDetailsData?.uid){
|
||||
setSelectedFamilyUid(familyDetailsData?.uid)
|
||||
}else if(details?.family_uid){
|
||||
setSelectedFamilyUid(details?.family_uid)
|
||||
}else{
|
||||
setSelectedFamilyUid('')
|
||||
}
|
||||
},[])
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalCom action={action} situation={situation}>
|
||||
<div className="w-11/12 lg:w-[700px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] bg-sky-blue/50 border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide flex items-center">
|
||||
{details ? (
|
||||
` Assign ${details?.firstname}'s Task`
|
||||
) : familyDetailsData ? (
|
||||
` Assign ${familyDetailsData.firstname}'s Task`
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-black">Assign task to{" "}</span>
|
||||
<div className="w-[270px] h-[40px] flex items-center relative after:absolute after:content-['▼'] active:after:rotate-180 after:transition-all after:duration-300 after:z-20 after:right-2 after:top-1/2 after:-translate-y-1/2 after:text-white after:text-lg">
|
||||
<select
|
||||
name=""
|
||||
id=""
|
||||
className="relative z-10 appearance-none text-lg text-white px-2 tracking-wide font-semibold transition-all cursor-pointer bg-blue-900 focus:outline-none border border-gray-200 rounded-full w-full h-full"
|
||||
onChange={handleFamChange}
|
||||
value={selectedFamilyUid}
|
||||
>
|
||||
<option value="" className="">
|
||||
Select a kid
|
||||
</option>
|
||||
{familyList}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#000] 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"
|
||||
>
|
||||
<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>
|
||||
<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>
|
||||
{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 ${
|
||||
taskType !== "new" ? "md:grid-cols-2" : "md:grid-cols-1"
|
||||
}`}
|
||||
>
|
||||
<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
|
||||
className={`job-action-modal-body w-full md:grid ${
|
||||
taskType !== "new" ? "md:grid-cols-2" : "md:grid-cols-1"
|
||||
}`}
|
||||
>
|
||||
<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>
|
||||
{/* Task Type === select */}
|
||||
{taskType == "select" && (
|
||||
<div className="p-4 w-full h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
|
||||
{familyTask?.data?.length ? (
|
||||
familyTask?.data?.map((item, index) => (
|
||||
<div
|
||||
key={item.job_uid}
|
||||
className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer"
|
||||
onClick={() =>
|
||||
<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>
|
||||
{/* Task Type === select */}
|
||||
{taskType == "select" && (
|
||||
<div className="p-4 w-full h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
|
||||
{familyTask?.data?.length ? (
|
||||
familyTask?.data?.map((item, index) => (
|
||||
<div
|
||||
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)
|
||||
}
|
||||
>
|
||||
<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 dark:text-white tracking-wide">
|
||||
{item?.title}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center cursor-default">
|
||||
No Task found!
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{taskType == "new" && (
|
||||
<div className="p-4 w-full h-[400px]">
|
||||
<NewTasks
|
||||
formState={formState}
|
||||
setFormState={setFormState}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/*Right Hand Side for details && Task Type === select */}
|
||||
{taskType == "select" && (
|
||||
<>
|
||||
{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}
|
||||
className="w-[15px] h-[15px] cursor-pointer"
|
||||
/>
|
||||
<p className="w-full text-dark-gray dark:text-white tracking-wide">
|
||||
{item?.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 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
|
||||
rows="5"
|
||||
style={{ resize: "none" }}
|
||||
value={activeTask?.data?.job_detail}
|
||||
readOnly
|
||||
// onChange={handleInputChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<></>
|
||||
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center cursor-default">
|
||||
No Task found!
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
{taskType == "new" && (
|
||||
<div className="p-4 w-full h-[400px]">
|
||||
<NewTasks
|
||||
formState={formState}
|
||||
setFormState={setFormState}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* BTN */}
|
||||
<div className="py-2 px-4 border-t-2 flex justify-between items-center">
|
||||
{/* error or success display */}
|
||||
<div className="w-auto h-auto flex items-center">
|
||||
{requestStatus.message != "" &&
|
||||
(!requestStatus.status ? (
|
||||
{/*Right Hand Side for details && Task Type === select */}
|
||||
{taskType == "select" && (
|
||||
<>
|
||||
{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="job-label">
|
||||
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="job-label">
|
||||
Timeline
|
||||
</label>
|
||||
<p className="p-1 text-sm text-slate-900 dark:text-white">{`${activeTask?.data?.timeline_days} day(s)`}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dummy, no value found for created! thus commented*/}
|
||||
{/* <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 job-label">
|
||||
Delivery Detail
|
||||
</label>
|
||||
<textarea
|
||||
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
|
||||
rows="5"
|
||||
style={{ resize: "none" }}
|
||||
value={activeTask?.data?.job_detail}
|
||||
readOnly
|
||||
// onChange={handleInputChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* BTN */}
|
||||
<div className="py-2 px-4 border-t-2 flex justify-between items-center">
|
||||
{/* error or success display */}
|
||||
<div className="w-auto h-auto flex items-center">
|
||||
{requestStatus.message != "" &&
|
||||
(!requestStatus.status ? (
|
||||
<div
|
||||
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px] self-start`}
|
||||
>
|
||||
{requestStatus.message}
|
||||
</div>
|
||||
) : (
|
||||
requestStatus.status && (
|
||||
<div
|
||||
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px] self-start`}
|
||||
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>
|
||||
) : (
|
||||
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>
|
||||
)
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* End of error or success display */}
|
||||
<div className="w-auto h-auto flex items-center gap-3">
|
||||
<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" />
|
||||
) : taskType == "select" ? (
|
||||
<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>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
disabled={requestStatus.loading}
|
||||
onClick={assignFamilyTask}
|
||||
className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
{`Assign to ${
|
||||
familyDetailsData?.firstname || details?.firstName
|
||||
}`}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{/* End of error or success display */}
|
||||
<div className="w-auto h-auto flex items-center gap-20">
|
||||
<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>
|
||||
)
|
||||
// : (
|
||||
// <button
|
||||
// type="button"
|
||||
// disabled={requestStatus.loading}
|
||||
// onClick={assignFamilyTask}
|
||||
// className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
// >
|
||||
// {details
|
||||
// ? `Assign task to ${details?.firstname}`
|
||||
// : familyDetailsData
|
||||
// ? `Assign task to ${familyDetailsData.firstname}`
|
||||
// : "Assign"}
|
||||
// </button>
|
||||
// )
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</ModalCom>
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</ModalCom>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AssignTaskPopout;
|
||||
|
||||
@@ -56,7 +56,7 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
<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"
|
||||
className="job-label"
|
||||
>
|
||||
Currency
|
||||
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
|
||||
@@ -98,10 +98,11 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
|
||||
{/* Price */}
|
||||
<div className="field w-full">
|
||||
<label htmlFor="price" className="job-label">Price</label>
|
||||
<InputCom
|
||||
fieldClass="px-6 text-right"
|
||||
label="Price"
|
||||
labelClass="tracking-wide"
|
||||
// label="Price"
|
||||
// labelClass="tracking-wide"
|
||||
inputBg="bg-slate-100"
|
||||
type="number"
|
||||
name="price"
|
||||
@@ -117,7 +118,7 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<label
|
||||
htmlFor="timeline_days"
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
|
||||
className="job-label"
|
||||
>
|
||||
Timeline
|
||||
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
|
||||
@@ -151,10 +152,11 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
|
||||
{/* Title */}
|
||||
<div className="field w-full mb-[5px]">
|
||||
<label htmlFor="title" className="job-label">Title</label>
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Title"
|
||||
labelClass="tracking-wide"
|
||||
// label="Title"
|
||||
// labelClass="tracking-wide"
|
||||
inputBg="bg-slate-100"
|
||||
type="text"
|
||||
name="title"
|
||||
@@ -167,10 +169,11 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
|
||||
{/* Description */}
|
||||
<div className="field w-full mb-[5px]">
|
||||
<label htmlFor="description" className="job-label">Description</label>
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Description"
|
||||
labelClass="tracking-wide"
|
||||
// label="Description"
|
||||
// labelClass="tracking-wide"
|
||||
inputBg="bg-slate-100"
|
||||
type="text"
|
||||
name="description"
|
||||
@@ -186,7 +189,7 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
<div className="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'
|
||||
className='job-label'
|
||||
>
|
||||
Job Delivery Details
|
||||
{/* {props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>} */}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import CustomBreadcrumb from "../../Breadcrumb/CustomBreadcrumb";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import Layout from "../../Partials/Layout";
|
||||
import { AddFamily, FamilyBanner, Relatives } from "./Tabs";
|
||||
|
||||
const FamilySettings = () => {
|
||||
let {state} = useLocation()
|
||||
let { state } = useLocation();
|
||||
const tabs = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -58,15 +59,42 @@ const FamilySettings = () => {
|
||||
{/* 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={``}>Family Settings</span>
|
||||
</h1>
|
||||
<CustomBreadcrumb
|
||||
title={"Family Settings"}
|
||||
breadcrumb={[
|
||||
{ link: "/", title: "Home" },
|
||||
{
|
||||
link: "/acc-family",
|
||||
title: "Family Account",
|
||||
},
|
||||
{
|
||||
link: "/familysettings",
|
||||
title: "Family Settings",
|
||||
active: true,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<Link to="/acc-family" className="flex gap-2 items-center text-dark-gray dark:text-white">
|
||||
<svg className="w-5 h-5 rtl:rotate-180" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M6.75 15.75L3 12m0 0l3.75-3.75M3 12h18" />
|
||||
<Link
|
||||
className="item-content relative text-[18px] transition-all duration-300 ease-in-out bg-[#76a5df] text-white font-medium dark:text-white h-12 px-2 flex items-center gap-2 rounded-md shadow-sm justify-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
|
||||
to="/acc-family"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"
|
||||
/>
|
||||
</svg>
|
||||
Family
|
||||
|
||||
<span>Family</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function FamilyTable({
|
||||
familyList,
|
||||
loader,
|
||||
popUpHandler,
|
||||
imageServer
|
||||
imageServer,
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
@@ -55,14 +55,19 @@ export default function FamilyTable({
|
||||
banner,
|
||||
enable_traking,
|
||||
profile_picture,
|
||||
imageServer
|
||||
imageServer,
|
||||
username,
|
||||
}) => {
|
||||
// Check for valid dates
|
||||
const addedDate = added ? added.split(" ")[0] : "N/A";
|
||||
const loginDate = last_login ? formatDateString(last_login) : "N/A";
|
||||
const key = `family-${family_uid}`; // Assign a unique key
|
||||
const image = localStorage.getItem('session_token') ? `${imageServer}${localStorage.getItem('session_token')}/family/${family_uid}` : ''
|
||||
|
||||
const image = localStorage.getItem("session_token")
|
||||
? `${imageServer}${localStorage.getItem(
|
||||
"session_token"
|
||||
)}/family/${family_uid}`
|
||||
: "";
|
||||
|
||||
const trackingStatus =
|
||||
enable_traking === "0"
|
||||
? "Stopped"
|
||||
@@ -80,14 +85,19 @@ export default function FamilyTable({
|
||||
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
// src={profile_picture}
|
||||
src={image || profile_picture || localImgLoad(`images/icons/${banner}`)}
|
||||
src={
|
||||
image ||
|
||||
profile_picture ||
|
||||
localImgLoad(`images/icons/${banner}`)
|
||||
}
|
||||
alt={`Avatar of ${firstname} ${lastname}`}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col flex-[0.9]">
|
||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||
{`${firstname} ${lastname} (${age < 10 ? `0${age}` : age})`}
|
||||
<h1 className="font-bold text-lg text-dark-gray dark:text-white whitespace-nowrap">
|
||||
{`${firstname} ${lastname}`}{" "}
|
||||
<span className="ml-1 text-sm">{`[${username}]`}</span>
|
||||
</h1>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Added: <span className="text-purple ml-1">{addedDate}</span>
|
||||
@@ -136,7 +146,7 @@ export default function FamilyTable({
|
||||
task_count,
|
||||
family_uid,
|
||||
banner,
|
||||
image
|
||||
image,
|
||||
})
|
||||
}
|
||||
type="button"
|
||||
@@ -186,7 +196,13 @@ export default function FamilyTable({
|
||||
</thead>
|
||||
<tbody className="h-full">
|
||||
{currentFamilyList?.map((familyMember, index) => {
|
||||
return <FamilyRow key={index} {...familyMember} imageServer={imageServer} />;
|
||||
return (
|
||||
<FamilyRow
|
||||
key={index}
|
||||
{...familyMember}
|
||||
imageServer={imageServer}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
import React, { Suspense, lazy, useEffect, useMemo, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { apiConst } from "../../lib/apiConst";
|
||||
import usersService from "../../services/UsersService";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
|
||||
|
||||
// Lazy Imports for components
|
||||
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyNewWaitlist"));
|
||||
const FamilyTasks = lazy(() => import("./Tabs/FamilyNewTasks"));
|
||||
const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending"));
|
||||
|
||||
export default function FamilyTableNew() {
|
||||
let { pathname } = useLocation();
|
||||
|
||||
// Initial state for family details
|
||||
const initialDetailState = {
|
||||
loading: false,
|
||||
data: null,
|
||||
link: "",
|
||||
};
|
||||
|
||||
const [assignTaskChecker, setAssignTaskChecker] = useState(false);
|
||||
|
||||
// console.log('accountDetails',accountDetails)
|
||||
// State for family details, tasks, waitlist, and pending
|
||||
const [details, setDetails] = useState({
|
||||
familyDetails: { ...initialDetailState },
|
||||
familyTasks: { ...initialDetailState },
|
||||
familyWaitList: { ...initialDetailState },
|
||||
familyPending: { ...initialDetailState },
|
||||
});
|
||||
|
||||
// Function to reset family details, tasks, waitlist, and pending
|
||||
const resetDetails = () => {
|
||||
setDetails({
|
||||
familyDetails: { ...initialDetailState },
|
||||
familyTasks: { ...initialDetailState },
|
||||
familyWaitList: { ...initialDetailState },
|
||||
familyPending: { ...initialDetailState },
|
||||
});
|
||||
};
|
||||
|
||||
const [updatePage, setUpdatePage] = useState(false); // State to determine when to update the page
|
||||
|
||||
// State for family task data
|
||||
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
|
||||
|
||||
// State for active task
|
||||
const [activeTask, setActiveTask] = useState({ id: 0, data: {} });
|
||||
|
||||
// State for error messages
|
||||
const [errMsg, setErrMsg] = useState("");
|
||||
|
||||
// State for family task popout
|
||||
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
|
||||
|
||||
// Create an instance of the usersService class
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
// Function to handle toggling the family task popout
|
||||
const familyPopUpHandler = () => {
|
||||
setFamilyTaskPopout((prev) => !prev);
|
||||
};
|
||||
|
||||
// Array of tab names
|
||||
const tabs = [
|
||||
{ id: 1, name: "Tasks" },
|
||||
{ id: 2, name: "Waiting" },
|
||||
{ id: 3, name: "Pending" },
|
||||
];
|
||||
|
||||
// State for the currently selected tab
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
|
||||
// Function to handle tab changes
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
// Object that maps tab names to their corresponding components
|
||||
const tabComponents = {
|
||||
Tasks: (
|
||||
<FamilyTasks
|
||||
image_link={details.familyTasks.link}
|
||||
loader={details.familyTasks.loading}
|
||||
familyData={details.familyTasks.data}
|
||||
action={familyPopUpHandler}
|
||||
setAssignTaskChecker={setAssignTaskChecker}
|
||||
/>
|
||||
),
|
||||
Waiting: (
|
||||
<FamilyWaitlist
|
||||
image_link={details.familyWaitList.link}
|
||||
familyData={details.familyWaitList.data}
|
||||
loader={details.familyWaitList.loading}
|
||||
setUpdatePage={setUpdatePage}
|
||||
/>
|
||||
),
|
||||
Pending: (
|
||||
<FamilyPending
|
||||
image_link={details.familyPending.link}
|
||||
familyData={details.familyPending.data}
|
||||
loader={details.familyPending.loading}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
const defaultTabComponent = tabComponents.Tasks;
|
||||
|
||||
// Selected tab component based on the current 'tab'
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
// Effect to manage family details and related data
|
||||
useEffect(() => {
|
||||
const manageFamily = async () => {
|
||||
try {
|
||||
resetDetails();
|
||||
|
||||
setDetails({
|
||||
familyTasks: { loading: true },
|
||||
familyWaitList: { loading: true },
|
||||
familyPending: { loading: true },
|
||||
});
|
||||
|
||||
// const { family_uid } = accountDetails;
|
||||
// const reqData = { family_uid };
|
||||
|
||||
const [familyTasksData, familyWaitingRes, familyPendingRes] =
|
||||
await Promise.all([
|
||||
apiCall.getMyActiveJobList(),
|
||||
apiCall.ManageFamilyNewWaitlist(),
|
||||
apiCall.ManageFamilyPending(),
|
||||
]);
|
||||
|
||||
let tasksData = familyTasksData?.data?.result_list;
|
||||
let _familyWaitData = familyWaitingRes?.data?.result_list;
|
||||
let familyPendingData = familyPendingRes?.data?.result_list;
|
||||
|
||||
// Getting the image server link
|
||||
let imageServerLink = familyWaitingRes.data?.session_image_server;
|
||||
|
||||
// Function to check for errors in data
|
||||
const checkDataError = (data) => data?.internal_return < 0;
|
||||
|
||||
if (
|
||||
checkDataError(tasksData) ||
|
||||
checkDataError(_familyWaitData) ||
|
||||
checkDataError(familyPendingData)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDetails({
|
||||
familyTasks: {
|
||||
loading: false,
|
||||
data: tasksData,
|
||||
link: imageServerLink,
|
||||
},
|
||||
familyWaitList: {
|
||||
loading: false,
|
||||
data: _familyWaitData,
|
||||
link: imageServerLink,
|
||||
},
|
||||
familyPending: {
|
||||
loading: false,
|
||||
data: familyPendingData,
|
||||
link: imageServerLink,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
resetDetails();
|
||||
setErrMsg("An error occurred");
|
||||
throw new Error(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Invoke the manageFamily function when the component mounts
|
||||
manageFamily();
|
||||
}, [updatePage]);
|
||||
|
||||
// Effect to manage family tasks
|
||||
useEffect(() => {
|
||||
let checkFamilyTask = true;
|
||||
const reqData = {
|
||||
limit: 30,
|
||||
offset: 0,
|
||||
job_type: "FAMILY",
|
||||
action: apiConst.WRENCHBOARD_PICTURE_FAMMEMBER,
|
||||
};
|
||||
|
||||
if (checkFamilyTask) {
|
||||
setFamilyTask({ loading: true });
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
// Cleanup function to prevent memory leaks
|
||||
return () => {
|
||||
checkFamilyTask = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
// console.log(updatePage);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full`}
|
||||
>
|
||||
<div className="relative w-full sm:rounded-lg overflow-x-auto">
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="h-full min-h-[609px] w-full overflow-hidden flex justify-center items-center">
|
||||
<LoadingSpinner size="16" color="sky-blue" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-3 min-h-[575px]">
|
||||
<div className="col-span-3 h-full w-full">
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="w-full pr-8 flex items-center gap-1 border-b border-b-[#FAFAF]">
|
||||
<ul className="flex gap-2 items-center 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-[2px] ${
|
||||
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] h-full">
|
||||
<div className="h-full relative overflow-y-auto">
|
||||
<Suspense
|
||||
fallback={<LoadingSpinner size="16" color="sky-blue" />}
|
||||
>
|
||||
{selectedTabComponent}
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
{familyTaskPopout && (
|
||||
<AssignTaskPopout
|
||||
action={familyPopUpHandler}
|
||||
situation={familyTaskPopout}
|
||||
familyTask={familyTask}
|
||||
setFamilyTask={setFamilyTask}
|
||||
setActiveTask={setActiveTask}
|
||||
activeTask={activeTask}
|
||||
setUpdatePage={setUpdatePage}
|
||||
// updateFamilyPendingTable={updateFamilyPendingTable}
|
||||
pathname={pathname}
|
||||
assignTaskChecker={assignTaskChecker}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from 'react'
|
||||
|
||||
import Layout from '../Partials/Layout'
|
||||
import ParentWaiting from '../MyOffers/ParentWaiting'
|
||||
|
||||
export default function ParentWaitingLayout() {
|
||||
return (
|
||||
<Layout>
|
||||
<ParentWaiting />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import { PaginatedList, handlePagingFunc } from "../../Pagination";
|
||||
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
|
||||
|
||||
export default function FamilyPending({ familyData, image_link, loader }) {
|
||||
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
||||
|
||||
let filteredFamilyData = useMemo(
|
||||
() => familyData?.filter((data) => data.family_uid !== ""),
|
||||
[familyData]
|
||||
);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem =
|
||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentPendingTasks = filteredFamilyData?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
|
||||
console.log(image_link);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full p-3 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px]`}
|
||||
>
|
||||
{familyData && (
|
||||
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
|
||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||
<tbody>
|
||||
{
|
||||
<>
|
||||
{currentPendingTasks.length > 0 ? (
|
||||
currentPendingTasks.map((value, index) => {
|
||||
let deliveryDate = value?.expire?.split(" ")[0];
|
||||
let thePrice = PriceFormatter(
|
||||
value?.price * 0.01,
|
||||
value?.currency_code,
|
||||
value?.currency
|
||||
);
|
||||
let image = `${image_link}${localStorage.getItem(
|
||||
"session_token"
|
||||
)}/job/${value.job_uid}`;
|
||||
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-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={image}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col flex-[0.9]">
|
||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||
{value.title}
|
||||
</h1>
|
||||
<div>{value.description}</div>
|
||||
<span className="text-sm text-thin-light-gray flex items-start gap-1">
|
||||
Price:{" "}
|
||||
<span className="text-purple">
|
||||
{thePrice}
|
||||
</span>
|
||||
</span>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Duration:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{value.timeline_days} day(s)
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Expire:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{deliveryDate}
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Sent to:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{value.job_to}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td className="text-right py-4 px-2 flex justify-end items-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setJobPopout({ show: true, data: value });
|
||||
}}
|
||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<tr>
|
||||
<td className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap text-center py-4 px-2">
|
||||
No Pending Task!
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0}
|
||||
next={currentPage + itemsPerPage >= filteredFamilyData.length}
|
||||
data={filteredFamilyData}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Active Job Popout */}
|
||||
{jobPopout.show && (
|
||||
<PendingJobsPopout
|
||||
details={jobPopout.data}
|
||||
onClose={() => {
|
||||
setJobPopout({ show: false, data: {} });
|
||||
}}
|
||||
situation={jobPopout.show}
|
||||
/>
|
||||
)}
|
||||
{/* End of Active Job Popout */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import { handlePagingFunc } from "../../Pagination/HandlePagination";
|
||||
import PaginatedList from "../../Pagination/PaginatedList";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
|
||||
export default function FamilyNewTasks({
|
||||
familyData,
|
||||
className,
|
||||
loader,
|
||||
action,
|
||||
image_link,
|
||||
}) {
|
||||
let navigate = useNavigate();
|
||||
let { pathname } = useLocation();
|
||||
|
||||
// ...
|
||||
let filteredFamilyData = useMemo(
|
||||
() => familyData?.filter((data) => data.family_uid !== ""),
|
||||
[familyData]
|
||||
);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem =
|
||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentTasks = filteredFamilyData?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] overflow-hidden rounded-2xl section-shadow p-3 ${
|
||||
familyData?.length <= 0 && "flex items-center justify-center"
|
||||
}`}
|
||||
>
|
||||
{loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
|
||||
<LoadingSpinner size={16} color="sky-blue" />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{familyData && (
|
||||
<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?.length <= 0 ? (
|
||||
<tr>
|
||||
<td
|
||||
colSpan="2"
|
||||
className="text-center py-4 font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap flex items-center justify-center gap-1"
|
||||
>
|
||||
You currently have no active tasks{" "}
|
||||
<span
|
||||
className="text-blue-400 cursor-pointer hover:underline transition duration-150"
|
||||
onClick={action}
|
||||
>
|
||||
add new
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
currentTasks.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
|
||||
);
|
||||
let image = `${image_link}${localStorage.getItem(
|
||||
"session_token"
|
||||
)}/job/${value.job_uid}`;
|
||||
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-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={image}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col flex-[0.9]">
|
||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||
{value.title}
|
||||
</h1>
|
||||
<div className="flex flex-col sm:flex-row items-start gap-1 md:gap-4 md: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,
|
||||
},
|
||||
});
|
||||
}}
|
||||
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) >=
|
||||
filteredFamilyData?.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
data={filteredFamilyData}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
import { useState } from "react";
|
||||
import SuggestTask from "../../FamilyPopup/SuggestTask";
|
||||
import { PaginatedList, handlePagingFunc } from "../../Pagination";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
|
||||
const FamilyNewWaitlist = ({
|
||||
familyData,
|
||||
className,
|
||||
accountDetails,
|
||||
loader,
|
||||
setUpdatePage
|
||||
}) => {
|
||||
const [popUp, setPopUp] = useState({ show: false, data: {} });
|
||||
const [continueTaskPopup, setContinueTaskPopup] = useState({
|
||||
show: false,
|
||||
data: {},
|
||||
});
|
||||
|
||||
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?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
|
||||
|
||||
const openPopUp = (value) => {
|
||||
setPopUp({ show: true, data: { ...value } });
|
||||
};
|
||||
|
||||
const closePopUp = () => {
|
||||
setPopUp({ show: false, data: {} });
|
||||
};
|
||||
|
||||
const openContinueTaskPopup = (value) => {
|
||||
setContinueTaskPopup({ show: true, data: { ...value } });
|
||||
};
|
||||
|
||||
const closeContinueTaskPopup = () => {
|
||||
setContinueTaskPopup({ show: false, data: {} });
|
||||
};
|
||||
|
||||
console.log("Check this >>",continueTaskPopup)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] p-3 overflow-hidden rounded-2xl section-shadow ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
{loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
|
||||
<LoadingSpinner size={16} color="sky-blue" />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{familyData && (
|
||||
<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 selectedImage = require(`../../../assets/images/family/${
|
||||
value?.banner || "default.jpg"
|
||||
}`);
|
||||
// console.log("VALUE", value);
|
||||
// let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
|
||||
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={selectedImage}
|
||||
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 flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-bold text-dark-gray dark:text-white">
|
||||
{addedDate}
|
||||
</p>
|
||||
<p className="text-xs py-1.5 w-[70px] cursor-default tracking-wide rounded-full bg-gold text-white flex justify-center items-center">
|
||||
{value.firstname}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="text-right py-4 px-2 flex justify-end">
|
||||
<button
|
||||
onClick={() => openPopUp(value)}
|
||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
{/* View */}
|
||||
<Icons name="right-arrow" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage === 0}
|
||||
next={currentPage + itemsPerPage >= familyData?.length}
|
||||
data={familyData}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{popUp.show && (
|
||||
<SuggestTask
|
||||
details={popUp.data}
|
||||
onClose={closePopUp}
|
||||
continuePopupData={openContinueTaskPopup}
|
||||
situation={popUp.show}
|
||||
/>
|
||||
)}
|
||||
|
||||
{continueTaskPopup.show && (
|
||||
<AssignTaskPopout
|
||||
details={continueTaskPopup.data}
|
||||
action={closeContinueTaskPopup}
|
||||
situation={continueTaskPopup.show}
|
||||
setUpdatePage={setUpdatePage}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FamilyNewWaitlist;
|
||||
@@ -5,7 +5,7 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
|
||||
|
||||
const FamilyWaitlist = memo(
|
||||
({ familyData, className, accountDetails, loader }) => {
|
||||
({ familyData, className, accountDetails, loader, setUpdatePage }) => {
|
||||
const [popUp, setPopUp] = useState({ show: false, data: {} });
|
||||
const [continueTaskPopup, setContinueTaskPopup] = useState({
|
||||
show: false,
|
||||
@@ -144,6 +144,7 @@ const FamilyWaitlist = memo(
|
||||
details={continueTaskPopup.data}
|
||||
action={closeContinueTaskPopup}
|
||||
situation={continueTaskPopup.show}
|
||||
setUpdatePage={setUpdatePage}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -7,11 +7,13 @@ import React, {
|
||||
} from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import FamilyTable from "./FamilyTable";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function FamilyAcc() {
|
||||
// State to store the selected year and month
|
||||
@@ -107,6 +109,7 @@ export default function FamilyAcc() {
|
||||
if (data?.internal_return >= 0 && data?.status === "OK") {
|
||||
const { result_list, session_image_server } = data;
|
||||
setFamilyList({ result_list, session_image_server });
|
||||
sessionStorage.setItem("family_list", JSON.stringify(result_list))
|
||||
setLoader(false);
|
||||
} else {
|
||||
return;
|
||||
@@ -136,7 +139,18 @@ export default function FamilyAcc() {
|
||||
<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={``}>Family Accounts</span>
|
||||
{/* <span className={``}>Family Accounts</span> */}
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {'Family Account'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/acc-family", title: "Family Account", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{familyList?.result_list?.length <
|
||||
process.env.REACT_APP_MAX_FAMILY_MEMBERS &&
|
||||
!loader && (
|
||||
@@ -150,31 +164,44 @@ export default function FamilyAcc() {
|
||||
)}
|
||||
</h1>
|
||||
</div>
|
||||
<Link
|
||||
to={`/familysettings`}
|
||||
state={{ imageServer: familyList?.session_image_server }}
|
||||
className="slider-btns flex space-x-4 w-12 h-12 rounded-md shadow-sm justify-center items-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6 dark:stroke-white"
|
||||
|
||||
<div className="flex gap-4 items-center">
|
||||
<Link state={familyList} to="/acc-family/activities" className={`nav-item flex items-center rounded-md shadow-sm justify-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)] bg-[#76a5df] text-white px-2 gap-2`}>
|
||||
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
|
||||
<Icons name="pending-job" />
|
||||
</span>
|
||||
<span
|
||||
className={`item-content relative text-[18px] transition-all duration-300 ease-in-out font-medium dark:text-white h-12 flex items-center`}
|
||||
>
|
||||
Activities
|
||||
</span>
|
||||
</Link>
|
||||
<Link
|
||||
to={`/familysettings`}
|
||||
state={{ imageServer: familyList?.session_image_server }}
|
||||
className="slider-btns flex space-x-4 w-12 h-12 rounded-md shadow-sm justify-center items-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)] bg-[#76a5df] text-white"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
</Link>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6 dark:stroke-white"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z"
|
||||
/>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
|
||||
<FamilyTable
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Form, Formik } from "formik";
|
||||
import { useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import { Form, Formik } from "formik";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
|
||||
const DEFAULT_IMAGE = require("../../assets/images/family/default.jpg");
|
||||
const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
@@ -51,21 +50,47 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
};
|
||||
|
||||
const handleParentSuggestion = (values) => {
|
||||
if (suggestedNextStep == "Send Task") {
|
||||
let firstName = state?.firstname;
|
||||
let family_uid = state?.family_uid;
|
||||
continuePopupData({ ...details, firstName, family_uid });
|
||||
if (suggestedNextStep === "Send Task") {
|
||||
let firstname = state?.firstname || details?.firstname;
|
||||
let family_uid = state?.family_uid || details?.family_uid;
|
||||
continuePopupData({
|
||||
...details,
|
||||
firstname,
|
||||
family_uid,
|
||||
});
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const isActivitiesPage = pathname === "/acc-family/activities";
|
||||
const isManageFamilyPage = pathname === "/manage-family";
|
||||
|
||||
const getButtonText = () => {
|
||||
if (isActivitiesPage) {
|
||||
return suggestedNextStep === "Send Task" ? "Continue" : "Complete";
|
||||
} else {
|
||||
if (!isManageFamilyPage) {
|
||||
if (submitTask.loading) return "Submitting Task";
|
||||
if (submitTask.state === "success") return "Task Submitted";
|
||||
if (submitTask.state === "bad") return "An Error Occurred";
|
||||
return "Send to Parents";
|
||||
} else {
|
||||
return suggestedNextStep === "Send Task" ? "Continue" : "Complete";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
console.log(details);
|
||||
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation}>
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
{pathname === "/manage-family"
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[48rem] h-full lg:h-[627px] 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-[1.875rem] py-[1.4375rem] border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
{isManageFamilyPage
|
||||
? `${state?.firstname}'s Suggested Task`
|
||||
: isActivitiesPage
|
||||
? `${details?.firstname}'s Suggested Task`
|
||||
: "Suggest to Parent"}
|
||||
</h1>
|
||||
<button
|
||||
@@ -97,19 +122,21 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={
|
||||
pathname !== "/manage-family"
|
||||
? handleSuggestedTask
|
||||
: handleParentSuggestion
|
||||
isActivitiesPage
|
||||
? handleParentSuggestion
|
||||
: isManageFamilyPage
|
||||
? handleParentSuggestion
|
||||
: handleSuggestedTask
|
||||
}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form>
|
||||
<div className="p-5 w-full bg-white rounded-md flex justify-between">
|
||||
<Form className="h-[33.875rem] flex flex-col">
|
||||
<div className="px-5 w-full bg-white rounded-md flex justify-between items-center h-full">
|
||||
{/* Image Section */}
|
||||
<div className="p-4 w-full md:w-2/4 md:border-r-2">
|
||||
<div className="p-4 w-full md:w-2/4 md:border-r-2 h-full flex items-center">
|
||||
<div
|
||||
className="w-full h-[236px] p-6 bg-gray-400 rounded-xl overflow-hidden"
|
||||
className="w-full h-[14.75rem] p-6 bg-gray-400 rounded-xl overflow-hidden"
|
||||
style={{
|
||||
background: `url(${selectedImage}) center / contain no-repeat`,
|
||||
}}
|
||||
@@ -117,17 +144,22 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
</div>
|
||||
|
||||
{/* ACTION SECTION */}
|
||||
<div className="p-4 w-full md:w-2/4 h-full">
|
||||
<div className="p-4 w-full md:w-2/4 h-full flex flex-col justify-between">
|
||||
{/* Title */}
|
||||
<div className="field w-full mb-[15px]">
|
||||
<div className="field w-full mb-[.9375rem]">
|
||||
<InputCom
|
||||
fieldClass={
|
||||
pathname === "/manage-family" ? "px-2" : "px-6"
|
||||
pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities"
|
||||
? "px-2"
|
||||
: "px-6"
|
||||
}
|
||||
label="Title"
|
||||
labalClass="text-[1.125rem]"
|
||||
labelClass="tracking-wide"
|
||||
inputBg={
|
||||
pathname === "/manage-family"
|
||||
pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities"
|
||||
? "bg-white"
|
||||
: "bg-slate-100"
|
||||
}
|
||||
@@ -147,15 +179,15 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div className="field w-full mb-[5px]">
|
||||
<div className="field w-full mb-[.3125rem]">
|
||||
<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'
|
||||
className='input-label text-[#181c32] dark:text-white text-[1.125rem] leading-[1.3102rem] font-semibold flex items-center gap-1'
|
||||
>
|
||||
Description
|
||||
{props.errors.description &&
|
||||
props.touched.description && (
|
||||
<span className="text-[12px] text-red-500">
|
||||
<span className="text-[.75rem] text-red-500">
|
||||
{props.errors.description}
|
||||
</span>
|
||||
)}
|
||||
@@ -164,9 +196,10 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
id="description"
|
||||
rows="5"
|
||||
className={`input-field pt-2 placeholder:text-base text-dark-gray dark:text-white w-full ${
|
||||
pathname === "/manage-family"
|
||||
? "px-2 h-[110px]"
|
||||
: "bg-slate-100 px-3 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px] h-[130px]"
|
||||
pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities"
|
||||
? "px-2 h-[6.875rem]"
|
||||
: "bg-slate-100 px-3 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[.625rem] h-[8.125rem]"
|
||||
}`}
|
||||
style={{ resize: "none" }}
|
||||
name="description"
|
||||
@@ -177,8 +210,9 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
</div>
|
||||
|
||||
{/* Radio buttons for family */}
|
||||
{pathname === "/manage-family" ? (
|
||||
<div className="h-[20px] w-full border-t dark:border-[#5356fb29] border-light-purple relative">
|
||||
{pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities" ? (
|
||||
<div className="h-[3.75rem] w-full border-t dark:border-[#5356fb29] border-light-purple relative">
|
||||
<div id="my-radio-group" className="sr-only">
|
||||
Parent suggested next step
|
||||
</div>
|
||||
@@ -196,7 +230,7 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
role="group"
|
||||
key={idx}
|
||||
htmlFor={`parent-suggested-${idx}`}
|
||||
className={`transition duration-150 ease-in-out parent-suggest group cursor-pointer`}
|
||||
className={`transition duration-150 ease-in-out parent-suggest group cursor-pointer flex items-center`}
|
||||
onClick={() => setSuggestedNextStep(title)}
|
||||
>
|
||||
<input
|
||||
@@ -205,19 +239,19 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
value={title}
|
||||
checked={suggestedNextStep === title}
|
||||
onChange={switchNextStep}
|
||||
className={`transition duration-150 ease-in-out parent-suggest pointer-events-none`}
|
||||
className={`transition duration-150 ease-in-out parent-suggest pointer-events-none w-[1.125rem] h-[1.125rem]`}
|
||||
/>
|
||||
<span
|
||||
onClick={() => setSuggestedNextStep(title)}
|
||||
id={`parent-suggested-${idx}`}
|
||||
name="parent-suggested"
|
||||
className={`ml-1 ${
|
||||
title == "Not Now"
|
||||
title === "Not Now"
|
||||
? "text-red-500"
|
||||
: title == "Duplicate"
|
||||
: title === "Duplicate"
|
||||
? "text-purple"
|
||||
: "text-black"
|
||||
} font-semibold`}
|
||||
} font-semibold text-[1.125rem]`}
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
@@ -229,7 +263,7 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full h-[70px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
||||
<div className="w-full h-[4.375rem] 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"
|
||||
@@ -243,19 +277,9 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
disabled={props.isSubmitting}
|
||||
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full transition duration-150 ease-in-out flex items-center"
|
||||
>
|
||||
{pathname !== "/manage-family" ? (
|
||||
{/* {pathname === "/acc-family/activities" ? (
|
||||
<>
|
||||
{submitTask.loading
|
||||
? "Submitting Task"
|
||||
: submitTask.state == "success"
|
||||
? "Task Submitted"
|
||||
: submitTask.state == "bad"
|
||||
? "An Error Occurred"
|
||||
: "Send to Parents"}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{suggestedNextStep == "Send Task" ? (
|
||||
{suggestedNextStep === "Send Task" ? (
|
||||
<>
|
||||
Continue <Icons name="chevron-right" />
|
||||
</>
|
||||
@@ -263,7 +287,32 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
"Complete"
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
) : (
|
||||
<>
|
||||
{pathname !== "/manage-family" ? (
|
||||
<>
|
||||
{submitTask.loading
|
||||
? "Submitting Task"
|
||||
: submitTask.state === "success"
|
||||
? "Task Submitted"
|
||||
: submitTask.state === "bad"
|
||||
? "An Error Occurred"
|
||||
: "Send to Parents"}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{suggestedNextStep === "Send Task" ? (
|
||||
<>
|
||||
Continue <Icons name="chevron-right" />
|
||||
</>
|
||||
) : (
|
||||
"Complete"
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)} */}
|
||||
{getButtonText()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,7 @@ export default function InputCom({
|
||||
forgotPassword,
|
||||
parentClass,
|
||||
labelClass,
|
||||
labalClass,
|
||||
inputClass,
|
||||
fieldClass,
|
||||
onClick,
|
||||
@@ -53,7 +54,7 @@ export default function InputCom({
|
||||
<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] text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1 ${labalClass}`}
|
||||
htmlFor={name}
|
||||
>
|
||||
{label}
|
||||
@@ -86,7 +87,7 @@ export default function InputCom({
|
||||
className={`input-wrapper w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-base ${
|
||||
inputClass
|
||||
? inputClass
|
||||
: "text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] border"
|
||||
: "text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] border"
|
||||
}`}
|
||||
>
|
||||
<input
|
||||
|
||||
@@ -1,44 +1,29 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import ParentWaiting from "../MyOffers/ParentWaiting";
|
||||
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
|
||||
import FamilyActiveLSlde from "./FamilyActiveLSlde";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
|
||||
export default function FamilyDash({ familyOffers, MyActiveJobList }) {
|
||||
export default function FamilyDash({ MyActiveJobList=[], serverImg }) {
|
||||
// console.log("PROPS IN FAMILY DASH->", familyOffers?.result_list);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const userApi = new usersService();
|
||||
|
||||
const trending = MyActiveJobList;
|
||||
// const trending = MyActiveJobList;
|
||||
|
||||
const { familyBannersList } = useSelector((state) => state.familyBannersList);
|
||||
|
||||
const { familyResources:{ tab_categories } } = useSelector((state) => state.familyResources);
|
||||
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
|
||||
let [reloadBanner, setReloadBanner] = useState(0)
|
||||
|
||||
// DO NOT UNCOMMENT THE CODE BELOW
|
||||
|
||||
// let [familyBannersList, setFamilyBannersList] = useState({loading:false, result:{}})
|
||||
// const getFamilyBanners = async () => { // FUNCTION TO GET FAMILY BANNERS
|
||||
// setFamilyBannersList({loading:true, result:[]});
|
||||
// try {
|
||||
// const res = await userApi.getFamilyBannersList();
|
||||
// setFamilyBannersList({loading:false, result:res.data});
|
||||
// console.log('TEST RESPONSE', res.data)
|
||||
// } catch (error) {
|
||||
// setFamilyBannersList({loading:false, result:[]});
|
||||
// console.log("Error getting tasks");
|
||||
// }
|
||||
// };
|
||||
|
||||
// useEffect(()=>{
|
||||
// getFamilyBanners()
|
||||
// },[])
|
||||
|
||||
useEffect(()=>{
|
||||
if(reloadBanner >= 2){
|
||||
dispatch(tableReload({ type: "FAMILYBANNERSLIST" })); // RELOAD FAMILY BANNERS LIST EVERY 10 MINS
|
||||
@@ -56,34 +41,42 @@ export default function FamilyDash({ familyOffers, MyActiveJobList }) {
|
||||
return (
|
||||
<div>
|
||||
<div className="home-page-wrapper">
|
||||
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
|
||||
{/* Header */}
|
||||
<div className="text-white mb-4 min-h-[3rem] px-2 w-full flex justify-between items-center rounded-xl bg-family-header-bg">
|
||||
<div className="w-full">
|
||||
<div className="w-full flex flex-wrap gap-x-4 ">
|
||||
<p className="text-lg font-normal leading-5">Welcome</p>
|
||||
<div className="">
|
||||
<h1 className="text-lg font-normal leading-5">{`${userDetails?.firstname} ${userDetails?.lastname}`}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="py-1 w-full text-sm text-right self-end">
|
||||
<p className="leading-4">Last Login: {`${userDetails?.last_login.split(' ')[0]}`}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{process.env.REACT_APP_SHOW_NEW_FAMILY_DASH == '1' &&
|
||||
<>
|
||||
{familyBannersList?.result_list && Object.keys(familyBannersList?.result_list).length > 0 &&
|
||||
{familyBannersList?.loading ?
|
||||
<div className="w-full bg-white rounded-2xl">
|
||||
<LoadingSpinner size='10' color='sky-blue' height='h-[20rem]' />
|
||||
</div>
|
||||
:
|
||||
familyBannersList?.result_list && Object.keys(familyBannersList?.result_list).length > 0 ?
|
||||
// Loop for Family Banners
|
||||
<div className="w-full mb-4 grid grid-cols-2 md:grid-cols-3 gap-2 md:gap-4">
|
||||
{Object.keys(familyBannersList?.result_list).map((item, index) => {
|
||||
let content = familyBannersList?.result_list[item]
|
||||
let action = item == 'recommend' ? 'familymarket' : 'mytask'
|
||||
// let action = item == 'recommend' ? 'familymarket' : 'mytask'
|
||||
return (
|
||||
<Link key={item} to={`/${action}`} className={`h-44 rounded-lg bg-white dark:bg-dark-white shadow-md flex justify-center items-center transition-all duration-300 hover:shadow-sm`}>
|
||||
<Link key={item} to={`/${content.banner.action}`} className={`rounded-xl bg-white dark:bg-dark-white shadow-md flex justify-center items-center transition-all duration-300 hover:shadow-sm`}>
|
||||
<div className="h-full w-full">
|
||||
<img className="w-full h-1/2 object-cover rounded-t-lg" src={content.banner.image} alt='banner image' />
|
||||
<div className="px-2 py-1">
|
||||
<h1 className="text-lg text-[#083e21] dark:text-white font-normal tracking-wide">{content.banner.text}</h1>
|
||||
<p className="text-sm text-black dark:text-white">{content.banner.description}</p>
|
||||
</div>
|
||||
{/* Horizontal Line */}
|
||||
<div className="w-full h-[1px] bg-slate-300"></div>
|
||||
|
||||
<div className="px-2 py-1 flex justify-between items-center">
|
||||
<span className="text-slate-400 dark:text-slate-200 text-sm">6w ago</span>
|
||||
{/* Dots */}
|
||||
<div className="flex justify-center gap-1">
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<img className="w-full h-[10rem] object-cover rounded-t-xl" src={content.banner.image} alt='banner image' />
|
||||
<div className="flex flex-col justify-between">
|
||||
<div className="px-2 py-2 border-b border-transparent min-h-[4rem] flex flex-col gap-1">
|
||||
<h1 className="text-lg text-[#083e21] dark:text-white font-bold tracking-wide">{content.banner.text}</h1>
|
||||
<p className="text-sm text-black dark:text-white">{content.banner.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,56 +84,58 @@ export default function FamilyDash({ familyOffers, MyActiveJobList }) {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
:
|
||||
null
|
||||
}
|
||||
|
||||
<div className="my-4">
|
||||
{tab_categories?.data &&
|
||||
<div className="mb-4">
|
||||
<h1 className="my-4 text-26 font-bold text-dark-gray dark:text-white tracking-wide">Resources</h1>
|
||||
<div className="w-full grid grid-cols-2 md:grid-cols-3 gap-2 md:gap-4">
|
||||
{[1,2,3,4,5].map((item, index) => (
|
||||
<Link key={item} to={`/`} className={`h-44 rounded-lg bg-white dark:bg-dark-white shadow-md flex justify-center items-center transition-all duration-300 hover:shadow-sm`}>
|
||||
<div className="h-full w-full">
|
||||
<img className="w-full h-1/2 object-cover rounded-t-lg" src={''} alt='banner image' />
|
||||
<div className="px-2 py-1">
|
||||
<h1 className="text-lg text-[#083e21] dark:text-white font-medium tracking-wide">{'Heading'}</h1>
|
||||
<p className="text-sm text-black dark:text-white">{'Description'}</p>
|
||||
</div>
|
||||
{/* Horizontal Line */}
|
||||
<div className="w-full h-[1px] bg-slate-300"></div>
|
||||
|
||||
<div className="px-2 py-1 flex justify-between items-center">
|
||||
<span className="text-slate-400 dark:text-slate-200 text-sm">6w ago</span>
|
||||
{/* Dots */}
|
||||
<div className="flex justify-center gap-1">
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<div className="w-full grid grid-cols-2 md:grid-cols-4 gap-2 md:gap-4">
|
||||
{tab_categories.data.map((item) => {
|
||||
// if(item.enabled){
|
||||
// }
|
||||
return (
|
||||
<Link key={item.uid} to={`/${item?.action}`} className={`group rounded-xl bg-white dark:bg-dark-white shadow-md flex justify-center items-center transition-all duration-300 hover:shadow-sm`}>
|
||||
<div className="h-full w-full">
|
||||
<div className="w-full h-[8rem] rounded-t-xl overflow-hidden">
|
||||
<img className="w-full h-full group-hover:scale-110 object-cover transition-all duration-300" src={item?.banner} alt='banner image' />
|
||||
</div>
|
||||
<div className="flex flex-col justify-between">
|
||||
<div className="px-2 py-1 border-b border-transparent min-h-[2rem] flex justify-between items-center gap-1">
|
||||
<h1 className="text-lg text-[#083e21] dark:text-white font-bold tracking-wide">{item?.content}</h1>
|
||||
<div className="flex justify-center gap-1">
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
<div className="w-1 h-1 bg-slate-400 rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</>
|
||||
}
|
||||
|
||||
{familyOffers?.result_list && familyOffers?.result_list.length > 0 && (
|
||||
{/* {familyOffers?.result_list && familyOffers?.result_list.length > 0 && (
|
||||
<MyOffersFamilyTable
|
||||
familyOffers={familyOffers?.result_list}
|
||||
image_server={familyOffers?.session_image_server}
|
||||
className="mb-10"
|
||||
/>
|
||||
)}
|
||||
{trending && trending.length > 0 && (
|
||||
)} */}
|
||||
|
||||
{/* {trending && trending.length > 0 && (
|
||||
<FamilyActiveLSlde
|
||||
trending={trending}
|
||||
className="mb-10"
|
||||
image_server={familyOffers?.session_image_server}
|
||||
image_server={serverImg}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
|
||||
<ParentWaiting className="mb-10" />
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -8,8 +8,6 @@ import {
|
||||
} from "../Dashboards";
|
||||
import MyJobTable from "../MyTasks/MyJobTable";
|
||||
import MyOffersTable from "../MyTasks/MyOffersTable";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import HomeActivities from "./HomeActivities";
|
||||
|
||||
export default function FullAccountDash(props) {
|
||||
// console.log("PROPS IN HOME->", props);
|
||||
@@ -21,7 +19,7 @@ export default function FullAccountDash(props) {
|
||||
case "DEFAULT_HOME_DASH":
|
||||
return (
|
||||
<HomeDashboard
|
||||
className="mb-10"
|
||||
className="mb-4"
|
||||
data={userDetails}
|
||||
bannerList={props.bannerList}
|
||||
nextDueTask={props.nextDueTask}
|
||||
@@ -30,7 +28,7 @@ export default function FullAccountDash(props) {
|
||||
case "FAMILY_PARENT_DASH":
|
||||
return (
|
||||
<FamilyParentDashboard
|
||||
className="mb-10"
|
||||
className="mb-4"
|
||||
data={userDetails}
|
||||
bannerList={props.bannerList}
|
||||
nextDueTask={props.nextDueTask}
|
||||
@@ -39,7 +37,7 @@ export default function FullAccountDash(props) {
|
||||
case "WORKER_HOME_DASH":
|
||||
return (
|
||||
<WorkerDashboard
|
||||
className="mb-10"
|
||||
className="mb-4"
|
||||
data={userDetails}
|
||||
bannerList={props.bannerList}
|
||||
nextDueTask={props.nextDueTask}
|
||||
@@ -48,7 +46,7 @@ export default function FullAccountDash(props) {
|
||||
case "JOBOWNER_HOME_DASH":
|
||||
return (
|
||||
<JobOwnerDashboard
|
||||
className="mb-10"
|
||||
className="mb-4"
|
||||
data={userDetails}
|
||||
bannerList={props.bannerList}
|
||||
nextDueTask={props.nextDueTask}
|
||||
@@ -59,15 +57,13 @@ export default function FullAccountDash(props) {
|
||||
}
|
||||
};
|
||||
|
||||
console.log(process.env.REACT_APP_SHOW_ACCOUNT_DASH)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="home-page-wrapper">
|
||||
{process.env.REACT_APP_SHOW_ACCOUNT_DASH == "1" && (
|
||||
<AccountDashboard className="mb-4" />
|
||||
)}
|
||||
{renderDashboard()}
|
||||
{process.env.REACT_APP_SHOW_ACCOUNT_DASH == "1" && (
|
||||
<AccountDashboard className="mb-4" bannerList={props.bannerList} />
|
||||
)}
|
||||
|
||||
{props?.dashTypes !== "undefined" &&
|
||||
props.offersList?.data?.result_list?.length ? (
|
||||
@@ -88,24 +84,17 @@ export default function FullAccountDash(props) {
|
||||
imageServer={props.offersList?.data?.session_image_server}
|
||||
/>
|
||||
</>
|
||||
) : !props.offersList?.loading && !props.MyActiveJobList?.loading ? (
|
||||
<HomeActivities className="mb-10" />
|
||||
) : (
|
||||
<div className="w-full h-[220px] flex items-center justify-center">
|
||||
<LoadingSpinner size="16" color="sky-blue" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/*<UpdateTable className="mb-10"/>*/}
|
||||
{/*<SellHistoryMarketVisitorAnalytic className="mb-10"/>*/}
|
||||
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
|
||||
|
||||
{/*<HomeTaskDisplay*/}
|
||||
{/* jobData={jobData}*/}
|
||||
{/* className="mb-10"*/}
|
||||
{/* bannerList={props.bannerList}*/}
|
||||
{/*/>*/}
|
||||
) : null}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// : !props.offersList?.loading && !props.MyActiveJobList?.loading ? (
|
||||
// <HomeActivities className="mb-10" />
|
||||
// )
|
||||
// : (
|
||||
// <div className="w-full h-[220px] flex items-center justify-center">
|
||||
// <LoadingSpinner size="16" color="sky-blue" />
|
||||
// </div>
|
||||
// )
|
||||
|
||||
@@ -53,7 +53,7 @@ export default function HomeActivities({ className }) {
|
||||
|
||||
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={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl relative min-h-[520px] ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -58,14 +58,11 @@ export default function Home(props) {
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
await Promise.all([getHomeDate(), getMyOffersList()]);
|
||||
await Promise.all([getHomeDate(), getMyOffersList(), getMyActiveJobList()]);
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getMyActiveJobList();
|
||||
if(userDetails?.account_type == 'FULL'){
|
||||
fetchData();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -75,8 +72,9 @@ export default function Home(props) {
|
||||
<FamilyDash
|
||||
account={userDetails}
|
||||
commonHeadData={props.bannerList}
|
||||
familyOffers={MyOffersList?.data}
|
||||
MyActiveJobList={MyActiveJobList?.data}
|
||||
// familyOffers={MyOffersList?.data}
|
||||
serverImg = {userDetails?.session_image_server}
|
||||
// MyActiveJobList={MyActiveJobList?.data}
|
||||
/>
|
||||
) : userDetails && userDetails?.account_type == "FULL" ? (
|
||||
<FullAccountDash
|
||||
@@ -95,21 +93,3 @@ export default function Home(props) {
|
||||
</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"/>
|
||||
<TopSellerTopBuyerSliderSection className="mb-10" />
|
||||
<UpdateTable className="mb-10"/>*/
|
||||
}
|
||||
// </div>
|
||||
// </Layout>
|
||||
|
||||
@@ -229,12 +229,13 @@ export default function MemberList({
|
||||
// iconName="message"
|
||||
/>
|
||||
</div>
|
||||
<div className="input-item w-full sm:w-[150%]">
|
||||
<div className="input-item w-full">
|
||||
<InputCom
|
||||
labelClass="tracking-wider"
|
||||
fieldClass="sm:px-6 px-2"
|
||||
value={fields.email}
|
||||
inputHandler={handleFieldsChange}
|
||||
inputClass="xl:w-[16rem] 2xl:w-full"
|
||||
placeholder="Email"
|
||||
// label="Email"
|
||||
name="email"
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function MainSection({
|
||||
);
|
||||
const [tab, setTab] = useState(Object.keys(marketCategories)[0]);
|
||||
|
||||
let [contentDisplay, setContentDisplay] = useState("grid"); // STATE TO HOLD LIST VIEW STYLE
|
||||
let [contentDisplay, setContentDisplay] = useState("list"); // STATE TO HOLD LIST VIEW STYLE
|
||||
|
||||
// Convert to array in order to map
|
||||
const mappedArray = Object.entries(marketCategories).map(([key, value]) => {
|
||||
@@ -109,12 +109,13 @@ export default function MainSection({
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<AvailableJobsCard
|
||||
contentDisplay={contentDisplay}
|
||||
image_server={image_server}
|
||||
key={datas.job_uid}
|
||||
datas={datas}
|
||||
/>
|
||||
<div key={datas.job_uid}>
|
||||
<AvailableJobsCard
|
||||
contentDisplay={contentDisplay}
|
||||
image_server={image_server}
|
||||
datas={datas}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</DataIteration>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useSelector } from "react-redux";
|
||||
import Layout from "../Partials/Layout";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import MainSection from "./MainSection";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function MarketPlace({ commonHeadData }) {
|
||||
let { jobLists } = useSelector((state) => state.jobLists);
|
||||
@@ -13,6 +14,17 @@ export default function MarketPlace({ commonHeadData }) {
|
||||
<>
|
||||
<Layout>
|
||||
<CommonHead commonHeadData={commonHeadData} />
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {'Market'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/market", title: "Market", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<MainSection
|
||||
marketPlaceProduct={marketData}
|
||||
categories={categories}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function ActiveJobMessage({ activeJobMesList }) {
|
||||
|
||||
return (
|
||||
<div className='flex flex-col justify-between'>
|
||||
<div className="w-full min-h-[450px] max-h-[450px] overflow-y-scroll">
|
||||
<div className="w-full h-full min-h-[400px] max-h-[400px] 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'>
|
||||
|
||||
@@ -11,8 +11,11 @@ import IndexJobActions from "./JobActions/IndexJobActions";
|
||||
|
||||
import usersService from "../../services/UsersService";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import { SocketValues } from "../Contexts/SocketIOContext";
|
||||
|
||||
function ActiveJobs(props) {
|
||||
let {sendMessage, joinRoom} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
|
||||
|
||||
const ApiCall = new usersService();
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -139,6 +142,9 @@ function ActiveJobs(props) {
|
||||
status: true,
|
||||
message: "Message Sent Successfully",
|
||||
});
|
||||
// function to trigger socket to emit 'send_message'
|
||||
sendMessage(messageToSend, `${props.details.contract}-${props.details.contract_uid}`)
|
||||
|
||||
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
|
||||
setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
|
||||
})
|
||||
@@ -255,6 +261,12 @@ function ActiveJobs(props) {
|
||||
props.details?.currency
|
||||
);
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
// calls function to add user to a room
|
||||
joinRoom(`${props.details.contract}-${props.details.contract_uid}`)
|
||||
},[props.details.contract, props.details.contract_uid])
|
||||
|
||||
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">
|
||||
@@ -286,7 +298,7 @@ function ActiveJobs(props) {
|
||||
<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">
|
||||
<h1 className="text-[20px] font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
{props.details?.title && props.details.title}
|
||||
</h1>
|
||||
</div>
|
||||
@@ -412,7 +424,7 @@ function ActiveJobs(props) {
|
||||
</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"
|
||||
className="p-4 w-full h-[200px] 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"
|
||||
@@ -421,7 +433,7 @@ function ActiveJobs(props) {
|
||||
autoFocus
|
||||
/>
|
||||
) : (
|
||||
<div className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300">
|
||||
<div className="p-4 w-full h-[200px] text-base text-slate-600 border border-slate-300">
|
||||
<div className="files">
|
||||
<label
|
||||
htmlFor="file"
|
||||
@@ -535,16 +547,23 @@ function ActiveJobs(props) {
|
||||
{/* 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 className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2">
|
||||
<span>Message</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={popUpHandler}
|
||||
className="text-[12px] tracking-wider text-emerald-600 dark:text-emerald-300"
|
||||
>
|
||||
View all
|
||||
</button>
|
||||
</p>
|
||||
<button
|
||||
{/* <button
|
||||
type="button"
|
||||
onClick={popUpHandler}
|
||||
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer flex justify-center items-center"
|
||||
>
|
||||
View all
|
||||
</button>
|
||||
</button> */}
|
||||
</div>
|
||||
{props.activeJobMesList.loading ? (
|
||||
<LoadingSpinner size="16" color="sky-blue" />
|
||||
|
||||
@@ -13,13 +13,6 @@ function CurrentJobAction() {
|
||||
<div>
|
||||
Waiting for the completion message from the client before you can approve.
|
||||
</div>
|
||||
{/*<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>
|
||||
|
||||
@@ -112,7 +112,7 @@ function ReviewJobAction({jobDetails}) {
|
||||
<tr>
|
||||
<td>
|
||||
<div className="flex justify-center items-center">
|
||||
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
<button type="button" onClick={popUpHandler} className="w-[130px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
Reject or Accept
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
import React, { useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||
import PaginatedList from "../Pagination/PaginatedList";
|
||||
|
||||
export default function MyPastDueTaskTable({ MyJobList, className }) {
|
||||
const 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 currentActiveJobList = MyJobList?.result_list?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full p-3 sm:p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
{MyJobList && MyJobList?.result_list && (
|
||||
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
|
||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||
<tbody>
|
||||
{
|
||||
<>
|
||||
{MyJobList &&
|
||||
MyJobList?.result_list &&
|
||||
MyJobList.result_list.length > 0 ? (
|
||||
currentActiveJobList.map((value, index) => {
|
||||
let deliveryDate = value?.delivery_date?.split(" ")[0];
|
||||
let thePrice = PriceFormatter(
|
||||
value?.price * 0.01,
|
||||
value?.currency_code,
|
||||
value?.currency
|
||||
);
|
||||
let image = `${
|
||||
MyJobList.session_image_server
|
||||
}${localStorage.getItem("session_token")}/job/${
|
||||
value.job_uid
|
||||
}`;
|
||||
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="max-w-[60px] max-h-[60px] min-w-[60px] min-h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={image}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col flex-[0.9]">
|
||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||
{value.title}
|
||||
</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>
|
||||
</span>
|
||||
<div className="flex flex-col sm:flex-row items-start gap-1 md:gap-4 md: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>
|
||||
</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="px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
{value.owner_status == "OWNER"
|
||||
? "Review"
|
||||
: "Send Updates"}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||
<td className="p-2">No Past Due Task!</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
MyJobList?.result_list.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
data={MyJobList?.result_list}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import MyPastDueTaskTable from "./MyPastDueTaskTable";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export default function MyPastDueTasks(props) {
|
||||
|
||||
const { userDetails: { account_type } } = useSelector((state) => state?.userDetails); // Gets user details
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
{account_type == 'FULL' &&
|
||||
<CommonHead commonHeadData={props.commonHeadData} />
|
||||
}
|
||||
<div className="notification-page w-full mb-10">
|
||||
<div className="notification-wrapper w-full">
|
||||
{/* heading */}
|
||||
{account_type == '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">
|
||||
<span
|
||||
>
|
||||
Past Due Task(s)
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {'Past Due Task(s)'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/pastdue", title: "Past Due", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
{props.loading ?
|
||||
<div className="w-full flex justify-center items-center bg-white rounded-2xl">
|
||||
<LoadingSpinner size='10' color='sky-blue' height='h-[20rem]' />
|
||||
</div>
|
||||
:
|
||||
<MyPastDueTaskTable MyJobList={props.MyJobList} />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import activeAidsBanner from "../../assets/images/kids-waiting.jpg";
|
||||
import ParentWaitingTable from "./ParentWaitingTable";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function ParentWaiting({ className }) {
|
||||
const [addFavorite, setValue] = useState(false);
|
||||
@@ -19,9 +20,20 @@ export default function ParentWaiting({ className }) {
|
||||
<>
|
||||
<div className={`overview-section w-full ${className || ""}`}>
|
||||
<div className="w-full mb-3 flex justify-between items-center gap-1">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
{/* <h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Waiting for Parent to Get Started...
|
||||
</h1>
|
||||
</h1> */}
|
||||
|
||||
<CustomBreadcrumb
|
||||
title = {'Waiting for Parent to Get Started...'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/suggested", title: "Suggested", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
|
||||
<Link
|
||||
to='/familymarket'
|
||||
className="px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
@@ -31,40 +43,17 @@ export default function ParentWaiting({ className }) {
|
||||
</div>
|
||||
{/* <div className="overview-section-wrapper py-2 min-h-[450px] lg:flex lg:space-x-2 flex-1 lg:gap-8"> */}
|
||||
<div className="overview-section-wrapper py-2 min-h-[400px] lg:grid grid-cols-2 gap-4">
|
||||
<div className="mb-10 lg:mb-0 h-full w-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
|
||||
<div className="overview-countdown mb-10 lg:mb-0 h-full w-full flex flex-col justify-between p-4 rounded-2xl bg-white dark:bg-dark-white">
|
||||
{<ParentWaitingTable />}
|
||||
</div>
|
||||
|
||||
<div className="h-full w-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
|
||||
<img
|
||||
src={activeAidsBanner}
|
||||
alt="banner"
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="overview-countdown h-full w-full flex flex-col justify-between p-4 rounded-2xl bg-white dark:bg-dark-white">
|
||||
{<ParentWaitingTable />}
|
||||
|
||||
{/* <div className="lg:mb-0 mb-3">*/}
|
||||
{/* <h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* Lock and Lob x Fiesta Spurs*/}
|
||||
{/* </h1>*/}
|
||||
{/* <span className="text-[18px] font-thin tracking-wide text-dark-gray dark:text-white">*/}
|
||||
{/* ID : 2320382*/}
|
||||
{/*</span>*/}
|
||||
{/* </div>*/}
|
||||
{/* /!* user *!/*/}
|
||||
{/* <div className="flex items-center space-x-3 lg:mb-0 mb-3">*/}
|
||||
{/* <div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">*/}
|
||||
{/* <img src={HeroUser} alt="" />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="text-xl tracking-wide font-bold antise text-dark-gray dark:text-white">*/}
|
||||
{/* Brokln Simons*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="text-sm tracking-wide text-dark-gray dark:text-white">*/}
|
||||
{/* @broklinslam_75*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -3,6 +3,7 @@ import OfferCard from "../Cards/OfferCard";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import SliderCom from "../Helpers/SliderCom";
|
||||
import FamilyOfferJobPopout from "../jobPopout/FamilyOfferJobPopout";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function MyOffersFamilyTable({ className, familyOffers, image_server }) {
|
||||
let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
||||
@@ -60,10 +61,21 @@ export default function MyOffersFamilyTable({ className, familyOffers, image_ser
|
||||
>
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
{/* <div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Ready to Start?
|
||||
</h1>
|
||||
</div> */}
|
||||
<div className="">
|
||||
<CustomBreadcrumb
|
||||
title = {'Ready to Start'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/pending", title: "Pending", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-3">
|
||||
<button onClick={nextHandler} type="button">
|
||||
|
||||
@@ -6,6 +6,7 @@ import CommonHead from "../UserHeader/CommonHead";
|
||||
import MyOffersTable from "./MyOffersTable";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function MyTasks({
|
||||
MyActiveOffersList,
|
||||
@@ -74,13 +75,25 @@ export default function MyTasks({
|
||||
/>
|
||||
)}
|
||||
<div className="w-full mb-5 flex justify-between items-center gap-1">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
<span
|
||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||
>
|
||||
My Tasks
|
||||
</span>
|
||||
</h1>
|
||||
{/* {userDetails.account_type == 'FULL'?
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
<span
|
||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||
>
|
||||
My Tasks
|
||||
</span>
|
||||
</h1>
|
||||
: */}
|
||||
<CustomBreadcrumb
|
||||
title = 'My Tasks'
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/mytask", title: "My Tasks", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
{/* } */}
|
||||
|
||||
{ActiveJobList?.data?.length > 0 && userDetails.account_type == 'FAMILY' &&
|
||||
<button
|
||||
@@ -94,6 +107,7 @@ export default function MyTasks({
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<MyJobTable ActiveJobList={ActiveJobList} Account={userDetails} imageServer={MyActiveOffersList.session_image_server} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import { useSelector } from "react-redux";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import WalletItemCard from "./WalletItemCard";
|
||||
import WalletItemCardFamily from "./WalletItemCardFamily";
|
||||
import { useEffect, useState } from "react";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import { localImgLoad } from "../../lib";
|
||||
import background from "../../assets/images/bg-sky-blue.jpg";
|
||||
import FamilyWalletRedeemOptions from "./FamilyWalletRedeemOptions";
|
||||
|
||||
/**
|
||||
* Renders a list of wallet items or a loading spinner depending on the state of the `wallet` object.
|
||||
*/
|
||||
export default function FamilyWalletBox({ wallet, payment }) {
|
||||
// const { loading, data } = wallet;
|
||||
|
||||
// const { userDetails } = useSelector((state) => state.userDetails);
|
||||
// const accountType = userDetails?.account_type === "FAMILY";
|
||||
|
||||
const [selectedWallet, setSelectedWallet] = useState('')
|
||||
|
||||
const [activeWalletBtn, setActiveWalletBtn] = useState('')
|
||||
|
||||
const handleChangeWallet = ({target:{name}}) => { // FUNCTION TO SWITCH WALLET IF USER HAS MORE THAN TWO WALLETS
|
||||
const currentWalletSelected = wallet?.data?.filter((item) => item.code == name);
|
||||
setSelectedWallet(currentWalletSelected[0])
|
||||
setActiveWalletBtn(name)
|
||||
// console.log(name, currentWalletSelected)
|
||||
}
|
||||
|
||||
const image = selectedWallet?.code
|
||||
? `${selectedWallet?.code.toLowerCase()}.svg`
|
||||
: "default.png";
|
||||
|
||||
useEffect(()=>{
|
||||
setSelectedWallet(wallet.data[0])
|
||||
setActiveWalletBtn(wallet?.data[0]?.code)
|
||||
},[wallet])
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="my-wallet-wrapper w-full">
|
||||
<div className="main-wrapper w-full mb-10">
|
||||
<div className="w-full mb-10 sm:grid grid-cols-2 gap-4">
|
||||
<div className="w-full mb-4 sm:mb-0 rounded-2xl bg-white dark:bg-dark-white overflow-hidden">
|
||||
{wallet?.loading ?
|
||||
<div className="w-full h-full flex items-center justify-center bg-white">
|
||||
<LoadingSpinner size="16" color="sky-blue" height='min-h-[240px]' />
|
||||
</div>
|
||||
: wallet?.data.length > 0 ?
|
||||
<>
|
||||
{wallet?.data?.length > 1 &&
|
||||
<div className="wal-selection px-5 py-2 text-black dark:text-white flex items-center gap-2">
|
||||
{wallet?.data?.map(item =>(
|
||||
<button
|
||||
className={`py-0.5 px-1 mb-1 rounded-lg border border-orange-500 ${activeWalletBtn == item?.code && 'bg-orange-500'}`}
|
||||
key={item?.wallet_uid}
|
||||
name={item?.code}
|
||||
onClick={handleChangeWallet}
|
||||
>
|
||||
{item?.description}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
<div className="p-5 bg-white-opacity min-h-[240px]"
|
||||
style={{
|
||||
background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||
}}
|
||||
>
|
||||
{/* image */}
|
||||
<div className="min-w-[100px] min-h-[100px] max-w-min md:max-w-[100px] max-h-min md:max-h-[100px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
|
||||
<img
|
||||
src={localImgLoad(`images/currency/${image}`)}
|
||||
className="w-full h-full"
|
||||
alt="currency-icon"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-base sm:text-lg text-white opacity-[70%] tracking-wide my-3">Current Balance</p>
|
||||
<p className="text-[44px] lg:text-[62px] font-bold text-white tracking-wide leading-10">
|
||||
{PriceFormatter(selectedWallet?.amount/100, selectedWallet?.code, undefined, "text-[2rem]")}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<div className="w-full h-full flex justify-center items-center rounded-2xl bg-white">
|
||||
<p>No Wallet Record Found</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div className="p-5 w-full rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white h-full min-h-[240px] max-h-96">
|
||||
<h1 className="text-xl font-bold text-black dark:text-white">Recent Activities</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<FamilyWalletRedeemOptions />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// data.length>0 && data.map((item) => (
|
||||
// <div key={item.wallet_uid} className="w-full h-full mb-10 ">
|
||||
// {/* <WalletItemCardFamily walletItem={item} payment={payment} countries={countries} /> */}
|
||||
// </div>
|
||||
// ))
|
||||
@@ -0,0 +1,81 @@
|
||||
import React, { Suspense, lazy, useEffect, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import usersService from "../../services/UsersService";
|
||||
import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
const FamilyWalletBox = lazy(() => import("./FamilyWalletBox"));
|
||||
|
||||
const FamilyWalletCon = () => {
|
||||
const apiCall = new usersService();
|
||||
// const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
|
||||
const { walletTable } = useSelector((state) => state.tableReload);
|
||||
|
||||
const [paymentHistory, setPaymentHistory] = useState({
|
||||
loading: true,
|
||||
data: [],
|
||||
});
|
||||
|
||||
const [familyWalletBal, setFamilyWalletBal] = useState({
|
||||
loading: true,
|
||||
data: []
|
||||
});
|
||||
|
||||
const getFamilyWalletBal = () => {
|
||||
setFamilyWalletBal({loading:true, data: []})
|
||||
apiCall.getFamilyWallet({family_uid: localStorage.getItem("uid")}).then(res => {
|
||||
setFamilyWalletBal({loading:false, data: res?.data?.result_list})
|
||||
}).catch(error => {
|
||||
setFamilyWalletBal({loading:false, data: []})
|
||||
})
|
||||
};
|
||||
|
||||
const getPaymentHistory = () => {
|
||||
apiCall
|
||||
.getPaymentHx()
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 0) {
|
||||
setPaymentHistory({ loading: false, data: [] });
|
||||
} else {
|
||||
setPaymentHistory({ loading: false, data: res.data?.result_list });
|
||||
// console.log('Hist', res.data?.result_list)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setPaymentHistory({ loading: false, data: [] });
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getPaymentHistory();
|
||||
getFamilyWalletBal()
|
||||
}, [walletTable]);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className='mb-4'>
|
||||
<CustomBreadcrumb
|
||||
title={'Wallet'}
|
||||
breadcrumb = {
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: '/family-wallet', title: 'Wallet', active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Suspense fallback={
|
||||
<div className="bg-white rounded-2xl">
|
||||
<LoadingSpinner size="16" color="sky-blue" height='h-[30rem]' />
|
||||
</div>
|
||||
}>
|
||||
<FamilyWalletBox
|
||||
wallet={familyWalletBal}
|
||||
payment={paymentHistory}
|
||||
/>
|
||||
</Suspense>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default FamilyWalletCon;
|
||||
@@ -0,0 +1,82 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import SearchCom from '../Helpers/SearchCom'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
export default function FamilyWalletRedeemOptions() {
|
||||
|
||||
const { familyWalletRedeemOptList } = useSelector((state) => state.familyWalletRedeemOptList); // FAMILY WALLET REDDEM OPTIONS LIST
|
||||
|
||||
const [filteredRedeemData, setFilteredRedeemData] = useState({value: '', data:{}}) // State to hold filtered redeem banner option
|
||||
|
||||
const handleFilterRedeemData = ({target}) => {
|
||||
// thiskey01
|
||||
let filterWord = target.value
|
||||
let filteredData = {}
|
||||
if(!filterWord){
|
||||
filteredData = {...familyWalletRedeemOptList?.data}
|
||||
}else{
|
||||
let matchedData = Object.keys(familyWalletRedeemOptList?.data)?.filter(item => (item.toLowerCase().startsWith(filterWord.toLowerCase())))
|
||||
filteredData = matchedData.map(item => familyWalletRedeemOptList.data[item])
|
||||
}
|
||||
setFilteredRedeemData({value:target.value, data: {...filteredData}})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
setFilteredRedeemData(prev => ({...prev, data:{...familyWalletRedeemOptList?.data}}))
|
||||
}, [familyWalletRedeemOptList.image])
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full sm:flex items-center gap-4">
|
||||
<h1 className="text-2xl font-bold text-black dark:text-white">Redeem Options</h1>
|
||||
<div className="sm:w-1/2 w-full sm:pr-20 pr-0 mb-5 sm:mb-0">
|
||||
<SearchCom
|
||||
placeholder='Search...'
|
||||
value={filteredRedeemData.value}
|
||||
handleSearch={handleFilterRedeemData}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* redeem options */}
|
||||
{familyWalletRedeemOptList.loading ?
|
||||
<div className='mt-5 w-full h-[20rem] rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white flex justify-center items-center'>
|
||||
<LoadingSpinner size='10' color='sky-blue' height='h-[30rem]' />
|
||||
</div>
|
||||
: familyWalletRedeemOptList?.data && Object.keys(familyWalletRedeemOptList?.data)?.length > 0 ?
|
||||
Object.keys(filteredRedeemData?.data)?.length ?
|
||||
<div className="mt-5 grid sm:grid-cols-2 lg:grid-cols-3 xxl:grid-cols-4 gap-4">
|
||||
{ Object.keys(filteredRedeemData?.data)?.map((item)=>{
|
||||
// text, image, description, action
|
||||
let newData = filteredRedeemData?.data[item].banner
|
||||
let bgImage = `url(${newData?.image})`
|
||||
return (
|
||||
<Link to={''} key={item}>
|
||||
<div className={`group relative h-60 text-black dark:text-white rounded-2xl shadow-lg hover:shadow-md transition-all duration-300 overflow-hidden`}
|
||||
style={{
|
||||
// background: `#ffffff ${bgImage} no-repeat center center / cover`
|
||||
}}
|
||||
>
|
||||
<img src={newData?.image} alt='Redeem Image' className='w-full h-full bg-cover rounded-2xl group-hover:scale-110 transition-all duration-300' />
|
||||
<div className='absolute bottom-0 mb-1 left-1/2 -translate-x-1/2 p-2 bg-white/80 rounded-2xl w-[90%] flex flex-col justify-center items-center gap-2'>
|
||||
<h1 className='text-lg font-bold text-[#083e21]'>{newData.text}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
:
|
||||
<div className='mt-5 w-full h-[20rem] rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white flex justify-center items-center'>
|
||||
<p>Search Item not Found!</p>
|
||||
</div>
|
||||
:
|
||||
<div className='mt-5 w-full h-[20rem] rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white flex justify-center items-center'>
|
||||
<p>No Redeem Options Found!</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -15,21 +15,6 @@ export default function WalletBox({ wallet, payment, countries }) {
|
||||
return (
|
||||
<div className="my-wallet-wrapper w-full mb-10">
|
||||
<div className="main-wrapper w-full">
|
||||
{accountType ?
|
||||
<div className="balance-inquery w-auto grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-[repeat(auto-fill,_minmax(354px,_1fr))] min-[1440px]:grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-auto">
|
||||
{loading ? (
|
||||
<div className="w-full h-full flex items-center justify-center">
|
||||
<LoadingSpinner size="16" color="sky-blue" />
|
||||
</div>
|
||||
) : (
|
||||
data.length > 0 && data.map((item) => (
|
||||
<div key={item.wallet_uid} className="lg:w-full h-full mb-10 lg:mb-0">
|
||||
<WalletItemCardFamily walletItem={item} payment={payment} countries={countries} />
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
:
|
||||
<div className="balance-inquery w-auto grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-[repeat(auto-fill,_minmax(354px,_1fr))] min-[1440px]:grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-auto">
|
||||
{loading ? (
|
||||
<div className="w-full h-full flex items-center justify-center">
|
||||
@@ -43,7 +28,6 @@ export default function WalletBox({ wallet, payment, countries }) {
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,8 +7,11 @@ import Icons from "../Helpers/Icons";
|
||||
import Accordion from "../Helpers/Accordion";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export default function WalletHeader(props) {
|
||||
|
||||
const {userDetails: { account_type }} = useSelector((state) => state?.userDetails);
|
||||
// debugger;
|
||||
//props.myWalletList.result_list
|
||||
let { pathname } = useLocation();
|
||||
@@ -21,187 +24,196 @@ export default function WalletHeader(props) {
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
|
||||
<div
|
||||
onClick={() => props.handlerBalance()}
|
||||
className="flex items-center lg:justify-between justify-center w-full h-full"
|
||||
>
|
||||
<span className="lg:block hidden">
|
||||
<Icons name="wallet" />
|
||||
</span>
|
||||
<p className="lg:text-xl text-lg font-bold text-white">Wallet</p>
|
||||
<span className="lg:block hidden">
|
||||
<Icons name="deep-plus" />
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className={`balance-dropdown w-96 z-30 bg-white dark:bg-dark-white absolute -left-24 rounded-lg cursor-pointer ${
|
||||
props.balanceDropdown ? "active" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="heading border-b dark:border-[#5356fb29] border-light-purple px-7 py-6">
|
||||
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
|
||||
Wallet
|
||||
</h3>
|
||||
{account_type == 'FULL' ?
|
||||
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
|
||||
<div
|
||||
onClick={() => props.handlerBalance()}
|
||||
className="flex items-center lg:justify-between justify-center w-full h-full"
|
||||
>
|
||||
<span className="lg:block hidden">
|
||||
<Icons name="wallet" />
|
||||
</span>
|
||||
<p className="lg:text-xl text-lg font-bold text-white">Wallet</p>
|
||||
<span className="lg:block hidden">
|
||||
<Icons name="deep-plus" />
|
||||
</span>
|
||||
</div>
|
||||
<div className="content px-7 pb-7">
|
||||
<ul>
|
||||
{props.myWalletList &&
|
||||
props.myWalletList?.length > 0 &&
|
||||
props.myWalletList.map((value, index) =>
|
||||
{
|
||||
let image = value.code ? `${value.code.toLocaleLowerCase()}.svg` : 'default.png'
|
||||
return(
|
||||
<li
|
||||
key={index}
|
||||
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
|
||||
onClick={onWalletClick}
|
||||
>
|
||||
<div className="sm:flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
|
||||
<div className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">
|
||||
<img src={localImgLoad(`images/currency/${image}`)} className="w-14 h-14" alt="" />
|
||||
<div
|
||||
className={`balance-dropdown w-96 z-30 bg-white dark:bg-dark-white absolute -left-24 rounded-lg cursor-pointer ${
|
||||
props.balanceDropdown ? "active" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="heading border-b dark:border-[#5356fb29] border-light-purple px-7 py-6">
|
||||
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
|
||||
Wallet
|
||||
</h3>
|
||||
</div>
|
||||
<div className="content px-7 pb-7">
|
||||
<ul>
|
||||
{props.myWalletList &&
|
||||
props.myWalletList?.length > 0 &&
|
||||
props.myWalletList.map((value, index) =>
|
||||
{
|
||||
let image = value.code ? `${value.code.toLocaleLowerCase()}.svg` : 'default.png'
|
||||
return(
|
||||
<li
|
||||
key={index}
|
||||
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
|
||||
onClick={onWalletClick}
|
||||
>
|
||||
<div className="sm:flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
|
||||
<div className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">
|
||||
<img src={localImgLoad(`images/currency/${image}`)} className="w-14 h-14" alt="" />
|
||||
</div>
|
||||
<div className="name">
|
||||
<p className="text-2xl font-bold text-dark-gray dark:text-white">
|
||||
{value.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="name">
|
||||
<p className="text-2xl font-bold text-dark-gray dark:text-white">
|
||||
{value.description}
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-purple">
|
||||
{PriceFormatter(value.amount * 0.01, value.code)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-purple">
|
||||
{PriceFormatter(value.amount * 0.01, value.code)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
)}
|
||||
|
||||
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank1} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* MetaMask*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 75,320 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank2} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* Coinbase Wallet*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 56,124 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank3} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* Bitski*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 99,123 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
{/*<li className="content-item py-5">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank4} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* WalletConnect*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 43,728 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
</ul>
|
||||
<div className="add-money-btn flex justify-center items-center mt-3">
|
||||
{/* <button
|
||||
onClick={() => {
|
||||
if(pathname == '/my-wallet') props.setBalanceDropdown.toggle()
|
||||
else navigate('/my-wallet', {replace: true})
|
||||
}}
|
||||
type="button"
|
||||
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Manage
|
||||
</button> */}
|
||||
<Link
|
||||
to="/my-wallet"
|
||||
onClick={onWalletClick}
|
||||
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Manage
|
||||
</Link>
|
||||
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank1} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* MetaMask*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 75,320 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank2} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* Coinbase Wallet*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 56,124 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank3} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* Bitski*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 99,123 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
{/*<li className="content-item py-5">*/}
|
||||
{/* <div className="sm:flex justify-between items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">*/}
|
||||
{/* <div*/}
|
||||
{/* className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank4} alt=""/>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-base text-dark-gray dark:text-white font-medium">*/}
|
||||
{/* WalletConnect*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="eth text-xl font-bold text-purple">*/}
|
||||
{/* 43,728 ETH*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="usd text-base text-thin-light-gray text-right">*/}
|
||||
{/* (773.69 USD)*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</li>*/}
|
||||
</ul>
|
||||
<div className="add-money-btn flex justify-center items-center mt-3">
|
||||
{/* <button
|
||||
onClick={() => {
|
||||
if(pathname == '/my-wallet') props.setBalanceDropdown.toggle()
|
||||
else navigate('/my-wallet', {replace: true})
|
||||
}}
|
||||
type="button"
|
||||
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Manage
|
||||
</button> */}
|
||||
<Link
|
||||
to="/my-wallet"
|
||||
onClick={onWalletClick}
|
||||
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Manage
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/*<div*/}
|
||||
{/* className="lg:hidden flex user-balance cursor-pointer lg:w-[252px] w-[150px] h-[48px] items-center rounded-full relative bg-purple">*/}
|
||||
{/* <div className="flex items-center lg:justify-between justify-center w-full h-full">*/}
|
||||
{/* <p className="lg:text-xl text-lg font-bold text-white">*/}
|
||||
{/* $ 234,435.34*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
:
|
||||
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
|
||||
<div
|
||||
onClick={() => navigate("/family-wallet", { replace: true })}
|
||||
className="flex items-center lg:justify-between justify-center w-full h-full"
|
||||
>
|
||||
<span className="lg:block hidden">
|
||||
<Icons name="wallet" />
|
||||
</span>
|
||||
<p className="lg:text-xl text-lg font-bold text-white">Wallet</p>
|
||||
<span className="lg:block hidden">
|
||||
<Icons name="deep-plus" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div className="lg:hidden block"></div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -34,9 +34,7 @@ export default function WalletItemCard({ walletItem, payment, countries }) {
|
||||
dispatch(tableReload({ type: "WALLETTABLE" }));
|
||||
};
|
||||
|
||||
const currentWalletCurrency = countries
|
||||
// .map((country) => country)
|
||||
.filter((country) => country.code === walletItem.country);
|
||||
const currentWalletCurrency = countries?.filter((country) => country.code === walletItem.country);
|
||||
|
||||
const image = walletItem.code
|
||||
? `${walletItem.code.toLowerCase()}.svg`
|
||||
|
||||
@@ -4,7 +4,6 @@ import background from "../../assets/images/bg-sky-blue.jpg"; //shape/balance-bg
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import CreditPopup from "./Popup/CreditPopup";
|
||||
import WalletAction from "./WalletAction";
|
||||
|
||||
/**
|
||||
@@ -13,30 +12,17 @@ import WalletAction from "./WalletAction";
|
||||
export default function WalletItemCardFamily({ walletItem, payment, countries }) {
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
|
||||
|
||||
/**
|
||||
* Opens the credit popup.
|
||||
* @param {Object} value - The value object.
|
||||
*/
|
||||
const openPopUp = (value) => {
|
||||
setCreditPopup({
|
||||
show: true,
|
||||
data: { ...value },
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the credit popup and dispatches a table reload action.
|
||||
*/
|
||||
const closePopUp = () => {
|
||||
setCreditPopup({ show: false, data: {} });
|
||||
dispatch(tableReload({ type: "WALLETTABLE" }));
|
||||
};
|
||||
|
||||
const currentWalletCurrency = countries
|
||||
// .map((country) => country)
|
||||
.filter((country) => country.code === walletItem.country);
|
||||
const currentWalletCurrency = countries?.filter((country) => country.code === walletItem.country);
|
||||
|
||||
const image = walletItem.code
|
||||
? `${walletItem.code.toLowerCase()}.svg`
|
||||
@@ -45,10 +31,10 @@ export default function WalletItemCardFamily({ walletItem, payment, countries })
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between"
|
||||
style={{
|
||||
background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||
}}
|
||||
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between bg-family-header-bg"
|
||||
// style={{
|
||||
// background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||
// }}
|
||||
>
|
||||
<div className="wallet w-full flex justify-between items-center gap-3">
|
||||
<div className="min-w-[100px] min-h-[100px] max-w-min md:max-w-[150px] max-h-min md:max-h-[150px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
|
||||
@@ -74,24 +60,7 @@ export default function WalletItemCardFamily({ walletItem, payment, countries })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="my-2 w-full h-[1px] bg-white"></div>
|
||||
|
||||
{/* <WalletAction
|
||||
walletItem={{ ...walletItem, walletCountry: currentWalletCurrency }}
|
||||
payment={payment}
|
||||
openPopUp={openPopUp}
|
||||
/> */}
|
||||
</div>
|
||||
|
||||
{creditPopup.show && (
|
||||
<CreditPopup
|
||||
details={creditPopup.data}
|
||||
walletItem={walletItem}
|
||||
onClose={closePopUp}
|
||||
situation={openPopUp}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import React, { useContext, useMemo, useState } from "react";
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
import React, { useContext } from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import bank1 from "../../assets/images/bank-1.png";
|
||||
import bank2 from "../../assets/images/bank-2.png";
|
||||
import bank3 from "../../assets/images/bank-3.png";
|
||||
import bank4 from "../../assets/images/bank-4.png";
|
||||
import profileImg from "../../assets/images/profile.jpg";
|
||||
import useToggle from "../../hooks/useToggle";
|
||||
import usersService from "../../services/UsersService";
|
||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import WalletHeader from "../MyWallet/WalletHeader";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
import Flag from "../../assets/images/united-states.svg";
|
||||
import siteLogo from "../../assets/images/wrenchboard-logo-text.png";
|
||||
// import { updateWalletDetails } from "../../store/walletDetails";
|
||||
@@ -21,17 +20,15 @@ import TimeDifference from "../Helpers/TimeDifference";
|
||||
const DEFAULT_PROFILE_IMAGE = require("../../assets/images/profile.jpg");
|
||||
|
||||
export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
|
||||
const {userDetails: { account_type }} = useSelector((state) => state?.userDetails);
|
||||
|
||||
const [balanceDropdown, setbalanceValue] = useToggle(false);
|
||||
const [notificationDropdown, setNotificationValue] = useToggle(false);
|
||||
const [userProfileDropdown, setProfileDropdown] = useToggle(false);
|
||||
const [moneyPopup, setPopup] = useToggle(false);
|
||||
const darkMode = useContext(DarkModeContext);
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
const { walletTable } = useSelector((state) => state.tableReload); // DETERMINES WHEN WALLET RELOADS
|
||||
const [myWalletList, setMyWalletList] = useState([]);
|
||||
const api = useMemo(() => new usersService(), []);
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
|
||||
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
|
||||
@@ -48,7 +45,6 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
|
||||
// 9308RDR122
|
||||
|
||||
|
||||
const handlerBalance = () => {
|
||||
setbalanceValue.toggle();
|
||||
if (notificationDropdown) {
|
||||
@@ -158,15 +154,16 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
</defs>
|
||||
</svg>
|
||||
</button>
|
||||
{/* search bar */}
|
||||
<div className="search-bar lg:block hidden w-[376px]">
|
||||
{/*<SearchCom />*/}
|
||||
|
||||
<div className="search-bar xl:hidden justify-center items-center w-[376px]">
|
||||
{/* Home */}
|
||||
<HomeButton />
|
||||
</div>
|
||||
|
||||
{/* user info */}
|
||||
<div className="user-info flex items-center justify-end w-full xl:space-x-7 space-x-2 z-10 ">
|
||||
{/* dark mode */}
|
||||
<button
|
||||
{/* <button
|
||||
onClick={darkMode.handleThemeSwitch}
|
||||
type="button"
|
||||
className="xl:w-[176px] w-[52px] h-[52px] dark:bg-white bg-dark-gray border border-pink rounded-full flex justify-center items-center"
|
||||
@@ -237,7 +234,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
{darkMode.theme === "light" ? "Dark" : "Light"} Mode
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</button> */}
|
||||
{/* balance */}
|
||||
|
||||
{/* My Page Button */}
|
||||
@@ -408,7 +405,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
</li>
|
||||
)}
|
||||
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
|
||||
<Link to="/my-wallet" className="notifications">
|
||||
<Link to={ account_type == "FULL" ? "/my-wallet" : "/family-wallet"} className="notifications">
|
||||
<div className="name">
|
||||
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
|
||||
My Wallet
|
||||
@@ -506,15 +503,6 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="for-mobile-profile lg:hidden block">
|
||||
<div
|
||||
// to="/profile"
|
||||
onClick={() => handlerProfile()}
|
||||
className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden block"
|
||||
>
|
||||
<img src={profileImg} alt="profile" className="w-full h-full" />
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -697,3 +685,33 @@ const PageButton = () => {
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
const HomeButton = () => {
|
||||
return (
|
||||
<Link
|
||||
to="/"
|
||||
className="flex user-balance cursor-pointer w-[110px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4"
|
||||
>
|
||||
<div className="flex items-center lg:justify-between justify-center w-full h-full">
|
||||
<span className="">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-7 h-7 stroke-white fill-white"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<p className="lg:text-xl text-lg font-bold text-white">Home</p>
|
||||
<span className=""></span>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,10 +20,7 @@ export default function Layout({ children }) {
|
||||
};
|
||||
const navigate = useNavigate();
|
||||
const logOut = () => {
|
||||
localStorage.removeItem("session_token");
|
||||
localStorage.removeItem("member_id");
|
||||
localStorage.removeItem("uid");
|
||||
sessionStorage.removeItem("family_uid");
|
||||
sessionStorage.clear();
|
||||
localStorage.clear();
|
||||
// toast.success("Come Back Soon", {
|
||||
// icon: `🙂`,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useContext, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { NavLink } from "react-router-dom";
|
||||
//import SideStatistics from "./SideStatistics";
|
||||
import { localImgLoad } from "../../lib";
|
||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||
|
||||
export default function RightSideBar({myJobList}) {
|
||||
export default function RightSideBar({ myJobList }) {
|
||||
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
|
||||
const [filterDataSet, setFilterDataSet] = useState([10, 30, 20, 40]);
|
||||
const dataSetHandler = (value) => {
|
||||
@@ -16,6 +17,7 @@ export default function RightSideBar({myJobList}) {
|
||||
setFilterDataSet([8, 15, 40, 30]);
|
||||
}
|
||||
};
|
||||
const darkMode = useContext(DarkModeContext);
|
||||
|
||||
const [selectedRate, setSelectedRate] = useState("ETH");
|
||||
const [rateStaticsDropdown, setRateStaticsDropdown] = useState(false);
|
||||
@@ -153,79 +155,181 @@ export default function RightSideBar({myJobList}) {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* dark mode */}
|
||||
<div
|
||||
onClick={darkMode.handleThemeSwitch}
|
||||
className="item flex space-x-5 items-center mb-4 cursor-pointer"
|
||||
>
|
||||
<span className="dark:text-dark-gray text-white">
|
||||
{darkMode.theme === "light" ? (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6 fill-black"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"
|
||||
/>
|
||||
</svg>
|
||||
) : (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="fill-current w-6 h-6"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M18.3065 16.3771C18.1572 16.6304 17.986 16.8743 17.7937 17.1062C17.7118 17.2044 17.7247 17.3515 17.8228 17.4339C17.9208 17.5163 18.0665 17.5028 18.1484 17.4046C18.3569 17.1532 18.5419 16.8897 18.7043 16.6155C18.7695 16.5051 18.7334 16.3622 18.6238 16.2966C18.5142 16.2304 18.3722 16.2668 18.3065 16.3771ZM18.9591 14.722C18.8948 15.0116 18.8078 15.2975 18.6982 15.5759C18.6511 15.6955 18.7093 15.831 18.8282 15.878C18.9466 15.9255 19.0812 15.8668 19.1283 15.7477C19.2472 15.446 19.3411 15.1368 19.4104 14.8231C19.4382 14.6978 19.3596 14.5735 19.2347 14.5456C19.1103 14.5176 18.9864 14.5968 18.9591 14.722ZM19.0673 12.944C19.0955 13.2411 19.1006 13.5395 19.0825 13.8375C19.0747 13.9655 19.1718 14.0763 19.2994 14.0837C19.4266 14.0917 19.5362 13.9939 19.5441 13.8659C19.564 13.5437 19.5584 13.2206 19.5274 12.8994C19.5154 12.7713 19.4021 12.6777 19.2754 12.6899C19.1482 12.702 19.0548 12.816 19.0673 12.944ZM18.6229 11.2201C18.7422 11.4948 18.8388 11.7769 18.9128 12.0641C18.9447 12.1884 19.071 12.2629 19.1949 12.2308C19.3184 12.1987 19.3924 12.0716 19.3605 11.9473C19.2805 11.6363 19.1755 11.3304 19.0465 11.0334C18.9951 10.9156 18.8587 10.8616 18.7417 10.9133C18.6247 10.9649 18.5715 11.1023 18.6229 11.2201ZM17.6651 9.72283C17.8653 9.94816 18.0448 10.1856 18.2034 10.4333C18.2723 10.5413 18.4157 10.5725 18.523 10.5026C18.6303 10.4333 18.6612 10.2889 18.5919 10.1809C18.4208 9.91324 18.2265 9.65578 18.0092 9.4123C17.9241 9.31639 17.7779 9.30848 17.6827 9.39414C17.5879 9.4798 17.58 9.62738 17.6651 9.72283Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M13.4409 5.61267C9.08757 5.61267 5.55359 9.14665 5.55359 13.5C5.55359 17.8533 9.08757 21.3873 13.4409 21.3873C17.7942 21.3873 21.3282 17.8533 21.3282 13.5C21.3282 9.14665 17.7942 5.61267 13.4409 5.61267ZM13.9049 6.5559C17.5298 6.79484 20.4003 9.81475 20.4003 13.5C20.4003 17.1852 17.5298 20.2051 13.9049 20.4441V6.5559Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M12.1116 1.32213V3.46343C12.1116 4.19318 12.7072 4.78556 13.4409 4.78556C14.1746 4.78556 14.7702 4.19318 14.7702 3.46343V1.32213C14.7702 0.592374 14.1746 0 13.4409 0C12.7072 0 12.1116 0.592374 12.1116 1.32213Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M21.0877 4.01472L19.5511 5.5513C19.0274 6.07499 19.0274 6.92528 19.5511 7.44898C20.0748 7.97267 20.9251 7.97267 21.4488 7.44898L22.9854 5.9124C23.509 5.38871 23.509 4.53841 22.9854 4.01472C22.4617 3.49102 21.6114 3.49102 21.0877 4.01472Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M25.6581 12.3649H23.4849C22.7443 12.3649 22.1431 12.9661 22.1431 13.7068C22.1431 14.4474 22.7443 15.0486 23.4849 15.0486H25.6581C26.3988 15.0486 27 14.4474 27 13.7068C27 12.9661 26.3988 12.3649 25.6581 12.3649Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M22.9854 21.5012L21.4488 19.9646C20.9251 19.4409 20.0748 19.4409 19.5511 19.9646C19.0274 20.4883 19.0274 21.3386 19.5511 21.8623L21.0877 23.3989C21.6114 23.9226 22.4617 23.9226 22.9854 23.3989C23.509 22.8752 23.509 22.0249 22.9854 21.5012Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M14.7702 25.6778V23.5365C14.7702 22.8068 14.1746 22.2144 13.4409 22.2144C12.7072 22.2144 12.1116 22.8068 12.1116 23.5365V25.6778C12.1116 26.4076 12.7072 27 13.4409 27C14.1746 27 14.7702 26.4076 14.7702 25.6778Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M5.78958 23.0647L7.29553 21.5372C7.80878 21.0166 7.80878 20.1714 7.29553 19.6508C6.78228 19.1302 5.94893 19.1302 5.43568 19.6508L3.92974 21.1783C3.41649 21.6989 3.41649 22.5441 3.92974 23.0647C4.44299 23.5853 5.27633 23.5853 5.78958 23.0647Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M1.32213 14.8293H3.46343C4.19318 14.8293 4.78556 14.2337 4.78556 13.5C4.78556 12.7663 4.19318 12.1707 3.46343 12.1707H1.32213C0.592374 12.1707 0 12.7663 0 13.5C0 14.2337 0.592374 14.8293 1.32213 14.8293Z"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M3.92974 5.82165L5.43568 7.34911C5.94893 7.86969 6.78228 7.86969 7.29553 7.34911C7.80878 6.82853 7.80878 5.98328 7.29553 5.46269L5.78958 3.93524C5.27633 3.41465 4.44299 3.41465 3.92974 3.93524C3.41649 4.45582 3.41649 5.30107 3.92974 5.82165Z"
|
||||
/>
|
||||
</svg>
|
||||
)}
|
||||
</span>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
{darkMode.theme === "light" ? "Dark" : "Light"} Mode
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/*JOB LINKS*/}
|
||||
{myJobList?.data?.result_list?.length > 0 &&
|
||||
<div className="top-platform mt-6 bg-white dark:bg-dark-white rounded-2xl py-8 2xl:w-[268px] w-full 2xl:mb-10 2xl:border-none border ">
|
||||
{/* heading */}
|
||||
<div className="px-8 heading flex justify-between items-center mb-3.5">
|
||||
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
|
||||
Job Links
|
||||
</h3>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
<div className="platform-list">
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img src={localImgLoad('images/icons/job_active.svg')} className="w-full h-full" alt='Active Task' />
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/my-active-jobs">Active Task</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
{/* action */}
|
||||
{userDetails?.account_type !== "FAMILY" &&
|
||||
myJobList?.data?.result_list?.length > 0 && (
|
||||
<div className="top-platform mt-6 bg-white dark:bg-dark-white rounded-2xl py-8 2xl:w-[268px] w-full 2xl:mb-10 2xl:border-none border ">
|
||||
{/* heading */}
|
||||
<div className="px-8 heading flex justify-between items-center mb-3.5">
|
||||
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
|
||||
Job Links
|
||||
</h3>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img src={localImgLoad('images/icons/job_pending.svg')} className="w-full h-full" alt='Review Task' />
|
||||
<div className="platform-list">
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img
|
||||
src={localImgLoad("images/icons/job_active.svg")}
|
||||
className="w-full h-full"
|
||||
alt="Active Task"
|
||||
/>
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/my-active-jobs">Active Task</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
{/* action */}
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/my-review-jobs">Review</NavLink>
|
||||
</p>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img
|
||||
src={localImgLoad("images/icons/job_pending.svg")}
|
||||
className="w-full h-full"
|
||||
alt="Review Task"
|
||||
/>
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/my-review-jobs">Review</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img
|
||||
src={localImgLoad("images/icons/job_past_due.svg")}
|
||||
className="w-full h-full"
|
||||
alt="Past Due Task"
|
||||
/>
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/my-pastdue-jobs">Past Due</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Line */}
|
||||
<div className="my-4 mx-auto w-10/12 h-[2px] bg-slate-500 dark:bg-white rounded-full"></div>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img
|
||||
src={localImgLoad("images/icons/job_group.svg")}
|
||||
className="w-full h-full"
|
||||
alt="Job Groups"
|
||||
/>
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/job-groups">Job Groups</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img src={localImgLoad('images/icons/job_past_due.svg')} className="w-full h-full" alt='Past Due Task' />
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/my-pastdue-jobs">Past Due</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Line */}
|
||||
<div className="my-4 mx-auto w-10/12 h-[2px] bg-slate-500 dark:bg-white rounded-full"></div>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img src={localImgLoad('images/icons/job_group.svg')} className="w-full h-full" alt='Job Groups' />
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/job-groups">Job Groups</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -33,6 +33,9 @@ export default function Resources(props) {
|
||||
const CreatedBits = __resources?.productdata?.datas;
|
||||
const blogItems = __resources?.blogdata?.payload;
|
||||
|
||||
console.log(__resources);
|
||||
console.log("Blog data >> ", blogItems);
|
||||
|
||||
// My Items Data
|
||||
const [uploadedFiles, setUploadedFiles] = useState({
|
||||
loading: false,
|
||||
@@ -63,7 +66,7 @@ export default function Resources(props) {
|
||||
loading: false,
|
||||
msg: "success",
|
||||
data: res?.result_list,
|
||||
image:res?.session_image_server
|
||||
image: res?.session_image_server,
|
||||
}));
|
||||
} catch (error) {
|
||||
setUploadedFiles((prev) => ({
|
||||
@@ -79,7 +82,13 @@ export default function Resources(props) {
|
||||
}, [uploadsTable]);
|
||||
|
||||
// const [tab, setTab] = useState(tab_categories ? tab_categories[0]?.name : "");
|
||||
const [tab, setTab] = useState(props.activeTab? props.activeTab : tab_categories ? tab_categories[0]?.name : "");
|
||||
const [tab, setTab] = useState(
|
||||
props.activeTab
|
||||
? props.activeTab
|
||||
: tab_categories
|
||||
? tab_categories[0]?.name
|
||||
: ""
|
||||
);
|
||||
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
@@ -105,8 +114,12 @@ export default function Resources(props) {
|
||||
|
||||
// const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
const defaultTabComponent = props.activeTab ? tabComponents[props.activeTab] : <BlogTab blogdata={blogItems} />;
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
const defaultTabComponent = props.activeTab ? (
|
||||
tabComponents[props.activeTab]
|
||||
) : (
|
||||
<BlogTab blogdata={blogItems} />
|
||||
);
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
// Tab Item Component
|
||||
const TabItem = ({ tabValue, isActive }) => {
|
||||
@@ -160,17 +173,16 @@ export default function Resources(props) {
|
||||
<ul className="lg:flex lg:space-x-14 space-x-8">
|
||||
{tabCategories?.length > 0 &&
|
||||
tabCategories?.map((tabValue, idx) => {
|
||||
if(tabValue.enabled){
|
||||
if (tabValue.enabled) {
|
||||
return (
|
||||
<TabItem
|
||||
key={tabValue.id}
|
||||
tabValue={tabValue}
|
||||
isActive={tab === tabValue.name || (idx === 0 && tab === "")}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
)}
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -134,7 +134,7 @@ export default function MyUploadedFiles({ uploadedFiles }) {
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
uploadedFiles?.data.length
|
||||
uploadedFiles?.data?.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import HomeActivities from "../../Home/HomeActivities";
|
||||
|
||||
const RecentActivitiesTab = () => {
|
||||
return (
|
||||
<div className="recent-activity-tab w-full">
|
||||
<HomeActivities />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RecentActivitiesTab;
|
||||
@@ -5,6 +5,7 @@ import NotificationSettingTab from "./NotificationSettingTab";
|
||||
import PaymentMathodsTab from "./PaymentMathodsTab";
|
||||
import PersonalInfoTab from "./PersonalInfoTab";
|
||||
import PrivacyPolicyTab from "./PrivacyPolicyTab";
|
||||
import RecentActivitiesTab from "./RecentActivitiesTab";
|
||||
import TermsConditionTab from "./TermsConditionTab";
|
||||
|
||||
export {
|
||||
@@ -15,5 +16,6 @@ export {
|
||||
PaymentMathodsTab,
|
||||
PersonalInfoTab,
|
||||
PrivacyPolicyTab,
|
||||
RecentActivitiesTab,
|
||||
TermsConditionTab,
|
||||
};
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import usersService from "../../services/UsersService";
|
||||
import Icons from "../Helpers/Icons";
|
||||
@@ -17,6 +11,7 @@ import {
|
||||
PaymentMathodsTab,
|
||||
PersonalInfoTab,
|
||||
PrivacyPolicyTab,
|
||||
RecentActivitiesTab,
|
||||
TermsConditionTab,
|
||||
} from "./Tabs";
|
||||
import RecipientAccountTab from "./Tabs/RecipientAccountTab";
|
||||
@@ -102,24 +97,30 @@ export default function Settings({ faq }) {
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "recent_activities",
|
||||
title: "Recent Activities",
|
||||
iconName: "login-activity",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "password",
|
||||
title: "Change Password",
|
||||
iconName: "password-hover",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
id: 8,
|
||||
name: "faq",
|
||||
title: "FAQ",
|
||||
iconName: "block-question",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
id: 9,
|
||||
name: "privacy",
|
||||
title: "Privacy Policy",
|
||||
iconName: "page-right",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
id: 10,
|
||||
name: "terms",
|
||||
title: "Terms and Conditions",
|
||||
iconName: "page-right",
|
||||
@@ -166,6 +167,7 @@ export default function Settings({ faq }) {
|
||||
</div>
|
||||
),
|
||||
login_activity: <LoginActivityTab />,
|
||||
recent_activities: <RecentActivitiesTab />,
|
||||
password: <ChangePasswordTab />,
|
||||
faq: <FaqTab datas={faq} />,
|
||||
privacy: <PrivacyPolicyTab />,
|
||||
|
||||
@@ -1,37 +1,18 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import RecomendedSliders from "./RecomendedSliders";
|
||||
|
||||
export default function CommonHead({ className, commonHeadData }) {
|
||||
export default function CommonHead({ className = "", commonHeadData = [] }) {
|
||||
return (
|
||||
<div
|
||||
className={`create-nft w-full lg:h-[140px] shadow lg:flex rounded-lg justify-between items-center md:p-2 p-2 bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] -2 border-pink mb-10 ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
{commonHeadData?.length > 0 && (
|
||||
<RecomendedSliders bannerData={commonHeadData} />
|
||||
<>
|
||||
{process.env.REACT_APP_SHOW_SLIDER_BANNERS === "1" && (
|
||||
<div
|
||||
className={`create-nft w-full lg:h-[140px] shadow lg:flex rounded-lg justify-between items-center md:p-2 p-2 bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] -2 border-pink mb-10 ${className}`}
|
||||
>
|
||||
{commonHeadData?.length > 0 && (
|
||||
<RecomendedSliders bannerData={commonHeadData} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{/*<div className="lg:w-8/12 w-full mb-8 lg:mb-0">*/}
|
||||
{/* /!*<h1 className="text-2xl text-dark-gray dark:text-white font-bold mb-2">*!/*/}
|
||||
{/* /!* This is common head which will appear as needed , will take many shape*!/*/}
|
||||
{/* /!*</h1>*!/*/}
|
||||
{/* /!*<p className="text-base text-thin-light-gray tracking-wide">*!/*/}
|
||||
{/* /!* some space for extra texts here*!/*/}
|
||||
{/* /!*</p>*!/*/}
|
||||
{/* */}
|
||||
{/*</div>*/}
|
||||
{/*<div className="flex-1 flex lg:justify-end">*/}
|
||||
{/* <div className="flex items-center space-x-5">*/}
|
||||
{/* <Link*/}
|
||||
{/* to="/mytask"*/}
|
||||
{/* className="w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"*/}
|
||||
{/* >*/}
|
||||
{/* View Task*/}
|
||||
{/* </Link>*/}
|
||||
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ const LoadedPage = ({reloader}) => {
|
||||
const { loading, data, error } = GetMyPageLoad(reloader);
|
||||
|
||||
return (
|
||||
<div className="w-full border border-gray-400 rounded-md p-4 flex flex-col h-72 gap-2 overflow-y-auto">
|
||||
<div className="w-full border border-gray-400 rounded-md p-4 flex flex-col h-72 gap-2 overflow-y-auto dark:text-white">
|
||||
{loading ? (
|
||||
<>
|
||||
<h1 className="text-xl font-bold tracking-wide">...</h1>
|
||||
|
||||
@@ -8,6 +8,7 @@ const YourPageForm = ({ values, onChange, onSubmit, loading, msg }) => (
|
||||
fieldClass="px-4"
|
||||
parentClass="flex items-center gap-1 justify-between"
|
||||
labelClass="flex-[0.2] mb-0 font-semibold"
|
||||
labalClass="dark:text-white"
|
||||
inputClass="flex-[0.8]"
|
||||
inputBg="bg-slate-100"
|
||||
label="Introduction: "
|
||||
@@ -24,7 +25,7 @@ const YourPageForm = ({ values, onChange, onSubmit, loading, msg }) => (
|
||||
</label>
|
||||
<textarea
|
||||
style={{ resize: "none" }}
|
||||
className="text-base px-4 py-2 rounded-md min-h-[100px] text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none flex-[0.8]"
|
||||
className="text-base px-4 py-2 rounded-[36px] min-h-[100px] text-dark-gray dark:text-white w-full bg-slate-100 focus:ring-0 focus:outline-none flex-[0.8]"
|
||||
name="description"
|
||||
cols="30"
|
||||
rows="2"
|
||||
|
||||
@@ -13,12 +13,39 @@ const YourPage = () => {
|
||||
const handleChange = ({ target: { name, value } }) =>
|
||||
setPageValues((prev) => ({ ...prev, [name]: value }));
|
||||
|
||||
const updateYourPageDetails = updateYourPage(
|
||||
pageValues,
|
||||
setResponse,
|
||||
setPageValues,
|
||||
setReloader
|
||||
);
|
||||
const updateYourPageDetails = async () => {
|
||||
if (!pageValues.intro || !pageValues.description) return;
|
||||
|
||||
try {
|
||||
setResponse({ loading: true, error: "", msg: "" });
|
||||
|
||||
let api = new usersService();
|
||||
const res = await api.MyPageIntro(pageValues);
|
||||
|
||||
setTimeout(() => {
|
||||
setResponse({
|
||||
loading: false,
|
||||
data: res.data,
|
||||
msg: "Update Complete",
|
||||
});
|
||||
|
||||
setReloader((prev) => !prev);
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
setResponse({ msg: "" });
|
||||
// Clear form after successful update
|
||||
setPageValues({ intro: "", description: "" });
|
||||
}, 3000);
|
||||
} catch (error) {
|
||||
return setResponse({
|
||||
loading: false,
|
||||
data: {},
|
||||
error: "Error updating page",
|
||||
msg: "",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
@@ -57,39 +84,3 @@ const responseInitialValues = {
|
||||
error: "",
|
||||
msg: "",
|
||||
};
|
||||
|
||||
function updateYourPage(pageValues, setResponse, setPageValues, setReloader) {
|
||||
return async () => {
|
||||
if (!pageValues.intro || !pageValues.description) return;
|
||||
|
||||
try {
|
||||
setResponse({ loading: true, error: "", msg: "" });
|
||||
|
||||
let api = new usersService();
|
||||
const res = await api.MyPageIntro(pageValues);
|
||||
|
||||
setTimeout(() => {
|
||||
setResponse({
|
||||
loading: false,
|
||||
data: res.data,
|
||||
msg: "Update Complete",
|
||||
});
|
||||
|
||||
setReloader((prev) => !prev);
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
setResponse({ msg: "" });
|
||||
// Clear form after successful update
|
||||
setPageValues({ intro: "", description: "" });
|
||||
}, 3000);
|
||||
} catch (error) {
|
||||
return setResponse({
|
||||
loading: false,
|
||||
data: {},
|
||||
error: "Error updating page",
|
||||
msg: "",
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Layout from '../Partials/Layout'
|
||||
|
||||
import usersService from '../../services/UsersService'
|
||||
import SearchCom from '../Helpers/SearchCom'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import CustomBreadcrumb from '../Breadcrumb/CustomBreadcrumb'
|
||||
import { localImgLoad } from '../../lib'
|
||||
|
||||
export default function FamAIQuestion() {
|
||||
const apiCall = new usersService()
|
||||
|
||||
const {pathname} = useLocation()
|
||||
|
||||
const [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: ''})
|
||||
|
||||
const [error, setError] = useState({question: '', searchPhrase: ''})
|
||||
|
||||
const [questions, setQuestions] = useState({loading: true, data: []})
|
||||
|
||||
const [askQuestion, setAskQuestion] = useState({question: '', searchPhrase: ''})
|
||||
|
||||
const changeAskQuestion = ({target: {name, value}}) => {
|
||||
setAskQuestion(prev => ({...prev, [name]: value}))
|
||||
setRequestStatus({loading: false, status: false, message: ''})
|
||||
}
|
||||
|
||||
const onSearch = () => {
|
||||
setError({question: '', searchPhrase: ''}) // sets error to false
|
||||
if(!askQuestion.question){
|
||||
return setError(prev => ({...prev, question: 'Select a question'}))
|
||||
}
|
||||
if(!askQuestion.searchPhrase){
|
||||
return setError(prev => ({...prev, searchPhrase: 'Enter search parameter'}))
|
||||
}
|
||||
if(askQuestion.searchPhrase.length > 60){
|
||||
return setError(prev => ({...prev, searchPhrase: 'Max of 60 characters'}))
|
||||
}
|
||||
|
||||
setRequestStatus({loading: true, status: false, message: ''})
|
||||
let reqData = {
|
||||
question_key: '',
|
||||
question: ''
|
||||
}
|
||||
apiCall.askResourcesResult().then(res => {
|
||||
console.log(res.data.choices[0].text)
|
||||
if(!res.data || res.data?.choices?.length < 1){
|
||||
setRequestStatus({loading: false, status: false, message: 'No result found!'})
|
||||
}
|
||||
setRequestStatus({loading: false, status: false, message: res.data?.choices[0].text})
|
||||
}).catch(error => {
|
||||
setRequestStatus({loading: false, status: false, message: 'No result found!'})
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
apiCall.getResourceList().then(res => {
|
||||
setQuestions({loading: false, data: res.data?.ask_categories?.data})
|
||||
}).catch(error => {
|
||||
setQuestions({loading: false, data: []})
|
||||
console.log('ERROR', error)
|
||||
})
|
||||
}, [])
|
||||
return (
|
||||
<Layout>
|
||||
<>
|
||||
<div className='mb-4'>
|
||||
<CustomBreadcrumb
|
||||
title={pathname == '/ai-question' ? 'Questions' : 'AI Lab'}
|
||||
breadcrumb = {
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: pathname == '/ai-question' ? '/ai-question' : '/ai-lab', title: pathname == '/ai-question' ? 'Questions' : 'AI Lab', active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={`w-full`}>
|
||||
<div className="main-container w-full">
|
||||
<div className="filter-section w-fullmb-6">
|
||||
{/* <h1 className="text-xl lg:text-2xl font-bold text-dark-gray dark:text-white tracking-wide">Ask our A.I</h1> */}
|
||||
<div className="mt-2 lg:grid grid-cols-2 gap-2 h-full lg:h-[500px]">
|
||||
<div className="h-full mb-5 lg:mb-0">
|
||||
<img className="w-full h-full rounded-2xl" src={localImgLoad(`images/resources-ask.jpg`)} alt='AI' />
|
||||
</div>
|
||||
<div className="p-8 bg-white rounded-2xl h-full">
|
||||
<div className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base">
|
||||
<select value={askQuestion.question} name='question' onChange={changeAskQuestion} className="input-field px-2 placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none">
|
||||
{questions.loading ?
|
||||
<option value='' className="">Loading...</option>
|
||||
:
|
||||
<>
|
||||
<option value='' className="">Find answer on:</option>
|
||||
{questions.data.length > 0 && questions.data.map((item, index)=>(
|
||||
<option key={index} value={item.question_key} className="">{item.name}</option>
|
||||
))}
|
||||
</>
|
||||
}
|
||||
|
||||
</select>
|
||||
</div>
|
||||
{error.question && <p className="text-red-500 text-[12px]">{error.question}</p>}
|
||||
{/* filter-search */}
|
||||
<div className="w-full my-5 border-2 rounded-full">
|
||||
<SearchCom
|
||||
name={'searchPhrase'}
|
||||
value={askQuestion.searchPhrase}
|
||||
handleSearch={changeAskQuestion}
|
||||
/>
|
||||
</div>
|
||||
{error.searchPhrase && <p className="text-red-500 text-[12px]">{error.searchPhrase}</p>}
|
||||
<div className="w-full flex justify-end items-center border-b-2 pb-4">
|
||||
<button
|
||||
onClick={onSearch}
|
||||
disabled={requestStatus.loading}
|
||||
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
|
||||
>
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
<div className="search_result my-2 max-h-[400px] overflow-auto">
|
||||
{requestStatus.loading ?
|
||||
<LoadingSpinner size='8' color='sky-blue' height='h-[100px]' />
|
||||
:
|
||||
<p className="py-2 text-sm font-bold text-dark-gray dark:text-white tracking-wide">{requestStatus.message}</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Layout from '../Partials/Layout'
|
||||
import SearchCom from '../Helpers/SearchCom'
|
||||
import DataIteration from '../Helpers/DataIteration'
|
||||
import FamBlogItem from './FamBlogItem'
|
||||
import CustomBreadcrumb from '../Breadcrumb/CustomBreadcrumb'
|
||||
import usersService from '../../services/UsersService'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
||||
|
||||
export default function FamBlog() {
|
||||
|
||||
const [blogData, setBlogData] = useState({loading: true, data: []});
|
||||
|
||||
const [filteredBlog, setFilteredBlog] = useState({value: '', data:[]}) // State to hold filter blog
|
||||
|
||||
const handleFilterBlog = ({target}) => {
|
||||
let filterWord = target.value
|
||||
let filteredData = []
|
||||
if(!filterWord){
|
||||
filteredData = blogData?.data?.blogdata
|
||||
}else{
|
||||
filteredData = blogData?.data?.blogdata?.filter(item => item.post_title.toLowerCase().startsWith(filterWord.toLowerCase()))
|
||||
}
|
||||
setFilteredBlog({value:target.value, data: filteredData})
|
||||
}
|
||||
|
||||
const api = new usersService();
|
||||
const getFamilyBlog = async () => {
|
||||
setBlogData({loading: true, data: []})
|
||||
try {
|
||||
const res = await api.getFamilyBlogData();
|
||||
setBlogData({loading: false, data:res.data});
|
||||
setFilteredBlog(prev => ({...prev, data:res.data?.blogdata}))
|
||||
} catch (error) {
|
||||
setBlogData({loading: false, data: []})
|
||||
throw new Error("Error getting mode");
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getFamilyBlog();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<>
|
||||
<div className='mb-4'>
|
||||
<CustomBreadcrumb
|
||||
title='Blog'
|
||||
breadcrumb = {
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/fam-blog", title: "Blogs", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={`w-full`}>
|
||||
<div className="main-container w-full">
|
||||
<div className="filter-section w-full items-center sm:flex justify-between mb-6">
|
||||
{/* filter-search */}
|
||||
{blogData?.data?.blogdata?.length > 0 &&
|
||||
<div className="sm:w-1/2 w-full sm:pr-20 pr-0 mb-5 sm:mb-0">
|
||||
<SearchCom
|
||||
placeholder='Search Blog Items...'
|
||||
value={filteredBlog.value}
|
||||
handleSearch={handleFilterBlog}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className="content-section w-full-width">
|
||||
{blogData.loading ?
|
||||
<div className='flex justify-center items-center bg-white rounded-2xl'>
|
||||
<LoadingSpinner size='10' color='sky-blue' height='h-[20rem]' />
|
||||
</div>
|
||||
: blogData?.data?.blogdata?.length > 0 && filteredBlog?.data?.length > 0?
|
||||
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
|
||||
<DataIteration
|
||||
datas={filteredBlog?.data}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={filteredBlog?.data?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<div key={Math.random()}>
|
||||
<FamBlogItem
|
||||
datas={datas}
|
||||
bg={blogData?.data?.image_url && blogData?.data?.image_url}
|
||||
className=''
|
||||
hidden={false}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</DataIteration>
|
||||
</div>
|
||||
:
|
||||
<div className='h-[30rem] flex justify-center items-center bg-white rounded-2xl'>
|
||||
<p>No Blog Found</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default function FamBlogItem({datas, className, bg, hidden=false}) {
|
||||
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 bg-sky-200"
|
||||
style={{
|
||||
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 */}
|
||||
<Link to={`/blog-page?blog_id=${datas?.ID ? datas.ID : '1'}`} 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 ? datas?.post_title : "dummy title..."}
|
||||
</h1>
|
||||
</Link>
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center space-x-2"></div>
|
||||
<div className="my-1">
|
||||
<Link
|
||||
to={`/blog-page?blog_id=${datas?.ID ? datas.ID : '1'}`}
|
||||
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
|
||||
rel="noreferrer"
|
||||
>
|
||||
View
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import Layout from '../Partials/Layout'
|
||||
|
||||
export default function FamGames() {
|
||||
return (
|
||||
<Layout>
|
||||
<div>Family Games Page</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import Layout from '../Partials/Layout'
|
||||
|
||||
export default function FamInterest() {
|
||||
return (
|
||||
<Layout>
|
||||
<div>Fam Interesting Dummy Page</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import defaultImg from "../../assets/images/myfiles/default.svg";
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
import { PaginatedList, handlePagingFunc } from "../../components/Pagination";
|
||||
import Layout from "../Partials/Layout";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function FamMyFiles() {
|
||||
|
||||
let uploadedFiles = [] // To be updated Later from replaced with real data from API CALL
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem =
|
||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentFiles = uploadedFiles?.data?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
return (
|
||||
<Layout>
|
||||
<>
|
||||
<div className=''>
|
||||
<CustomBreadcrumb
|
||||
title='My Files'
|
||||
breadcrumb = {
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/myfiles", title: "My Files", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4 w-full flex justify-end item-center">
|
||||
<Link
|
||||
to="/my-uploads"
|
||||
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
|
||||
>
|
||||
Add My Item
|
||||
</Link>
|
||||
</div>
|
||||
<div
|
||||
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow relative min-h-[520px]`}
|
||||
>
|
||||
<div className="header w-full sm:flex justify-between items-center mb-5">
|
||||
<div className="flex space-x-2 items-center mb-2 sm:mb-0">
|
||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
My Uploads
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative w-full overflow-x-auto sm:rounded-lg">
|
||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||
<tbody>
|
||||
<>
|
||||
{uploadedFiles?.data && uploadedFiles?.data.length ? (
|
||||
currentFiles.map((value, idx) => {
|
||||
let addedDate = value?.added?.split(" ")[0];
|
||||
let formattedSize = formatFileSize(value?.file_size);
|
||||
let imageLink = `${uploadedFiles?.image}${localStorage.getItem('session_token')}/myfile/${value.file_uid}`
|
||||
return (
|
||||
<tr
|
||||
key={value?.file_uid}
|
||||
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
||||
>
|
||||
<td className=" py-4">
|
||||
<div className="flex space-x-2 items-center w-full">
|
||||
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={
|
||||
localImgLoad(
|
||||
`images/myfiles/${value.banner}`
|
||||
) || defaultImg
|
||||
}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col flex-[0.9]">
|
||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||
{value.title || "Dummy Text"}
|
||||
</h1>
|
||||
<div>
|
||||
{value.description || "Dummy Description"}
|
||||
</div>
|
||||
<span className="text-sm text-thin-light-gray flex flext-start gap-1">
|
||||
Added:{" "}
|
||||
<span className="text-purple">{addedDate}</span>
|
||||
</span>
|
||||
<div className="flex gap-4 items-center">
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
File Name:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{value.file_name}
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
File Size:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{formattedSize}
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
File Type:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{value?.file_type}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="text-right py-4 px-2">
|
||||
<div className="flex justify-center items-center">
|
||||
<a
|
||||
href={imageLink}
|
||||
title="download"
|
||||
// className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<img
|
||||
src={localImgLoad('images/icons/download-arrow.svg')}
|
||||
alt='download-link'
|
||||
className="w-auto h-6 flex justify-center items-center"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||
<td className="p-2" colSpan={3}>
|
||||
No Files Currently!
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
</tbody>
|
||||
</table>
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
uploadedFiles?.data?.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
data={uploadedFiles?.data}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
const formatFileSize = (sizeInBytes) => {
|
||||
if (sizeInBytes < 1024) {
|
||||
return `${sizeInBytes} bytes`;
|
||||
} else if (sizeInBytes < 1024 * 1024) {
|
||||
const sizeInKB = (sizeInBytes / 1024).toFixed(2);
|
||||
return `${sizeInKB} KB`;
|
||||
} else {
|
||||
const sizeInMB = (sizeInBytes / (1024 * 1024)).toFixed(2);
|
||||
return `${sizeInMB} MB`;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from 'react'
|
||||
import Layout from '../Partials/Layout'
|
||||
import CustomBreadcrumb from '../Breadcrumb/CustomBreadcrumb'
|
||||
|
||||
export default function FamWorkInProgress() {
|
||||
return (
|
||||
<Layout>
|
||||
<>
|
||||
<div className='mb-4'>
|
||||
<CustomBreadcrumb
|
||||
title='Games and Interest'
|
||||
breadcrumb = {
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/work-in-progress", title: "Games and Interest", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className='h-[20rem] w-full bg-white shadow-lg flex justify-center items-center rounded-2xl'>Work in Progress Coming Soon</div>
|
||||
</>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import InputCom from "../Helpers/Inputs/InputCom/index";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import Detail from "./popoutcomponent/Detail";
|
||||
import { SocketValues } from "../Contexts/SocketIOContext";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
family: Yup.string().required("This is required "),
|
||||
@@ -29,6 +30,9 @@ function JobListPopout({
|
||||
openWallet,
|
||||
setWalletItem,
|
||||
}) {
|
||||
|
||||
let {marketUpdate} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
|
||||
|
||||
const [selectedTab, setSelectedTab] = useState("public");
|
||||
const tabs = ["public", "individual", "group"];
|
||||
|
||||
@@ -201,7 +205,9 @@ function JobListPopout({
|
||||
setRequestStatus({ message: "", status: false });
|
||||
}, 3000);
|
||||
}
|
||||
dispatch(tableReload({ type: "JOBTABLE" }));
|
||||
marketUpdate('market', 'full-markets-jobs') // sends an event to the socket to update market lists
|
||||
dispatch(tableReload({ type: "JOBTABLE" })); // reloads my job page
|
||||
dispatch(tableReload({ type: "MARKETTABLELIST" })); // reloads market page
|
||||
setRequestStatus({ message: data?.status_msg ? data?.status_msg : "Offer Assigned Successful", status: true });
|
||||
setTimeout(() => {
|
||||
setLoader({ jobFields: false });
|
||||
@@ -224,6 +230,12 @@ function JobListPopout({
|
||||
members: [],
|
||||
});
|
||||
|
||||
const DetailsSection = ({ label, value }) => (
|
||||
<div className="my-3 md:flex">
|
||||
<Detail label={label} value={value} />
|
||||
</div>
|
||||
);
|
||||
|
||||
// FUNCTION TO POPULATE USER GROUP LIST
|
||||
useEffect(() => {
|
||||
// setGroupList({loading: true, groups: [], members: []})
|
||||
@@ -250,12 +262,6 @@ function JobListPopout({
|
||||
});
|
||||
}, []);
|
||||
|
||||
const DetailsSection = ({ label, value }) => (
|
||||
<div className="my-3 md:flex">
|
||||
<Detail label={label} value={value} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const DetailsComponent = () => {
|
||||
const detailsArray = [
|
||||
{ label: "Description", value: details.description },
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react'
|
||||
function Detail({label, value, bg,}) {
|
||||
return (
|
||||
<>
|
||||
<label className='w-full md:w-1/4 text-slate-900 dark:text-white tracking-wide font-semibold'>{label}</label>
|
||||
<label className='job-label w-full md:w-1/4'>{label}</label>
|
||||
<p className={`p-1 w-full md:w-3/4 text-sm text-slate-900 dark:text-white ${bg ? bg : null}`}>{value}</p>
|
||||
</>
|
||||
)
|
||||
|
||||
+7
-2
@@ -52,9 +52,8 @@
|
||||
}
|
||||
.job-action {
|
||||
background-color: #4687ba;
|
||||
height: 100px;
|
||||
border-radius: 15px;
|
||||
padding: 5px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.msg_box {
|
||||
@@ -153,6 +152,12 @@
|
||||
--toastify-color-success: #f539f8;
|
||||
}
|
||||
|
||||
@layer components{
|
||||
.job-label{
|
||||
@apply text-slate-900 dark:text-white tracking-wide font-semibold
|
||||
}
|
||||
}
|
||||
|
||||
/* ===================== EXTRA ===================== */
|
||||
.bottomMargin {
|
||||
margin-bottom: 15px;
|
||||
|
||||
@@ -133,6 +133,7 @@ export const apiConst = {
|
||||
WRENCHBOARD_ACCOUNT_HOMEBANNERS: 11200,
|
||||
WRENCHBOARD_ACCOUNT_PLAYGROUND: 11201,
|
||||
WRENCHBOARD_ACCOUNT_FAMILY_BANNERS: 22005,
|
||||
WRENCHBOARD_ACCOUNT_FAMILY_RESOURCES: 22017,
|
||||
|
||||
WRENCHBOARD_ACCOUNT_RECENTS: 11202,
|
||||
WRENCHBOARD_ACCOUNT_NOTIFICATIONS: 11205,
|
||||
|
||||
@@ -12,8 +12,14 @@ import { updateNotifications } from "../store/notifications";
|
||||
import { updateUserJobList } from "../store/userJobList";
|
||||
import { updateWalletDetails } from "../store/walletDetails";
|
||||
import { familyBannersList } from "../store/FamilyBannerList";
|
||||
import { familyResources } from "../store/FamilyResources";
|
||||
import {familyWalletRedeemOptList} from '../store/FamilyWalletRedeemOpt'
|
||||
import { SocketValues } from "../components/Contexts/SocketIOContext";
|
||||
|
||||
const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
|
||||
let {joinRoom} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
|
||||
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
const dispatch = useDispatch();
|
||||
const [lastActivityTime, setLastActivityTime] = useState(Date.now());
|
||||
@@ -21,23 +27,20 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
const [loadProfileDetails, setLoadProfileDetails] = useState([]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { jobListTable, walletTable, familyBannersListTable } = useSelector(
|
||||
const { jobListTable, marketTableList, walletTable, familyBannersListTable } = useSelector(
|
||||
(state) => state.tableReload
|
||||
);
|
||||
|
||||
const {
|
||||
userDetails: { username, uid, session, account_type },
|
||||
userDetails: { username, uid, session, account_type, parent_uid },
|
||||
} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||
|
||||
let loggedIn = username && session && uid ? true : false; // variable to determine if user is logged in
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
//Removing Data stored at localStorage after session expires
|
||||
const expireSession = () => {
|
||||
localStorage.removeItem("uid");
|
||||
localStorage.removeItem("member_id");
|
||||
localStorage.removeItem("session_token");
|
||||
sessionStorage.removeItem("family_uid");
|
||||
sessionStorage.clear();
|
||||
localStorage.clear();
|
||||
navigate("/login", { replace: true }); // redirects user to login page after session expires
|
||||
};
|
||||
@@ -103,6 +106,8 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
});
|
||||
};
|
||||
loadProfile();
|
||||
}else{
|
||||
setIsLogin({ loading: false, status: true });
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -187,6 +192,9 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
}, [jobListTable, isLogin.status]);
|
||||
|
||||
useEffect(() => {
|
||||
if((!loggedIn && !isLogin.status) || account_type == 'FAMILY'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FAMILY
|
||||
return
|
||||
}
|
||||
const getMyWalletList = async () => {
|
||||
dispatch(updateWalletDetails({ loading: true, data: [] }));
|
||||
try {
|
||||
@@ -201,7 +209,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
}
|
||||
};
|
||||
getMyWalletList();
|
||||
}, [walletTable]);
|
||||
}, [walletTable, isLogin.status]);
|
||||
|
||||
useEffect(() => {
|
||||
if((!loggedIn && !isLogin.status) || account_type == 'FAMILY'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FAMILY
|
||||
@@ -217,7 +225,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
}
|
||||
};
|
||||
getMarketActiveJobList();
|
||||
}, [apiCall, dispatch, jobListTable, isLogin.status]);
|
||||
}, [apiCall, dispatch, marketTableList, isLogin.status]);
|
||||
|
||||
//FUNCTION TO GET COMMON HEAD DATA
|
||||
useEffect(() => {
|
||||
@@ -227,7 +235,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
apiCall
|
||||
.getHeroJBanners()
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 0) {
|
||||
if (res.data?.internal_return < 0) {
|
||||
return;
|
||||
}
|
||||
dispatch(commonHeadBanner(res.data));
|
||||
@@ -239,6 +247,9 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
|
||||
//FUNCTION TO GET COMMON HEAD DATA
|
||||
useEffect(() => {
|
||||
if((!loggedIn && !isLogin.status) || account_type == 'FAMILY'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FAMILY
|
||||
return
|
||||
}
|
||||
apiCall
|
||||
.getRecentActivitiedData()
|
||||
.then((res) => {
|
||||
@@ -251,7 +262,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
.catch((error) => {
|
||||
console.log("ERROR ", error);
|
||||
});
|
||||
}, []);
|
||||
}, [isLogin.status]);
|
||||
|
||||
|
||||
//FUNCTION TO GET FAMILY BANNERS
|
||||
@@ -263,29 +274,62 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
// setFamilyBannersList({loading:true, result:[]});
|
||||
try {
|
||||
const res = await apiCall.getFamilyBannersList();
|
||||
dispatch(familyBannersList(res.data))
|
||||
dispatch(familyBannersList({...res.data, loading:false}))
|
||||
} catch (error) {
|
||||
dispatch(familyBannersList({loading:false}))
|
||||
console.log("Error getting tasks");
|
||||
}
|
||||
};
|
||||
getFamilyBanners()
|
||||
}, [isLogin.status, familyBannersListTable]);
|
||||
|
||||
// useEffect(() => {
|
||||
// apiCall
|
||||
// .getHeroJBanners()
|
||||
// .then((res) => {
|
||||
// if (res.data.internal_return < 0) {
|
||||
// return;
|
||||
// }
|
||||
// dispatch(commonHeadBanner(res.data));
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.log("ERROR ", error);
|
||||
// });
|
||||
// }, []);
|
||||
//
|
||||
//FUNCTION TO GET FAMILY RESOURCES
|
||||
useEffect(() => {
|
||||
if((!loggedIn && !isLogin.status) || account_type == 'FULL'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FULL
|
||||
return
|
||||
}
|
||||
const getFamilyResourcesList = async () => { // FUNCTION TO GET FAMILY BANNERS
|
||||
try {
|
||||
const res = await apiCall.getFamilyResources();
|
||||
dispatch(familyResources(res?.data?.result_list))
|
||||
// console.log('RESPONSE', res?.data?.result_list)
|
||||
} catch (error) {
|
||||
console.log("Error getting tasks");
|
||||
}
|
||||
};
|
||||
getFamilyResourcesList()
|
||||
}, [isLogin.status]);
|
||||
|
||||
|
||||
//FUNCTION TO GET FAMILY WALLET REDEEM OPTIONS
|
||||
useEffect(() => {
|
||||
if((!loggedIn && !isLogin.status) || account_type == 'FULL'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FULL
|
||||
return
|
||||
}
|
||||
const familyWalletRedeemOptions = async () => { // FUNCTION TO GET FAMILY WALLET REDDEM OPTIONS
|
||||
dispatch(familyWalletRedeemOptList({loading: true, image: '', data:{}}))
|
||||
apiCall.getFamilyWalletRedeemOptions().then((res)=>{
|
||||
dispatch(familyWalletRedeemOptList({loading: false, image: res?.data?.session_image_server, data:res?.data?.result_list}))
|
||||
}).catch((err)=>{
|
||||
console.log(err)
|
||||
dispatch(familyWalletRedeemOptList({loading: false, image: '', data:{}}))
|
||||
})
|
||||
};
|
||||
familyWalletRedeemOptions()
|
||||
}, [isLogin.status]);
|
||||
|
||||
useEffect(()=>{ // sends an event to the socket to enable user join a room to be able to receive update when jobs enters the market
|
||||
joinRoom('full-markets-jobs')
|
||||
},[isLogin.status])
|
||||
|
||||
useEffect(()=>{ // sends an event to the socket to enable user join a room to be able to receive update for parent child job assign
|
||||
if(loggedIn || isLogin.status){
|
||||
joinRoom(`FAMILY-${account_type == 'FULL' ? uid : sessionStorage.getItem('parent_uid')}`)
|
||||
console.log(`Room joined for parent child task assign as ${account_type} with ${account_type == 'FULL' ? uid : sessionStorage.getItem('parent_uid')}}`)
|
||||
}
|
||||
},[isLogin.status])
|
||||
|
||||
// RENDER PAGE
|
||||
return isLogin.loading && !loggedIn ? (
|
||||
<LoadingSpinner size="32" color="sky-blue" height="h-screen" />
|
||||
) : !isLogin.status && !loggedIn ? (
|
||||
|
||||
@@ -31,6 +31,10 @@ class usersService {
|
||||
return this.postAuxEnd("/createuser", reqData);
|
||||
}
|
||||
|
||||
blogData() {
|
||||
return this.getAuxEnd("/blogdata", null);
|
||||
}
|
||||
|
||||
CompleteOauthLogin(reqData) {
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/authlogin", reqData);
|
||||
@@ -384,13 +388,26 @@ class usersService {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_JOB_CREATEJOB,
|
||||
action: apiConst.WRENCHBOARD_JOB_CREATEJOB || apiConst.WRENCHBOARD_FAMILY_LIST,
|
||||
limit: 30,
|
||||
offset: 0,
|
||||
};
|
||||
return this.postAuxEnd("/familywaitingtasks", postData);
|
||||
}
|
||||
|
||||
ManageFamilyNewWaitlist() {
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_FAMILY_LIST,
|
||||
limit: 20,
|
||||
page: 1,
|
||||
offset: 0,
|
||||
};
|
||||
return this.postAuxEnd("/familywaitingtasks", postData);
|
||||
}
|
||||
|
||||
ManageFamilyPending() {
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
@@ -1245,11 +1262,11 @@ class usersService {
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_RELATIVE_INVITE,
|
||||
...reqData
|
||||
...reqData,
|
||||
};
|
||||
return this.postAuxEnd("/familyrelinvite", postData);
|
||||
}
|
||||
|
||||
|
||||
// API FUNCTION TO FAMILY BANNERS
|
||||
getFamilyBannersList() {
|
||||
var postData = {
|
||||
@@ -1258,10 +1275,50 @@ class usersService {
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_ACCOUNT_FAMILY_BANNERS,
|
||||
limit: 20,
|
||||
offset: 1
|
||||
offset: 1,
|
||||
};
|
||||
return this.postAuxEnd("/familybanners", postData);
|
||||
}
|
||||
|
||||
// API FUNCTION TO FAMILY RESOURCES
|
||||
getFamilyResources() {
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_ACCOUNT_FAMILY_RESOURCES,
|
||||
limit: 20,
|
||||
offset: 1,
|
||||
};
|
||||
return this.postAuxEnd("/familyresources", postData);
|
||||
}
|
||||
|
||||
// API FUNCTION TO GET FAMILY BLOG DATA
|
||||
getFamilyBlogData() {
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
page: 0,
|
||||
offset: 0,
|
||||
limit: 100,
|
||||
};
|
||||
return this.postAuxEnd("/blogdata", postData);
|
||||
}
|
||||
|
||||
// API FUNCTION FOR FAMILY WALLET REDEEM OPTIONS
|
||||
getFamilyWalletRedeemOptions() {
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_JOB_ACTIVE,
|
||||
offset: 0,
|
||||
limit: 30,
|
||||
};
|
||||
return this.postAuxEnd("/familywallet/redeem/options", postData);
|
||||
}
|
||||
|
||||
/*
|
||||
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
|
||||
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
familyBannersList: {}
|
||||
familyBannersList: {loading:true}
|
||||
};
|
||||
|
||||
export const familyBannersListSlice = createSlice({
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
familyResources: {}
|
||||
};
|
||||
|
||||
export const familyResourcesSlice = createSlice({
|
||||
name: "familyResources",
|
||||
initialState,
|
||||
reducers: {
|
||||
familyResources: (state,action) => {
|
||||
state.familyResources = {...action.payload}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { familyResources } = familyResourcesSlice.actions;
|
||||
|
||||
export default familyResourcesSlice.reducer;
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
familyWalletRedeemOptList: {loading: true, image: '', data: {}}
|
||||
};
|
||||
|
||||
export const familyWalletRedeemOptListSlice = createSlice({
|
||||
name: "familyWalletRedeemOptList",
|
||||
initialState,
|
||||
reducers: {
|
||||
familyWalletRedeemOptList: (state,action) => {
|
||||
state.familyWalletRedeemOptList = {...action.payload}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { familyWalletRedeemOptList } = familyWalletRedeemOptListSlice.actions;
|
||||
|
||||
export default familyWalletRedeemOptListSlice.reducer;
|
||||
@@ -9,6 +9,9 @@ const initialState = {
|
||||
walletTable: false,
|
||||
uploadsTable: false,
|
||||
familyBannersListTable: false,
|
||||
chatMessageList: false,
|
||||
marketTableList: false,
|
||||
familyOfferList: false,
|
||||
};
|
||||
|
||||
export const tableReloadSlice = createSlice({
|
||||
@@ -41,6 +44,15 @@ export const tableReloadSlice = createSlice({
|
||||
case "FAMILYBANNERSLIST":
|
||||
state.familyBannersListTable = !state.familyBannersListTable;
|
||||
return;
|
||||
case "CHATMESSAGELIST":
|
||||
state.chatMessageList = !state.chatMessageList;
|
||||
return;
|
||||
case "MARKETTABLELIST":
|
||||
state.marketTableList = !state.marketTableList;
|
||||
return;
|
||||
case "FAMILYOFFERLIST":
|
||||
state.familyOfferList = !state.familyOfferList;
|
||||
return;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
+5
-1
@@ -9,6 +9,8 @@ import notificationsReducer from "./notifications";
|
||||
import userJobListReducer from "./userJobList";
|
||||
import walletDetails from "./walletDetails";
|
||||
import familyBannerListReducer from "./FamilyBannerList"
|
||||
import familyResourcesReducer from './FamilyResources'
|
||||
import familyWalletRedeemOptListReducer from './FamilyWalletRedeemOpt'
|
||||
|
||||
export default configureStore({
|
||||
reducer: {
|
||||
@@ -20,6 +22,8 @@ export default configureStore({
|
||||
commonHeadBanner: commonHeadBannerReducer,
|
||||
notifications: notificationsReducer,
|
||||
walletDetails: walletDetails,
|
||||
familyBannersList: familyBannerListReducer
|
||||
familyBannersList: familyBannerListReducer,
|
||||
familyResources: familyResourcesReducer,
|
||||
familyWalletRedeemOptList: familyWalletRedeemOptListReducer
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import FamAIQuestion from '../components/familyResources/FamAIQuestion'
|
||||
|
||||
export default function FamAIQuestionPage() {
|
||||
return (
|
||||
<>
|
||||
<FamAIQuestion />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import FamBlog from '../components/familyResources/FamBlog'
|
||||
|
||||
export default function FamBlogPage() {
|
||||
return (
|
||||
<>
|
||||
<FamBlog />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
import FamGames from '../components/familyResources/FamGames'
|
||||
export default function FamGamesPage() {
|
||||
return (
|
||||
<>
|
||||
<FamGames />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import FamInterest from '../components/familyResources/FamInterest'
|
||||
|
||||
export default function FamInterestPage() {
|
||||
return (
|
||||
<>
|
||||
<FamInterest />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import FamMyFiles from '../components/familyResources/FamMyFiles'
|
||||
|
||||
export default function FamMyFilesPage() {
|
||||
return (
|
||||
<>
|
||||
<FamMyFiles />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import FamWorkInProgress from '../components/familyResources/FamWorkInProgress'
|
||||
|
||||
export default function FamWorkInProgressPage() {
|
||||
return (
|
||||
<>
|
||||
<FamWorkInProgress />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import FamilyActivities from "../components/FamilyAcc/FamilyActivities";
|
||||
|
||||
const FamilyActivitiesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<FamilyActivities />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FamilyActivitiesPage;
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import FamilyPending from '../components/FamilyAcc/FamilyPendingOffer'
|
||||
|
||||
export default function FamilyPendingOfferPage() {
|
||||
return (
|
||||
<>
|
||||
<FamilyPending />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import FamilyWalletCon from "../components/MyWallet/FamilyWalletCon";
|
||||
|
||||
export default function FamilyWalletPage() {
|
||||
return <FamilyWalletCon />;
|
||||
}
|
||||
@@ -2,12 +2,17 @@ import React, { useEffect, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import ActiveJobs from "../components/MyActiveJobs/ActiveJobs";
|
||||
import usersService from "../services/UsersService";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
/**
|
||||
* This code defines a React functional component called `ManageActiveJobs`.
|
||||
* It fetches a list of active job messages and renders the `ActiveJobs` component with the necessary props.
|
||||
*/
|
||||
function ManageActiveJobs() {
|
||||
const { chatMessageList } = useSelector(
|
||||
(state) => state.tableReload
|
||||
);
|
||||
|
||||
const ApiCall = new usersService();
|
||||
|
||||
const navigate = useNavigate();
|
||||
@@ -39,7 +44,7 @@ function ManageActiveJobs() {
|
||||
loading: false,
|
||||
error: false,
|
||||
data: res.data.result_list,
|
||||
image: res.data.session_image_server
|
||||
image: res.data.session_image_server,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -54,7 +59,7 @@ function ManageActiveJobs() {
|
||||
}
|
||||
setDetails(state);
|
||||
getActiveJobMesList();
|
||||
}, [activeJobMesListReload]);
|
||||
}, [activeJobMesListReload, chatMessageList]);
|
||||
|
||||
return (
|
||||
<ActiveJobs
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useContext,useState, useEffect } from "react";
|
||||
import usersService from "../services/UsersService";
|
||||
//import MyJobs from "../components/MyJobs";
|
||||
//import MyActiveJobs from "../components/MyActiveJobs";
|
||||
|
||||
import MyPastDueJobs from "../components/MyActiveJobs/MyPastDueJobs";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
@@ -9,7 +8,7 @@ export default function MyPastDueJobsPage() {
|
||||
let {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
|
||||
const [MyJobList, setMyJobList] = useState([]);
|
||||
const api = new usersService();
|
||||
//TARGET ENDPOINT[POST]http://10.204.5.100:9083/en/wrench/api/v1/jobmanageractive
|
||||
|
||||
const getMyJobList = async () => {
|
||||
try {
|
||||
const res = await api.getMyPastDueJobList();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user