Compare commits

..

35 Commits

Author SHA1 Message Date
victorAnumudu a9cf3c9d22 added breadcrumb to some pages in full account type 2024-03-07 16:51:24 +01:00
ameye 01bf8a4c52 Merge branch 'login-page-width' of WrenchBoard/Users-Wrench into master 2024-03-07 12:50:47 +00:00
victorAnumudu 68ab094bf6 reduced login page width 2024-03-07 13:42:16 +01:00
ameye d938202f7a Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-03-07 12:25:12 +00:00
Ebube c9f66bdacb Completed layout for family activities 2024-03-07 10:01:43 +01:00
Ebube 5854ad194a Added layout for activities page 2024-03-07 09:23:14 +01:00
ameye 0f25a92b88 Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-03-06 22:01:34 +00:00
Ebube 9d7bcd91f4 . 2024-03-06 20:48:54 +01:00
Ebube 68115e79fa Added the following changes 2024-03-06 18:52:07 +01:00
ameye de379c2bbc Merge branch 'manage-job-padding' of WrenchBoard/Users-Wrench into master 2024-03-06 17:42:38 +00:00
victorAnumudu 2c11a0755d manage job page padding reduction 2024-03-06 18:21:58 +01:00
ameye f4ed892c5c Merge branch 'family-wallet-page' of WrenchBoard/Users-Wrench into master 2024-03-06 16:24:49 +00:00
ameye 30403f27c5 Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-03-06 16:24:44 +00:00
victorAnumudu cf2df7529d added family wallet page 2024-03-06 16:12:55 +01:00
Ebube b3695324b3 Removed next due task countdown and modified my page format 2024-03-06 15:21:55 +01:00
ameye cf8f32ed64 Merge branch 'past-due-task' of WrenchBoard/Users-Wrench into master 2024-03-06 11:00:07 +00:00
victorAnumudu bd59f26146 added past due task page 2024-03-06 00:00:27 +01:00
ameye 3a397aad86 Merge branch 'family-home-active-task' of WrenchBoard/Users-Wrench into master 2024-03-05 14:51:16 +00:00
victorAnumudu 0f548e216d removed active task display from family home page 2024-03-05 15:49:04 +01:00
ameye 50fd9711e0 Merge branch 'breadcrumb-addition' of WrenchBoard/Users-Wrench into master 2024-03-04 17:46:41 +00:00
victorAnumudu f4d9eb65c6 added breadcrumb component to other family account pages 2024-03-04 18:12:02 +01:00
ameye 774224ba6d Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-03-04 16:46:09 +00:00
Ebube 9eae733755 changed to square brackets and reduced font 2024-03-04 17:34:11 +01:00
ameye 0aee3b9d6f Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-03-04 15:29:11 +00:00
Ebube b676a2a4f3 username replacement and Active task window feedback 2024-03-04 15:16:41 +01:00
ameye 0baacb3057 Merge branch 'family-blog-population' of WrenchBoard/Users-Wrench into master 2024-03-04 14:14:58 +00:00
victorAnumudu 9737c02d45 added family blog api resources 2024-03-04 15:05:31 +01:00
ameye 1048e51ddf Merge branch 'family-commonheader' of WrenchBoard/Users-Wrench into master 2024-03-04 10:52:33 +00:00
victorAnumudu 6545c32326 removed common header in family single blog post page 2024-03-04 01:29:22 +01:00
ameye 6ea9078848 Merge branch 'family-file-resource' of WrenchBoard/Users-Wrench into master 2024-03-01 20:55:47 +00:00
victorAnumudu 735cc0b296 corrected text error 2024-03-01 21:36:28 +01:00
ameye 29e058828b Merge branch 'family-resource-pages' of WrenchBoard/Users-Wrench into master 2024-03-01 20:13:32 +00:00
victorAnumudu 5d5542c221 merged master to branch 2024-03-01 21:05:03 +01:00
ameye b59f92c89f Merge branch 'bug-fixing' of WrenchBoard/Users-Wrench into master 2024-03-01 19:58:07 +00:00
victorAnumudu e01bfa369b created pages for family resources 2024-03-01 18:49:23 +01:00
65 changed files with 1885 additions and 620 deletions
+4 -1
View File
@@ -108,4 +108,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
+4 -1
View File
@@ -76,4 +76,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
+4 -1
View File
@@ -82,4 +82,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
+16 -4
View File
@@ -59,7 +59,13 @@ import VerifyYouPagesTwo from "./views/VerifyYouPagesTwo";
import YourPages from "./views/YourPage_";
import ParentWaitingPage from "./views/ParentWaitingPage";
import FamilyPendingOfferPage from "./views/FamilyPendingOfferPage";
import FamilyPastDuePage from "./views/FamilyPastDuePage";
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 (
@@ -120,26 +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="/pastdue" element={<FamilyPastDuePage />} />
<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 />} />
@@ -158,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 -1
View File
@@ -25,7 +25,7 @@ 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 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>
+32 -11
View File
@@ -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>
@@ -1,5 +1,4 @@
import React from "react";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
@@ -41,39 +40,6 @@ export default function FamilyParentDashboard({
</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>
)}
<span className="text-base font-thin tracking-wide text-white flex items-end">
Last Login : {loginDate}
</span>
@@ -1,5 +1,4 @@
import React from "react";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
@@ -38,38 +37,6 @@ export default function HomeDashboard({ className, bannerList, nextDueTask }) {
</div>
</div>
{/* countdown */}
{nextDueTask?.next_due &&
Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border 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>
)}
<span className="text-base font-thin tracking-wide text-white flex items-end">
Last Login : {loginDate}
</span>
@@ -1,5 +1,4 @@
import React from "react";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
@@ -42,38 +41,6 @@ export default function JobOwnerDashboard({
</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>
)}
<span className="text-base font-thin tracking-wide text-white flex items-end">
Last Login : {loginDate}
</span>
+35 -28
View File
@@ -1,14 +1,16 @@
import React, { useState } from "react";
import React 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 HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
import HomeSliders from "../Home/HomeSliders";
export default function WorkerDashboard({ className, bannerList, nextDueTask }) {
export default function WorkerDashboard({
className,
bannerList,
nextDueTask,
}) {
const settings = {
autoplay: true,
dots: true,
@@ -57,32 +59,37 @@ export default function WorkerDashboard({ className, bannerList, nextDueTask })
</div>
</div>
{/* countdown */}
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border 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>
{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>
</div>
)}
)}
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link to="/mytask" className="text-white text-base">
@@ -1,5 +1,4 @@
import React from "react";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
@@ -41,39 +40,6 @@ export default function WorkerDashboard({
</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>
)}
<span className="text-base font-thin tracking-wide text-white flex items-end">
Last Login : {loginDate}
</span>
@@ -0,0 +1,78 @@
import React, { Suspense, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import usersService from "../../services/UsersService";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import FamilyTableNew from "./FamilyTableNew";
export default function FamilyActivities() {
const [familyList, setFamilyList] = useState({});
const [loader, setLoader] = useState(false);
const apiCall = useMemo(() => new usersService(), []);
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">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span className={``}>Tasks & Chores</span>
</h1>
</div>
<Link className="flex items-center gap-2" 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
familyList={familyList?.result_list}
loader={loader}
imageServer={familyList?.session_image_server}
/>
</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>
);
+13 -1
View File
@@ -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">
@@ -3,6 +3,7 @@ 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';
export default function FamilyPendingOffer() {
const userApi = new usersService();
@@ -25,8 +26,21 @@ export default function FamilyPendingOffer() {
},[])
return (
<Layout>
<div className="mb-5">
<CustomBreadcrumb
title = {'Ready to Start'}
breadcrumb={
[
{ link: "/", title: "Home" },
{ link: "/pending", title: "Pending", active: true},
]
}
/>
</div>
{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
+25 -9
View File
@@ -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>
+314
View File
@@ -0,0 +1,314 @@
import React, {
Suspense,
lazy,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { useReactToPrint } from "react-to-print";
import localImgLoad from "../../lib/localImgLoad";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import FamilyWallet from "./Tabs/FamilyWallet";
import { apiConst } from "../../lib/apiConst";
// Lazy Imports for components
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
const FamilyAccount = lazy(() => import("./Tabs/FamilyAccount"));
const FamilyProfile = lazy(() => import("./Tabs/FamilyProfile"));
const FamilyTasks = lazy(() => import("./Tabs/FamilyTasks"));
const FamilyPending = lazy(() => import("./Tabs/FamilyPending"));
export default function FamilyTableNew({
className,
accountDetails,
listReload,
loader,
}) {
// Initial state for family details
const initialDetailState = {
loading: false,
data: null,
};
// 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);
};
// Ref for the account section
const accountRef = useRef();
// React-to-Print hook for handling printing
const useHandlePrint = useReactToPrint({
content: () => accountRef.current,
});
// 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
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
accountDetails={accountDetails}
/>
),
Waiting: (
<FamilyWaitlist
familyData={details.familyWaitList.data}
accountDetails={accountDetails}
loader={details.familyWaitList.loading}
/>
),
Pending: (
<FamilyPending
familyData={details.familyPending.data}
accountDetails={accountDetails}
loader={details.familyPending.loading}
/>
),
Account: (
<FamilyAccount
familyData={details.familyDetails.data}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
),
Profile: <FamilyProfile familyData={details.familyDetails.data} />,
wallet: <FamilyWallet familyData={details.familyDetails.data} />,
};
// Default tab component
const defaultTabComponent = (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
accountDetails={accountDetails}
/>
);
// 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({
familyDetails: { loading: true },
familyTasks: { loading: true },
familyWaitList: { loading: true },
familyPending: { loading: true },
});
const { family_uid } = accountDetails;
const reqData = { family_uid };
const [familyRes, tasksRes, familyWaitRes, familyPending] =
await Promise.all([
apiCall.ManageFamily(reqData),
apiCall.ManageTasks(reqData),
apiCall.ManageFamilyWaitlist(),
apiCall.ManageFamilyPending(),
]);
const familyData = familyRes.data;
const tasksData = tasksRes.data;
const familyWaitData = familyWaitRes.data;
const familyPendingData = familyPending.data;
// Function to check for errors in data
const checkDataError = (data) => data?.internal_return < 0;
if (
checkDataError(familyData) ||
checkDataError(tasksData) ||
checkDataError(familyWaitData) ||
checkDataError(familyPendingData)
) {
return;
}
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
familyPending: { loading: false, data: familyPendingData },
});
} 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;
};
}, []);
return (
<div
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full ${
className || ""
}`}
>
<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}
familyDetailsData={details.familyDetails.data}
setUpdatePage={setUpdatePage}
/>
)}
</div>
);
}
+51 -25
View File
@@ -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
@@ -136,7 +138,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-acc", active: true},
]
}
/>
</div>
{familyList?.result_list?.length <
process.env.REACT_APP_MAX_FAMILY_MEMBERS &&
!loader && (
@@ -150,31 +163,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-2 items-center">
<Link to="/acc-family/activities" className={`nav-item flex items-center `}>
<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 group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium`}
>
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%)]"
>
<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
@@ -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] 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}
+16 -54
View File
@@ -7,14 +7,14 @@ import { useDispatch, useSelector } from "react-redux";
import { tableReload } from "../../store/TableReloads";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function FamilyDash({ MyActiveJobList, serverImg }) {
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);
@@ -24,25 +24,6 @@ export default function FamilyDash({ MyActiveJobList, serverImg }) {
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
@@ -60,17 +41,17 @@ export default function FamilyDash({ MyActiveJobList, serverImg }) {
return (
<div>
<div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
{/* Header */}
<div className="text-white mb-4 p-2 w-full rounded-xl bg-sky-blue place-content-center">
<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 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="w-full text-sm flex justify-end items-end">
<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>
@@ -112,29 +93,10 @@ export default function FamilyDash({ MyActiveJobList, serverImg }) {
<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-4 gap-2 md:gap-4">
{tab_categories.data.map((item) => {
// onClick={()=>navigate('/resources', {state:{tab:'created'}})}
let resourceState = ''
switch(item?.action){
case 'fam-blog':
resourceState = 'blog'
break
case 'ai-question':
resourceState = 'onsale'
break
case 'myfiles':
resourceState = 'created'
break
case 'ai-lab':
resourceState = 'onsale'
break
default:
resourceState = 'blog'
break
}
// console.log('EX', item.enabled, item?.action, resourceState)
if(item.enabled){
// if(item.enabled){
// }
return (
<Link key={item.uid} to={'/resources'} state={{tab:resourceState}} className={`group rounded-xl bg-white dark:bg-dark-white shadow-md flex justify-center items-center transition-all duration-300 hover:shadow-sm`}>
<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' />
@@ -151,7 +113,7 @@ export default function FamilyDash({ MyActiveJobList, serverImg }) {
</div>
</div>
</Link>
)}
)
})}
</div>
</div>
@@ -167,13 +129,13 @@ export default function FamilyDash({ MyActiveJobList, serverImg }) {
/>
)} */}
{trending && trending.length > 0 && (
{/* {trending && trending.length > 0 && (
<FamilyActiveLSlde
trending={trending}
className="mb-10"
image_server={serverImg}
/>
)}
)} */}
</div>
</div>
);
+2 -24
View File
@@ -58,17 +58,13 @@ export default function Home(props) {
useEffect(() => {
const fetchData = async () => {
await Promise.all([getHomeDate(), getMyOffersList()]);
await Promise.all([getHomeDate(), getMyOffersList(), getMyActiveJobList()]);
};
if(userDetails?.account_type == 'FULL'){
fetchData();
}
}, []);
useEffect(() => {
getMyActiveJobList();
}, []);
return (
<Layout>
<div className="home-page-wrapper">
@@ -78,7 +74,7 @@ export default function Home(props) {
commonHeadData={props.bannerList}
// familyOffers={MyOffersList?.data}
serverImg = {userDetails?.session_image_server}
MyActiveJobList={MyActiveJobList?.data}
// MyActiveJobList={MyActiveJobList?.data}
/>
) : userDetails && userDetails?.account_type == "FULL" ? (
<FullAccountDash
@@ -97,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>
+2 -1
View File
@@ -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"
+1 -1
View File
@@ -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]) => {
+12
View File
@@ -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'>
+14 -7
View File
@@ -286,7 +286,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 +412,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 +421,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 +535,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>
);
}
+14 -2
View File
@@ -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"
+3 -3
View File
@@ -75,7 +75,7 @@ export default function MyTasks({
/>
)}
<div className="w-full mb-5 flex justify-between items-center gap-1">
{userDetails.account_type == 'FULL'?
{/* {userDetails.account_type == 'FULL'?
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
@@ -83,7 +83,7 @@ export default function MyTasks({
My Tasks
</span>
</h1>
:
: */}
<CustomBreadcrumb
title = 'My Tasks'
breadcrumb={
@@ -93,7 +93,7 @@ export default function MyTasks({
]
}
/>
}
{/* } */}
{ActiveJobList?.data?.length > 0 && userDetails.account_type == 'FAMILY' &&
<button
+95
View File
@@ -0,0 +1,95 @@
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 FamilyWallet = () => {
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 [allCountries, setAllCountries] = useState({
// STATE TO HOLD LIST OF COUNTRIES
loading: true,
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 });
}
})
.catch(() => {
setPaymentHistory({ loading: false, data: [] });
});
};
// FUNCTION TO GET COUNTRIES
const getCountry = () => {
apiCall
.getSignupCountryData()
.then((res) => {
if (res?.data?.internal_return < 0) {
setAllCountries((prev) => ({ loading: false, data: [] }));
return;
}
setAllCountries((prev) => ({
loading: false,
data: res?.data?.result_list,
}));
})
.catch((error) => {
setAllCountries((prev) => ({ loading: false, data: [] }));
});
};
useEffect(() => {
getCountry();
getPaymentHistory();
}, [walletTable]);
console.log(
"Testing all country: ",
allCountries,
"Testing wallet: ",
walletDetails
);
return (
<Layout>
<div className='mb-4'>
<CustomBreadcrumb
title={'Wallet'}
breadcrumb = {
[
{ link: "/", title: "Home" },
{ link: '/family-wallet', title: 'Wallet', active: true},
]
}
/>
</div>
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
<FamilyWalletBox
wallet={walletDetails}
payment={paymentHistory}
countries={allCountries.data}
/>
</Suspense>
</Layout>
);
};
export default FamilyWallet;
@@ -0,0 +1,34 @@
import { useSelector } from "react-redux";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import WalletItemCard from "./WalletItemCard";
import WalletItemCardFamily from "./WalletItemCardFamily";
/**
* Renders a list of wallet items or a loading spinner depending on the state of the `wallet` object.
*/
export default function FamilyWalletBox({ wallet, payment, countries }) {
const { loading, data } = wallet;
const { userDetails } = useSelector((state) => state.userDetails);
const accountType = userDetails?.account_type === "FAMILY";
return (
<div className="my-wallet-wrapper w-full mb-10">
<div className="main-wrapper w-full">
<div className="balance-inquery w-auto grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-[repeat(auto-fill,_minmax(354px,_1fr))] min-[1440px]:grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-auto">
{loading ? (
<div className="w-full h-full flex items-center justify-center bg-white">
<LoadingSpinner size="16" color="sky-blue" height='h-[30rem]' />
</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>
</div>
);
}
-16
View File
@@ -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>
);
+184 -172
View File
@@ -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>
</>
);
+1 -3
View File
@@ -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`
@@ -34,9 +34,7 @@ export default function WalletItemCardFamily({ 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 -1
View File
@@ -20,6 +20,9 @@ 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);
@@ -402,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
+11 -30
View File
@@ -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>
</>
);
}
+1 -1
View File
@@ -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>
+2 -1
View File
@@ -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"
+33 -42
View File
@@ -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>
)
}
+108
View File
@@ -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>
);
}
@@ -1,10 +1,10 @@
import React from 'react'
import Layout from '../Partials/Layout'
export default function FamilyPastDue() {
export default function FamGames() {
return (
<Layout>
<div>Family PastDue Page Here</div>
<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>
)
}
+1 -2
View File
@@ -52,9 +52,8 @@
}
.job-action {
background-color: #4687ba;
height: 100px;
border-radius: 15px;
padding: 5px;
padding: 3px;
}
.msg_box {
+2 -15
View File
@@ -288,23 +288,10 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
}
};
getFamilyResourcesList()
}, [isLogin.status, familyBannersListTable]);
}, [isLogin.status]);
// useEffect(() => {
// apiCall
// .getHeroJBanners()
// .then((res) => {
// if (res.data.internal_return < 0) {
// return;
// }
// dispatch(commonHeadBanner(res.data));
// })
// .catch((error) => {
// console.log("ERROR ", error);
// });
// }, []);
//
// RENDER PAGE
return isLogin.loading && !loggedIn ? (
<LoadingSpinner size="32" color="sky-blue" height="h-screen" />
) : !isLogin.status && !loggedIn ? (
+14
View File
@@ -1279,6 +1279,20 @@ class usersService {
};
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);
}
/*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import FamAIQuestion from '../components/familyResources/FamAIQuestion'
export default function FamAIQuestionPage() {
return (
<>
<FamAIQuestion />
</>
)
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import FamBlog from '../components/familyResources/FamBlog'
export default function FamBlogPage() {
return (
<>
<FamBlog />
</>
)
}
+9
View File
@@ -0,0 +1,9 @@
import React from 'react'
import FamGames from '../components/familyResources/FamGames'
export default function FamGamesPage() {
return (
<>
<FamGames />
</>
)
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import FamInterest from '../components/familyResources/FamInterest'
export default function FamInterestPage() {
return (
<>
<FamInterest />
</>
)
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import FamMyFiles from '../components/familyResources/FamMyFiles'
export default function FamMyFilesPage() {
return (
<>
<FamMyFiles />
</>
)
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import FamWorkInProgress from '../components/familyResources/FamWorkInProgress'
export default function FamWorkInProgressPage() {
return (
<>
<FamWorkInProgress />
</>
)
}
+12
View File
@@ -0,0 +1,12 @@
import React from "react";
import FamilyActivities from "../components/FamilyAcc/FamilyActivities";
const FamilyActivitiesPage = () => {
return (
<>
<FamilyActivities />
</>
);
};
export default FamilyActivitiesPage;
-10
View File
@@ -1,10 +0,0 @@
import React from 'react'
import FamilyPastDue from '../components/FamilyAcc/FamilyPastDue'
export default function FamilyPastDuePage() {
return (
<>
<FamilyPastDue />
</>
)
}
+5
View File
@@ -0,0 +1,5 @@
import FamilyWallet from "../components/MyWallet/FamilyWallet";
export default function FamilyWalletPage() {
return <FamilyWallet />;
}
+1 -1
View File
@@ -39,7 +39,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) => {
+2 -3
View File
@@ -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();
+36
View File
@@ -0,0 +1,36 @@
import React, { useContext,useState, useEffect } from "react";
import usersService from "../services/UsersService";
import MyPastDueTasks from "../components/MyActiveJobs/MyPastDueTasks";
import { useSelector } from "react-redux";
export default function MyPastDueTasksPage() {
let {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
const [MyJobList, setMyJobList] = useState({loading:true, data:[]});
const api = new usersService();
const getMyJobList = async () => {
try {
const res = await api.getMyPastDueJobList();
console.log("DATA", res.data);
setMyJobList({loading:false, data:res.data})
} catch (error) {
setMyJobList({loading:false, data:[]})
console.log("Error getting mode");
}
};
useEffect(() => {
getMyJobList();
}, []);
// debugger;
return (
<>
<MyPastDueTasks
MyJobList={MyJobList?.data}
loading={MyJobList?.loading}
commonHeadData={commonHeadBanner?.result_list}
/>
</>
);
}
+3
View File
@@ -23,6 +23,9 @@ module.exports = {
screens:{
xxs: '400px',
xxl:'1900px'
},
backgroundImage: {
'family-header-bg': "linear-gradient(90deg, rgba(45,126,241,1) 0%, rgba(58,143,195,1) 0%, rgba(11,100,119,1) 100%)",
}
},
},