Compare commits

...

20 Commits

Author SHA1 Message Date
victorAnumudu ef545c9714 validated email 2023-07-10 13:48:23 +01:00
ameye 029a7327a8 Merge branch 'google-login-fix' of WrenchBoard/Users-Wrench into master 2023-07-10 11:22:19 +00:00
victorAnumudu 5a5d933b24 google login fix 2023-07-10 12:18:43 +01:00
ameye 9f19c930b7 Merge branch 'suggested-task-page' of WrenchBoard/Users-Wrench into master 2023-07-10 08:46:47 +00:00
Ebube 84d7fabae7 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into suggested-task-page 2023-07-10 09:14:54 +01:00
Ebube b245f87556 Optimizations and underlying fixes done yesterday 2023-07-10 09:14:30 +01:00
CHIEFSOFT\ameye bed5303fa4 wallet 2023-07-09 20:42:00 -04:00
ameye a5af8ed722 Merge branch 'home-hero-min-height' of WrenchBoard/Users-Wrench into master 2023-07-09 23:26:57 +00:00
victorAnumudu ec97d118b2 AuthLayout added to redirect page 2023-07-09 23:55:35 +01:00
ameye 85213c31a1 Merge branch 'home-hero-min-height' of WrenchBoard/Users-Wrench into master 2023-07-09 22:55:28 +00:00
victorAnumudu f9b6c68f99 added min height to home page hero section 2023-07-09 23:34:39 +01:00
ameye 2a4b77c9a0 Merge branch 'home-page-hero-adjustment' of WrenchBoard/Users-Wrench into master 2023-07-09 22:28:43 +00:00
victorAnumudu 97aa5dba21 Merge 'master' into home-page-hero-adjustment 2023-07-09 23:19:30 +01:00
victorAnumudu 58a10ca6be home page hero section adjusted and google login success redirect implemented 2023-07-09 23:14:07 +01:00
CHIEFSOFT\ameye f3edf1d90b home banner 2023-07-09 17:57:05 -04:00
CHIEFSOFT\ameye 1f7b310b6f google login 2023-07-09 15:41:49 -04:00
ameye aecb06ca96 Merge branch 'verify-link' of WrenchBoard/Users-Wrench into master 2023-07-09 10:54:08 +00:00
CHIEFSOFT\ameye d89194f18e sty 2023-07-09 00:39:38 -04:00
CHIEFSOFT\ameye 03866d666b banner bg 2023-07-09 00:17:20 -04:00
CHIEFSOFT\ameye 4224be46bc banner issues 2023-07-08 23:19:23 -04:00
22 changed files with 349 additions and 304 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

