diff --git a/src/assets/images/wrench-home-back-common.jpg b/src/assets/images/wrench-home-back-common.jpg new file mode 100644 index 0000000..d175467 Binary files /dev/null and b/src/assets/images/wrench-home-back-common.jpg differ diff --git a/src/assets/images/wrench-home-back-nigeria.jpg b/src/assets/images/wrench-home-back-nigeria.jpg new file mode 100644 index 0000000..b3ab096 Binary files /dev/null and b/src/assets/images/wrench-home-back-nigeria.jpg differ diff --git a/src/components/AuthPages/AuthLayout2.jsx b/src/components/AuthPages/AuthLayout2.jsx index 022f7d2..1e7fcb7 100644 --- a/src/components/AuthPages/AuthLayout2.jsx +++ b/src/components/AuthPages/AuthLayout2.jsx @@ -1,20 +1,28 @@ -import React, { lazy } from "react"; +import React, { lazy, useContext } from "react"; import { Link } from "react-router-dom"; import { localImgLoad } from "../../lib"; +import DarkModeContext from "../Contexts/DarkModeContext"; + export default function LoginLayout({ slogan, children }) { const bgImg = localImgLoad('images/left-wrenchboard.jpg') + const bgImgNig = localImgLoad('images/wrench-home-back-nigeria.jpg') + const bgImgCom = localImgLoad('images/wrench-home-back-common.jpg') + + const {countryMode} = useContext(DarkModeContext); return ( -
-
-
+
+ {/* -
-
+
*/} +
+
{children && children}
@@ -48,7 +56,7 @@ export default function LoginLayout({ slogan, children }) {

- © {new Date().getFullYear()} - + © {new Date().getFullYear()} - WrenchBoard {" "} diff --git a/src/components/AuthPages/ForgotPassword/index2.jsx b/src/components/AuthPages/ForgotPassword/index2.jsx index ae7e77f..76f0ac6 100644 --- a/src/components/AuthPages/ForgotPassword/index2.jsx +++ b/src/components/AuthPages/ForgotPassword/index2.jsx @@ -99,7 +99,7 @@ export default function ForgotPassword() {

-
+
{msgSuccess == null ? <>
diff --git a/src/components/AuthPages/Login/index2.jsx b/src/components/AuthPages/Login/index2.jsx index 9763c86..0e920f5 100644 --- a/src/components/AuthPages/Login/index2.jsx +++ b/src/components/AuthPages/Login/index2.jsx @@ -264,7 +264,7 @@ export default function Login() {
{/*
*/}
-
+
{/* HIDES THIS IF USER SESSION HAS EXPIRED */} {sessionExpired != "true" && (
diff --git a/src/components/AuthPages/SignUp/index2.jsx b/src/components/AuthPages/SignUp/index2.jsx index 2ee3637..e0f57f1 100644 --- a/src/components/AuthPages/SignUp/index2.jsx +++ b/src/components/AuthPages/SignUp/index2.jsx @@ -158,7 +158,7 @@ export default function SignUp() {
-
+

Create Account diff --git a/src/components/AuthPages/UpdatePassword/index2.jsx b/src/components/AuthPages/UpdatePassword/index2.jsx index 49567dc..bbced1e 100644 --- a/src/components/AuthPages/UpdatePassword/index2.jsx +++ b/src/components/AuthPages/UpdatePassword/index2.jsx @@ -19,7 +19,7 @@ export default function UpdatePassword() { {updated === false ? (
-
+

Update Password diff --git a/src/components/AuthPages/VerifyLink/index2.jsx b/src/components/AuthPages/VerifyLink/index2.jsx index c305b04..bda6a11 100644 --- a/src/components/AuthPages/VerifyLink/index2.jsx +++ b/src/components/AuthPages/VerifyLink/index2.jsx @@ -132,7 +132,7 @@ export default function VerifyLink() {

-
+

{linkSuccess diff --git a/src/components/AuthPages/VerifyPassword/index2.jsx b/src/components/AuthPages/VerifyPassword/index2.jsx index 47b220a..0d3c89b 100644 --- a/src/components/AuthPages/VerifyPassword/index2.jsx +++ b/src/components/AuthPages/VerifyPassword/index2.jsx @@ -152,7 +152,7 @@ const VerifyPassword = () => { {requestStatus.loading ? ( ) : !requestStatus.loading && requestStatus.status ? ( -
+
{linkSuccess == null ? ( <>
diff --git a/src/components/AuthPages/VerifyYou/index2.jsx b/src/components/AuthPages/VerifyYou/index2.jsx index 09d0635..5c28f52 100644 --- a/src/components/AuthPages/VerifyYou/index2.jsx +++ b/src/components/AuthPages/VerifyYou/index2.jsx @@ -18,7 +18,7 @@ export default function VerifyYou() {
-
+

Let's verify your email now diff --git a/src/components/FamilyAcc/FamilySettings/Tabs/InviteRelative.jsx b/src/components/FamilyAcc/FamilySettings/Tabs/InviteRelative.jsx new file mode 100644 index 0000000..e880d90 --- /dev/null +++ b/src/components/FamilyAcc/FamilySettings/Tabs/InviteRelative.jsx @@ -0,0 +1,275 @@ +import React, { useState } from 'react' +import ModalCom from '../../../Helpers/ModalCom'; +import LoadingSpinner from '../../../Spinners/LoadingSpinner'; +import InputCom from '../../../Helpers/Inputs/InputCom/index'; +import { Formik, Form } from 'formik'; +import * as Yup from "yup"; +import usersService from '../../../../services/UsersService'; + +const validationSchema = Yup.object().shape({ + email: Yup.string() + .email("Wrong email format") + .matches( + /^[^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"), + firstname: Yup.string() + .min(3, "Minimum 3 characters") + .max(25, "Maximum 25 characters") + .required("Firstname is required"), + lastname: Yup.string() + .min(3, "Minimum 3 characters") + .max(25, "Maximum 25 characters") + .required("Lastname is required"), + family_type: Yup.string() + .min(3, "Minimum 3 characters") + .max(25, "Maximum 25 characters") + .required("Family Type is required"), + }); + + const initialValues = { + firstname: '', + lastname: '', + family_type: '', + email: '' + }; + + +export default function InviteRelative({action, situation, setReloadRelList, relativeList}) { + + const api = new usersService() + + let [requestStatus, setRequestStatus] = useState({ + loading: false, + status: false, + message: "", + }); // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER + + const handleInvite = (values) => { + setRequestStatus({loading: true, status: false, message: ""}) + api.inviteFamilyRelative(values).then(response => { + let {status, data} = response + if(data?.internal_return < 0){ + setRequestStatus({loading: false, status: false, message: "Unable to complete"}) + return setTimeout(()=>{ + setRequestStatus({ loading: false, status: false, message: ""}) + },3000) + } + setRequestStatus({loading: false, status: true, message: "Relative Added"}) + //RELOAD RELATIVE LSIT TABLE + setReloadRelList(prev => !prev) + setTimeout(()=>{ + action() + },3000) + }).catch(error => { + setRequestStatus({loading: false, status: false, message: "Something went wrong, try again!"}) + setTimeout(()=>{ + setRequestStatus({ loading: false, status: false, message: ""}) + },3000) + }) + } + + return ( + +
+
+

+ Invite Parent/Relative +

+ +
+
+
+ + {(props) => { + return ( +
+
+
+ {/* inputs starts here */} + {/* Email */} +
+ +
+ {/* first name and last name */} +
+
+ +
+
+ +
+
+ + {/* Type */} +
+ {/*
+ +
*/} +
+ + +
+
+
+ {requestStatus.loading ? ( + + ) : ( + + )} +
+
+
+
+
+
+ ); + }} +
+
+ + {/* ERROR DISPLAY AND SUBMIT BUTTON */} + {requestStatus.message != "" && + (!requestStatus.status ? ( +
+ {requestStatus.message} +
+ ) : ( + requestStatus.status && ( +
+ {requestStatus.message} +
+ ) + ))} + {/* End of error or success display */} +
+
+
+ ) +} diff --git a/src/components/FamilyAcc/FamilySettings/Tabs/RelativeTable.jsx b/src/components/FamilyAcc/FamilySettings/Tabs/RelativeTable.jsx new file mode 100644 index 0000000..4706be5 --- /dev/null +++ b/src/components/FamilyAcc/FamilySettings/Tabs/RelativeTable.jsx @@ -0,0 +1,73 @@ +import React, { useState } from 'react' +import { handlePagingFunc } from '../../../Pagination/HandlePagination'; +import PaginatedList from '../../../Pagination/PaginatedList'; + +export default function RelativeTable({relativeList}) { + + // Handle Pagination + const [currentPage, setCurrentPage] = useState(0); + const indexOfFirstItem = Number(currentPage); + const indexOfLastItem =Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE); + + const currentRelativeList = relativeList?.slice(indexOfFirstItem, indexOfLastItem); + + const handlePagination = (e) => { + handlePagingFunc(e, setCurrentPage); + }; + + return ( +
+
+ + + <> + {relativeList && relativeList?.length > 0 ? ( + currentRelativeList.map((value, index) => ( + + + + + + )) + ) : ( + + + + )} + + +
+
+

+ {value.firstname && value.firstname} {value.lastname && value.lastname} +

+ + {value.email && value.email} + +
+
+ {/* Family Type */} + {value.family_type && value.family_type.toUpperCase()} + + {value.status && value.status} +
No Members Found
+ + {/* PAGINATION BUTTON */} + = + relativeList?.length + ? true + : false + } + data={relativeList} + start={indexOfFirstItem} + stop={indexOfLastItem} + /> + {/* END OF PAGINATION BUTTON */} +
+
+ ); + }; diff --git a/src/components/FamilyAcc/FamilySettings/Tabs/Relatives.jsx b/src/components/FamilyAcc/FamilySettings/Tabs/Relatives.jsx index 3eeff60..a662d61 100644 --- a/src/components/FamilyAcc/FamilySettings/Tabs/Relatives.jsx +++ b/src/components/FamilyAcc/FamilySettings/Tabs/Relatives.jsx @@ -1,8 +1,68 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' +import RelativeTable from './RelativeTable' +import InviteRelative from './InviteRelative' +import usersService from '../../../../services/UsersService' +import LoadingSpinner from '../../../Spinners/LoadingSpinner' const Relatives = () => { + + const api = new usersService() + + const [reloadRelList, setReloadRelList] = useState(false) + + const [invitePopout, setInvitePopout] = useState(false) + + const [relativeList, setRelativeList] = useState({loading: true, result_list:[], family_types:[]}) + + const showInviteMemberPopout = () => { + setInvitePopout(true) + } + + const getRelativeList = () => { + setRelativeList(prev => ({...prev, loading: true})) + api.getFamilyRelativeList().then(response => { + let {status, data} = response + if(status != 200 || !data){ + setRelativeList({loading:false, result_list:[], family_types:[]}) + return + } + setRelativeList({loading:false, result_list:data?.result_list, family_types:data?.family_types}) + }).catch(error => { + setRelativeList({loading:false, result_list:[], family_types:[]}) + }) + } + + useEffect(()=>{ + getRelativeList() + },[reloadRelList]) + return ( -
Relatives
+ <> +
+
+ +
+
+
+ {relativeList.loading ? + + : + + } +
+
+ + {/* INVITE RELATIVE POPOUT */} + {invitePopout && + setInvitePopout(false)} + situation={invitePopout} + setReloadRelList={setReloadRelList} + relativeList={relativeList} + /> + } + {/* END OF INVITE RELATIVE POPOUT */} + ) } diff --git a/src/components/FamilyAcc/FamilySettings/index.jsx b/src/components/FamilyAcc/FamilySettings/index.jsx index c779e09..252f377 100644 --- a/src/components/FamilyAcc/FamilySettings/index.jsx +++ b/src/components/FamilyAcc/FamilySettings/index.jsx @@ -62,10 +62,14 @@ const FamilySettings = () => { Family Settings

- Go Back + + + + + Family +
- {/* Something Here */} - {/*
*/} +
diff --git a/src/components/JobGroups/DeleteGroup.jsx b/src/components/JobGroups/DeleteGroup.jsx index 6c646d3..c07064b 100644 --- a/src/components/JobGroups/DeleteGroup.jsx +++ b/src/components/JobGroups/DeleteGroup.jsx @@ -73,7 +73,7 @@ export default function DeleteGroup({action, situation, details}) {

- Are you sure, you want to delete
'{details?.group_name}' + Are you sure, you want to delete
'{details?.group_name}' group?

diff --git a/src/components/JobGroups/DeleteMember.jsx b/src/components/JobGroups/DeleteMember.jsx index e899cff..8d8f2fe 100644 --- a/src/components/JobGroups/DeleteMember.jsx +++ b/src/components/JobGroups/DeleteMember.jsx @@ -23,7 +23,7 @@ export default function DeleteMember({action, situation, details}) {

- Delete Member + Remove Member

)}
diff --git a/src/components/JobGroups/GroupList.jsx b/src/components/JobGroups/GroupList.jsx index 7dcfa73..6ba0d80 100644 --- a/src/components/JobGroups/GroupList.jsx +++ b/src/components/JobGroups/GroupList.jsx @@ -1,72 +1,104 @@ -import React, { useState } from 'react' +import React, { useState } from "react"; -import InputCom from '../../components/Helpers/Inputs/InputCom/index' -import DeleteGroup from './DeleteGroup' -import AddGroup from './AddGroup' +import AddGroup from "./AddGroup"; +import DeleteGroup from "./DeleteGroup"; +import { localImgLoad } from "../../lib"; -export default function GroupList({groupList, selectedGroup, changeSelectedGroup, setUpdateList}) { +export default function GroupList({ + groupList, + selectedGroup, + changeSelectedGroup, + setUpdateList, +}) { + const [deletePopout, setDeletePopout] = useState({ + status: false, + data: {}, + }); - const [deletePopout, setDeletePopout] = useState({ - status: false, - data: {} - }) + const [addGroupPopout, setAddGroupPopout] = useState(false); - const [addGroupPopout, setAddGroupPopout] = useState(false) - - const handleAddGroup = () => { - setAddGroupPopout(true) - } - - const handleDeleteGroup = (item) => { - setDeletePopout({ - status: true, - data: {...item} - }) - } + const handleAddGroup = () => { + setAddGroupPopout(true); + }; + const handleDeleteGroup = (item) => { + setDeletePopout({ + status: true, + data: { ...item }, + }); + }; return ( <> -
- {/*

Jobs Groups

*/} -
- -
- - {groupList && groupList.length < 1 ? -

No Group Found!

- : -
-
- {groupList.map(item=> ( -
-
- -

{item.group_name}

-
- -
- ))} -
-
- } +
+ {/*

Jobs Groups

*/} +
+
- - {deletePopout.status && - setDeletePopout({status:false, data:{}})} - situation={deletePopout.status} - details={deletePopout.data} - /> - } - {addGroupPopout && - setAddGroupPopout(false)} - situation={addGroupPopout} - setUpdateList={setUpdateList} - /> - } + {groupList && groupList.length < 1 ? ( +

+ No Group Found! +

+ ) : ( +
+
+ {groupList.map((item) => ( +
+
+ +

+ {item.group_name} +

+
+ +
+ ))} +
+
+ )} +
+ + {deletePopout.status && ( + setDeletePopout({ status: false, data: {} })} + situation={deletePopout.status} + details={deletePopout.data} + /> + )} + + {addGroupPopout && ( + setAddGroupPopout(false)} + situation={addGroupPopout} + setUpdateList={setUpdateList} + /> + )} - ) + ); } diff --git a/src/components/JobGroups/GroupMemberTable.jsx b/src/components/JobGroups/GroupMemberTable.jsx index a9b43ee..bf04139 100644 --- a/src/components/JobGroups/GroupMemberTable.jsx +++ b/src/components/JobGroups/GroupMemberTable.jsx @@ -1,98 +1,118 @@ -import React, { useState } from 'react' -import { handlePagingFunc } from '../Pagination/HandlePagination'; -import PaginatedList from '../Pagination/PaginatedList'; -import DeleteMember from './DeleteMember'; +import React, { useState } from "react"; +import { handlePagingFunc } from "../Pagination/HandlePagination"; +import PaginatedList from "../Pagination/PaginatedList"; +import DeleteMember from "./DeleteMember"; +import { localImgLoad } from "../../lib"; -export default function GroupMemberTable({selectedList}) { - - // Handle Pagination - const [currentPage, setCurrentPage] = useState(0); - const indexOfFirstItem = Number(currentPage); - const indexOfLastItem =Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE); +export default function GroupMemberTable({ selectedList }) { + // Handle Pagination + const [currentPage, setCurrentPage] = useState(0); + const indexOfFirstItem = Number(currentPage); + const indexOfLastItem = + Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE); - const currentSelectedList = selectedList?.slice(indexOfFirstItem, indexOfLastItem); - - const handlePagination = (e) => { - handlePagingFunc(e, setCurrentPage); - }; + const currentSelectedList = selectedList?.slice( + indexOfFirstItem, + indexOfLastItem + ); - const [deletePopout, setDeletePopout] = useState({ - status: false, - data: {} - }) + const handlePagination = (e) => { + handlePagingFunc(e, setCurrentPage); + }; - const handleDeleteMember = (item) => { - setDeletePopout({ - status: true, - data: {...item} - }) - } - - return ( -
-
- - - <> - {selectedList && selectedList?.length > 0 ? ( - currentSelectedList.map((value, index) => ( - - {/* + const [deletePopout, setDeletePopout] = useState({ + status: false, + data: {}, + }); + + const handleDeleteMember = (item) => { + setDeletePopout({ + status: true, + data: { ...item }, + }); + }; + + return ( +
+
+
{value?.firstname}
+ + <> + {selectedList && selectedList?.length > 0 ? ( + currentSelectedList.map((value, index) => ( + + {/* */} - - - - )) - ) : ( - - - - )} - - -
{value?.firstname} {value?.lastname} {value?.email} -
-

- {value.firstname && value.firstname} {value.lastname && value.lastname} -

- - {value.email && value.email} - -
-
- -
No Members Found
- - {/* PAGINATION BUTTON */} - = - selectedList?.length - ? true - : false - } - data={selectedList} - start={indexOfFirstItem} - stop={indexOfLastItem} - /> - {/* END OF PAGINATION BUTTON */} -
- - {/* DELETE MEMBER POPOUT */} - {deletePopout.status && - setDeletePopout({status:false, data:{}})} - situation={deletePopout.status} - details={deletePopout.data} - /> - } - {/* END OF DELETE MEMBER POPOUT */} -
- ); - }; + +
+

+ {value.firstname && value.firstname}{" "} + {value.lastname && value.lastname} +

+ + {value.email && value.email} + +
+ + + + + + )) + ) : ( + + No Members Found. Please add + + )} + + + + + {/* PAGINATION BUTTON */} + = + selectedList?.length + ? true + : false + } + data={selectedList} + start={indexOfFirstItem} + stop={indexOfLastItem} + /> + {/* END OF PAGINATION BUTTON */} +
+ + {/* DELETE MEMBER POPOUT */} + {deletePopout.status && ( + setDeletePopout({ status: false, data: {} })} + situation={deletePopout.status} + details={deletePopout.data} + /> + )} + {/* END OF DELETE MEMBER POPOUT */} +
+ ); +} diff --git a/src/components/JobGroups/JobGroups.jsx b/src/components/JobGroups/JobGroups.jsx index 4d80a2a..ae081f8 100644 --- a/src/components/JobGroups/JobGroups.jsx +++ b/src/components/JobGroups/JobGroups.jsx @@ -1,79 +1,119 @@ -import React, { useEffect, useState } from 'react' -import Layout from '../Partials/Layout' +import React, { useEffect, useState } from "react"; +import Layout from "../Partials/Layout"; -import GroupList from './GroupList' -import MemberList from './MemberList' -import LoadingSpinner from '../Spinners/LoadingSpinner' +import GroupList from "./GroupList"; +import MemberList from "./MemberList"; +import LoadingSpinner from "../Spinners/LoadingSpinner"; -import usersService from '../../services/UsersService' +import usersService from "../../services/UsersService"; export default function JobGroups() { + const userApi = new usersService(); - const userApi = new usersService(); + const [updateList, setUpdateList] = useState(false); - const [updateList, setUpdateList] = useState(false) + const [groupList, setGroupList] = useState({ + loading: true, + groups: [], + members: [], + }); - - const [groupList, setGroupList] = useState({ - loading:true, - groups: [], - members: [] - }) + const [selectedGroup, setSelectedGroup] = useState({ + id: "", + name: "", + data: [], + }); - const [selectedGroup, setSelectedGroup] = useState({id:'', name:'', data: []}) + const changeSelectedGroup = (e) => { + let groupID = e.target.value; + const activeMembers = groupList?.members?.filter( + (item) => item.group_id == groupID + ); + const activeGroup = groupList?.groups?.filter( + (item) => item.group_id == groupID + ); + setSelectedGroup({ + id: groupID, + name: activeGroup[0]?.group_name, + data: activeMembers, + }); + }; - const changeSelectedGroup = (e) => { - let groupID = e.target.value - const activeMembers = groupList?.members?.filter(item => item.group_id == groupID) - const activeGroup = groupList?.groups?.filter(item => item.group_id == groupID) - setSelectedGroup({id: groupID, name:activeGroup[0]?.group_name, data:activeMembers}) - } - - useEffect(()=>{ - setGroupList({loading: true, groups: [], members: []}) - userApi.jobGroupList({}).then(res => { - const {status, data} = res - if(status != 200 || data?.internal_return < 0){ - setGroupList({loading: false, groups: [], members: []}) - return - } - if(data.result_list.length < 0){ - setGroupList({loading: false, groups: [], members: []}) - return - } - setGroupList({loading: false, groups: data.result_list, members: data.result_list_member}) - if(selectedGroup.id == ''){ - let activeGroupId = data.result_list[0].group_id - let activeGroup = data.result_list[0].group_name - let activeMembers = data.result_list_member?.filter(item => item.group_id == activeGroupId) - setSelectedGroup({id: activeGroupId, name:activeGroup, data:activeMembers}) - }else{ - let activeMembers = data.result_list_member?.filter(item => item.group_id == selectedGroup?.id) - setSelectedGroup({id: selectedGroup?.id, name:selectedGroup?.name, data:activeMembers}) - } - }).catch(error => { - setGroupList({loading: false, groups: [], members: []}) - console.log(error) - }) - },[updateList]) + useEffect(() => { + setGroupList({ loading: true, groups: [], members: [] }); + userApi + .jobGroupList({}) + .then((res) => { + const { status, data } = res; + if (status != 200 || data?.internal_return < 0) { + setGroupList({ loading: false, groups: [], members: [] }); + return; + } + if (data.result_list.length < 0) { + setGroupList({ loading: false, groups: [], members: [] }); + return; + } + setGroupList({ + loading: false, + groups: data.result_list, + members: data.result_list_member, + }); + if (selectedGroup.id == "") { + let activeGroupId = data.result_list[0].group_id; + let activeGroup = data.result_list[0].group_name; + let activeMembers = data.result_list_member?.filter( + (item) => item.group_id == activeGroupId + ); + setSelectedGroup({ + id: activeGroupId, + name: activeGroup, + data: activeMembers, + }); + } else { + let activeMembers = data.result_list_member?.filter( + (item) => item.group_id == selectedGroup?.id + ); + setSelectedGroup({ + id: selectedGroup?.id, + name: selectedGroup?.name, + data: activeMembers, + }); + } + }) + .catch((error) => { + setGroupList({ loading: false, groups: [], members: [] }); + console.log(error); + }); + }, [updateList]); return ( -
-

Jobs Groups

-
-
- {groupList.loading ? -
- -
- : - <> - - - - } -
+
+

+ Job Groups +

+
+
+ {groupList.loading ? ( +
+ +
+ ) : ( + <> + + + + )} +
- ) + ); } diff --git a/src/components/JobGroups/MemberList.jsx b/src/components/JobGroups/MemberList.jsx index faec8c7..095378c 100644 --- a/src/components/JobGroups/MemberList.jsx +++ b/src/components/JobGroups/MemberList.jsx @@ -6,8 +6,8 @@ import GroupMemberTable from "./GroupMemberTable"; import EmailValidator from "../../lib/EmailValidator"; -import usersService from "../../services/UsersService"; import { apiConst } from "../../lib/apiConst"; +import usersService from "../../services/UsersService"; export default function MemberList({ groupList, @@ -277,7 +277,7 @@ export default function MemberList({ )}
-
+
{selectedGroup?.data?.length < 1 ? (

No Member Found, Please Add diff --git a/src/components/MyActiveJobs/MyActiveJobTable.jsx b/src/components/MyActiveJobs/MyActiveJobTable.jsx index 0807476..55b4833 100644 --- a/src/components/MyActiveJobs/MyActiveJobTable.jsx +++ b/src/components/MyActiveJobs/MyActiveJobTable.jsx @@ -1,12 +1,10 @@ import React, { useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; -import localImgLoad from "../../lib/localImgLoad"; import { PriceFormatter } from "../Helpers/PriceFormatter"; import { handlePagingFunc } from "../Pagination/HandlePagination"; import PaginatedList from "../Pagination/PaginatedList"; export default function MyActiveJobTable({ MyJobList, className }) { - const navigate = useNavigate(); let { pathname } = useLocation(); @@ -45,7 +43,11 @@ export default function MyActiveJobTable({ MyJobList, className }) { value?.currency_code, value?.currency ); - let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}` + let image = `${ + MyJobList.session_image_server + }${localStorage.getItem("session_token")}/job/${ + value.job_uid + }`; return ( {value.owner_status == "OWNER" - ? "Manage" + ? "Review" : "Send Updates"}

diff --git a/src/components/MyJobs/MyJobTable.jsx b/src/components/MyJobs/MyJobTable.jsx index 6f46aac..1e94fd8 100644 --- a/src/components/MyJobs/MyJobTable.jsx +++ b/src/components/MyJobs/MyJobTable.jsx @@ -1,21 +1,23 @@ import { useCallback, useEffect, useMemo, useState } from "react"; -import dataImage2 from "../../assets/images/data-table-user-2.png"; -import SelectBox from "../Helpers/SelectBox"; -import DeleteJobPopout from "../jobPopout/DeleteJobPopout"; -import JobListPopout from "../jobPopout/JobListPopout"; -import LoadingSpinner from "../Spinners/LoadingSpinner"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import usersService from "../../services/UsersService"; +import { PriceFormatter } from "../Helpers/PriceFormatter"; +import SelectBox from "../Helpers/SelectBox"; import { handlePagingFunc } from "../Pagination/HandlePagination"; import PaginatedList from "../Pagination/PaginatedList"; +import LoadingSpinner from "../Spinners/LoadingSpinner"; +import DeleteJobPopout from "../jobPopout/DeleteJobPopout"; import EditJobPopOut from "../jobPopout/EditJobPopout"; -import { PriceFormatter } from "../Helpers/PriceFormatter"; -import EditIcon from "../../assets/images/icon-edit.svg"; import DeleteIcon from "../../assets/images/icon-delete.svg"; -import localImgLoad from "../../lib/localImgLoad"; +import EditIcon from "../../assets/images/icon-edit.svg"; +import { tableReload } from "../AddJob/settings"; +import CreditPopup from "../MyWallet/Popup/CreditPopup"; +import JobListPopout from "../jobPopout/JobListPopout"; export default function MyJobTable({ MyJobList, reloadJobList, className }) { + const dispatch = useDispatch(); + // Getting the categories const currentJobCart = MyJobList?.data?.categories; // DropDown Box @@ -25,24 +27,46 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) { Object.keys(filterCategories)[0] ); - let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW + const [jobPopout, setJobPopout] = useState({ show: false, data: {} }); - let [deleteJobPopout, setDeleteJobPopout] = useState({ + const [deleteJobPopout, setDeleteJobPopout] = useState({ show: false, data: {}, - }); // STATE TO HOLD THE VALUE OF THE ITEM DETAILS TO DELETE AND DETERMINE WHEN TO SHOW + }); const [editJob, setEditJob] = useState({ show: false, data: {} }); const [myCountry, setCountries] = useState(""); + const { userDetails: { country }, } = useSelector((state) => state?.userDetails); const userApi = useMemo(() => new usersService(), []); + const [creditPopup, setCreditPopup] = useState({ show: false, data: {} }); + const [walletItem, setWalletItem] = useState(null); + + /** + * Opens the credit popup. + * @param {Object} value - The value object. + */ + const openPopUp = (value) => { + setCreditPopup({ + show: true, + data: { ...value }, + }); + }; + + /** + * Closes the credit popup and dispatches a table reload action. + */ + const closePopUp = () => { + setCreditPopup({ show: false, data: {} }); + dispatch(tableReload({ type: "WALLETTABLE" })); + }; + // Get Country Api const getCountryList = useCallback(async () => { - try { const res = await userApi.getSignupCountryData(); if (res.status === 200 && res.data.internal_return >= 0) { @@ -59,7 +83,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) { throw new Error(error); } }, [userApi, country]); - console.log('MY COUNTRY', myCountry) + useEffect(() => { getCountryList(); }, [getCountryList]); @@ -101,6 +125,121 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) { } }; + const { MyJobListHeader, MyJobListTable } = myJobTableFeatures( + filterCategories, + selectedCategory, + handleSetCategory, + setDeleteJobPopout, + setEditJob, + setJobPopout, + MyJobList, + filteredCurrentJobList, + handlePagination, + currentPage, + currentJobList, + indexOfFirstItem, + indexOfLastItem + ); + + return ( +
+ + {MyJobList?.loading ? ( + + ) : ( + + )} + + {/* Job List Popout */} + {jobPopout.show && ( + { + setJobPopout({ show: false, data: {} }); + }} + setWalletItem={setWalletItem} + openWallet={openPopUp} + situation={jobPopout.show} + /> + )} + {/* End of Job List Popout */} + + {/* Delete Job Popout */} + {deleteJobPopout.show && ( + { + setDeleteJobPopout({ show: false, data: {} }); + }} + reloadJobList={reloadJobList} + situation={deleteJobPopout.show} + /> + )} + {/* END of Delete Job Popout */} + + {editJob.show && ( + { + setEditJob({ + show: false, + data: {}, + }); + }} + situation={editJob.show} + country={myCountry} + categories={currentJobCart} + /> + )} + + {creditPopup.show && ( + + )} +
+ ); +} + +function myJobTableFeatures( + filterCategories, + selectedCategory, + handleSetCategory, + setDeleteJobPopout, + setEditJob, + setJobPopout, + MyJobList, + filteredCurrentJobList, + handlePagination, + currentPage, + currentJobList, + indexOfFirstItem, + indexOfLastItem +) { + // List of job table features + const MyJobListHeader = () => ( +
+
+

+ {filterCategories[selectedCategory]} Jobs +

+
+ +
+ ); + const JobListItem = ({ value, index, image_server }) => { let thePrice = PriceFormatter( value?.price * 0.01, @@ -190,7 +329,10 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) { diff --git a/src/components/MyWallet/Popup/CreditPopup.jsx b/src/components/MyWallet/Popup/CreditPopup.jsx index 717af4e..47b6549 100644 --- a/src/components/MyWallet/Popup/CreditPopup.jsx +++ b/src/components/MyWallet/Popup/CreditPopup.jsx @@ -79,7 +79,7 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => { ) : confirmCredit?.show?.acceptConfirm?.state ? ( diff --git a/src/components/Partials/Default.jsx b/src/components/Partials/Default.jsx index fb8c123..b3e9d38 100644 --- a/src/components/Partials/Default.jsx +++ b/src/components/Partials/Default.jsx @@ -5,6 +5,13 @@ function Default({ children }) { // dark mode setup const [theme, setTheme] = useState(null); + // country mode setup + const [countryMode, setCountryMode] = useState(localStorage.getItem('cnt') ? localStorage.getItem('cnt')?.toUpperCase() : '') + + + const queryParams = new URLSearchParams(location?.search); + const country = queryParams.get("cnt")?.toUpperCase(); + useEffect(() => { if (window.matchMedia("(prefers-color-scheme: dark)").matches) { setTheme("dark"); @@ -24,9 +31,17 @@ function Default({ children }) { const handleThemeSwitch = () => { setTheme(theme === "dark" ? "light" : "dark"); }; + + useEffect(()=>{ + if(country){ + setCountryMode(country) + localStorage.setItem('cnt', country) + } + },[countryMode]) + return ( <> - + {children && children} diff --git a/src/components/Partials/Layout.jsx b/src/components/Partials/Layout.jsx index dab7137..81f0b0b 100644 --- a/src/components/Partials/Layout.jsx +++ b/src/components/Partials/Layout.jsx @@ -24,7 +24,7 @@ export default function Layout({ children }) { localStorage.removeItem("member_id"); localStorage.removeItem("uid"); sessionStorage.removeItem("family_uid"); - // localStorage.clear(); + localStorage.clear(); // toast.success("Come Back Soon", { // icon: `🙂`, // }); diff --git a/src/components/jobPopout/JobListPopout.jsx b/src/components/jobPopout/JobListPopout.jsx index 8df3e9b..f805719 100644 --- a/src/components/jobPopout/JobListPopout.jsx +++ b/src/components/jobPopout/JobListPopout.jsx @@ -1,13 +1,13 @@ import { Field, Form, Formik } from "formik"; import React, { useCallback, useEffect, useMemo, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; import * as Yup from "yup"; import usersService from "../../services/UsersService"; +import { tableReload } from "../../store/TableReloads"; import InputCom from "../Helpers/Inputs/InputCom/index"; import ModalCom from "../Helpers/ModalCom"; import LoadingSpinner from "../Spinners/LoadingSpinner"; import Detail from "./popoutcomponent/Detail"; -import { tableReload } from "../../store/TableReloads"; -import { useDispatch } from "react-redux"; const validationSchema = Yup.object().shape({ family: Yup.string().required("This is required "), @@ -22,14 +22,22 @@ const validationSchema = Yup.object().shape({ group: Yup.string(), }); -function JobListPopout({ details, onClose, situation }) { +function JobListPopout({ + details, + onClose, + situation, + openWallet, + setWalletItem, +}) { + const [selectedTab, setSelectedTab] = useState("public"); + const tabs = ["public", "individual", "group"]; - const [selectedTab, setSelectedTab] = useState('public') - const tabs = ['public', 'individual', 'group'] + const dispatch = useDispatch(); -const dispatch = useDispatch() - -const [requestStatus, setRequestStatus] = useState({message:'', status:false}) + const [requestStatus, setRequestStatus] = useState({ + message: "", + status: false, + }); const [familyList, setFamilyList] = useState([]); let [loader, setLoader] = useState({ @@ -43,6 +51,30 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false}) }); const apiCall = useMemo(() => new usersService(), []); + const { walletDetails } = useSelector((state) => state.walletDetails); + + const getWalletDetail = (currency) => { + // A FUNCTION TO GET USER BALANCE BASED ON TASK CURRENCY + const walletChecker = walletDetails?.data.find( + (item) => item.description === currency + ); + return walletChecker + ? { + description: walletChecker.description, + country: walletChecker.country, + code: walletChecker.code, + amount: walletChecker.amount, + } + : 0; + }; + + const taskWalletSelector = getWalletDetail(details?.currency); + + const openCreditPopup = () => { + onClose(); + setWalletItem(taskWalletSelector); + openWallet(); + }; // member listing const memberList = useCallback(async () => { @@ -117,6 +149,7 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false}) job_uid, job_description: textArea, }; + let reqData; // for family input @@ -147,7 +180,7 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false}) // for group input reqData = { ...jobReq, - email: '', + email: "", group_id: values?.group, assign_mode: 110044, duration: details?.timeline_days, @@ -161,52 +194,203 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false}) try { const res = await apiCall.assignJobTask(reqData); let { status, data } = await res; - if(status != 200 || data.internal_return < 0){ - setRequestStatus({message:'Unable to complete', status:false}) - return setTimeout(()=>{ + if (status != 200 || data.internal_return < 0) { + setRequestStatus({ message: "Unable to complete", status: false }); + return setTimeout(() => { setLoader({ jobFields: false }); - setRequestStatus({message:'', status:false}) - },3000) + setRequestStatus({ message: "", status: false }); + }, 3000); } dispatch(tableReload({ type: "JOBTABLE" })); - setRequestStatus({message:'Successful', status:true}) - setTimeout(()=>{ + setRequestStatus({ message: "Successful", status: true }); + setTimeout(() => { setLoader({ jobFields: false }); onClose(); throw new Response(data); - },3000) + }, 3000); } catch (error) { - setRequestStatus({message:'Unable to complete', status:false}) - setTimeout(()=>{ - setRequestStatus({message:'', status:false}) + setRequestStatus({ message: "Unable to complete", status: false }); + setTimeout(() => { + setRequestStatus({ message: "", status: false }); setLoader({ jobFields: false }); throw new Error(error); - },3000) + }, 3000); } }; - const [groupList, setGroupList] = useState({loading: true, groups: [], members: []}) + const [groupList, setGroupList] = useState({ + loading: true, + groups: [], + members: [], + }); // FUNCTION TO POPULATE USER GROUP LIST - useEffect(()=>{ + useEffect(() => { // setGroupList({loading: true, groups: [], members: []}) - apiCall.jobGroupList({}).then(res => { - const {status, data} = res - if(status != 200 || data?.internal_return < 0){ - setGroupList({loading: false, groups: [], members: []}) - return + apiCall + .jobGroupList({}) + .then((res) => { + const { status, data } = res; + if (status != 200 || data?.internal_return < 0) { + setGroupList({ loading: false, groups: [], members: [] }); + return; } - if(data.result_list.length < 0){ - setGroupList({loading: false, groups: [], members: []}) - return + if (data.result_list.length < 0) { + setGroupList({ loading: false, groups: [], members: [] }); + return; } - setGroupList({loading: false, groups: data.result_list, members: data.result_list_member}) - }).catch(error => { - setGroupList({loading: false, groups: [], members: []}) - }) -},[]) + setGroupList({ + loading: false, + groups: data.result_list, + members: data.result_list_member, + }); + }) + .catch((error) => { + setGroupList({ loading: false, groups: [], members: [] }); + }); + }, []); + + const DetailsSection = ({ label, value }) => ( +
+ +
+ ); + + const DetailsComponent = () => { + const detailsArray = [ + { label: "Description", value: details.description }, + { label: "Price", value: details.thePrice }, + { label: "Timeline", value: `${details.timeline_days} day(s)` }, + { label: "Created", value: new Date(details?.created).toDateString() }, + ]; + + return ( +
+ {/*

{details.title}

*/} + + {/* INPUT SECTION */} + {detailsArray.map((detail, index) => ( + + ))} + +
+ +