Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d98141c39 | |||
| 5fe5ccbd4d | |||
| 76c0994eb0 | |||
| a1bc6db381 | |||
| 6f5d72e033 | |||
| 762de4c23e | |||
| 2a8b7ba6ec | |||
| 50e44dab43 | |||
| 7649a90c47 | |||
| 3c2c46e293 | |||
| 8dc634d900 | |||
| 3a9cb4667e | |||
| 5f4b032f68 | |||
| 8ab3e9ae50 | |||
| 01b5fba75b | |||
| 66b8c96592 | |||
| 616352e1ac | |||
| acc4417835 | |||
| 7da693f298 | |||
| b0423c665c | |||
| 7089b8f14b | |||
| 2c2e2b0ca5 | |||
| ba3dd91d81 | |||
| 3f04c9f9f8 | |||
| 781f5cc5a6 | |||
| 58097d8b57 | |||
| 630ccefa51 | |||
| ed9f2dec0e | |||
| d2ed29c6a6 | |||
| 4e81156d72 | |||
| e402c02c1f | |||
| 5907b5d872 | |||
| 042cc4110c | |||
| 944fd134f6 | |||
| 5e6b208513 | |||
| 762601a5c3 | |||
| 1e28a0e15b | |||
| a910ab177f | |||
| 4e741f587c | |||
| f779529cc6 | |||
| 44cedf2f65 | |||
| fbcba191b0 |
Vendored
+10
-1
@@ -21,5 +21,14 @@
|
||||
"emmet.triggerExpansionOnTab": true,
|
||||
"emmet.includeLanguages": {
|
||||
"javascript": "javascriptreact"
|
||||
}
|
||||
},
|
||||
"cSpell.words": [
|
||||
"completesignuplink",
|
||||
"MOBILEUSER",
|
||||
"MYFILES",
|
||||
"mynotifications",
|
||||
"PASSWORDRESET",
|
||||
"TRANSFERSTART",
|
||||
"WRENCHBOARD"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -89,9 +89,9 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<label
|
||||
htmlFor="country"
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
|
||||
className="job-label job-label-flex"
|
||||
>
|
||||
Currency
|
||||
<span>Currency</span>
|
||||
{props.errors.country && props.touched.country && (
|
||||
<span className="text-[12px] text-red-500">
|
||||
{props.errors.country}
|
||||
@@ -136,9 +136,9 @@ function AddJob({ popUpHandler, categories }) {
|
||||
{/* Price */}
|
||||
<div className="field w-full">
|
||||
<InputCom
|
||||
fieldClass="px-6 text-right"
|
||||
fieldClass="px-6 text-right flex"
|
||||
label="Price"
|
||||
labelClass="tracking-wide"
|
||||
labelClass=""
|
||||
type="number"
|
||||
name="price"
|
||||
placeholder="0"
|
||||
@@ -159,7 +159,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Title"
|
||||
labelClass="tracking-wide"
|
||||
labelClass=""
|
||||
type="text"
|
||||
name="title"
|
||||
value={props.values.title}
|
||||
@@ -178,7 +178,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Description"
|
||||
labelClass="tracking-wide"
|
||||
labelClass=""
|
||||
type="text"
|
||||
name="description"
|
||||
value={props.values.description}
|
||||
@@ -197,7 +197,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<div className="sm:w-[60%] w-full">
|
||||
<label
|
||||
htmlFor="Job Delivery Details"
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
|
||||
className="job-label job-label-flex"
|
||||
>
|
||||
Job Delivery Details
|
||||
{props.errors.job_detail &&
|
||||
@@ -220,13 +220,13 @@ function AddJob({ popUpHandler, categories }) {
|
||||
</div>
|
||||
|
||||
<div className="sm:w-[35%] w-full">
|
||||
<div
|
||||
<label
|
||||
htmlFor="Job Categories"
|
||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
||||
className='job-label'
|
||||
id="checked-group"
|
||||
>
|
||||
Categories
|
||||
</div>
|
||||
</label>
|
||||
<div
|
||||
className="sm:flex-col flex flex-wrap px-3 mt-3"
|
||||
role="group"
|
||||
@@ -266,7 +266,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<div className="field w-full mb-[5px]">
|
||||
<div className={`flex items-center justify-between mb-2.5`}>
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||
className="job-label"
|
||||
htmlFor="timeline_days"
|
||||
>
|
||||
Timeline
|
||||
@@ -328,10 +328,10 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<div className="flex items-center space-x-4 mr-9">
|
||||
<button
|
||||
type="button"
|
||||
className="text-18 text-light-red tracking-wide "
|
||||
className="text-18 tracking-wide h-11 flex justify-center items-center border border-light-red text-base rounded-full text-light-red cursor-pointer"
|
||||
>
|
||||
<span
|
||||
className="border-b dark:border-[#5356fb29] border-light-red"
|
||||
className="px-2"
|
||||
onClick={popUpHandler}
|
||||
>
|
||||
{" "}
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function SocketIOContextProvider({children}) {
|
||||
|
||||
const marketUpdate = (message, room) => {
|
||||
if(message && room){
|
||||
socket.emit("marketjob_addded", { message, room });
|
||||
socket.emit("marketjob_added", { message, room });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,23 +44,47 @@ export default function SocketIOContextProvider({children}) {
|
||||
}
|
||||
};
|
||||
|
||||
const sendJobInterestToOwner = (message, room) => {
|
||||
if(message && room){
|
||||
socket.emit("marketjob", { message:{...message}, room });
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
socket.on("receive_message", (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
dispatch(tableReload({type:'CHATMESSAGELIST'}))
|
||||
dispatch(tableReload({type:'CHATMESSAGELIST'})) // dispatches to update chat message sending from owner to worker and vice versa
|
||||
});
|
||||
|
||||
socket.on("received_refreshmarket_jobs", (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
dispatch(tableReload({type:'MARKETTABLELIST'}))
|
||||
dispatch(tableReload({type:'MARKETTABLELIST'})) // dispatches to update market list on full account
|
||||
});
|
||||
|
||||
socket.on("family_actions", (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
let user_uid = userDetails.account_type == 'FULL' ? userDetails.uid : sessionStorage.getItem('family_uid')
|
||||
let user_uid = userDetails.account_type == 'FULL' ? userDetails.uid : sessionStorage.getItem('family_uid') // gets user UID
|
||||
let {message} = data
|
||||
if(message.action == "REFRESH_OFFER" && message.family_uid == user_uid && message.audience == "MEMBER"){
|
||||
dispatch(tableReload({type:'FAMILYOFFERLIST'}))
|
||||
if(message.action == "REFRESH_OFFER" && message.family_uid == user_uid && message.audience == "MEMBER"){ // for refreshing child account when parent assigns a job
|
||||
dispatch(tableReload({type:'FAMILYOFFERLIST'})) // dispatches to update family pending/offer list on family side
|
||||
}
|
||||
if(message.action == "REFRESH_TASK" && message.audience == "PARENT"){ // for refreshing parent account when child accepts or rejects a job
|
||||
dispatch(tableReload({type:'PARENTFAMILYTASKLIST'})) // dispatches to update parent family task list on parent side
|
||||
}
|
||||
if(message.action == "REFRESH_WALLET" && message.family_uid == user_uid && message.audience == "MEMBER"){ // for refreshing child wallet account when parent sends money to kid
|
||||
dispatch(tableReload({type:'WALLETTABLE'})) // dispatches to update wallet balance on family side
|
||||
}
|
||||
// console.log('DATA', data)
|
||||
});
|
||||
|
||||
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 {message} = data
|
||||
if(message.action == "REFRESH_OFFERS" && message.audience == "MERCHANT"){ // for refreshing job owner offer interest list when any worker sends interest
|
||||
dispatch(tableReload({type:'OFFERINTERESTLISTRELOAD'}))
|
||||
}
|
||||
});
|
||||
|
||||
}, [socket]);
|
||||
|
||||
let values = {
|
||||
@@ -70,6 +94,7 @@ export default function SocketIOContextProvider({children}) {
|
||||
setSocketMsgReceived,
|
||||
marketUpdate,
|
||||
parentAssignJobToKid,
|
||||
sendJobInterestToOwner,
|
||||
socketMsgReceived,
|
||||
// room,
|
||||
// setRoom,
|
||||
|
||||
@@ -29,14 +29,15 @@ const AccountDashboard = ({ className, bannerList }) => {
|
||||
props;
|
||||
|
||||
return (
|
||||
<TopBanner
|
||||
btn={short_button_text}
|
||||
image={image}
|
||||
title={short_title}
|
||||
desc={short_description}
|
||||
link_path={link_path}
|
||||
key={idx}
|
||||
/>
|
||||
<div key={idx}>
|
||||
<TopBanner
|
||||
btn={short_button_text}
|
||||
image={image}
|
||||
title={short_title}
|
||||
desc={short_description}
|
||||
link_path={link_path}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
@@ -48,14 +49,15 @@ const AccountDashboard = ({ className, bannerList }) => {
|
||||
props;
|
||||
|
||||
return (
|
||||
<LowerBanner
|
||||
btn={short_button_text}
|
||||
image={image}
|
||||
title={short_title}
|
||||
desc={short_description}
|
||||
link_path={link_path}
|
||||
key={idx}
|
||||
/>
|
||||
<div key={idx}>
|
||||
<LowerBanner
|
||||
btn={short_button_text}
|
||||
image={image}
|
||||
title={short_title}
|
||||
desc={short_description}
|
||||
link_path={link_path}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -52,7 +52,13 @@ export default function FamilyActivities() {
|
||||
<span>Family</span>
|
||||
</Link>
|
||||
</div>
|
||||
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="bg-white">
|
||||
<LoadingSpinner color="sky-blue" size="16" height='h-[30rem]' />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<FamilyTableNew />
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { Suspense, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import usersService from "../../../services/UsersService";
|
||||
@@ -23,7 +23,9 @@ const AssignTaskPopout = ({
|
||||
|
||||
}) => {
|
||||
const {parentAssignJobToKid} = SocketValues()
|
||||
|
||||
const apiCall = new usersService();
|
||||
|
||||
let { pathname, state } = useLocation();
|
||||
|
||||
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||
@@ -80,7 +82,7 @@ const AssignTaskPopout = ({
|
||||
setRequestStatus({ loading: true, status: false, message: "" });
|
||||
|
||||
if(!selectedFamilyUid){ // If no family found, throw error
|
||||
setRequestStatus({ loading: false, status: false, message: "Please Select Family Member" });
|
||||
setRequestStatus({ loading: false, status: false, message: "Please Select a Kid" });
|
||||
return setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
}, 3000);
|
||||
@@ -219,7 +221,10 @@ 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
|
||||
|
||||
useEffect(()=>{ // effect to update family UID when components mounts
|
||||
if(familyDetailsData?.uid){
|
||||
@@ -231,12 +236,13 @@ const AssignTaskPopout = ({
|
||||
}
|
||||
},[])
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalCom action={action} situation={situation}>
|
||||
<div className="w-11/12 lg:w-[700px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] bg-sky-blue/50 border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide flex items-center">
|
||||
<div className="modal-header-con">
|
||||
<h1 className="modal-title">
|
||||
{details ? (
|
||||
` Assign ${details?.firstname}'s Task`
|
||||
) : familyDetailsData ? (
|
||||
@@ -244,11 +250,11 @@ const AssignTaskPopout = ({
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-black">Assign task to{" "}</span>
|
||||
<div className="w-[270px] h-[40px] flex items-center relative after:absolute after:content-['▼'] active:after:rotate-180 after:transition-all after:duration-300 after:z-20 after:right-2 after:top-1/2 after:-translate-y-1/2 after:text-white after:text-lg">
|
||||
<div className="w-[270px] h-[40px] flex items-center">
|
||||
<select
|
||||
name=""
|
||||
id=""
|
||||
className="relative z-10 appearance-none text-lg text-white px-2 tracking-wide font-semibold transition-all cursor-pointer bg-blue-900 focus:outline-none border border-gray-200 rounded-full w-full h-full"
|
||||
className="text-lg text-black/80 px-2 tracking-wide font-semibold transition-all cursor-pointer bg-white focus:outline-none border border-gray-200 rounded-full w-full h-full"
|
||||
onChange={handleFamChange}
|
||||
value={selectedFamilyUid}
|
||||
>
|
||||
@@ -263,7 +269,7 @@ const AssignTaskPopout = ({
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#000] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={action}
|
||||
>
|
||||
<svg
|
||||
@@ -382,25 +388,37 @@ const AssignTaskPopout = ({
|
||||
value={activeTask?.data?.description}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<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="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 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>
|
||||
|
||||
@@ -435,7 +453,7 @@ const AssignTaskPopout = ({
|
||||
</div>
|
||||
|
||||
{/* BTN */}
|
||||
<div className="py-2 px-4 border-t-2 flex justify-between items-center">
|
||||
<div className="modal-footer-wrapper">
|
||||
{/* error or success display */}
|
||||
<div className="w-auto h-auto flex items-center">
|
||||
{requestStatus.message != "" &&
|
||||
@@ -462,7 +480,7 @@ const AssignTaskPopout = ({
|
||||
disabled={requestStatus.loading}
|
||||
onClick={action}
|
||||
type="button"
|
||||
className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white cursor-pointer"
|
||||
className="custom-btn border-gradient"
|
||||
>
|
||||
<span className="text-gradient">Close</span>
|
||||
</button>
|
||||
@@ -474,7 +492,7 @@ const AssignTaskPopout = ({
|
||||
type="button"
|
||||
disabled={requestStatus.loading}
|
||||
onClick={assignFamilyTask}
|
||||
className="px-1 w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
className="custom-btn btn-gradient text-white"
|
||||
>
|
||||
Assign
|
||||
</button>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { apiConst } from "../../lib/apiConst";
|
||||
import usersService from "../../services/UsersService";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
// Lazy Imports for components
|
||||
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyNewWaitlist"));
|
||||
@@ -11,11 +12,15 @@ const FamilyTasks = lazy(() => import("./Tabs/FamilyNewTasks"));
|
||||
const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending"));
|
||||
|
||||
export default function FamilyTableNew() {
|
||||
|
||||
const { parentFamilyTaskList } = useSelector((state) => state.tableReload);
|
||||
console.log('parentFamilyTaskList', parentFamilyTaskList)
|
||||
|
||||
let { pathname } = useLocation();
|
||||
|
||||
// Initial state for family details
|
||||
const initialDetailState = {
|
||||
loading: false,
|
||||
loading: true,
|
||||
data: null,
|
||||
link: "",
|
||||
};
|
||||
@@ -115,13 +120,13 @@ export default function FamilyTableNew() {
|
||||
useEffect(() => {
|
||||
const manageFamily = async () => {
|
||||
try {
|
||||
resetDetails();
|
||||
// resetDetails();
|
||||
|
||||
setDetails({
|
||||
familyTasks: { loading: true },
|
||||
familyWaitList: { loading: true },
|
||||
familyPending: { loading: true },
|
||||
});
|
||||
// setDetails({
|
||||
// familyTasks: { loading: true },
|
||||
// familyWaitList: { loading: true },
|
||||
// familyPending: { loading: true },
|
||||
// });
|
||||
|
||||
// const { family_uid } = accountDetails;
|
||||
// const reqData = { family_uid };
|
||||
@@ -169,7 +174,13 @@ export default function FamilyTableNew() {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
resetDetails();
|
||||
// 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);
|
||||
}
|
||||
@@ -177,7 +188,7 @@ export default function FamilyTableNew() {
|
||||
|
||||
// Invoke the manageFamily function when the component mounts
|
||||
manageFamily();
|
||||
}, [updatePage]);
|
||||
}, [updatePage, parentFamilyTaskList]);
|
||||
|
||||
// Effect to manage family tasks
|
||||
useEffect(() => {
|
||||
|
||||
@@ -15,8 +15,10 @@ function FamilyWallet({familyData}) {
|
||||
|
||||
useEffect(()=>{
|
||||
setFamilyWallet({loading:true, data: []})
|
||||
apiUrl.getFamilyWallet({family_uid:familyData?.uid}).then(res => {
|
||||
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: []})
|
||||
})
|
||||
|
||||
@@ -9,8 +9,9 @@ import usersService from "../../../../services/UsersService";
|
||||
import LoadingSpinner from "../../../Spinners/LoadingSpinner";
|
||||
import { PriceFormatter } from "../../../Helpers/PriceFormatter";
|
||||
import { tableReload } from "../../../../store/TableReloads";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { apiConst } from "../../../../lib/apiConst";
|
||||
import { SocketValues } from "../../../Contexts/SocketIOContext";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
// amount: Yup.string()
|
||||
@@ -30,6 +31,11 @@ const validationSchema = Yup.object().shape({
|
||||
});
|
||||
|
||||
function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
||||
|
||||
const {userDetails} = useSelector((state) => state?.userDetails); // Gets User Detail
|
||||
|
||||
const { parentAssignJobToKid } = SocketValues() // socket emit event from FULL account
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const apiUrl = new usersService();
|
||||
@@ -54,6 +60,7 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
||||
};
|
||||
// FUNCTION TO PERFORM FAMILY TRANSFER
|
||||
const handleAddFund = (values) => {
|
||||
|
||||
setRequestStatus({ loading: true, status: false, message: "" });
|
||||
|
||||
let senderBal = startTransfer?.data?.origing_current_balance || ""; // SENDER'S ACCOUNT BALANCE
|
||||
@@ -132,6 +139,17 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
||||
status: true,
|
||||
message: "Transfer Successful",
|
||||
});
|
||||
|
||||
//SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||
// message, room
|
||||
let socketMsg = {
|
||||
"audience": "MEMBER",
|
||||
"action": "REFRESH_WALLET",
|
||||
"family_uid": reqData.family_uid,
|
||||
}
|
||||
let socketRoom = `FAMILY-${userDetails.uid}`
|
||||
parentAssignJobToKid(socketMsg, socketRoom) //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||
|
||||
setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
dispatch(tableReload({ type: "WALLETTABLE" })); // UPDATES PARENT WALLET ACCOUNT
|
||||
@@ -170,13 +188,13 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
||||
return (
|
||||
<ModalCom action={action} situation={situation}>
|
||||
<div className="relative logout-modal-wrapper lg:w-[500px] h-full lg:h-auto 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 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">
|
||||
Add Fund
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={action}
|
||||
>
|
||||
<svg
|
||||
@@ -271,7 +289,7 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
||||
<div className="field w-full mb-[0.5rem]">
|
||||
<div className="w-full">
|
||||
<label
|
||||
htmlFor="Job Delivery Details"
|
||||
htmlFor="job-label"
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
|
||||
>
|
||||
Comment
|
||||
|
||||
@@ -248,13 +248,13 @@ const FamilyForm = ({
|
||||
}) => {
|
||||
return (
|
||||
<div className="logout-modal-wrapper w-11/12 lg:w-[460px] 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: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">
|
||||
Add Members
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={popUpHandler}
|
||||
>
|
||||
<CloseIcon />
|
||||
@@ -267,8 +267,8 @@ const FamilyForm = ({
|
||||
name="first_name"
|
||||
type="text"
|
||||
parentClass="flex items-center gap-1 w-full"
|
||||
labelClass="flex-[0.2] mb-0"
|
||||
inputClass="flex-[0.8] input-curve lg border border-[#dce4e9]"
|
||||
labelClass="flex-[0.4] mb-0"
|
||||
inputClass="flex-[0.6] input-curve lg border border-[#dce4e9]"
|
||||
fieldClass="px-2"
|
||||
value={first_name}
|
||||
inputHandler={inputHandler}
|
||||
@@ -279,8 +279,8 @@ const FamilyForm = ({
|
||||
name="last_name"
|
||||
type="text"
|
||||
parentClass="flex items-center gap-1 w-full"
|
||||
labelClass="flex-[0.2] mb-0"
|
||||
inputClass="flex-[0.8] input-curve lg border border-[#dce4e9]"
|
||||
labelClass="flex-[0.4] mb-0"
|
||||
inputClass="flex-[0.6] input-curve lg border border-[#dce4e9]"
|
||||
fieldClass="px-2"
|
||||
value={last_name}
|
||||
inputHandler={inputHandler}
|
||||
@@ -289,7 +289,7 @@ const FamilyForm = ({
|
||||
{/* Age dropdown */}
|
||||
<div className="">
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[15px] font-semibold"
|
||||
className="job-label"
|
||||
htmlFor="age-selection"
|
||||
>
|
||||
Birthday: (Year/Month)
|
||||
|
||||
@@ -84,9 +84,9 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation}>
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[48rem] h-full lg:h-[627px] 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-[1.875rem] py-[1.4375rem] border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[48rem] min-h-[500px] bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||
<div className="modal-header-con">
|
||||
<h1 className="modal-title">
|
||||
{isManageFamilyPage
|
||||
? `${state?.firstname}'s Suggested Task`
|
||||
: isActivitiesPage
|
||||
@@ -95,7 +95,7 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={onClose}
|
||||
>
|
||||
<svg
|
||||
@@ -179,10 +179,10 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div className="field w-full mb-[.3125rem]">
|
||||
<div className="w-full mb-[.3125rem]">
|
||||
<label
|
||||
htmlFor="description"
|
||||
className='input-label text-[#181c32] dark:text-white text-[1.125rem] leading-[1.3102rem] font-semibold flex items-center gap-1'
|
||||
className='job-label'
|
||||
>
|
||||
Description
|
||||
{props.errors.description &&
|
||||
|
||||
@@ -54,7 +54,7 @@ export default function InputCom({
|
||||
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
|
||||
{label && (
|
||||
<label
|
||||
className={`input-label text-[#181c32] text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1 ${labalClass}`}
|
||||
className={`job-label ${error && 'job-label-flex'} ${labalClass}`}
|
||||
htmlFor={name}
|
||||
>
|
||||
{label}
|
||||
|
||||
@@ -89,13 +89,13 @@ export default function AddGroup({ action, situation, setUpdateList }) {
|
||||
return (
|
||||
<ModalCom action={action} situation={situation}>
|
||||
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto 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 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">
|
||||
Add Group
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={action}
|
||||
>
|
||||
<svg
|
||||
@@ -139,9 +139,9 @@ export default function AddGroup({ action, situation, setUpdateList }) {
|
||||
<button
|
||||
onClick={action}
|
||||
type="button"
|
||||
className="text-base text-light-red tracking-wide "
|
||||
className="w-[152px] h-[46px] flex justify-center items-center rounded-full text-base text-light-red tracking-wide border border-light-red"
|
||||
>
|
||||
<span className="border-b dark:border-[#5356fb29] border-light-red">
|
||||
<span className="">
|
||||
Cancel
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -21,13 +21,13 @@ export default function DeleteMember({action, situation, details}) {
|
||||
situation={situation}
|
||||
>
|
||||
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto 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 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">
|
||||
Remove Member
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={action}
|
||||
>
|
||||
<svg
|
||||
|
||||
@@ -24,12 +24,6 @@ export default function MemberList({
|
||||
|
||||
const handleFieldsChange = ({ target: { name, value } }) => {
|
||||
setFields((prev) => ({ ...prev, [name]: value }));
|
||||
// let error = requestState?.errors?.indexOf(name) //// checks if the input field was in error array and removes it when the input changes
|
||||
// if(error >= 0){
|
||||
// let oldErrorArr = requestState.errors
|
||||
// let newErrorArr = oldErrorArr.splice(error, 1)
|
||||
// setRequestState(prev => ({...prev, errors:oldErrorArr}))
|
||||
// }
|
||||
|
||||
if (value == "") {
|
||||
setRequestState({
|
||||
@@ -89,6 +83,63 @@ export default function MemberList({
|
||||
// return
|
||||
// }
|
||||
|
||||
if(fields.firstname.length > 25){ // checks if firstname length is more than 25
|
||||
setRequestState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "Firstname must not be more than 25 characters",
|
||||
data: [],
|
||||
errors: [],
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
data: [],
|
||||
errors: [],
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
if(fields.lastname.length > 25){ // checks if lastname length is more than 25
|
||||
setRequestState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "Lastname must not be more than 25 characters",
|
||||
data: [],
|
||||
errors: [],
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
data: [],
|
||||
errors: [],
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
if(fields.email.length > 45){ // checks if email length is more than 45
|
||||
setRequestState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "Email must not be more than 45 characters",
|
||||
data: [],
|
||||
errors: [],
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
data: [],
|
||||
errors: [],
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
//checks if email is a valid email address
|
||||
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
|
||||
if (!EmailValidator(fields.email)) {
|
||||
@@ -201,7 +252,7 @@ export default function MemberList({
|
||||
{selectedGroup?.name}
|
||||
</h1>
|
||||
<div className="w-full flex flex-col-reverse lg:flex-col">
|
||||
<div className="py-3 w-full">
|
||||
<div className="relative py-3 w-full">
|
||||
<div className="relative grid grid-cols-1 sm:grid-cols-2 gap-2 place-content-center">
|
||||
<div className="input-item">
|
||||
<InputCom
|
||||
@@ -229,13 +280,15 @@ export default function MemberList({
|
||||
// iconName="message"
|
||||
/>
|
||||
</div>
|
||||
<div className="input-item w-full">
|
||||
</div>
|
||||
<div className="sm:flex gap-2 items-center">
|
||||
<div className="input-item my-2 w-full sm:w-9/12">
|
||||
<InputCom
|
||||
labelClass="tracking-wider"
|
||||
fieldClass="sm:px-6 px-2"
|
||||
value={fields.email}
|
||||
inputHandler={handleFieldsChange}
|
||||
inputClass="xl:w-[16rem] 2xl:w-full"
|
||||
inputClass=""
|
||||
placeholder="Email"
|
||||
// label="Email"
|
||||
name="email"
|
||||
@@ -243,7 +296,7 @@ export default function MemberList({
|
||||
// iconName="message"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-end items-end">
|
||||
<div className="flex justify-end items-end w-full sm:w-3/12">
|
||||
{requestState.loading ? (
|
||||
<LoadingSpinner size="8" color="sky-blue" />
|
||||
) : (
|
||||
@@ -266,10 +319,11 @@ export default function MemberList({
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="absolute top-full w-full my-1 text-center">
|
||||
{!requestState.loading && requestState.message && (
|
||||
<p
|
||||
className={`text-lg absolute -bottom-7 left-0 ${
|
||||
className={`text-base ${
|
||||
requestState.status ? "text-green-500" : "text-red-500"
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -4,6 +4,7 @@ import ListView from "../../assets/images/list-view.png";
|
||||
import AvailableJobsCard from "../Cards/AvailableJobsCard";
|
||||
import DataIteration from "../Helpers/DataIteration";
|
||||
import SelectBox from "../Helpers/SelectBox";
|
||||
import NewPaginatedList from "../Pagination/NewPaginatedList";
|
||||
|
||||
export default function MainSection({
|
||||
className,
|
||||
@@ -120,6 +121,40 @@ export default function MainSection({
|
||||
</DataIteration>
|
||||
</div>
|
||||
</div>
|
||||
{/* {products?.length &&
|
||||
<NewPaginatedList
|
||||
data={products}
|
||||
itemsPerPage={6}
|
||||
filterItem=''
|
||||
tableTitle=''
|
||||
>
|
||||
{
|
||||
({data})=>(
|
||||
<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"
|
||||
}
|
||||
>
|
||||
{
|
||||
data.map((datum, index) => (
|
||||
<div key={datum.job_uid+index}>
|
||||
<AvailableJobsCard
|
||||
contentDisplay={contentDisplay}
|
||||
image_server={image_server}
|
||||
datas={datum}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</NewPaginatedList>
|
||||
} */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import usersService from "../../../services/UsersService";
|
||||
import ModalCom from "../../Helpers/ModalCom";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import { SocketValues } from "../../Contexts/SocketIOContext";
|
||||
|
||||
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
|
||||
let {sendJobInterestToOwner} = SocketValues() // function to emit job interest request
|
||||
const emitOfferInterest = () => {
|
||||
let message = {
|
||||
"audience": "MERCHANT",
|
||||
"action": "REFRESH_OFFERS",
|
||||
"offer_code": details?.offer_code,
|
||||
"offer_uid": details?.offer_uid,
|
||||
"job_uid": details?.job_uid,
|
||||
}
|
||||
let room = `INTEREST-${details?.market_uid}`
|
||||
sendJobInterestToOwner(message, room)
|
||||
}
|
||||
|
||||
const [textValue, setTextValue] = useState("");
|
||||
const [errMsg, setErrMsg] = useState({
|
||||
market: false,
|
||||
@@ -88,7 +103,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
state: true,
|
||||
});
|
||||
}
|
||||
|
||||
emitOfferInterest() // FUNCTIONS TO EMIT EVENT INDICATING SOMEONE SENDS AN INTEREST IN YOUR JOB
|
||||
setTimeout(() => setManageInt({ msg: "" }), 3000);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
@@ -118,9 +133,9 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation}>
|
||||
<div className="logout-modal-wrapper w-11/12 md:w-[650px] md:h-[580px] h-full 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]">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
<div className="w-11/12 md:w-[650px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="modal-header-con">
|
||||
<h1 className="modal-title">
|
||||
{details.offer_code}
|
||||
</h1>
|
||||
<CloseIcon onClose={onClose} />
|
||||
@@ -128,7 +143,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
|
||||
<div className="md:flex bg-white dark:bg-dark-white text-slate-900 dark:text-white rounded-lg">
|
||||
<div className="p-4 w-full md:w-[75%] md:border-r-1">
|
||||
<div className="max-h-[240px] h-full">
|
||||
<div className="min-h-[240px]">
|
||||
<h2 className="font-semibold text-slate-900 dark:text-white tracking-wide">
|
||||
{details?.title}
|
||||
</h2>
|
||||
@@ -153,7 +168,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
},
|
||||
].map(({ name, content, danger }, idx) => (
|
||||
<div className={`my-3 md:flex items-center`} key={idx}>
|
||||
<label className="w-full md:w-[19%] tracking-wide font-semibold whitespace-pre-wrap">
|
||||
<label className="job-label w-full md:w-[19%]">
|
||||
{name}
|
||||
</label>
|
||||
<div
|
||||
@@ -198,7 +213,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
<hr />
|
||||
<div className="w-full flex flex-col gap-3">
|
||||
<div className="w-full">
|
||||
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
|
||||
<label className="job-label w-full">
|
||||
If you have any questions about this task:
|
||||
</label>
|
||||
<textarea
|
||||
@@ -218,7 +233,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
{errMsg.market && "Something went wrong"}
|
||||
</span>
|
||||
<button
|
||||
className="self-end w-[150px] h-[48px] rounded-full text-base bg-yellow-500 text-white"
|
||||
className="custom-btn self-end bg-yellow-500 text-white"
|
||||
name="market-message"
|
||||
onClick={MarketDetail}
|
||||
>
|
||||
@@ -235,7 +250,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
<div className="w-full md:w-[23%] h-full flex flex-col">
|
||||
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md md:min-h-[420px] flex flex-col justify-between">
|
||||
<div className="w-full flex flex-col justify-center pb-4 gap-2">
|
||||
<p className="w-full text-slate-900 tracking-wide my-1 font-semibold">
|
||||
<p className="job-label w-full">
|
||||
Interested in the task?
|
||||
</p>
|
||||
<hr />
|
||||
@@ -270,33 +285,39 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
|
||||
<div className="text-slate-900">
|
||||
<p className="flex items-center tracking-wide">
|
||||
Interest: <b className="ml-1">{details.interest_count}</b>
|
||||
<span className="job-label">Interest: </span> <b className="ml-1">{details.interest_count}</b>
|
||||
</p>
|
||||
<hr />
|
||||
<p className="my-1">Expire: {details.expire}</p>
|
||||
<p className="my-1 flex flex-col">
|
||||
<span className="job-label">Expire: </span>
|
||||
<span> {new Date(details.expire).toLocaleString()} </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="self-center w-[150px] mt-2 h-[48px] rounded-full text-base bg-transparent border border-red-500 text-red-500 mx-auto"
|
||||
name="cancel"
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
{/* END OF ACTION SECTION */}
|
||||
</div>
|
||||
<div className="modal-footer-wrapper">
|
||||
<button
|
||||
className="custom-btn bg-transparent border border-red-500 text-red-500 ml-auto"
|
||||
name="cancel"
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ModalCom>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default MarketPopUp;
|
||||
|
||||
const CloseIcon = ({ onClose }) => (
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={onClose}
|
||||
>
|
||||
<svg
|
||||
|
||||
@@ -546,13 +546,13 @@ function ActiveJobs(props) {
|
||||
|
||||
{/* MESSAGE SECTION */}
|
||||
<div className="w-full lg:w-1/2">
|
||||
<div className="flex justify-between items-center gap-5">
|
||||
<p className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2">
|
||||
<div className="flex justify-between items-center gap-5 justify-between">
|
||||
<p className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2 justify-between">
|
||||
<span>Message</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={popUpHandler}
|
||||
className="text-[12px] tracking-wider text-emerald-600 dark:text-emerald-300"
|
||||
className="text-[12px] tracking-wider text-gray-400 dark:text-slate-400"
|
||||
>
|
||||
View all
|
||||
</button>
|
||||
|
||||
@@ -4,6 +4,7 @@ import Layout from "../Partials/Layout";
|
||||
import MyJobTable from "./MyJobTable";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import AddJobPage from "../../views/AddJobPage";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function MyJobs(props) {
|
||||
let { state } = useLocation();
|
||||
@@ -32,8 +33,8 @@ export default function MyJobs(props) {
|
||||
<div className="notification-page w-full mb-10">
|
||||
<div className="notification-wrapper w-full">
|
||||
{/* heading */}
|
||||
<div className="sm:flex items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<div className="sm:flex items-center mb-2">
|
||||
<div className="w-full">
|
||||
<h1 className="text-26 font-bold flex items-center space-x-1 text-dark-gray dark:text-white gap-2">
|
||||
<span>My Jobs</span>
|
||||
|
||||
@@ -46,6 +47,17 @@ export default function MyJobs(props) {
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
// title = 'My Jobs'
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/myjobs", title: "My Jobs", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<MyJobTable MyJobList={props.MyJobList} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,9 @@ const FamilyWalletBox = lazy(() => import("./FamilyWalletBox"));
|
||||
const FamilyWalletCon = () => {
|
||||
const apiCall = new usersService();
|
||||
// const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
|
||||
|
||||
const {userDetails} = useSelector((state) => state?.userDetails); // GETS USER INFO
|
||||
|
||||
const { walletTable } = useSelector((state) => state.tableReload);
|
||||
|
||||
const [paymentHistory, setPaymentHistory] = useState({
|
||||
@@ -23,7 +26,7 @@ const FamilyWalletCon = () => {
|
||||
|
||||
const getFamilyWalletBal = () => {
|
||||
setFamilyWalletBal({loading:true, data: []})
|
||||
apiCall.getFamilyWallet({family_uid: localStorage.getItem("uid")}).then(res => {
|
||||
apiCall.getFamilyWallet({family_uid: userDetails.uid}).then(res => {
|
||||
setFamilyWalletBal({loading:false, data: res?.data?.result_list})
|
||||
}).catch(error => {
|
||||
setFamilyWalletBal({loading:false, data: []})
|
||||
|
||||
@@ -28,6 +28,7 @@ export default function OffersInterestTable({offerInterestList, className}) {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
|
||||
let imgServer = offerInterestList?.imgServer // FOR RENDERING IMAGE FROM SERVER
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full my-8 p-8 bg-white dark:bg-dark-white rounded-2xl section-shadow min-h-[520px] ${
|
||||
@@ -54,14 +55,19 @@ export default function OffersInterestTable({offerInterestList, className}) {
|
||||
</thead>
|
||||
<tbody className="h-full">
|
||||
{currentOfferInterestList?.map((item, index) => {
|
||||
let image = item.banner ? item.banner : 'default.jpg'
|
||||
// let image = item.banner ? item.banner : 'default.jpg'
|
||||
const image = localStorage.getItem("session_token")
|
||||
? `${imgServer}${localStorage.getItem("session_token")}/job/${
|
||||
item.job_uid
|
||||
}`
|
||||
: "";
|
||||
return (
|
||||
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
||||
<td className=" py-4">
|
||||
<div className="flex space-x-2 items-center">
|
||||
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<div className="min-w-[60px] max-w-[60px] min-h-[60px] max-h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={localImgLoad(`images/taskbanners/${image}`)}
|
||||
src={`${image}`}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
@@ -90,7 +96,7 @@ export default function OffersInterestTable({offerInterestList, className}) {
|
||||
<button
|
||||
onClick={() => {
|
||||
navigate("/manage-offer", {
|
||||
state: { ...item, pathname },
|
||||
state: { ...item, pathname, jobImage:image },
|
||||
});
|
||||
}}
|
||||
type="button"
|
||||
|
||||
@@ -56,13 +56,18 @@ export default function OthersInterestTable({othersInterestedList, className}) {
|
||||
</thead>
|
||||
<tbody className="h-full">
|
||||
{currentOthersInterestedList?.map((item, index) => {
|
||||
const image = localStorage.getItem("session_token")
|
||||
? `${othersInterestedList.imageServer}${localStorage.getItem("session_token")}/job/${
|
||||
item.job_uid
|
||||
}`
|
||||
: "";
|
||||
return (
|
||||
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
||||
<td className=" py-4">
|
||||
<div className="flex space-x-2 items-center">
|
||||
<div className="min-w-[60px] min-h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={dataImage1}
|
||||
src={image}
|
||||
alt="data"
|
||||
className="w-full h-full"
|
||||
/>
|
||||
|
||||
@@ -9,6 +9,7 @@ export default function OffersInterest(props) {
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const data1 = [];
|
||||
|
||||
export default function NewPaginatedList({
|
||||
data = data1,
|
||||
itemsPerPage = 5,
|
||||
filterItem,
|
||||
tableTitle,
|
||||
children,
|
||||
}) {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [filteredData, setFilteredData] = useState(data);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const [newData, setNewData] = useState([]);
|
||||
|
||||
const numberOfSelection = itemsPerPage;
|
||||
|
||||
const handlePrev = () => {
|
||||
if (currentPage != 0) {
|
||||
setCurrentPage((prev) => prev - numberOfSelection);
|
||||
}
|
||||
};
|
||||
const handleNext = () => {
|
||||
if (currentPage < data.length) {
|
||||
setCurrentPage((prev) => prev + numberOfSelection);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = ({ target: { value } }, name) => {
|
||||
setSearchTerm(value);
|
||||
let newFilteredData = data.filter((item) =>
|
||||
item[name].toLowerCase().startsWith(value.toLowerCase())
|
||||
);
|
||||
setFilteredData(newFilteredData);
|
||||
setCurrentPage(0);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setNewData(
|
||||
filteredData?.slice(currentPage, numberOfSelection + currentPage)
|
||||
);
|
||||
}, [currentPage, filteredData]);
|
||||
console.log("newData", newData, filteredData);
|
||||
return (
|
||||
<div className="w-full">
|
||||
<h1 className="text-2xl mb-5 font-semibold">{tableTitle}</h1>
|
||||
|
||||
{data.length > 0 && filterItem && (
|
||||
<div className="mb-10 flex justify-end items-center gap-2">
|
||||
{filterItem.map((item, index) => (
|
||||
<label
|
||||
key={index}
|
||||
className="flex flex-col sm:flex-row items-center gap-2 text-slate-600 dark:text-slate-100 transition-all duration-500"
|
||||
>
|
||||
Search by {item[0].toUpperCase() + item.slice(1)}
|
||||
<input
|
||||
name={item}
|
||||
type="text"
|
||||
className="py-1 px-2 text-sm min-w-[100px] text-black dark:text-white bg-white dark:bg-slate-800 rounded-full border-0 outline-none ring-1 ring-slate-300 dark:ring-white transition-all duration-500"
|
||||
value={searchTerm}
|
||||
onChange={(e) => {
|
||||
handleSearch(e, item);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{children({ data: newData })}
|
||||
|
||||
{/* 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`}
|
||||
>
|
||||
<
|
||||
</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`}
|
||||
>
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -89,7 +89,9 @@ export default function MobileSidebar({
|
||||
<ul className="flex flex-col space-y-6">
|
||||
{/* Using mini component reduces the bulk amount of html */}
|
||||
<ListItem
|
||||
title= {userDetails?.account_type == "FULL" ? "Dashboard" : "Home"}
|
||||
title={
|
||||
userDetails?.account_type == "FULL" ? "Dashboard" : "Home"
|
||||
}
|
||||
route="/"
|
||||
sidebar={sidebar}
|
||||
iconName="new-dashboard"
|
||||
@@ -190,17 +192,21 @@ export default function MobileSidebar({
|
||||
<div className="items">
|
||||
<ul className="flex flex-col space-y-6">
|
||||
{[
|
||||
{ name: "List", path: "/myjobs", iconName: "job-list" },
|
||||
{
|
||||
name: "List",
|
||||
path: "/myjobs",
|
||||
iconName: "job-list",
|
||||
},
|
||||
// {
|
||||
// name: "Waiting",
|
||||
// path: "/pend-interest",
|
||||
// iconName: "pending-job",
|
||||
// },
|
||||
{
|
||||
name: "Offers",
|
||||
path: "/my-offers",
|
||||
iconName: "pending-job",
|
||||
},
|
||||
{
|
||||
name: "Waiting",
|
||||
path: "/pend-interest",
|
||||
iconName: "pending-job",
|
||||
},
|
||||
{
|
||||
name: "Active",
|
||||
path: "/my-active-jobs",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { NavLink } from "react-router-dom";
|
||||
//import SideStatistics from "./SideStatistics";
|
||||
import { localImgLoad } from "../../lib";
|
||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||
import Icons from "../Helpers/Icons";
|
||||
|
||||
export default function RightSideBar({ myJobList }) {
|
||||
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
|
||||
@@ -81,6 +82,19 @@ export default function RightSideBar({ myJobList }) {
|
||||
{/* action */}
|
||||
</div>
|
||||
|
||||
<div className="item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 rounded-full flex items-center justify-center">
|
||||
<Icons name="pending-job" />
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/pend-interest">Waiting</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
{/* action */}
|
||||
</div>
|
||||
<div className="item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 rounded-full">
|
||||
@@ -235,6 +249,7 @@ export default function RightSideBar({ myJobList }) {
|
||||
/>
|
||||
</svg>
|
||||
)}
|
||||
|
||||
</span>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
{darkMode.theme === "light" ? "Dark" : "Light"} Mode
|
||||
@@ -274,6 +289,24 @@ export default function RightSideBar({ myJobList }) {
|
||||
{/* action */}
|
||||
</div>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
<img
|
||||
src={localImgLoad("images/icons/job_active.svg")}
|
||||
className="w-full h-full"
|
||||
alt="Active Task"
|
||||
/>
|
||||
</div>
|
||||
{/* name */}
|
||||
<div>
|
||||
<p className="text-thin-light-gray text-base font-medium">
|
||||
<NavLink to="/offer-interest">Offers Interest</NavLink>
|
||||
</p>
|
||||
</div>
|
||||
{/* action */}
|
||||
</div>
|
||||
|
||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||
{/* image */}
|
||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||
|
||||
@@ -216,11 +216,11 @@ export default function Sidebar({
|
||||
path: "/myjobs",
|
||||
iconName: "job-list",
|
||||
},
|
||||
{
|
||||
name: "Waiting",
|
||||
path: "/pend-interest",
|
||||
iconName: "pending-job",
|
||||
},
|
||||
// {
|
||||
// name: "Waiting",
|
||||
// path: "/pend-interest",
|
||||
// iconName: "pending-job",
|
||||
// },
|
||||
{
|
||||
name: "Offers",
|
||||
path: "/my-offers",
|
||||
|
||||
@@ -64,13 +64,13 @@ function DeleteJobPopout({ details, onClose, situation }) {
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation}>
|
||||
<div className="logout-modal-wrapper lg:w-[600px] 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 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">
|
||||
Delete Job
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={onClose}
|
||||
>
|
||||
<svg
|
||||
@@ -119,10 +119,10 @@ function DeleteJobPopout({ details, onClose, situation }) {
|
||||
{details.title}
|
||||
</p>
|
||||
<p className="text-lg tracking-wide text-dark-gray dark:text-white flex items-start gap-1">
|
||||
Price: {details.thePrice}
|
||||
<span className="job-label">Price: </span>{details.thePrice}
|
||||
</p>
|
||||
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
|
||||
Duration: {details.timeline_days} day(s)
|
||||
<span className="job-label">Duration: </span>{details.timeline_days} day(s)
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex space-x-2.5">
|
||||
|
||||
@@ -212,13 +212,13 @@ const EditJobPopOut = ({
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation}>
|
||||
<div className="logout-modal-wrapper w-11/12 lg:w-[600px] 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 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">
|
||||
Edit Job
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={onClose}
|
||||
>
|
||||
<svg
|
||||
@@ -328,8 +328,8 @@ const EditJobPopOut = ({
|
||||
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
|
||||
<div className="sm:w-[60%] w-full">
|
||||
<label
|
||||
htmlFor="Job Delivery Details"
|
||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
||||
htmlFor="job-label"
|
||||
className='job-label'
|
||||
>
|
||||
Job Delivery Details
|
||||
</label>
|
||||
@@ -352,7 +352,7 @@ const EditJobPopOut = ({
|
||||
<div className="sm:w-[35%] w-full">
|
||||
<div
|
||||
htmlFor="Job Categories"
|
||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
||||
className='job-label'
|
||||
id="checked-group"
|
||||
>
|
||||
Categories
|
||||
@@ -422,7 +422,7 @@ const EditJobPopOut = ({
|
||||
<div className="field w-1/2">
|
||||
<div className={`flex items-center justify-between`}>
|
||||
<label
|
||||
className="w-full input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex flex-col"
|
||||
className="job-label flex flex-col"
|
||||
htmlFor="timeline_days"
|
||||
>
|
||||
Timeline -
|
||||
|
||||
@@ -10,7 +10,12 @@ import localImgLoad from "../../lib/localImgLoad";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import { SocketValues } from "../Contexts/SocketIOContext";
|
||||
|
||||
function FamilyOfferJobPopout({ details, onClose, situation }) {
|
||||
|
||||
const {parentAssignJobToKid} = SocketValues()
|
||||
|
||||
const apiUrl = new usersService();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
@@ -69,6 +74,18 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
|
||||
message: `Offer ${name}ed Successfully`,
|
||||
trigger: "",
|
||||
});
|
||||
// trigger socket event to refresh parent side
|
||||
//SENDS MESSAGE TO SOCKET TO UPDATE PARENT ACCOUNT WHEN CHILD ACCEPTS OR REJECTS A JOB ASSIGNED BY PARENT
|
||||
// message, room
|
||||
let socketMsg = {
|
||||
"audience": "PARENT",
|
||||
"action": "REFRESH_TASK",
|
||||
"family_uid": sessionStorage.getItem('family_uid'),
|
||||
}
|
||||
let socketRoom = `FAMILY-${sessionStorage.getItem('parent_uid')}`
|
||||
parentAssignJobToKid(socketMsg, socketRoom) //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||
// end of socket event trigger
|
||||
|
||||
setTimeout(() => {
|
||||
onClose();
|
||||
dispatch(tableReload({ type: "MYTASKTABLE" }));
|
||||
|
||||
@@ -303,13 +303,13 @@ function JobListPopout({
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation} className="">
|
||||
<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-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
<div className="modal-header-con">
|
||||
<h1 className="modal-title">
|
||||
{details.title}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={onClose}
|
||||
>
|
||||
<svg
|
||||
|
||||
@@ -135,13 +135,13 @@ function PendingJobsPopout({ 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">
|
||||
Manage Pending Item
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={onClose}
|
||||
>
|
||||
<svg
|
||||
@@ -170,7 +170,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
||||
<p className="text-base font-semibold text-slate-900 dark:text-white tracking-wide">
|
||||
{details.title}
|
||||
</p>
|
||||
<div className="my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300">
|
||||
<div className="my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300 rounded-2xl">
|
||||
<span className="w-8 h-8 text-center text-sm rounded-full flex justify-center items-center text-red-300 bg-yellow-100">
|
||||
!
|
||||
</span>
|
||||
@@ -236,7 +236,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
||||
|
||||
{/* ACTION SECTION */}
|
||||
<div className="p-4 w-full md:w-1/4 h-full">
|
||||
<p className="mb-6 text-sm dark:text-white">Actions</p>
|
||||
<p className="job-label mb-6 dark:text-white">Actions</p>
|
||||
|
||||
<div className="mb-3">
|
||||
<p className="px-2 py-1 text-sm bg-slate-100">
|
||||
|
||||
+27
-1
@@ -154,7 +154,33 @@
|
||||
|
||||
@layer components{
|
||||
.job-label{
|
||||
@apply text-slate-900 dark:text-white tracking-wide font-semibold
|
||||
@apply text-base text-slate-900 dark:text-white tracking-wide font-semibold
|
||||
}
|
||||
.job-label-flex{
|
||||
@apply flex items-center gap-2
|
||||
}
|
||||
|
||||
/* STYLES FOR MODAL */
|
||||
/* Modal Header */
|
||||
.modal-header-con{
|
||||
@apply w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] bg-sky-blue/50 border-b dark:border-[#5356fb29] border-light-purple
|
||||
}
|
||||
.modal-title{
|
||||
@apply text-2xl leading-8 font-bold text-dark-gray dark:text-white tracking-wide flex items-center
|
||||
}
|
||||
.modal-close-btn{
|
||||
@apply text-[#000] dark:text-red-500
|
||||
}
|
||||
|
||||
/* modal footer */
|
||||
.modal-footer-wrapper{
|
||||
@apply py-2 px-4 border-t-2 flex justify-between items-center
|
||||
}
|
||||
/* END OF STYLES FOR MODAL BOX */
|
||||
|
||||
/* STYLES FOR BUTTON */
|
||||
.custom-btn {
|
||||
@apply px-2 min-w-[80px] h-11 flex justify-center items-center text-base rounded-full cursor-pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1174,7 +1174,7 @@ class usersService {
|
||||
return this.postAuxEnd("/suggeststatus", postData);
|
||||
}
|
||||
|
||||
// FUNCTION TO GET FAMILY WALLET
|
||||
// FUNCTION TO GET FAMILY WALLET AS A KID
|
||||
getFamilyWallet(reqData) {
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
@@ -1186,6 +1186,18 @@ class usersService {
|
||||
return this.postAuxEnd("/familywallet", postData);
|
||||
}
|
||||
|
||||
// FUNCTION TO GET FAMILY WALLET AS A PARENT
|
||||
getKidWallets(reqData) {
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_FAMILY_WALLET,
|
||||
...reqData,
|
||||
};
|
||||
return this.postAuxEnd("/kidwallets", postData);
|
||||
}
|
||||
|
||||
// FUNCTION TO START FAMILY TRANSFER
|
||||
familyTransferStart(reqData) {
|
||||
var postData = {
|
||||
|
||||
@@ -12,6 +12,8 @@ const initialState = {
|
||||
chatMessageList: false,
|
||||
marketTableList: false,
|
||||
familyOfferList: false,
|
||||
parentFamilyTaskList: false,
|
||||
offerInterestListReload: false,
|
||||
};
|
||||
|
||||
export const tableReloadSlice = createSlice({
|
||||
@@ -53,6 +55,12 @@ export const tableReloadSlice = createSlice({
|
||||
case "FAMILYOFFERLIST":
|
||||
state.familyOfferList = !state.familyOfferList;
|
||||
return;
|
||||
case "PARENTFAMILYTASKLIST": // reloads list of active family task on parent side
|
||||
state.parentFamilyTaskList = !state.parentFamilyTaskList;
|
||||
return;
|
||||
case "OFFERINTERESTLISTRELOAD": // to reload offer interest list of owner when a worker sends interest in a job
|
||||
state.offerInterestListReload = !state.offerInterestListReload;
|
||||
return;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ function AddJobPage({ action, situation, categories }) {
|
||||
return (
|
||||
<ModalCom action={action} situation={situation}>
|
||||
<div className="lg:w-[600px] w-11/12 lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white dark:text-white">
|
||||
<div className="heading flex justify-between items-center py-6 md:px-[30px] px-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
||||
<p className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
Create New Job
|
||||
</p>
|
||||
<div className="modal-header-con">
|
||||
<h1 className="modal-title">
|
||||
New Job
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
className="modal-close-btn"
|
||||
onClick={action}
|
||||
>
|
||||
<svg
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function MyReviewDueJobsPage() {
|
||||
let { othersInterestedTable } = useSelector((state) => state.tableReload); // FOR OTHERS INTERESTED TABLE RELOAD
|
||||
|
||||
const apiCall = new usersService();
|
||||
const [othersInterestedList, setOthersInterestedList] = useState({loading: true, data: []})
|
||||
const [othersInterestedList, setOthersInterestedList] = useState({loading: true, data: [], imageServer:''})
|
||||
|
||||
useEffect(() => {
|
||||
if(!state){
|
||||
@@ -26,9 +26,9 @@ export default function MyReviewDueJobsPage() {
|
||||
}else{
|
||||
newData = []
|
||||
}
|
||||
setOthersInterestedList({loading: false, data: newData})
|
||||
setOthersInterestedList({loading: false, data: newData, imageServer:res.data.session_image_server})
|
||||
}).catch(err => {
|
||||
setOthersInterestedList({loading: false, data: []})
|
||||
setOthersInterestedList({loading: false, data: [], imageServer:''})
|
||||
console.log('Error: ', err)
|
||||
})
|
||||
}, [othersInterestedTable]);
|
||||
|
||||
@@ -5,20 +5,33 @@ import OffersInterest from "../components/OffersInterest";
|
||||
|
||||
import usersService from "../services/UsersService";
|
||||
|
||||
import { SocketValues } from "../components/Contexts/SocketIOContext"; // for reading socket context values
|
||||
|
||||
export default function OffersInterestPage() {
|
||||
|
||||
const { offerInterestListReload } = useSelector((state) => state.tableReload); // table/list reload variable
|
||||
|
||||
const {userDetails} = useSelector((state) => state?.userDetails); // Gets USER Details
|
||||
|
||||
let {joinRoom} = SocketValues() // function to join room for socket
|
||||
|
||||
const apiCall = new usersService()
|
||||
|
||||
let {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
|
||||
|
||||
let [offerInterestList, setOfferInterestList] = useState({loading: true, data: []})
|
||||
let [offerInterestList, setOfferInterestList] = useState({loading: true, data: [], imgServer:''})
|
||||
|
||||
useEffect(()=>{
|
||||
apiCall.offersInterestList().then(res => {
|
||||
setOfferInterestList({loading: false, data: res.data.result_list})
|
||||
setOfferInterestList({loading: false, data: res.data.result_list, imgServer:res.data.session_image_server})
|
||||
}).catch(err => {
|
||||
setOfferInterestList({loading: false, data: []})
|
||||
setOfferInterestList({loading: false, data: [], imgServer:''})
|
||||
console.log('Error: ', err)
|
||||
})
|
||||
},[offerInterestListReload])
|
||||
|
||||
useEffect(()=>{
|
||||
joinRoom(`INTEREST-${userDetails?.uid}`)
|
||||
},[])
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user