Compare commits

...

31 Commits

Author SHA1 Message Date
victorAnumudu 36d8c70fd9 refactored some components and seperated their API calls 2024-03-27 23:17:58 +01:00
tokslaw 23443a4677 Merge branch 'family-media-task' of WrenchBoard/Users-Wrench into master 2024-03-27 17:42:54 +00:00
victorAnumudu 16e5656422 rendered video component for media task type 2024-03-27 18:39:04 +01:00
ameye 0e42668285 Merge branch 'media-task-api' of WrenchBoard/Users-Wrench into master 2024-03-27 12:42:23 +00:00
victorAnumudu 66bd8cf6ec added api for assign media task 2024-03-27 13:38:17 +01:00
ameye 3d7ad25517 Merge branch 'media-task' of WrenchBoard/Users-Wrench into master 2024-03-27 11:40:30 +00:00
victorAnumudu 2d5c828089 added inputs validation 2024-03-27 12:20:01 +01:00
victorAnumudu e39a8358f7 initial commit 2024-03-27 09:44:30 +01:00
tokslaw e9c57550a2 Merge branch 'assign-media-tab' of WrenchBoard/Users-Wrench into master 2024-03-26 19:21:02 +00:00
victorAnumudu 27f87ee92d added media tab on assign task to kid 2024-03-26 20:16:53 +01:00
ameye edf23352ef Merge branch 'error-msg' of WrenchBoard/Users-Wrench into master 2024-03-26 11:56:31 +00:00
victorAnumudu 002e2fead4 added error message object 2024-03-26 12:51:59 +01:00
ameye 160c302417 Merge branch 'my-page-link' of WrenchBoard/Users-Wrench into master 2024-03-25 16:46:49 +00:00
victorAnumudu 44ae966cc1 removed my page link from header nav 2024-03-25 17:17:08 +01:00
ameye f3b977c624 Merge branch 'package-lock-revert' of WrenchBoard/Users-Wrench into master 2024-03-25 14:25:14 +00:00
victorAnumudu 0c99e416ea reverted package-lock.json 2024-03-25 15:23:37 +01:00
tokslaw fd531d7d10 Merge branch 'assign-job-popout-style' of WrenchBoard/Users-Wrench into master 2024-03-25 11:47:25 +00:00
victorAnumudu ac027a3228 changed font weight 2024-03-25 12:45:55 +01:00
victorAnumudu 001492eeb5 changed price to reward 2024-03-25 12:40:01 +01:00
victorAnumudu 72fe2cad5f changed assign new job popout style 2024-03-25 12:36:10 +01:00
ameye eac693eba6 Merge branch 'pagination-item' of WrenchBoard/Users-Wrench into master 2024-03-24 19:25:43 +00:00
victorAnumudu d3b1462fe3 increased number of item to show in pagination 2024-03-24 15:57:21 +01:00
ameye 748546641d Merge branch 'market-pagination' of WrenchBoard/Users-Wrench into master 2024-03-24 12:35:26 +00:00
victorAnumudu 48a50fd47c added pagination for market list 2024-03-23 20:06:30 +01:00
tokslaw e87cb95b43 Merge branch 'offer-interest-refresh-fixed' of WrenchBoard/Users-Wrench into master 2024-03-22 17:09:35 +00:00
victorAnumudu 7638d68a7d merged branch with master, offer interest refresh fixed 2024-03-22 16:20:38 +01:00
victorAnumudu 3541363f9f added dummy pagination 2024-03-22 16:18:19 +01:00
victorAnumudu 30ce6a7d6e initial commit 2024-03-22 15:07:13 +01:00
ameye 115366672a Merge branch 'return-link' of WrenchBoard/Users-Wrench into master 2024-03-22 13:16:19 +00:00
victorAnumudu 3cd8b6e574 added link to family page 2024-03-22 12:45:34 +01:00
ameye 9850cdd392 Merge branch 'offer-interest-refresh' of WrenchBoard/Users-Wrench into master 2024-03-22 10:30:33 +00:00
39 changed files with 1460 additions and 706 deletions
+4 -1
View File
@@ -114,4 +114,7 @@ REACT_APP_SHOW_NEW_FAMILY_DASH=1
REACT_APP_SHOW_ACCOUNT_DASH=1
# Displays the slider banners
REACT_APP_SHOW_SLIDER_BANNERS=0
REACT_APP_SHOW_SLIDER_BANNERS=0
# FOR MEDIA LINK
REACT_APP_MEDIA_LINK='https://dev-media.wrenchboard.com '
+4 -1
View File
@@ -82,4 +82,7 @@ REACT_APP_SHOW_NEW_FAMILY_DASH=1
REACT_APP_SHOW_ACCOUNT_DASH=1
# Displays the slider banners
REACT_APP_SHOW_SLIDER_BANNERS=0
REACT_APP_SHOW_SLIDER_BANNERS=0
# FOR MEDIA LINK
REACT_APP_MEDIA_LINK='https://dev-media.wrenchboard.com '
+4 -1
View File
@@ -88,4 +88,7 @@ REACT_APP_SHOW_NEW_FAMILY_DASH=1
REACT_APP_SHOW_ACCOUNT_DASH=1
# Displays the slider banners
REACT_APP_SHOW_SLIDER_BANNERS=0
REACT_APP_SHOW_SLIDER_BANNERS=0
# FOR MEDIA LINK
REACT_APP_MEDIA_LINK='https://media.wrenchboard.com '
+10 -2
View File
@@ -1,7 +1,10 @@
import { Suspense, lazy } from "react";
import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import { PriceFormatter } from "../Helpers/PriceFormatter";
const VideoElement = lazy(() => import("../VideoCom/VideoElement")); // LAZY IMPORTING VIDEO COMPONENT
export default function OfferCard({
datas,
hidden = false,
@@ -19,9 +22,13 @@ export default function OfferCard({
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
{/* thumbnail */}
<div className="w-full h-40">
{/* thumbnail image */}
{/* thumbnail image/video */}
{datas.job_type == "MEDIA" ?
<Suspense fallback={<p>Loading...</p>}>
<VideoElement videoId={datas?.media_uid} />
</Suspense>
:
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
@@ -30,6 +37,7 @@ export default function OfferCard({
>
{hidden && <div className="flex justify-center"></div>}
</div>
}
</div>
{/* details */}
<div className="details">
+3 -2
View File
@@ -78,11 +78,12 @@ export default function SocketIOContextProvider({children}) {
});
socket.on("marketjob_actions", (data) => { // Triggers refresh on owner side, when somebody sends/shows interest in a job
// let user_uid = userDetails.account_type == 'FULL' ? userDetails.uid : sessionStorage.getItem('family_uid') // gets user UID
let user_uid = userDetails.account_type == 'FULL' ? userDetails.uid : sessionStorage.getItem('family_uid') // gets user UID
let {message} = data
if(message.action == "REFRESH_OFFERS" && message.audience == "MERCHANT"){ // for refreshing job owner offer interest list when any worker sends interest
if(message.action == "REFRESH_OFFERS" && message.audience == "MERCHANT" && message.market_uid == user_uid){ // for refreshing job owner offer interest list when any worker sends interest
dispatch(tableReload({type:'OFFERINTERESTLISTRELOAD'}))
}
console.log('data', data)
});
}, [socket]);
+37 -2
View File
@@ -1,8 +1,9 @@
import React, { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { Link, useLocation, useNavigate } from "react-router-dom";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import FamilyManageTabs from "./FamilyManageTabs";
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
export default function FamilyManage() {
const [selectTab, setValue] = useState("today");
@@ -34,7 +35,7 @@ export default function FamilyManage() {
<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="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span
@@ -50,6 +51,40 @@ export default function FamilyManage() {
className="relative"
></div>
</div>
</div> */}
<div className="w-full mb-5 flex justify-between items-center">
<div className="">
<CustomBreadcrumb
title = {'Manage Family'}
breadcrumb={
[
{ link: "/", title: "Home" },
{ link: "/manage-family", title: "Manage Family", active: true},
]
}
/>
</div>
<Link
className="item-content relative text-[18px] transition-all duration-300 ease-in-out bg-[#76a5df] text-white font-medium dark:text-white h-12 px-2 flex items-center gap-2 rounded-md shadow-sm justify-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
to="/acc-family"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-4 h-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"
/>
</svg>
<span>Family</span>
</Link>
</div>
<FamilyManageTabs accountDetails={accountDetails} />
</div>
+102 -101
View File
@@ -14,6 +14,7 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import FamilyWallet from "./Tabs/FamilyWallet";
import { apiConst } from "../../lib/apiConst";
import { useSelector } from "react-redux";
// Lazy Imports for components
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
@@ -29,43 +30,32 @@ export default function FamilyManageTabs({
listReload,
loader,
}) {
const { jobListTable, pendingListTable, parentFamilyTaskList } = useSelector((state) => state.tableReload); // TABLE RELOAD TRIGGERS
// Initial state for family details
const initialDetailState = {
loading: false,
data: null,
data: [],
};
// console.log('accountDetails',accountDetails)
// State for family details, tasks, waitlist, and pending
const [details, setDetails] = useState({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
// Function to reset family details, tasks, waitlist, and pending
const resetDetails = () => {
setDetails({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
};
// State for family details, tasks, waitlist, and pending
let [familyDetails, setFamilyDetails] = useState({loading: false, data: {}})
let [familyTasks, setFamilyTasks] = useState({...initialDetailState})
let [familyWaitList, setFamilyWaitList] = useState({...initialDetailState})
let [familyPending, setFamilyPending] = useState({...initialDetailState})
const [updatePage, setUpdatePage] = useState(false) // State to determine when to update the page
// State for family task data
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
// State for list of created jobs by FULL USER
const [jobList, setJobList] = useState({ loading: false, data: [] });
// State for active task
// State for active/selected job
const [activeTask, setActiveTask] = useState({ id: 0, data: {} });
// State for error messages
const [errMsg, setErrMsg] = useState("");
// State for family task popout
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
const [assignTaskPopout, setAssignTaskPopout] = useState(false);
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
@@ -79,8 +69,8 @@ export default function FamilyManageTabs({
const apiCall = useMemo(() => new usersService(), []);
// Function to handle toggling the family task popout
const familyPopUpHandler = () => {
setFamilyTaskPopout((prev) => !prev);
const familyAssignPopUpHandler = () => {
setAssignTaskPopout((prev) => !prev);
};
// Function to trigger a click on the hidden profile image input
@@ -177,44 +167,40 @@ export default function FamilyManageTabs({
Tasks: (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
familyData={familyTasks}
accountDetails={accountDetails}
/>
),
Waiting: (
<FamilyWaitlist
familyData={details.familyWaitList.data}
familyData={familyWaitList}
accountDetails={accountDetails}
loader={details.familyWaitList.loading}
setUpdatePage={setUpdatePage}
/>
),
Pending: (
<FamilyPending
familyData={details.familyPending.data}
familyData={familyPending}
accountDetails={accountDetails}
loader={details.familyPending.loading}
setUpdatePage={setUpdatePage}
/>
),
Account: (
<FamilyAccount
familyData={details.familyDetails.data}
familyData={familyDetails}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
),
Profile: <FamilyProfile familyData={details.familyDetails.data} />,
wallet: <FamilyWallet familyData={details.familyDetails.data} />,
Profile: <FamilyProfile familyData={familyDetails.data} />,
wallet: <FamilyWallet familyData={familyDetails.data} />,
};
// Default tab component
const defaultTabComponent = (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
familyData={familyTasks}
accountDetails={accountDetails}
/>
);
@@ -222,67 +208,90 @@ export default function FamilyManageTabs({
// Selected tab component based on the current 'tab'
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
// Effect to manage family details and related data
// Effect to manage family details
useEffect(() => {
const manageFamily = async () => {
setFamilyDetails({loading:true, data: {}})
try {
resetDetails();
setDetails({
familyDetails: { loading: true },
familyTasks: { loading: true },
familyWaitList: { loading: true },
familyPending: { loading: true },
});
const { family_uid } = accountDetails;
const reqData = { family_uid };
const [familyRes, tasksRes, familyWaitRes, familyPending] =
await Promise.all([
apiCall.ManageFamily(reqData),
apiCall.ManageTasks(reqData),
apiCall.ManageFamilyWaitlist(),
apiCall.ManageFamilyPending(),
]);
const familyData = familyRes.data;
const tasksData = tasksRes.data;
const familyWaitData = familyWaitRes.data;
const familyPendingData = familyPending.data;
// Function to check for errors in data
const checkDataError = (data) => data?.internal_return < 0;
if (
checkDataError(familyData) ||
checkDataError(tasksData) ||
checkDataError(familyWaitData) ||
checkDataError(familyPendingData)
) {
return;
const response = await apiCall.ManageFamily(reqData)
if(response.status != 200 || !response?.data){
return setFamilyDetails({loading:false, data: {}})
}
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
familyPending: { loading: false, data: familyPendingData },
});
setFamilyDetails({loading:false, data: response?.data})
} catch (error) {
resetDetails();
setErrMsg("An error occurred");
throw new Error(error);
setFamilyDetails({loading:false, data: {}})
}
};
// Invoke the manageFamily function when the component mounts
manageFamily();
}, []);
// Effect to manage active family task details
useEffect(() => {
const manageTasks = async () => {
setFamilyTasks({loading:true, data: []})
try {
const { family_uid } = accountDetails;
const reqData = { family_uid };
const response = await apiCall.ManageTasks(reqData)
if(response.status != 200 || !response?.data){
return setFamilyTasks({loading:false, data: []})
}
setFamilyTasks({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyTasks({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageTasks();
}, [updatePage, parentFamilyTaskList]);
// Effect to manage family wait task details
useEffect(() => {
const manageFamilyWaitlist = async () => {
setFamilyWaitList({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyWaitlist()
if(response.status != 200 || !response?.data){
return setFamilyWaitList({loading:false, data: []})
}
setFamilyWaitList({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyWaitList({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyWaitlist();
}, [updatePage]);
// Effect to manage family tasks
// Effect to manage family pending task details
useEffect(() => {
const manageFamilyPending = async () => {
setFamilyPending({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyPending()
if(response.status != 200 || !response?.data){
return setFamilyPending({loading:false, data: []})
}
setFamilyPending({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyPending({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyPending();
}, [updatePage, pendingListTable]);
// Effect to get all parent job list
useEffect(() => {
let checkFamilyTask = true;
const reqData = {
limit: 30,
offset: 0,
@@ -290,12 +299,11 @@ export default function FamilyManageTabs({
action: apiConst.WRENCHBOARD_PICTURE_FAMMEMBER,
};
if (checkFamilyTask) {
setFamilyTask({ loading: true });
setJobList({ loading: true });
apiCall
.getMyJobList(reqData)
.then((res) => {
setFamilyTask({ loading: false, data: res?.data?.result_list });
setJobList({ loading: false, data: res?.data?.result_list });
if (res?.data?.result_list?.length) {
setActiveTask((prev) => ({
...prev,
@@ -304,15 +312,9 @@ export default function FamilyManageTabs({
}
})
.catch((err) => {
setFamilyTask({ loading: false, data: [] });
setJobList({ loading: false, data: [] });
console.log("Error", err);
});
}
// Cleanup function to prevent memory leaks
return () => {
checkFamilyTask = false;
};
}, []);
return (
@@ -395,7 +397,7 @@ export default function FamilyManageTabs({
</ul>
<button
type="button"
onClick={familyPopUpHandler}
onClick={familyAssignPopUpHandler}
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add task
@@ -417,15 +419,14 @@ export default function FamilyManageTabs({
</Suspense>
</div>
{familyTaskPopout && (
{assignTaskPopout && (
<AssignTaskPopout
action={familyPopUpHandler}
situation={familyTaskPopout}
familyTask={familyTask}
setFamilyTask={setFamilyTask}
action={familyAssignPopUpHandler}
situation={assignTaskPopout}
jobList={jobList}
setActiveTask={setActiveTask}
activeTask={activeTask}
familyDetailsData={details.familyDetails.data}
familyDetailsData={familyDetails.data}
setUpdatePage={setUpdatePage}
/>
)}
@@ -0,0 +1,340 @@
import React, { useEffect, useState, lazy, Suspense } from 'react'
import LoadingSpinner from '../../Spinners/LoadingSpinner'
import { NewTasks } from './forms'
import { PriceFormatter } from '../../Helpers/PriceFormatter'
import { useSelector } from 'react-redux';
import { InputCom } from '../../AddJob/settings';
import * as Yup from "yup";
import { Form, Formik } from "formik";
// To get the validation schema
const validationSchema = Yup.object().shape({
currency: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("required"),
amount: Yup.number()
.typeError("Invalid number")
.min(1, "Must be greater than 0")
.test("no-e", "Invalid number", (value) => {
if (value && /\d+e/.test(value)) {
return false;
}
return true;
})
.required("required"),
job_description: Yup.string()
.min(3, "Minimum 3 characters")
.max(499, "Maximum 499 characters")
.required("required"),
timeline_days: Yup.number()
.typeError("you must specify a number")
.min(1, "Must be greater than 0")
.required("required"),
});
const VideoElement = lazy(() => import("../../VideoCom/VideoElement")); // LAZY IMPORTING VIDEO COMPONENT
export default function AssignMediaTask({
commonMedia,
requestStatus,
setRequestStatus,
assignMediaTask,
activeMedia,
handleActiveMedia,
closeModal,
family_uid
}) {
// For form initial values
const initialValues = {
// initial values for formik
currency: "",
amount: "",
job_description: "",
timeline_days: "",
media_uid: activeMedia.uid,
family_uid: family_uid,
media_type: "COMMON"
};
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
// let imageSrc = (localStorage.getItem("session_token")
// ? `${userDetails?.session_image_server}${localStorage.getItem("session_token")}/job/${activeMedia.uid}` : ""); // FOR GETTING JOB IMAGE
return (
<>
{commonMedia?.loading ? (
<div className="h-[30rem] w-full flex justify-center items-center">
<LoadingSpinner color="sky-blue" size="16" />
</div>
) : (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={(values, helpers)=>{assignMediaTask(values, helpers)}}
>
{(props) => {
return (
<Form>
<>
<div
className={`job-action-modal-body w-full min-h-[450px] max-h-[450px] overflow-y-auto md:grid md:grid-cols-2`}
>
<div className="p-4 pt-0">
<div className="p-4 w-full min-h-[400px] max-h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
{commonMedia?.data?.length ? (
commonMedia?.data?.map((item, index) => (
<div
key={item.uid}
className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer"
onClick={() => handleActiveMedia(item)}
>
<input
type="radio"
name="media-list"
checked={activeMedia?.uid == item?.uid}
onChange={() =>
handleActiveMedia(item)
}
className="w-[15px] h-[15px] cursor-pointer"
/>
<p className="w-full text-dark-gray dark:text-white tracking-wide">
{item?.title}
</p>
</div>
))
) : (
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center cursor-default">
No Media found!
</p>
)}
</div>
</div>
{/*Right Hand Side for details && Task Type === select */}
<>
{commonMedia?.data?.length > 0 ? (
<div className="p-4 py-0 h-full">
<div className="w-full">
<div className="mb-3 w-full">
<label className="job-label">
Description
</label>
<p className="p-1 text-sm text-slate-900 dark:text-white">
{activeMedia?.description}
</p>
</div>
<div className="my-3 w-full flex items-center justify-center">
<div className="w-full max-w-xs h-28 rounded-2xl flex items-center justify-center">
<Suspense fallback={<p>Loading...</p>}>
<VideoElement videoId={activeMedia?.uid} />
</Suspense>
</div>
</div>
<div className="grid grid-cols-2 gap-3">
{/* Price */}
<div className="field w-full">
<label htmlFor="price" className="job-label flex gap-1">
Price
<span className='text-red-500 text-[10px]'>{props.errors.amount && props.touched.amount && props.errors.amount}</span>
</label>
<InputCom
fieldClass="px-6 text-right"
// label="Price"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="number"
name="amount"
placeholder="0"
value={props.values.amount}
inputHandler={props.handleChange}
// error={props.errors.price && props.touched.price && props.errors.price}
/>
</div>
{/* Currency */}
<div className="field w-full">
<label
htmlFor="currency"
className="job-label flex gap-1"
>
Currency
{props.errors.currency && props.touched.currency && <span className="text-[10px] text-red-500">{props.errors.currency}</span>}
</label>
<select
id="currency"
name="currency"
value={props.values.currency}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-[13.975px]" value="">
Loading...
</option>
) : walletDetails.data.length ? (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Currency
</option>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.code}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found!
</option>
)}
</select>
</div>
</div>
{/* Duration */}
<div className="field w-full">
<label
htmlFor="timeline_days"
className="job-label flex gap-1"
>
Timeline
{props.errors.timeline_days && props.touched.timeline_days && <span className="text-[12px] text-red-500">{props.errors.timeline_days}</span>}
</label>
<select
id="timeline_days"
name="timeline_days"
value={props.values.timeline_days}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
>
{publicArray.length && (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Duration
</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-[13.975px]"
value={duration}
>
{name}
</option>
))}
</>
)}
</select>
</div>
{/* Delivery Detail */}
<div className="my-3">
<label className="w-full job-label flex gap-1">
Delivery Detail
{props.errors.job_description && props.touched.job_description && <span className="text-[12px] text-red-500">{props.errors.job_description}</span>}
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
value={props.values.job_description}
onChange={props.handleChange}
name='job_description'
/>
</div>
</div>
</div>
) : (
<></>
)}
</>
</div>
{/* BTN */}
<div className="modal-footer-wrapper">
{/* error or success display */}
<div className="w-auto h-auto flex items-center">
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px] self-start`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-2 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
<div className="w-auto h-auto flex items-center gap-20">
<button
disabled={requestStatus.loading}
onClick={()=>closeModal()}
type="button"
className="custom-btn border-gradient"
>
<span className="text-gradient">Close</span>
</button>
<div className="">
{requestStatus.loading ? (
<LoadingSpinner color="sky-blue" size="8" />
) : (
<button
type="submit"
disabled={requestStatus.loading}
// onClick={assignFamilyTask}
className="custom-btn btn-gradient text-white"
>
Assign
</button>
)
}
</div>
</div>
</div>
</>
</Form>
)
}
}
</Formik>
)
}
</>
)
}
const publicArray = [
{ duration: 1, name: "1 day" },
{ duration: 2, name: "2 days" },
{ duration: 3, name: "3 days" },
{ duration: 4, name: "4 days" },
{ duration: 5, name: "5 days" },
{ duration: 6, name: "6 days" },
{ duration: 7, name: "1 week" },
{ duration: 14, name: "2 weeks" },
{ duration: 21, name: "3 weeks" },
{ duration: 28, name: "4 weeks" },
];
@@ -0,0 +1,263 @@
import React from 'react'
import LoadingSpinner from '../../Spinners/LoadingSpinner'
import { NewTasks } from './forms'
import { PriceFormatter } from '../../Helpers/PriceFormatter'
import { useSelector } from 'react-redux';
export default function AssignPrevNewTask({
jobList,
requestStatus,
assignFamilyTask,
taskType,
switchTaskType,
formState,
setFormState,
activeTask,
handleActiveTask,
closeModal
}) {
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
let imageSrc = (localStorage.getItem("session_token")
? `${userDetails?.session_image_server}${localStorage.getItem("session_token")}/job/${activeTask.data.job_uid}` : ""); // FOR GETTING JOB IMAGE
return (
<>
{jobList?.loading ? (
<div className="h-[30rem] w-full flex justify-center items-center">
<LoadingSpinner color="sky-blue" size="16" />
</div>
) : (
<>
<div
className={`job-action-modal-body w-full min-h-[450px] max-h-[450px] overflow-y-auto md:grid ${
taskType !== "new" ? "md:grid-cols-2" : "md:grid-cols-1"
}`}
>
<div className="p-4 pt-0">
<div className="mb-2 w-full flex items-center gap-4">
<div className="flex items-center gap-2 text-sky-blue text-base">
<input
type="radio"
name="task-type"
value="select"
className="w-[20px] h-[20px] cursor-pointer"
checked={taskType == "select"}
onChange={switchTaskType}
/>
<span className="text-lg tracking-wide font-semibold">Previous Task</span>
</div>
<div className="flex items-center gap-2 text-sky-blue text-base">
<input
type="radio"
name="task-type"
value="new"
className="w-[20px] h-[20px] cursor-pointer"
checked={taskType == "new"}
onChange={switchTaskType}
/>
<span className="text-lg tracking-wide font-semibold">New Task</span>
</div>
</div>
{/* Task Type === select */}
{taskType == "select" && (
<div className="p-4 w-full h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
{jobList?.data?.length ? (
jobList?.data?.map((item, index) => (
<div
key={item.job_uid}
className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer"
onClick={() => handleActiveTask(item.job_uid, item)}
>
<input
type="radio"
name="task-list"
checked={
activeTask.id == item.job_uid ||
(activeTask.id == index && true)
}
onChange={() =>
handleActiveTask(item.job_uid, item)
}
className="w-[15px] h-[15px] cursor-pointer"
/>
<p className="w-full text-dark-gray dark:text-white tracking-wide">
{item?.title}
</p>
</div>
))
) : (
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center cursor-default">
No Task found!
</p>
)}
</div>
)}
{taskType == "new" && (
<div className="p-4 w-full h-full">
<NewTasks
formState={formState}
setFormState={setFormState}
/>
</div>
)}
</div>
{/*Right Hand Side for details && Task Type === select */}
{taskType == "select" && (
<>
{jobList?.data?.length > 0 ? (
<div className="p-4 pt-0 h-full">
<div className="w-full">
<p className="text-lg font-bold text-dark-gray dark:text-white tracking-wide border-b-2">
{activeTask?.data?.title}
</p>
{/* <div className="my-3">
<Detail
label="Description"
value={activeTask?.data?.description}
/>
</div> */}
<div className="my-3 w-full">
<label className="job-label">
Description
</label>
<p className="p-1 text-sm text-slate-900 dark:text-white">
{activeTask?.data?.description}
</p>
</div>
<div className="grid grid-cols-2">
<div className="w-full">
<div className="my-3 w-full flex items-center gap-1">
<label className="job-label">
Reward
</label>
<p className="p-1 text-sm text-slate-900 dark:text-white">
{PriceFormatter(
activeTask?.data?.price * 0.01,
activeTask?.data?.currency,
activeTask?.data?.curreny_code
)}
</p>
</div>
<div className="my-3 w-full flex items-center gap-1">
<label className="job-label">
Timeline
</label>
<p className="p-1 text-sm text-slate-900 dark:text-white">{`${activeTask?.data?.timeline_days} day(s)`}</p>
</div>
</div>
<div className="w-full flex items-center justify-center">
<div className="w-28 h-28 rounded-2xl flex items-center justify-center">
<img
className="w-full h-auto"
loading="lazy"
src={imageSrc}
alt='job image'
/>
</div>
</div>
</div>
{/* Dummy, no value found for created! thus commented*/}
{/* <div className="my-3 sm:flex items-center">
<Detail
label="Created"
value={`Dummy, no value found for created!`}
/>
</div> */}
<div className="my-3">
<label className="w-full job-label">
Delivery Detail
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
value={activeTask?.data?.job_detail}
readOnly
// onChange={handleInputChange}
/>
</div>
</div>
</div>
) : (
<></>
)}
</>
)}
</div>
{/* BTN */}
<div className="modal-footer-wrapper">
{/* error or success display */}
<div className="w-auto h-auto flex items-center">
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px] self-start`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-2 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
<div className="w-auto h-auto flex items-center gap-20">
<button
disabled={requestStatus.loading}
onClick={()=>closeModal()}
type="button"
className="custom-btn border-gradient"
>
<span className="text-gradient">Close</span>
</button>
<div className="">
{requestStatus.loading ? (
<LoadingSpinner color="sky-blue" size="8" />
) : (
<button
type="button"
disabled={requestStatus.loading}
onClick={assignFamilyTask}
className="custom-btn btn-gradient text-white"
>
Assign
</button>
)
// : (
// <button
// type="button"
// disabled={requestStatus.loading}
// onClick={assignFamilyTask}
// className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
// >
// {details
// ? `Assign task to ${details?.firstname}`
// : familyDetailsData
// ? `Assign task to ${familyDetailsData.firstname}`
// : "Assign"}
// </button>
// )
}
</div>
</div>
</div>
</>
)
}
</>
)
}
@@ -9,18 +9,20 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
import Detail from "../../jobPopout/popoutcomponent/Detail";
import { NewTasks } from "./forms";
import { SocketValues } from "../../Contexts/SocketIOContext";
import { errorMsg } from "../../../lib/errorMsg";
import AssignPrevNewTask from "./AssignPrevNewTask";
import AssignMediaTask from "./AssignMediaTask";
const AssignTaskPopout = ({
action,
details,
situation,
familyDetailsData,
familyTask,
jobList,
activeTask,
setActiveTask,
setUpdatePage,
assignTaskChecker,
setUpdatePage,
}) => {
const {parentAssignJobToKid} = SocketValues()
@@ -53,6 +55,21 @@ const AssignTaskPopout = ({
message: "",
}); // HOLDS RESPONSE FOR SENDING API REQUEST
let [commonMedia, setCommonMedia] = useState({loading: true, data: [], image: ''}) // HOLDS COMMON MEDIA DATA
let [activeMedia, setActiveMedia] = useState({}) // HOLDS ACTIVE COMMON MEDIA DATA
const handleActiveMedia = (data = {}) => {
// FUNCTION TO CHANGE SELECTED ACTIVE MEDIA
setActiveMedia({...data});
};
let [assignType, setAssignType] = useState("task"); // SWITCHES BTW TASK AND MEDIA ASSIGNMENT
const switchAssignType = ({ target: { name } }) => {
// FUNCTION TO CHANGE ASSIGN TASK TYPE
setAssignType(name);
};
let [taskType, setTaskType] = useState(details ? "new" : "select"); // SWITCHES BTW SELECT TASK AND NEW TASK
const switchTaskType = ({ target: { value } }) => {
@@ -89,13 +106,13 @@ const AssignTaskPopout = ({
}
let reqData = {};
if (taskType == "select") {
if (taskType == "select" && assignType == 'task') {
// RUNS HERE IF TASK TYPE IS SELECT
if (!Object.keys(activeTask.data).length) {
setRequestStatus({
loading: false,
status: false,
message: "No Task is seleted",
message: "No Task is selected",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
@@ -113,7 +130,7 @@ const AssignTaskPopout = ({
};
}
if (taskType === "new") {
if (taskType === "new" && assignType == 'task') {
const {
banner,
category,
@@ -172,10 +189,13 @@ const AssignTaskPopout = ({
.assignFamilyTask(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
let error = errorMsg[res?.data?.error_msg] || ''
setRequestStatus({
loading: false,
status: false,
message: "failed to assign task",
message: error? error : "failed to assign task",
});
return setTimeout(() => {
@@ -187,7 +207,7 @@ const AssignTaskPopout = ({
setRequestStatus({
loading: false,
status: true,
message: "action successful",
message: "Task Assigned successfully",
});
setUpdatePage(prev => !prev); // Updates family task page by calling the useeffect hook
@@ -221,10 +241,43 @@ const AssignTaskPopout = ({
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
};
let imageSrc = (localStorage.getItem("session_token")
? `${userDetails?.session_image_server}${localStorage.getItem("session_token")}/job/${activeTask.data.job_uid}` : ""); // FOR GETTING JOB IMAGE
const closeModal = () => { // FOR CLOSING ASSIGN TASK MODAL
action()
}
const assignMediaTask = (values, helpers) => { // FUNCTION TO HANDLE ASSIGNING MEDIA TASK
setRequestStatus({ loading: true, status: false, message: "" });
if(!selectedFamilyUid){ // If no family found, throw error
setRequestStatus({ loading: false, status: false, message: "Please Select a Kid" });
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 3000);
}
let reqData = {...values, assign_mode:'110012', family_uid:selectedFamilyUid, media_uid:activeMedia.uid, amount:values.amount * 100}
apiCall.parentAssignMediaTask(reqData).then(res => { // API CALL TO ASSIGN MEDIA TASK
if(res.status != 200 || res.data.internal_return < 0){
setRequestStatus({ loading: false, status: false, message: "Failed to Assign Task" });
return setTimeout(()=>{
setRequestStatus({ loading: false, status: false, message: "" });
}, 3000)
}
setRequestStatus({ loading: false, status: true, message: "Task Assigned Successfully" });
return setTimeout(()=>{
setRequestStatus({ loading: false, status: false, message: "" });
closeModal() // FOR CLOSING ASSIGN MODAL
}, 3000)
}).catch(err => {
setRequestStatus({ loading: false, status: false, message: "Failed, something went wrong. Try Again" });
return setTimeout(()=>{
setRequestStatus({ loading: false, status: false, message: "" });
}, 3000)
})
}
useEffect(()=>{ // effect to update family UID when components mounts
if(familyDetailsData?.uid){
@@ -236,6 +289,15 @@ const AssignTaskPopout = ({
}
},[])
useEffect(()=>{
apiCall.getParentCommonMedia().then((res)=>{
// console.log('RESPONSE', res)
setCommonMedia({loading: false, data: res?.data?.result, image: ''})
setActiveMedia(res?.data?.result[0])
}).catch(err => {
setCommonMedia({loading: false, data: [], image: ''})
})
},[])
return (
<>
@@ -293,230 +355,52 @@ const AssignTaskPopout = ({
</svg>
</button>
</div>
{familyTask?.loading ? (
<div className="h-[100px] w-full flex justify-center items-center">
<LoadingSpinner color="sky-blue" size="16" />
</div>
) : (
<>
<div
className={`job-action-modal-body w-full md:grid ${
taskType !== "new" ? "md:grid-cols-2" : "md:grid-cols-1"
}`}
<div className="modal-body">
<div className="px-4 py-2 w-full flex items-center gap-4">
<button
name='task'
className={`py-1 px-2 font-medium bg-transparent border border-purple text-purple transition-all rounded-md duration-300 ${assignType=='task' && 'bg-yellow-500'}`}
onClick={switchAssignType}
disabled={requestStatus.loading}
>
<div className="p-4">
<div className="mb-2 w-full flex items-center gap-4">
<div className="flex items-center gap-2 text-sky-blue text-base">
<input
type="radio"
name="task-type"
value="select"
className="w-[20px] h-[20px] cursor-pointer"
checked={taskType == "select"}
onChange={switchTaskType}
/>
<span>Select Task</span>
</div>
<div className="flex items-center gap-2 text-sky-blue text-base">
<input
type="radio"
name="task-type"
value="new"
className="w-[20px] h-[20px] cursor-pointer"
checked={taskType == "new"}
onChange={switchTaskType}
/>
<span>New Task</span>
</div>
</div>
{/* Task Type === select */}
{taskType == "select" && (
<div className="p-4 w-full h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
{familyTask?.data?.length ? (
familyTask?.data?.map((item, index) => (
<div
key={item.job_uid}
className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer"
onClick={() => handleActiveTask(item.job_uid, item)}
>
<input
type="radio"
name="task-list"
checked={
activeTask.id == item.job_uid ||
(activeTask.id == index && true)
}
onChange={() =>
handleActiveTask(item.job_uid, item)
}
className="w-[15px] h-[15px] cursor-pointer"
/>
<p className="w-full text-dark-gray dark:text-white tracking-wide">
{item?.title}
</p>
</div>
))
) : (
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center cursor-default">
No Task found!
</p>
)}
</div>
)}
{taskType == "new" && (
<div className="p-4 w-full h-[400px]">
<NewTasks
formState={formState}
setFormState={setFormState}
/>
</div>
)}
</div>
{/*Right Hand Side for details && Task Type === select */}
{taskType == "select" && (
<>
{familyTask?.data?.length > 0 ? (
<div className="p-4">
<div className="w-full">
<p className="text-lg font-bold text-dark-gray dark:text-white tracking-wide border-b-2">
{activeTask?.data?.title}
</p>
<div className="my-3">
<Detail
label="Description"
value={activeTask?.data?.description}
/>
</div>
<div className="grid grid-cols-2">
<div className="w-full">
<div className="my-3 w-full flex items-center gap-1">
<label className="job-label">
Price
</label>
<p className="p-1 text-sm text-slate-900 dark:text-white">
{PriceFormatter(
activeTask?.data?.price * 0.01,
activeTask?.data?.currency,
activeTask?.data?.curreny_code
)}
</p>
</div>
<div className="my-3 w-full flex items-center gap-1">
<label className="job-label">
Timeline
</label>
<p className="p-1 text-sm text-slate-900 dark:text-white">{`${activeTask?.data?.timeline_days} day(s)`}</p>
</div>
</div>
<div className="w-full flex items-center justify-center">
<div className="w-28 h-28 rounded-2xl flex items-center justify-center">
<img
className="w-full h-auto"
loading="lazy"
src={imageSrc}
alt='job image'
/>
</div>
</div>
</div>
{/* Dummy, no value found for created! thus commented*/}
{/* <div className="my-3 sm:flex items-center">
<Detail
label="Created"
value={`Dummy, no value found for created!`}
/>
</div> */}
<div className="my-3">
<label className="w-full job-label">
Delivery Detail
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
value={activeTask?.data?.job_detail}
readOnly
// onChange={handleInputChange}
/>
</div>
</div>
</div>
) : (
<></>
)}
</>
)}
</div>
{/* BTN */}
<div className="modal-footer-wrapper">
{/* error or success display */}
<div className="w-auto h-auto flex items-center">
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px] self-start`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-2 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
<div className="w-auto h-auto flex items-center gap-20">
<button
disabled={requestStatus.loading}
onClick={action}
type="button"
className="custom-btn border-gradient"
>
<span className="text-gradient">Close</span>
</button>
<div className="">
{requestStatus.loading ? (
<LoadingSpinner color="sky-blue" size="8" />
) : (
<button
type="button"
disabled={requestStatus.loading}
onClick={assignFamilyTask}
className="custom-btn btn-gradient text-white"
>
Assign
</button>
)
// : (
// <button
// type="button"
// disabled={requestStatus.loading}
// onClick={assignFamilyTask}
// className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
// >
// {details
// ? `Assign task to ${details?.firstname}`
// : familyDetailsData
// ? `Assign task to ${familyDetailsData.firstname}`
// : "Assign"}
// </button>
// )
}
</div>
</div>
</div>
</>
)}
Task
</button>
<button
name='media'
className={`py-1 px-2 font-medium bg-transparent border border-purple text-purple transition-all rounded-md duration-300 ${assignType=='media' && 'bg-yellow-500'}`}
onClick={switchAssignType}
disabled={requestStatus.loading}
>
Media
</button>
</div>
<div className="">
{assignType == 'task' ?
<AssignPrevNewTask
jobList={jobList}
requestStatus={requestStatus}
assignFamilyTask={assignFamilyTask}
taskType={taskType}
switchTaskType={switchTaskType}
formState={formState}
setFormState={setFormState}
activeTask={activeTask}
handleActiveTask={handleActiveTask}
closeModal={closeModal}
/>
:
<AssignMediaTask
commonMedia={commonMedia}
requestStatus={requestStatus}
assignMediaTask={assignMediaTask}
activeMedia={activeMedia}
handleActiveMedia={handleActiveMedia}
closeModal={closeModal}
family_uid = {selectedFamilyUid}
/>
}
</div>
</div>
</div>
</ModalCom>
</>
@@ -1,13 +1,17 @@
import React, { useEffect, useState } from "react";
import usersService from "../../../../services/UsersService";
import InputCom from "../../../Helpers/Inputs/InputCom";
import { useSelector } from "react-redux";
export default function NewTasks({ formState, setFormState }) {
let [currency, setCurrency] = useState({
loading: true,
status: false,
data: null,
});
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
// let [currency, setCurrency] = useState({
// loading: true,
// status: false,
// data: null,
// });
const selectImage = require(`../../../../assets/images/taskbanners/${
formState.banner || "default.jpg"
@@ -15,25 +19,25 @@ export default function NewTasks({ formState, setFormState }) {
const ApiCall = new usersService();
// FUNCTION TO GET Currency
const getUserCurrency = () => {
setCurrency((prev) => ({ ...prev, loading: true }));
ApiCall.getUserWallets()
.then((res) => {
if (res.data.internal_return < 0) {
setCurrency({ loading: false, status: true, data: [] });
return;
}
// const getUserCurrency = () => {
// setCurrency((prev) => ({ ...prev, loading: true }));
// ApiCall.getUserWallets()
// .then((res) => {
// if (res.data.internal_return < 0) {
// setCurrency({ loading: false, status: true, data: [] });
// return;
// }
setCurrency({
loading: false,
status: true,
data: res.data.result_list,
});
})
.catch((err) => {
setCurrency({ loading: false, status: false, data: [] });
});
};
// setCurrency({
// loading: false,
// status: true,
// data: res.data.result_list,
// });
// })
// .catch((err) => {
// setCurrency({ loading: false, status: false, data: [] });
// });
// };
const handleInputChange = (event) => {
const { name, value } = event.target;
@@ -43,17 +47,97 @@ export default function NewTasks({ formState, setFormState }) {
}));
};
useEffect(() => {
getUserCurrency();
}, []);
// useEffect(() => {
// getUserCurrency();
// }, []);
return (
<form className="w-full flex justify-between items-start">
<div className="flex flex-col gap-3 max-w-[77%]">
<div className="w-full block sm:grid grid-cols-3 gap-2">
<div className="w-full flex flex-col gap-2 col-span-2">
{/* Title */}
<div className="field w-full">
<label htmlFor="title" className="job-label">Title</label>
<InputCom
fieldClass="px-6"
// label="Title"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="title"
value={formState.title}
inputHandler={handleInputChange}
// blurHandler={props.handleBlur}
// error={props.errors.title && props.touched.title && props.errors.title}
/>
</div>
{/* Description */}
{/* <div className="field w-full mb-[5px]">
<label htmlFor="description" className="job-label">Description</label>
<InputCom
fieldClass="px-6"
// label="Description"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="description"
value={formState.description}
inputHandler={handleInputChange}
// blurHandler={props.handleBlur}
// error={props.errors.description && props.touched.description && props.errors.description}
/>
</div> */}
<div className="field flex flex-col sm:flex-row w-full gap-2">
<div className="w-full">
<label
htmlFor="description"
className='job-label'
>
Description
</label>
<textarea
id="description"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`}
style={{ resize: "none" }}
name="description"
value={formState.description}
onChange={handleInputChange}
// onBlur={props.handleBlur}
/>
</div>
</div>
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full gap-2">
<div className="w-full">
<label
htmlFor="Job Delivery Details"
className='job-label'
>
Job Delivery Details
{/* {props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>} */}
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`}
style={{ resize: "none" }}
name="job_detail"
value={formState.job_detail}
onChange={handleInputChange}
// onBlur={props.handleBlur}
/>
</div>
</div>
</div>
{/* inputs starts here */}
<div className="grid md:grid-cols-3 grid-cols-1 gap-6 mb-[5px]">
<div className="w-full flex flex-col gap-2">
{/* Currency */}
<div className="field w-full mb-6 xl:mb-0">
<div className="field w-full">
<label
htmlFor="country"
className="job-label"
@@ -65,26 +149,26 @@ export default function NewTasks({ formState, setFormState }) {
id="country"
name="country"
value={formState.country}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={handleInputChange}
// onBlur={props.handleBlur}
>
{currency?.loading ? (
{walletDetails?.loading ? (
<option className="text-slate-500 text-[13.975px]" value="">
Loading...
</option>
) : currency.data.length ? (
) : walletDetails.data.length ? (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Currency
</option>
{currency.data?.map((item, index) => (
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.description}
{item?.code}
</option>
))}
</>
@@ -115,7 +199,7 @@ export default function NewTasks({ formState, setFormState }) {
</div>
{/* Duration */}
<div className="field w-full mb-6 xl:mb-0">
<div className="field w-full">
<label
htmlFor="timeline_days"
className="job-label"
@@ -127,7 +211,7 @@ export default function NewTasks({ formState, setFormState }) {
id="timeline_days"
name="timeline_days"
value={formState.timeline_days}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={handleInputChange}
// onBlur={props.handleBlur}
>
@@ -138,6 +222,7 @@ export default function NewTasks({ formState, setFormState }) {
</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-[13.975px]"
value={duration}
>
@@ -148,74 +233,19 @@ export default function NewTasks({ formState, setFormState }) {
)}
</select>
</div>
</div>
{/* Title */}
<div className="field w-full mb-[5px]">
<label htmlFor="title" className="job-label">Title</label>
<InputCom
fieldClass="px-6"
// label="Title"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="title"
value={formState.title}
inputHandler={handleInputChange}
// blurHandler={props.handleBlur}
// error={props.errors.title && props.touched.title && props.errors.title}
/>
</div>
{/* Description */}
<div className="field w-full mb-[5px]">
<label htmlFor="description" className="job-label">Description</label>
<InputCom
fieldClass="px-6"
// label="Description"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="description"
value={formState.description}
inputHandler={handleInputChange}
// blurHandler={props.handleBlur}
// error={props.errors.description && props.touched.description && props.errors.description}
/>
</div>
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
{/* Banner Image */}
<div className="w-full">
<label
htmlFor="Job Delivery Details"
className='job-label'
>
Job Delivery Details
{/* {props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>} */}
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`}
style={{ resize: "none" }}
name="job_detail"
value={formState.job_detail}
onChange={handleInputChange}
// onBlur={props.handleBlur}
/>
<div className="h-32 w-full">
<img
src={selectImage}
alt="task_banner_img"
className="w-full h-full object-contain"
/>
</div>
</div>
</div>
</div>
{/* Banner Image */}
<div className="max-w-[20%] w-full">
<div className="h-32 w-full">
<img
src={selectImage}
alt="task_banner_img"
className="w-full h-full object-contain"
/>
</div>
</div>
</form>
);
+78 -128
View File
@@ -13,59 +13,42 @@ const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending"));
export default function FamilyTableNew() {
const { parentFamilyTaskList } = useSelector((state) => state.tableReload);
console.log('parentFamilyTaskList', parentFamilyTaskList)
const { jobListTable, pendingListTable, parentFamilyTaskList } = useSelector((state) => state.tableReload); // TABLE RELOAD TRIGGERS
let { pathname } = useLocation();
// Initial state for family details
const initialDetailState = {
loading: true,
data: null,
link: "",
loading: false,
data: [],
};
const [assignTaskChecker, setAssignTaskChecker] = useState(false);
// console.log('accountDetails',accountDetails)
// State for family details, tasks, waitlist, and pending
const [details, setDetails] = useState({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
let [familyTasks, setFamilyTasks] = useState({...initialDetailState})
// Function to reset family details, tasks, waitlist, and pending
const resetDetails = () => {
setDetails({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
};
let [familyPending, setFamilyPending] = useState({...initialDetailState})
let [familyWaitList, setFamilyWaitList] = useState({...initialDetailState})
const [updatePage, setUpdatePage] = useState(false); // State to determine when to update the page
// State for family task data
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
// State for list of created jobs by FULL USER
const [jobList, setJobList] = useState({ loading: false, data: [] });
// State for active task
// State for active/selected job
const [activeTask, setActiveTask] = useState({ id: 0, data: {} });
// State for error messages
const [errMsg, setErrMsg] = useState("");
// State for family task popout
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
const [assignTaskPopout, setAssignTaskPopout] = useState(false);
// Create an instance of the usersService class
const apiCall = useMemo(() => new usersService(), []);
// Function to handle toggling the family task popout
const familyPopUpHandler = () => {
setFamilyTaskPopout((prev) => !prev);
const familyAssignPopUpHandler = () => {
setAssignTaskPopout((prev) => !prev);
};
// Array of tab names
@@ -87,26 +70,19 @@ export default function FamilyTableNew() {
const tabComponents = {
Tasks: (
<FamilyTasks
image_link={details.familyTasks.link}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
action={familyPopUpHandler}
setAssignTaskChecker={setAssignTaskChecker}
familyData={familyTasks}
action={familyAssignPopUpHandler}
/>
),
Waiting: (
<FamilyWaitlist
image_link={details.familyWaitList.link}
familyData={details.familyWaitList.data}
loader={details.familyWaitList.loading}
familyData={familyWaitList}
setUpdatePage={setUpdatePage}
/>
),
Pending: (
<FamilyPending
image_link={details.familyPending.link}
familyData={details.familyPending.data}
loader={details.familyPending.loading}
familyData={familyPending}
/>
),
};
@@ -116,83 +92,66 @@ export default function FamilyTableNew() {
// Selected tab component based on the current 'tab'
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
// Effect to manage family details and related data
// Effect to manage active family task details
useEffect(() => {
const manageFamily = async () => {
const manageTasks = async () => {
setFamilyTasks({loading:true, data: []})
try {
// resetDetails();
// setDetails({
// familyTasks: { loading: true },
// familyWaitList: { loading: true },
// familyPending: { loading: true },
// });
// const { family_uid } = accountDetails;
// const reqData = { family_uid };
const [familyTasksData, familyWaitingRes, familyPendingRes] =
await Promise.all([
apiCall.getMyActiveJobList(),
apiCall.ManageFamilyNewWaitlist(),
apiCall.ManageFamilyPending(),
]);
let tasksData = familyTasksData?.data?.result_list;
let _familyWaitData = familyWaitingRes?.data?.result_list;
let familyPendingData = familyPendingRes?.data?.result_list;
// Getting the image server link
let imageServerLink = familyWaitingRes.data?.session_image_server;
// Function to check for errors in data
const checkDataError = (data) => data?.internal_return < 0;
if (
checkDataError(tasksData) ||
checkDataError(_familyWaitData) ||
checkDataError(familyPendingData)
) {
return;
const response = await apiCall.getMyActiveJobList()
if(response.status != 200 || !response?.data){
return setFamilyTasks({loading:false, data: []})
}
setDetails({
familyTasks: {
loading: false,
data: tasksData,
link: imageServerLink,
},
familyWaitList: {
loading: false,
data: _familyWaitData,
link: imageServerLink,
},
familyPending: {
loading: false,
data: familyPendingData,
link: imageServerLink,
},
});
setFamilyTasks({loading:false, data: response?.data})
} catch (error) {
// resetDetails();
setDetails({
familyDetails: { ...initialDetailState, loading: false, },
familyTasks: { ...initialDetailState, loading: false, },
familyWaitList: { ...initialDetailState, loading: false,},
familyPending: { ...initialDetailState, loading: false, },
})
setErrMsg("An error occurred");
throw new Error(error);
setFamilyTasks({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamily();
manageTasks();
}, [updatePage, parentFamilyTaskList]);
// Effect to manage family tasks
// Effect to manage family wait task details
useEffect(() => {
const manageFamilyWaitlist = async () => {
setFamilyWaitList({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyWaitlist()
if(response.status != 200 || !response?.data){
return setFamilyWaitList({loading:false, data: []})
}
setFamilyWaitList({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyWaitList({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyWaitlist();
}, [updatePage]);
// Effect to manage family pending task details
useEffect(() => {
const manageFamilyPending = async () => {
setFamilyPending({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyPending()
if(response.status != 200 || !response?.data){
return setFamilyPending({loading:false, data: []})
}
setFamilyPending({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyPending({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyPending();
}, [updatePage, pendingListTable]);
// Effect to get all parent job list
useEffect(() => {
let checkFamilyTask = true;
const reqData = {
limit: 30,
offset: 0,
@@ -200,12 +159,11 @@ export default function FamilyTableNew() {
action: apiConst.WRENCHBOARD_PICTURE_FAMMEMBER,
};
if (checkFamilyTask) {
setFamilyTask({ loading: true });
setJobList({ loading: true });
apiCall
.getMyJobList(reqData)
.then((res) => {
setFamilyTask({ loading: false, data: res?.data?.result_list });
setJobList({ loading: false, data: res?.data?.result_list });
if (res?.data?.result_list?.length) {
setActiveTask((prev) => ({
...prev,
@@ -214,15 +172,9 @@ export default function FamilyTableNew() {
}
})
.catch((err) => {
setFamilyTask({ loading: false, data: [] });
setJobList({ loading: false, data: [] });
console.log("Error", err);
});
}
// Cleanup function to prevent memory leaks
return () => {
checkFamilyTask = false;
};
}, []);
// console.log(updatePage);
@@ -260,7 +212,7 @@ export default function FamilyTableNew() {
</ul>
<button
type="button"
onClick={familyPopUpHandler}
onClick={familyAssignPopUpHandler}
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add task
@@ -282,20 +234,18 @@ export default function FamilyTableNew() {
</Suspense>
</div>
{familyTaskPopout && (
{assignTaskPopout && (
<AssignTaskPopout
action={familyPopUpHandler}
situation={familyTaskPopout}
familyTask={familyTask}
setFamilyTask={setFamilyTask}
action={familyAssignPopUpHandler}
situation={assignTaskPopout}
jobList={jobList}
setActiveTask={setActiveTask}
activeTask={activeTask}
familyDetailsData={''}
setUpdatePage={setUpdatePage}
// updateFamilyPendingTable={updateFamilyPendingTable}
pathname={pathname}
assignTaskChecker={assignTaskChecker}
/>
)}
</div>
);
}
@@ -3,7 +3,7 @@ import QRCode from "react-qr-code";
import { useSelector } from "react-redux";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, ref) => {
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint}, ref) => {
const { userDetails } = useSelector((state) => state.userDetails);
return (
<div
@@ -16,13 +16,13 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, re
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
{familyData?.data?.username ? familyData?.data?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
{familyData?.data?.pin ? familyData?.data?.pin : "please wait..."}
</span>
</h2>
</div>
@@ -35,7 +35,7 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, re
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
{loader ?
{familyData.loading ?
<div className="w-full">
<LoadingSpinner size='8' color='sky-blue' />
</div>
@@ -44,7 +44,7 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, re
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
// value={`https://www.google.com`}
value={`${userDetails?.uid}@${familyData?.username}@${familyData?.uid}`}
value={`${userDetails?.uid}@${familyData?.data?.username}@${familyData?.data?.uid}`}
viewBox={`0 0 256 256`}
/>
}
@@ -2,13 +2,14 @@ import { useMemo, useState } from "react";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyPending({ familyData, image_link, loader }) {
export default function FamilyPending({ familyData }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let filteredFamilyData = useMemo(
() => familyData?.filter((data) => data.family_uid !== ""),
[familyData]
() => familyData?.data?.result_list?.filter((data) => data.family_uid !== ""),
[familyData?.data?.result_list]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -25,13 +26,18 @@ export default function FamilyPending({ familyData, image_link, loader }) {
handlePagingFunc(e, setCurrentPage);
};
console.log(image_link);
return (
<div
className={`update-table w-full p-3 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px]`}
>
{familyData && (
{familyData.loading ?
(<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
):
<>
{familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
@@ -45,7 +51,7 @@ export default function FamilyPending({ familyData, image_link, loader }) {
value?.currency_code,
value?.currency
);
let image = `${image_link}${localStorage.getItem(
let image = `${familyData?.data?.session_image_server}${localStorage.getItem(
"session_token"
)}/job/${value.job_uid}`;
return (
@@ -137,7 +143,8 @@ export default function FamilyPending({ familyData, image_link, loader }) {
{/* END OF PAGINATION BUTTON */}
</div>
)}
</>
}
{/* Active Job Popout */}
{jobPopout.show && (
<PendingJobsPopout
@@ -9,17 +9,15 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyNewTasks({
familyData,
className,
loader,
action,
image_link,
}) {
let navigate = useNavigate();
let { pathname } = useLocation();
// ...
let filteredFamilyData = useMemo(
() => familyData?.filter((data) => data.family_uid !== ""),
[familyData]
() => familyData?.data?.result_list?.filter((data) => data.family_uid !== ""),
[familyData?.data?.result_list]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -36,22 +34,22 @@ export default function FamilyNewTasks({
return (
<div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] overflow-hidden rounded-2xl section-shadow p-3 ${
familyData?.length <= 0 && "flex items-center justify-center"
familyData?.data?.result_list?.length <= 0 && "flex items-center justify-center"
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
{familyData && (
{familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{familyData?.length <= 0 ? (
{familyData?.data?.result_list?.length <= 0 ? (
<tr>
<td
colSpan="2"
@@ -76,7 +74,7 @@ export default function FamilyNewTasks({
value?.currency_code,
value?.currency
);
let image = `${image_link}${localStorage.getItem(
let image = `${familyData?.data?.result_list}${localStorage.getItem(
"session_token"
)}/job/${value.job_uid}`;
return (
@@ -8,8 +8,6 @@ import Icons from "../../Helpers/Icons";
const FamilyNewWaitlist = ({
familyData,
className,
accountDetails,
loader,
setUpdatePage
}) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
@@ -22,7 +20,7 @@ const FamilyNewWaitlist = ({
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = currentPage;
const indexOfLastItem = currentPage + itemsPerPage;
const currentTask = familyData?.slice(
const currentTask = familyData?.data?.result_list?.slice(
indexOfFirstItem,
indexOfLastItem
);
@@ -53,13 +51,13 @@ const FamilyNewWaitlist = ({
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
{familyData && (
{familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
@@ -69,7 +67,7 @@ const FamilyNewWaitlist = ({
value?.banner || "default.jpg"
}`);
// console.log("VALUE", value);
// let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
// let image = `${familyData?.data?.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
@@ -121,8 +119,8 @@ const FamilyNewWaitlist = ({
<PaginatedList
onClick={handlePagination}
prev={currentPage === 0}
next={currentPage + itemsPerPage >= familyData?.length}
data={familyData}
next={currentPage + itemsPerPage >= familyData?.data?.result_list?.length}
data={familyData?.data?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
@@ -3,21 +3,23 @@ import localImgLoad from "../../../lib/localImgLoad";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyPending({
familyData,
className,
accountDetails,
loader,
setUpdatePage,
}) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
familyData?.data?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[accountDetails?.family_uid, familyData?.result_list]
[accountDetails?.family_uid, familyData?.data?.result_list]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -40,6 +42,12 @@ export default function FamilyPending({
className || ""
}`}
>
{familyData.loading ?
(<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
):
<>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
@@ -54,7 +62,7 @@ export default function FamilyPending({
value?.currency_code,
value?.currency
);
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
let image = `${familyData.data.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -144,6 +152,8 @@ export default function FamilyPending({
{/* END OF PAGINATION BUTTON */}
</div>
)}
</>
}
{/* Active Job Popout */}
{jobPopout.show && (
@@ -151,6 +161,7 @@ export default function FamilyPending({
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
setUpdatePage(prev => !prev);
}}
situation={jobPopout.show}
/>
+13 -14
View File
@@ -10,7 +10,6 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyTasks({
familyData,
className,
loader,
accountDetails,
}) {
let navigate = useNavigate();
@@ -19,17 +18,17 @@ export default function FamilyTasks({
// ...
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
familyData?.data?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
[familyData?.data, accountDetails]
);
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentTask = familyData?.result_list.slice(
const currentTask = familyData?.data?.result_list?.slice(
indexOfFirstItem,
indexOfLastItem
);
@@ -43,21 +42,21 @@ export default function FamilyTasks({
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
{familyData && familyData?.result_list && (
{familyData?.data && familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{familyData &&
familyData?.result_list &&
familyData.result_list.length > 0 ? (
{familyData?.data &&
familyData?.data?.result_list &&
familyData?.data.result_list.length > 0 ? (
currentTask.map((value, index) => {
// find due date
const dueDate = value?.delivery_date.split(" ")[0];
@@ -67,7 +66,7 @@ export default function FamilyTasks({
value?.currency_code,
value?.currency
);
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
let image = `${familyData?.data?.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -149,11 +148,11 @@ export default function FamilyTasks({
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familyData?.result_list.length
familyData?.data?.result_list.length
? true
: false
}
data={familyData?.result_list}
data={familyData?.data?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
@@ -5,7 +5,7 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
const FamilyWaitlist = memo(
({ familyData, className, accountDetails, loader, setUpdatePage }) => {
({ familyData, className, accountDetails, setUpdatePage }) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
const [continueTaskPopup, setContinueTaskPopup] = useState({
show: false,
@@ -13,10 +13,10 @@ const FamilyWaitlist = memo(
});
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
familyData?.data?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
[familyData.data, accountDetails]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -52,9 +52,9 @@ const FamilyWaitlist = memo(
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
@@ -67,8 +67,7 @@ const FamilyWaitlist = memo(
const selectedImage = require(`../../../assets/images/family/${
value?.banner || "default.jpg"
}`);
console.log('VALUE', value)
// let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
// let image = `${familyData.data.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
@@ -17,8 +17,6 @@ function FamilyWallet({familyData}) {
setFamilyWallet({loading:true, data: []})
apiUrl.getKidWallets({family_uid:familyData?.uid}).then(res => {
setFamilyWallet({loading:false, data: res?.data?.result_list || []})
console.log('familyData', familyData, res?.data?.result_list)
}).catch(error => {
setFamilyWallet({loading:false, data: []})
})
@@ -80,8 +80,6 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
}
};
console.log(details);
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lw-[90%] md:w-[48rem] min-h-[500px] bg-white dark:bg-dark-white lg:rounded-2xl">
+1 -1
View File
@@ -7,7 +7,7 @@ function DataIteration(props) {
{datas &&
datas?.length >= endLength &&
datas?.slice(startLength, endLength)
.map((value) => children({ datas: value }))}
.map((value, index) => children({ datas: value, index }))}
</>
);
}
+47 -7
View File
@@ -5,6 +5,7 @@ import AvailableJobsCard from "../Cards/AvailableJobsCard";
import DataIteration from "../Helpers/DataIteration";
import SelectBox from "../Helpers/SelectBox";
import NewPaginatedList from "../Pagination/NewPaginatedList";
import InfiniteScroll from "../infiniteScroll/InfiniteScroll";
export default function MainSection({
className,
@@ -96,7 +97,9 @@ export default function MainSection({
</div>
{/* end of contentDisplay toggler */}
</div>
<div className="filter-navigate-content w-full min-h-screen">
{/* OLD MARKET JOB LISTING */}
{/* <div className="filter-navigate-content w-full min-h-screen">
<div
className={
contentDisplay == "grid"
@@ -109,8 +112,8 @@ export default function MainSection({
startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products?.length}
>
{({ datas }) => (
<div key={datas.job_uid}>
{({ datas, index }) => (
<div key={datas.job_uid+index}>
<AvailableJobsCard
contentDisplay={contentDisplay}
image_server={image_server}
@@ -120,11 +123,13 @@ export default function MainSection({
)}
</DataIteration>
</div>
</div>
{/* {products?.length &&
</div> */}
{/* END OF OLD MARKET JOB LISTING */}
{products?.length ?
<NewPaginatedList
data={products}
itemsPerPage={6}
itemsPerPage={9}
filterItem=''
tableTitle=''
>
@@ -154,7 +159,42 @@ export default function MainSection({
)
}
</NewPaginatedList>
} */}
// <InfiniteScroll
// allData={products}
// addItemBy={3}
// intialItemsToShow={9}
// >
// {
// ({dataToShow})=>(
// <div className="filter-navigate-content w-full min-h-[600px]">
// <div
// className={
// contentDisplay == "grid"
// ? "grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]"
// : "w-full"
// }
// >
// {
// dataToShow.map((datum, index) => (
// <div key={datum.job_uid+index}>
// <AvailableJobsCard
// contentDisplay={contentDisplay}
// image_server={image_server}
// datas={datum}
// />
// </div>
// ))
// }
// </div>
// </div>
// )
// }
// </InfiniteScroll>
:
<div className="w-full h-[40rem] bg-white dark:bg-dark-white flex justify-center items-center">
No Jobs Found!
</div>
}
</div>
</div>
);
@@ -16,6 +16,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
"offer_code": details?.offer_code,
"offer_uid": details?.offer_uid,
"job_uid": details?.job_uid,
"market_uid": details?.market_uid
}
let room = `INTEREST-${details?.market_uid}`
sendJobInterestToOwner(message, room)
+7
View File
@@ -3,6 +3,7 @@ import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead";
import MainSection from "./MainSection";
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function MarketPlace({ commonHeadData }) {
let { jobLists } = useSelector((state) => state.jobLists);
@@ -25,12 +26,18 @@ export default function MarketPlace({ commonHeadData }) {
}
/>
</div>
{jobLists.loading ?
<div className="w-full flex justify-center items-center bg-white dark:bg-dark-white">
<LoadingSpinner size='20' height='h-[40rem]' />
</div>
:
<MainSection
marketPlaceProduct={marketData}
categories={categories}
image_server={image_server}
className="mb-10"
/>
}
</Layout>
</>
);
+45 -22
View File
@@ -42,7 +42,11 @@ export default function NewPaginatedList({
filteredData?.slice(currentPage, numberOfSelection + currentPage)
);
}, [currentPage, filteredData]);
console.log("newData", newData, filteredData);
useEffect(()=>{
setCurrentPage(0)
},[itemsPerPage])
return (
<div className="w-full">
<h1 className="text-2xl mb-5 font-semibold">{tableTitle}</h1>
@@ -74,27 +78,46 @@ export default function NewPaginatedList({
{/* show prev and next button if data exist */}
{data.length > 0 && (
<div className="mt-10 w-full flex gap-4 justify-center items-center">
<button
onClick={handlePrev}
className={`w-12 h-12 rounded-full flex justify-center items-center border ${
currentPage == 0
? "text-slate-300 border-slate-300 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
: "text-slate-600 border-slate-600 dark:text-slate-300 dark:border-slate-300"
} transition-all duration-500`}
>
&lt;
</button>
<button
onClick={handleNext}
className={`w-12 h-12 rounded-full flex justify-center items-center border ${
currentPage + numberOfSelection >= data.length
? "text-slate-300 border-slate-300 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
: "text-slate-600 border-slate-600 dark:text-slate-300 dark:border-slate-300"
} transition-all duration-500`}
>
&gt;
</button>
</div>
<button
onClick={handlePrev}
className={`w-12 h-12 rounded-full flex justify-center items-center transition-all duration-300 ${
currentPage == 0
? "text-slate-400 border-slate-400 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
: "text-slate-600 border-slate-600 dark:text-white dark:border-white"
}`}
>
&lt;
</button>
{data.length && data.map((item, index)=>{
if(index%itemsPerPage == 0 && index >= currentPage && index <= currentPage+itemsPerPage){
return (
<button
key={index}
onClick={handleNext}
className={`w-12 h-12 rounded-full flex justify-center items-center border transition-all duration-300 ${
currentPage != index
? "text-slate-400 border-slate-400 dark:text-slate-400 dark:border-slate-400"
: "text-slate-600 border-slate-600 dark:text-white dark:border-white pointer-events-none"
}`}
>
{index/itemsPerPage +1}
</button>
)
}
})}
<button
onClick={handleNext}
className={`w-12 h-12 rounded-full flex justify-center items-center transition-all duration-300 ${
currentPage + numberOfSelection >= data.length
? "text-slate-400 border-slate-400 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
: "text-slate-600 border-slate-600 dark:text-white dark:border-white"
}`}
>
&gt;
</button>
</div>
)}
</div>
);
+1 -1
View File
@@ -238,7 +238,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
{/* balance */}
{/* My Page Button */}
{userDetails.account_type === "FULL" ? <PageButton /> : null}
{/* {userDetails.account_type === "FULL" ? <PageButton /> : null} */}
{/*<div className="lg:hidden block"></div>*/}
<WalletHeader
+4 -4
View File
@@ -85,11 +85,11 @@ export default function Layout({ children }) {
{logoutModal && (
<ModalCom action={logoutModalHandler} situation={logoutModal}>
<div className="logout-modal-wrapper w-11/12 sm:w-[460px] bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
<div className="modal-header-con">
<h1 className="modal-title">
Confirm
</h1>
<button type="button" className="text-[#374557] dark:text-red-500" onClick={logoutModalHandler}>
<button type="button" className="modal-close-btn" onClick={logoutModalHandler}>
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" className="fill-current" xmlns="http://www.w3.org/2000/svg">
<path d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z" fill="" fillOpacity="0.6" />
<path d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z" fill="#" fillOpacity="0.6" />
@@ -109,7 +109,7 @@ export default function Layout({ children }) {
Are you sure you want to Logout of your WrenchBoard account?
</p>
</div>
<div className="flex space-x-2.5">
<div className="modal-footer-wrapper flex justify-center items-center gap-5">
<button onClick={logOut} type="button" className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full">
{`Yes ${process.env.REACT_APP_LOGOUT_TEXT}`}
</button>
+32 -13
View File
@@ -40,7 +40,7 @@ export default function RightSideBar({ myJobList }) {
return (
<>
<div className="right-sidebar-wrapper overflow-y-scroll overflow-style-none 2xl:fixed h-full 2xl:pb-96">
<div className="top-platform bg-white dark:bg-dark-white rounded-2xl p-8 2xl:w-[268px] w-full 2xl:mb-10 2xl:border-none border ">
<div className="top-platform bg-white dark:bg-dark-white rounded-2xl p-8 2xl:w-[268px] w-full 2xl:mb-6 2xl:border-none border ">
{/* heading */}
<div className="heading flex justify-between items-center mb-3.5">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
@@ -49,10 +49,10 @@ export default function RightSideBar({ myJobList }) {
<div></div>
</div>
<div className="platform-list">
<div className="platform-list flex flex-col gap-y-2.5">
{userDetails && userDetails?.account_type !== "FAMILY" && (
<>
<div className="item flex space-x-3 items-center mb-4">
<div className="item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
@@ -82,7 +82,7 @@ export default function RightSideBar({ myJobList }) {
{/* action */}
</div>
<div className="item flex space-x-3 items-center mb-4">
<div className="item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 rounded-full flex items-center justify-center">
<Icons name="pending-job" />
@@ -95,7 +95,7 @@ export default function RightSideBar({ myJobList }) {
</div>
{/* action */}
</div>
<div className="item flex space-x-3 items-center mb-4">
<div className="item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
@@ -129,10 +129,29 @@ export default function RightSideBar({ myJobList }) {
</p>
</div>
</div>
<div className="item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 rounded-full bg-sky-500/50 p-1 flex justify-center items-center">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 50" id="Page">
<path
fillRule="evenodd"
d="M0 13V2a2 2 0 0 1 2-2h64a2 2 0 0 1 2 2v11H0Zm0 4v31a2 2 0 0 0 2 2h20V17H0Zm26 33h40a2 2 0 0 0 2-2V17H26v33Z"
fill="#ffffff"
className="color000000 svgShape"
></path>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/yourpage">My Page</NavLink>
</p>
</div>
</div>
</>
)}
<div className="item flex space-x-3 items-center mb-4">
<div className="item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
@@ -172,7 +191,7 @@ export default function RightSideBar({ myJobList }) {
{/* dark mode */}
<div
onClick={darkMode.handleThemeSwitch}
className="item flex space-x-5 items-center mb-4 cursor-pointer"
className="item flex space-x-5 items-center cursor-pointer"
>
<span className="dark:text-dark-gray text-white">
{darkMode.theme === "light" ? (
@@ -270,8 +289,8 @@ export default function RightSideBar({ myJobList }) {
<div></div>
</div>
<div className="platform-list">
<div className="px-8 item flex space-x-3 items-center mb-4">
<div className="platform-list flex flex-col gap-y-2.5">
<div className="px-8 item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 p-[4px] rounded-full">
<img
@@ -289,7 +308,7 @@ export default function RightSideBar({ myJobList }) {
{/* action */}
</div>
<div className="px-8 item flex space-x-3 items-center mb-4">
<div className="px-8 item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 p-[4px] rounded-full">
<img
@@ -307,7 +326,7 @@ export default function RightSideBar({ myJobList }) {
{/* action */}
</div>
<div className="px-8 item flex space-x-3 items-center mb-4">
<div className="px-8 item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 p-[4px] rounded-full">
<img
@@ -324,7 +343,7 @@ export default function RightSideBar({ myJobList }) {
</div>
</div>
<div className="px-8 item flex space-x-3 items-center mb-4">
<div className="px-8 item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 p-[4px] rounded-full">
<img
@@ -344,7 +363,7 @@ export default function RightSideBar({ myJobList }) {
{/* Line */}
<div className="my-4 mx-auto w-10/12 h-[2px] bg-slate-500 dark:bg-white rounded-full"></div>
<div className="px-8 item flex space-x-3 items-center mb-4">
<div className="px-8 item flex space-x-3 items-center">
{/* image */}
<div className="w-8 h-8 p-[4px] rounded-full">
<img
+22
View File
@@ -0,0 +1,22 @@
import React, { useEffect, useRef } from 'react'
export default function VideoElement({videoId}) {
let videoRef = useRef(null)
useEffect(()=>{
if(videoRef.current){
videoRef.current.pause()
videoRef.current.removeAttribute('src')
videoRef.current.load()
}
},[videoId])
return (
<video ref={videoRef} className='w-full h-full' controls>
<source src={`https://dev-media.wrenchboard.com/videos/${videoId}`} type='video/mp4'></source>
Your browser does not support the video tag.
</video>
)
}
@@ -0,0 +1,62 @@
import React, { useEffect, useState } from 'react'
import LoadingSpinner from '../Spinners/LoadingSpinner'
export default function InfiniteScroll({
allData=data,
addItemBy=12,
intialItemsToShow=39,
children
}) {
let [currentPage, setCurrentPage] = useState(intialItemsToShow)
let [loading, setLoading] = useState(false)
let dataToShow = allData.slice(0, currentPage)
// let [winScr, setWinScr] = useState(0)
const customScroll = ()=>{
let wi = window.innerHeight + window.scrollY
// let scrollContainer = document.querySelector('.scroll-container').scrollHeight
let scrollBody = document.body.offsetHeight
if(wi >= scrollBody && allData.length > currentPage){
setLoading(true)
setTimeout(()=>{
setCurrentPage(prev => prev+addItemBy)
setLoading(false)
},2000)
}
// else if(window.scrollY < winScr && currentPage > intialItemsToShow){
// setCurrentPage(prev => prev-addItemBy)
// window.scrollTo(0,wi)
// setWinScr(window.scrollY)
// }
// else if(winScr == 0 && currentPage > intialItemsToShow){
// setCurrentPage(prev => intialItemsToShow)
// window.scrollTo(0,0)
// setWinScr(window.scrollY)
// }
}
useEffect(()=>{
window.addEventListener('scroll', customScroll)
return () => {
window.removeEventListener('scroll', customScroll)
}
},[currentPage])
return (
<div className='w-full'>
{children({ dataToShow })}
{loading &&
<div className='w-full my-2 p-2 flex justify-center items-center'>
<LoadingSpinner size='8' />
</div>
}
</div>
)
}
// let data = new Array(100).fill(0).map((_,i) => i )
@@ -123,13 +123,13 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
<div className="modal-header-con">
<h1 className="modal-title">
Start Task
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
className="modal-close-btn"
onClick={onClose}
>
<svg
@@ -153,7 +153,7 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
</svg>
</button>
</div>
<div className="md:flex bg-white rounded-lg shadow-lg">
<div className="md:flex bg-white rounded-lg">
<div className="p-4 w-full md:w-3/4 md:border-r-2">
<div className="flex gap-2">
<div className="image-wrapper w-32">
@@ -261,12 +261,12 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
</div>
{/* close button */}
<div className="p-6 flex justify-end">
<div className="modal-footer-wrapper flex justify-end">
<button
onClick={onClose}
disabled={requestStatus.loading}
type="button"
className="border-gradient text-18 tracking-wide px-2 py-2 rounded-full"
className="custom-btn border-gradient"
>
<span className="text-gradient">Cancel</span>
</button>
+6 -6
View File
@@ -103,13 +103,13 @@ function OfferJobPopout({ details, onClose, situation }) {
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
<div className="modal-header-con">
<h1 className="modal-title">
Start Task
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
className="modal-close-btn"
onClick={onClose}
>
<svg
@@ -133,7 +133,7 @@ function OfferJobPopout({ details, onClose, situation }) {
</svg>
</button>
</div>
<div className="md:flex bg-white dark:bg-dark-white rounded-lg shadow-lg">
<div className="md:flex bg-white dark:bg-dark-white rounded-lg">
<div className="p-4 w-full md:w-3/4 md:border-r-2">
<p className="text-lg my-5 font-semibold text-slate-900 dark:text-white tracking-wide">
{details.title}
@@ -234,12 +234,12 @@ function OfferJobPopout({ details, onClose, situation }) {
</div>
{/* close button */}
<div className="p-6 flex justify-end">
<div className="modal-footer-wrapper flex justify-end">
<button
onClick={onClose}
disabled={requestStatus.loading}
type="button"
className="border-gradient text-18 tracking-wide px-2 py-2 rounded-full"
className="custom-btn border-gradient"
>
<span className="text-gradient">Cancel</span>
</button>
+12 -8
View File
@@ -9,6 +9,7 @@ import Detail from "./popoutcomponent/Detail";
import { useDispatch } from "react-redux";
import { tableReload } from "../../store/TableReloads";
import { NewDateTimeFormatter } from "../../lib/NewDateTimeFormatter";
const showSuccessToast = (message) => {
toast.success(message, {
@@ -70,7 +71,9 @@ function PendingJobsPopout({ details, onClose, situation }) {
.pendingJobSendTome(reqData)
.then((res) => {
setRequestMessage({ status: true, message: res.data.status });
dispatch(tableReload({ type: "PENDINGTABLE" }));
setTimeout(() => {
onClose()
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({ status: false, message: "" });
}, 4000);
@@ -184,12 +187,12 @@ function PendingJobsPopout({ details, onClose, situation }) {
</div>
{/* INPUT SECTION */}
<div className="my-2 md:flex">
{/* <div className="my-2 md:flex">
<Detail
label="Date Added"
value={details.offer_added || "default"}
/>
</div>
</div> */}
<div className="my-2 md:flex">
<Detail label="Description" value={details.description} />
@@ -198,12 +201,13 @@ function PendingJobsPopout({ details, onClose, situation }) {
<div className="my-2 md:flex">
<Detail
label="Offer Expire"
value={
details.expire &&
`${details.expire.split(" ")[0]} ${
details.expire.split(" ")[1].split(".")[0]
}`
}
// value={
// details.expire &&
// `${details.expire.split(" ")[0]} ${
// details.expire.split(" ")[1].split(".")[0]
// }`
// }
value={NewDateTimeFormatter(new Date(details.expire))}
/>
</div>
+17
View File
@@ -0,0 +1,17 @@
export function NewDateTimeFormatter(isoDateString, addHour = true) {
const date = new Date(isoDateString);
if (addHour) {
date.setTime(date.getTime() + 1 * 60 * 60 * 1000);
}
const formattedDate = date.toLocaleDateString("en-US", {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
// second: "2-digit",
hour12: true,
timeZone: "UTC",
});
return formattedDate;
}
+4
View File
@@ -0,0 +1,4 @@
export let errorMsg = {
error_unable_to_create_fund_for_task: "Insufficient Wallet Balance to Create Task",
}
+2 -1
View File
@@ -219,8 +219,9 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
const getMarketActiveJobList = async () => {
try {
const res = await apiCall.getActiveJobList();
dispatch(updateJobs(res.data));
dispatch(updateJobs({loading: false, ...res.data}));
} catch (error) {
dispatch(updateJobs({loading: false}));
console.log("Error getting mode");
}
};
+26 -1
View File
@@ -1330,7 +1330,32 @@ class usersService {
};
return this.postAuxEnd("/familywallet/redeem/options", postData);
}
// API FUNCTION FOR PARENT TO CALL COMMON MEDIA
getParentCommonMedia() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: apiConst.WRENCHBOARD_ACCOUNT_FAMILY_RESOURCES,
offset: 1,
limit: 20,
};
return this.postAuxEnd("/commonmedia", postData);
}
// API FUNCTION FOR PARENT TO ASSIGN MEDIA TASK
parentAssignMediaTask(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: apiConst.WRENCHBOARD_JOB_OFFER_SYSTEM,
...reqData
};
return this.postAuxEnd("/assignmediatask", postData);
}
/*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
+1 -1
View File
@@ -1,7 +1,7 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
jobLists: {}
jobLists: {loading: true}
};
export const jobSlice = createSlice({