Files
Users-Wrench/src/components/MyJobs/MyJobTable.jsx
T
victorAnumudu fa40f8f725 initial commit
2024-04-12 13:48:50 +01:00

397 lines
12 KiB
React

import { useCallback, useEffect, useMemo, useState } from "react";
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 DeleteIcon from "../../assets/images/icon-delete.svg";
import EditIcon from "../../assets/images/icon-edit.svg";
import { tableReload } from "../AddJob/settings";
import CreditPopup from "../MyWallet/Popup/CreditPopup";
import JobListPopout from "../jobPopout/JobListPopout";
import EditJobPopoutNew from "../jobPopout/EditJobPopoutNew";
export default function MyJobTable({ MyJobList, reloadJobList, className }) {
const dispatch = useDispatch();
// Getting the categories
const currentJobCart = MyJobList?.data?.categories;
// DropDown Box
const filterCategories = { All: "All Categories", ...currentJobCart };
const [selectedCategory, setCategory] = useState(
Object.keys(filterCategories)[0]
);
const [jobPopout, setJobPopout] = useState({ show: false, data: {} });
const [deleteJobPopout, setDeleteJobPopout] = useState({
show: false,
data: {},
});
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) {
const {
data: { result_list },
} = await res;
let checkCountry = result_list
?.filter((item) => item.code == country)
?.map((item) => item.country)
.join("");
setCountries(checkCountry);
}
} catch (error) {
throw new Error(error);
}
}, [userApi, country]);
useEffect(() => {
getCountryList();
}, [getCountryList]);
// Handle Pagination
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
// Handle Filter Job List
const filterJobList = () => {
if (selectedCategory === "All") return MyJobList?.data?.result_list;
else
return MyJobList?.data?.result_list?.filter((item) =>
item.category.includes(selectedCategory)
);
};
const currentJobList = filterJobList();
// Handling Filter Pagination
const filteredCurrentJobList = currentJobList?.slice(
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
// Handles the category selection
const handleSetCategory = (value) => {
setCurrentPage(0);
for (let i in filterCategories) {
if (filterCategories[i] == value) {
setCategory(i);
}
}
};
const { MyJobListHeader, MyJobListTable } = myJobTableFeatures(
filterCategories,
selectedCategory,
handleSetCategory,
setDeleteJobPopout,
setEditJob,
setJobPopout,
MyJobList,
filteredCurrentJobList,
handlePagination,
currentPage,
currentJobList,
indexOfFirstItem,
indexOfLastItem
);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
<MyJobListHeader />
{MyJobList?.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<MyJobListTable />
)}
{/* Job List Popout */}
{jobPopout.show && (
<JobListPopout
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
setWalletItem={setWalletItem}
openWallet={openPopUp}
situation={jobPopout.show}
/>
)}
{/* End of Job List Popout */}
{/* Delete Job Popout */}
{deleteJobPopout.show && (
<DeleteJobPopout
details={deleteJobPopout.data}
onClose={() => {
setDeleteJobPopout({ show: false, data: {} });
}}
reloadJobList={reloadJobList}
situation={deleteJobPopout.show}
/>
)}
{/* END of Delete Job Popout */}
{editJob.show && (
<EditJobPopoutNew
details={editJob.data}
onClose={() => {
setEditJob({
show: false,
data: {},
});
}}
situation={editJob.show}
country={myCountry}
categories={currentJobCart}
/>
)}
{creditPopup.show && (
<CreditPopup
details={creditPopup.data}
walletItem={walletItem}
onClose={closePopUp}
situation={openPopUp}
/>
)}
</div>
);
}
function myJobTableFeatures(
filterCategories,
selectedCategory,
handleSetCategory,
setDeleteJobPopout,
setEditJob,
setJobPopout,
MyJobList,
filteredCurrentJobList,
handlePagination,
currentPage,
currentJobList,
indexOfFirstItem,
indexOfLastItem
) {
// List of job table features
const MyJobListHeader = () => (
<div className="header w-full flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
{filterCategories[selectedCategory]} Jobs
</h1>
</div>
<SelectBox
action={handleSetCategory}
datas={Object.values(filterCategories)}
className="Update-table-dropdown"
contentBodyClasses="w-auto min-w-max"
/>
</div>
);
const JobListItem = ({ value, index, image_server }) => {
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
const image = localStorage.getItem("session_token")
? `${image_server}${localStorage.getItem("session_token")}/job/${
value.job_uid
}`
: "";
return (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className="py-9">
<div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items">
<div className="flex space-x-2 items-center job-items w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
alt="data"
className="w-full h-full rounded-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price: <span className="text-purple">{thePrice}</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
</div>
</div>
<div className="h-[33px] w-[150px] flex flex-nowrap items-center self-end">
<button
type="button"
className="p-1 border-2 border-red-400 rounded-md"
onClick={() => {
setDeleteJobPopout({
show: true,
data: { thePrice, ...value },
});
}}
>
<img
className="w-[21px] h-[21px]"
src={DeleteIcon}
alt="delete-icon"
/>
</button>
<div className="mx-[4px] h-full w-[1px] bg-black dark:bg-dark-gray"></div>
<button
type="button"
className="p-1 border-2 border-sky-blue rounded-md flex items-center"
onClick={() => {
setEditJob({
show: true,
data: { thePrice, ...value },
});
}}
>
<img
className="w-[21px] h-[21px]"
src={EditIcon}
alt="edit-icon"
/>
<span className="text-sm text-sky-blue">Edit</span>
</button>
</div>
</div>
</td>
<td className="text-right py-9 px-2">
<button
type="button"
onClick={() => {
setJobPopout({
show: true,
data: { thePrice, ...value },
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Assign
</button>
</td>
</tr>
);
};
const NoJobsRow = ({ text }) => (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">{text}</td>
</tr>
);
const MyJobListTable = () => (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[520px]">
<table className="table-auto min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<>
{MyJobList?.data?.result_list?.length > 0 ? (
filteredCurrentJobList.length > 0 ? (
filteredCurrentJobList.map((value, index) => (
<JobListItem
key={index}
index={index}
value={value}
image_server={MyJobList.data.session_image_server}
/>
))
) : (
<NoJobsRow text="No Jobs Available In This Category!" />
)
) : (
<NoJobsRow text="No Jobs Available!" />
)}
</>
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
currentJobList?.length
? true
: false
}
data={currentJobList}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
);
return { MyJobListHeader, MyJobListTable };
}