Compare commits

...

9 Commits

15 changed files with 1079 additions and 629 deletions
+2
View File
@@ -44,6 +44,7 @@ import MyPastDueJobsPage from "./views/MyPastDueJobsPage";
import BlogPage from "./views/BlogPage"; import BlogPage from "./views/BlogPage";
import MyReviewDueJobsPage from "./views/MyReviewDueJobsPage"; import MyReviewDueJobsPage from "./views/MyReviewDueJobsPage";
import OffersInterestPage from "./views/OffersInterestPage"; import OffersInterestPage from "./views/OffersInterestPage";
import ManageInterestOfferPage from './views/ManageInterestOfferPage'
export default function Routers() { export default function Routers() {
return ( return (
@@ -99,6 +100,7 @@ export default function Routers() {
<Route exact path="/manage-active-job" element={<ManageActiveJobs />} /> <Route exact path="/manage-active-job" element={<ManageActiveJobs />} />
<Route exact path="/blog-page" element={<BlogPage />} /> <Route exact path="/blog-page" element={<BlogPage />} />
<Route exact path="/offer-interest" element={<OffersInterestPage />} /> <Route exact path="/offer-interest" element={<OffersInterestPage />} />
<Route exact path="/manage-offer" element={<ManageInterestOfferPage />} />
<Route <Route
+16
View File
@@ -0,0 +1,16 @@
export const PriceFormatter = (price, currency, currencyName) => {
const supportedCurrencies = ["USD", "EUR", "GBP"];
const symbolFormatter = supportedCurrencies.includes(currency)
? currency
: undefined;
const formatter = new Intl.NumberFormat("en", {
style: symbolFormatter,
currencyDisplay: "symbol",
minimumFractionDigits: 2,
});
const displayCurrencyName = symbolFormatter ? "" : currencyName;
return `${formatter.format(price)} ${displayCurrencyName}`;
};
+1 -1
View File
@@ -278,7 +278,7 @@ function ActiveJobs(props) {
<div className="w-full my-2"> <div className="w-full my-2">
<p className="w-full text-base text-right text-sky-blue"> <p className="w-full text-base text-right text-sky-blue">
{userDetails.firstname && userDetails.firstname} {props.details.job_to && props.details.job_to}
</p> </p>
<div className="text-base text-slate-700 dark:text-black tracking-wide"> <div className="text-base text-slate-700 dark:text-black tracking-wide">
<p className="font-semibold text-black">Description: </p> <p className="font-semibold text-black">Description: </p>
@@ -1,8 +1,9 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import dataImage2 from "../../assets/images/data-table-user-2.png"; import dataImage2 from "../../assets/images/data-table-user-2.png";
import { useNavigate, useLocation } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination"; import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList"; import PaginatedList from "../Pagination/PaginatedList";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function MyActiveJobTable({ MyJobList, className }) { export default function MyActiveJobTable({ MyJobList, className }) {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -43,7 +44,11 @@ export default function MyActiveJobTable({ MyJobList, className }) {
MyJobList.result_list.length > 0 ? ( MyJobList.result_list.length > 0 ? (
currentActiveJobList.map((value, index) => { currentActiveJobList.map((value, index) => {
let deliveryDate = value?.delivery_date?.split(" ")[0]; let deliveryDate = value?.delivery_date?.split(" ")[0];
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
return ( return (
<tr <tr
key={index} key={index}
@@ -66,7 +71,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Price:{" "} Price:{" "}
<span className="text-purple"> <span className="text-purple">
{value.price * 0.01} {thePrice}
</span> </span>
</span> </span>
<div className="flex gap-4 items-center"> <div className="flex gap-4 items-center">
@@ -85,7 +90,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
</span> </span>
</span> </span>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Send to:{" "} Sent to:{" "}
<span className="text-purple"> <span className="text-purple">
{" "} {" "}
{value.job_to === null {value.job_to === null
@@ -11,9 +11,7 @@ export default function MyPastDueJobs(props) {
}; };
return ( return (
<Layout> <Layout>
<CommonHead <CommonHead commonHeadData={props.commonHeadData} />
commonHeadData={props.commonHeadData}
/>
<div className="notification-page w-full mb-10"> <div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full"> <div className="notification-wrapper w-full">
{/* heading */} {/* heading */}
@@ -1,8 +1,9 @@
import React, { useState } from "react"; import React, { useState } from "react";
import dataImage2 from "../../assets/images/data-table-user-2.png"; import dataImage2 from "../../assets/images/data-table-user-2.png";
import PendingJobsPopout from "../jobPopout/PendingJobsPopout";
import { handlePagingFunc } from "../Pagination/HandlePagination"; import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList"; import PaginatedList from "../Pagination/PaginatedList";
import PendingJobsPopout from "../jobPopout/PendingJobsPopout";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function MyPendingJobTable({ MyJobList, className }) { export default function MyPendingJobTable({ MyJobList, className }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
@@ -42,6 +43,11 @@ export default function MyPendingJobTable({ MyJobList, className }) {
MyJobList.result_list.length > 0 ? ( MyJobList.result_list.length > 0 ? (
currentActiveJobList.map((value, index) => { currentActiveJobList.map((value, index) => {
let deliveryDate = value?.expire?.split(" ")[0]; let deliveryDate = value?.expire?.split(" ")[0];
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
return ( return (
<tr <tr
key={index} key={index}
@@ -64,7 +70,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Price:{" "} Price:{" "}
<span className="text-purple"> <span className="text-purple">
{value.price * 0.01} {thePrice}
</span> </span>
</span> </span>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
@@ -83,7 +89,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
</span> </span>
</span> </span>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Send to:{" "} Sent to:{" "}
<span className="text-purple"> <span className="text-purple">
{" "} {" "}
{value.job_to} {value.job_to}
@@ -106,7 +112,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
</button> </button>
</td> </td>
</tr> </tr>
) );
}) })
) : ( ) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap"> <tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
+13 -6
View File
@@ -4,6 +4,7 @@ import PaginatedList from "../Pagination/PaginatedList";
import { handlePagingFunc } from "../Pagination/HandlePagination"; import { handlePagingFunc } from "../Pagination/HandlePagination";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import { useNavigate, useLocation } from "react-router-dom"; import { useNavigate, useLocation } from "react-router-dom";
import { PriceFormatter } from "../Helpers/PriceFormatter";
const noTasksBg = require("../../assets/images/no-task-background.jpg"); const noTasksBg = require("../../assets/images/no-task-background.jpg");
@@ -58,7 +59,13 @@ export default function MyJobTable({ className, ActiveJobList }) {
<div className="relative w-full sm:rounded-lg"> <div className="relative w-full sm:rounded-lg">
<div className="h-auto w-full"> <div className="h-auto w-full">
{ActiveJobList?.data?.length > 0 && {ActiveJobList?.data?.length > 0 &&
currentTask?.map((task, idx) => ( currentTask?.map((task, idx) => {
let thePrice = PriceFormatter(
task?.price * 0.01,
task?.currency_code,
task?.currency
);
return (
<div <div
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] w-full flex justify-between items-center hover:bg-gray-50" className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] w-full flex justify-between items-center hover:bg-gray-50"
key={idx} key={idx}
@@ -81,11 +88,9 @@ export default function MyJobTable({ className, ActiveJobList }) {
</span> </span>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Price: Price:
<span className="text-purple ml-1"> <span className="text-purple ml-1">{thePrice}</span>
{Number(task?.price) * 0.01}
</span> </span>
</span> <div className="flex gap-4 items-center">
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Duration: Duration:
<span className="text-purple ml-1"> <span className="text-purple ml-1">
@@ -109,6 +114,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
</div> </div>
</div> </div>
</div> </div>
</div>
<div className="flex justify-center items-center py-4 px-2"> <div className="flex justify-center items-center py-4 px-2">
<button <button
@@ -124,7 +130,8 @@ export default function MyJobTable({ className, ActiveJobList }) {
</button> </button>
</div> </div>
</div> </div>
))} );
})}
{ActiveJobList?.data?.length <= 0 && ( {ActiveJobList?.data?.length <= 0 && (
<div className="flex flex-col items-center justify-center gap-9 my-5"> <div className="flex flex-col items-center justify-center gap-9 my-5">
+15 -20
View File
@@ -6,9 +6,9 @@ import top4 from "../../assets/images/top-buyer-4.png";
import Icons from "../Helpers/Icons"; import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom"; import SliderCom from "../Helpers/SliderCom";
import OfferJobPopout from '../jobPopout/OfferJobPopout' import OfferJobPopout from "../jobPopout/OfferJobPopout";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function MyOffersTable({ className, MyActiveOffersList }) { export default function MyOffersTable({ className, MyActiveOffersList }) {
let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
@@ -52,7 +52,7 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
}; };
if (!MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0) { if (!MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0) {
return(''); // want blank or no appear when no items return ""; // want blank or no appear when no items
} }
return ( return (
@@ -114,9 +114,15 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
</div> </div>
<div className="slider-content"> <div className="slider-content">
<SliderCom settings={settings} selector={sellSlider}> <SliderCom settings={settings} selector={sellSlider}>
{ {MyActiveOffersList &&
MyActiveOffersList && MyActiveOffersList?.result_list?.length > 0 && MyActiveOffersList?.result_list?.length > 0 &&
MyActiveOffersList?.result_list?.map((value, index) => ( MyActiveOffersList?.result_list?.map((value, index) => {
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
return (
<div className="item" key={index}> <div className="item" key={index}>
<div className="offer-slide-item flex flex-col justify-between items-center"> <div className="offer-slide-item flex flex-col justify-between items-center">
{/* title */} {/* title */}
@@ -131,15 +137,9 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
{value.timeline_days} Days {value.timeline_days} Days
</p> </p>
<div className="my-2 flex space-x-1 items-center text-purple text-xs"> <div className="my-2 flex space-x-1 items-center text-purple text-xs">
<span>{value.price*0.01} {value.currency}</span> <span>{thePrice}</span>
</div> </div>
</div> </div>
{/* items */}
{/* <div className="flex justify-center">
<div className="flex space-x-1 items-center text-purple text-xs">
<span>{value.price*0.01} {value.currency}</span>
</div>
</div> */}
<button <button
type="button" type="button"
onClick={() => { onClick={() => {
@@ -149,14 +149,10 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
> >
Start Task Start Task
</button> </button>
</div> </div>
</div> </div>
)) );
} })}
{/* <div className="item">*/} {/* <div className="item">*/}
{/* /!* img *!/*/} {/* /!* img *!/*/}
@@ -411,7 +407,6 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
/> />
)} )}
{/* End of Offer Job Popout */} {/* End of Offer Job Popout */}
</div> </div>
</> </>
); );
@@ -0,0 +1,210 @@
import React, { useState } from "react";
import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import { useNavigate } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import OthersInterestedTable from "./OthersInterestedTable";
export default function ManageInterestOffer(props) {
const navigate = useNavigate()
const messageList = {data: [1,2,3,4,5,6]} // TO BE REMOVED AND REPLACE WITH REAL MESSAGE FROM API CALL
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentMessageList = messageList?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
};
return (
<Layout>
<CommonHead
commonHeadData={props.commonHeadData}
/>
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span className={`${selectTab === "today" ? "block" : "hidden"}`}>Manage Offer Interest</span>
</h1>
</div>
</div>
{/* manage offer section */}
<div className="w-full mb-8 p-8 bg-white dark:bg-dark-white rounded-2xl section-shadow">
{/* <div className="w-full flex justify-start space-x-3 items-center">
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() =>
navigate(props.offerDetails.pathname, { replace: true })
}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-sm lg:text-xl font-bold text-sky-blue dark:text-white tracking-wide">
{props.offerDetails?.offer_code && props.offerDetails.offer_code}
</h1>
</div> */}
<div className="my-2 w-full md:grid gap-5 grid-cols-3">
{/* Detail section */}
<div className="w-full mb-5 lg:mb-0 col-span-2">
<div className="w-full flex justify-start space-x-3 items-center">
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() =>
navigate(props.offerDetails.pathname, { replace: true })
}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-sm lg:text-xl font-bold text-sky-blue dark:text-white tracking-wide">
{props.offerDetails?.offer_code && props.offerDetails.offer_code}
</h1>
</div>
<h1 className="my-5 text-xl lg:text-2xl font-bold text-dark-gray dark:text-white tracking-wide border">
{props.offerDetails?.title}
</h1>
<div className="flex items-center">
<div className="w-3/4">
<div className="my-5 flex items-center gap-1">
<span className="w-[150px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Name</span>
<span className="text-sm font-bold text-dark-gray dark:text-white tracking-wide">Dummy name</span>
</div>
<div className="my-5 flex items-center gap-1">
<span className="w-[150px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Member Since</span>
<span className="text-sm font-bold text-dark-gray dark:text-white tracking-wide">Dummy Date</span>
</div>
<div className="my-5 flex items-center gap-1">
<span className="w-[150px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Jobs completed</span>
<span className="text-sm font-bold text-dark-gray dark:text-white tracking-wide">Dummy number</span>
</div>
<div className="my-5 flex items-center gap-1">
<span className="w-[150px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Jobs active</span>
<span className="text-sm font-bold text-dark-gray dark:text-white tracking-wide">Dummy number</span>
</div>
<div className="my-5 flex items-center gap-1">
<span className="w-[150px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Jobs uncompleted</span>
<span className="text-sm font-bold text-dark-gray dark:text-white tracking-wide">Dummy number</span>
</div>
<div className="my-5 flex items-center gap-1">
<span className="w-[150px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Pending Offers</span>
<span className="text-sm font-bold text-dark-gray dark:text-white tracking-wide">Dummy number</span>
</div>
<div className="flex items-center gap-1">
<span className="w-[150px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">% completion</span>
<span className="text-sm font-bold text-dark-gray dark:text-white tracking-wide">Dummy number</span>
</div>
</div>
<div className="w-1/4 flex flex-col justify-center items-center gap-10">
<button
type="button"
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<span className="text-white">Accept</span>
</button>
<button
type="button"
className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white"
>
<span className="text-gradient">Reject</span>
</button>
</div>
</div>
</div>
{/* END OF Detail section */}
{/* message section */}
<div className="p-4 w-full min-h-full bg-sky-100 dark:bg-dark-gray col-span-1">
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">Message to dummy name</p>
<div className="my-4 w-full">
<textarea rows={5} className="p-4 text-base font-bold text-dark-gray dark:text-white tracking-wide w-full resize-none rounded-md outline-none" />
<div className="w-full flex justify-end items-center">
<button
type="button"
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<span className="text-white">Send</span>
</button>
</div>
</div>
{/* message list */}
{currentMessageList.map((item, index)=>(
<div className="my-3 w-full">
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">2023-04-06-from { }<span className="font-normal">Dummy name</span></p>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">I am testing message</p>
</div>
))}
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
messageList?.data?.length
? true
: false
}
data={messageList?.data}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
{/* END of message section */}
</div>
</div>
{/* END OF manage offer section */}
</div>
<div className="w-full overflow-x-auto">
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span className={`${selectTab === "today" ? "block" : "hidden"}`}>Others interested in this Task</span>
</h1>
</div>
</div>
</div>
</div>
<OthersInterestedTable othersInterestedList={props.othersInterestedList} />
</div>
</div>
</Layout>
);
}
@@ -5,19 +5,23 @@ import { useNavigate, useLocation, Link } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination"; import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList"; import PaginatedList from "../Pagination/PaginatedList";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import familyImage from '../../assets/images/no-family-side.png' import familyImage from '../../assets/images/no-family-side.png'
export default function FamilyTable({ className, familyList, loader, popUpHandler }) { export default function OffersInterestTable({offerInterestList, className}) {
const navigate = useNavigate();
let { pathname } = useLocation();
const filterCategories = ["All Categories", "Explore", "Featured"]; const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]); const [selectedCategory, setCategory] = useState(filterCategories[0]);
const navigate = useNavigate();
// let location = useLocation();
const [currentPage, setCurrentPage] = useState(0); const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage); const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE); Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentFamilyList = familyList?.slice(indexOfFirstItem, indexOfLastItem); const currentOfferInterestList = offerInterestList?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => { const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage); handlePagingFunc(e, setCurrentPage);
@@ -25,93 +29,72 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
return ( return (
<div <div
className={`update-table w-full h-full p-8 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] ${ className={`update-table w-full p-8 bg-white dark:bg-dark-white rounded-2xl section-shadow min-h-[520px] ${
className || "" className || ""
}`} }`}
> >
<div className="relative w-full h-full overflow-x-auto sm:rounded-lg">
{loader ? ( {offerInterestList?.loading ? (
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center"> <div className="min-h-[520px] w-full flex flex-col justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" /> <LoadingSpinner size="16" color="sky-blue" />
</div> </div>
) )
: :
familyList?.length > 0 ? offerInterestList?.data?.length > 0 ?
( (
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative"> <table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<thead className="sticky top-0"> <thead className="sticky top-0">
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom "> {/* <tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
<th className="py-4">Name</th> <th className="py-4">Name</th>
<th className="py-4 text-center">Last Login</th> <th className="py-4 text-center">Last Login</th>
<th className="py-4 text-center">No of Tasks</th> <th className="py-4 text-center">No of Tasks</th>
<th className="py-4 text-right"></th> <th className="py-4 text-right"></th>
</tr> </tr> */}
</thead> </thead>
<tbody className="h-full"> <tbody className="h-full">
{currentFamilyList?.map((props, idx) => { {currentOfferInterestList?.map((item, idx) => {
let {
firstname,
lastname,
age,
added,
last_login,
task_count,
family_uid,
} = props;
let addedDate = added?.split(" ")[0];
let LoginDate = last_login?.split(" ")[0];
return ( return (
<tr <tr key={item?.offer_uid} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={family_uid}
>
<td className=" py-4"> <td className=" py-4">
<div className="flex space-x-2 items-center w-full"> <div className="flex space-x-2 items-center">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] min-w-[60px]"> <div className="min-w-[60px] min-h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img <img
src={dataImage1} src={dataImage1}
alt="data" alt="data"
className="w-full h-full" className="w-full h-full"
/> />
</div> </div>
<div className="flex flex-col flex-[0.9]"> <div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap"> <h1 className="font-bold text-xl text-dark-gray dark:text-white">
{`${firstname} ${lastname} (${age})`} {item?.title}
</h1> </h1>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">{item?.expire}</span>
Added:{" "}
<span className="text-purple ml-1">
{addedDate}
</span>
</span>
</div> </div>
</div> </div>
</td> </td>
<td className="text-center py-4 px-2"> <td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center"> <div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap"> <p className="font-bold text-x text-dark-gray dark:text-white">{item?.client_name}</p>
{LoginDate}
</span>
</div> </div>
</td> </td>
<td className="text-center py-4 px-2"> <td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center"> <div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap"> {/* <span className="font-bold text-x text-dark-gray dark:text-white">{formatNumber(item?.price * 0.01)}</span> */}
{task_count} <span className="font-bold text-x text-dark-gray dark:text-white">{PriceFormatter(item?.price * 0.01,item?.currency_code,item?.currency)}</span>
</span>
</div> </div>
</td> </td>
<td className="text-right py-4 px-2 flex items-center justify-center">
<td className="text-right py-4">
<button <button
onClick={() => { onClick={() => {
navigate("/manage-family", { navigate("/manage-offer", {
state: { ...props }, state: { ...item, pathname },
}); });
}} }}
type="button" type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
> >
Manage View
</button> </button>
</td> </td>
</tr> </tr>
@@ -125,33 +108,33 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
( (
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between"> <div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<div className="p-2 w-full md:w-1/2"> <div className="p-2 w-full md:w-1/2">
<p className="mb-4 p-3 md:p-16">Add your family, assign tasks, and get the whole team engaged.</p> <p className="mb-4 p-3 md:p-16">No Offer list avaliable.</p>
<button <button
onClick={popUpHandler} onClick={()=>{navigate('/market', {replace: true})}}
type="button" type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full" className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
> >
Add Family Goto Market
</button> </button>
</div> </div>
<div className="p-2 w-full md:w-1/2"> <div className="p-2 w-full md:w-1/2">
<img className='w-full' src={familyImage} alt="Add Family" /> <img className='w-full' src={familyImage && familyImage} alt="Add Family" />
</div> </div>
</div> </div>
) )
} }
</div>
{/* PAGINATION BUTTON */} {/* PAGINATION BUTTON */}
<PaginatedList <PaginatedList
onClick={handlePagination} onClick={handlePagination}
prev={currentPage == 0 ? true : false} prev={currentPage == 0 ? true : false}
next={ next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >= currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familyList?.length offerInterestList?.data?.length
? true ? true
: false : false
} }
data={familyList} data={offerInterestList?.data}
start={indexOfFirstItem} start={indexOfFirstItem}
stop={indexOfLastItem} stop={indexOfLastItem}
/> />
@@ -159,3 +142,28 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
</div> </div>
); );
} }
// Function to format number to two(2) decimal places
// function formatNumber(number) {
// // Convert the number to a string
// let numStr = String(number);
// // Split the string into integer and decimal parts
// let parts = numStr.split('.');
// let integerPart = parts[0];
// let decimalPart = parts[1] || '';
// // Add thousands separators to the integer part
// let formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// // Truncate or pad the decimal part to two decimal points
// let formattedDecimal = decimalPart.slice(0, 2).padEnd(2, '0');
// // Combine the formatted integer and decimal parts
// let formattedNumber = formattedInteger + '.' + formattedDecimal;
// return formattedNumber;
// }
@@ -0,0 +1,144 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { useNavigate, useLocation, Link } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import familyImage from '../../assets/images/no-family-side.png'
export default function OthersInterestTable({othersInterestedList, className}) {
const navigate = useNavigate();
let { pathname } = useLocation();
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentOthersInterestedList = othersInterestedList?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
{othersInterestedList?.loading ? (
<div className="min-h-[520px] w-full flex flex-col justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
)
:
othersInterestedList?.data?.length > 0 ?
(
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<thead className="sticky top-0">
{/* <tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
<th className="py-4">Name</th>
<th className="py-4 text-center">Last Login</th>
<th className="py-4 text-center">No of Tasks</th>
<th className="py-4 text-right"></th>
</tr> */}
</thead>
<tbody className="h-full">
{currentOthersInterestedList?.map((item, idx) => {
return (
<tr key={item?.offer_uid} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="min-w-[60px] min-h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage1}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{item?.title}
</h1>
<span className="text-sm text-thin-light-gray">{item?.expire}</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<p className="font-bold text-x text-dark-gray dark:text-white">{item?.client_name}</p>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
{/* <span className="font-bold text-x text-dark-gray dark:text-white">{formatNumber(item?.price * 0.01)}</span> */}
<span className="font-bold text-x text-dark-gray dark:text-white">{PriceFormatter(item?.price * 0.01,item?.currency_code,item?.currency)}</span>
</div>
</td>
<td className="text-right py-4">
<button
onClick={() => {
navigate("/manage-offer", {
state: { ...item, pathname },
});
}}
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})
}
</tbody>
</table>
)
:
(
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<div className="p-2 w-full md:w-1/2">
<p className="mb-4 p-3 md:p-16">No Offer list avaliable.</p>
<button
onClick={()=>{navigate('/market', {replace: true})}}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Goto Market
</button>
</div>
<div className="p-2 w-full md:w-1/2">
<img className='w-full' src={familyImage && familyImage} alt="Add Family" />
</div>
</div>
)
}
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
othersInterestedList?.data?.length
? true
: false
}
data={othersInterestedList?.data}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
);
}
+3 -11
View File
@@ -2,6 +2,7 @@ import React, { useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import Layout from "../Partials/Layout"; import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead"; import CommonHead from "../UserHeader/CommonHead";
import OffersInterestTable from './OffersInterestTable'
export default function OffersInterest(props) { export default function OffersInterest(props) {
const [selectTab, setValue] = useState("today"); const [selectTab, setValue] = useState("today");
@@ -19,22 +20,13 @@ export default function OffersInterest(props) {
<div className="sm:flex justify-between items-center mb-6"> <div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0"> <div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold text-dark-gray dark:text-white"> <h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span <span className={`${selectTab === "today" ? "block" : "hidden"}`}>Offer Interest</span>
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Offer Interest
</span>
</h1> </h1>
</div> </div>
<div className="slider-btns flex space-x-4">
</div>
</div>
<div>
Blog Items Details
</div> </div>
</div> </div>
</div> </div>
<OffersInterestTable offerInterestList={props.offerInterestList} />
</Layout> </Layout>
); );
} }
+13
View File
@@ -653,6 +653,19 @@ class usersService {
return this.postAuxEnd("/offersresponse", postData); return this.postAuxEnd("/offersresponse", postData);
} }
// END POINT FOR OFFERS INTEREST LIST
offersInterestList() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 13024,
limit: 30,
offset: 0
};
return this.postAuxEnd("/offersinterestlist", postData);
}
// END POINT FOR WORKER TO MARK TASK AS COMPLETED // END POINT FOR WORKER TO MARK TASK AS COMPLETED
workerJobAction(reqData) { workerJobAction(reqData) {
var postData = { var postData = {
+39
View File
@@ -0,0 +1,39 @@
import React, { useContext,useState, useEffect } from "react";
import usersService from "../services/UsersService";
import ManageInterestOffer from "../components/OffersInterest/ManageInterestOffer";
import { useSelector } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
export default function MyReviewDueJobsPage() {
const {state} = useLocation()
let navigate = useNavigate()
let {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
const apiCall = new usersService();
const [othersInterestedList, setOthersInterestedList] = useState({loading: true, data: []})
useEffect(() => {
if(!state){
navigate('/', {replace: true})
return
}
apiCall.offersInterestList().then(res => {
setOthersInterestedList({loading: false, data: res.data.result_list})
}).catch(err => {
setOthersInterestedList({loading: false, data: []})
console.log('Error: ', err)
})
}, []);
// debugger;
return (
<>
<ManageInterestOffer
othersInterestedList={othersInterestedList}
commonHeadData={commonHeadBanner.result_list}
offerDetails={state}
/>
</>
);
}
+16 -1
View File
@@ -3,12 +3,27 @@ import React, { useContext, useState, useEffect } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import OffersInterest from "../components/OffersInterest"; import OffersInterest from "../components/OffersInterest";
import usersService from "../services/UsersService";
export default function OffersInterestPage() { export default function OffersInterestPage() {
const apiCall = new usersService()
let {commonHeadBanner} = useSelector(state => state.commonHeadBanner) let {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
let [offerInterestList, setOfferInterestList] = useState({loading: true, data: []})
useEffect(()=>{
apiCall.offersInterestList().then(res => {
setOfferInterestList({loading: false, data: res.data.result_list})
}).catch(err => {
setOfferInterestList({loading: false, data: []})
console.log('Error: ', err)
})
},[])
return ( return (
<> <>
<OffersInterest commonHeadData={commonHeadBanner.result_list} /> <OffersInterest commonHeadData={commonHeadBanner.result_list} offerInterestList={offerInterestList} />
</> </>
); );
} }