Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53db8df5c7 | |||
| dd3f9d99f3 | |||
| 8807b671ad | |||
| d66093a2ad | |||
| b79eb6b158 | |||
| a759daaf90 | |||
| 600aec62cf | |||
| 1612bf11ce | |||
| f4e261eb6c | |||
| b622398b6a | |||
| e60957e6be | |||
| 6a2082d732 | |||
| 452c6bf8a1 | |||
| 9f89376aa9 | |||
| 4e91e47978 | |||
| fcaa485b17 | |||
| 64056bb2a4 | |||
| e49c4d66f8 | |||
| 8fdb939b72 | |||
| 7849a027b4 |
@@ -49,6 +49,7 @@ import MyWaitingJobsPage from "./views/MyWaitingJobsPage";
|
||||
import FamilyMarketPage from "./views/FamilyMarketPage";
|
||||
import FacebookRedirect from "./views/FacebookRedirect";
|
||||
import AppleRedirectPage from "./views/AppleRedirectPage";
|
||||
import LndPage from "./views/LndPage";
|
||||
|
||||
export default function Routers() {
|
||||
return (
|
||||
@@ -76,6 +77,7 @@ export default function Routers() {
|
||||
<Route path="/vemail" element={<VerifyLinkPages />} />
|
||||
<Route path="/complereset" element={<VerifyPasswordPages />} />
|
||||
<Route exact path="/outmessage" element={<VerifyYouPages />} />
|
||||
<Route exact path="/lnd/*" element={<LndPage />} />
|
||||
|
||||
{/* private route */}
|
||||
<Route element={<AuthRoute />}>
|
||||
|
||||
@@ -245,6 +245,9 @@ export default function Login() {
|
||||
</div>
|
||||
<div className="content-wrapper login shadow-md w-full lg:max-w-[530px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
|
||||
<div className="w-full">
|
||||
|
||||
{/* HIDES THIS IF USER SESSION HAS EXPIRED */}
|
||||
{sessionExpired != 'true' &&
|
||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||
{/* <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||
Sign In to WrenchBoard
|
||||
@@ -259,11 +262,12 @@ export default function Login() {
|
||||
</Link>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* SHOWS THIS IF USER SESSION HAS EXPIRED */}
|
||||
{sessionExpired == 'true' &&
|
||||
<div className="w-full p-1">
|
||||
<p className="text-red-500 text-sm text-center">Your session expired and will need to login again</p>
|
||||
<div className="w-full p-1 mb-7">
|
||||
<p className="text-red-500 text-base text-center">Your session expired and will need to login again</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function FamilyManageTabs({
|
||||
loading: false,
|
||||
data: null,
|
||||
};
|
||||
|
||||
console.log('accountDetails',accountDetails)
|
||||
// State for family details, tasks, waitlist, and pending
|
||||
const [details, setDetails] = useState({
|
||||
familyDetails: { ...initialDetailState },
|
||||
@@ -66,8 +66,10 @@ export default function FamilyManageTabs({
|
||||
// State for family task popout
|
||||
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
|
||||
|
||||
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
|
||||
|
||||
// State for profile image
|
||||
const [profileImg, setProfileImg] = useState(profile);
|
||||
const [profileImg, setProfileImg] = useState(accountDetails.image ? accountDetails.image : profile);
|
||||
|
||||
// Ref for profile image input
|
||||
const profileImgInput = useRef(null);
|
||||
@@ -90,24 +92,78 @@ export default function FamilyManageTabs({
|
||||
* Checks if the selected file exceeds the maximum file size limit and displays an alert if it does.
|
||||
* If the file is within the size limit, it reads the file using the FileReader API and sets the profile image state with the result.
|
||||
*/
|
||||
const profileImgChangeHandler = (e) => {
|
||||
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
|
||||
// const profileImgChangeHandler = (e) => {
|
||||
// const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
|
||||
|
||||
const file = e.target.files[0];
|
||||
if (file && file.size > MAX_FILE_SIZE) {
|
||||
alert("File size exceeds the limit.");
|
||||
return;
|
||||
// const file = e.target.files[0];
|
||||
// if (file && file.size > MAX_FILE_SIZE) {
|
||||
// alert("File size exceeds the limit.");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (file) {
|
||||
// const imgReader = new FileReader();
|
||||
// imgReader.onload = () => {
|
||||
// const imageDataUrl = imgReader.result;
|
||||
|
||||
// // Set the profile image
|
||||
// setProfileImg(imageDataUrl);
|
||||
// };
|
||||
// imgReader.readAsDataURL(file);
|
||||
// }
|
||||
// };
|
||||
|
||||
const profileImgChangeHandler = (e) => {
|
||||
setUploadStatus({loading: false, status: false, message:''})
|
||||
let acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"] // ARRAY OF SUPPORTED FORMATS
|
||||
let uploadedFile = e.target.files[0] //UPLOADED FILE
|
||||
|
||||
const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase();
|
||||
if(!acceptedFormat.includes(fileFormat)){ //CHECKING FOR CORRECT UPLOAD FORMAT
|
||||
const msg = `Please select ${acceptedFormat.slice(0, -1).join(', ')} or ${acceptedFormat.slice(-1)}`;
|
||||
setUploadStatus({loading: false, status: false, message:msg})
|
||||
return setTimeout(()=>{
|
||||
profileImgInput.current.value = '' // clear the input
|
||||
setUploadStatus({loading: false, status: false, message:''})
|
||||
},5000)
|
||||
}
|
||||
|
||||
if (file) {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = () => {
|
||||
const imageDataUrl = imgReader.result;
|
||||
if(uploadedFile.size > 5*1048576){ // CHECKING FOR CORRECT FILE SIZE
|
||||
setUploadStatus({loading: false, status: false, message:'File must not exceed 5MB'})
|
||||
return setTimeout(()=>{
|
||||
profileImgInput.current.value = '' // clear the input
|
||||
setUploadStatus({loading: false, status: false, message:''})
|
||||
},5000)
|
||||
}
|
||||
|
||||
// Set the profile image
|
||||
setProfileImg(imageDataUrl);
|
||||
if (e.target.value !== "") {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = (event) => {
|
||||
let reqData = { // PAYLOAD FOR API CALL
|
||||
family_uid: accountDetails?.family_uid,
|
||||
file_name: uploadedFile?.name,
|
||||
file_size: uploadedFile?.size,
|
||||
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
|
||||
file_data: event?.target?.result,
|
||||
msg_type: 'FILE',
|
||||
action: 111305
|
||||
}
|
||||
setUploadStatus({loading: true, status: false, message:'Loading...'})
|
||||
apiCall.sendFiles(reqData).then(res=>{
|
||||
if(res.status != 200 || res.data.internal_return < 0){
|
||||
return setUploadStatus({loading: false, status: false, message: 'Something went wrong, try again'})
|
||||
}
|
||||
setUploadStatus({loading: false, status: true, message: 'Uploaded successfully'})
|
||||
setProfileImg(event.target.result);
|
||||
}).catch(error=>{
|
||||
setUploadStatus({loading: false, status: false, message: 'Network error, try again'})
|
||||
}).finally(()=>{
|
||||
setTimeout(()=>{
|
||||
setUploadStatus({loading: false, status: false, message: ''})
|
||||
},5000)
|
||||
})
|
||||
};
|
||||
imgReader.readAsDataURL(file);
|
||||
imgReader.readAsDataURL(e.target.files[0]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -298,6 +354,7 @@ export default function FamilyManageTabs({
|
||||
profileImgChangeHandler={profileImgChangeHandler}
|
||||
browseProfileImg={browseProfileImg}
|
||||
accountDetails={accountDetails}
|
||||
uploadStatus={uploadStatus}
|
||||
/>
|
||||
<div className="mt-4 flex flex-col justify-center items-center gap-2 lg:flex-row lg:justify-center lg:items-center xl:flex-col xl:justify-center xl:items-center 2xl:flex-row 2xl:justify-center 2xl:items-center 2xl:gap-[2px]">
|
||||
<button
|
||||
|
||||
@@ -19,6 +19,7 @@ export default function FamilyTable({
|
||||
familyList,
|
||||
loader,
|
||||
popUpHandler,
|
||||
imageServer
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
@@ -54,12 +55,14 @@ export default function FamilyTable({
|
||||
banner,
|
||||
enable_traking,
|
||||
profile_picture,
|
||||
imageServer
|
||||
}) => {
|
||||
// Check for valid dates
|
||||
const addedDate = added ? added.split(" ")[0] : "N/A";
|
||||
const loginDate = last_login ? formatDateString(last_login) : "N/A";
|
||||
const key = `family-${family_uid}`; // Assign a unique key
|
||||
|
||||
const image = localStorage.getItem('session_token') ? `${imageServer}${localStorage.getItem('session_token')}/family/${family_uid}` : ''
|
||||
|
||||
const trackingStatus =
|
||||
enable_traking === "0"
|
||||
? "Stopped"
|
||||
@@ -76,8 +79,8 @@ export default function FamilyTable({
|
||||
<div className="flex space-x-2 items-center w-full">
|
||||
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1]">
|
||||
<img
|
||||
src={profile_picture}
|
||||
// src={profile_picture || localImgLoad(`images/icons/${banner}`)}
|
||||
// src={profile_picture}
|
||||
src={image || profile_picture || localImgLoad(`images/icons/${banner}`)}
|
||||
alt={`Avatar of ${firstname} ${lastname}`}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
@@ -133,6 +136,7 @@ export default function FamilyTable({
|
||||
task_count,
|
||||
family_uid,
|
||||
banner,
|
||||
image
|
||||
})
|
||||
}
|
||||
type="button"
|
||||
@@ -147,8 +151,8 @@ export default function FamilyTable({
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M.366 19.708c.405.39 1.06.39 1.464 0l8.563-8.264a1.95 1.95 0 0 0 0-2.827L1.768.292A1.063 1.063 0 0 0 .314.282a.976.976 0 0 0-.011 1.425l7.894 7.617a.975.975 0 0 1 0 1.414L.366 18.295a.974.974 0 0 0 0 1.413"
|
||||
fill="#4687ba"
|
||||
className="color000000 svgShape"
|
||||
// fill=""
|
||||
className="color000000 svgShape fill-[#fff]"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
@@ -182,7 +186,7 @@ export default function FamilyTable({
|
||||
</thead>
|
||||
<tbody className="h-full">
|
||||
{currentFamilyList?.map((familyMember, index) => {
|
||||
return <FamilyRow key={index} {...familyMember} />;
|
||||
return <FamilyRow key={index} {...familyMember} imageServer={imageServer} />;
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -213,7 +217,7 @@ export default function FamilyTable({
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0}
|
||||
next={currentPage + itemsPerPage >= familyList.length}
|
||||
next={currentPage + itemsPerPage >= familyList?.length}
|
||||
data={familyList}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
|
||||
@@ -50,7 +50,7 @@ function RewardsTable() {
|
||||
<div className='flex flex-col justify-between min-h-[500px]'>
|
||||
{familyRewardHistory.loading ?
|
||||
<LoadingSpinner size='16' color='sky-blue' height='h-[500px]' />
|
||||
:
|
||||
: familyRewardHistory.data.length ?
|
||||
<table className="wallet-activity w-full table-auto border-collapse text-left">
|
||||
<thead className='border-b-2'>
|
||||
<tr className='text-slate-600'>
|
||||
@@ -60,8 +60,6 @@ function RewardsTable() {
|
||||
<th className="p-2">Confirmation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{familyRewardHistory.data.length ?
|
||||
(
|
||||
<tbody>
|
||||
{currentReward.map((item, index) => {
|
||||
let date = new Date(item.added).toLocaleDateString()
|
||||
@@ -84,24 +82,15 @@ function RewardsTable() {
|
||||
}
|
||||
)}
|
||||
</tbody>
|
||||
)
|
||||
:
|
||||
familyRewardHistory.error ?
|
||||
(
|
||||
<tbody>
|
||||
<tr className='text-slate-500'>
|
||||
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
)
|
||||
:
|
||||
<tbody>
|
||||
<tr className='text-slate-500'>
|
||||
<td className="p-2" colSpan={4}>No Rewards History Found!</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
}
|
||||
</table>
|
||||
:familyRewardHistory.error ?
|
||||
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
|
||||
<span>Opps! an error occurred. Please try again!</span>
|
||||
</div>
|
||||
:
|
||||
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
|
||||
<span>No Rewards History Found!</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* PAGINATION BUTTON */}
|
||||
|
||||
@@ -255,9 +255,9 @@ export default function History() {
|
||||
{/* PURCHASE SECTION */}
|
||||
{tab == 'purchases' &&
|
||||
<div className="wallet w-full border-t">
|
||||
<h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Purchases</h1>
|
||||
{/* <h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Purchases</h1> */}
|
||||
{purchaseHistory.loading ?
|
||||
<LoadingSpinner size='16' color='sky-blue' />
|
||||
<LoadingSpinner size='16' color='sky-blue' height='h-[500px]' />
|
||||
:
|
||||
<PurchasesTable purchase={purchaseHistory} />
|
||||
}
|
||||
@@ -268,10 +268,10 @@ export default function History() {
|
||||
{/* RECENT ACTIVITY SECTION */}
|
||||
{tab == 'recent' &&
|
||||
<div className="wallet w-full border-t">
|
||||
<h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Recent Activity</h1>
|
||||
{/* <h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Recent Activity</h1> */}
|
||||
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
|
||||
{paymentHistory.loading ?
|
||||
<LoadingSpinner size='16' color='sky-blue' />
|
||||
<LoadingSpinner size='16' color='sky-blue' height='h-[500px]' />
|
||||
:
|
||||
<RecentActivityTable payment={paymentHistory} />
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Layout from '../Partials/Layout'
|
||||
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
||||
|
||||
function Lnd() {
|
||||
|
||||
const [reqStatus, setReqStatus] = useState({loading:true, data: []})
|
||||
|
||||
useEffect(()=>{
|
||||
const timer = setTimeout(()=>{
|
||||
setReqStatus({loading:false, data: []})
|
||||
},2000)
|
||||
return () => clearTimeout(timer)
|
||||
}, [])
|
||||
return (
|
||||
<>
|
||||
{reqStatus.loading ?
|
||||
<LoadingSpinner color='sky-blue' size='32' height='min-h-screen' />
|
||||
:
|
||||
<div className='min-h-screen flex flex-col justify-center items-center'>Empty Dummy Page</div>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Lnd
|
||||
@@ -16,45 +16,36 @@ function PurchasesTable({purchase}) {
|
||||
|
||||
return (
|
||||
<div className='flex flex-col justify-between min-h-[500px]'>
|
||||
<table className="wallet-activity w-full table-auto border-collapse text-left">
|
||||
<thead className='border-b-2'>
|
||||
<tr className='text-slate-600'>
|
||||
<th className="p-2">Trx.</th>
|
||||
<th className="p-2">Amount</th>
|
||||
<th className="p-2">Fee</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{purchase.data.length ?
|
||||
(
|
||||
<tbody>
|
||||
{currentPurchase.map((item, index) => (
|
||||
<tr key={index} className='text-slate-500'>
|
||||
<td className="p-2">{item.added_date}<br />
|
||||
<b>{item.confirmation} </b>
|
||||
</td>
|
||||
<td className="p-2">{item.amount}</td>
|
||||
<td className="p-2">{item.fee}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
)
|
||||
<table className="wallet-activity w-full table-auto border-collapse text-left">
|
||||
<thead className='border-b-2'>
|
||||
<tr className='text-slate-600'>
|
||||
<th className="p-2">Trx.</th>
|
||||
<th className="p-2">Amount</th>
|
||||
<th className="p-2">Fee</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{currentPurchase.map((item, index) => (
|
||||
<tr key={index} className='text-slate-500'>
|
||||
<td className="p-2">{item.added_date}<br />
|
||||
<b>{item.confirmation} </b>
|
||||
</td>
|
||||
<td className="p-2">{item.amount}</td>
|
||||
<td className="p-2">{item.fee}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
:purchase.error ?
|
||||
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
|
||||
<span>Opps! an error occurred. Please try again!</span>
|
||||
</div>
|
||||
:
|
||||
purchase.error ?
|
||||
(
|
||||
<tbody>
|
||||
<tr className='text-slate-500'>
|
||||
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
)
|
||||
:
|
||||
<tbody>
|
||||
<tr className='text-slate-500'>
|
||||
<td className="p-2" colSpan={4}>No Purchase History Found!</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
|
||||
<span>No Purchase History Found!</span>
|
||||
</div>
|
||||
}
|
||||
</table>
|
||||
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= purchase?.data?.length ? true : false} data={purchase?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
|
||||
|
||||
@@ -19,16 +19,16 @@ function RecentActivityTable({ payment }) {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col justify-between min-h-[500px]">
|
||||
<table className="wallet-activity w-full table-auto border-collapse text-left">
|
||||
<thead className="border-b-2">
|
||||
<tr className="text-slate-600">
|
||||
<th className="p-2">Date</th>
|
||||
<th className="p-4">Trx.</th>
|
||||
<th className="p-2">Amnt./Fee</th>
|
||||
<th className="p-2">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{payment?.data?.length > 0 ? (
|
||||
{payment?.data?.length > 0 ?
|
||||
<table className="wallet-activity w-full table-auto border-collapse text-left">
|
||||
<thead className="border-b-2">
|
||||
<tr className="text-slate-600">
|
||||
<th className="p-2">Date</th>
|
||||
<th className="p-4">Trx.</th>
|
||||
<th className="p-2">Amnt./Fee</th>
|
||||
<th className="p-2">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{currentActivity.map((item, index) => (
|
||||
<tr key={index} className="text-slate-500">
|
||||
@@ -46,24 +46,16 @@ function RecentActivityTable({ payment }) {
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
) : payment?.error ? (
|
||||
<tbody>
|
||||
<tr className="text-slate-500">
|
||||
<td className="p-2" colSpan={4}>
|
||||
Opps! an error occurred. Please try again!
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
) : (
|
||||
<tbody>
|
||||
<tr className="text-slate-500">
|
||||
<td className="p-2" colSpan={4}>
|
||||
No Payment History Found!
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
)}
|
||||
</table>
|
||||
</table>
|
||||
:payment.error ?
|
||||
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
|
||||
<span>Opps! an error occurred. Please try again!</span>
|
||||
</div>
|
||||
:
|
||||
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
|
||||
<span>No Payment History Found!</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
|
||||
@@ -36,6 +36,10 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
|
||||
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
|
||||
|
||||
const image = `${userDetails.session_image_server}${localStorage.getItem(
|
||||
"session_token"
|
||||
)}/profile/${userDetails.uid}`;
|
||||
|
||||
const handlerBalance = () => {
|
||||
setbalanceValue.toggle();
|
||||
if (notificationDropdown) {
|
||||
@@ -91,7 +95,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
// User Profile
|
||||
let { firstname, lastname, email, profile_pic_url } = userDetails;
|
||||
let userEmail = email?.split("@")[0];
|
||||
const userProfileImage = profile_pic_url || DEFAULT_PROFILE_IMAGE;
|
||||
const userProfileImage = image || DEFAULT_PROFILE_IMAGE;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function Sidebar({
|
||||
logoutModalHandler,
|
||||
myJobList,
|
||||
}) {
|
||||
const darkMode = useContext(DarkModeContext);
|
||||
const darkMode = useContext(DarkModeContext);
|
||||
|
||||
let { userDetails } = useSelector((state) => state.userDetails);
|
||||
//const jobLists = getJobList(); // pass from upper - we need in a lot of places
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import usersService from "../../../services/UsersService";
|
||||
@@ -6,6 +6,9 @@ import Icons from "../../Helpers/Icons";
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
|
||||
import cover from "../../../assets/images/profile-info-cover.png";
|
||||
import profileImage from "../../../assets/images/profile.jpg";
|
||||
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
@@ -43,18 +46,13 @@ export default function PersonalInfoTab({
|
||||
frstNmeHndlr,
|
||||
lstNmeHndlr,
|
||||
dscrphn,
|
||||
profileImg,
|
||||
coverImg,
|
||||
profileImgInput,
|
||||
browseProfileImg,
|
||||
profileImgChangHandler,
|
||||
coverImgInput,
|
||||
browseCoverImg,
|
||||
coverImgChangHandler,
|
||||
uploadStatus
|
||||
}) {
|
||||
let { userDetails } = useSelector((state) => state.userDetails);
|
||||
|
||||
const image = `${userDetails.session_image_server}${localStorage.getItem(
|
||||
"session_token"
|
||||
)}/profile/${userDetails.uid}`;
|
||||
|
||||
const apiCall = new usersService();
|
||||
|
||||
let navigate = useNavigate();
|
||||
@@ -85,6 +83,123 @@ export default function PersonalInfoTab({
|
||||
status: false,
|
||||
});
|
||||
|
||||
const [profileImg, setProfileImg] = useState(
|
||||
userDetails?.session_image_server ? image : profileImage
|
||||
);
|
||||
|
||||
let [uploadStatus, setUploadStatus] = useState({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "",
|
||||
}); // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
|
||||
|
||||
const [coverImg, setCoverImg] = useState(cover);
|
||||
|
||||
// profile img
|
||||
const profileImgInput = useRef(null);
|
||||
const browseProfileImg = () => {
|
||||
profileImgInput.current.click();
|
||||
};
|
||||
|
||||
const profileImgChangHandler = (e) => {
|
||||
setUploadStatus({ loading: false, status: false, message: "" });
|
||||
const acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"]; // ARRAY OF SUPPORTED FORMATS
|
||||
const uploadedFile = e.target.files[0]; //UPLOADED FILE
|
||||
|
||||
const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase();
|
||||
const MAX_FILE_SIZE = 5 * 1048576; // 5MB
|
||||
|
||||
if (!acceptedFormat.includes(fileFormat)) {
|
||||
//CHECKING FOR CORRECT UPLOAD FORMAT
|
||||
const msg = `Please select ${acceptedFormat
|
||||
.slice(0, -1)
|
||||
.join(", ")} or ${acceptedFormat.slice(-1)}`;
|
||||
setUploadStatus({ loading: false, status: false, message: msg });
|
||||
return setTimeout(() => {
|
||||
profileImgInput.current.value = ""; // clear the input
|
||||
setUploadStatus({ loading: false, status: false, message: "" });
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
if (uploadedFile.size > MAX_FILE_SIZE) {
|
||||
// CHECKING FOR CORRECT FILE SIZE
|
||||
setUploadStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "File must not exceed 5MB",
|
||||
});
|
||||
return setTimeout(() => {
|
||||
profileImgInput.current.value = ""; // clear the input
|
||||
setUploadStatus({ loading: false, status: false, message: "" });
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
if (e.target.value !== "") {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = (event) => {
|
||||
let reqData = {
|
||||
// PAYLOAD FOR API CALL
|
||||
file_name: uploadedFile?.name,
|
||||
file_size: uploadedFile?.size,
|
||||
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
|
||||
file_data: event?.target?.result,
|
||||
msg_type: "FILE",
|
||||
action: 11300,
|
||||
};
|
||||
setUploadStatus({
|
||||
loading: true,
|
||||
status: false,
|
||||
message: "Loading...",
|
||||
});
|
||||
apiCall
|
||||
.sendFiles(reqData)
|
||||
.then((res) => {
|
||||
if (res.status != 200 || res.data.internal_return < 0) {
|
||||
return setUploadStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "Something went wrong, try again",
|
||||
});
|
||||
}
|
||||
setUploadStatus({
|
||||
loading: false,
|
||||
status: true,
|
||||
message: "Uploaded successfully",
|
||||
});
|
||||
setProfileImg(event.target.result);
|
||||
})
|
||||
.catch((error) => {
|
||||
setUploadStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: "Network error, try again",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
setUploadStatus({ loading: false, status: false, message: "" });
|
||||
}, 5000);
|
||||
});
|
||||
};
|
||||
imgReader.readAsDataURL(uploadedFile);
|
||||
}
|
||||
};
|
||||
|
||||
// cover img
|
||||
const coverImgInput = useRef(null);
|
||||
const browseCoverImg = () => {
|
||||
coverImgInput.current.click();
|
||||
};
|
||||
const coverImgChangHandler = (e) => {
|
||||
if (e.target.value !== "") {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = (event) => {
|
||||
setCoverImg(event.target.result);
|
||||
};
|
||||
imgReader.readAsDataURL(e.target.files[0]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdateUser = (values, helpers) => {
|
||||
setRequestState({ message: "", loading: true, status: false });
|
||||
|
||||
@@ -363,65 +478,77 @@ export default function PersonalInfoTab({
|
||||
</div>
|
||||
</div>
|
||||
{/* {process.env.REACT_APP_SHOW_UPLOAD_PROFILE_PICTURE != 0 && */}
|
||||
<div className="w-[232px] mb-10">
|
||||
<div className="update-profile w-full mb-9">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white flex items-center mb-2">
|
||||
Update Profile
|
||||
<span className="ml-1">
|
||||
<Icons name="block-question" />
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray mb-5">
|
||||
Profile of at least Size
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
300x300
|
||||
</span>
|
||||
. Gifs work too.
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
Max 5mb
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<div className="w-full relative">
|
||||
<img
|
||||
src={profileImg}
|
||||
alt="profile"
|
||||
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-contain object-center"
|
||||
/>
|
||||
<input
|
||||
ref={profileImgInput}
|
||||
onChange={(e) => profileImgChangHandler(e)}
|
||||
type="file"
|
||||
className="hidden"
|
||||
/>
|
||||
<div
|
||||
onClick={browseProfileImg}
|
||||
className="w-[32px] h-[32px] absolute bottom-7 sm:right-10 right-[105px] hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
|
||||
<div className="w-[232px] mb-10">
|
||||
<div className="update-profile w-full mb-9">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white flex items-center mb-2">
|
||||
Update Profile
|
||||
<span className="ml-1">
|
||||
<Icons name="block-question" />
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray mb-5">
|
||||
Profile of at least Size
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
200x200
|
||||
</span>
|
||||
. Gifs work too.
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
Max 5mb
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<div className="w-[200px] h-[200px] relative">
|
||||
<img
|
||||
src={profileImg}
|
||||
alt="profile"
|
||||
className="sm:w-[198px] sm:h-[198px] w-full h-full rounded-full overflow-hidden object-cover object-center"
|
||||
/>
|
||||
<input
|
||||
ref={profileImgInput}
|
||||
onChange={(e) => profileImgChangHandler(e)}
|
||||
type="file"
|
||||
className="hidden"
|
||||
/>
|
||||
<div
|
||||
onClick={browseProfileImg}
|
||||
className="w-[32px] h-[32px] absolute bottom-4 right-4 hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
|
||||
>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<path
|
||||
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
{uploadStatus.message && !uploadStatus.loading && <p className={`text-center ${uploadStatus.status ? 'text-green-500':'text-red-500'}`}>{uploadStatus.message}</p>}
|
||||
{uploadStatus.loading && <p className="text-center">{uploadStatus.message}</p>}
|
||||
</div>
|
||||
{uploadStatus.message && !uploadStatus.loading && (
|
||||
<p
|
||||
className={`text-center ${
|
||||
uploadStatus.status
|
||||
? "text-green-500"
|
||||
: "text-red-500"
|
||||
}`}
|
||||
>
|
||||
{uploadStatus.message}
|
||||
</p>
|
||||
)}
|
||||
{uploadStatus.loading && (
|
||||
<p className="text-center">{uploadStatus.message}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* } */}
|
||||
</div>
|
||||
|
||||
|
||||
+115
-194
@@ -6,8 +6,6 @@ import React, {
|
||||
useState,
|
||||
} from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import cover from "../../assets/images/profile-info-cover.png";
|
||||
import profile from "../../assets/images/profile.jpg";
|
||||
import usersService from "../../services/UsersService";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import Layout from "../Partials/Layout";
|
||||
@@ -26,161 +24,8 @@ import RecipientAccountTab from "./Tabs/RecipientAccountTab";
|
||||
export default function Settings({ faq }) {
|
||||
const apiCall = new usersService();
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
const [profileImg, setProfileImg] = useState(
|
||||
userDetails?.profile_pic_url ? userDetails.profile_pic_url : profile
|
||||
);
|
||||
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
|
||||
const [coverImg, setCoverImg] = useState(cover);
|
||||
const [reloadCardList, setReloadCardList] = useState(false); // STATE TO DETERMINE WHEN CARD LIST RELOADS. EG: WHEN USER DELETES A CARD
|
||||
|
||||
// profile img
|
||||
const profileImgInput = useRef(null);
|
||||
const browseProfileImg = () => {
|
||||
profileImgInput.current.click();
|
||||
};
|
||||
const profileImgChangHandler = (e) => {
|
||||
// if (e.target.value !== "") {
|
||||
// const imgReader = new FileReader();
|
||||
// imgReader.onload = (event) => {
|
||||
// setProfileImg(event.target.result);
|
||||
// };
|
||||
// imgReader.readAsDataURL(e.target.files[0]);
|
||||
// }
|
||||
setUploadStatus({loading: false, status: false, message:''})
|
||||
let acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"] // ARRAY OF SUPPORTED FORMATS
|
||||
let uploadedFile = e.target.files[0] //UPLOADED FILE
|
||||
|
||||
if(!acceptedFormat.includes(uploadedFile?.type?.split("/")[1]?.toLowerCase())){ //CHECKING FOR CORRECT UPLOAD FORMAT
|
||||
let msg = 'Please select '
|
||||
for(let i=0; i<=acceptedFormat.length-1; i++){
|
||||
if(i == acceptedFormat.length-1){
|
||||
msg+=`or ${acceptedFormat[i]}`
|
||||
}else{
|
||||
msg+=`${acceptedFormat[i]}, `
|
||||
}
|
||||
}
|
||||
setUploadStatus({loading: false, status: false, message:msg})
|
||||
return setTimeout(()=>{
|
||||
profileImgInput.current.value = '' // clear the input
|
||||
setUploadStatus({loading: false, status: false, message:''})
|
||||
},5000)
|
||||
}
|
||||
|
||||
if(uploadedFile.size > 5*1048576){ // CHECKING FOR CORRECT FILE SIZE
|
||||
setUploadStatus({loading: false, status: false, message:'File must not exceed 5MB'})
|
||||
return setTimeout(()=>{
|
||||
profileImgInput.current.value = '' // clear the input
|
||||
setUploadStatus({loading: false, status: false, message:''})
|
||||
},5000)
|
||||
}
|
||||
|
||||
if (e.target.value !== "") {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = (event) => {
|
||||
let reqData = { // PAYLOAD FOR API CALL
|
||||
file_name: uploadedFile?.name,
|
||||
file_size: uploadedFile?.size,
|
||||
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
|
||||
file_data: event?.target?.result,
|
||||
msg_type: 'FILE',
|
||||
action: 'WRENCHBOARD_PICTURE_PROFILE',
|
||||
// action: 11307
|
||||
}
|
||||
setUploadStatus({loading: true, status: false, message:'Loading...'})
|
||||
apiCall.sendFiles(reqData).then(res=>{
|
||||
if(res.status != 200 || res.data.internal_return < 0){
|
||||
return setUploadStatus({loading: false, status: false, message: 'Something went wrong, try again'})
|
||||
}
|
||||
setUploadStatus({loading: false, status: true, message: 'Uploaded successfully'})
|
||||
setProfileImg(event.target.result);
|
||||
}).catch(error=>{
|
||||
setUploadStatus({loading: false, status: false, message: 'Network error, try again'})
|
||||
}).finally(()=>{
|
||||
setTimeout(()=>{
|
||||
setUploadStatus({loading: false, status: false, message: ''})
|
||||
},5000)
|
||||
})
|
||||
};
|
||||
imgReader.readAsDataURL(e.target.files[0]);
|
||||
}
|
||||
};
|
||||
// cover img
|
||||
const coverImgInput = useRef(null);
|
||||
const browseCoverImg = () => {
|
||||
coverImgInput.current.click();
|
||||
};
|
||||
const coverImgChangHandler = (e) => {
|
||||
if (e.target.value !== "") {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = (event) => {
|
||||
setCoverImg(event.target.result);
|
||||
};
|
||||
imgReader.readAsDataURL(e.target.files[0]);
|
||||
}
|
||||
};
|
||||
|
||||
// Tabs Handling
|
||||
const tabs = [
|
||||
{
|
||||
id: 1,
|
||||
name: "personal",
|
||||
title: "Edit Profile",
|
||||
iconName: "people-hover",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "payment",
|
||||
title: "Payment Cards",
|
||||
iconName: "bank-card",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "recipients-account",
|
||||
title: "Recipients Account",
|
||||
iconName: "bank-card",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "notification",
|
||||
title: "Notification Setting",
|
||||
iconName: "notification-setting",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "login_activity",
|
||||
title: "Login Activity",
|
||||
iconName: "login-activity",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "password",
|
||||
title: "Change Password",
|
||||
iconName: "password-hover",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "faq",
|
||||
title: "FAQ",
|
||||
iconName: "block-question",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "privacy",
|
||||
title: "Privacy Policy",
|
||||
iconName: "page-right",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "terms",
|
||||
title: "Terms and Conditions",
|
||||
iconName: "page-right",
|
||||
},
|
||||
];
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
// Recipient Account
|
||||
const [recipientAccount, setRecipientAccount] = useState({
|
||||
state: false,
|
||||
@@ -223,6 +68,120 @@ export default function Settings({ faq }) {
|
||||
getRecipientAccount();
|
||||
}, [reloadCardList]);
|
||||
|
||||
// Tabs Handling
|
||||
const tabs = [
|
||||
{
|
||||
id: 1,
|
||||
name: "personal",
|
||||
title: "Edit Profile",
|
||||
iconName: "people-hover",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "payment",
|
||||
title: "Payment Cards",
|
||||
iconName: "bank-card",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "recipients_account",
|
||||
title: "Recipients Account",
|
||||
iconName: "bank-card",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "notification",
|
||||
title: "Notification Setting",
|
||||
iconName: "notification-setting",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "login_activity",
|
||||
title: "Login Activity",
|
||||
iconName: "login-activity",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "password",
|
||||
title: "Change Password",
|
||||
iconName: "password-hover",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "faq",
|
||||
title: "FAQ",
|
||||
iconName: "block-question",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "privacy",
|
||||
title: "Privacy Policy",
|
||||
iconName: "page-right",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "terms",
|
||||
title: "Terms and Conditions",
|
||||
iconName: "page-right",
|
||||
},
|
||||
];
|
||||
|
||||
const [tab, setTab] = useState(() => {
|
||||
// Retrieve the active tab from local storage or use the default tab
|
||||
return localStorage.getItem("activeTab") || tabs[0].name;
|
||||
});
|
||||
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
// Update local storage when the tab changes
|
||||
useEffect(() => {
|
||||
localStorage.setItem("activeTab", tab);
|
||||
}, [tab]);
|
||||
|
||||
const tabComponents = {
|
||||
personal: (
|
||||
<div className="tab-item">
|
||||
<PersonalInfoTab />
|
||||
</div>
|
||||
),
|
||||
payment: (
|
||||
<div className="tab-item">
|
||||
<PaymentMathodsTab />
|
||||
</div>
|
||||
),
|
||||
recipients_account: (
|
||||
<div className="tab-item">
|
||||
<RecipientAccountTab
|
||||
recipientAccount={recipientAccount}
|
||||
setRecipientAccount={setRecipientAccount}
|
||||
setReloadCardList={setReloadCardList}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
notification: (
|
||||
<div className="tab-item">
|
||||
<NotificationSettingTab />
|
||||
</div>
|
||||
),
|
||||
login_activity: <LoginActivityTab />,
|
||||
password: <ChangePasswordTab />,
|
||||
faq: <FaqTab datas={faq} />,
|
||||
privacy: <PrivacyPolicyTab />,
|
||||
terms: <TermsConditionTab />,
|
||||
};
|
||||
|
||||
// Default tab component
|
||||
const defaultTabComponent = (
|
||||
<div className="tab-item">
|
||||
<PersonalInfoTab />
|
||||
</div>
|
||||
);
|
||||
|
||||
// Selected tab component based on the current 'tab'
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Layout>
|
||||
@@ -263,45 +222,7 @@ export default function Settings({ faq }) {
|
||||
</div>
|
||||
<div className="w-[1px] bg-[#E3E4FE] dark:bg-[#a7a9b533] mr-10"></div>
|
||||
<div className="content-body-items flex-1">
|
||||
{tab === "personal" && (
|
||||
<div className="tab-item">
|
||||
<PersonalInfoTab
|
||||
profileImg={profileImg}
|
||||
coverImg={coverImg}
|
||||
browseProfileImg={browseProfileImg}
|
||||
profileImgInput={profileImgInput}
|
||||
profileImgChangHandler={profileImgChangHandler}
|
||||
coverImgChangHandler={coverImgChangHandler}
|
||||
browseCoverImg={browseCoverImg}
|
||||
coverImgInput={coverImgInput}
|
||||
uploadStatus={uploadStatus}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{tab === "payment" && (
|
||||
<div className="tab-item">
|
||||
<PaymentMathodsTab />
|
||||
</div>
|
||||
)}
|
||||
{tab === "recipients-account" && (
|
||||
<div className="tab-item">
|
||||
<RecipientAccountTab
|
||||
recipientAccount={recipientAccount}
|
||||
setRecipientAccount={setRecipientAccount}
|
||||
setReloadCardList={setReloadCardList}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{tab === "notification" && (
|
||||
<div className="tab-item">
|
||||
<NotificationSettingTab />
|
||||
</div>
|
||||
)}
|
||||
{tab === "login_activity" && <LoginActivityTab />}
|
||||
{tab === "password" && <ChangePasswordTab />}
|
||||
{tab === "faq" && <FaqTab datas={faq} />}
|
||||
{tab === "privacy" && <PrivacyPolicyTab />}
|
||||
{tab === "terms" && <TermsConditionTab />}
|
||||
{selectedTabComponent}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -52,6 +52,18 @@ const EditJobPopOut = ({
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [taskImage, setTaskImage] = useState('')
|
||||
|
||||
const changeTaskImage = (e) => {
|
||||
if (e.target.value !== "") {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = (event) => {
|
||||
setTaskImage(event.target.result);
|
||||
};
|
||||
imgReader.readAsDataURL(e.target.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({
|
||||
loading: false,
|
||||
status: false,
|
||||
@@ -138,7 +150,7 @@ const EditJobPopOut = ({
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="logout-modal-body w-full flex flex-col items-center px-10 py-8">
|
||||
<div className="logout-modal-body w-full flex flex-col items-center px-10 pb-8 pt-2">
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
@@ -279,43 +291,67 @@ const EditJobPopOut = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field w-full mb-6">
|
||||
<div
|
||||
className={`flex items-center justify-between mb-2.5`}
|
||||
>
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||
htmlFor="timeline_days"
|
||||
>
|
||||
Timeline
|
||||
<span className="text-green-700 text-sm tracking-wide">
|
||||
- Expected duration of this task
|
||||
</span>
|
||||
<div className="w-full flex items-center gap-2 mb-2">
|
||||
{/* FOR TASK IMAGE */}
|
||||
<div className="w-1/2 relative max-h-[130px] min-h-[130px]">
|
||||
<input
|
||||
id="task_image"
|
||||
className="hidden"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={changeTaskImage}
|
||||
/>
|
||||
{taskImage ?
|
||||
<div className="w-full absolute -top-5">
|
||||
<img src={taskImage} className="max-h-[150px] min-h-[150px] w-full object-cover" alt="uplaoded task image" />
|
||||
<span onClick={()=>setTaskImage('')} className="p-2 absolute text-sm top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white/20 hover:bg-white/70 hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800">Remove Image</span>
|
||||
</div>
|
||||
:
|
||||
<label
|
||||
className="absolute -top-5 h-[150px] w-full flex flex-col justify-center items-center bg-slate-100 dark:bg-[#11131F] cursor-pointer input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold" htmlFor='task_image'>
|
||||
Select Task Image
|
||||
</label>
|
||||
}
|
||||
</div>
|
||||
{/* END OF TASK IMAGE */}
|
||||
|
||||
<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 ${
|
||||
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>
|
||||
{publicArray.map(({ name, duration }, idx) => (
|
||||
<option
|
||||
className="text-slate-500 text-lg"
|
||||
value={duration}
|
||||
<div className="field w-1/2">
|
||||
<div
|
||||
className={`flex items-center justify-between`}
|
||||
>
|
||||
<label
|
||||
className="w-full input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex flex-col"
|
||||
htmlFor="timeline_days"
|
||||
>
|
||||
{name}
|
||||
</option>
|
||||
))}
|
||||
</Field>
|
||||
Timeline -
|
||||
<span className="w-full text-center text-green-700 text-sm tracking-wide">
|
||||
Expected duration of this task
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<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 ${
|
||||
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>
|
||||
{publicArray.map(({ name, duration }, idx) => (
|
||||
<option
|
||||
className="text-slate-500 text-lg"
|
||||
value={duration}
|
||||
>
|
||||
{name}
|
||||
</option>
|
||||
))}
|
||||
</Field>
|
||||
</div>
|
||||
</div>
|
||||
{/* inputs ends here */}
|
||||
</div>
|
||||
|
||||
@@ -24,6 +24,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
||||
const [pendingJobLoader, setPendingJobLoader] = useState({
|
||||
extend: false,
|
||||
offer: false,
|
||||
cancel: false,
|
||||
});
|
||||
|
||||
let [requestMessage, setRequestMessage] = useState({
|
||||
@@ -81,6 +82,29 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
||||
setRequestMessage({ status: false, message: "" });
|
||||
}, 3000);
|
||||
});
|
||||
} else if (name == "cancel") {
|
||||
// RUNS THIS IF JOB OFFER IS CANCELLED
|
||||
reqData = { ...pendingData, reason: "cancel", offer_result: 3333 };
|
||||
setPendingJobLoader({ cancel: true });
|
||||
apiCall
|
||||
.pendingCancelOffer(reqData)
|
||||
.then((res) => {
|
||||
setRequestMessage({ status: true, message: res.data.status });
|
||||
setTimeout(() => {
|
||||
setPendingJobLoader({ cancel: false });
|
||||
setRequestMessage({ status: false, message: "" });
|
||||
onClose();
|
||||
dispatch(tableReload({ type: "PENDINGTABLE" }));
|
||||
dispatch(tableReload({ type: "JOBTABLE" }));
|
||||
}, 4000);
|
||||
})
|
||||
.catch((error) => {
|
||||
setRequestMessage("Try Again");
|
||||
setTimeout(() => {
|
||||
setPendingJobLoader({ cancel: false });
|
||||
setRequestMessage({ status: false, message: "" });
|
||||
}, 3000);
|
||||
});
|
||||
} else return;
|
||||
// try {
|
||||
// if (name === "extend") {
|
||||
@@ -274,9 +298,16 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
||||
<div className="mt-10 md:mt-32 md:flex md:justify-center">
|
||||
<button
|
||||
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
onClick={onClose}
|
||||
onClick={handlePendingJobsBtn}
|
||||
name="cancel"
|
||||
>
|
||||
Cancel Offer
|
||||
{pendingJobLoader.cancel ? (
|
||||
<div className="w-[96px] flex justify-center items-center h-full">
|
||||
<LoadingSpinner size={5} color="sky-blue" />
|
||||
</div>
|
||||
) : (
|
||||
"Cancel Offer"
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1237,10 +1237,6 @@ class usersService {
|
||||
console.log(response);
|
||||
// res = response;
|
||||
console.log("~~~~~~~ Toks2 POST ~~~~~~~~");
|
||||
if(response.data.internal_return == '-9999'){
|
||||
localStorage.clear()
|
||||
window.location.href=`/login?sessionExpired=true`
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from 'react'
|
||||
|
||||
import Lnd from '../components/Lnd/Lnd'
|
||||
|
||||
function LndPage() {
|
||||
return (
|
||||
<>
|
||||
<Lnd />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default LndPage
|
||||
@@ -22,7 +22,7 @@ export default function MyPendingJobsPage() {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getMyJobList();
|
||||
getMyJobList();
|
||||
}, [pendingListTable]);
|
||||
|
||||
// debugger;
|
||||
|
||||
Reference in New Issue
Block a user