Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f11e8b415 | |||
| a1d74b773d | |||
| 7969199584 | |||
| 9dd8f49ff8 | |||
| fa5e9b8107 | |||
| 3e7ab11e62 | |||
| 6f259ad8ad | |||
| a31a20652f | |||
| e3a5952675 | |||
| f48297c5c0 | |||
| 23e5a9aaa4 | |||
| 02d90ebb14 | |||
| 38b979a2e9 | |||
| 93d9afa417 | |||
| 1e2219fb00 | |||
| 560897f6f9 | |||
| 630a029c6e | |||
| 6e2fdc46d1 | |||
| d3b2cddd6c | |||
| f6bd70fdca | |||
| de3bfa2541 | |||
| cd60831f76 | |||
| 71152f7a05 | |||
| 8cbdb1b8a6 | |||
| abbf60ad48 | |||
| c956befed9 | |||
| a5dbeaecbf | |||
| 0b0b563dda | |||
| f8a3e42fe6 | |||
| ced88fa497 | |||
| 89e2527ba6 | |||
| 9e6b59624f | |||
| 1b6b4f17b0 | |||
| 8a9ec35994 | |||
| fa2102eb61 | |||
| bf73461c64 | |||
| 5ffa6eb691 | |||
| 5a0d8aebdb | |||
| e8ed10ddbf | |||
| cca423a41c | |||
| 6a6900a62b | |||
| c6b4fcc43d | |||
| 29510c3b85 | |||
| 1d8e54c57d | |||
| 426599dd1f | |||
| c8d6d3d7d4 | |||
| 593ea74388 | |||
| d81b9970b3 | |||
| 777ff54220 | |||
| 382a266b9a | |||
| 2d80dd9450 | |||
| 0eaa72a5ec | |||
| a2e2df867d | |||
| 10d4e169d3 | |||
| 79ed578483 | |||
| 25440a3c06 | |||
| 5f4c40a318 | |||
| ff7e8ea1ab | |||
| cba14f4265 | |||
| 9c342f87f7 | |||
| 498966dd23 | |||
| b282295924 | |||
| 7222a4d750 | |||
| 271f5635a0 | |||
| 86c4283507 | |||
| 5e5d953769 | |||
| aa7065c5b4 | |||
| 29fee11ec3 | |||
| 264d7b8501 | |||
| 8f90bcdf10 | |||
| 4b897cb3a9 | |||
| 0977650bf4 | |||
| 1f76dd0db8 | |||
| f772cf0a68 | |||
| c4c5c7967e | |||
| 45ecec24ac | |||
| 16fd35df83 | |||
| 3f6a391d30 | |||
| 5eb64f49c0 | |||
| 1761150bd3 | |||
| a4b15dd06e | |||
| 1a15410e4c | |||
| da1133ed43 | |||
| 23605bc358 | |||
| 2092682be6 | |||
| 0e270d8efa | |||
| 3bb4fe6a02 | |||
| fa728d3879 | |||
| a9ce76123b | |||
| 3ac1be9b89 | |||
| e4be117c90 | |||
| 58834cd7ca | |||
| 59945c28e4 | |||
| 0feaf42f49 | |||
| 5a623dd147 | |||
| 9265fde343 | |||
| 452bb73bef | |||
| cfec230ce3 | |||
| 87430f530d | |||
| 52cb0cb2da | |||
| a19df45997 | |||
| 7868e7d689 | |||
| 08f1ae1a9f | |||
| c4cc27490b | |||
| 90b609d457 | |||
| a6c6c36fbc | |||
| 03b79f0e0c | |||
| 0af52df1d2 | |||
| 9e1a68f81a | |||
| 12e4b7824a | |||
| 5769332e74 | |||
| bab0296f4f | |||
| d457550d58 | |||
| f106e17ce6 |
@@ -17,7 +17,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=300000
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
|
||||
REACT_APP_SESSION_EXPIRE_CHECKER=60000
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=300000
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
|
||||
REACT_APP_SESSION_EXPIRE_CHECKER=60000
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=300000
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
|
||||
REACT_APP_SESSION_EXPIRE_CHECKER=60000
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ import BlogPage from "./views/BlogPage";
|
||||
import MyReviewDueJobsPage from "./views/MyReviewDueJobsPage";
|
||||
import OffersInterestPage from "./views/OffersInterestPage";
|
||||
import ManageInterestOfferPage from './views/ManageInterestOfferPage'
|
||||
import MyWaitingJobsPage from "./views/MyWaitingJobsPage";
|
||||
import FamilyMarketPage from "./views/FamilyMarketPage";
|
||||
|
||||
export default function Routers() {
|
||||
return (
|
||||
@@ -86,13 +88,15 @@ export default function Routers() {
|
||||
<Route exact path="/notification" element={<Notification />} />
|
||||
<Route exact path="/market-place" element={<MarketPlacePage />} />
|
||||
<Route exact path="/market" element={<MarketPlacePage />} />
|
||||
<Route exact path="/familymarket" element={<FamilyMarketPage />} />
|
||||
<Route exact path="/notification" element={<Notification />} />
|
||||
<Route exact path="/mytask" element={<MyTaskPage />} />
|
||||
<Route exact path="/myjobs" element={<MyJobsPage />} />
|
||||
<Route exact path="/add-job" element={<AddJobPage />} />
|
||||
{/* <Route exact path="/add-job" element={<AddJobPage />} /> */}
|
||||
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
|
||||
<Route exact path="/my-pastdue-jobs" element={<MyPastDueJobsPage />} />
|
||||
<Route exact path="/my-pending-jobs" element={<MyPendingJobsPage />} />
|
||||
<Route exact path="/pend-interest" element={<MyWaitingJobsPage />} />
|
||||
<Route exact path="/my-review-jobs" element={<MyReviewDueJobsPage />} />
|
||||
<Route exact path="/acc-family" element={<FamilyAccPage />} />
|
||||
<Route exact path="/manage-family" element={<FamilyManagePage />} />
|
||||
|
||||
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" id="delete"><g color="#000"><path fill="#ee4c45" style="line-height:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;block-progression:tb;white-space:normal;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" d="M12 1028.362c-6.626 0-12 5.374-12 12s5.374 12 12 12 12-5.374 12-12-5.374-12-12-12z" font-family="sans-serif" font-weight="400" overflow="visible" transform="translate(0 -1028.362)"></path><path fill="#fff" style="isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" d="M10.5 1034.362v1h-3v1h9v-1h-3v-1h-3zm-2 3v9h7v-9h-7zm1 1h1v7h-1v-7zm2 0h1v7h-1v-7zm2 0h1v7h-1v-7z" overflow="visible" transform="translate(0 -1028.362)"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 841 B |
@@ -0,0 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 60 60" viewBox="0 0 60 60" id="edit"><path fill="#3B4652" d="M52.9687347,19.3099976l-2.7999878-2.7999878c-0.9099731-0.9100342-2.3899536-0.9100342-3.2999878,0
|
||||
l-1.4129639,1.4129639c0.0185547,0.017395,0.0423584,0.0234985,0.0601196,0.0422974l5.7765503,6.1199341
|
||||
c0.0361328,0.038269,0.0506592,0.0881348,0.0813599,0.1296997l1.5949097-1.5949097
|
||||
C53.8787689,21.7099609,53.8787689,20.2199707,52.9687347,19.3099976z"></path><path fill="#2B79C2" d="M10.8887787,25.5499878H34.998764l7.5900269-7.5900269l1.7599487-1.75V9c0-1.6500244-1.3499756-3-3-3h-32
|
||||
c-1.6599731,0-3,1.3499756-3,3v42c0,1.6499634,1.3400269,3,3,3h32c1.6500244,0,3-1.3500366,3-3V34.0700073l-5.8899536,5.8800049
|
||||
c-0.3099976,0.3199463-0.7000122,0.5599976-1.1199951,0.7099609l-7.2200317,2.5200195
|
||||
c-0.3099976,0.1099854-0.6500244,0.1699829-0.9899902,0.1699829c-0.7800293,0-1.5200195-0.2999878-2.0900269-0.8399658
|
||||
c-0.3399658-0.3400269-0.5799561-0.7400513-0.7299805-1.1600342H10.8887787c-0.5599976,0-1-0.4500122-1-1s0.4400024-1,1-1
|
||||
h15.4199829v-0.0100098l1.7000122-4.8899536H10.8887787c-0.5599976,0-1-0.4500122-1-1c0-0.5500488,0.4400024-1,1-1H28.708786
|
||||
l0.0999756-0.3000488c0.1699829-0.4699707,0.4400024-0.8800049,0.789978-1.1900024l3.4000244-3.4099731H10.8887787
|
||||
c-0.5599976,0-1-0.4500122-1-1S10.3287811,25.5499878,10.8887787,25.5499878z M10.8887787,46.25h24.9099731
|
||||
c0.5599976,0,1,0.4500122,1,1s-0.4400024,1-1,1H10.8887787c-0.5599976,0-1-0.4500122-1-1S10.3287811,46.25,10.8887787,46.25z
|
||||
M10.8887787,11.75h24.9099731c0.5599976,0,1,0.4500122,1,1s-0.4400024,1-1,1H10.8887787c-0.5599976,0-1-0.4500122-1-1
|
||||
S10.3287811,11.75,10.8887787,11.75z M10.8887787,18.6499634h24.9099731c0.5599976,0,1,0.4500122,1,1c0,0.5500488-0.4400024,1-1,1
|
||||
H10.8887787c-0.5599976,0-1-0.4499512-1-1C9.8887787,19.0999756,10.3287811,18.6499634,10.8887787,18.6499634z"></path><path fill="#3B4652" d="M30.9387665,32.4400024c-0.1099854,0.0999756-0.1900024,0.2299805-0.2399902,0.3699951
|
||||
l-2.5100098,7.2099609c-0.1300049,0.3600464-0.039978,0.7700195,0.2299805,1.0400391
|
||||
c0.2000122,0.1900024,0.4500122,0.289978,0.710022,0.289978c0.1099854,0,0.2199707-0.0200195,0.3300171-0.0599976
|
||||
l7.2099609-2.5100098c0.1400146-0.0499878,0.2700195-0.1300049,0.3800049-0.2399902l12.5599976-12.5599976l-5.9299927-6.2799683
|
||||
L30.9387665,32.4400024z"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 159 KiB |
@@ -1,32 +1,37 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Field, Form, Formik } from "formik";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import * as Yup from "yup";
|
||||
import usersService from "../../services/UsersService";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import usersService from "../../services/UsersService";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import { Field, Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
country: Yup.string()
|
||||
.min(1, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Country is required"),
|
||||
price: Yup.number()
|
||||
.typeError("you must specify a number")
|
||||
price: Yup.string()
|
||||
.typeError("Invalid number")
|
||||
.min(1, "Price must be greater than 0")
|
||||
.test("no-e", "Invalid number", (value) => {
|
||||
if (value && /\d+e/.test(value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.required("Price is required"),
|
||||
title: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(100, "Maximum 25 characters")
|
||||
.min(25, "Minimum 25 characters")
|
||||
.max(45, "Maximum 45 characters")
|
||||
.required("Title is required"),
|
||||
description: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.min(25, "Minimum 25 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Description is required"),
|
||||
job_detail: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.min(25, "Minimum 25 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Details is required"),
|
||||
timeline_days: Yup.number()
|
||||
@@ -38,19 +43,18 @@ const validationSchema = Yup.object().shape({
|
||||
|
||||
function AddJob({ popUpHandler, categories }) {
|
||||
const ApiCall = new usersService();
|
||||
|
||||
let dispatch = useDispatch();
|
||||
|
||||
let { userDetails } = useSelector((state) => state.userDetails);
|
||||
|
||||
let [country, setCountry] = useState({
|
||||
let [currency, setCurrency] = useState({
|
||||
loading: true,
|
||||
status: false,
|
||||
data: [],
|
||||
}); // To Hold the array of country getUserCountry returns
|
||||
data: null,
|
||||
}); // To Hold the array of currency getUserCurrency returns
|
||||
|
||||
let initialValues = {
|
||||
// initial values for formik
|
||||
country: userDetails.country,
|
||||
country: "",
|
||||
price: "",
|
||||
title: "",
|
||||
description: "",
|
||||
@@ -65,31 +69,42 @@ function AddJob({ popUpHandler, categories }) {
|
||||
message: "",
|
||||
}); // Holds state when submit button is pressed
|
||||
|
||||
// FUNCTION TO GET COUNTRY
|
||||
const getUserCountry = () => {
|
||||
setCountry((prev) => ({ ...prev, loading: true }));
|
||||
ApiCall.getSignupCountryData()
|
||||
// FUNCTION TO GET Currency
|
||||
const getUserCurrency = () => {
|
||||
setCurrency((prev) => ({ ...prev, loading: true }));
|
||||
ApiCall.getUserWallets()
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 1) {
|
||||
setCountry({ loading: false, status: true, data: [] });
|
||||
if (res.data.internal_return < 0) {
|
||||
setCurrency({ loading: false, status: true, data: [] });
|
||||
return;
|
||||
}
|
||||
setCountry({
|
||||
console.log("Res for currency >> ", res);
|
||||
|
||||
setCurrency({
|
||||
loading: false,
|
||||
status: true,
|
||||
data: res.data.signup_country,
|
||||
data: res.data.result_list,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
setCountry({ loading: false, status: false, data: [] });
|
||||
setCurrency({ loading: false, status: false, data: [] });
|
||||
});
|
||||
};
|
||||
|
||||
// FUNCTION TO HANDLE ADD JOB FORM
|
||||
const handleAddJob = (values, helpers) => {
|
||||
values.category = values.category?.join("@");
|
||||
let reqData = {
|
||||
country: values?.country,
|
||||
price: Number(values.price) * 100,
|
||||
title: values?.title,
|
||||
description: values?.description,
|
||||
job_detail: values?.job_detail,
|
||||
timeline_days: values?.timeline_days,
|
||||
category: values.category?.join("@"),
|
||||
};
|
||||
|
||||
setRequestStatus({ loading: true, status: false, message: "" });
|
||||
ApiCall.jobManagerCreateJob(values)
|
||||
ApiCall.jobManagerCreateJob(reqData)
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 1) {
|
||||
setRequestStatus({
|
||||
@@ -97,6 +112,9 @@ function AddJob({ popUpHandler, categories }) {
|
||||
status: false,
|
||||
message: "Could not complete your request at the moment",
|
||||
});
|
||||
setTimeout(() => {
|
||||
popUpHandler();
|
||||
}, 1500);
|
||||
return;
|
||||
}
|
||||
setRequestStatus({
|
||||
@@ -113,7 +131,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "Opps! soemthing went wrong. Try Again",
|
||||
message: "Opps! something went wrong. Try Again",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -124,10 +142,9 @@ function AddJob({ popUpHandler, categories }) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getUserCountry();
|
||||
getUserCurrency();
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between">
|
||||
<Formik
|
||||
@@ -141,46 +158,41 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<div className="flex flex-col-reverse sm:flex-row">
|
||||
<div className="fields w-full">
|
||||
{/* inputs starts here */}
|
||||
{/* country */}
|
||||
<div className="xl:flex xl:space-x-7 mb-[5px]">
|
||||
<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 block"
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
|
||||
>
|
||||
Country
|
||||
Currency
|
||||
{props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>}
|
||||
</label>
|
||||
<select
|
||||
id="country"
|
||||
name="country"
|
||||
disabled
|
||||
value={props.values.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`}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
>
|
||||
{country.loading ? (
|
||||
{currency.loading ? (
|
||||
<option className="text-slate-500 text-lg" value="">
|
||||
Loading...
|
||||
</option>
|
||||
) : country.data.length ? (
|
||||
) : currency.data.length ? (
|
||||
<>
|
||||
<option className="text-slate-500 text-lg" value="">
|
||||
Select...
|
||||
Select a currency
|
||||
</option>
|
||||
{country.data.map((item, index) => {
|
||||
if (item[0] == userDetails.country) {
|
||||
return (
|
||||
<option
|
||||
key={index}
|
||||
className="text-slate-500 text-lg"
|
||||
value={item[0]}
|
||||
>
|
||||
{item[1]}
|
||||
</option>
|
||||
);
|
||||
}
|
||||
})}
|
||||
{currency.data?.map((item, index) => (
|
||||
<option
|
||||
key={index}
|
||||
className="text-slate-500 text-lg"
|
||||
value={item?.country}
|
||||
>
|
||||
{item?.description}
|
||||
</option>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<option className="text-slate-500 text-lg" value="">
|
||||
@@ -203,7 +215,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
value={props.values.price}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
errorBorder={props.errors.price && props.touched.price}
|
||||
error={props.errors.price && props.touched.price && props.errors.price}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -221,7 +233,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
value={props.values.title}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
errorBorder={props.errors.title && props.touched.title}
|
||||
error={props.errors.title && props.touched.title && props.errors.title}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -237,7 +249,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
value={props.values.description}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
errorBorder={props.errors.description && props.touched.description}
|
||||
error={props.errors.description && props.touched.description && props.errors.description}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -246,14 +258,15 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<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"'
|
||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1'
|
||||
>
|
||||
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-6 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] border border-[#dce4e9] rounded-[10px]`}
|
||||
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={props.values.job_detail}
|
||||
@@ -275,8 +288,11 @@ function AddJob({ popUpHandler, categories }) {
|
||||
role="group"
|
||||
aria-labelledby="checked-group"
|
||||
>
|
||||
{Object.entries(categories).map(([key, value]) => (
|
||||
<label key={key} className="flex gap-1 w-full items-center">
|
||||
{Object?.entries(categories).map(([key, value]) => (
|
||||
<label
|
||||
key={key}
|
||||
className="flex gap-1 w-full items-center"
|
||||
>
|
||||
<Field
|
||||
type="checkbox"
|
||||
name="category"
|
||||
@@ -285,16 +301,13 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<span className="text-[13.975px]">{value}</span>
|
||||
</label>
|
||||
))}
|
||||
<span className="h-5 text-sm italic text-[#cf3917]">
|
||||
{props.errors.category &&
|
||||
props.touched.category &&
|
||||
"please select a category"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className={`${!props.errors && "invisible"} h-5`}>
|
||||
{props.errors.job_detail && props.touched.job_detail && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.job_detail}
|
||||
</p>
|
||||
)}
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<div className="field w-full mb-[5px]">
|
||||
@@ -313,7 +326,12 @@ function AddJob({ popUpHandler, categories }) {
|
||||
<Field
|
||||
component="select"
|
||||
name="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 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 ${
|
||||
props.errors.timeline_days &&
|
||||
props.touched.timeline_days
|
||||
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
|
||||
: "border border-[#f5f8fa] dark:border-[#5e6278]"
|
||||
}`}
|
||||
value={props.values.timeline_days}
|
||||
>
|
||||
<option value="">Select Duration</option>
|
||||
@@ -354,8 +372,8 @@ function AddJob({ popUpHandler, categories }) {
|
||||
|
||||
<div className="w-full h-[70px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
||||
<div className="flex items-center space-x-4 mr-9">
|
||||
<Link
|
||||
to="/myjobs"
|
||||
<button
|
||||
type="button"
|
||||
className="text-18 text-light-red tracking-wide "
|
||||
>
|
||||
<span
|
||||
@@ -365,7 +383,7 @@ function AddJob({ popUpHandler, categories }) {
|
||||
{" "}
|
||||
Cancel
|
||||
</span>
|
||||
</Link>
|
||||
</button>
|
||||
|
||||
{requestStatus.loading ? (
|
||||
<LoadingSpinner size="8" color="sky-blue" />
|
||||
@@ -403,3 +421,10 @@ const publicArray = [
|
||||
{ duration: 21, name: "3 weeks" },
|
||||
{ duration: 28, name: "4 weeks" },
|
||||
];
|
||||
|
||||
// .test("no-e", "Invalid number", (value) => {
|
||||
// if (value && /\d+e/.test(value)) {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// })
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function CollectionTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<CollectionCard key={datas.uniqKey} collectionData={datas} />
|
||||
|
||||
@@ -42,7 +42,9 @@ export default function CreateSaleSlider({
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Sell</h1>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Create for Sell
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<button onClick={nextHandler} type="button">
|
||||
@@ -89,7 +91,7 @@ export default function CreateSaleSlider({
|
||||
<div className="trending-products relative w-full">
|
||||
<SliderCom selector={trendingSlider} settings={settings}>
|
||||
{products &&
|
||||
products.length > 0 &&
|
||||
products?.length > 0 &&
|
||||
products.map((item) => (
|
||||
<ProductCardStyleTwo
|
||||
key={item.id}
|
||||
|
||||
@@ -49,7 +49,9 @@ export default function CreatedBidsSlider({
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Bits</h1>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Create for Bits
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<button onClick={nextHandler} type="button">
|
||||
@@ -96,7 +98,7 @@ export default function CreatedBidsSlider({
|
||||
<div className="trending-products relative w-full">
|
||||
<SliderCom selector={trendingSlider} settings={settings}>
|
||||
{products &&
|
||||
products.length > 0 &&
|
||||
products?.length > 0 &&
|
||||
products.map((item) => (
|
||||
<ProductCardStyleOne
|
||||
key={item.id}
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function OnSaleTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<ProductCardStyleTwo key={datas.id} datas={datas} />
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function OwnTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<ProductCardStyleOne key={datas.id} datas={datas} />
|
||||
|
||||
@@ -18,6 +18,9 @@ export default function Login() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
let [loginType, setLoginType] = useState({ full: true, family: false });
|
||||
const [selectedLoginType, setSelectedLoginType] = useState(
|
||||
document.cookie.includes("loginType=family") ? "loginfamily" : "loginfull"
|
||||
);
|
||||
|
||||
const [checked, setValue] = useState(false);
|
||||
const [loginLoading, setLoginLoading] = useState(false);
|
||||
@@ -77,6 +80,10 @@ export default function Login() {
|
||||
login_mode: 1100,
|
||||
action: 11025,
|
||||
};
|
||||
|
||||
// Clear the loginType cookie if the user switches to loginfull
|
||||
document.cookie =
|
||||
"loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
|
||||
} else if (name == "loginfamily") {
|
||||
// Post Data Info for family Login
|
||||
postData = {
|
||||
@@ -86,6 +93,8 @@ export default function Login() {
|
||||
login_mode: 1105,
|
||||
action: 11025,
|
||||
};
|
||||
// Set the loginType cookie to remember the user's selection
|
||||
document.cookie = "loginType=family; expires=Session; path=/;";
|
||||
} else {
|
||||
setLoginLoading(false);
|
||||
setMsgError("Invalid Login Type. Consider refreshing the page");
|
||||
@@ -127,15 +136,22 @@ export default function Login() {
|
||||
};
|
||||
|
||||
const googleLogin = useGoogleLogin({
|
||||
flow: 'auth-code',
|
||||
ux_mode:'redirect',
|
||||
flow: "auth-code",
|
||||
ux_mode: "redirect",
|
||||
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
|
||||
onSuccess: async (codeResponse) => {
|
||||
console.log("GOOGLE LOGIN GOOD --- ",codeResponse);
|
||||
console.log("GOOGLE LOGIN GOOD --- ", codeResponse);
|
||||
},
|
||||
onError: (errorResponse) => console.log(errorResponse),
|
||||
});
|
||||
|
||||
// In order to update the selected login type whenever the component renders
|
||||
useEffect(() => {
|
||||
setSelectedLoginType(
|
||||
document.cookie.includes("loginType=family") ? "loginfamily" : "loginfull"
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setMail("");
|
||||
setPassword("");
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function SignUp() {
|
||||
|
||||
if (res.status === 200) {
|
||||
const { data } = res;
|
||||
if (data.status === -1 && data.acc === "DULPICATE") {
|
||||
if (data && data.acc === "DULPICATE") {
|
||||
setMsgError("This account has been already created");
|
||||
setSignUpLoading(false);
|
||||
}
|
||||
@@ -108,12 +108,12 @@ export default function SignUp() {
|
||||
|
||||
useEffect(() => {
|
||||
getCountryList();
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="layout-wrapper login">
|
||||
<div className="main-wrapper w-full xl:h-screen h-full xl:py-10 py-12 overflow-y-auto">
|
||||
<div className="main-wrapper login-wrapper w-full xl:h-screen h-full xl:py-10 py-12 overflow-y-auto">
|
||||
<div className=" h-full">
|
||||
<div className="flex-1 flex justify-center items-center">
|
||||
<div className="w-full">
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function CollectionTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<CollectionCard key={datas.uniqKey} collectionData={datas} />
|
||||
|
||||
@@ -42,7 +42,9 @@ export default function CreateSaleSlider({
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Sell</h1>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Create for Sell
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<button onClick={nextHandler} type="button">
|
||||
@@ -89,7 +91,7 @@ export default function CreateSaleSlider({
|
||||
<div className="trending-products relative w-full">
|
||||
<SliderCom selector={trendingSlider} settings={settings}>
|
||||
{products &&
|
||||
products.length > 0 &&
|
||||
products?.length > 0 &&
|
||||
products.map((item) => (
|
||||
<ProductCardStyleTwo
|
||||
key={item.id}
|
||||
|
||||
@@ -49,7 +49,9 @@ export default function CreatedBidsSlider({
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Bits</h1>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Create for Bits
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<button onClick={nextHandler} type="button">
|
||||
@@ -96,7 +98,7 @@ export default function CreatedBidsSlider({
|
||||
<div className="trending-products relative w-full">
|
||||
<SliderCom selector={trendingSlider} settings={settings}>
|
||||
{products &&
|
||||
products.length > 0 &&
|
||||
products?.length > 0 &&
|
||||
products.map((item) => (
|
||||
<ProductCardStyleOne
|
||||
key={item.id}
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function OnSaleTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<ProductCardStyleTwo key={datas.id} datas={datas} />
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function OwnTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<ProductCardStyleOne key={datas.id} datas={datas} />
|
||||
|
||||
@@ -13,38 +13,14 @@ export default function AvailableJobsCard({
|
||||
}) {
|
||||
//debugger;
|
||||
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
|
||||
const [manageInt, setManageInt] = useState(null);
|
||||
const [imageUrl, setImageUrl] = useState("");
|
||||
|
||||
const navigate = useNavigate();
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
const marketInterestData = useCallback(async () => {
|
||||
let { offer_code } = datas;
|
||||
let reqData = { offer_code };
|
||||
|
||||
try {
|
||||
const manageInt = await apiCall.MarketInterest(reqData);
|
||||
const manageIntRes = await manageInt?.data;
|
||||
setManageInt(manageIntRes);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}, [apiCall, datas]);
|
||||
|
||||
let thePrice = PriceFormatter(
|
||||
datas?.price * 0.01,
|
||||
datas?.currency_code,
|
||||
datas?.currency
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!datas) {
|
||||
navigate("/market", { replace: true });
|
||||
}
|
||||
marketInterestData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const imagePath = require(`../../assets/images/${datas.thumbnil}`); // Replace with your directory path for local images
|
||||
setImageUrl(imagePath);
|
||||
@@ -187,7 +163,7 @@ export default function AvailableJobsCard({
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="block sm:flex flex-wrap gap-4">
|
||||
<p className="text-sm text-thin-light-gray">
|
||||
<p className="text-sm text-thin-light-gray flex flext-start gap-1">
|
||||
Price: <span className="text-purple">{thePrice}</span>
|
||||
</p>
|
||||
<p className="text-sm text-thin-light-gray">
|
||||
@@ -227,7 +203,6 @@ export default function AvailableJobsCard({
|
||||
setMarketPopUp({ show: false, data: {} });
|
||||
}}
|
||||
situation={marketPopUp.show}
|
||||
marketInt={manageInt}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
import Icons from "../Helpers/Icons";
|
||||
|
||||
export default function FamilyMarketCard({
|
||||
className,
|
||||
datas,
|
||||
hidden = false,
|
||||
}) {
|
||||
// debugger;
|
||||
const [addFavorite, setValue] = useState(datas.whishlisted);
|
||||
const [options, setOption] = useState(false);
|
||||
const favoriteHandler = () => {
|
||||
if (!addFavorite) {
|
||||
setValue(true);
|
||||
toast.success("Added to Favorite List");
|
||||
} else {
|
||||
setValue(false);
|
||||
toast.warn("Remove to Favorite List");
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className={`card-style-two w-full h-[336px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-col justify-between w-full h-full">
|
||||
<div className="thumbnail-area w-full">
|
||||
<div
|
||||
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
|
||||
style={{
|
||||
background: `url(${`https://blog.float.sg/wp-content/uploads/${datas.meta_value}`}) 0% 0% / cover no-repeat`,
|
||||
}}
|
||||
>
|
||||
<div className="product-two-options flex justify-between mb-5 relative">
|
||||
<div className="status">
|
||||
{datas?.isActive && (
|
||||
<span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">
|
||||
Active
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{hidden && <div className="flex justify-center"></div>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="details-area">
|
||||
{/* title */}
|
||||
<Link to="/shop-details" className="mb-2.5">
|
||||
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
|
||||
{datas.post_title}
|
||||
</h1>
|
||||
</Link>
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center space-x-2"></div>
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -23,20 +23,20 @@ export default function HomeBannerOffersCard(props) {
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col justify-between h-full">
|
||||
<div className="content flex justify-between items-center mb-5">
|
||||
<div className="content flex justify-between items-center">
|
||||
<div className="siderCardHeader">
|
||||
<h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
<span className="heroSilderTitle">{props.itemData.title}</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-[233px]">
|
||||
<div className="flex flex-col justify-around items-center flex-1">
|
||||
<div className="siderCardDescription">
|
||||
{props.itemData.description}
|
||||
</div>
|
||||
<div className="siderCardButton">
|
||||
[ {props.itemData.button_text} ]
|
||||
</div>
|
||||
<button className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
{props.itemData.button_text}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
@@ -6,6 +6,7 @@ import CountDown from "../Helpers/CountDown";
|
||||
import Icons from "../Helpers/Icons";
|
||||
|
||||
export default function ProductCardStyleOne({ datas, hidden = false }) {
|
||||
const [imageUrl, setImageUrl] = useState("");
|
||||
const [addFavorite, setValue] = useState(false);
|
||||
const [options, setOption] = useState(false);
|
||||
const favoriteHandler = () => {
|
||||
@@ -17,6 +18,8 @@ export default function ProductCardStyleOne({ datas, hidden = false }) {
|
||||
toast.warn("Remove to Favorite List");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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">
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
export default function ProductCardStyleTwo({
|
||||
className,
|
||||
datas,
|
||||
hidden = false,
|
||||
bg
|
||||
}) {
|
||||
// debugger;
|
||||
const [addFavorite, setValue] = useState(datas.whishlisted);
|
||||
const [options, setOption] = useState(false);
|
||||
const favoriteHandler = () => {
|
||||
if (!addFavorite) {
|
||||
setValue(true);
|
||||
toast.success("Added to Favorite List");
|
||||
} else {
|
||||
setValue(false);
|
||||
toast.warn("Remove to Favorite List");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`card-style-two w-full h-[336px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-col justify-between w-full h-full">
|
||||
<div className="thumbnail-area w-full">
|
||||
<div
|
||||
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
|
||||
style={{
|
||||
// background: `url(${`https://blog.wrenchboard.com/wp-content/uploads/${datas.meta_value}`}) 0% 0% / cover no-repeat`,
|
||||
background: `url(${`${bg}${datas.meta_value}`}) 0% 0% / cover no-repeat`,
|
||||
}}
|
||||
>
|
||||
<div className="product-two-options flex justify-between mb-5 relative">
|
||||
<div className="status">
|
||||
{datas?.isActive && (
|
||||
<span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">
|
||||
Active
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{hidden && <div className="flex justify-center"></div>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="details-area">
|
||||
{/* title */}
|
||||
<a href={datas.guid} target="_blank" className="mb-2.5" rel="noreferrer">
|
||||
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
|
||||
{datas.post_title || "dummy title..."}
|
||||
</h1>
|
||||
</a>
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center space-x-2"></div>
|
||||
<div className="my-1">
|
||||
<a
|
||||
href={datas.guid}
|
||||
target="_blank"
|
||||
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
|
||||
rel="noreferrer"
|
||||
>
|
||||
View
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -11,6 +11,7 @@ export default function FamilyManage() {
|
||||
let location = useLocation();
|
||||
let navigate = useNavigate();
|
||||
let accountDetails = location?.state;
|
||||
|
||||
// tab handler
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import SiteService from "../../services/SiteService";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import DataIteration from "../Helpers/DataIteration";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import collections from "../../data/collectionplan_data.json";
|
||||
import FamilyMarketCard from "../Cards/FamilyMarketCard";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export default function FamilyMarket() {
|
||||
const [selectTab, setValue] = useState("today");
|
||||
const [popUp, setPopUp] = useState(false);
|
||||
|
||||
const apiCall = useMemo(() => new SiteService(), []);
|
||||
|
||||
// This is to make sure it's called once and used everywhere
|
||||
let memberId = localStorage.getItem("member_id");
|
||||
let uid = localStorage.getItem("uid");
|
||||
let sessionId = localStorage.getItem("session_token");
|
||||
|
||||
const popUpHandler = () => {
|
||||
setPopUp((prev) => !prev);
|
||||
};
|
||||
|
||||
// tab handler
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
{/*<CommonHead />*/}
|
||||
<div className="notification-page w-full mb-10">
|
||||
<div className="notification-wrapper w-full">
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
|
||||
<span
|
||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||
>
|
||||
Suggest Task to the Parents
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<div
|
||||
onClick={() => filterHandler("today")}
|
||||
className="relative"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Body */}
|
||||
<div className="filter-section w-full items-center sm:flex justify-between mb-6">
|
||||
{/* filter-search */}
|
||||
<div className="sm:w-1/2 w-full sm:pr-20 pr-0 mb-5 sm:mb-0">
|
||||
<SearchCom />
|
||||
</div>
|
||||
{/* filer-dropdown */}
|
||||
<div className="flex-1 flex sm:justify-end">
|
||||
<Link
|
||||
to="/upload-product"
|
||||
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
|
||||
>
|
||||
Any Other Task
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-section w-full-width">
|
||||
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
|
||||
<DataIteration
|
||||
datas={collections?.data}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={collections?.data.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<FamilyMarketCard key={datas.id} datas={datas} />
|
||||
)}
|
||||
</DataIteration>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{popUp && (
|
||||
<ModalCom action={popUpHandler} situation={popUp}>
|
||||
{/* */}
|
||||
</ModalCom>
|
||||
)}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
const CloseIcon = () => (
|
||||
<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"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
@@ -0,0 +1,263 @@
|
||||
import React, {useState, useEffect} from 'react'
|
||||
import ModalCom from '../../Helpers/ModalCom'
|
||||
import Detail from '../../jobPopout/popoutcomponent/Detail'
|
||||
import usersService from '../../../services/UsersService'
|
||||
import LoadingSpinner from '../../Spinners/LoadingSpinner'
|
||||
import { PriceFormatter } from '../../Helpers/PriceFormatter'
|
||||
|
||||
function AssignTaskPopout({action, situation, familyDetails}) {
|
||||
const apiCall = new usersService()
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: ''}) // HOLDS RESPONSE FOR SENDING API REQUEST
|
||||
|
||||
let [familyTask, setFamilyTask] = useState({loading: true, data: []})
|
||||
|
||||
let [taskType, setTaskType] = useState('select') // SWITCHES BTW SELECT TASK AND NEW TASK
|
||||
|
||||
let [activeTask, setActiveTask] = useState({id: 0, data: {}}) // HOLDS SELECTED TASK
|
||||
|
||||
const switchTaskType = ({target:{value}}) => { // FUNCTION TO CHANGE SELECTED ACTIVE TASK
|
||||
setTaskType(value)
|
||||
}
|
||||
|
||||
const handleActiveTask = (id=0, data={}) => { // FUNCTION TO CHANGE SELECTED ACTIVE TASK
|
||||
setActiveTask({id, data})
|
||||
}
|
||||
|
||||
const assignFamilyTask = () => {
|
||||
setRequestStatus({loading: true, status: false, message: ''})
|
||||
let reqData = {}
|
||||
if(taskType == 'select'){ // RUNS HERE IF TASK TYPE IS SELECT
|
||||
if(!Object.keys(activeTask.data).length){
|
||||
setRequestStatus({loading: false, status: false, message: 'No Task is seleted'})
|
||||
return setTimeout(()=>{
|
||||
setRequestStatus({loading: false, status: false, message: ''})
|
||||
}, 3000)
|
||||
}
|
||||
reqData = { // API PAYLOADS
|
||||
job_id: activeTask.data?.job_id,
|
||||
job_uid: activeTask.data?.job_uid,
|
||||
family_uid: familyDetails.uid,
|
||||
job_description: activeTask.data?.description,
|
||||
assign_mode: 110011,
|
||||
}
|
||||
|
||||
apiCall.assignFamilyTask(reqData).then(res => {
|
||||
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: ''})
|
||||
}, 5000)
|
||||
}
|
||||
setRequestStatus({loading: false, status: true, message: 'action successful'})
|
||||
setTimeout(()=>{
|
||||
setRequestStatus({loading: false, status: false, message: ''})
|
||||
action() // FUNCTION THAT CLOSES THE MODAL BOX
|
||||
}, 5000)
|
||||
}).catch(err => {
|
||||
setRequestStatus({loading: false, status: false, message: 'An Error occured, try again'})
|
||||
setTimeout(()=>{
|
||||
setRequestStatus({loading: false, status: false, message: ''})
|
||||
}, 5000)
|
||||
})
|
||||
}
|
||||
|
||||
if(taskType == 'new'){ // RUNS HERE IF TASK TYPE IS NEW TASK
|
||||
console.log('TESTING')
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
const reqData = {
|
||||
limit: 30,
|
||||
offset: 0,
|
||||
job_type: 'FAMILY',
|
||||
action: 13005
|
||||
}
|
||||
apiCall.getMyJobList(reqData).then(res => {
|
||||
setFamilyTask({loading: false, data: res?.data?.result_list})
|
||||
if(res?.data?.result_list?.length){
|
||||
setActiveTask(prev => ({...prev, data:res?.data?.result_list[0]}))
|
||||
}
|
||||
}).catch(err => {
|
||||
setFamilyTask({loading: false, data: []})
|
||||
console.log('Error', err)
|
||||
})
|
||||
},[])
|
||||
return (
|
||||
<>
|
||||
<ModalCom
|
||||
action={action}
|
||||
situation={situation}
|
||||
>
|
||||
<div className="w-full h-full lg:w-[700px] lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||
<div className="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">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
Assign task to {familyDetails?.firstname}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
onClick={action}
|
||||
>
|
||||
<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"
|
||||
/>
|
||||
</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 md:grid-cols-2">
|
||||
<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>
|
||||
<div className='p-4 w-full h-[400px] overflow-y-auto bg-slate-100'>
|
||||
{
|
||||
taskType == 'select' ?
|
||||
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 tracking-wide">{item?.title}</p>
|
||||
</div>
|
||||
))
|
||||
:
|
||||
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center">No Task found!</p>
|
||||
:
|
||||
<p className="p-8 text-lg text-dark-gray dark:text-white tracking-wide text-center">SPACE FOR NEW TASK</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{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='flex items-center'>
|
||||
<div className="my-3 w-full flex items-center gap-1">
|
||||
<label className='text-slate-900 dark:text-white tracking-wide font-semibold'>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='text-slate-900 dark:text-white tracking-wide font-semibold'>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="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 text-slate-900 dark:text-white tracking-wide font-semibold">
|
||||
Delivery Detail
|
||||
</label>
|
||||
<textarea
|
||||
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
|
||||
rows="5"
|
||||
style={{ resize: "none" }}
|
||||
value={activeTask?.data?.job_detail}
|
||||
readOnly
|
||||
// onChange={handleInputChange}
|
||||
/>
|
||||
{/* <p>{}</p> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<></>
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* BTN */}
|
||||
<div className='p-2 border-t-2 flex justify-end items-center gap-3'>
|
||||
{/* error or success display */}
|
||||
{requestStatus.message != "" &&
|
||||
(!requestStatus.status ? (
|
||||
<div
|
||||
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
|
||||
>
|
||||
{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>
|
||||
)
|
||||
))}
|
||||
{/* End of error or success display */}
|
||||
<button
|
||||
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"
|
||||
>
|
||||
<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="px-1 w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
Assign
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</ModalCom>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AssignTaskPopout
|
||||
@@ -14,6 +14,9 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import profile from "../../../assets/images/profile-info-profile.png";
|
||||
import FamilyTasks from "./FamilyTasks";
|
||||
|
||||
import AssignTaskPopout from '../FamilyPopout/AssignTaskPopout'
|
||||
|
||||
|
||||
export default function FamilyManageTabs({
|
||||
className,
|
||||
accountDetails,
|
||||
@@ -50,6 +53,13 @@ export default function FamilyManageTabs({
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
let [familyTaskPopout, setFamilyTaskPopout] = useState(false) // DETERMINES WHEN FAMILY ADD TASK POPOUT DISPLAYS
|
||||
|
||||
const familyPopUpHandler = () => { // FUNCTION TO CHANGE THE FAMILY ADD TASK POPOIUT STATE
|
||||
setFamilyTaskPopout(prev => !prev)
|
||||
}
|
||||
|
||||
// For profile uploads
|
||||
const [profileImg, setProfileImg] = useState(profile);
|
||||
// profile img
|
||||
@@ -120,7 +130,7 @@ export default function FamilyManageTabs({
|
||||
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
>
|
||||
<div className="relative w-full overflow-x-auto sm:rounded-lg">
|
||||
<Suspense
|
||||
fallback={
|
||||
@@ -141,21 +151,31 @@ export default function FamilyManageTabs({
|
||||
</div>
|
||||
<div className="col-span-3 justify-self-end h-full w-full">
|
||||
<div className="flex flex-col w-full">
|
||||
<ul className="flex-[0.1] flex gap-2 items-center border-b border-b-[#FAFAF] w-full">
|
||||
{tabs.map(({ name, id }) => (
|
||||
<li
|
||||
onClick={() => tabHandler(name)}
|
||||
className={`p-4 flex hover:text-purple transition-all ease-in-out items-center cursor-pointer overflow-hidden text-xl ${
|
||||
tab === name
|
||||
? "text-purple border-r"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
key={id}
|
||||
>
|
||||
<h1>{name}</h1>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="w-full pr-8 flex items-center gap-1">
|
||||
<ul className="flex gap-2 items-center border-b border-b-[#FAFAF] w-full">
|
||||
{tabs.map(({ name, id }) => (
|
||||
<li
|
||||
onClick={() => tabHandler(name)}
|
||||
className={`p-4 flex hover:text-purple transition-all ease-in-out items-center cursor-pointer overflow-hidden text-xl ${
|
||||
tab === name
|
||||
? "text-purple border-r"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
key={id}
|
||||
>
|
||||
<h1>{name}</h1>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<button
|
||||
type="button"
|
||||
onClick={familyPopUpHandler}
|
||||
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Add task
|
||||
{/* {accountDetails?.firstname} */}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-[0.9] lg:min-h-[450px] h-full">
|
||||
{/* Your content here */}
|
||||
{tabs.map(({ name, id }) => {
|
||||
@@ -171,6 +191,7 @@ export default function FamilyManageTabs({
|
||||
className={className}
|
||||
loader={details.familyTasks.loading}
|
||||
familyData={details.familyTasks.data}
|
||||
accountDetails={accountDetails}
|
||||
/>
|
||||
)}
|
||||
{name === "Account" && (
|
||||
@@ -191,6 +212,15 @@ export default function FamilyManageTabs({
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
{/* FAMILY ADD TASK POPOUT */}
|
||||
{familyTaskPopout &&
|
||||
<AssignTaskPopout
|
||||
action={familyPopUpHandler}
|
||||
situation={familyTaskPopout}
|
||||
familyDetails={details.familyDetails.data}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ import PaginatedList from "../../Pagination/PaginatedList";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import ModalCom from "../../Helpers/ModalCom";
|
||||
import Detail from "../../jobPopout/popoutcomponent/Detail";
|
||||
|
||||
export default function FamilyTasks({ familyData, className, loader }) {
|
||||
|
||||
export default function FamilyTasks({ familyData, className, loader, accountDetails }) {
|
||||
let navigate = useNavigate();
|
||||
let { pathname } = useLocation();
|
||||
|
||||
@@ -34,7 +37,6 @@ export default function FamilyTasks({ familyData, className, loader }) {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{" "}
|
||||
{familyData && familyData?.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">
|
||||
@@ -72,7 +74,7 @@ export default function FamilyTasks({ familyData, className, loader }) {
|
||||
{value.title}
|
||||
</h1>
|
||||
<div className="flex gap-4 items-center">
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
<span className="text-sm text-thin-light-gray flex flex-start gap-1">
|
||||
Price:{" "}
|
||||
<span className="text-purple">
|
||||
{thePrice}
|
||||
@@ -105,9 +107,8 @@ export default function FamilyTasks({ familyData, className, loader }) {
|
||||
state: {
|
||||
...value,
|
||||
pathname,
|
||||
dueDate,
|
||||
thePrice,
|
||||
},
|
||||
accountDetails
|
||||
}
|
||||
});
|
||||
}}
|
||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
|
||||
@@ -1,59 +1,64 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
function CountDown({ lastDate = "" }) {
|
||||
// const [showDate, setDate] = useState(0);
|
||||
const [showHour, setHour] = useState(0);
|
||||
const [showMinute, setMinute] = useState(0);
|
||||
const [showSecound, setDateSecound] = useState(0);
|
||||
// count Down
|
||||
const provideDate = new Date(lastDate);
|
||||
// format date
|
||||
const year = provideDate.getFullYear();
|
||||
const month = provideDate.getMonth();
|
||||
// console.log(month);
|
||||
const date = provideDate.getDate();
|
||||
// console.log(date);
|
||||
const hours = provideDate.getHours();
|
||||
// console.log(hours);
|
||||
const minutes = provideDate.getMinutes();
|
||||
// console.log(minutes);
|
||||
const seconds = provideDate.getSeconds();
|
||||
// console.log(seconds);
|
||||
|
||||
// date calculation logic
|
||||
const _seconds = 1000;
|
||||
const _minutes = _seconds * 60;
|
||||
const _hours = _minutes * 60;
|
||||
const _date = _hours * 24;
|
||||
|
||||
// interval function
|
||||
const startInterval = () => {
|
||||
const timer = setInterval(() => {
|
||||
const now = new Date();
|
||||
const distance =
|
||||
new Date(year, month, date, hours, minutes, seconds).getTime() -
|
||||
now.getTime();
|
||||
if (distance < 0) {
|
||||
clearInterval(timer);
|
||||
return;
|
||||
}
|
||||
// setDate(Math.floor(distance / _date));
|
||||
setMinute(Math.floor((distance % _hours) / _minutes));
|
||||
setHour(Math.floor((distance % _date) / _hours));
|
||||
setDateSecound(Math.floor((distance % _minutes) / _seconds));
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// effect
|
||||
useEffect(() => {
|
||||
if (lastDate !== "") {
|
||||
startInterval();
|
||||
}
|
||||
// State to store the countdown values
|
||||
const [countdownValues, setCountdownValues] = useState({
|
||||
showHour: 0,
|
||||
showMinute: 0,
|
||||
showSecond: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (lastDate) {
|
||||
// Interval function to update countdown values
|
||||
const intervalId = setInterval(() => {
|
||||
const now = new Date().getTime();
|
||||
const targetDate = new Date(lastDate).getTime();
|
||||
const distance = targetDate - now;
|
||||
|
||||
if (distance < 0) {
|
||||
// If the countdown has reached zero or gone past the target date, clear the interval
|
||||
clearInterval(intervalId);
|
||||
setCountdownValues({
|
||||
showHour: 0,
|
||||
showMinute: 0,
|
||||
showSecond: 0,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the countdown values (days, hours, minutes, seconds)
|
||||
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor(
|
||||
(distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
|
||||
);
|
||||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||
|
||||
// since we don't have a slot for days...
|
||||
const totalHours = days * 24 + hours;
|
||||
|
||||
// Update the countdown values in the state
|
||||
setCountdownValues({
|
||||
showHour: totalHours,
|
||||
showMinute: minutes,
|
||||
showSecond: seconds,
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
// Clean up the interval on component unmount or when the lastDate prop changes
|
||||
return () => clearInterval(intervalId);
|
||||
}
|
||||
}, [lastDate]);
|
||||
|
||||
// Destructure the countdown values from the state
|
||||
const { showHour, showMinute, showSecond } = countdownValues;
|
||||
|
||||
return (
|
||||
<span>
|
||||
{showHour} : {showMinute} : {showSecound}
|
||||
{showHour < 10 ? "0" + showHour : showHour} :{" "}
|
||||
{showMinute < 10 ? "0" + showMinute : showMinute} :{" "}
|
||||
{showSecond < 10 ? "0" + showSecond : showSecond}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useRef } from "react";
|
||||
import Icons from "../../Icons";
|
||||
import { Link } from "react-router-dom";
|
||||
import Icons from "../../Icons";
|
||||
|
||||
export default function InputCom({
|
||||
label,
|
||||
@@ -22,7 +22,7 @@ export default function InputCom({
|
||||
spanTag,
|
||||
inputBg,
|
||||
direction,
|
||||
errorBorder
|
||||
error,
|
||||
}) {
|
||||
const inputRef = useRef(null);
|
||||
// Entry Validation
|
||||
@@ -41,27 +41,29 @@ export default function InputCom({
|
||||
// for Patterns
|
||||
const inputPatterns = () => {
|
||||
const inputConfig = inputConfigs[inputRef?.current?.name]?.pattern;
|
||||
return inputConfig || ""
|
||||
}
|
||||
return inputConfig || "";
|
||||
};
|
||||
return (
|
||||
<div className={`input-com ${parentClass}`}>
|
||||
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
|
||||
{label && (
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
|
||||
htmlFor={name}
|
||||
>
|
||||
{label}
|
||||
{spanTag &&
|
||||
spanTag == '*' ?
|
||||
{spanTag && spanTag == "*" ? (
|
||||
<span className="text-red-700 text-sm tracking-wide">
|
||||
{' '}{spanTag}
|
||||
{" "}
|
||||
{spanTag}
|
||||
</span>
|
||||
:
|
||||
) : (
|
||||
<span className="text-green-700 text-sm tracking-wide">
|
||||
{spanTag}
|
||||
</span>
|
||||
}
|
||||
)}
|
||||
{/* displays error is any */}
|
||||
{error && <span className="text-[12px] text-red-500">{error}</span>}
|
||||
</label>
|
||||
)}
|
||||
{forgotPassword && (
|
||||
@@ -74,7 +76,7 @@ export default function InputCom({
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className={`input-wrapper border ${errorBorder ? "border-red-500 border-[0.5px] animate-shake" : "border border-[#f5f8fa] dark:border-[#5e6278]"} w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`}
|
||||
className={`input-wrapper border w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`}
|
||||
>
|
||||
<input
|
||||
placeholder={placeholder}
|
||||
@@ -96,11 +98,9 @@ export default function InputCom({
|
||||
/>
|
||||
{iconName && (
|
||||
<div className="absolute right-6 bottom-[10px] z-10 flex gap-2">
|
||||
{
|
||||
iconName.split(' ').map((item, index)=>(
|
||||
<Icons key={index} name={item} />
|
||||
))
|
||||
}
|
||||
{iconName.split(" ").map((item, index) => (
|
||||
<Icons key={index} name={item} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{passIcon && (
|
||||
@@ -126,6 +126,7 @@ const inputConfigs = {
|
||||
province: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
|
||||
city: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
|
||||
amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" },
|
||||
description: { minLength: 5, maxLength: 250 },
|
||||
};
|
||||
|
||||
/* Numbers Only: <input type="text" pattern="[0-9]*" /> strictly numbers
|
||||
|
||||
@@ -1,16 +1,51 @@
|
||||
export const PriceFormatter = (price, currency, currencyName) => {
|
||||
const supportedCurrencies = ["USD", "EUR", "GBP"];
|
||||
const symbolFormatter = supportedCurrencies.includes(currency)
|
||||
? currency
|
||||
: undefined;
|
||||
import React from "react";
|
||||
|
||||
const formatter = new Intl.NumberFormat("en", {
|
||||
style: symbolFormatter,
|
||||
currencyDisplay: "symbol",
|
||||
minimumFractionDigits: 2,
|
||||
});
|
||||
// export const PriceFormatter = (price, currency, currencyName) => {
|
||||
// const supportedCurrencies = ["USD", "EUR", "GBP"];
|
||||
// const symbolFormatter = supportedCurrencies.includes(currency)
|
||||
// ? currency
|
||||
// : undefined;
|
||||
|
||||
const displayCurrencyName = symbolFormatter ? "" : currencyName;
|
||||
// const formatter = new Intl.NumberFormat("en", {
|
||||
// style: symbolFormatter,
|
||||
// currencyDisplay: "symbol",
|
||||
// minimumFractionDigits: 2,
|
||||
// });
|
||||
|
||||
return `${formatter.format(price)} ${displayCurrencyName}`;
|
||||
// const displayCurrencyName = symbolFormatter ? "" : currencyName;
|
||||
|
||||
// return `${formatter.format(price)} ${displayCurrencyName}`;
|
||||
// };
|
||||
|
||||
export const PriceFormatter = (
|
||||
price = "00",
|
||||
currency = "",
|
||||
currencyName = ""
|
||||
) => {
|
||||
// Convert the number to a string
|
||||
let numStr = String(price);
|
||||
|
||||
// Split the string into integer and decimal parts
|
||||
let parts = numStr.split(".");
|
||||
let integerPart = parts[0] || "";
|
||||
let decimalPart = parts[1] || "";
|
||||
|
||||
// Add thousands separators to the integer part
|
||||
// let formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
let formattedInteger = integerPart;
|
||||
|
||||
// Truncate or pad the decimal part to two decimal points
|
||||
let formattedDecimal = decimalPart.slice(0, 2).padEnd(2, "0");
|
||||
|
||||
// Combine the formatted integer and decimal parts
|
||||
// let formattedNumber = formattedInteger + '.' + formattedDecimal;
|
||||
|
||||
// return formattedNumber;
|
||||
return (
|
||||
<span className="text-sm flex items-center">
|
||||
<sup>{currency || currencyName || ""}</sup>
|
||||
<span className="px-1 font-bold text-lg">{formattedInteger || ""}</span>
|
||||
<sup>{formattedDecimal || ""}</sup>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import Icons from "./Icons";
|
||||
|
||||
export default function SearchCom({ className, inputClasses }) {
|
||||
export default function SearchCom({ className, inputClasses, placeholder }) {
|
||||
return (
|
||||
<div
|
||||
className={`w-full h-[48px] pl-8 flex rounded-full overflow-hidden bg-white dark:bg-dark-white ${
|
||||
@@ -17,7 +17,7 @@ export default function SearchCom({ className, inputClasses }) {
|
||||
inputClasses || ""
|
||||
}`}
|
||||
type="text"
|
||||
placeholder="Search items, collections..."
|
||||
placeholder={placeholder || 'Search items, collections...'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,23 +3,22 @@ import datas from "../../data/product_data.json";
|
||||
import TopSellerTopBuyerSliderSection from "./TopSellerTopBuyerSliderSection";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import FamilyActiveLSlde from "./FamilyActiveLSlde";
|
||||
|
||||
|
||||
import ParentWaiting from "../MyPendingJobs/ParentWaiting";
|
||||
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
|
||||
|
||||
export default function FamilyDash(props) {
|
||||
console.log("PROPS IN FAMILY DASH->", props);
|
||||
|
||||
console.log("PROPS IN FAMILY DASH->",props);
|
||||
|
||||
const trending = datas.datas;
|
||||
return (
|
||||
<div>
|
||||
<div className="home-page-wrapper">
|
||||
<CommonHead
|
||||
commonHeadData={props.commonHeadData}
|
||||
/>
|
||||
<FamilyActiveLSlde trending={trending} className="mb-10" />
|
||||
<TopSellerTopBuyerSliderSection className="mb-10" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const trending = datas.datas;
|
||||
return (
|
||||
<div>
|
||||
<div className="home-page-wrapper">
|
||||
<CommonHead commonHeadData={props.commonHeadData} />
|
||||
<MyOffersFamilyTable MyActiveOffersList={trending} className="mb-10" />
|
||||
<FamilyActiveLSlde trending={trending} className="mb-10" />
|
||||
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
|
||||
<ParentWaiting className="mb-10" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,10 +61,10 @@ export default function Hero({ className, bannerList, nextDueTask }) {
|
||||
<div className="flex flex-col justify-between">
|
||||
<p className="text-base text-white tracking-wide">Current Task</p>
|
||||
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
|
||||
{nextDueTask.next_due.item_code}
|
||||
{(nextDueTask.next_due.item_code).substr(0,4)+'...'}
|
||||
</p>
|
||||
<p className="text-base text-white tracking-wide">
|
||||
{nextDueTask.next_due.price} Naira
|
||||
{nextDueTask.next_due.price * 0.01} Naira
|
||||
</p>
|
||||
</div>
|
||||
<div className="w-[1px] h-full bg-white-opacity"></div>
|
||||
|
||||
@@ -3,11 +3,10 @@ import slider2 from "../../assets/images/slider-2.jpg";
|
||||
import HomeBannerOffersCard from "../Cards/HomeBannerOffersCard";
|
||||
|
||||
export default function HomeSliders(props) {
|
||||
// console.log("BANNER LIST IN HomeSliders->", props.bannerList);
|
||||
// debugger;
|
||||
return (
|
||||
<>
|
||||
<div className="hero-slider relative 2xl:w-[600px] xl:w-[500px] lg:w-[420px] w-full mb-2 lg:mb-0 ">
|
||||
<div className="hero-slider relative 2xl:w-[600px] xl:w-[400px] lg:w-[420px] w-full mb-2 lg:mb-0 ">
|
||||
<div className="w-full">
|
||||
<SliderCom settings={props.settings}>
|
||||
{props.bannerList?.length <= 0 && (
|
||||
|
||||
@@ -39,14 +39,17 @@ export default function Home(props) {
|
||||
return (
|
||||
<Layout>
|
||||
<div className="home-page-wrapper">
|
||||
{userDetails && userDetails?.account_type == "FAMILY" && (
|
||||
<FamilyDash commonHeadData={props.bannerList} />
|
||||
)}
|
||||
{userDetails && userDetails?.account_type == "FULL" && (
|
||||
{userDetails && userDetails?.account_type == "FAMILY" ? (
|
||||
<FamilyDash account={userDetails} commonHeadData={props.bannerList} />
|
||||
) : userDetails && userDetails?.account_type == "FULL" ? (
|
||||
<FullAccountDash
|
||||
nextDueTask={nextDueTask}
|
||||
bannerList={props.bannerList}
|
||||
/>
|
||||
) : (
|
||||
<div>
|
||||
You are not logged in or your account type is not supported.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from 'react'
|
||||
|
||||
function Detail({label, value, bg,}) {
|
||||
return (
|
||||
<>
|
||||
<label className='w-full md:w-1/4 text-slate-900 tracking-wide font-semibold'>{label}</label>
|
||||
<p className={`p-1 w-full md:w-3/4 text-sm text-slate-900 ${bg ? bg : null}`}>{value}</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Detail
|
||||
@@ -1,22 +1,98 @@
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import ModalCom from "../../Helpers/ModalCom";
|
||||
import { toast } from "react-toastify";
|
||||
import { Form, Formik } from "formik";
|
||||
import usersService from "../../../services/UsersService";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
|
||||
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
const [marketMsg, setMarketMsg] = useState({
|
||||
loading: false,
|
||||
data: {},
|
||||
state: undefined,
|
||||
});
|
||||
const [manageInt, setManageInt] = useState({
|
||||
loading: false,
|
||||
data: {},
|
||||
state: undefined,
|
||||
msg: "",
|
||||
});
|
||||
const MarketCalls = (details) => {
|
||||
const [marketMsg, setMarketMsg] = useState({
|
||||
loading: false,
|
||||
data: {},
|
||||
state: undefined,
|
||||
});
|
||||
const [manageInt, setManageInt] = useState({
|
||||
loading: false,
|
||||
data: {},
|
||||
state: undefined,
|
||||
msg: "",
|
||||
});
|
||||
|
||||
const { offer_code } = details;
|
||||
const reqData = { offer_code };
|
||||
|
||||
const MarketDetail = async () => {
|
||||
try {
|
||||
setMarketMsg({ loading: true });
|
||||
if (!textValue) return;
|
||||
|
||||
reqData.yourmessage = textValue;
|
||||
|
||||
const marketMessage = await apiCall.MarketMessage(reqData);
|
||||
const marketMessageRes = marketMessage?.data;
|
||||
|
||||
if (marketMessageRes?.internal_return < 0) {
|
||||
toast.warn("Something wrong happened", {
|
||||
autoClose: 2000,
|
||||
hideProgressBar: true,
|
||||
});
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success("Message sent", {
|
||||
autoClose: 2500,
|
||||
hideProgressBar: true,
|
||||
});
|
||||
|
||||
setMarketMsg({ data: marketMessageRes, state: true });
|
||||
setTimeout(() => onClose(), 2000);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
setTextValue("");
|
||||
setMarketMsg({ loading: false });
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
|
||||
const ManageInterest = async () => {
|
||||
try {
|
||||
setManageInt({ loading: true });
|
||||
|
||||
const manageInt = await apiCall.MarketInterest(reqData);
|
||||
const manageIntRes = manageInt?.data;
|
||||
|
||||
if (manageIntRes?.internal_return < 0) {
|
||||
setManageInt({
|
||||
loading: false,
|
||||
msg: manageIntRes?.status,
|
||||
data: manageIntRes,
|
||||
state: false,
|
||||
});
|
||||
} else {
|
||||
setManageInt({
|
||||
loading: false,
|
||||
msg: manageIntRes?.status,
|
||||
data: manageIntRes,
|
||||
state: true,
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => setManageInt({ msg: "" }), 3000);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// ManageInterest();
|
||||
// }, []);
|
||||
|
||||
return { MarketDetail, ManageInterest, manageInt, marketMsg };
|
||||
};
|
||||
|
||||
const [textValue, setTextValue] = useState("");
|
||||
|
||||
@@ -26,84 +102,26 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
const marketCalls = useCallback(
|
||||
async (e) => {
|
||||
try {
|
||||
const nameOfCall = e?.target?.name;
|
||||
const { offer_code } = details;
|
||||
const reqData = { offer_code };
|
||||
let { manageInt, ManageInterest, MarketDetail, marketMsg } = MarketCalls(details);
|
||||
|
||||
if (nameOfCall === "market-message") {
|
||||
setMarketMsg({ loading: true });
|
||||
if (!textValue) return;
|
||||
|
||||
reqData.yourmessage = textValue;
|
||||
|
||||
const marketMessage = await apiCall.MarketMessage(reqData);
|
||||
const marketMessageRes = marketMessage?.data;
|
||||
|
||||
if (marketMessageRes?.internal_return < 0) {
|
||||
toast.warn("Something wrong happened", {
|
||||
autoClose: 2000,
|
||||
hideProgressBar: true,
|
||||
});
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success("Message sent", {
|
||||
autoClose: 2500,
|
||||
hideProgressBar: true,
|
||||
});
|
||||
|
||||
setMarketMsg({ data: marketMessageRes, state: true });
|
||||
setTimeout(() => onClose(), 2000);
|
||||
} else {
|
||||
setManageInt({ loading: true });
|
||||
|
||||
const manageInt = await apiCall.MarketInterest(reqData);
|
||||
const manageIntRes = manageInt?.data;
|
||||
|
||||
if (manageIntRes?.internal_return < 0) {
|
||||
setManageInt({
|
||||
loading: false,
|
||||
msg: `Error - ${manageIntRes?.status}`,
|
||||
data: manageIntRes,
|
||||
state: false,
|
||||
});
|
||||
} else {
|
||||
setManageInt({
|
||||
loading: false,
|
||||
msg: manageIntRes?.status,
|
||||
data: manageIntRes,
|
||||
state: true,
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => setManageInt({ msg: "" }), 3000);
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
setTextValue("");
|
||||
setMarketMsg({ loading: false });
|
||||
}, 2000);
|
||||
}
|
||||
},
|
||||
[apiCall, details, onClose, textValue]
|
||||
let thePrice = PriceFormatter(
|
||||
details?.price * 0.01,
|
||||
details?.currency_code,
|
||||
details?.currency
|
||||
);
|
||||
|
||||
console.log('Checking my mangeInt',manageInt)
|
||||
|
||||
// let addedIntDate = marketInt?.added?.split(" ")[0];
|
||||
let expireIntDate = marketInt?.expire?.split(" ")[0];
|
||||
// let expireIntDate = marketInt?.expire?.split(" ")[0];
|
||||
|
||||
let cleanedText = details?.job_description
|
||||
?.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, '"')
|
||||
.replace(/&/g, "&");
|
||||
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation} className="edit-popup">
|
||||
<div className="logout-modal-wrapper md:w-[750px] md:h-[700px] h-full bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="logout-modal-wrapper md:w-[750px] md:h-[660px] 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">
|
||||
{details.offer_code}
|
||||
@@ -112,8 +130,8 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
</div>
|
||||
|
||||
<div className="md:flex bg-white rounded-lg">
|
||||
<div className="p-4 w-full md:w-3/4 md:border-r-1">
|
||||
<div className="min-h-[290px]">
|
||||
<div className="p-4 w-full md:w-[75%] md:border-r-1">
|
||||
<div className="min-h-[263px]">
|
||||
<h2 className="font-semibold text-slate-900 dark:text-black tracking-wide">
|
||||
{details?.title}
|
||||
</h2>
|
||||
@@ -128,17 +146,17 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
name: "",
|
||||
content: {
|
||||
text: `Timeline: ${details.timeline_days} day(s) -- `,
|
||||
bold: `Budget: ${details.price} naira`,
|
||||
bold: `Budget: ${thePrice}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Delivery Detail",
|
||||
content: details.job_description,
|
||||
content: cleanedText,
|
||||
danger: true,
|
||||
},
|
||||
].map(({ name, content, danger }, idx) => (
|
||||
<div className={`my-3 md:flex items-center`} key={idx}>
|
||||
<label className="w-full md:w-1/4 text-slate-900 tracking-wide font-semibold">
|
||||
<label className="w-full md:w-[19%] text-slate-900 tracking-wide font-semibold whitespace-pre-wrap">
|
||||
{name}
|
||||
</label>
|
||||
<div
|
||||
@@ -152,19 +170,23 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
<p
|
||||
className={``}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: danger && content?.replace(/"/g, ""),
|
||||
__html: danger && content,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<p className={`w-full md:w-3/4 text-slate-900`}>
|
||||
<p className={`w-full text-slate-900`}>
|
||||
{name !== "Delivery Detail" ? (
|
||||
<>
|
||||
{typeof content !== "object" ? content : null}
|
||||
{typeof content === "object" && (
|
||||
<span className="flex items-center gap-2">
|
||||
{content?.text}
|
||||
<strong>{content?.bold}</strong>
|
||||
</span>
|
||||
<>
|
||||
<hr className="mb-1" />
|
||||
<span className="flex items-center gap-2">
|
||||
{content?.text}
|
||||
<strong>{thePrice}</strong>
|
||||
</span>
|
||||
<hr className="mt-1" />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
@@ -194,7 +216,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
<button
|
||||
className="self-end w-[150px] h-[52px] rounded-md text-base bg-yellow-500 text-white"
|
||||
name="market-message"
|
||||
onClick={marketCalls}
|
||||
onClick={MarketDetail}
|
||||
>
|
||||
{marketMsg.loading ? (
|
||||
<LoadingSpinner size={5} color="white" />
|
||||
@@ -207,17 +229,17 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full md:w-1/4 h-full ">
|
||||
<div className="w-[90%] mx-auto bg-[#f1f8ff] p-4 rounded-md md:min-h-[550px] flex flex-col justify-between">
|
||||
<div className="w-full md:w-[23%] h-full ">
|
||||
<div className="mx-auto bg-[#f1f8ff] p-4 rounded-md md:min-h-[498px] flex flex-col justify-between">
|
||||
<div className="w-full flex flex-col justify-center py-4 gap-2">
|
||||
<p className="w-full text-slate-900 tracking-wide my-1">
|
||||
Interested in the task?
|
||||
</p>
|
||||
<hr />
|
||||
<button
|
||||
className="bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md inline-flex flex-col items-center justify-center"
|
||||
className="bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md inline-flex sm:flex-col flex-row sm:gap-0 gap-1 items-center justify-center"
|
||||
name="market-interest"
|
||||
onClick={marketCalls}
|
||||
onClick={ManageInterest}
|
||||
>
|
||||
{" "}
|
||||
<span>Send</span>
|
||||
@@ -248,9 +270,18 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
Interest: <b className="ml-1">{details.interest_count}</b>
|
||||
</p>
|
||||
<hr />
|
||||
<p className="my-1">Expire: {expireIntDate}</p>
|
||||
<p className="my-1">
|
||||
Expire: {details.expire}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="self-end w-[150px] mt-2 h-[52px] rounded-md 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>
|
||||
|
||||
@@ -248,6 +248,8 @@ function ActiveJobs(props) {
|
||||
}
|
||||
}, [passDue]);
|
||||
|
||||
console.log("AC JOBS >>", props);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="py-[20px] bg-white dark:bg-black dark:text-white px-4 rounded-2xl shadow-md md:flex justify-between items-start gap-16">
|
||||
@@ -257,8 +259,13 @@ function ActiveJobs(props) {
|
||||
<button
|
||||
type="button"
|
||||
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
|
||||
onClick={() =>
|
||||
navigate(props.details.pathname, { replace: true })
|
||||
onClick={() =>{
|
||||
if(props.details.pathname == '/manage-family'){
|
||||
navigate(props.details.pathname, {state: { ...props.details.accountDetails }}, { replace: true })
|
||||
}else{
|
||||
navigate(props.details.pathname, { replace: true })
|
||||
}
|
||||
}
|
||||
}
|
||||
>
|
||||
<svg
|
||||
@@ -278,12 +285,14 @@ function ActiveJobs(props) {
|
||||
|
||||
<div className="w-full my-2">
|
||||
<p className="w-full text-base text-right text-sky-blue">
|
||||
{props.details.job_to && props.details.job_to}
|
||||
{props?.details && props.details.job_to}
|
||||
</p>
|
||||
<div className="text-base text-slate-700 dark:text-white tracking-wide">
|
||||
<p className="font-semibold text-black dark:text-white">Description: </p>
|
||||
<p className="font-semibold text-black dark:text-white">
|
||||
Description:{" "}
|
||||
</p>
|
||||
<p className="p-2 border border-sky-blue">
|
||||
{props.details?.description && props.details.description}
|
||||
{props?.details && props.details.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -297,11 +306,10 @@ function ActiveJobs(props) {
|
||||
<div className="my-1">
|
||||
<p className="text-base text-slate-700">
|
||||
<span className="font-semibold">Due: </span>
|
||||
{props.details?.delivery_date &&
|
||||
props.details.delivery_date.split(" ")[0]}
|
||||
{props?.details && props.details.delivery_date.split(" ")[0]}
|
||||
</p>
|
||||
<p className="py-2 text-base text-slate-700">
|
||||
{props.details?.delivery_date &&
|
||||
{props?.delivery_date &&
|
||||
props.details.delivery_date.split(" ")[1]}
|
||||
</p>
|
||||
</div>
|
||||
@@ -310,7 +318,9 @@ function ActiveJobs(props) {
|
||||
<p className="font-semibold">Due: </p>
|
||||
<div className="flex flex-col justify-between">
|
||||
<p className="text-base text-slate-700 tracking-wide">
|
||||
<CountDown lastDate={props.details.delivery_date} />
|
||||
<CountDown
|
||||
lastDate={props?.details && props.details.delivery_date}
|
||||
/>
|
||||
</p>
|
||||
<div className="text-base text-slate-700 tracking-wide flex gap-[5px]">
|
||||
<span>Hrs</span>
|
||||
@@ -322,14 +332,18 @@ function ActiveJobs(props) {
|
||||
)}
|
||||
|
||||
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
|
||||
<span className="font-semibold text-black dark:text-white">Duration: </span>
|
||||
<span className="font-semibold text-black dark:text-white">
|
||||
Duration:{" "}
|
||||
</span>
|
||||
<span className="">
|
||||
{props.details?.timeline_days && props.details.timeline_days}{" "}
|
||||
day(s)
|
||||
</span>
|
||||
</div>
|
||||
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
|
||||
<span className="font-semibold text-black dark:text-white">No: </span>
|
||||
<span className="font-semibold text-black dark:text-white">
|
||||
No:{" "}
|
||||
</span>
|
||||
<span className="">
|
||||
{props.details?.contract && props.details.contract}
|
||||
</span>
|
||||
|
||||
@@ -79,7 +79,7 @@ function CurrentTaskAction({jobDetails}) {
|
||||
<tr>
|
||||
<td>
|
||||
<div className="flex justify-center items-center">
|
||||
<button onClick={popUpHandler} type="button" className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
<button onClick={popUpHandler} type="button" className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
Send of Review
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -10,8 +10,8 @@ import ReviewJobAction from './ReviewJobAction'
|
||||
import ReviewTaskAction from './ReviewTaskAction'
|
||||
|
||||
function IndexJobActions({details}) { // FUNCTION TO RENDER SPECIFIC JOB ACTION DEPENDING ON OWNER STATUS & STATUS DESCRIPTION
|
||||
let owner = details.owner_status
|
||||
let description = details.status_description
|
||||
let owner = details?.owner_status
|
||||
let description = details?.status_description
|
||||
switch(owner) {
|
||||
case 'OWNER':
|
||||
return (()=>{
|
||||
|
||||
@@ -119,7 +119,7 @@ function PastDueJobAction({jobDetails}) {
|
||||
<tr>
|
||||
<td>
|
||||
<div className="flex justify-center items-center">
|
||||
<button type="button" onClick={popUpHandler} className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
Cancel or Extend Timeline
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@ function PastDueTaskAction() {
|
||||
<tr>
|
||||
<td>
|
||||
<div className="flex justify-center items-center">
|
||||
<button type="button" className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
<button type="button" className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
Request Extension
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -108,7 +108,7 @@ function ReviewJobAction({jobDetails}) {
|
||||
<tr>
|
||||
<td>
|
||||
<div className="flex justify-center items-center">
|
||||
<button type="button" onClick={popUpHandler} className="w-120 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
<button type="button" onClick={popUpHandler} className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
Reject or Accept
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
|
||||
{value.title}
|
||||
</h1>
|
||||
<div>{value.description}</div>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
<span className="text-sm text-thin-light-gray flex flext-start gap-1">
|
||||
Price:{" "}
|
||||
<span className="text-purple">
|
||||
{thePrice}
|
||||
|
||||
@@ -10,6 +10,7 @@ export default function MyActiveJobs(props) {
|
||||
setValue(value);
|
||||
};
|
||||
console.log("AMEYE LOC1", props.MyJobList);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead commonHeadData={props.commonHeadData} />
|
||||
|
||||
@@ -11,6 +11,9 @@ import PaginatedList from "../Pagination/PaginatedList";
|
||||
import EditJobPopOut from "../jobPopout/EditJobPopout";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
|
||||
import EditIcon from '../../assets/images/icon-edit.svg'
|
||||
import DeleteIcon from '../../assets/images/icon-delete.svg'
|
||||
|
||||
export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
||||
// Getting the categories
|
||||
const currentJobCart = MyJobList?.data?.categories;
|
||||
@@ -119,7 +122,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
||||
{value.title}
|
||||
</h1>
|
||||
<div>{value.description}</div>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
<span className="text-sm text-thin-light-gray flex items-start gap-1">
|
||||
Price: <span className="text-purple">{thePrice}</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
@@ -132,10 +135,10 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="min-w-[110px] max-w-[110px] bg-yellow-300 mx-2 rounded-md flex flex-nowrap space-x-2 justify-center items-center self-end">
|
||||
<div className="h-[33px] w-[150px] flex flex-nowrap items-center self-end">
|
||||
<button
|
||||
type="button"
|
||||
className="p-2 w-[60px] h-11"
|
||||
className="p-1 border-2 border-red-400 rounded-md"
|
||||
onClick={() => {
|
||||
setDeleteJobPopout({
|
||||
show: true,
|
||||
@@ -143,12 +146,12 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
||||
});
|
||||
}}
|
||||
>
|
||||
[Delete]
|
||||
<img className="w-[21px] h-[21px]" src={DeleteIcon} alt='delete-icon' />
|
||||
</button>
|
||||
<span>|</span>
|
||||
<div className="mx-[4px] h-full w-[1px] bg-black dark:bg-dark-gray"></div>
|
||||
<button
|
||||
type="button"
|
||||
className="p-2 w-[40px] h-11"
|
||||
className="p-1 border-2 border-sky-blue rounded-md flex items-center"
|
||||
onClick={() => {
|
||||
setEditJob({
|
||||
show: true,
|
||||
@@ -156,7 +159,8 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
||||
});
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
<img className="w-[21px] h-[21px]" src={EditIcon} alt='edit-icon' />
|
||||
<span className="text-sm text-sky-blue">Edit</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -186,9 +190,9 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
||||
<div className="header w-full flex justify-between items-center mb-5">
|
||||
<div className="flex space-x-2 items-center">
|
||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
All Jobs
|
||||
{filterCategories[selectedCategory]} Jobs
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<SelectBox
|
||||
action={handleSetCategory}
|
||||
datas={Object.values(filterCategories)}
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import MyJobTable from "./MyJobTable";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import AddJobPage from "../../views/AddJobPage";
|
||||
|
||||
export default function MyJobs(props) {
|
||||
let { state } = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const [popUp, setPopUp] = useState(false);
|
||||
const popUpHandler = () => {
|
||||
setPopUp((prev) => !prev);
|
||||
|
||||
if (state?.popup) navigate("/", { replace: true })
|
||||
else return
|
||||
};
|
||||
|
||||
const categoryOptions = props.MyJobList?.data?.categories;
|
||||
|
||||
useEffect(() => {
|
||||
if (!state?.popup) {
|
||||
setPopUp(false);
|
||||
} else {
|
||||
setPopUp(true);
|
||||
}
|
||||
}, [state?.popup]);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead commonHeadData={props.commonHeadData} />
|
||||
|
||||
@@ -67,7 +67,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
|
||||
{value.title}
|
||||
</h1>
|
||||
<div>{value.description}</div>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
<span className="text-sm text-thin-light-gray flex items-start gap-1">
|
||||
Price:{" "}
|
||||
<span className="text-purple">
|
||||
{thePrice}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import activeAidsBanner from "../../assets/images/kids-waiting.jpg";
|
||||
import HeroUser from "../../assets/images/hero-user.png";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
import ParentWaitingTable from "./ParentWaitingTable";
|
||||
|
||||
export default function ParentWaiting({ className }) {
|
||||
const [addFavorite, setValue] = useState(false);
|
||||
const favoriteHandler = () => {
|
||||
if (!addFavorite) {
|
||||
setValue(true);
|
||||
toast.success("Added to Favorite List");
|
||||
} else {
|
||||
setValue(false);
|
||||
toast.warn("Remove to Favorite List");
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div className={`overview-section w-full ${className || ""}`}>
|
||||
<div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Waiting for Parent to Get Started...
|
||||
</h1>
|
||||
</div>
|
||||
<div className="overview-section-wrapper lg:flex lg:h-[494px] lg:pace-x-2 flex-1 lg:gap-8">
|
||||
<div className=" w-full h-full bg-white dark:bg-dark-white flex-[50%] rounded-2xl overflow-hidden mb-10">
|
||||
<img
|
||||
src={activeAidsBanner}
|
||||
alt="banner"
|
||||
className="w-full lg:h-full h-[400px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="overview-countdown lg:w-2/5 w-full h-full flex flex-col justify-between lg:p-8 rounded-2xl bg-white dark:bg-dark-white flex-[50%] ">
|
||||
{<ParentWaitingTable />}
|
||||
|
||||
{/* <div className="lg:mb-0 mb-3">*/}
|
||||
{/* <h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* Lock and Lob x Fiesta Spurs*/}
|
||||
{/* </h1>*/}
|
||||
{/* <span className="text-[18px] font-thin tracking-wide text-dark-gray dark:text-white">*/}
|
||||
{/* ID : 2320382*/}
|
||||
{/*</span>*/}
|
||||
{/* </div>*/}
|
||||
{/* /!* user *!/*/}
|
||||
{/* <div className="flex items-center space-x-3 lg:mb-0 mb-3">*/}
|
||||
{/* <div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">*/}
|
||||
{/* <img src={HeroUser} alt="" />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="text-xl tracking-wide font-bold antise text-dark-gray dark:text-white">*/}
|
||||
{/* Brokln Simons*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="text-sm tracking-wide text-dark-gray dark:text-white">*/}
|
||||
{/* @broklinslam_75*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
import React, { useState } from "react";
|
||||
import transaction1 from "../../assets/images/recent-transation-1.png";
|
||||
import transaction2 from "../../assets/images/recent-transation-2.png";
|
||||
import transaction3 from "../../assets/images/recent-transation-3.png";
|
||||
|
||||
export default function ParentWaitingTable() {
|
||||
const transationFilterData = [
|
||||
{
|
||||
id: 1,
|
||||
name: "all",
|
||||
uniqueId: Math.random(),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "send",
|
||||
uniqueId: Math.random(),
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "recent",
|
||||
uniqueId: Math.random(),
|
||||
},
|
||||
];
|
||||
const [filterActive, setValue] = useState(transationFilterData[0].id);
|
||||
const filterHander = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
return (
|
||||
<div className="rounded-2xl bg-white dark:bg-dark-white ">
|
||||
{/* heading */}
|
||||
<div className="heading sm:flex justify-between items-center">
|
||||
|
||||
<div>
|
||||
<ul className="flex space-x-5 items-center">
|
||||
{transationFilterData.map((value) => (
|
||||
<li
|
||||
onClick={() => filterHander(value.id)}
|
||||
key={value.uniqueId}
|
||||
className={`text-base text-thin-light-gray hover:text-purple border-b dark:border-[#5356fb29] border-transparent hover:border-purple uppercase ${
|
||||
filterActive === value.id ? "border-purple text-purple" : ""
|
||||
}`}
|
||||
>
|
||||
{value.name}
|
||||
</li>
|
||||
))}
|
||||
{/* <li className="text-base text-thin-light-gray hover:text-purple border-b dark:border-[#5356fb29] border-transparent hover:border-purple uppercase">
|
||||
All
|
||||
</li>
|
||||
<li className="text-base text-thin-light-gray hover:text-purple border-b dark:border-[#5356fb29] border-transparent hover:border-purple uppercase">
|
||||
SEND
|
||||
</li>
|
||||
<li className="text-base text-thin-light-gray hover:text-purple border-b dark:border-[#5356fb29] border-transparent hover:border-purple uppercase">
|
||||
recent
|
||||
</li> */}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/* content */}
|
||||
|
||||
{filterActive === 2 ? (
|
||||
<div className="content">
|
||||
<ul>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction1} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Add ETH from MetaMask
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-green text-right">
|
||||
+324.75
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction2} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Add BTC from Coinbase Wallet
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-red text-right">
|
||||
-824.78
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction3} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Buy Nft art from LTC
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-red text-right">
|
||||
-924.54
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
) : filterActive === 3 ? (
|
||||
<div className="content">
|
||||
<ul>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction1} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Add ETH from MetaMask
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-green text-right">
|
||||
+324.75
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction2} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Add BTC from Coinbase Wallet
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-red text-right">
|
||||
-824.78
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
) : (
|
||||
<div className="content">
|
||||
<ul>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction1} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Add ETH from MetaMask
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-green text-right">
|
||||
+324.75
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction2} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Add BTC from Coinbase Wallet
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-red text-right">
|
||||
-824.78
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction3} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Buy Nft art from LTC
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-red text-right">
|
||||
-924.54
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className="content-item py-3 border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] hover:border-purple">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="account-name flex space-x-4 items-center">
|
||||
<div className="icon w-14 h-14 flex justify-center items-center">
|
||||
<img src={transaction1} alt="" className="" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="name">
|
||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-1">
|
||||
Add ETH from MetaMask
|
||||
</p>
|
||||
</div>
|
||||
<div className="time">
|
||||
<p className="text-sm text-thin-light-gray font-medium">
|
||||
22 hours ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-dark-gray dark:text-white">
|
||||
$512.44
|
||||
</p>
|
||||
<p className="usd text-base text-light-green text-right">
|
||||
+324.75
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -7,8 +7,9 @@ import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
|
||||
const noTasksBg = require("../../assets/images/no-task-background.jpg");
|
||||
const noFamilyTasksBg = require("../../assets/images/family-no-task-background.jpg");
|
||||
|
||||
export default function MyJobTable({ className, ActiveJobList }) {
|
||||
export default function MyJobTable({ className, ActiveJobList, Account }) {
|
||||
let navigate = useNavigate();
|
||||
let { pathname } = useLocation();
|
||||
|
||||
@@ -25,14 +26,17 @@ export default function MyJobTable({ className, ActiveJobList }) {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
|
||||
let accountType = Account?.account_type == "FULL"
|
||||
|
||||
// To navigate to task
|
||||
const [btnLoader, setBtnLoader] = useState(false);
|
||||
const navigateMarket = () => {
|
||||
setBtnLoader(true);
|
||||
setTimeout(() => {
|
||||
navigate("/market", { replace: true });
|
||||
const timeoutId = setTimeout(() => {
|
||||
navigate(accountType ? "/market" : "/familymarket", { replace: true });
|
||||
setBtnLoader(false);
|
||||
}, 2500);
|
||||
return () => clearTimeout(timeoutId);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -42,12 +46,12 @@ export default function MyJobTable({ className, ActiveJobList }) {
|
||||
} bg-cover bg-center`}
|
||||
style={{
|
||||
backgroundImage: !ActiveJobList?.data.length
|
||||
? `url('${noTasksBg}')`
|
||||
? `url('${accountType ? noTasksBg : noFamilyTasksBg}')`
|
||||
: "none",
|
||||
}}
|
||||
>
|
||||
{/* Adding this dark overlay in order to see the texts properly */}
|
||||
{!ActiveJobList?.data.length && (
|
||||
{!ActiveJobList?.data.length && accountType && (
|
||||
<div class="absolute inset-0 bg-black opacity-30"></div>
|
||||
)}
|
||||
{ActiveJobList?.data.length > 0 && ActiveJobList.loading && (
|
||||
@@ -60,6 +64,8 @@ export default function MyJobTable({ className, ActiveJobList }) {
|
||||
<div className="h-auto w-full">
|
||||
{ActiveJobList?.data?.length > 0 &&
|
||||
currentTask?.map((task, idx) => {
|
||||
// find due date
|
||||
const dueDate = task?.delivery_date.split(" ")[0];
|
||||
let thePrice = PriceFormatter(
|
||||
task?.price * 0.01,
|
||||
task?.currency_code,
|
||||
@@ -86,7 +92,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
|
||||
<span className="text-base text-gray-600">
|
||||
{task?.description}
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
<span className="text-sm text-thin-light-gray flex flext-start gap-1">
|
||||
Price:
|
||||
<span className="text-purple ml-1">{thePrice}</span>
|
||||
</span>
|
||||
@@ -101,9 +107,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Due Date:
|
||||
<span className="text-purple ml-1">
|
||||
{task?.delivery_date}
|
||||
</span>
|
||||
<span className="text-purple ml-1">{dueDate}</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Confirmation:
|
||||
@@ -134,20 +138,41 @@ export default function MyJobTable({ className, ActiveJobList }) {
|
||||
})}
|
||||
|
||||
{ActiveJobList?.data?.length <= 0 && (
|
||||
<div className="flex flex-col items-center justify-center gap-9 my-5">
|
||||
<div className="p-2 font-bold text-3xl text-white whitespace-nowrap">
|
||||
You currently have "0" task
|
||||
</div>
|
||||
<button
|
||||
className="w-[115px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
onClick={navigateMarket}
|
||||
<div
|
||||
className={`flex flex-col ${
|
||||
accountType ? "items-center" : "items-end"
|
||||
} justify-center gap-9 my-5`}
|
||||
>
|
||||
<div
|
||||
className={`p-2 font-bold text-3xl ${
|
||||
accountType ? "text-white" : "text-purple"
|
||||
} whitespace-nowrap`}
|
||||
>
|
||||
{btnLoader ? (
|
||||
<div className="signup btn-loader"></div>
|
||||
) : (
|
||||
"Find Task"
|
||||
)}
|
||||
</button>
|
||||
You currently have {accountType ? '"0"' : "no"} task
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
!accountType &&
|
||||
"bg-black opacity-30 h-[17rem] p-5 rounded-md -translate-x-20"
|
||||
}
|
||||
>
|
||||
<button
|
||||
className={`${
|
||||
!accountType
|
||||
? "w-[130px] h-20 bg-[#19a706] text-lg font-semibold rounded-md py-2 px-4"
|
||||
: "w-[115px] h-11 btn-gradient rounded-full"
|
||||
} flex justify-center items-center text-base text-white`}
|
||||
onClick={navigateMarket}
|
||||
>
|
||||
{btnLoader ? (
|
||||
<div className="signup btn-loader"></div>
|
||||
) : accountType ? (
|
||||
"Find Task"
|
||||
) : (
|
||||
"Ask Parent For New Task"
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{ActiveJobList?.internal_return < 0 && (
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
import { useRef, useState } from "react";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import SliderCom from "../Helpers/SliderCom";
|
||||
|
||||
import OfferJobPopout from "../jobPopout/OfferJobPopout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
|
||||
export default function MyOffersFamilyTable({ className, MyActiveOffersList }) {
|
||||
let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
||||
const settings = {
|
||||
arrows: false,
|
||||
dots: false,
|
||||
infinite: MyActiveOffersList?.result_list?.length > 4,
|
||||
autoplay: true,
|
||||
slidesToShow: 4,
|
||||
slidesToScroll: 1,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 426,
|
||||
settings: {
|
||||
slidesToShow: 2,
|
||||
slidesToScroll: 1,
|
||||
infinite: MyActiveOffersList?.result_list?.length > 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
console.log("YES WE SEE OFFERS", MyActiveOffersList);
|
||||
const sellSlider = useRef(null);
|
||||
//const buySlider = useRef(null);
|
||||
const prevHandler = (value) => {
|
||||
if (value === "sell") {
|
||||
sellSlider.current.slickPrev();
|
||||
}
|
||||
// if (value === "buy") {
|
||||
// buySlider.current.slickPrev();
|
||||
// }
|
||||
};
|
||||
const nextHandler = (value) => {
|
||||
if (value === "sell") {
|
||||
sellSlider.current.slickNext();
|
||||
}
|
||||
// if (value === "buy") {
|
||||
// buySlider.current.slickNext();
|
||||
// }
|
||||
};
|
||||
|
||||
if (!MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0) {
|
||||
return ""; // want blank or no appear when no items
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={`top-seller-top-buyer-wrapper ${className || ""}`}>
|
||||
<div className="top-seller-top-buyer-wrapper-container">
|
||||
<div className="main-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4">
|
||||
<div className="lg:w-2/2 w-full mb-10 lg:mb-0 sm:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl section-shadow">
|
||||
<div className="heading flex justify-between items-center mb-4">
|
||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
You Have Task(s) Waiting For You
|
||||
</h1>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<button
|
||||
onClick={() => nextHandler("sell")}
|
||||
type="button"
|
||||
className="transform rotate-180 text-dark-gray dark:text-white dark:opacity-25"
|
||||
>
|
||||
<Icons name="arrows" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => prevHandler("sell")}
|
||||
type="button"
|
||||
className="transform rotate-180"
|
||||
>
|
||||
<div className=" text-dark-gray dark:text-white">
|
||||
<svg
|
||||
width="11"
|
||||
height="19"
|
||||
viewBox="0 0 11 19"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.09766 1.1499L1.13307 9.11449L9.09766 17.0791"
|
||||
stroke="url(#paint0_linear_220_23410)"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="paint0_linear_220_23410"
|
||||
x1="9.09766"
|
||||
y1="1.1499"
|
||||
x2="-4.2474"
|
||||
y2="7.96749"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stopColor="#F539F8" />
|
||||
<stop offset="0.416763" stopColor="#C342F9" />
|
||||
<stop offset="1" stopColor="#5356FB" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="slider-content">
|
||||
<SliderCom settings={settings} selector={sellSlider}>
|
||||
{MyActiveOffersList &&
|
||||
MyActiveOffersList?.result_list?.length > 0 &&
|
||||
MyActiveOffersList?.result_list?.map((value, index) => {
|
||||
let thePrice = PriceFormatter(
|
||||
value?.price * 0.01,
|
||||
value?.currency_code,
|
||||
value?.currency
|
||||
);
|
||||
return (
|
||||
<div className="item" key={index}>
|
||||
<div className="offer-slide-item flex flex-col justify-between items-center">
|
||||
{/* title */}
|
||||
<div className="flex justify-center">
|
||||
<p className="text-xl text-dark-gray dark:text-white font-bold mb-2">
|
||||
{value.title}
|
||||
</p>
|
||||
</div>
|
||||
{/* username */}
|
||||
<div className="flex flex-col justify-center my-1">
|
||||
<p className="text-xs text-thin-light-gray">
|
||||
{value.timeline_days} Days
|
||||
</p>
|
||||
<div className="my-2 flex space-x-1 items-center text-purple text-xs">
|
||||
<span>{thePrice}</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setOfferPopout({
|
||||
show: true,
|
||||
data: {...value, thePrice },
|
||||
});
|
||||
}}
|
||||
className="w-20 h-11 self-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Start Task
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</SliderCom>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Offer Job Popout */}
|
||||
{offerPopout.show && (
|
||||
<OfferJobPopout
|
||||
details={offerPopout.data}
|
||||
onClose={() => {
|
||||
setOfferPopout({ show: false, data: {} });
|
||||
}}
|
||||
situation={offerPopout.show}
|
||||
/>
|
||||
)}
|
||||
{/* End of Offer Job Popout */}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -143,7 +143,10 @@ export default function MyOffersTable({ className, MyActiveOffersList }) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setOfferPopout({ show: true, data: value });
|
||||
setOfferPopout({
|
||||
show: true,
|
||||
data: {...value, thePrice },
|
||||
});
|
||||
}}
|
||||
className="w-20 h-11 self-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import MyJobTable from "./MyJobTable";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import TopSellerTopBuyerSliderSection from "../Home/TopSellerTopBuyerSliderSection";
|
||||
// import TopSellerTopBuyerSliderSection from "../Home/TopSellerTopBuyerSliderSection";
|
||||
import MyOffersTable from "./MyOffersTable";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export default function MyTasks({
|
||||
MyActiveOffersList,
|
||||
ActiveJobList,
|
||||
commonHeadData,
|
||||
}) {
|
||||
const { userDetails } = useSelector(
|
||||
(state) => state?.userDetails
|
||||
);
|
||||
|
||||
const [selectTab, setValue] = useState("today");
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
|
||||
let accountType = userDetails?.account_type == "FULL"
|
||||
|
||||
console.log("Active something >>", MyActiveOffersList)
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead commonHeadData={commonHeadData} />
|
||||
@@ -38,14 +47,14 @@ export default function MyTasks({
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
{MyActiveOffersList &&
|
||||
{MyActiveOffersList && accountType &&
|
||||
MyActiveOffersList?.result_list?.length >= 0 && (
|
||||
<MyOffersTable
|
||||
MyActiveOffersList={MyActiveOffersList}
|
||||
className="mb-10"
|
||||
/>
|
||||
)}
|
||||
<MyJobTable ActiveJobList={ActiveJobList} />
|
||||
<MyJobTable ActiveJobList={ActiveJobList} Account={userDetails} />
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
import { useState } from "react";
|
||||
import dataImage2 from "../../assets/images/data-table-user-2.png";
|
||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||
import PaginatedList from "../Pagination/PaginatedList";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
|
||||
|
||||
export default function MyWaitingJobTable({ MyJobList, className }) {
|
||||
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem =
|
||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentActiveJobList = MyJobList?.result_list?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
{MyJobList && MyJobList?.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>
|
||||
{
|
||||
<>
|
||||
{MyJobList &&
|
||||
MyJobList?.result_list &&
|
||||
MyJobList.result_list.length > 0 ? (
|
||||
currentActiveJobList.map((value, index) => {
|
||||
// let deliveryDate = value?.expire?.split(" ")[0];
|
||||
let thePrice = PriceFormatter(
|
||||
value?.price * 0.01,
|
||||
value?.currency_code,
|
||||
value?.currency
|
||||
);
|
||||
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 w-full">
|
||||
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] max-w-[60px]">
|
||||
<img
|
||||
src={dataImage2}
|
||||
alt="data"
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col flex-[0.9]">
|
||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||
{value.title}
|
||||
</h1>
|
||||
<div>{value.description}</div>
|
||||
<span className="text-sm text-thin-light-gray flex items-start gap-1">
|
||||
Price:{" "}
|
||||
<span className="text-purple">
|
||||
{thePrice}
|
||||
</span>
|
||||
</span>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Duration:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{value?.timeline_days} day(s)
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Expire:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{value?.expire}
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm text-thin-light-gray">
|
||||
Sent :{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{value?.sent}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td className="text-right py-4 px-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setJobPopout({ show: true, data: value });
|
||||
}}
|
||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||
<td className="p-2">No Pending Task!</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
MyJobList?.result_list.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
data={MyJobList?.result_list}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Active Job Popout */}
|
||||
{jobPopout.show && (
|
||||
<MarketPopUp
|
||||
details={jobPopout.data}
|
||||
onClose={() => {
|
||||
setJobPopout({ show: false, data: {} });
|
||||
}}
|
||||
situation={jobPopout.show}
|
||||
/>
|
||||
)}
|
||||
{/* End of Active Job Popout */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import MyWaitingJobTable from "./MyWaitingJobTable";
|
||||
|
||||
export default function MyWaitingJobs(props) {
|
||||
const [selectTab, setValue] = useState("today");
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
console.log("AMEYE LOC1", props.MyJobList);
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead
|
||||
commonHeadData={props.commonHeadData}
|
||||
/>
|
||||
<div className="notification-page w-full mb-10">
|
||||
<div className="notification-wrapper w-full">
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
<span
|
||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||
>
|
||||
Waiting Job(s)
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<div
|
||||
onClick={() => filterHandler("today")}
|
||||
className="relative"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<MyWaitingJobTable MyJobList={props.MyJobList} />
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import RecentActivityTable from './WalletComponent/RecentActivityTable'
|
||||
import PurchasesTable from './WalletComponent/PurchasesTable'
|
||||
import CouponTable from './WalletComponent/CouponTable'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
||||
import { PriceFormatter } from '../Helpers/PriceFormatter'
|
||||
|
||||
function Balance({wallet, coupon}) {
|
||||
return (
|
||||
@@ -42,11 +43,11 @@ function Balance({wallet, coupon}) {
|
||||
</div>
|
||||
<div className='balance-info'>
|
||||
<p className='py-2'>Balance</p>
|
||||
<span className='py-1 px-2 bg-green-100 text-green-500 rounded-lg'>{item.symbol}{(item.amount*0.01).toFixed(2)}</span>
|
||||
<span className='py-1 px-2 bg-green-100 text-green-500 rounded-lg flex flex-start gap-1'>{PriceFormatter(item.amount * 0.01, item.code)}</span>
|
||||
</div>
|
||||
<div className='balance-info'>
|
||||
<p className='py-2'>Escrow</p>
|
||||
<span className='py-1 px-2 bg-red-100 text-red-500 rounded-lg'>{item.symbol}{(item.escrow*0.01).toFixed(2)}</span>
|
||||
<span className='py-1 px-2 bg-red-100 text-red-500 rounded-lg flex flex-start gap-1'>{PriceFormatter(item.escrow * 0.01, item.code)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import bank2 from "../../assets/images/bank-2.png";
|
||||
import bank3 from "../../assets/images/bank-3.png";
|
||||
import bank4 from "../../assets/images/bank-4.png";
|
||||
import Accordion from "../Helpers/Accordion";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
|
||||
export default function WalletHeader(props) {
|
||||
// debugger;
|
||||
@@ -58,10 +59,7 @@ export default function WalletHeader(props) {
|
||||
</div>
|
||||
<div>
|
||||
<p className="eth text-xl font-bold text-purple">
|
||||
{(value.amount * 0.01).toFixed(2)} {value.code}
|
||||
</p>
|
||||
<p className="usd text-base text-thin-light-gray text-right">
|
||||
{/*(773.69 USD)*/}
|
||||
{PriceFormatter(value.amount * 0.01, value.code)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,6 @@ import Layout from "../Partials/Layout";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
|
||||
import usersService from "../../services/UsersService";
|
||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||
import PaginatedList from "../Pagination/PaginatedList";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import OthersInterestedTable from "./OthersInterestedTable";
|
||||
|
||||
@@ -15,25 +13,64 @@ export default function ManageInterestOffer(props) {
|
||||
|
||||
let [redirectTime, setRedirectTime] = useState(5)
|
||||
|
||||
let [messageToSend, setMessageToSend] = useState('')
|
||||
|
||||
let [tab, setTab] = useState("info"); //message STATE FOR SWITCHING BETWEEN TABS
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: '', processType: ''})
|
||||
|
||||
const messageList = {data: [1,2,3,4,5,6]} // TO BE REMOVED AND REPLACE WITH REAL MESSAGE FROM API CALL
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem = Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentMessageList = messageList?.data?.slice(indexOfFirstItem, indexOfLastItem);
|
||||
let [messageListReload, setMessageListReload] = useState(false) // STATE TO DETERMINE WHEN MESSAGE LIST WILL RELOAD
|
||||
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
const [messageList, setMessageList] = useState({loading: true, data: []}) // TO BE REMOVED AND REPLACE WITH REAL MESSAGE FROM API CALL
|
||||
|
||||
const [selectTab, setValue] = useState("today");
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
|
||||
//FUNCTION TO HANDLE ON CHANGE MESSAGE IN TEXTAREA
|
||||
const onMessageChange = ({target:{value}}) => {
|
||||
if(messageToSend.length > 149){
|
||||
setRequestStatus({loading: false, status: false, message: 'max of 150 characters', processType: 'sendmessage'})
|
||||
}else{
|
||||
setRequestStatus({loading: false, status: false, message: '', processType: 'sendmessage'})
|
||||
}
|
||||
setMessageToSend(value)
|
||||
}
|
||||
|
||||
//FUNCTION TO SEND MESSAGE TO CLIENT
|
||||
const sendMessage = () => {
|
||||
let reqData = { // API PAYLOADS
|
||||
msg_type: 'MRKTINT',
|
||||
yourmessage: messageToSend,
|
||||
offer_uid: props.offerDetails.offer_uid,
|
||||
interest_uid: props.offerDetails.interest_uid
|
||||
}
|
||||
setRequestStatus(prev => ({...prev, loading: true, processType: 'sendmessage'}))
|
||||
if(!messageToSend){
|
||||
setRequestStatus({loading: false, status: false, message: 'Please enter message to send', processType: 'sendmessage'})
|
||||
return
|
||||
}
|
||||
if(messageToSend.length > 149){
|
||||
return
|
||||
}
|
||||
apiCall.offerInterestMsg(reqData).then(res=>{
|
||||
if(res.status != 200 || res.data.internal_return < 0){
|
||||
setRequestStatus({loading: false, status: false, message: 'message not sent, try again', processType: 'sendmessage'})
|
||||
return
|
||||
}
|
||||
setRequestStatus({loading: false, status: true, message: 'message sent', processType: 'sendmessage'})
|
||||
setMessageToSend('') // sets message to empty strings
|
||||
setMessageListReload(prev => !prev) //A FUNCTION TO MAKE MESSAGE LIST RELOAD
|
||||
}).catch(error => {
|
||||
setRequestStatus({loading: false, status: false, message: 'Opps, an error occured', processType: 'sendmessage'})
|
||||
}).finally(()=>{
|
||||
setTimeout(() => {
|
||||
setRequestStatus({loading: false, status: false, message: '', processType: ''})
|
||||
}, 5000);
|
||||
})
|
||||
}
|
||||
|
||||
//FUNCTION TO ACCEPT/REJECT OFFER INTEREST
|
||||
const interestOfferProcess = ({target:{name}}) => {
|
||||
setRequestStatus(prev => ({...prev, loading: true, processType: name}))
|
||||
@@ -65,9 +102,20 @@ export default function ManageInterestOffer(props) {
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
// run API to get message to replace message array above, add reload variable as dependence array
|
||||
},[])
|
||||
useEffect(()=>{ //API to get Offer Interest message list
|
||||
let reqData = { // API PAYLOADS
|
||||
msg_type: 'MRKTINT',
|
||||
offer_uid: props.offerDetails?.offer_uid,
|
||||
interest_uid: props.offerDetails?.interest_uid
|
||||
}
|
||||
setMessageList(prev => ({...prev, loading: true}))
|
||||
apiCall.offerInterestListMsg(reqData).then(res=>{
|
||||
setMessageList({loading: false, data:res?.data?.result_list})
|
||||
}).catch(err => {
|
||||
setMessageList(prev => ({...prev, loading: false}))
|
||||
console.log('Failed', err)
|
||||
})
|
||||
},[messageListReload])
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead
|
||||
@@ -143,13 +191,15 @@ export default function ManageInterestOffer(props) {
|
||||
{/* info tab */}
|
||||
{tab == 'info' ?
|
||||
<div className="info-details w-full border-t">
|
||||
<div className="my-3 flex items-center gap-1">
|
||||
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Name</span>
|
||||
<span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_name}</span>
|
||||
</div>
|
||||
<div className="my-3 flex items-center gap-1">
|
||||
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Member Since</span>
|
||||
<span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_added}</span>
|
||||
<div className="my-0 md:my-3 block md:flex items-center gap-10">
|
||||
<div className="my-3 md:my-0 flex items-center gap-1">
|
||||
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Name</span>
|
||||
<span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_name}</span>
|
||||
</div>
|
||||
<div className="my-3 md:my-0 flex items-center gap-1">
|
||||
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Member Since</span>
|
||||
<span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_added}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="my-3 flex items-center gap-1">
|
||||
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Jobs completed</span>
|
||||
@@ -178,45 +228,67 @@ export default function ManageInterestOffer(props) {
|
||||
</div>
|
||||
:
|
||||
<div className="message-details w-full border-t">
|
||||
<div className="my-0 w-full flex items-center gap-5">
|
||||
<div className="w-3/4">
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">Message to dummy name</p>
|
||||
<textarea rows={2} autoFocus={true} className="p-2 text-base font-bold text-dark-gray dark:text-white dark:bg-dark-gray border tracking-wide w-full resize-none rounded-md outline-none" />
|
||||
<p className="my-1 text-base text-dark-gray dark:text-white tracking-wide">To: <span className="font-bold">{props.offerDetails?.client_name}</span></p>
|
||||
<div className="w-full flex items-center gap-5">
|
||||
<div className="w-full">
|
||||
<textarea
|
||||
value={messageToSend}
|
||||
onChange={onMessageChange}
|
||||
rows={2} autoFocus={true}
|
||||
className="p-2 text-base font-bold text-dark-gray dark:text-white dark:bg-dark-gray border tracking-wide w-full resize-none rounded-md outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-1/4 flex flex-col justify-center items-center">
|
||||
<button
|
||||
type="button"
|
||||
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Send</span>
|
||||
</button>
|
||||
<div className="flex justify-end items-center">
|
||||
{requestStatus.loading && requestStatus.processType == 'sendmessage' ?
|
||||
<LoadingSpinner color='sky-blue' size='10' />
|
||||
:
|
||||
<button
|
||||
type="button"
|
||||
onClick={sendMessage}
|
||||
disabled={requestStatus.loading}
|
||||
// className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
className="w-[100px] h-[50px] bg-sky-blue text-center text-lg font-semibold text-white rounded-md shadow-md flex justify-center items-center"
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{/* message list */}
|
||||
<div className="min-h-[100px] max-h-[200px] overflow-y-auto">
|
||||
{currentMessageList.map((item, index)=>(
|
||||
<div key={index} className="my-2 w-full flex items-center gap-1">
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">2023-04-06-from { }<span className="font-normal">Dummy name</span></p>
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">I am testing message</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
messageList?.data?.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
data={messageList?.data}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
{/* ERROR DISPLAY FOR MESSAGE SENDING */}
|
||||
<div className="w-full">
|
||||
{/* error or success display */}
|
||||
{requestStatus.message != "" && requestStatus.processType == 'sendmessage' &&
|
||||
(!requestStatus.status ? (
|
||||
<div
|
||||
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
|
||||
>
|
||||
{requestStatus.message}
|
||||
</div>
|
||||
) : (
|
||||
requestStatus.status && (
|
||||
<div
|
||||
className={`relative p-4 my-4 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 DISPLAY FOR MESSAGE SENDING */}
|
||||
|
||||
{/* message list */}
|
||||
<div className="my-1 min-h-[100px] max-h-[200px] border-t overflow-y-scroll">
|
||||
{ messageList.loading ?
|
||||
<LoadingSpinner color='sky-blue' size='16' />
|
||||
: messageList?.data?.map((item, index)=>(
|
||||
<div key={index} className="my-2 w-full flex items-center gap-1">
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">{item.added.split(' ')[0]}-from { }<span className="font-normal">{item.sender || 'Dummy name'}</span></p>
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">{item.msg}</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -226,7 +298,7 @@ export default function ManageInterestOffer(props) {
|
||||
{/* BUTTON section */}
|
||||
<div className="p-4 w-full min-h-full bg-sky-100 dark:bg-dark-gray col-span-1">
|
||||
<div className="w-full h-full">
|
||||
<div className="mt-0 sm:mt-10 flex sm:flex-col justify-center items-center gap-10">
|
||||
<div className="h-full flex sm:flex-col justify-center items-center gap-10">
|
||||
{requestStatus.loading && requestStatus.processType == 'accept' ?
|
||||
<LoadingSpinner color='sky-blue' size='10' />
|
||||
:
|
||||
@@ -235,9 +307,10 @@ export default function ManageInterestOffer(props) {
|
||||
name='accept'
|
||||
disabled={requestStatus.loading}
|
||||
onClick={interestOfferProcess}
|
||||
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
// className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
className='max-w-[150px] h-[100px] bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md shadow-md'
|
||||
>
|
||||
Accept
|
||||
Accept this Interest
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -249,9 +322,10 @@ export default function ManageInterestOffer(props) {
|
||||
name='reject'
|
||||
disabled={requestStatus.loading}
|
||||
onClick={interestOfferProcess}
|
||||
className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-black"
|
||||
// className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-black"
|
||||
className='max-w-[150px] h-[100px] bg-red-300 text-center text-lg font-semibold text-white py-2 px-4 rounded-md shadow-md'
|
||||
>
|
||||
Reject
|
||||
Reject this Interest
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@@ -259,7 +333,7 @@ export default function ManageInterestOffer(props) {
|
||||
{/* ERROR DISPLAY */}
|
||||
<div className="w-full">
|
||||
{/* error or success display */}
|
||||
{requestStatus.message != "" && requestStatus.processType != 'sendmeassge' &&
|
||||
{requestStatus.message != "" && requestStatus.processType != 'sendmessage' &&
|
||||
(!requestStatus.status ? (
|
||||
<div
|
||||
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
|
||||
@@ -285,6 +359,7 @@ export default function ManageInterestOffer(props) {
|
||||
{/* END OF manage offer section */}
|
||||
</div>
|
||||
|
||||
{props.othersInterestedList?.data?.length ?
|
||||
<div className="w-full overflow-x-auto">
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-3">
|
||||
@@ -296,6 +371,9 @@ export default function ManageInterestOffer(props) {
|
||||
</div>
|
||||
<OthersInterestedTable othersInterestedList={props.othersInterestedList} />
|
||||
</div>
|
||||
:
|
||||
null
|
||||
}
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
@@ -107,19 +107,7 @@ export default function OffersInterestTable({offerInterestList, className}) {
|
||||
:
|
||||
(
|
||||
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
|
||||
<div className="p-2 w-full md:w-1/2">
|
||||
<p className="mb-4 p-3 md:p-16">No Offer list avaliable.</p>
|
||||
<button
|
||||
onClick={()=>{navigate('/market', {replace: true})}}
|
||||
type="button"
|
||||
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
|
||||
>
|
||||
Goto Market
|
||||
</button>
|
||||
</div>
|
||||
<div className="p-2 w-full md:w-1/2">
|
||||
<img className='w-full' src={familyImage && familyImage} alt="Add Family" />
|
||||
</div>
|
||||
<p className="mb-4 p-3">No list avaliable.</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import React, { useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import useToggle from "../../hooks/useToggle";
|
||||
import { drawerToggle } from "../../store/drawer";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
@@ -11,10 +10,9 @@ import RightSideBar from "./RightSideBar";
|
||||
import Sidebar from "./Sidebar";
|
||||
import usersService from "../../services/UsersService";
|
||||
|
||||
|
||||
export default function Layout({ children }) {
|
||||
const { drawer } = useSelector((state) => state.drawer);
|
||||
const {userJobList} = useSelector((state) => state.userJobList)
|
||||
const { userJobList } = useSelector((state) => state.userJobList);
|
||||
const dispatch = useDispatch();
|
||||
const [MobileSideBar, setMobileSidebar] = useToggle(false);
|
||||
const [logoutModal, setLogoutModal] = useState(false);
|
||||
@@ -197,4 +195,4 @@ export default function Layout({ children }) {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,9 +225,10 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
|
||||
<ul className="flex flex-col space-y-6">
|
||||
<ListItem
|
||||
title="Add Job"
|
||||
route="/add-job"
|
||||
route="/myjobs"
|
||||
iconName="people-two"
|
||||
sidebar={sidebar}
|
||||
state={true}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -301,11 +302,12 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
|
||||
);
|
||||
}
|
||||
|
||||
const ListItem = ({ sidebar, route, title, bubble }) => {
|
||||
const ListItem = ({ sidebar, route, title, bubble, popup }) => {
|
||||
return (
|
||||
<li className="item group">
|
||||
<NavLink
|
||||
to={route}
|
||||
state={popup ? { popup: true } : { popup: false }}
|
||||
className={`nav-item flex items-center ${
|
||||
((navData) => (navData.isActive ? "active" : ""),
|
||||
sidebar ? "justify-start space-x-3.5" : "justify-center")
|
||||
|
||||
@@ -8,7 +8,12 @@ import {
|
||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||
import Icons from "../Helpers/Icons";
|
||||
|
||||
export default function Sidebar({ sidebar, action, logoutModalHandler, myJobList }) {
|
||||
export default function Sidebar({
|
||||
sidebar,
|
||||
action,
|
||||
logoutModalHandler,
|
||||
myJobList,
|
||||
}) {
|
||||
const darkMode = useContext(DarkModeContext);
|
||||
|
||||
let { userDetails } = useSelector((state) => state.userDetails);
|
||||
@@ -119,6 +124,15 @@ export default function Sidebar({ sidebar, action, logoutModalHandler, myJobList
|
||||
iconName="market"
|
||||
/>
|
||||
)}
|
||||
{userDetails && userDetails?.account_type == "FAMILY" && (
|
||||
<ListItem
|
||||
title="Family Market"
|
||||
route="/familymarket"
|
||||
// bubble={noOfJobs}
|
||||
sidebar={sidebar}
|
||||
iconName="market"
|
||||
/>
|
||||
)}
|
||||
<ListItem
|
||||
title="My Task(s)"
|
||||
route="/mytask"
|
||||
@@ -131,27 +145,25 @@ export default function Sidebar({ sidebar, action, logoutModalHandler, myJobList
|
||||
|
||||
{/* menu and settings item */}
|
||||
{userDetails?.account_type !== "FAMILY" && (
|
||||
<div
|
||||
className={`menu-item transition-all duration-300 ease-in-out ${
|
||||
sidebar ? "my-5" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="heading mb-5">
|
||||
<h1 className="title text-xl font-bold text-purple">
|
||||
Family
|
||||
</h1>
|
||||
</div>
|
||||
<div className="items">
|
||||
<ul className="flex flex-col space-y-6">
|
||||
<ListItem
|
||||
title="Family Corner"
|
||||
route="/acc-family"
|
||||
iconName="people-two"
|
||||
sidebar={sidebar}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
className={`menu-item transition-all duration-300 ease-in-out ${
|
||||
sidebar ? "my-5" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="heading mb-5">
|
||||
<h1 className="title text-xl font-bold text-purple">Family</h1>
|
||||
</div>
|
||||
<div className="items">
|
||||
<ul className="flex flex-col space-y-6">
|
||||
<ListItem
|
||||
title="Family Corner"
|
||||
route="/acc-family"
|
||||
iconName="people-two"
|
||||
sidebar={sidebar}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{userDetails?.account_type !== "FAMILY" && (
|
||||
<>
|
||||
@@ -249,9 +261,10 @@ export default function Sidebar({ sidebar, action, logoutModalHandler, myJobList
|
||||
<ul className="flex flex-col space-y-6">
|
||||
<ListItem
|
||||
title="Add Job"
|
||||
route="/add-job"
|
||||
route="/myjobs"
|
||||
iconName="people-two"
|
||||
sidebar={sidebar}
|
||||
popup={true}
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -325,11 +338,12 @@ export default function Sidebar({ sidebar, action, logoutModalHandler, myJobList
|
||||
);
|
||||
}
|
||||
|
||||
const ListItem = ({ sidebar, route, title, bubble, iconName }) => {
|
||||
const ListItem = ({ sidebar, route, title, bubble, iconName, popup }) => {
|
||||
return (
|
||||
<li className={`item group`}>
|
||||
<NavLink
|
||||
to={route}
|
||||
state={popup ? { popup: true } : { popup: false }}
|
||||
className={`nav-item flex items-center ${
|
||||
((navData) => (navData.isActive ? "active" : ""),
|
||||
sidebar ? "justify-start space-x-3.5" : "justify-center")
|
||||
|
||||
@@ -1,140 +1,156 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import authProfilePic from "../../assets/images/auth-profile-picture.png";
|
||||
import profileBanner from "../../assets/images/profile-cover.png";
|
||||
import collections from "../../data/collectionplan_data.json";
|
||||
import marketPlace from "../../data/marketplace_data.json";
|
||||
// import authProfilePic from "../../assets/images/auth-profile-picture.png";
|
||||
// import profileBanner from "../../assets/images/profile-cover.png";
|
||||
// import collections from "../../data/collectionplan_data.json"; Should this be cleaned off?
|
||||
// import marketPlace from "../../data/marketplace_data.json";
|
||||
import LoadingSpinner from "../../components/Spinners/LoadingSpinner";
|
||||
import products from "../../data/product_data.json";
|
||||
import Layout from "../Partials/Layout";
|
||||
import ActivitiesTab from "./ActivitiesTab";
|
||||
import CollectionTab from "./CollectionTab";
|
||||
import CreatedTab from "./CreatedTab";
|
||||
import HiddenProductsTab from "./HiddenProductsTab";
|
||||
import OnSaleTab from "./OnSaleTab";
|
||||
import OwnTab from "./OwnTab";
|
||||
import {
|
||||
ActivitiesTab, BlogTab,
|
||||
CollectionTab,
|
||||
CreatedTab,
|
||||
HiddenProductsTab,
|
||||
OnSaleTab,
|
||||
OwnTab,
|
||||
} from "./tabs";
|
||||
|
||||
export default function Resources() {
|
||||
const onSaleProducts = marketPlace.data;
|
||||
const CreatedSell = marketPlace.data;
|
||||
const CreatedBits = products.datas;
|
||||
// const mainProducts = products.datas;
|
||||
export default function Resources(props) {
|
||||
// console.log("RESOURCES=>", props);
|
||||
const ownProducts = products.datas;
|
||||
const collectionProducts = collections.data;
|
||||
// Resource Props
|
||||
const __resources = props.MyResourceData;
|
||||
//debugger;
|
||||
// Collection Items
|
||||
const CreatedSell = __resources?.marketdata?.data;
|
||||
const tab_categories = __resources?.tab_categories?.data;
|
||||
const collectionProducts = __resources?.collectiondata?.data;
|
||||
const onSaleProducts = __resources?.marketdata?.data;
|
||||
const CreatedBits = __resources?.productdata?.datas;
|
||||
const blogItems = __resources?.blogdata?.payload;
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
id: 1,
|
||||
name: "onsale",
|
||||
content: "On Sale",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "owned",
|
||||
content: "Owned",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "created",
|
||||
content: "Created",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "hidden",
|
||||
content: "Hidden",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "collection",
|
||||
content: "Collection",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "activity",
|
||||
content: "Activity",
|
||||
},
|
||||
];
|
||||
const [tab, setTab] = useState(tab_categories ? tab_categories[0]?.name : "");
|
||||
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
// Category Components
|
||||
const tabComponents = {
|
||||
blog: <BlogTab blogdata={blogItems} />,
|
||||
onsale: <OnSaleTab products={onSaleProducts} />,
|
||||
owned: <OwnTab products={ownProducts} />,
|
||||
created: (
|
||||
<CreatedTab marketProducts={CreatedSell} mainProducts={CreatedBits} />
|
||||
),
|
||||
hidden: (
|
||||
<HiddenProductsTab
|
||||
marketProducts={CreatedSell}
|
||||
mainProducts={CreatedBits}
|
||||
/>
|
||||
),
|
||||
collection: <CollectionTab products={collectionProducts} />,
|
||||
activity: <ActivitiesTab />,
|
||||
};
|
||||
|
||||
const defaultTabComponent = <BlogTab blogdata={blogItems} />;
|
||||
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
// Tab Item Component
|
||||
const TabItem = ({ tabValue, isActive }) => {
|
||||
let countNumber = (name) => { // FUNCTION TO DETERMINE THE COUNT NUMBER
|
||||
if(name == 'blog'){
|
||||
return blogItems?.blogdata?.length
|
||||
}else if(name == 'onsale'){
|
||||
return onSaleProducts?.length
|
||||
}else if(name == 'owned'){
|
||||
return ownProducts?.length
|
||||
}else if(name == 'created'){
|
||||
return CreatedSell?.length + CreatedBits?.length
|
||||
}else{
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return (
|
||||
<li
|
||||
className={`relative group inline`}
|
||||
onClick={() => tabHandler(tabValue.name)}
|
||||
>
|
||||
<span
|
||||
className={`py-4 sm:border-b-none border-b group-hover:border-purple border-transparent lg:text-xl text-sm tracking-wide font-bold group-hover:text-purple text-dark-gray dark:text-white relative z-10 cursor-pointer ${
|
||||
isActive
|
||||
? "text-purple border-purple"
|
||||
: "text-dark-gray dark:text-white border-transparent"
|
||||
}`}
|
||||
>
|
||||
{tabValue.content}
|
||||
</span>
|
||||
<span
|
||||
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
|
||||
isActive
|
||||
? "text-white bg-pink"
|
||||
: "text-thin-light-gray bg-[#F2B8FD]"
|
||||
}`}
|
||||
>
|
||||
{/* 16 blog, onsale, owned,created */}
|
||||
{countNumber(tabValue.name)}
|
||||
</span>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
// Tab List Component
|
||||
const TabList = ({ tabCategories }) => {
|
||||
return (
|
||||
<ul className="lg:flex lg:space-x-14 space-x-8">
|
||||
{tabCategories?.length > 0 &&
|
||||
tabCategories?.map((tabValue, idx) => (
|
||||
<TabItem
|
||||
key={tabValue.id}
|
||||
tabValue={tabValue}
|
||||
isActive={tab === tabValue.name || (idx === 0 && tab === "")}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Layout>
|
||||
<div className="nft-authprofile-wrapper w-full">
|
||||
<div className="main-wrapper w-full">
|
||||
<div className="content-wrapper-profile-only w-full mb-6">
|
||||
<div className="auth-tab-content relative mb-10">
|
||||
<div className="lg:flex justify-between">
|
||||
<div className="tab-items">
|
||||
<ul className="lg:flex lg:space-x-14 space-x-8">
|
||||
{tabs &&
|
||||
tabs.length > 0 &&
|
||||
tabs.map((tabValue) => (
|
||||
<li
|
||||
key={tabValue.id}
|
||||
className="relative group inline"
|
||||
onClick={() => tabHandler(tabValue.name)}
|
||||
>
|
||||
<span
|
||||
className={`py-4 sm:border-b-none border-b group-hover:border-purple border-transparent lg:text-xl text-sm tracking-wide font-bold group-hover:text-purple text-dark-gray dark:text-white relative z-10 cursor-pointer ${
|
||||
tab === tabValue.name
|
||||
? "text-purple border-purple "
|
||||
: "text-dark-gray dark:text-white border-transparent "
|
||||
}`}
|
||||
>
|
||||
{tabValue.content}
|
||||
</span>
|
||||
<span
|
||||
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
|
||||
tab === tabValue.name
|
||||
? "text-white bg-pink"
|
||||
: "text-thin-light-gray bg-[#F2B8FD]"
|
||||
}`}
|
||||
>
|
||||
16
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div style={{ transform: "translateY(-22px)" }}>
|
||||
<Link
|
||||
to="/upload-product"
|
||||
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
|
||||
>
|
||||
Upload Product
|
||||
</Link>
|
||||
{__resources.length == 0 || Object.keys(__resources).length == 0 ? (
|
||||
<div className="w-full h-full flex items-center justify-center">
|
||||
<LoadingSpinner size={16} color="sky-blue" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="main-wrapper w-full">
|
||||
<div className="content-wrapper-profile-only w-full mb-6">
|
||||
<div className="auth-tab-content relative mb-10">
|
||||
<div className="lg:flex justify-between">
|
||||
<div className="tab-items">
|
||||
<TabList tabCategories={tab_categories} />
|
||||
</div>
|
||||
<div style={{ transform: "translateY(-22px)" }}>
|
||||
<Link
|
||||
to="/upload-product"
|
||||
className="btn-gradient lg:flex hidden w-[153px] h-[46px] rounded-full text-white justify-center items-center"
|
||||
>
|
||||
Add My Item
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden lg:block w-full h-[1px] bg-[#DCD5FE] dark:bg-[#5356fb29] absolute top-[42px] left-0"></div>
|
||||
</div>
|
||||
<div className="hidden lg:block w-full h-[1px] bg-[#DCD5FE] dark:bg-[#5356fb29] absolute top-[42px] left-0"></div>
|
||||
</div>
|
||||
|
||||
<div className="tab-cotainer w-full mb-10">
|
||||
{selectedTabComponent}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="tab-cotainer w-full mb-10">
|
||||
{tab === "onsale" ? (
|
||||
<OnSaleTab products={onSaleProducts} />
|
||||
) : tab === "owned" ? (
|
||||
<OwnTab products={ownProducts} />
|
||||
) : tab === "created" ? (
|
||||
<CreatedTab
|
||||
marketProducts={CreatedSell}
|
||||
mainProducts={CreatedBits}
|
||||
/>
|
||||
) : tab === "hidden" ? (
|
||||
<HiddenProductsTab
|
||||
marketProducts={CreatedSell}
|
||||
mainProducts={CreatedBits}
|
||||
/>
|
||||
) : tab === "collection" ? (
|
||||
<CollectionTab products={collectionProducts} />
|
||||
) : tab === "activity" ? (
|
||||
<ActivitiesTab />
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Layout>
|
||||
</>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from "react";
|
||||
import dataImage1 from "../../assets/images/data-table-user-1.png";
|
||||
import dataImage2 from "../../assets/images/data-table-user-2.png";
|
||||
import dataImage3 from "../../assets/images/data-table-user-3.png";
|
||||
import dataImage4 from "../../assets/images/data-table-user-4.png";
|
||||
import dataImage1 from "../../../assets/images/data-table-user-1.png";
|
||||
import dataImage2 from "../../../assets/images/data-table-user-2.png";
|
||||
import dataImage3 from "../../../assets/images/data-table-user-3.png";
|
||||
import dataImage4 from "../../../assets/images/data-table-user-4.png";
|
||||
|
||||
export default function ActivitiesTab({ className }) {
|
||||
return (
|
||||
@@ -0,0 +1,65 @@
|
||||
import ProductCardStyleTwo from "../../Cards/ProductCardStyleTwo";
|
||||
import DataIteration from "../../Helpers/DataIteration";
|
||||
import SearchCom from "../../Helpers/SearchCom";
|
||||
import ResourceBlogCard from "../../Cards/ResourceBlogCard";
|
||||
|
||||
export default function BlogTab({ className, blogdata }) {
|
||||
console.log("Blog data here>> ", blogdata);
|
||||
// debugger;
|
||||
return (
|
||||
<>
|
||||
<div className={`onsale-tab-wrapper w-full ${className || ""}`}>
|
||||
<div className="main-container w-full">
|
||||
<div className="filter-section w-full items-center sm:flex justify-between mb-6">
|
||||
{/* filter-search */}
|
||||
<div className="sm:w-1/2 w-full sm:pr-20 pr-0 mb-5 sm:mb-0">
|
||||
<SearchCom placeholder='Search Blog Items...' />
|
||||
</div>
|
||||
{/* filer-dropdown */}
|
||||
<div className="flex-1 flex sm:justify-end">
|
||||
{/* <div className="flex space-x-1 items-center">*/}
|
||||
{/*<span className="text-18 text-thin-light-gray">*/}
|
||||
{/* Recently Received*/}
|
||||
{/*</span>*/}
|
||||
{/* <span>*/}
|
||||
{/* <svg*/}
|
||||
{/* width="20"*/}
|
||||
{/* height="10"*/}
|
||||
{/* viewBox="0 0 13 6"*/}
|
||||
{/* fill="none"*/}
|
||||
{/* xmlns="http://www.w3.org/2000/svg"*/}
|
||||
{/* >*/}
|
||||
{/* <path*/}
|
||||
{/* opacity="0.7"*/}
|
||||
{/* d="M12.4124 0.247421C12.3327 0.169022 12.2379 0.106794 12.1335 0.0643287C12.0291 0.0218632 11.917 0 11.8039 0C11.6908 0 11.5787 0.0218632 11.4743 0.0643287C11.3699 0.106794 11.2751 0.169022 11.1954 0.247421L7.27012 4.07837C7.19045 4.15677 7.09566 4.219 6.99122 4.26146C6.88678 4.30393 6.77476 4.32579 6.66162 4.32579C6.54848 4.32579 6.43646 4.30393 6.33202 4.26146C6.22758 4.219 6.13279 4.15677 6.05312 4.07837L2.12785 0.247421C2.04818 0.169022 1.95338 0.106794 1.84895 0.0643287C1.74451 0.0218632 1.63249 0 1.51935 0C1.40621 0 1.29419 0.0218632 1.18975 0.0643287C1.08531 0.106794 0.990517 0.169022 0.910844 0.247421C0.751218 0.404141 0.661621 0.616141 0.661621 0.837119C0.661621 1.0581 0.751218 1.2701 0.910844 1.42682L4.84468 5.26613C5.32677 5.73605 5.98027 6 6.66162 6C7.34297 6 7.99647 5.73605 8.47856 5.26613L12.4124 1.42682C12.572 1.2701 12.6616 1.0581 12.6616 0.837119C12.6616 0.616141 12.572 0.404141 12.4124 0.247421Z"*/}
|
||||
{/* fill="#374557"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* </svg>*/}
|
||||
{/*</span>*/}
|
||||
{/* </div>*/}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="content-section w-full-width">
|
||||
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
|
||||
<DataIteration
|
||||
datas={blogdata?.blogdata}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={blogdata?.blogdata.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<ResourceBlogCard
|
||||
key={datas.id}
|
||||
datas={datas}
|
||||
bg={blogdata.image_url}
|
||||
/>
|
||||
)}
|
||||
</DataIteration>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
import CollectionCard from "../Cards/CollectionCard";
|
||||
import DataIteration from "../Helpers/DataIteration";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import CollectionCard from "../../Cards/CollectionCard";
|
||||
import DataIteration from "../../Helpers/DataIteration";
|
||||
import SearchCom from "../../Helpers/SearchCom";
|
||||
|
||||
export default function CollectionTab({ className, products }) {
|
||||
return (
|
||||
@@ -43,7 +42,7 @@ export default function CollectionTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<CollectionCard key={datas.uniqKey} collectionData={datas} />
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useRef } from "react";
|
||||
import ProductCardStyleTwo from "../Cards/ProductCardStyleTwo";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import SliderCom from"../Helpers/SliderCom";
|
||||
import { useRef } from "react";
|
||||
import ProductCardStyleTwo from "../../Cards/ProductCardStyleTwo";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import SliderCom from "../../Helpers/SliderCom";
|
||||
|
||||
export default function CreateSaleSlider({
|
||||
className,
|
||||
@@ -42,7 +42,9 @@ export default function CreateSaleSlider({
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Sell</h1>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Create for Sell
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<button onClick={nextHandler} type="button">
|
||||
@@ -89,7 +91,7 @@ export default function CreateSaleSlider({
|
||||
<div className="trending-products relative w-full">
|
||||
<SliderCom selector={trendingSlider} settings={settings}>
|
||||
{products &&
|
||||
products.length > 0 &&
|
||||
products?.length > 0 &&
|
||||
products.map((item) => (
|
||||
<ProductCardStyleTwo
|
||||
key={item.id}
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useRef } from "react";
|
||||
import ProductCardStyleOne from "../Cards/ProductCardStyleOne";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import SliderCom from "../Helpers/SliderCom";
|
||||
import { useRef } from "react";
|
||||
import ProductCardStyleOne from "../../Cards/ProductCardStyleOne";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import SliderCom from "../../Helpers/SliderCom";
|
||||
|
||||
export default function CreatedBidsSlider({
|
||||
className,
|
||||
@@ -49,7 +49,9 @@ export default function CreatedBidsSlider({
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">Create for Bits</h1>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Create for Bits
|
||||
</h1>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-4">
|
||||
<button onClick={nextHandler} type="button">
|
||||
@@ -96,7 +98,7 @@ export default function CreatedBidsSlider({
|
||||
<div className="trending-products relative w-full">
|
||||
<SliderCom selector={trendingSlider} settings={settings}>
|
||||
{products &&
|
||||
products.length > 0 &&
|
||||
products?.length > 0 &&
|
||||
products.map((item) => (
|
||||
<ProductCardStyleOne
|
||||
key={item.id}
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import SearchCom from "../../Helpers/SearchCom";
|
||||
import CreatedBidsSlider from "./CreatedBidsSlider";
|
||||
import CreateSaleSlider from "./CreateSaleSlider";
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import SearchCom from "../../Helpers/SearchCom";
|
||||
import CreatedBidsSlider from "./CreatedBidsSlider";
|
||||
import CreateSaleSlider from "./CreateSaleSlider";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
import ProductCardStyleTwo from "../Cards/ProductCardStyleTwo";
|
||||
import DataIteration from "../Helpers/DataIteration";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import ProductCardStyleTwo from "../../Cards/ProductCardStyleTwo";
|
||||
import DataIteration from "../../Helpers/DataIteration";
|
||||
import SearchCom from "../../Helpers/SearchCom";
|
||||
|
||||
export default function OnSaleTab({ className, products }) {
|
||||
return (
|
||||
@@ -43,7 +42,7 @@ export default function OnSaleTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<ProductCardStyleTwo key={datas.id} datas={datas} />
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
import ProductCardStyleOne from "../Cards/ProductCardStyleOne";
|
||||
import DataIteration from "../Helpers/DataIteration";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import ProductCardStyleOne from "../../Cards/ProductCardStyleOne";
|
||||
import DataIteration from "../../Helpers/DataIteration";
|
||||
import SearchCom from "../../Helpers/SearchCom";
|
||||
|
||||
export default function OwnTab({ className, products }) {
|
||||
return (
|
||||
@@ -43,7 +42,7 @@ export default function OwnTab({ className, products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<ProductCardStyleOne key={datas.id} datas={datas} />
|
||||
@@ -0,0 +1,17 @@
|
||||
import ActivitiesTab from "./ActivitiesTab";
|
||||
import CollectionTab from "./CollectionTab";
|
||||
import CreatedTab from "./CreatedTab";
|
||||
import HiddenProductsTab from "./HiddenProductsTab";
|
||||
import OnSaleTab from "./OnSaleTab";
|
||||
import OwnTab from "./OwnTab";
|
||||
import BlogTab from "./BlogTab";
|
||||
|
||||
export {
|
||||
BlogTab,
|
||||
ActivitiesTab,
|
||||
CollectionTab,
|
||||
CreatedTab,
|
||||
HiddenProductsTab,
|
||||
OnSaleTab,
|
||||
OwnTab,
|
||||
};
|
||||
@@ -8,7 +8,7 @@ export default function MainSection({ products }) {
|
||||
<DataIteration
|
||||
datas={products}
|
||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||
endLength={products.length}
|
||||
endLength={products?.length}
|
||||
>
|
||||
{({ datas }) => (
|
||||
<div key={datas.id + Math.random()} className="item">
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
import React from "react";
|
||||
|
||||
export default function PrivacyPolicyTab() {
|
||||
return (
|
||||
<div className="terms-conditon-tab w-full">
|
||||
<div className="terms-condition-wrappr w-full">
|
||||
<div className="mb-6">
|
||||
<h1 className="text-3xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Privacy Policy
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
Wrenchboard issues this policy to inform users about the information
|
||||
we collect, the use and disclosures in the course of interactions
|
||||
with the WrenchBoard services by customers. We value the privacy of
|
||||
our customers and such strive to employ best industry standards and
|
||||
practices to protect their privacy. By signing up for this services,
|
||||
using our products or technologies offered through the WrenchBoard
|
||||
website, you expressly agree to the terms of this Privacy Policy.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Collection of Information
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
When you sign up for WrenchBoard platform as a user, freelancer,
|
||||
worker or client, you inadvertently provide certain personal
|
||||
information such as name and email address. This information may be
|
||||
used to identify or contact you as part of the service we provide.
|
||||
Below is information we may collect from registered users of the
|
||||
service.
|
||||
</p>
|
||||
<ul className="flex flex-col rounded-[0.25rem]">
|
||||
{[
|
||||
"We collect financial information which include bank account numbers, debit/credit account.",
|
||||
"We collect financial information which include bank account numbers, debit/credit account.",
|
||||
"We collect personal information (names email addresses) from you and your friends when you use our referral program. We may also receive information about you from third party sites during promotions and campaigns.",
|
||||
].map((item, idx) => (
|
||||
<li
|
||||
className="border-opacity-10 block relative px-[1.25rem] py-[0.75rem] first:rounded-tl first:rounded-tr text-[#505056]"
|
||||
key={idx}
|
||||
>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Use of Personal Information
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
The information we collect about you is mainly utilized to provide a
|
||||
secure, efficient and smooth user experience as you interact with
|
||||
the site. We may also utilize the information to contact you to
|
||||
resolve issues with your account or resolve disputes between
|
||||
freelancers and clients. We also use your personal information in
|
||||
the following ways.
|
||||
</p>
|
||||
<ul className="flex flex-col rounded-[0.25rem]">
|
||||
{[
|
||||
"To comply with the regulatory requirement, whenever the need arises.",
|
||||
"To improve business relationship between Wrenchboard and users.",
|
||||
"To manage and protect our IT infrastructure.",
|
||||
"To contact you as the need arises as part of the services we offer to users.",
|
||||
"To provide some indication on the promotional offers and advertisement we direct to you.",
|
||||
"To protect you and your information. We regularly send you notification based on activities as you use the service.",
|
||||
].map((item, idx) => (
|
||||
<li
|
||||
className="border-opacity-10 block relative px-[1.25rem] py-[0.75rem] first:rounded-tl first:rounded-tr text-[#505056]"
|
||||
key={idx}
|
||||
>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
How We Share Your Personal Information:
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
When you sign up to the Service as a freelancer and create a
|
||||
profile, we will share your limited personal information with
|
||||
clients or project owners for whom you may perform a task or do work
|
||||
for based on expression of interest. Such information will include
|
||||
name, profile information with experience and your ranking based on
|
||||
previous performance. This information will be available to the
|
||||
public.
|
||||
<br />
|
||||
When you register as a client or project owner and post a job in the
|
||||
market place or offer jobs to preselected freelancers or workers on
|
||||
this service, information about you, your business will be shared.
|
||||
This information will be based on the information provided in your
|
||||
profile. <br />
|
||||
In order to deliver a quality service on WrenchBoard, we require the
|
||||
services of third parties and agents such as PayPal, Quickteller
|
||||
Service or banks to facilitate and process transactions. <br />
|
||||
We may also share your personal information when and if compelled or
|
||||
mandated by government agencies, or court injunctions or regulatory
|
||||
requirement. In order to settle disputes or claims, we may also be
|
||||
compelled to share your information in order to deliver services to
|
||||
you. <br />
|
||||
Finally, we may share your information with companies that we plan
|
||||
to to merge with or to be acquired by. We will take necessary
|
||||
measure to ensure that all such new affiliations and corporate
|
||||
entities comply with the Privacy Policies hereby stated failing
|
||||
which you will be notified duly.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
How We Use Cookies and Related Technologies:
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
When you access the service or website, www.wrenchboard.com , we
|
||||
store small files called Cookies in your browser. Cookies and
|
||||
related technologies like beacons and tags are used to identify
|
||||
customers uniquely. With Cookies, we can track and trend the pages
|
||||
of interest within the website. Hence, these technologies help us
|
||||
focus only relevant promotions or advertisement to each customer.
|
||||
Through this technologies, we are able to improve the service based
|
||||
on the feedback from the interaction with users. We also rely on
|
||||
these technologies to mitigate fraudulent attempts on your
|
||||
WrenchBoard account. You may elect to disable cookies to prevent
|
||||
installation of cookies from the website to your browser. However,
|
||||
your functional experience with the service or website may be
|
||||
impacted. Note that you automatically disconnect from cookies when
|
||||
you close your browser session or log out of the service.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Measures We Take to Secure Your Information
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
Your data and privacy are important to us as such we take extreme
|
||||
care on how we protect your information. We use a combination of
|
||||
industry standard encryption technologies to protect your
|
||||
information. Your password is not visible to our technical support
|
||||
team or any one in WrenchBoard. Our IT infrastructures are located
|
||||
in hosting facilities with strict access controls, and security
|
||||
protocols with only pre checked and authorized persons have access.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Updating Your Information or Opting Out
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
Users of this service may update the information posted in profiles
|
||||
or their accounts at any time. The accuracy of information posted on
|
||||
the profiles and accounts is entirely the responsibility of users.
|
||||
You may also decide to opt out the service or close your account at
|
||||
any time. We may also deactivate your account if you violate the
|
||||
terms of use of the website. Whilst we will endeavor to delete your
|
||||
core information in such instances, we will retain minimal records
|
||||
for reasons including disputes, claims or administrative purposes.
|
||||
Also, note that it may not be possible to delete any information you
|
||||
had shared with other users on the website previously.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Deactivate/Delete your account
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
If you no longer wish to use our Services, you can deactivate your
|
||||
Services account. If you want to deactivate your account, that
|
||||
setting is available to you in your account settings. Otherwise,
|
||||
please get in touch with our support. While we close any associated
|
||||
process, you will not be able to access your account. Note that this
|
||||
process cannot be reversed since we will remove your data. If you
|
||||
want to use our services in the future, it will be a new account
|
||||
altogether.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="mt-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Changes To the Policy
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
We reserve the rights to update and make changes to this Privacy
|
||||
policy at anytime. Changes will become effective once posted.
|
||||
However, we will notify you by email or when you log on to the
|
||||
service or website about any changes that fundamentally affect how
|
||||
we manage your personal information. Contacting Us: You may contact
|
||||
us about this policy through our email address anytime :
|
||||
support@wrenchboard.com
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,77 +4,231 @@ export default function TermsConditionTab() {
|
||||
return (
|
||||
<div className="terms-conditon-tab w-full">
|
||||
<div className="terms-condition-wrappr w-full">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
1. Definitions
|
||||
<div className="mb-6">
|
||||
<h1 className="text-3xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Terms of use
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
What you do own when you buy an NFT are the keys to a non-fungible –
|
||||
perhaps unique – token. That token is yours to trade or hold or
|
||||
display in Decentraland. But the digital file associated with an NFT
|
||||
is just as easy to copy and paste and download as any other – the
|
||||
Finally, players lose their NFTs sometimes according to the rules
|
||||
and regulations of the NFT game.
|
||||
These Website Terms & Conditions (“T&Cs”) apply to your access and
|
||||
use of www.wrenchboard.com,dashboard.wrenchboard.com (the “Site”),
|
||||
including all software, data, reports, text, images, sounds, video,
|
||||
and all contents made available through any portion of the Site
|
||||
(collectively, the “Content”). Content includes all such elements as
|
||||
a whole, as well as individual elements and portions thereof.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
2. Acceptance
|
||||
<hr />
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Acceptance of Terms
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet
|
||||
sint. Velit officia consequat duis enim velit mollit. Exercitation
|
||||
veniam consequat sunt nostrud amet.Capacity. You confirm that you
|
||||
have the legal capacity to receive and hold and make use of the NFT
|
||||
under French jurisdiction and any other relevant
|
||||
jurisdiction.Acceptance. By participating in the Sale, You accept
|
||||
and agree to these Terms and Conditions without any condition or
|
||||
restriction. If You do not agree to this Contract, You shall not
|
||||
participate in the Sale made by the Company Exercitation veniam
|
||||
consequat sunt nostrud amet.Capacity. You confirm that you have the
|
||||
legal capacity to receive and hold find to end.Contract, You shall
|
||||
not participate in the Sale made by the Company Exercitation venia
|
||||
WRENCHBOARD permits you (“User” or “you” or “your”) to access and
|
||||
use the Site and Content, subject to these T&Cs. By accessing or
|
||||
using any portion of the Site, you acknowledge that you have read,
|
||||
understood, and agree to be bound by these T&Cs. If you do not agree
|
||||
with these T&Cs, you must not accept these T&Cs or access or use the
|
||||
site or content.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-8 bg-purple p-[23px] text-white rounded-lg">
|
||||
<p className="text-[18px]">
|
||||
These Terms and Conditions are related to the sale of NFTs by the
|
||||
Company (the “Company”) on its Website. It solely governs the
|
||||
contractual relationship between You and the Company regarding the
|
||||
Sale and any related contract.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
3. The Sale
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
General Conditions of Use
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
The Company offers NFTs featuring the Betonyou universe. The holders
|
||||
of one or more NFTs will be able to win cryptos while playing video
|
||||
games. In the future, the Company plans to develop its own games and
|
||||
Metaverse around the Betonyou universe (“Project”). <br />
|
||||
<b> Authorization to Access and Use Site and Content.</b> Subject to
|
||||
your compliance with these T&Cs and the provisions hereof, you may
|
||||
access or use the Site and Content solely for the purpose of your
|
||||
evaluation of WRENCHBOARD and WRENCHBOARD’s products and services.
|
||||
You may only link to the Site or Content, or any portion thereof, as
|
||||
expressly permitted by WRENCHBOARD.
|
||||
<br />
|
||||
To release the NFTs and fund the project, the Company offers NFTs
|
||||
from a dedicated website("Sale"). The web address of this website
|
||||
will be given at the time of the mint. The NFT acquisition does not
|
||||
confer any rights on the Company or in the future development.
|
||||
<b> Ownership and Restrictions.</b> All rights, title, and interest
|
||||
in and to the Site and Content will remain with and belong
|
||||
exclusively to WRENCHBOARD. You will not (a) sublicense, resell,
|
||||
rent, lease, transfer, assign, time share or otherwise commercially
|
||||
exploit or make the Site and any Content available to any third
|
||||
party, (b) use the Site and Content in any unlawful manner
|
||||
(including without limitation in violation of any data, privacy or
|
||||
export control laws) or in any manner that interferes with or
|
||||
disrupts the integrity or performance of the Site and Content or
|
||||
their related components, or (c) modify, adapt or hack the Site and
|
||||
Content to, or try to, gain unauthorized access to the restricted
|
||||
portions of the Site and Content or related systems or networks
|
||||
(i.e., circumvent any encryption or other security measures, gain
|
||||
access to any source code or any other underlying form of technology
|
||||
or information, and gain access to any part of the Site and Content,
|
||||
or any other products or services of WRENCHBOARD that are not
|
||||
readily made available to the general public). You are not permitted
|
||||
to copy, modify, frame, repost, publicly perform or display, sell,
|
||||
reproduce, distribute, or create derivative works of the Site and
|
||||
Content, except that you may download, display, and print one copy
|
||||
of the publicly available materials (i.e., the Content that does not
|
||||
require an Account name or password to access) on any single
|
||||
computer solely for your personal, non-commercial use, provided that
|
||||
you do not modify the material in any way and you keep intact all
|
||||
copyright, trademark, and other proprietary notices. You agree not
|
||||
to access the Site or Content by any means other than through the
|
||||
interface that is provided by WRENCHBOARD to access the same. You
|
||||
may not use any “page-scrape,” “deep-link,” “spider,” or “robot or
|
||||
other automatic program, device, algorithm or methodology, or any
|
||||
similar manual process, to access, copy, acquire, or monitor any
|
||||
portion of the Site or any Content, or in any way reproduce or
|
||||
circumvent the presentation or navigational structure of the Site or
|
||||
any Content, to obtain or attempt to obtain any Content or other
|
||||
information through any means not made generally available through
|
||||
the Site by WRENCHBOARD. WRENCHBOARD reserves the right to take any
|
||||
lawful measures to prevent any such activity. You may not forge
|
||||
headers or otherwise manipulate identifiers in order to disguise the
|
||||
origin of any message or transmittal you send to WRENCHBOARD on or
|
||||
through the Site or any service offered on or through the Site. You
|
||||
may not pretend that you are, or that you represent, someone else,
|
||||
or impersonate any other individual or entity.
|
||||
<b> Responsibility for Your Data.</b> You are solely responsible for
|
||||
all data, information, and other content, that you upload, post, or
|
||||
otherwise provide or store (hereafter “post(ing)”) in connection
|
||||
with or relating to the Site.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
4. Purchaser’s obligations
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Use of Intellectual Property.
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
To the fullest extent permitted by applicable law, You undertake to
|
||||
indemnify, defend and hold harmless the Company from and against all
|
||||
claims, demands, actions, damages, losses, costs and expenses
|
||||
(including attorneys’ fees) that arise from or relate to (i) your
|
||||
Subscription or use of the NFTs; (ii) your responsibilities or
|
||||
obligations under this Contract; and (iii) your breach of this
|
||||
Contract. <br /> <br /> Company undertakes to act with the care
|
||||
normally expected from a professional in his field and to comply
|
||||
with the best practice in force. The best endeavor obligation only
|
||||
binds the Company.
|
||||
<b> Rights in User Content.</b> By posting your information and
|
||||
other content (“User Content”) on or through the Site and Content,
|
||||
you grant WRENCHBOARD a worldwide, non-exclusive, perpetual,
|
||||
irrevocable, royalty-free, fully paid, sublicensable and
|
||||
transferable license to use, modify, reproduce, distribute, display,
|
||||
publish and perform User Content in connection with the Site and
|
||||
Content. WRENCHBOARD has the right, but not the obligation, to
|
||||
monitor the Site and Content and User Content. WRENCHBOARD may
|
||||
remove or disable any User Content at any time for any reason, or
|
||||
for no reason at all. You, the user, acknowledge that you bear sole
|
||||
responsibility for adequate security, protection, and backup of User
|
||||
Content. WRENCHBOARD will have no liability to you for any
|
||||
unauthorized access or use of any of User Content, or any
|
||||
corruption, deletion, destruction, or loss of any of User Content.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Feedback
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
You may submit ideas, suggestions, or comments (“Feedback”)
|
||||
regarding the Site and Content or WRENCHBOARD’s business, products,
|
||||
or services. By submitting any Feedback, you acknowledge and agree
|
||||
that (a) your Feedback is provided by you voluntarily and
|
||||
WRENCHBOARD may, without any obligations or limitation, use and
|
||||
exploit such Feedback in any manner and for any purpose, (b) you
|
||||
will not seek and are not entitled to any money or other form of
|
||||
compensation, consideration, or attribution with respect to your
|
||||
Feedback regardless of whether WRENCHBOARD considered or used your
|
||||
Feedback in any manner, and (c) your Feedback is not the
|
||||
confidential or proprietary information of you or any third party.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Termination of Access Due to Violations
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
WRENCHBOARD may, in its sole discretion and without prior notice,
|
||||
terminate your access to the Site and/or block your future access to
|
||||
the Site if we determine that you have violated these T&Cs or other
|
||||
agreements or guidelines which may be associated with your use of
|
||||
the Site. You also agree that any violation by you of these T&Cs
|
||||
will cause irreparable harm to WRENCHBOARD, for which monetary
|
||||
damages would be inadequate, and you consent to WRENCHBOARD
|
||||
obtaining any injunctive or equitable relief that WRENCHBOARD deems
|
||||
necessary or appropriate in such circumstances, without limiting
|
||||
WRENCHBOARD’s other available remedies. Further, WRENCHBOARD may, in
|
||||
its sole discretion and without prior notice, terminate your access
|
||||
to the Site, for cause, which includes (but is not limited to) (1)
|
||||
requests by law enforcement or other government agencies, (2)
|
||||
discontinuance or material modification of the Site or any service
|
||||
offered on or through the Site, or (3) unexpected technical issues
|
||||
or problems.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
T&Cs Updates
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
WRENCHBOARD reserves the right, at its sole discretion, to change or
|
||||
modify portions of these T&Cs at any time. WRENCHBOARD will post the
|
||||
changes to these T&Cs on the Site and will indicate at the top of
|
||||
this page the date these terms were last revised. It is your
|
||||
responsibility to check the T&Cs periodically for changes. Your
|
||||
continued use of the Site and Content after the date any such
|
||||
changes become effective constitutes your acceptance of the new or
|
||||
revised T&Cs.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
NO WARRANTIES AND DISCLAIMER BY WRENCHBOARD
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
THE SITE AND CONTENT, AND ALL SERVER AND NETWORK COMPONENTS, ARE
|
||||
PROVIDED ON AN “AS IS” AND “AS AVAILABLE” BASIS WITH ALL ERRORS AND
|
||||
DEFECTS AND WITHOUT ANY WARRANTIES OF ANY KIND, AND WRENCHBOARD
|
||||
EXPRESSLY DISCLAIMS ALL REPRESENTATIONS AND WARRANTIES, INCLUDING
|
||||
ANY IMPLIED WARRANTIES OF ACCURACY, COMPLETENESS, MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, AND ANY
|
||||
REPRESENTATIONS OR WARRANTIES ARISING FROM COURSE OF DEALING, COURSE
|
||||
OF PERFORMANCE OR USAGE OF TRADE. YOU ACKNOWLEDGE THAT WRENCHBOARD
|
||||
DOES NOT WARRANT THAT YOUR ACCESS OR USE OR BOTH OF THE SITE AND
|
||||
CONTENT WILL BE UNINTERRUPTED, TIMELY, SECURE, ERROR-FREE OR
|
||||
VIRUS-FREE, AND WRENCHBOARD DOES NOT MAKE ANY WARRANTY AS TO THE
|
||||
RESULTS THAT MAY BE OBTAINED FROM USE OF THE SITE AND CONTENT. NO
|
||||
INFORMATION, ADVICE OR SERVICES OBTAINED BY YOU FROM WRENCHBOARD OR
|
||||
THROUGH THE SITE WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN
|
||||
THESE TERMS and CONDITIONS AND YOU SHOULD NOT RELY ON THE SITE AND
|
||||
THE GENERAL CONTENT ALONE AS THE BASIS FOR YOUR BUSINESS DECISIONS.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="my-8">
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
WRENCHBOARD reserves the right to do any of the following, at any
|
||||
time, without notice: (1) to modify, suspend or terminate operation
|
||||
of or access to the Site, or any portion of the Site, for any
|
||||
reason; (2) to modify or change the Site, or any portion of the
|
||||
Site, for any reason; and (3) to interrupt the operation of the
|
||||
Site, or any portion of the Site, as necessary to perform routine or
|
||||
non-routine maintenance, error correction, or other changes..
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<div className="mt-8">
|
||||
<h1 className="text-2xl tracking-wide font-bold text-dark-gray dark:text-white mb-4">
|
||||
Changes To the Policy
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray leading-[28px] ">
|
||||
We reserve the rights to update and make changes to this Privacy
|
||||
policy at anytime. Changes will become effective once posted.
|
||||
However, we will notify you by email or when you log on to the
|
||||
service or website about any changes that fundamentally affect how
|
||||
we manage your personal information. Contacting Us: You may contact
|
||||
us about this policy through our email address anytime :
|
||||
support@wrenchboard.com
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import ChangePasswordTab from "./ChangePasswordTab";
|
||||
import FaqTab from "./FaqTab";
|
||||
import LoginActivityTab from "./LoginActivityTab";
|
||||
import NotificationSettingTab from "./NotificationSettingTab";
|
||||
import PaymentMathodsTab from "./PaymentMathodsTab";
|
||||
import PersonalInfoTab from "./PersonalInfoTab";
|
||||
import PrivacyPolicyTab from "./PrivacyPolicyTab";
|
||||
import TermsConditionTab from "./TermsConditionTab";
|
||||
|
||||
export {
|
||||
ChangePasswordTab,
|
||||
FaqTab,
|
||||
LoginActivityTab,
|
||||
NotificationSettingTab,
|
||||
PaymentMathodsTab,
|
||||
PersonalInfoTab,
|
||||
PrivacyPolicyTab,
|
||||
TermsConditionTab,
|
||||
};
|
||||
@@ -1,56 +1,20 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import cover from "../../assets/images/profile-info-cover.png";
|
||||
import profile from "../../assets/images/profile-info-profile.png";
|
||||
|
||||
import Icons from "../Helpers/Icons";
|
||||
import Layout from "../Partials/Layout";
|
||||
import ChangePasswordTab from "./Tabs/ChangePasswordTab";
|
||||
import FaqTab from "./Tabs/FaqTab";
|
||||
import LoginActivityTab from "./Tabs/LoginActivityTab";
|
||||
import NotificationSettingTab from "./Tabs/NotificationSettingTab";
|
||||
import PaymentMathodsTab from "./Tabs/PaymentMathodsTab";
|
||||
import PersonalInfoTab from "./Tabs/PersonalInfoTab";
|
||||
import TermsConditionTab from "./Tabs/TermsConditionTab";
|
||||
import {
|
||||
ChangePasswordTab,
|
||||
FaqTab,
|
||||
LoginActivityTab,
|
||||
NotificationSettingTab,
|
||||
PaymentMathodsTab,
|
||||
PersonalInfoTab,
|
||||
PrivacyPolicyTab,
|
||||
TermsConditionTab,
|
||||
} from "./Tabs";
|
||||
|
||||
export default function Settings({faq}) {
|
||||
const tabs = [
|
||||
{
|
||||
id: 1,
|
||||
name: "personal",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "payment",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "notification",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "login_activity",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "password",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "faq",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "privacy",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "terms",
|
||||
},
|
||||
];
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
export default function Settings({ faq }) {
|
||||
const [profileImg, setProfileImg] = useState(profile);
|
||||
const [coverImg, setCoverImg] = useState(cover);
|
||||
|
||||
@@ -83,6 +47,62 @@ export default function Settings({faq}) {
|
||||
}
|
||||
};
|
||||
|
||||
// Tabs Handling
|
||||
const tabs = [
|
||||
{
|
||||
id: 1,
|
||||
name: "personal",
|
||||
title: "Edit Profile",
|
||||
iconName: "people-hover",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "payment",
|
||||
title: "Payment Method",
|
||||
iconName: "bank-card",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "notification",
|
||||
title: "Notification Setting",
|
||||
iconName: "notification-setting",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "login_activity",
|
||||
title: "Login Activity",
|
||||
iconName: "login-activity",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "password",
|
||||
title: "Change Password",
|
||||
iconName: "password-hover",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "faq",
|
||||
title: "FAQ",
|
||||
iconName: "block-question",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "privacy",
|
||||
title: "Privacy Policy",
|
||||
iconName: "page-right",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "terms",
|
||||
title: "Terms and Conditions",
|
||||
iconName: "page-right",
|
||||
},
|
||||
];
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Layout>
|
||||
@@ -97,136 +117,28 @@ export default function Settings({faq}) {
|
||||
<div className="content-container w-full pt-10 rounded-2xl bg-white dark:bg-dark-white ">
|
||||
<div className="content-heading w-full mb-8 lg:px-10 px-4">
|
||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white antialiased">
|
||||
Parsonal Informaiton
|
||||
Personal Information
|
||||
</h1>
|
||||
</div>
|
||||
<div className="content-body w-full lg:flex lg:px-10 px-4">
|
||||
<div className="content-tab-items lg:w-[230px] w-full mr-2">
|
||||
<ul className="overflow-hidden mb-10 lg:mb-0">
|
||||
<li
|
||||
onClick={() => tabHandler("personal")}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "personal"
|
||||
? "text-purple"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="people-hover" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">Edit Profile</p>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => tabHandler("payment")}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "payment"
|
||||
? "text-purple"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="bank-card" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">Payment Method</p>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => tabHandler("notification")}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "notification"
|
||||
? "text-purple"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="notification-setting" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">
|
||||
Notifiction Setting
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => tabHandler("login_activity")}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "login_activity"
|
||||
? "text-purple"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="login-activity" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">Login Activity</p>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => tabHandler("password")}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "password"
|
||||
? "text-purple"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="password-hover" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">Change Password</p>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => tabHandler("faq")}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "faq" ? "text-purple" : " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="block-question" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">FAQ</p>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => tabHandler("terms")}
|
||||
{tabs.map(({ name, id, title, iconName }) => (
|
||||
<li
|
||||
onClick={() => tabHandler(name)}
|
||||
key={id}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "privacy"
|
||||
? "text-purple"
|
||||
: " text-thin-light-gray"
|
||||
tab === name ? "text-purple" : " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="page-right" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">
|
||||
Privacy Policy
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => tabHandler("terms")}
|
||||
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
|
||||
tab === "terms"
|
||||
? "text-purple"
|
||||
: " text-thin-light-gray"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<Icons name="page-right" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">
|
||||
Terms and Conditions
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
>
|
||||
<div>
|
||||
<Icons name={iconName} />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-18 tracking-wide">{title}</p>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="w-[1px] bg-[#E3E4FE] dark:bg-[#a7a9b533] mr-10"></div>
|
||||
@@ -258,6 +170,7 @@ export default function Settings({faq}) {
|
||||
{tab === "login_activity" && <LoginActivityTab />}
|
||||
{tab === "password" && <ChangePasswordTab />}
|
||||
{tab === "faq" && <FaqTab datas={faq} />}
|
||||
{tab === "privacy" && <PrivacyPolicyTab />}
|
||||
{tab === "terms" && <TermsConditionTab />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,34 +2,36 @@ import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import RecomendedSliders from "./RecomendedSliders";
|
||||
|
||||
export default function CommonHead({ className,commonHeadData }) {
|
||||
return (
|
||||
<div
|
||||
className={`create-nft w-full lg:h-[140px] shadow lg:flex rounded-lg justify-between items-center md:p-2 p-2 bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] -2 border-pink mb-10 ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
{commonHeadData?.length > 0 && <RecomendedSliders bannerData={commonHeadData} /> }
|
||||
{/*<div className="lg:w-8/12 w-full mb-8 lg:mb-0">*/}
|
||||
{/* /!*<h1 className="text-2xl text-dark-gray dark:text-white font-bold mb-2">*!/*/}
|
||||
{/* /!* This is common head which will appear as needed , will take many shape*!/*/}
|
||||
{/* /!*</h1>*!/*/}
|
||||
{/* /!*<p className="text-base text-thin-light-gray tracking-wide">*!/*/}
|
||||
{/* /!* some space for extra texts here*!/*/}
|
||||
{/* /!*</p>*!/*/}
|
||||
{/* */}
|
||||
{/*</div>*/}
|
||||
{/*<div className="flex-1 flex lg:justify-end">*/}
|
||||
{/* <div className="flex items-center space-x-5">*/}
|
||||
{/* <Link*/}
|
||||
{/* to="/mytask"*/}
|
||||
{/* className="w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"*/}
|
||||
{/* >*/}
|
||||
{/* View Task*/}
|
||||
{/* </Link>*/}
|
||||
export default function CommonHead({ className, commonHeadData }) {
|
||||
return (
|
||||
<div
|
||||
className={`create-nft w-full lg:h-[140px] shadow lg:flex rounded-lg justify-between items-center md:p-2 p-2 bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] -2 border-pink mb-10 ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
{commonHeadData?.length > 0 && (
|
||||
<RecomendedSliders bannerData={commonHeadData} />
|
||||
)}
|
||||
{/*<div className="lg:w-8/12 w-full mb-8 lg:mb-0">*/}
|
||||
{/* /!*<h1 className="text-2xl text-dark-gray dark:text-white font-bold mb-2">*!/*/}
|
||||
{/* /!* This is common head which will appear as needed , will take many shape*!/*/}
|
||||
{/* /!*</h1>*!/*/}
|
||||
{/* /!*<p className="text-base text-thin-light-gray tracking-wide">*!/*/}
|
||||
{/* /!* some space for extra texts here*!/*/}
|
||||
{/* /!*</p>*!/*/}
|
||||
{/* */}
|
||||
{/*</div>*/}
|
||||
{/*<div className="flex-1 flex lg:justify-end">*/}
|
||||
{/* <div className="flex items-center space-x-5">*/}
|
||||
{/* <Link*/}
|
||||
{/* to="/mytask"*/}
|
||||
{/* className="w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"*/}
|
||||
{/* >*/}
|
||||
{/* View Task*/}
|
||||
{/* </Link>*/}
|
||||
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
);
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,126 +7,128 @@ import Icons from "../Helpers/Icons";
|
||||
import SliderCom from "../Helpers/SliderCom";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export default function RecomendedSliders({ className,bannerData }) {
|
||||
const settings = {
|
||||
arrows: false,
|
||||
dots: false,
|
||||
infinite: bannerData.length > 4 ? true : false,
|
||||
autoplay: true,
|
||||
slidesToShow: bannerData.length > 4 ? 4 : bannerData.length,
|
||||
slidesToScroll: 1,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 426,
|
||||
settings: {
|
||||
infinite: bannerData.length > 2 ? true : false,
|
||||
slidesToShow: bannerData.length > 2 ? 2 : bannerData.length,
|
||||
slidesToScroll: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const sellSlider = useRef(null);
|
||||
const buySlider = useRef(null);
|
||||
const prevHandler = (value) => {
|
||||
if (value === "sell") {
|
||||
sellSlider.current.slickPrev();
|
||||
}
|
||||
if (value === "buy") {
|
||||
buySlider.current.slickPrev();
|
||||
}
|
||||
};
|
||||
const nextHandler = (value) => {
|
||||
if (value === "sell") {
|
||||
sellSlider.current.slickNext();
|
||||
}
|
||||
if (value === "buy") {
|
||||
buySlider.current.slickNext();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{/*<div className="heading flex justify-between items-center mb-4">*/}
|
||||
{/* <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* Top Seller*/}
|
||||
{/* </h1>*/}
|
||||
{/* <div className="slider-btns flex space-x-4">*/}
|
||||
{/* <button*/}
|
||||
{/* onClick={() => nextHandler("sell")}*/}
|
||||
{/* type="button"*/}
|
||||
{/* className="transform rotate-180 text-dark-gray dark:text-white dark:opacity-25"*/}
|
||||
{/* >*/}
|
||||
{/* <Icons name="arrows" />*/}
|
||||
{/* </button>*/}
|
||||
{/* <button*/}
|
||||
{/* onClick={() => prevHandler("sell")}*/}
|
||||
{/* type="button"*/}
|
||||
{/* className="transform rotate-180"*/}
|
||||
{/* >*/}
|
||||
{/* <div className=" text-dark-gray dark:text-white">*/}
|
||||
{/* <svg*/}
|
||||
{/* width="11"*/}
|
||||
{/* height="19"*/}
|
||||
{/* viewBox="0 0 11 19"*/}
|
||||
{/* fill="none"*/}
|
||||
{/* xmlns="http://www.w3.org/2000/svg"*/}
|
||||
{/* >*/}
|
||||
{/* <path*/}
|
||||
{/* d="M9.09766 1.1499L1.13307 9.11449L9.09766 17.0791"*/}
|
||||
{/* stroke="url(#paint0_linear_220_23410)"*/}
|
||||
{/* strokeWidth="2"*/}
|
||||
{/* strokeLinecap="round"*/}
|
||||
{/* strokeLinejoin="round"*/}
|
||||
{/* />*/}
|
||||
{/* <defs>*/}
|
||||
{/* <linearGradient*/}
|
||||
{/* id="paint0_linear_220_23410"*/}
|
||||
{/* x1="9.09766"*/}
|
||||
{/* y1="1.1499"*/}
|
||||
{/* x2="-4.2474"*/}
|
||||
{/* y2="7.96749"*/}
|
||||
{/* gradientUnits="userSpaceOnUse"*/}
|
||||
{/* >*/}
|
||||
{/* <stop stopColor="#F539F8" />*/}
|
||||
{/* <stop offset="0.416763" stopColor="#C342F9" />*/}
|
||||
{/* <stop offset="1" stopColor="#5356FB" />*/}
|
||||
{/* </linearGradient>*/}
|
||||
{/* </defs>*/}
|
||||
{/* </svg>*/}
|
||||
{/* </div>*/}
|
||||
{/* </button>*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
<div className="slider-content">
|
||||
<SliderCom settings={settings} selector={sellSlider}>
|
||||
{bannerData.map((item, index) => (
|
||||
<Link key={index} to={`/${item.link_path}`}>
|
||||
<div className="item">
|
||||
<div className={`commonHeaderSliderItem flex flex-col justify-between items-center ${item.short_style}`}>
|
||||
{/* title */}
|
||||
<div className="flex justify-center">
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white">
|
||||
{item.short_title}
|
||||
</p>
|
||||
</div>
|
||||
{/* username */}
|
||||
<div className="flex justify-center mb-1">
|
||||
<p className="text-xs text-thin-light-gray">
|
||||
{item.short_description}
|
||||
</p>
|
||||
</div>
|
||||
{/* items */}
|
||||
<div className="flex justify-center">
|
||||
<div className="flex space-x-1 items-center text-purple text-xs">
|
||||
<span>{item.short_button_text}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</SliderCom>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
export default function RecomendedSliders({ className, bannerData }) {
|
||||
const settings = {
|
||||
arrows: false,
|
||||
dots: false,
|
||||
infinite: bannerData.length > 4 ? true : false,
|
||||
autoplay: true,
|
||||
slidesToShow: bannerData.length > 4 ? 4 : bannerData.length,
|
||||
slidesToScroll: 1,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 426,
|
||||
settings: {
|
||||
infinite: bannerData.length > 2 ? true : false,
|
||||
slidesToShow: bannerData.length > 2 ? 2 : bannerData.length,
|
||||
slidesToScroll: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const sellSlider = useRef(null);
|
||||
const buySlider = useRef(null);
|
||||
const prevHandler = (value) => {
|
||||
if (value === "sell") {
|
||||
sellSlider.current.slickPrev();
|
||||
}
|
||||
if (value === "buy") {
|
||||
buySlider.current.slickPrev();
|
||||
}
|
||||
};
|
||||
const nextHandler = (value) => {
|
||||
if (value === "sell") {
|
||||
sellSlider.current.slickNext();
|
||||
}
|
||||
if (value === "buy") {
|
||||
buySlider.current.slickNext();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{/*<div className="heading flex justify-between items-center mb-4">*/}
|
||||
{/* <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* Top Seller*/}
|
||||
{/* </h1>*/}
|
||||
{/* <div className="slider-btns flex space-x-4">*/}
|
||||
{/* <button*/}
|
||||
{/* onClick={() => nextHandler("sell")}*/}
|
||||
{/* type="button"*/}
|
||||
{/* className="transform rotate-180 text-dark-gray dark:text-white dark:opacity-25"*/}
|
||||
{/* >*/}
|
||||
{/* <Icons name="arrows" />*/}
|
||||
{/* </button>*/}
|
||||
{/* <button*/}
|
||||
{/* onClick={() => prevHandler("sell")}*/}
|
||||
{/* type="button"*/}
|
||||
{/* className="transform rotate-180"*/}
|
||||
{/* >*/}
|
||||
{/* <div className=" text-dark-gray dark:text-white">*/}
|
||||
{/* <svg*/}
|
||||
{/* width="11"*/}
|
||||
{/* height="19"*/}
|
||||
{/* viewBox="0 0 11 19"*/}
|
||||
{/* fill="none"*/}
|
||||
{/* xmlns="http://www.w3.org/2000/svg"*/}
|
||||
{/* >*/}
|
||||
{/* <path*/}
|
||||
{/* d="M9.09766 1.1499L1.13307 9.11449L9.09766 17.0791"*/}
|
||||
{/* stroke="url(#paint0_linear_220_23410)"*/}
|
||||
{/* strokeWidth="2"*/}
|
||||
{/* strokeLinecap="round"*/}
|
||||
{/* strokeLinejoin="round"*/}
|
||||
{/* />*/}
|
||||
{/* <defs>*/}
|
||||
{/* <linearGradient*/}
|
||||
{/* id="paint0_linear_220_23410"*/}
|
||||
{/* x1="9.09766"*/}
|
||||
{/* y1="1.1499"*/}
|
||||
{/* x2="-4.2474"*/}
|
||||
{/* y2="7.96749"*/}
|
||||
{/* gradientUnits="userSpaceOnUse"*/}
|
||||
{/* >*/}
|
||||
{/* <stop stopColor="#F539F8" />*/}
|
||||
{/* <stop offset="0.416763" stopColor="#C342F9" />*/}
|
||||
{/* <stop offset="1" stopColor="#5356FB" />*/}
|
||||
{/* </linearGradient>*/}
|
||||
{/* </defs>*/}
|
||||
{/* </svg>*/}
|
||||
{/* </div>*/}
|
||||
{/* </button>*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
<div className="slider-content">
|
||||
<SliderCom settings={settings} selector={sellSlider}>
|
||||
{bannerData.map((item, index) => (
|
||||
<Link key={index} to={`/${item.link_path}`}>
|
||||
<div className="item">
|
||||
<div
|
||||
className={`commonHeaderSliderItem flex gap-1 flex-col justify-between items-center ${item.short_style}`}
|
||||
>
|
||||
{/* title */}
|
||||
<div className="flex justify-center items-center text-center">
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white">
|
||||
{item.short_title}
|
||||
</p>
|
||||
</div>
|
||||
{/* username */}
|
||||
<div className="flex justify-center mb-1">
|
||||
<p className="text-xs text-thin-light-gray text-justify">
|
||||
{item.short_description}
|
||||
</p>
|
||||
</div>
|
||||
{/* items */}
|
||||
<div className="flex justify-center">
|
||||
<div className="flex space-x-1 items-center text-purple text-xs">
|
||||
<span>{item.short_button_text}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</SliderCom>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ function DeleteJobPopout({ details, onClose, situation }) {
|
||||
<p className="text-xl tracking-wide text-dark-gray dark:text-white">
|
||||
{details.title}
|
||||
</p>
|
||||
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
|
||||
<p className="text-lg tracking-wide text-dark-gray dark:text-white flex items-start gap-1">
|
||||
Price: {details.thePrice}
|
||||
</p>
|
||||
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
|
||||
|
||||
@@ -1,13 +1,47 @@
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import { Field, Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import usersService from "../../services/UsersService";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import * as Yup from "yup";
|
||||
import usersService from "../../services/UsersService";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
country: Yup.string()
|
||||
.min(1, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Country is required"),
|
||||
price: Yup.string()
|
||||
.typeError("Invalid number")
|
||||
.min(1, "Price must be greater than 0")
|
||||
.test("no-e", "Invalid number", (value) => {
|
||||
if (value && /\d+e/.test(value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.required("Price is required"),
|
||||
title: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(100, "Maximum 25 characters")
|
||||
.required("Title is required"),
|
||||
description: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Description is required"),
|
||||
job_detail: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Details is required"),
|
||||
timeline_days: Yup.number()
|
||||
.typeError("you must specify a number")
|
||||
.min(1, "Price must be greater than 0")
|
||||
.required("Timeline is required"),
|
||||
category: Yup.array().min(1, "Select at least one checkbox"),
|
||||
});
|
||||
|
||||
const EditJobPopOut = ({
|
||||
details,
|
||||
@@ -24,59 +58,35 @@ const EditJobPopOut = ({
|
||||
message: "",
|
||||
}); // Holds state when submit button is pressed
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
country: Yup.string()
|
||||
.min(1, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Country is required"),
|
||||
price: Yup.number()
|
||||
.typeError("you must specify a number")
|
||||
.min(1, "Price must be greater than 0")
|
||||
.required("Price is required"),
|
||||
title: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(100, "Maximum 25 characters")
|
||||
.required("Title is required"),
|
||||
description: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Description is required"),
|
||||
job_detail: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Details is required"),
|
||||
timeline_days: Yup.number()
|
||||
.typeError("you must specify a number")
|
||||
.min(1, "Price must be greater than 0")
|
||||
.required("Price is required"),
|
||||
});
|
||||
|
||||
let initialValues = {
|
||||
// initial values for formik
|
||||
country: country,
|
||||
price: details?.price,
|
||||
country: details.currency,
|
||||
price: details?.price * 0.01,
|
||||
title: details?.title,
|
||||
description: details?.description,
|
||||
job_detail: details?.job_detail,
|
||||
timeline_days: details?.timeline_days,
|
||||
category: details?.category
|
||||
category: details?.category,
|
||||
};
|
||||
|
||||
console.log("This is the init values for edit job",initialValues)
|
||||
|
||||
const jobApi = useMemo(() => new usersService(), []);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleEditJob = useCallback(
|
||||
async (values) => {
|
||||
values.category = values.category?.join("@");
|
||||
setRequestStatus({ loading: true, message: "" });
|
||||
let reqData = {
|
||||
country: values?.country,
|
||||
price: Number(values.price) * 100,
|
||||
title: values?.title,
|
||||
description: values?.description,
|
||||
job_detail: values?.job_detail,
|
||||
timeline_days: values?.timeline_days,
|
||||
category: values.category?.join("@"),
|
||||
job_id: details.job_id,
|
||||
job_uid: details.job_uid,
|
||||
...values,
|
||||
};
|
||||
delete reqData?.country;
|
||||
setRequestStatus({ loading: true, message: "" });
|
||||
|
||||
try {
|
||||
let res = await jobApi.jobManagerUpdateJob(reqData);
|
||||
let { data } = await res;
|
||||
@@ -142,7 +152,7 @@ const EditJobPopOut = ({
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<InputCom
|
||||
fieldClass="px-6 cursor-default"
|
||||
label="Country"
|
||||
label="Currency"
|
||||
labelClass="tracking-wide"
|
||||
inputBg="bg-slate-100"
|
||||
inputClass="input-curve lg border border-light-purple"
|
||||
@@ -165,7 +175,7 @@ const EditJobPopOut = ({
|
||||
inputClass="input-curve lg border border-light-purple"
|
||||
type="number"
|
||||
name="price"
|
||||
value={props.values.price * 0.01}
|
||||
value={props.values.price}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
errorBorder={
|
||||
@@ -222,7 +232,11 @@ const EditJobPopOut = ({
|
||||
<textarea
|
||||
id="Job Delivery Details"
|
||||
rows="5"
|
||||
className={`input-field px-6 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] border border-[#dce4e9] rounded-[10px]`}
|
||||
className={`input-field px-6 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] ${
|
||||
props.errors.job_detail && props.touched.job_detail
|
||||
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
|
||||
: "border border-[#f5f8fa] dark:border-[#5e6278]"
|
||||
} rounded-[10px]`}
|
||||
style={{ resize: "none" }}
|
||||
name="job_detail"
|
||||
value={props.values.job_detail}
|
||||
@@ -257,16 +271,13 @@ const EditJobPopOut = ({
|
||||
<span className="text-[13.975px]">{value}</span>
|
||||
</label>
|
||||
))}
|
||||
<span className="h-5 text-sm italic text-[#cf3917]">
|
||||
{props.errors.category &&
|
||||
props.touched.category &&
|
||||
"please select a category"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className={`${!props.errors && "invisible"} h-5`}>
|
||||
{props.errors.job_detail && props.touched.job_detail && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.job_detail}
|
||||
</p>
|
||||
)}
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<div className="field w-full mb-6">
|
||||
@@ -287,7 +298,12 @@ const EditJobPopOut = ({
|
||||
<Field
|
||||
component="select"
|
||||
name="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 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 ${
|
||||
props.errors.timeline_days &&
|
||||
props.touched.timeline_days
|
||||
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
|
||||
: "border border-[#f5f8fa] dark:border-[#5e6278]"
|
||||
}`}
|
||||
value={props.values.timeline_days}
|
||||
>
|
||||
<option value="">Select Duration</option>
|
||||
|
||||
@@ -167,6 +167,8 @@ function JobListPopout({ details, onClose, situation }) {
|
||||
}
|
||||
};
|
||||
|
||||
// console.log("Job List P >> ", details)
|
||||
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation} className="job-popup">
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
|
||||
@@ -1,64 +1,108 @@
|
||||
import React, {useState} from 'react'
|
||||
import Detail from './popoutcomponent/Detail'
|
||||
import ModalCom from '../Helpers/ModalCom'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import React, { useState } from "react";
|
||||
import Detail from "./popoutcomponent/Detail";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import usersService from '../../services/UsersService'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
||||
import usersService from "../../services/UsersService";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
|
||||
import { tableReload } from '../../store/TableReloads'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
function OfferJobPopout({details, onClose, situation}) {
|
||||
const apiUrl = new usersService()
|
||||
const navigate = useNavigate()
|
||||
const dispatch = useDispatch()
|
||||
function OfferJobPopout({ details, onClose, situation }) {
|
||||
const apiUrl = new usersService();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: '', trigger: ''})
|
||||
const [requestStatus, setRequestStatus] = useState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
trigger: "",
|
||||
});
|
||||
|
||||
//FUNCTION TO HANDLE AN OFFER
|
||||
const handleOffer = ({target:{name}}) => {
|
||||
const handleOffer = ({ target: { name } }) => {
|
||||
const reqData = {
|
||||
// offer_result: 100,
|
||||
offer_code: details.contract,
|
||||
contract: details.contract
|
||||
}
|
||||
contract: details.contract,
|
||||
};
|
||||
|
||||
//logic to determine the button pressed and set reqDate accordingly
|
||||
if(name == 'accept'){
|
||||
setRequestStatus({loading: true, status: false, message: '', trigger: 'offer'})
|
||||
reqData.offer_result = 100
|
||||
if (name == "accept") {
|
||||
setRequestStatus({
|
||||
loading: true,
|
||||
status: false,
|
||||
message: "",
|
||||
trigger: "offer",
|
||||
});
|
||||
reqData.offer_result = 100;
|
||||
}
|
||||
if(name == 'reject'){
|
||||
setRequestStatus({loading: true, status: false, message: '', trigger: 'reject'})
|
||||
reqData.offer_result = 333
|
||||
if (name == "reject") {
|
||||
setRequestStatus({
|
||||
loading: true,
|
||||
status: false,
|
||||
message: "",
|
||||
trigger: "reject",
|
||||
});
|
||||
reqData.offer_result = 333;
|
||||
}
|
||||
|
||||
// API CALL
|
||||
apiUrl.offersResponse(reqData).then(response => {
|
||||
if(response.status != 200 || response.data.internal_return < 0){
|
||||
setRequestStatus({loading: false, status: false, message: `Unable to ${name} Offer, try again later`, trigger: ''})
|
||||
return
|
||||
}
|
||||
setRequestStatus({loading: false, status: true, message: `Offer ${name}ed Successfully`, trigger: ''})
|
||||
setTimeout(()=>{
|
||||
onClose()
|
||||
dispatch(tableReload({type:'MYTASKTABLE'}))
|
||||
navigate('/mytask', {replace:true})
|
||||
setRequestStatus({loading: false, status: false, message: '', trigger: ''})
|
||||
},2000)
|
||||
}).catch(error => {
|
||||
setRequestStatus({loading: false, status: false, message: `Opps! An Error Occurred`, trigger: ''})
|
||||
}).finally(()=>{
|
||||
setTimeout(()=>{
|
||||
setRequestStatus({loading: false, status: false, message: '', trigger: ''})
|
||||
},5000)
|
||||
})
|
||||
}
|
||||
apiUrl
|
||||
.offersResponse(reqData)
|
||||
.then((response) => {
|
||||
if (response.status != 200 || response.data.internal_return < 0) {
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: `Unable to ${name} Offer, try again later`,
|
||||
trigger: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: true,
|
||||
message: `Offer ${name}ed Successfully`,
|
||||
trigger: "",
|
||||
});
|
||||
setTimeout(() => {
|
||||
onClose();
|
||||
dispatch(tableReload({ type: "MYTASKTABLE" }));
|
||||
navigate("/mytask", { replace: true });
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
trigger: "",
|
||||
});
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: `Opps! An Error Occurred`,
|
||||
trigger: "",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
trigger: "",
|
||||
});
|
||||
}, 5000);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation}>
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto 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">
|
||||
Start Task
|
||||
@@ -89,117 +133,121 @@ function OfferJobPopout({details, onClose, situation}) {
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className='md:flex bg-white rounded-lg shadow-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 tracking-wide'>{details.title}</p>
|
||||
|
||||
<div className="md:flex bg-white rounded-lg shadow-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 tracking-wide">
|
||||
{details.title}
|
||||
</p>
|
||||
|
||||
{/* INPUT SECTION */}
|
||||
<div className='my-2 md:flex'>
|
||||
<Detail
|
||||
label='Date'
|
||||
value={details.offer_added || 'default'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='my-2 md:flex'>
|
||||
<Detail
|
||||
label='Description'
|
||||
value={details.description}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='my-2 md:flex'>
|
||||
<Detail
|
||||
label='Offer Expire'
|
||||
value={details.expire && `${details.expire.split(' ')[0]} ${details.expire.split(' ')[1].split('.')[0]}`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='my-2 md:flex'>
|
||||
<Detail
|
||||
label='Price'
|
||||
value={`${details.price*0.01} ${details.currency}`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='my-2 md:flex'>
|
||||
<Detail
|
||||
label='Duration'
|
||||
value={`${details.timeline_days} day(s)`}
|
||||
<div className="my-2 md:flex">
|
||||
<Detail
|
||||
label="Date"
|
||||
value={
|
||||
(details.offer_added && details.offer_added?.split(" ")[0]) ||
|
||||
"default"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='my-2 md:flex'>
|
||||
<Detail
|
||||
label='Detail'
|
||||
value={details.job_description || details.description}
|
||||
<div className="my-2 md:flex">
|
||||
<Detail label="Description" value={details.description} />
|
||||
</div>
|
||||
|
||||
<div className="my-2 md:flex">
|
||||
<Detail
|
||||
label="Offer Expire"
|
||||
value={details.expire && details.expire.split(" ")[0]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* ACTION SECTION */}
|
||||
<div className='p-4 w-full md:w-1/4 h-full'>
|
||||
<div className='my-3 md:flex md:justify-center'>
|
||||
{requestStatus.loading && requestStatus.trigger == 'offer' ?
|
||||
<LoadingSpinner size={8} color='sky-blue' />
|
||||
:
|
||||
<button
|
||||
name='accept'
|
||||
onClick={handleOffer}
|
||||
disabled={requestStatus.loading}
|
||||
className='px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'>
|
||||
Accept Offer
|
||||
</button>
|
||||
}
|
||||
|
||||
<div className="my-2 md:flex">
|
||||
<Detail label="Price" value={details.thePrice} />
|
||||
</div>
|
||||
|
||||
<div className='mt-10 md:mt-20 md:flex md:justify-center'>
|
||||
{requestStatus.loading && requestStatus.trigger == 'reject' ?
|
||||
<LoadingSpinner size={8} color='sky-blue' />
|
||||
:
|
||||
<button
|
||||
name='reject'
|
||||
|
||||
<div className="my-2 md:flex">
|
||||
<Detail
|
||||
label="Duration"
|
||||
value={`${details.timeline_days} day(s)`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="my-2 md:flex">
|
||||
<Detail
|
||||
label="Detail"
|
||||
value={details.job_description || details.description}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ACTION SECTION */}
|
||||
<div className="p-4 w-full md:w-1/4 h-full">
|
||||
<div className="my-3 md:flex md:justify-center">
|
||||
{requestStatus.loading && requestStatus.trigger == "offer" ? (
|
||||
<LoadingSpinner size={8} color="sky-blue" />
|
||||
) : (
|
||||
<button
|
||||
name="accept"
|
||||
onClick={handleOffer}
|
||||
disabled={requestStatus.loading}
|
||||
className='px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'>
|
||||
Reject Offer
|
||||
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Accept Offer
|
||||
</button>
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-10 md:mt-20 md:flex md:justify-center">
|
||||
{requestStatus.loading && requestStatus.trigger == "reject" ? (
|
||||
<LoadingSpinner size={8} color="sky-blue" />
|
||||
) : (
|
||||
<button
|
||||
name="reject"
|
||||
onClick={handleOffer}
|
||||
disabled={requestStatus.loading}
|
||||
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Reject Offer
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
|
||||
{requestStatus.message != "" && (
|
||||
!requestStatus.status ?
|
||||
(<div className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
|
||||
{requestStatus.message}
|
||||
</div>)
|
||||
:
|
||||
requestStatus.status &&
|
||||
(<div className={`relative p-4 my-4 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>
|
||||
)
|
||||
)}
|
||||
{requestStatus.message != "" &&
|
||||
(!requestStatus.status ? (
|
||||
<div
|
||||
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
|
||||
>
|
||||
{requestStatus.message}
|
||||
</div>
|
||||
) : (
|
||||
requestStatus.status && (
|
||||
<div
|
||||
className={`relative p-4 my-4 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>
|
||||
)
|
||||
))}
|
||||
{/* End of error or success display */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* close button */}
|
||||
{/* close button */}
|
||||
<div className="p-6 flex justify-end">
|
||||
<button
|
||||
onClick={onClose}
|
||||
disabled={requestStatus.loading}
|
||||
type="button"
|
||||
className="border-gradient text-18 tracking-wide px-2 py-2 rounded-full"
|
||||
>
|
||||
<span className="text-gradient">Cancel</span>
|
||||
</button>
|
||||
onClick={onClose}
|
||||
disabled={requestStatus.loading}
|
||||
type="button"
|
||||
className="border-gradient text-18 tracking-wide px-2 py-2 rounded-full"
|
||||
>
|
||||
<span className="text-gradient">Cancel</span>
|
||||
</button>
|
||||
</div>
|
||||
{/* end of close button */}
|
||||
</div>
|
||||
</ModalCom>
|
||||
)
|
||||
</div>
|
||||
</ModalCom>
|
||||
);
|
||||
}
|
||||
|
||||
export default OfferJobPopout
|
||||
export default OfferJobPopout;
|
||||
|
||||
@@ -4,6 +4,7 @@ import ModalCom from "../Helpers/ModalCom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import { toast } from "react-toastify";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
|
||||
const showSuccessToast = (message) => {
|
||||
toast.success(message, {
|
||||
@@ -133,7 +134,8 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
||||
<div className="my-2 md:flex">
|
||||
<Detail
|
||||
label="Price"
|
||||
value={`${details.price * 0.01} ${details.currency}`}
|
||||
// value={`${details.price * 0.01} ${details.currency}`}
|
||||
value={PriceFormatter(details.price * 0.01, details?.currency_code, details.currency)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||