From 5b9c564f9636c581e6b68c6d9b47fd3c435e7f4a Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Tue, 16 Jul 2024 12:11:52 +0100 Subject: [PATCH] add family tab populated with family list --- src/Routers.jsx | 13 +- .../FamilyAcc/FamilyListSettings.jsx | 346 ++++++++++++++++++ .../FamilyPopout/AssignTaskPopout.jsx | 12 +- src/components/FamilyAcc/FamilyRoutes.jsx | 45 +++ .../FamilySettings/Tabs/AddFamily.jsx | 11 +- src/components/FamilyAcc/FamilyTable.jsx | 2 +- src/components/FamilyAcc/FamilyTableNew.jsx | 5 +- .../FamilyAcc/FamilyTableSettings.jsx | 244 ++++++++++++ src/components/FamilyAcc/index.jsx | 67 ++-- src/views/FamilyRoutesPage.jsx | 21 ++ 10 files changed, 719 insertions(+), 47 deletions(-) create mode 100644 src/components/FamilyAcc/FamilyListSettings.jsx create mode 100644 src/components/FamilyAcc/FamilyRoutes.jsx create mode 100644 src/components/FamilyAcc/FamilyTableSettings.jsx create mode 100644 src/views/FamilyRoutesPage.jsx diff --git a/src/Routers.jsx b/src/Routers.jsx index e8466e5..033f698 100644 --- a/src/Routers.jsx +++ b/src/Routers.jsx @@ -67,6 +67,7 @@ import MyPastDueTasksPage from "./views/MyPastDueTasksPage"; import FamilyWalletPage from "./views/FamilyWalletPage"; import FamilyActivitiesPage from "./views/FamilyActivitiesPage"; import FamGamesPage from "./views/FamGamesPage"; +import FamilyRoutesPage from "./views/FamilyRoutesPage"; export default function Routers() { return ( @@ -147,11 +148,7 @@ export default function Routers() { } /> } /> } /> - } - /> + } /> } /> } /> @@ -170,8 +167,12 @@ export default function Routers() { path="/my-review-jobs" element={} /> - } /> + + {/* } /> } /> + } /> */} + } /> + } /> } /> } /> diff --git a/src/components/FamilyAcc/FamilyListSettings.jsx b/src/components/FamilyAcc/FamilyListSettings.jsx new file mode 100644 index 0000000..04f1597 --- /dev/null +++ b/src/components/FamilyAcc/FamilyListSettings.jsx @@ -0,0 +1,346 @@ +import React, { + useCallback, + useEffect, + useMemo, + useState, + } from "react"; + import { Link, useOutletContext } 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 FamilyTableSettings from "./FamilyTableSettings"; + import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb"; + + export default function FamilyListSettings() { + + const {loader, setLoader, familyList, setListReload} = useOutletContext() // CONTEXT VALUES FROM OUTLET TO CHILD + + // State to store the selected year and month + const [selectedYear, setSelectedYear] = useState(""); + const [selectedMonth, setSelectedMonth] = useState(""); + // const [familyList, setFamilyList] = useState({}); + // const [loader, setLoader] = useState(false); + const [popUp, setPopUp] = useState(false); + // const [listReload, setListReload] = useState(false); + const [msgErr, setMsgErr] = useState(""); + const [formData, setFormData] = useState({ + first_name: "", + last_name: "", + }); + + const apiCall = useMemo(() => new usersService(), []); + + const popUpHandler = () => { + setPopUp((prev) => !prev); + }; + + // Handle year selection + const handleYearChange = (e) => { + setSelectedYear(e.target.value); + }; + + // Handle month selection + const handleMonthChange = (e) => { + setSelectedMonth(e.target.value); + }; + + const handleInputChange = (event) => { + const { name, value } = event?.target; + setFormData((prevFormData) => ({ ...prevFormData, [name]: value })); + }; + + // use the useEffect hook to clear the selected month if the year changes (to ensure consistency) + useEffect(() => { + if (selectedYear === "" && selectedMonth !== "") { + setSelectedMonth(""); + } + }, [selectedYear]); + + const addMember = async () => { + const { first_name, last_name } = formData; + setLoader(true); + try { + if (first_name !== "" && last_name !== "") { + const reqData = { + firstname: first_name, + lastname: last_name, + year: +selectedYear, + month: +selectedMonth, + }; + + const res = await apiCall.addFamily(reqData); + const { data } = res; + + if (data?.internal_return > 0 && data?.status === "OK") { + setLoader(false); + setListReload((prev) => !prev); + popUpHandler(); + } else { + setLoader(false); + setMsgErr("Sorry, something went wrong"); + } + } else { + setLoader(false); + setMsgErr("Please fill in the fields"); + } + } catch (error) { + setLoader(false); + setMsgErr("An error occurred"); + throw new Error(error); + } finally { + setTimeout(() => { + setMsgErr(null); + }, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT)); + setFormData({ + first_name: "", + last_name: "", + }); + setSelectedMonth(""); + setSelectedYear(""); + } + }; + + // const memberList = useCallback(async () => { + // setLoader(true); + // try { + // const res = await apiCall.familyListings(); + // const { data } = res; + // if (data?.internal_return >= 0 && data?.status === "OK") { + // const { result_list, session_image_server } = data; + // setFamilyList({ result_list, session_image_server }); + // sessionStorage.setItem("family_list", JSON.stringify(result_list)) + // setLoader(false); + // } else { + // return; + // } + // } catch (error) { + // setLoader(false); + // throw new Error(error); + // } + // }, [apiCall]); + + // useEffect(() => { + // let checkMemberList = true; + // if (checkMemberList) { + // memberList(); + // } + // return () => { + // checkMemberList = false; + // }; + // }, [listReload, memberList]); + + return ( + <> + {/**/} +
+
+ +
+
+ {popUp && ( + + + + )} + + ); + } + + const FamilyForm = ({ + value: { first_name, last_name }, + ageValue, + inputHandler, + selectedMonth, + selectedYear, + monthHandler, + yearHandler, + msgErr, + loader, + onClick, + popUpHandler, + }) => { + return ( +
+
+

+ Add Members +

+ +
+
+ + +
+ {/* Age dropdown */} +
+ +
+ +
+ {msgErr && ( +
+ {msgErr} +
+ )} +
+
+ +
+
+ +
+ ); + }; + + const CloseIcon = () => ( + + + + + ); + + function YearMonthDropdowns({ + selectedMonth, + selectedYear, + handleMonthChange, + handleYearChange, + }) { + // Get the current year + const currentYear = new Date().getFullYear(); + + // Generate an array of years from the current year to (currentYear - 19) + const years = Array.from({ length: 17 }, (_, index) => currentYear - index); + + // Array of month names + const months = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ]; + + return ( +
+ + + +
+ ); + } + \ No newline at end of file diff --git a/src/components/FamilyAcc/FamilyPopout/AssignTaskPopout.jsx b/src/components/FamilyAcc/FamilyPopout/AssignTaskPopout.jsx index fa338ed..3765a9d 100644 --- a/src/components/FamilyAcc/FamilyPopout/AssignTaskPopout.jsx +++ b/src/components/FamilyAcc/FamilyPopout/AssignTaskPopout.jsx @@ -1,6 +1,6 @@ import React, { Suspense, useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { useLocation } from "react-router-dom"; +import { useLocation, useOutletContext } from "react-router-dom"; import usersService from "../../../services/UsersService"; import { tableReload } from "../../../store/TableReloads"; import ModalCom from "../../Helpers/ModalCom"; @@ -22,8 +22,10 @@ const AssignTaskPopout = ({ jobList, activeTask, setActiveTask, - setUpdatePage, + setUpdatePage, + familyList }) => { + const newJobList = {...jobList, data:jobList?.data?.filter(item => item?.job_mode == 'FAMILY')} const {parentAssignJobToKid} = SocketValues() @@ -46,9 +48,9 @@ const AssignTaskPopout = ({ const dispatch = useDispatch(); - const getFamilySession = JSON.parse(sessionStorage.getItem("family_list")); + // const getFamilySession = JSON.parse(sessionStorage.getItem("family_list")); - const familyList = getFamilySession?.map((member) => ( + const famList = familyList?.map((member) => ( @@ -334,7 +336,7 @@ const AssignTaskPopout = ({ - {familyList} + {famList} diff --git a/src/components/FamilyAcc/FamilyRoutes.jsx b/src/components/FamilyAcc/FamilyRoutes.jsx new file mode 100644 index 0000000..70fc28f --- /dev/null +++ b/src/components/FamilyAcc/FamilyRoutes.jsx @@ -0,0 +1,45 @@ +import React, {useState, useEffect} from "react"; +import { Outlet } from "react-router-dom"; +import Layout from "../Partials/Layout"; +import usersService from "../../services/UsersService"; + + +export default function FamilyRoutes() { + + const apiCall = new usersService(); + + const [loader, setLoader] = useState(false); + + const [familyList, setFamilyList] = useState({}); + + const [listReload, setListReload] = useState(false); + + const memberList = async () => { + setLoader(true); + try { + const res = await apiCall.familyListings(); + const { data } = res; + if (data?.internal_return >= 0 && data?.status === "OK") { + const { result_list, session_image_server } = data; + setFamilyList({ result_list, session_image_server }); + sessionStorage.setItem("family_list", JSON.stringify(result_list)) + setLoader(false); + } else { + return; + } + } catch (error) { + setLoader(false); + throw new Error(error); + } + } + + useEffect(() => { + memberList(); + }, [listReload]); + + return ( + <> + + + ); +} diff --git a/src/components/FamilyAcc/FamilySettings/Tabs/AddFamily.jsx b/src/components/FamilyAcc/FamilySettings/Tabs/AddFamily.jsx index b0d4b0e..b3dad0f 100644 --- a/src/components/FamilyAcc/FamilySettings/Tabs/AddFamily.jsx +++ b/src/components/FamilyAcc/FamilySettings/Tabs/AddFamily.jsx @@ -1,8 +1,15 @@ -import React from 'react' +import React, {Suspense, lazy} from 'react' +// import FamilyList from '../../FamilyList' +import LoadingSpinner from '../../../../components/Spinners/LoadingSpinner' const AddFamily = () => { + const FamilyListSettings = lazy(() => import('../../FamilyListSettings')); return ( -
Add Family
+ <> + }> + + + ) } diff --git a/src/components/FamilyAcc/FamilyTable.jsx b/src/components/FamilyAcc/FamilyTable.jsx index 8888c3e..63611a0 100644 --- a/src/components/FamilyAcc/FamilyTable.jsx +++ b/src/components/FamilyAcc/FamilyTable.jsx @@ -173,7 +173,7 @@ export default function FamilyTable({ return (
diff --git a/src/components/FamilyAcc/FamilyTableNew.jsx b/src/components/FamilyAcc/FamilyTableNew.jsx index 5b3fa08..4ced8c7 100644 --- a/src/components/FamilyAcc/FamilyTableNew.jsx +++ b/src/components/FamilyAcc/FamilyTableNew.jsx @@ -1,5 +1,5 @@ import React, { Suspense, lazy, useEffect, useMemo, useState } from "react"; -import { useLocation } from "react-router-dom"; +import { useLocation, useOutletContext } from "react-router-dom"; import { apiConst } from "../../lib/apiConst"; import usersService from "../../services/UsersService"; import LoadingSpinner from "../Spinners/LoadingSpinner"; @@ -13,6 +13,8 @@ const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending")); export default function FamilyTableNew() { + const {familyList} = useOutletContext() // CONTEXT VALUES FROM OUTLET TO CHILD + const { jobListTable, pendingListTable, parentFamilyTaskList } = useSelector((state) => state.tableReload); // TABLE RELOAD TRIGGERS @@ -243,6 +245,7 @@ export default function FamilyTableNew() { activeTask={activeTask} familyDetailsData={''} setUpdatePage={setUpdatePage} + familyList={familyList?.result_list} /> )} diff --git a/src/components/FamilyAcc/FamilyTableSettings.jsx b/src/components/FamilyAcc/FamilyTableSettings.jsx new file mode 100644 index 0000000..a7b96fc --- /dev/null +++ b/src/components/FamilyAcc/FamilyTableSettings.jsx @@ -0,0 +1,244 @@ +import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { handlePagingFunc } from "../Pagination/HandlePagination"; +import PaginatedList from "../Pagination/PaginatedList"; +import LoadingSpinner from "../Spinners/LoadingSpinner"; + +import familyImage from "../../assets/images/no-family-side.png"; +import { formatDateString } from "../../lib"; +import localImgLoad from "../../lib/localImgLoad"; + +/** + * Renders a list of family members that can be managed. + * It has its current maximum members at 8 and it comes with pagination and loading spinner functionality. + + * @returns {JSX.Element} - The rendered component. + */ +export default function FamilyTableSettings({ + className, + familyList, + loader, + popUpHandler, + imageServer, +}) { + const navigate = useNavigate(); + const [currentPage, setCurrentPage] = useState(0); + const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE); + const indexOfFirstItem = Number(currentPage); + const indexOfLastItem = + Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE); + const currentFamilyList = familyList?.slice( + indexOfFirstItem, + indexOfLastItem + ); + + const handleManageClick = (familyMember) => { + navigate("/manage-family", { state: familyMember }); + }; + + const handlePagination = (e) => { + handlePagingFunc(e, setCurrentPage); + }; + + /** + * Renders a table row for a family member. + * @returns {JSX.Element} - The table row component. + */ + const FamilyRow = ({ + firstname, + lastname, + age, + added, + last_login, + task_count, + family_uid, + banner, + enable_traking, + profile_picture, + 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 trackingStatus = + enable_traking === "0" + ? "Stopped" + : enable_traking === "100" + ? "Active" + : ""; + + return ( + + +
+
+ {`Avatar +
+
+

+ {`${firstname} ${lastname}`}{" "} + {`[${username}]`} +

+ + Added: {addedDate} + + + Last Login:{" "} + {loginDate} + +
+
+ + + {/* +
+ + {trackingStatus} + +
+ + + +
+ + {task_count} + +
+ */} + + + + + + ); + }; + + return ( +
+
+ {loader ? ( +
+ +
+ ) : ( + <> + {familyList?.length > 0 ? ( + + + + + {/* + */} + + + + + {currentFamilyList?.map((familyMember, index) => { + return ( + + ); + })} + +
NameTrackingNo of Tasks
+ ) : ( +
+
+

+ Add your family, assign tasks, and get the whole team + engaged. +

+ +
+
+ Add Family +
+
+ )} + + )} +
+ {/* PAGINATION BUTTON */} + = familyList?.length} + data={familyList} + start={indexOfFirstItem} + stop={indexOfLastItem} + /> + {/* END OF PAGINATION BUTTON */} +
+ ); +} diff --git a/src/components/FamilyAcc/index.jsx b/src/components/FamilyAcc/index.jsx index 9c3276e..a9e83ba 100644 --- a/src/components/FamilyAcc/index.jsx +++ b/src/components/FamilyAcc/index.jsx @@ -5,7 +5,7 @@ import React, { useMemo, useState, } from "react"; -import { Link } from "react-router-dom"; +import { Link, useOutletContext } from "react-router-dom"; import usersService from "../../services/UsersService"; import Icons from "../Helpers/Icons"; import InputCom from "../Helpers/Inputs/InputCom"; @@ -16,13 +16,16 @@ import FamilyTable from "./FamilyTable"; import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb"; export default function FamilyAcc() { + + const {loader, setLoader, familyList, setListReload} = useOutletContext() // CONTEXT VALUES FROM OUTLET TO CHILD + // State to store the selected year and month const [selectedYear, setSelectedYear] = useState(""); const [selectedMonth, setSelectedMonth] = useState(""); - const [familyList, setFamilyList] = useState({}); - const [loader, setLoader] = useState(false); + // const [familyList, setFamilyList] = useState({}); + // const [loader, setLoader] = useState(false); const [popUp, setPopUp] = useState(false); - const [listReload, setListReload] = useState(false); + // const [listReload, setListReload] = useState(false); const [msgErr, setMsgErr] = useState(""); const [formData, setFormData] = useState({ first_name: "", @@ -101,34 +104,34 @@ export default function FamilyAcc() { } }; - const memberList = useCallback(async () => { - setLoader(true); - try { - const res = await apiCall.familyListings(); - const { data } = res; - if (data?.internal_return >= 0 && data?.status === "OK") { - const { result_list, session_image_server } = data; - setFamilyList({ result_list, session_image_server }); - sessionStorage.setItem("family_list", JSON.stringify(result_list)) - setLoader(false); - } else { - return; - } - } catch (error) { - setLoader(false); - throw new Error(error); - } - }, [apiCall]); + // const memberList = useCallback(async () => { + // setLoader(true); + // try { + // const res = await apiCall.familyListings(); + // const { data } = res; + // if (data?.internal_return >= 0 && data?.status === "OK") { + // const { result_list, session_image_server } = data; + // setFamilyList({ result_list, session_image_server }); + // sessionStorage.setItem("family_list", JSON.stringify(result_list)) + // setLoader(false); + // } else { + // return; + // } + // } catch (error) { + // setLoader(false); + // throw new Error(error); + // } + // }, [apiCall]); - useEffect(() => { - let checkMemberList = true; - if (checkMemberList) { - memberList(); - } - return () => { - checkMemberList = false; - }; - }, [listReload, memberList]); + // useEffect(() => { + // let checkMemberList = true; + // if (checkMemberList) { + // memberList(); + // } + // return () => { + // checkMemberList = false; + // }; + // }, [listReload, memberList]); return ( @@ -177,7 +180,7 @@ export default function FamilyAcc() { diff --git a/src/views/FamilyRoutesPage.jsx b/src/views/FamilyRoutesPage.jsx new file mode 100644 index 0000000..da9e477 --- /dev/null +++ b/src/views/FamilyRoutesPage.jsx @@ -0,0 +1,21 @@ +import React from 'react' +import { Route, Routes } from "react-router-dom"; + +import FamilyRoutes from '../components/FamilyAcc/FamilyRoutes' +import FamilyAcc from '../components/FamilyAcc'; +import FamilyActivities from '../components/FamilyAcc/FamilyActivities'; +import FamilySettings from '../components/FamilyAcc/FamilySettings'; +import FourZeroFour from '../components/FourZeroFour'; + +export default function FamilyRoutesPage() { + return ( + + }> + } /> + } /> + } /> + } /> + + + ) +} -- 2.34.1