@@ -1,53 +1,63 @@
import React, { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import usersService from '../../../services/UsersService';
import {updateUserDetails} from "../../../store/UserDetails";
import { useDispatch } from "react-redux";
import AuthLayout from "../AuthLayout";
function Redirect() {
const location = useLocation();
const navigate = useNavigate();
const userApi = new usersService();
const dispatch = useDispatch()
const queryParams = new URLSearchParams(location?.search);
const codeResponse = queryParams.get("code");
useEffect(()=>{
if(!codeResponse){
navigate('/login', {replace: true})
return
}
console.log(codeResponse);
/*
POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
if(!codeResponse){
navigate('/login', {state: {error: true}})
return
}
console.log(codeResponse);
/*
POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code
*/
var reqData = {
auth_type: "GOOGLE",
code: codeResponse,
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
};
userApi
.authStart(reqData)
.then((res) => {
console.log(res.data);
if (res.status != 200 || res.internal_return < 0) {
return;
}
// "{"message":"Endpoint not found.","URI":"http:\/\/localhost:9083\/index.php\/en\/wrench\/api\/v1\/authstart"}[]"
alert(JSON.stringify(res.data));
})
.catch((error) => {
console.log(error);
});
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code
*/
var reqData = {
auth_type: "GOOGLE",
code: codeResponse,
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
};
userApi
.authStart(reqData)
.then((res) => {
if (res.status == 200 && res.data.internal_return >= 0 && res.data.member_id && res.data.uid && res.data.session) {
localStorage.setItem("member_id", `${res.data.member_id}`);
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
dispatch(updateUserDetails({...res.data, loggedIn:true}));
navigate('/', {replace: true})
return
}
navigate('/login', {state: {error: true}})
})
.catch((error) => {
navigate('/login', {state: {error: true}})
console.log(error);
});
},[])
return (
<div>Redirecting ... </div>
<AuthLayout>
<div className='min-h-[70vh]'>Redirecting ... </div>
</AuthLayout>
)
}
+11 -2
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useLayoutEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Link, useNavigate, useLocation } from "react-router-dom";
import linkedInLogo from "../../../assets/images/Linkedin.png";
import appleLogo from "../../../assets/images/apple-black.svg";
import facebookLogo from "../../../assets/images/facebook-4.svg";
@@ -16,6 +16,7 @@ import { updateUserDetails } from "../../../store/UserDetails";
export default function Login() {
const dispatch = useDispatch();
const {state} = useLocation()
let [loginType, setLoginType] = useState('');
@@ -105,7 +106,7 @@ export default function Login() {
userApi
.logInUser(postData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
if (res.status != 200 || res.data.internal_return < 0 || !res.data.member_id || !res.data.uid || !res.data.session) {
// setMsgError("Wrong, email/password");
setLoginError(true);
setLoginLoading(false);
@@ -175,6 +176,14 @@ export default function Login() {
}
let loginValue = readCookie('loginType')
setLoginType(loginValue)
if(state?.error){ //check if the login path has an error state indicating any social handle login with error
setMsgError("Unexpected Error, Please try again soon.");
setTimeout(()=>{
setMsgError("");
navigate('/login', {replace: true})
},4000)
}
},[])
@@ -21,7 +21,8 @@ export default function FamilyActiveJobsCard({ datas, hidden = false }) {
toast.warn("Remove to Favorite List");
}
};
//debugger;
const bannerName = datas.banner == null ?'default.jpg':datas.banner;
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
@@ -32,7 +33,7 @@ export default function FamilyActiveJobsCard({ datas, hidden = false }) {
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${localImgLoad(
`images/taskbanners/${datas.banner}`
`images/taskbanners/${bannerName}`
)}) center / contain no-repeat`,
}}
>
@@ -17,21 +17,21 @@ export default function HomeBannerOffersCard(props) {
return (
<Link
to={link_result}
className="item w-full block group banner-630-340 bg-cover bg-center"
className="item p-2 w-full flex items-center min-h-[340px] bg-alice-blue bg-cover bg-center"
style={{
backgroundImage: `url('${imageUrl}')`,
}}
>
<div className="flex flex-col justify-between h-full">
<div className="w-[80%] h-full mx-auto flex flex-col justify-between">
<div className="content flex justify-between items-center">
<div className="siderCardHeader">
<h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
<div className="mb-2">
<h1 className="text-2xl lg:text-4xl font-bold text-dark-gray dark:text-white tracking-wide">
<span className="heroSilderTitle">{props.itemData.title}</span>
</h1>
</div>
</div>
<div className="flex flex-col justify-around items-center flex-1">
<div className="siderCardDescription">
<div className="siderCardDescription mb-2">
{props.itemData.description}
</div>
<button className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
+61 -33
View File
@@ -1,26 +1,28 @@
import React, {
Suspense,
lazy,
useCallback,
useEffect,
useMemo,
useRef,
useState,
useTransition,
} from "react";
import { useReactToPrint } from "react-to-print";
import profile from "../../assets/images/profile-info-profile.png";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import {
FamilyWaitlist,
FamilyAccount,
FamilyProfile,
FamilyTasks,
ProfileInfo,
FamilyPending,
} from "./Tabs";
import localImgLoad from "../../lib/localImgLoad";
// 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 ProfileInfo = lazy(() => import("./Tabs/ProfileInfo"));
const FamilyPending = lazy(() => import("./Tabs/FamilyPending"));
export default function FamilyManageTabs({
className,
accountDetails,
@@ -35,14 +37,15 @@ export default function FamilyManageTabs({
});
const [errMsg, setErrMsg] = useState("");
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
const [profileImg, setProfileImg] = useState(profile);
const profileImgInput = useRef(null);
const [isPending, startTransition] = useTransition();
const apiCall = useMemo(() => new usersService(), []);
const familyPopUpHandler = () => {
setFamilyTaskPopout((prev) => !prev);
};
const [profileImg, setProfileImg] = useState(profile);
const profileImgInput = useRef(null);
const browseProfileImg = () => {
profileImgInput.current.click();
};
@@ -57,16 +60,15 @@ export default function FamilyManageTabs({
}
};
const apiCall = useMemo(() => new usersService(), []);
const manageFamily = useCallback(async () => {
try {
setDetails({
setDetails((prevDetails) => ({
...prevDetails,
familyDetails: { loading: true },
familyTasks: { loading: true },
familyWaitList: { loading: true },
familyPending: { loading: true },
});
}));
const { family_uid } = accountDetails;
const reqData = { family_uid };
@@ -89,22 +91,26 @@ export default function FamilyManageTabs({
tasksData?.internal_return < 0 ||
familyWaitData?.internal_return < 0 ||
familyPendingData?.internal_return < 0
)
) {
return;
}
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
familyPending: { loading: false, data: familyPendingData },
startTransition(() => {
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
familyPending: { loading: false, data: familyPendingData },
});
});
} catch (error) {
setDetails({
setDetails((prevDetails) => ({
...prevDetails,
familyDetails: { loading: false },
familyTasks: { loading: false },
familyWaitList: { loading: false },
familyPending: { loading: false },
});
}));
setErrMsg("An error occurred");
throw new Error(error);
}
@@ -119,13 +125,15 @@ export default function FamilyManageTabs({
const tabs = [
{ id: 1, name: "Tasks" },
{ id: 2, name: "Waiting" },
{ id: 3, name: "Pending" }
{ id: 3, name: "Pending" },
];
const [tab, setTab] = useState(tabs[0].name);
const tabHandler = (value) => {
setTab(value);
startTransition(() => {
setTab(value);
});
};
const tabComponents = {
@@ -174,7 +182,13 @@ export default function FamilyManageTabs({
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
useEffect(() => {
manageFamily();
let __manageFamily = true;
if (__manageFamily) {
manageFamily();
}
return () => {
__manageFamily = false;
};
}, [tab, manageFamily]);
return (
@@ -202,15 +216,25 @@ export default function FamilyManageTabs({
/>
<div className="mt-4 flex justify-center items-center gap-2">
<button
onClick={() => tabHandler('Account')}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center">
<img src={localImgLoad('images/icons/account.svg')} className="w-[70px] h-[70px]" alt='Settings-Icon' />
onClick={() => tabHandler("Account")}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center"
>
<img
src={localImgLoad("images/icons/account.svg")}
className="w-[70px] h-[70px]"
alt="Settings-Icon"
/>
<p className="mt-2 text-lg text-sky-blue">Account</p>
</button>
<button
onClick={() => tabHandler('Profile')}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center">
<img src={localImgLoad('images/icons/profile.svg')} className="w-[70px] h-[70px]" alt='Settings-Icon' />
onClick={() => tabHandler("Profile")}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center"
>
<img
src={localImgLoad("images/icons/profile.svg")}
className="w-[70px] h-[70px]"
alt="Settings-Icon"
/>
<p className="mt-2 text-lg text-sky-blue">Profile</p>
</button>
</div>
@@ -243,7 +267,11 @@ export default function FamilyManageTabs({
</div>
<div className="flex-[0.9] lg:min-h-[450px] h-full">
<div className="h-full p-4 border border-[#dbd9d9] relative overflow-y-auto">
{selectedTabComponent}
<Suspense
fallback={<LoadingSpinner size="16" color="sky-blue" />}
>
{selectedTabComponent}
</Suspense>
</div>
</div>
</div>
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useTransition } from "react";
import ModalCom from "../../Helpers/ModalCom";
import Detail from "../../jobPopout/popoutcomponent/Detail";
import usersService from "../../../services/UsersService";
@@ -6,7 +6,7 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { NewTasks } from "./forms";
function AssignTaskPopout({ action, details, situation, familyDetails }) {
const AssignTaskPopout = React.memo(({ action, details, situation, familyDetails }) => {
const apiCall = new usersService();
let [requestStatus, setRequestStatus] = useState({
@@ -15,7 +15,7 @@ function AssignTaskPopout({ action, details, situation, familyDetails }) {
message: "",
}); // HOLDS RESPONSE FOR SENDING API REQUEST
let [familyTask, setFamilyTask] = useState({ loading: true, data: [] });
let [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
let [taskType, setTaskType] = useState(details ? "new" : "select"); // SWITCHES BTW SELECT TASK AND NEW TASK
@@ -156,27 +156,35 @@ function AssignTaskPopout({ action, details, situation, familyDetails }) {
};
useEffect(() => {
let checkFamilyTask = true;
const reqData = {
limit: 30,
offset: 0,
job_type: "FAMILY",
action: 13005,
};
apiCall
.getMyJobList(reqData)
.then((res) => {
setFamilyTask({ loading: false, data: res?.data?.result_list });
if (res?.data?.result_list?.length) {
setActiveTask((prev) => ({
...prev,
data: res?.data?.result_list[0],
}));
if (checkFamilyTask) {
setFamilyTask({ loading: false, data: res?.data?.result_list });
if (res?.data?.result_list?.length) {
setActiveTask((prev) => ({
...prev,
data: res?.data?.result_list[0],
}));
}
}
})
.catch((err) => {
setFamilyTask({ loading: false, data: [] });
console.log("Error", err);
});
return () => {
checkFamilyTask = false;
};
}, []);
return (
@@ -428,6 +436,6 @@ function AssignTaskPopout({ action, details, situation, familyDetails }) {
</ModalCom>
</>
);
}
})
export default AssignTaskPopout;
export default AssignTaskPopout;
@@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react";
import usersService from "../../../../services/UsersService";
import InputCom from "../../../Helpers/Inputs/InputCom";
// const DEFAULT_IMAGE =
export default function NewTasks({ formState, setFormState }) {
let [currency, setCurrency] = useState({
loading: true,
-3
View File
@@ -8,10 +8,7 @@ import PaginatedList from "../Pagination/PaginatedList";
import familyImage from '../../assets/images/no-family-side.png'
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
const navigate = useNavigate();
// let location = useLocation();
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
+49 -49
View File
@@ -1,56 +1,56 @@
import { forwardRef } from 'react'
import QRCode from 'react-qr-code';
import { forwardRef } from "react";
import QRCode from "react-qr-code";
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
return (
<div
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
ref={myRef}
>
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
<div className="flex items-center justify-around h-[380px]">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
</span>
</h2>
</div>
<span className="text-5xl text-gray-400 opacity-20 font-bold">
or
</span>
<div className="max-w-[200px]">
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
viewBox={`0 0 256 256`}
/>
</div>
return (
<div
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
ref={myRef}
>
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
<div className="flex items-center justify-around h-[380px]">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
</span>
</h2>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
<button
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
onClick={handlePrint}
>
Print
</button>
<span className="text-5xl text-gray-400 opacity-20 font-bold">
or
</span>
<div className="max-w-[200px]">
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
viewBox={`0 0 256 256`}
/>
</div>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
<button
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
onClick={handlePrint}
>
Print
</button>
</div>
</div>
);
});
</div>
);
});
export default FamilyAccount
export default FamilyAccount;
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useMemo, useState } from "react";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import dataImage2 from "../../../assets/images/data-table-user-2.png";
@@ -13,8 +13,12 @@ export default function FamilyPending({
}) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let filteredFamilyData = familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
let filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[accountDetails?.family_uid, familyData?.result_list]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -51,7 +55,7 @@ export default function FamilyPending({
value?.currency_code,
value?.currency
);
let image = value.banner ? value.banner : 'default.jpg'
let image = value.banner ? value.banner : "default.jpg";
return (
<tr
key={index}
@@ -61,7 +65,9 @@ export default function FamilyPending({
<div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={localImgLoad(`images/taskbanners/${image}`)}
src={localImgLoad(
`images/taskbanners/${image}`
)}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -1,31 +1,50 @@
import { useState } from "react";
import { useState, useMemo, memo } from "react";
import { handlePagingFunc, PaginatedList } from "../../Pagination";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import SuggestTask from "../../FamilyPopup/SuggestTask";
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
const FamilyWaitlist = memo(({ familyData, className, accountDetails, loader }) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
const [continueTaskPopup, setContinueTaskPopup] = useState({
show: false,
data: {},
});
let filteredFamilyData = familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
);
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = currentPage;
const indexOfLastItem = currentPage + itemsPerPage;
const currentTask = filteredFamilyData?.slice(
indexOfFirstItem,
indexOfLastItem
const currentTask = useMemo(
() => filteredFamilyData?.slice(indexOfFirstItem, indexOfLastItem),
[filteredFamilyData, indexOfFirstItem, indexOfLastItem]
);
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
const openPopUp = (value) => {
setPopUp({ show: true, data: { ...value } });
};
const closePopUp = () => {
setPopUp({ show: false, data: {} });
};
const openContinueTaskPopup = (value) => {
setContinueTaskPopup({ show: true, data: { ...value } });
};
const closeContinueTaskPopup = () => {
setContinueTaskPopup({ show: false, data: {} });
};
return (
<div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${
@@ -83,12 +102,7 @@ const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
</td>
<td className="text-right py-4 px-2">
<button
onClick={() =>
setPopUp({
show: true,
data: { ...value, selectedImage },
})
}
onClick={() => openPopUp(value)}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
@@ -114,28 +128,21 @@ const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
{popUp.show && (
<SuggestTask
details={popUp.data}
onClose={() => {
setPopUp({ show: false, data: {} });
}}
continuePopupData={(value) =>
setContinueTaskPopup({ show: true, data: { ...value } })
}
onClose={closePopUp}
continuePopupData={openContinueTaskPopup}
situation={popUp.show}
/>
)}
{/* Continue Task */}
{continueTaskPopup.show && (
<AssignTaskPopout
details={continueTaskPopup.data}
action={() => {
setContinueTaskPopup({ show: false, data: {} });
}}
action={closeContinueTaskPopup}
situation={continueTaskPopup.show}
/>
)}
</div>
);
};
});
export default FamilyWaitlist;
+46 -39
View File
@@ -1,9 +1,16 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import React, {
Suspense,
useCallback,
useEffect,
useMemo,
useState,
} from "react";
import InputCom from "../Helpers/Inputs/InputCom";
import Layout from "../Partials/Layout";
import FamilyTable from "./FamilyTable";
import SiteService from "../../services/SiteService";
import ModalCom from "../Helpers/ModalCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function FamilyAcc() {
const [selectTab, setValue] = useState("today");
@@ -20,60 +27,50 @@ export default function FamilyAcc() {
const apiCall = useMemo(() => new SiteService(), []);
// This is to make sure it's called once and used everywhere
let memberId = localStorage.getItem("member_id");
let uid = localStorage.getItem("uid");
let sessionId = localStorage.getItem("session_token");
const popUpHandler = () => {
setPopUp((prev) => !prev);
};
// tab handler
const filterHandler = (value) => {
setValue(value);
};
// For the age drop down
let startAge = 5;
let endAge = 16;
// creates an array of age values ranging from 16 to 70
const ageRange = Array.from(
{ length: endAge - startAge + 1 },
(_, index) => startAge + index
);
// age handler
const ageRange = useMemo(() => {
const startAge = 5;
const endAge = 16;
return Array.from(
{ length: endAge - startAge + 1 },
(_, index) => startAge + index
);
}, []);
const handleAgeSelect = (event) => {
setSelectedAge(parseInt(event.target.value));
};
// Input handler
const handleInputChange = (event) => {
const { name, value } = event?.target;
setFormData({ ...formData, [name]: value });
setFormData((prevFormData) => ({ ...prevFormData, [name]: value }));
};
// Add member
const addMember = async () => {
const { first_name, last_name } = formData;
setLoader(true);
try {
if (first_name !== "" && last_name !== "") {
let reqData = {
member_id: memberId,
uid: uid,
session_id: sessionId,
const reqData = {
firstname: first_name,
lastname: last_name,
age: selectedAge,
};
let res = await apiCall.addFamily(reqData);
const res = await apiCall.addFamily(reqData);
const { data } = res;
if (data?.internal_return > 0 && data?.status == "OK") {
if (data?.internal_return > 0 && data?.status === "OK") {
setLoader(false);
setListReload((prev) => !prev);
popUpHandler()
popUpHandler();
} else {
setLoader(false);
setMsgErr("Sorry, something went wrong");
@@ -94,38 +91,42 @@ export default function FamilyAcc() {
first_name: "",
last_name: "",
});
setSelectedAge("")
setSelectedAge("");
}
};
// member listing
const memberList = useCallback(async () => {
setLoader(true);
try {
let reqData = {
member_id: memberId,
uid: uid,
session_id: sessionId,
const reqData = {
limit: 20,
offset: 0,
action: 22010,
};
let res = await apiCall.familyListings(reqData);
const res = await apiCall.familyListings(reqData);
const { data } = res;
if (data?.internal_return >= 0 && data?.status == "OK") {
let { result_list } = data;
if (data?.internal_return >= 0 && data?.status === "OK") {
const { result_list } = data;
setFamilyList(result_list);
setLoader(false);
} else return;
} else {
return;
}
} catch (error) {
setLoader(false);
throw new Error(error);
}
}, [apiCall, memberId, sessionId, uid]);
}, [apiCall]);
useEffect(() => {
memberList();
let checkMemberList = true;
if (checkMemberList) {
memberList();
}
return () => {
checkMemberList = false;
};
}, [listReload, memberList]);
return (
@@ -158,7 +159,13 @@ export default function FamilyAcc() {
></div>
</div>
</div>
<FamilyTable familyList={familyList} loader={loader} popUpHandler={popUpHandler} />
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
<FamilyTable
familyList={familyList}
loader={loader}
popUpHandler={popUpHandler}
/>
</Suspense>
</div>
</div>
{popUp && (
+4 -2
View File
@@ -31,6 +31,7 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
const handleSuggestedTask = async (values) => {
if (!values.title && !values.description) return;
try {
setSubmitTask({ loading: true });
const reqData = { ...values };
@@ -195,7 +196,8 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
role="group"
key={idx}
htmlFor={`parent-suggested-${idx}`}
className={`transition duration-150 ease-in-out parent-suggest`}
className={`transition duration-150 ease-in-out parent-suggest group cursor-pointer`}
onClick={() => setSuggestedNextStep(title)}
>
<input
type="radio"
@@ -203,7 +205,7 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
value={title}
checked={suggestedNextStep === title}
onChange={switchNextStep}
className={`transition duration-150 ease-in-out parent-suggest`}
className={`transition duration-150 ease-in-out parent-suggest pointer-events-none`}
/>
<span
onClick={() => setSuggestedNextStep(title)}
+5 -5
View File
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import heroBg from "../../assets/images/hero-bg.svg";
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";
@@ -24,7 +24,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
return (
<div
className={`w-full lg:h-[444px] h-full lg:flex lg:p-8 p-4 justify-between items-center lg:space-x-28 rounded-2xl overflow-hidden ${
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden ${
className || ""
}`}
style={{
@@ -33,7 +33,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
backgroundSize: "cover",
}}
>
<div className="flex-1 h-[330px] lg:h-full flex flex-col justify-between mb-5 lg:mb-0">
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
{/* heading */}
<div>
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
@@ -57,7 +57,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
</div>
{/* countdown */}
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border border-white-opacity">
<div className="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">
@@ -84,7 +84,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
)}
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link to="/mytask" className="text-white text-base sm:block hidden">
<Link to="/mytask" className="text-white text-base">
<span className=" border-b dark:border-[#5356fb29] border-white">
{" "}
View All Task(s)
+1 -1
View File
@@ -6,7 +6,7 @@ export default function HomeSliders(props) {
// debugger;
return (
<>
<div className="hero-slider relative 2xl:w-[600px] xl:w-[400px] lg:w-[420px] w-full mb-2 lg:mb-0 ">
<div className="hero-slider relative h-full w-full mb-2 lg:mb-0">
<div className="w-full">
<SliderCom settings={props.settings}>
{props.bannerList?.length <= 0 && (
+13 -73
View File
@@ -1,5 +1,5 @@
import React, { useState } from "react";
import background from "../../assets/images/shape/balance-bg.svg";
import background from "../../assets/images/bg-sky-blue.jpg" //shape/balance-bg.svg";
import {PriceFormatter} from "../Helpers/PriceFormatter";
import {Link} from "react-router-dom";
@@ -39,7 +39,7 @@ export default function WalletItemCard({walletItem}) {
Current Balance
</p>
<p className="text-[44px] font-bold text-white tracking-wide leading-10 mb-2">
{PriceFormatter(walletItem.amount * 0.01, walletItem.code)}
{walletItem.amount * 0.01} {walletItem.code}
</p>
<p className="text-lg text-white tracking-wide">
HOLDINGS : {PriceFormatter(walletItem.escrow * 0.01, walletItem.code)}
@@ -47,9 +47,14 @@ export default function WalletItemCard({walletItem}) {
</p>
</div>
<div className="counters flex space-x-16">
<Link to='transfer-fund' className='px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[48px] rounded-full relative bg-purple lg:text-xl text-lg font-bold text-white'>Transfer</Link>:''
<Link to='add-fund' state={{currency:walletItem.description}} className='px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[48px] rounded-full relative bg-green lg:text-xl text-lg font-bold text-white'>
<div>
{
walletItem.action_type != 'AC_AD_FD_ONLY' ?
<Link to='transfer-fund' className='px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[40px] rounded-full relative bg-purple lg:text-xl text-lg font-bold text-white'>Transfer</Link>:''
}
</div>
<div>
<Link to='add-fund' state={{currency:walletItem.description}} className='px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[40px] rounded-full relative bg-white lg:text-xl text-lg font-bold'>
<span className="">
<svg xmlns="http://www.w3.org/2000/svg" width="38"
height="38" viewBox="0 0 42 42" fill="none"><path
@@ -57,75 +62,10 @@ export default function WalletItemCard({walletItem}) {
fill="white"></path>
</svg>
</span>
<span className='text-white'>Add Credit</span>
</Link>
<span className='text-black'>Add Credit</span>
</Link>
</div>
{/*<div className="circle-count">*/}
{/* <div>*/}
{/* <div className="percent">*/}
{/* <svg>*/}
{/* <circle cx="37" cy="37" r="30"></circle>*/}
{/* <circle*/}
{/* cx="37"*/}
{/* cy="37"*/}
{/* r="30"*/}
{/* style={{ "--percent": `${eth}` }}*/}
{/* ></circle>*/}
{/* </svg>*/}
{/* <div className="number">*/}
{/* <h3>*/}
{/* {eth}*/}
{/* <span>%</span>*/}
{/* </h3>*/}
{/* </div>*/}
{/* </div>*/}
{/* <p className="text-18 text-white text-center">2.32 ETH</p>*/}
{/* </div>*/}
{/*</div>*/}
{/*<div className="circle-count">*/}
{/* <div>*/}
{/* <div className="percent">*/}
{/* <svg>*/}
{/* <circle cx="37" cy="37" r="30"></circle>*/}
{/* <circle*/}
{/* cx="37"*/}
{/* cy="37"*/}
{/* r="30"*/}
{/* style={{ "--percent": `${btc}` }}*/}
{/* ></circle>*/}
{/* </svg>*/}
{/* <div className="number">*/}
{/* <h3>*/}
{/* {btc}*/}
{/* <span>%</span>*/}
{/* </h3>*/}
{/* </div>*/}
{/* </div>*/}
{/* <p className="font-18 text-white text-center">1.76 BTC</p>*/}
{/* </div>*/}
{/*</div>*/}
{/*<div className="circle-count">*/}
{/* <div>*/}
{/* <div className="percent">*/}
{/* <svg>*/}
{/* <circle cx="37" cy="37" r="30"></circle>*/}
{/* <circle*/}
{/* cx="37"*/}
{/* cy="37"*/}
{/* r="30"*/}
{/* style={{ "--percent": `${ltc}` }}*/}
{/* ></circle>*/}
{/* </svg>*/}
{/* <div className="number">*/}
{/* <h3>*/}
{/* {ltc}*/}
{/* <span>%</span>*/}
{/* </h3>*/}
{/* </div>*/}
{/* </div>*/}
{/* <p className="text-18 text-white text-center">2.32 LTC</p>*/}
{/* </div>*/}
{/*</div>*/}
</div>
</div>
);
@@ -11,6 +11,11 @@ import ReferralTable from "../MyWallet/WalletComponent/ReferralTable";
const validationSchema = Yup.object().shape({
ref_email: Yup.string()
.email("Wrong email format")
.matches(
// /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/,
/^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
"Invalid email format"
)
.min(3, "Minimum 3 characters")
.max(50, "Maximum 50 characters")
.required("Email is required"),
@@ -14,6 +14,11 @@ import * as Yup from "yup";
const validationSchema = Yup.object().shape({
email: Yup.string()
.email("Wrong email format")
.matches(
// /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/,
/^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
"Invalid email format"
)
.min(3, "Minimum 3 characters")
.max(50, "Maximum 50 characters")
.required("Email is required"),
@@ -96,7 +101,7 @@ export default function PersonalInfoTab({
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
toast.success("Update Successful");
setTimeout(() => {
navigate("/", { replace: true });
// navigate("/", { replace: true });
window.location.reload(true);
}, 1000);
})
+4 -8
View File
@@ -27,10 +27,12 @@
.heroSilderTitle{
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
font-family: sans; color: white;
font-size: 42px;
font-family: Circular, Helvetica Neue, Helvetica, Roboto, Arial, sans-serif;
}
.back-dark1{
background-color: #193F5F;
min-width: 280px !important;
}
.job-action{
background-color: aliceblue;
height: 100px;
@@ -49,13 +51,7 @@
color: white;
font-weight: bold;
}
.siderCardHeader{
margin: 40px 40px 10px 40px;
font-size: 24px;
font-weight: bolder;
}
.siderCardDescription{
margin: 10px 45px 10px 45px;
background-color: aliceblue;
padding: 5px;
border-radius: 5px;
+25
View File
@@ -10,6 +10,10 @@ class usersService {
return this.postAuxEnd("/createuser", reqData);
}
CompleteOauthLogin(reqData) {
localStorage.setItem("session_token", ``);
return this.postAuxEnd("/authlogin", reqData);
}
CompleteSignUp(reqData) {
localStorage.setItem("session_token", ``);
return this.postAuxEnd("/completesignuplink", reqData);
@@ -849,6 +853,27 @@ class usersService {
return this.postAuxEnd("/offerinterestlistmsg", postData);
}
// TO ADD FAMILY
addFamily(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/familyadd", postData);
}
familyListings(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/familylist", postData);
}
// FUNCTION TO ASSIGN TASK TO FAMILY MEMBER
assignFamilyTask(reqData) {
var postData = {
+5 -5
View File
@@ -1,9 +1,9 @@
import FamilyAcc from "../components/FamilyAcc";
export default function FamilyAccPage() {
return (
<>
<FamilyAcc />
</>
);
return (
<>
<FamilyAcc />
</>
);
}