Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ebe9fe12b | |||
| 3fbaf6b78a | |||
| 421a24c185 | |||
| 6386fbcda6 | |||
| 2e09d77597 | |||
| 10dae9193c | |||
| 3f487337f4 | |||
| 7eabee8855 | |||
| 360f0500a9 | |||
| 9b6c5b72ad | |||
| afc5e25cfc | |||
| 58fe5eb82c | |||
| 2f3fdc0695 | |||
| 0a465fceb0 | |||
| 5e968db2f5 | |||
| 1916bc1a65 | |||
| 1103127cae | |||
| 751369071c | |||
| 4cc8f27c14 | |||
| aab455c2c3 | |||
| 21843c4bc7 | |||
| 8702728ffa | |||
| a8416a8433 | |||
| 70c9d1778c | |||
| 930559c96b | |||
| c4af2dfcc8 | |||
| b186549b8d |
@@ -90,4 +90,9 @@ REACT_APP_SHOW_OFFER_GROUP_JOB=0
|
||||
REACT_APP_SHOW_UPLOAD_PROFILE_PICTURE=0
|
||||
|
||||
#GOOGLE RECAPTCHA SITEKEY
|
||||
REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
||||
REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6Ld_qKooAAAAADNL1TPzRLmcBA8vlpvx__39Rj39
|
||||
#6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
||||
|
||||
#FAMILY MEMBER MINIMUM AGE
|
||||
REACT_APP_FAMILY_MINIMUM_AGE=4
|
||||
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
||||
+6
-1
@@ -58,4 +58,9 @@ REACT_APP_SHOW_OFFER_GROUP_JOB=0
|
||||
REACT_APP_SHOW_UPLOAD_PROFILE_PICTURE=0
|
||||
|
||||
#GOOGLE RECAPTCHA SITEKEY
|
||||
REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
||||
REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6Ld_qKooAAAAADNL1TPzRLmcBA8vlpvx__39Rj39
|
||||
#6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
||||
|
||||
#FAMILY MEMBER MINIMUM AGE
|
||||
REACT_APP_FAMILY_MINIMUM_AGE=4
|
||||
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
||||
+6
-1
@@ -64,4 +64,9 @@ REACT_APP_SHOW_OFFER_GROUP_JOB=0
|
||||
REACT_APP_SHOW_UPLOAD_PROFILE_PICTURE=0
|
||||
|
||||
#GOOGLE RECAPTCHA SITEKEY
|
||||
REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
||||
REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6Ld_qKooAAAAADNL1TPzRLmcBA8vlpvx__39Rj39
|
||||
#6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
||||
|
||||
#FAMILY MEMBER MINIMUM AGE
|
||||
REACT_APP_FAMILY_MINIMUM_AGE=4
|
||||
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
||||
|
||||
@@ -24,7 +24,7 @@ const ForgetPwdResponse = ({title, message, type}) => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigate("/login")}
|
||||
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
||||
className={`h-[48px] rounded-full mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
||||
>
|
||||
<span>Home</span>
|
||||
</button>
|
||||
|
||||
@@ -176,14 +176,14 @@ export default function ForgotPassword() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigate("/login")}
|
||||
className={`rounded-full mb-6 text-[15px] font-semibold text-white hover:text-white flex justify-center bg-red-500 hover:bg-red-600 transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
|
||||
className={`h-[48px] rounded-full mb-6 text-[15px] font-semibold text-white hover:text-white flex justify-center bg-red-500 hover:bg-red-600 transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={resetHandler}
|
||||
className={`rounded-full mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
||||
className={`h-[48px] rounded-full mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
||||
>
|
||||
{resetLoading ? (
|
||||
<div className="signup btn-loader"></div>
|
||||
|
||||
@@ -14,10 +14,14 @@ import { useGoogleLogin } from "@react-oauth/google";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { updateUserDetails } from "../../../store/UserDetails";
|
||||
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
|
||||
export default function Login() {
|
||||
const dispatch = useDispatch();
|
||||
const { state } = useLocation();
|
||||
|
||||
const [validCaptcha, setValidCaptcha] = useState({show: false, valid:''}); // FOR CAPTCHA
|
||||
|
||||
let [loginType, setLoginType] = useState("");
|
||||
|
||||
const [loginLoading, setLoginLoading] = useState(false);
|
||||
@@ -107,6 +111,14 @@ export default function Login() {
|
||||
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
|
||||
return;
|
||||
}
|
||||
if(name == "full" && !validCaptcha.valid && validCaptcha.show){ // RUNS AND DISPLAYS CAPTCHA, IF ERROR OCCURED DURING LOGIN FOR FULL LOGIN ALONE
|
||||
setMsgError("Please Verify Captcha");
|
||||
setLoginLoading(false);
|
||||
setTimeout(() => {
|
||||
setMsgError("");
|
||||
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
|
||||
return;
|
||||
}
|
||||
userApi
|
||||
.logInUser(postData)
|
||||
.then((res) => {
|
||||
@@ -120,6 +132,7 @@ export default function Login() {
|
||||
// setMsgError("Wrong, email/password");
|
||||
setLoginError(true);
|
||||
setLoginLoading(false);
|
||||
setValidCaptcha(prev => ({...prev, show:true})) // DISPLAYS CAPTCHA IF ERROR
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("member_id", `${res.data.member_id}`);
|
||||
@@ -135,6 +148,7 @@ export default function Login() {
|
||||
.catch((error) => {
|
||||
setMsgError("Unable to login, try again");
|
||||
setLoginLoading(false);
|
||||
setValidCaptcha(prev => ({...prev, show:true})) // DISPLAYS CAPTCHA IF ERROR
|
||||
})
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
@@ -145,6 +159,14 @@ export default function Login() {
|
||||
});
|
||||
};
|
||||
|
||||
function captchaChecker(value) { // FUNCTION TO VALIDATE CAPTCHA
|
||||
if(value){
|
||||
setValidCaptcha({show: true, valid:value})
|
||||
}else{
|
||||
setValidCaptcha({show: true, valid:''})
|
||||
}
|
||||
}
|
||||
|
||||
const googleLogin = useGoogleLogin({
|
||||
flow: "auth-code",
|
||||
ux_mode: "redirect",
|
||||
@@ -296,6 +318,17 @@ export default function Login() {
|
||||
forgotPassword
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* hCaptha clone for the time being */}
|
||||
{validCaptcha.show &&
|
||||
<div className="mb-5 flex justify-center w-full">
|
||||
<ReCAPTCHA
|
||||
sitekey={process.env.REACT_APP_GOOGLE_RECAPTCHA_SITEKEY}
|
||||
onChange={captchaChecker}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
{loginError && (
|
||||
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
|
||||
Invalid username or password- Please{" "}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import dataImage2 from "../../assets/images/data-table-user-2.png";
|
||||
import dataImage2 from "../../assets/images/taskbanners/default.jpg";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import React, {
|
||||
useState,
|
||||
} from "react";
|
||||
import { useReactToPrint } from "react-to-print";
|
||||
import profile from "../../assets/images/profile-info-profile.png";
|
||||
import profile from "../../assets/images/icons/family.svg";
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
import usersService from "../../services/UsersService";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
@@ -51,6 +51,8 @@ export default function FamilyManageTabs({
|
||||
});
|
||||
};
|
||||
|
||||
const [updatePage, setUpdatePage] = useState(false) // State to determine when to update the page
|
||||
|
||||
// State for family task data
|
||||
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
|
||||
|
||||
@@ -82,14 +84,29 @@ export default function FamilyManageTabs({
|
||||
profileImgInput.current.click();
|
||||
};
|
||||
|
||||
// Function to handle changes in the profile image input
|
||||
/**
|
||||
* Handles the change event of the profile image input field.
|
||||
* 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) => {
|
||||
if (e.target.value !== "") {
|
||||
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;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
const imgReader = new FileReader();
|
||||
imgReader.onload = (event) => {
|
||||
setProfileImg(event.target.result);
|
||||
imgReader.onload = () => {
|
||||
const imageDataUrl = imgReader.result;
|
||||
|
||||
// Set the profile image
|
||||
setProfileImg(imageDataUrl);
|
||||
};
|
||||
imgReader.readAsDataURL(e.target.files[0]);
|
||||
imgReader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -148,7 +165,7 @@ export default function FamilyManageTabs({
|
||||
handlePrint={useHandlePrint}
|
||||
/>
|
||||
),
|
||||
Profile: <FamilyProfile />,
|
||||
Profile: <FamilyProfile familyData={details.familyDetails.data} />,
|
||||
};
|
||||
|
||||
// Default tab component
|
||||
@@ -220,7 +237,7 @@ export default function FamilyManageTabs({
|
||||
|
||||
// Invoke the manageFamily function when the component mounts
|
||||
manageFamily();
|
||||
}, []);
|
||||
}, [updatePage]);
|
||||
|
||||
// Effect to manage family tasks
|
||||
useEffect(() => {
|
||||
@@ -356,6 +373,7 @@ export default function FamilyManageTabs({
|
||||
setActiveTask={setActiveTask}
|
||||
activeTask={activeTask}
|
||||
familyDetailsData={details.familyDetails.data}
|
||||
setUpdatePage={setUpdatePage}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,7 @@ const AssignTaskPopout = React.memo(
|
||||
familyTask,
|
||||
activeTask,
|
||||
setActiveTask,
|
||||
setUpdatePage
|
||||
}) => {
|
||||
const apiCall = new usersService();
|
||||
|
||||
@@ -143,6 +144,7 @@ const AssignTaskPopout = React.memo(
|
||||
status: true,
|
||||
message: "action successful",
|
||||
});
|
||||
setUpdatePage(prev => !prev) // Updates family task page by calling the useeffect hook
|
||||
setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
action(); // FUNCTION THAT CLOSES THE MODAL BOX
|
||||
|
||||
@@ -139,8 +139,8 @@ export default function FamilyTable({
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="h-full">
|
||||
{currentFamilyList?.map((familyMember) => {
|
||||
return <FamilyRow {...familyMember} />;
|
||||
{currentFamilyList?.map((familyMember, index) => {
|
||||
return <FamilyRow key={index} {...familyMember} />;
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -1,11 +1,221 @@
|
||||
export default function FamilyProfile({ className }) {
|
||||
import { useState } from "react";
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import usersService from "../../../services/UsersService";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { Formik, Form } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
|
||||
export default function FamilyProfile({familyData, className }) {
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
firstname: Yup.string()
|
||||
.required("Firstname is required"),
|
||||
lastname: Yup.string()
|
||||
// .min(3, "Minimum 3 characters")
|
||||
// .max(25, "Maximum 25 characters")
|
||||
.required("Lastname is required"),
|
||||
year: Yup.number()
|
||||
.required("Year is required")
|
||||
.min(new Date().getFullYear()-process.env.REACT_APP_FAMILY_MAXIMUM_AGE, `Age must be within ${process.env.REACT_APP_FAMILY_MINIMUM_AGE} to ${process.env.REACT_APP_FAMILY_MAXIMUM_AGE} years`)
|
||||
.max(new Date().getFullYear()-process.env.REACT_APP_FAMILY_MINIMUM_AGE, `Age must be within ${process.env.REACT_APP_FAMILY_MINIMUM_AGE} to ${process.env.REACT_APP_FAMILY_MAXIMUM_AGE} years`),
|
||||
month: Yup.number()
|
||||
.required("Month is required")
|
||||
.min(1, "Month is required"),
|
||||
});
|
||||
|
||||
const navigate = useNavigate()
|
||||
const api = new usersService()
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({loading:false, status:false, message: ''})
|
||||
|
||||
// let [updateDetails, setUpdateDetails] = useState({
|
||||
// family_uid: familyData.uid,
|
||||
// firstname: familyData.firstname,
|
||||
// lastname: familyData.lastname,
|
||||
// year: familyData.year,
|
||||
// month: familyData.month,
|
||||
// action: 22020
|
||||
// })
|
||||
|
||||
// initial values for formik
|
||||
let initialValues = {
|
||||
family_uid: familyData.uid,
|
||||
firstname: familyData.firstname,
|
||||
lastname: familyData.lastname,
|
||||
year: familyData.year,
|
||||
month: familyData.month,
|
||||
action: 22020
|
||||
};
|
||||
|
||||
const handleChange = ({target:{name, value}})=>{
|
||||
setUpdateDetails(prev => ({...prev, [name]:value}))
|
||||
}
|
||||
|
||||
const updateFamily = (values, helpers) => {
|
||||
setRequestStatus({loading:true, status:false, message: ''})
|
||||
// let {firstname, lastname, year, month} = updateDetails
|
||||
// if(!firstname || !lastname || year == 0 || month == 0) {
|
||||
// setRequestStatus({loading:false, status:false, message: 'Please fill all fields'})
|
||||
// return setTimeout(()=>{
|
||||
// setRequestStatus({loading:false, status:false, message: ''})
|
||||
// }, 5000)
|
||||
// }
|
||||
api.getFamilyUpdate(values).then(res=>{
|
||||
if(res.data.internal_return < 0){
|
||||
return setRequestStatus({loading:false, status:false, message: 'Failed, try again!'})
|
||||
}
|
||||
setRequestStatus({loading:false, status:true, message: 'Family account updated'})
|
||||
setTimeout(()=>{
|
||||
navigate('/acc-family', {replace:true})
|
||||
}, 5000)
|
||||
}).catch(error => {
|
||||
setRequestStatus({loading:false, status:false, message: 'Unable to update, try again!'})
|
||||
}).finally(()=>{
|
||||
setTimeout(()=>{
|
||||
setRequestStatus({loading:false, status:false, message: ''})
|
||||
}, 5000)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px] p-3 ${
|
||||
className={`w-full bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px] p-3 ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
<h1>Profile</h1>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={updateFamily}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className="logout-modal-body w-full lg:w-[500px] lg:mx-auto flex flex-col items-center px-10 py-8 gap-4">
|
||||
<InputCom
|
||||
placeholder="Firstname"
|
||||
label="First Name:"
|
||||
name="firstname"
|
||||
type="text"
|
||||
parentClass="flex items-center gap-1 w-full"
|
||||
labelClass="flex-[0.2] mb-0"
|
||||
inputClass={`flex-[0.8] input-curve lg border border-[#dce4e9] ${props.errors.firstname && props.touched.firstname ? 'border border-red-500' : ''}`}
|
||||
fieldClass="px-2"
|
||||
value={props.values.firstname}
|
||||
inputHandler={props.handleChange}
|
||||
/>
|
||||
<InputCom
|
||||
placeholder="Lastname"
|
||||
label="Last Name:"
|
||||
name="lastname"
|
||||
type="text"
|
||||
parentClass="flex items-center gap-1 w-full"
|
||||
labelClass="flex-[0.2] mb-0"
|
||||
inputClass={`flex-[0.8] input-curve lg border border-[#dce4e9] ${props.errors.lastname && props.touched.lastname ? 'border border-red-500' : ''}`}
|
||||
fieldClass="px-2"
|
||||
value={props.values?.lastname}
|
||||
inputHandler={props.handleChange}
|
||||
/>
|
||||
<div className="input-com mb-7 flex flex-col gap-1 w-full">
|
||||
{/* Age dropdown */}
|
||||
<div className="">
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[15px] font-semibold"
|
||||
htmlFor="age-selection"
|
||||
>
|
||||
Birthday: (Year/Month)
|
||||
</label>
|
||||
{((props.errors.year && props.touched.year) || (props.errors.month && props.touched.month)) && (
|
||||
<span className="text-[12px] text-red-500">
|
||||
{' '}{props.errors.year || props.errors.month}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex max-w-[330px] w-full self-end gap-4">
|
||||
<select
|
||||
name='year'
|
||||
id="yearDropdown"
|
||||
value={props.values.year}
|
||||
onChange={props.handleChange}
|
||||
className={`input-wrapper border border-[#f5f8fa] ${props.errors.year && props.touched.year ? 'border border-red-500' : ''} dark:border-[#5e6278] w-56 rounded-[35px] h-10 overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent px-4`}
|
||||
>
|
||||
<option value="">Select a Year</option>
|
||||
{years.map((year) => (
|
||||
<option key={year} value={year}>
|
||||
{year}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select
|
||||
name='month'
|
||||
id="monthDropdown"
|
||||
// value={(months.filter(month => month.id == selectedMonth)[0]?.id) || ''}
|
||||
value={(months.filter(month => month.id == props.values.month)[0]?.id) || 0}
|
||||
onChange={props.handleChange}
|
||||
className={`input-wrapper border border-[#f5f8fa] ${props.errors.month && props.touched.month ? 'border border-red-500' : ''} dark:border-[#5e6278] w-56 rounded-[35px] h-10 overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent px-4`}
|
||||
>
|
||||
<option value="">Select a Month</option>
|
||||
{months.map(({id, name}) => (
|
||||
<option key={id} value={id}>
|
||||
{name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{requestStatus.message && (
|
||||
<div className={`relative p-2 ${!requestStatus.status ? 'text-[#912741] bg-[#fcd9e2] border-[#fbc6d3]' : 'text-green-700'} mb-2 rounded-[0.475rem] text-xs font-light leading-[19.5px]`}>
|
||||
{requestStatus.message}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-end w-full">
|
||||
{requestStatus.loading ?
|
||||
<>
|
||||
<div className="signup btn-loader"></div>
|
||||
<LoadingSpinner size='4' />
|
||||
</>
|
||||
:
|
||||
<button
|
||||
type="submit"
|
||||
// onClick={updateFamily}
|
||||
// className={`rounded-[0.475rem] text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
|
||||
className="text-white btn-gradient text-lg tracking-wide px-6 py-2 rounded-full"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Get the current year
|
||||
// const currentYear = new Date().getFullYear() - process.env.REACT_APP_FAMILY_MINIMUM_AGE;
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
// Generate an array of years from the current year to (currentYear - 19)
|
||||
const years = Array.from({ length: 19 }, (_, index) => currentYear - index);
|
||||
|
||||
const months = [
|
||||
{id:'1', name:"January"},
|
||||
{id:'2', name:"February"},
|
||||
{id:'3', name:"March"},
|
||||
{id:'4', name:"April"},
|
||||
{id:'5', name:"May"},
|
||||
{id:'6', name:"June"},
|
||||
{id:'7', name:"July"},
|
||||
{id:'8', name:"August"},
|
||||
{id:'9', name:"September"},
|
||||
{id:'10', name:"October"},
|
||||
{id:'11', name:"November"},
|
||||
{id:'12', name:"December"},
|
||||
];
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
import React from "react";
|
||||
import localImgLoad from "../../../lib/localImgLoad";
|
||||
|
||||
|
||||
export default function ProfileInfo({
|
||||
profileImg,
|
||||
profileImgInput,
|
||||
profileImgChangHandler,
|
||||
profileImgChangeHandler,
|
||||
browseProfileImg,
|
||||
accountDetails,
|
||||
}) {
|
||||
// console.log(accountDetails.banner)
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="flex justify-center">
|
||||
<div className="w-full relative">
|
||||
<img
|
||||
src={localImgLoad(`images/icons/${accountDetails.banner}`)}
|
||||
alt=""
|
||||
src={
|
||||
profileImg
|
||||
? profileImg
|
||||
: localImgLoad(`images/icons/${accountDetails.banner}`)
|
||||
}
|
||||
alt="profile"
|
||||
className="sm:w-[180px] sm:h-[180px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
|
||||
/>
|
||||
<input
|
||||
ref={profileImgInput}
|
||||
onChange={(e) => profileImgChangHandler(e)}
|
||||
accept="image/*"
|
||||
onChange={profileImgChangeHandler}
|
||||
type="file"
|
||||
className="hidden"
|
||||
/>
|
||||
|
||||
@@ -197,11 +197,11 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
<hr />
|
||||
<div className="my-3 w-full flex flex-col gap-3">
|
||||
<div className="w-full">
|
||||
<label className="w-full text-slate-900 dark:text-white tracking-wide">
|
||||
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
|
||||
If you have any questions about this task:
|
||||
</label>
|
||||
<textarea
|
||||
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
|
||||
className={`p-1 w-full text-lg text-slate-900 dark:text-white bg-transparent outline-none border-2 border-slate-900 rounded-md`}
|
||||
rows="5"
|
||||
style={{ resize: "none" }}
|
||||
placeholder="Enter message here ..."
|
||||
@@ -210,7 +210,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
className="self-end w-[150px] h-[52px] rounded-md text-base bg-yellow-500 text-white"
|
||||
className="self-end w-[150px] h-[48px] rounded-full text-base bg-yellow-500 text-white"
|
||||
name="market-message"
|
||||
onClick={MarketDetail}
|
||||
>
|
||||
@@ -225,10 +225,10 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full md:w-[23%] h-full ">
|
||||
<div className="w-full md:w-[23%] h-full flex flex-col">
|
||||
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] 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">
|
||||
<p className="w-full text-slate-900 tracking-wide my-1 font-semibold">
|
||||
Interested in the task?
|
||||
</p>
|
||||
<hr />
|
||||
@@ -270,7 +270,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||
</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"
|
||||
className="self-center w-[150px] mt-2 h-[48px] rounded-full text-base bg-transparent border border-red-500 text-red-500 mx-auto"
|
||||
name="cancel"
|
||||
onClick={onClose}
|
||||
>
|
||||
|
||||
@@ -118,7 +118,11 @@ function PastDueJobAction({jobDetails}) {
|
||||
<tr>
|
||||
<td>
|
||||
<div className="flex justify-center items-center">
|
||||
<button type="button" onClick={popUpHandler} className="w-[180px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
<button
|
||||
type="button"
|
||||
onClick={popUpHandler}
|
||||
className="px-4 h-[48px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
Cancel or Extend Timeline
|
||||
</button>
|
||||
</div>
|
||||
@@ -230,8 +234,12 @@ function PastDueJobAction({jobDetails}) {
|
||||
|
||||
{/* cancel btn */}
|
||||
<div className='flex justify-end items-center'>
|
||||
<button onClick={popUpHandler} type="button" className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
|
||||
<span className='text-gradient'>Cancel</span>
|
||||
<button onClick={popUpHandler} type="button"
|
||||
// className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white"
|
||||
className='w-[150px] mt-2 h-[48px] rounded-full text-base bg-transparent border border-red-500 text-red-500'
|
||||
>
|
||||
Cancel
|
||||
{/* <span className='text-gradient'>Cancel</span> */}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,8 +12,7 @@ function NairaWithdraw({
|
||||
state,
|
||||
setShowConfirmNairaWithdraw,
|
||||
}) {
|
||||
|
||||
let MaxNoOfBanks = process.env.REACT_APP_MAX_CREDIT_BANK_ACCOUNT // HOLDS THE VALUE OF THE MAX NUMBER OF BANKS USER CAN ADD
|
||||
let MaxNoOfBanks = process.env.REACT_APP_MAX_CREDIT_BANK_ACCOUNT; // HOLDS THE VALUE OF THE MAX NUMBER OF BANKS USER CAN ADD
|
||||
const apiCall = new usersService();
|
||||
const [tab, setTab] = useState("previous");
|
||||
let [requestStatus, setRequestStatus] = useState(false);
|
||||
@@ -25,7 +24,9 @@ function NairaWithdraw({
|
||||
recipientID: state?.previousAccount?.recipientID || "",
|
||||
},
|
||||
newAccount: {
|
||||
country: state?.newAccount?.amount || "",
|
||||
country: wallet.walletCountry
|
||||
? wallet.walletCountry[0][0]
|
||||
: wallet.country,
|
||||
bank: state?.newAccount?.amount || "",
|
||||
accountNumber: state?.newAccount?.amount || "",
|
||||
accountType: state?.newAccount?.amount || "",
|
||||
@@ -67,10 +68,14 @@ function NairaWithdraw({
|
||||
|
||||
// Handling card change
|
||||
const handleBankOptions = (event) => {
|
||||
const { value } = event.target;
|
||||
let bankCountry = wallet.walletCountry
|
||||
? wallet.walletCountry[0][0]
|
||||
: wallet.country
|
||||
setBankName((prev) => ({ loading: true, data: [] }));
|
||||
apiCall
|
||||
.getCountryBank({ country: value })
|
||||
.getCountryBank({
|
||||
country: bankCountry
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 0) {
|
||||
setBankName((prev) => ({ loading: false, data: [] }));
|
||||
@@ -140,6 +145,7 @@ function NairaWithdraw({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleBankOptions()
|
||||
getCountry(); // TO LOAD LIST COUNTRY
|
||||
getAccountTypes(); // TO LOAD LIST ACCOUNT TYPES
|
||||
}, []);
|
||||
@@ -226,7 +232,7 @@ function NairaWithdraw({
|
||||
setShowConfirmNairaWithdraw({ show: true, state: stateData });
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
if (tab === "new") {
|
||||
const { accountNumber, accountType, bank, city, country, state } =
|
||||
values?.newAccount;
|
||||
@@ -281,6 +287,8 @@ function NairaWithdraw({
|
||||
getRecipients();
|
||||
}, []);
|
||||
|
||||
console.log("Testing Wallet Country", wallet?.walletCountry[0][0]);
|
||||
|
||||
return (
|
||||
<ModalCom action={action} situation={situation} className="edit-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">
|
||||
@@ -424,7 +432,11 @@ function NairaWithdraw({
|
||||
<label
|
||||
onClick={() => setTab("new")}
|
||||
htmlFor="new"
|
||||
className={`cursor-pointer flex items-center gap-1 ${recipients.data.length >= MaxNoOfBanks ? 'pointer-events-none':''}`}
|
||||
className={`cursor-pointer flex items-center gap-1 ${
|
||||
recipients.data.length >= MaxNoOfBanks
|
||||
? "pointer-events-none"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<input
|
||||
id="new"
|
||||
@@ -436,7 +448,12 @@ function NairaWithdraw({
|
||||
tab == "new" ? "" : ""
|
||||
} tracking-wide transition duration-200`}
|
||||
/>
|
||||
New Account{" "} {recipients.data.length >= MaxNoOfBanks && <span className="text-[14px] text-red-500">Max Reached</span>}
|
||||
New Account{" "}
|
||||
{recipients.data.length >= MaxNoOfBanks && (
|
||||
<span className="text-[14px] text-red-500">
|
||||
Max Reached
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -523,12 +540,12 @@ function NairaWithdraw({
|
||||
</>
|
||||
)}
|
||||
|
||||
{tab == "new" && (
|
||||
recipients.loading ?
|
||||
{tab == "new" &&
|
||||
(recipients.loading ? (
|
||||
<div className="mt-3 flex flex-col w-full h-[188px] justify-center items-center">
|
||||
<LoadingSpinner size='10' color='sky-blue' />
|
||||
<LoadingSpinner size="10" color="sky-blue" />
|
||||
</div>
|
||||
:recipients.data.length < MaxNoOfBanks ?
|
||||
) : recipients.data.length < MaxNoOfBanks ? (
|
||||
<div className="w-full mt-3 rounded-md bg-slate-100">
|
||||
<div className="relative fields w-full flex flex-col p-4">
|
||||
<div className="flex flex-[2] min-h-[52px]">
|
||||
@@ -541,7 +558,12 @@ function NairaWithdraw({
|
||||
Country{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<select
|
||||
<div className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding tracking-[1.5px] flex items-center pointer-events-none">
|
||||
<span className="text-slate-500 text-lg italic">
|
||||
{wallet.walletCountry[0][1]}
|
||||
</span>
|
||||
</div>
|
||||
{/* <select
|
||||
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding tracking-[1.5px]"
|
||||
name="newAccount.country"
|
||||
value={props.values.newAccount?.country}
|
||||
@@ -552,7 +574,7 @@ function NairaWithdraw({
|
||||
>
|
||||
{allCountries.loading ? (
|
||||
<option
|
||||
className="text-slate-500 text-lg"
|
||||
className="text-slate-500 text-lg"
|
||||
value=""
|
||||
>
|
||||
Loading...
|
||||
@@ -585,13 +607,7 @@ function NairaWithdraw({
|
||||
No Options Found!
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
{/* {props.errors.country &&
|
||||
props.touched.country && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.country}
|
||||
</p>
|
||||
)} */}
|
||||
</select> */}
|
||||
</div>
|
||||
|
||||
{/* bank name */}
|
||||
@@ -646,11 +662,6 @@ function NairaWithdraw({
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
{/* {props.errors.bank && props.touched.bank && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.bank}
|
||||
</p>
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -671,16 +682,12 @@ function NairaWithdraw({
|
||||
name="newAccount.accountNumber"
|
||||
placeholder="Account No"
|
||||
maxLength={10}
|
||||
value={props.values.newAccount?.accountNumber}
|
||||
value={
|
||||
props.values.newAccount?.accountNumber
|
||||
}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{/* {props.errors.accountNumber &&
|
||||
props.touched.accountNumber && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.accountNumber}
|
||||
</p>
|
||||
)} */}
|
||||
</div>
|
||||
|
||||
{/* Account Type */}
|
||||
@@ -732,12 +739,6 @@ function NairaWithdraw({
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
{/* {props.errors.accountType &&
|
||||
props.touched.accountType && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.accountType}
|
||||
</p>
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -748,7 +749,8 @@ function NairaWithdraw({
|
||||
htmlFor="newAccount.state"
|
||||
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4]"
|
||||
>
|
||||
State <span className="text-red-500">*</span>
|
||||
State{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<InputCom
|
||||
fieldClass="px-6 tracking-[1.5px]"
|
||||
@@ -760,11 +762,6 @@ function NairaWithdraw({
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{/* {props.errors.state && props.touched.state && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.state}
|
||||
</p>
|
||||
)} */}
|
||||
</div>
|
||||
|
||||
{/* city */}
|
||||
@@ -785,20 +782,15 @@ function NairaWithdraw({
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{/* {props.errors.city && props.touched.city && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.city}
|
||||
</p>
|
||||
)} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* end of inputs for new accounts */}
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
) : (
|
||||
<div className="mt-3 flex w-full h-[188px] justify-center items-center"></div>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="transfer-fund-btn flex justify-end items-center gap-2 py-4">
|
||||
|
||||
@@ -5,7 +5,6 @@ import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
const WalletBox = lazy(() => import("./WalletBox"));
|
||||
|
||||
|
||||
const WalletRoutes = () => {
|
||||
const apiCall = new usersService();
|
||||
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
|
||||
@@ -16,6 +15,12 @@ const WalletRoutes = () => {
|
||||
data: [],
|
||||
});
|
||||
|
||||
const [allCountries, setAllCountries] = useState({
|
||||
// STATE TO HOLD LIST OF COUNTRIES
|
||||
loading: true,
|
||||
data: [],
|
||||
});
|
||||
|
||||
const getPaymentHistory = () => {
|
||||
apiCall
|
||||
.getPaymentHx()
|
||||
@@ -31,14 +36,45 @@ const WalletRoutes = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// FUNCTION TO GET COUNTRIES
|
||||
const getCountry = () => {
|
||||
apiCall
|
||||
.getSignupCountryData()
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 0) {
|
||||
setAllCountries((prev) => ({ loading: false, data: [] }));
|
||||
return;
|
||||
}
|
||||
setAllCountries((prev) => ({
|
||||
loading: false,
|
||||
data: res.data.signup_country,
|
||||
}));
|
||||
})
|
||||
.catch((error) => {
|
||||
setAllCountries((prev) => ({ loading: false, data: [] }));
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getCountry();
|
||||
getPaymentHistory();
|
||||
}, [walletTable]);
|
||||
|
||||
console.log(
|
||||
"Testing all country: ",
|
||||
allCountries,
|
||||
"Testing wallet: ",
|
||||
walletDetails
|
||||
);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<WalletBox wallet={walletDetails} payment={paymentHistory} />
|
||||
<WalletBox
|
||||
wallet={walletDetails}
|
||||
payment={paymentHistory}
|
||||
countries={allCountries.data}
|
||||
/>
|
||||
</Suspense>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import usersService from "../../services/UsersService";
|
||||
import ConfirmNairaWithdraw from "./Popup/ConfirmNairaWithdraw";
|
||||
import NairaWithdraw from "./Popup/NairaWithdraw";
|
||||
@@ -8,7 +8,7 @@ function WalletAction({ walletItem, payment, openPopUp }) {
|
||||
show: false,
|
||||
state: {},
|
||||
}); // DETERMINES WHEN NAIRA WITHDRAWAL POPS UP
|
||||
|
||||
|
||||
const [showConfirmNairaWithdraw, setShowConfirmNairaWithdraw] = useState({
|
||||
show: false,
|
||||
state: {},
|
||||
|
||||
@@ -4,7 +4,7 @@ import WalletItemCard from "./WalletItemCard";
|
||||
/**
|
||||
* Renders a list of wallet items or a loading spinner depending on the state of the `wallet` object.
|
||||
*/
|
||||
export default function WalletBox({ wallet, payment }) {
|
||||
export default function WalletBox({ wallet, payment, countries }) {
|
||||
const { loading, data } = wallet;
|
||||
|
||||
return (
|
||||
@@ -18,7 +18,7 @@ export default function WalletBox({ wallet, payment }) {
|
||||
) : (
|
||||
data.length > 0 && data.map((item) => (
|
||||
<div key={item.wallet_uid} className="lg:w-full h-full mb-10 lg:mb-0">
|
||||
<WalletItemCard walletItem={item} payment={payment} />
|
||||
<WalletItemCard walletItem={item} payment={payment} countries={countries} />
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
|
||||
@@ -10,7 +10,7 @@ import WalletAction from "./WalletAction";
|
||||
/**
|
||||
* Renders a card displaying information about a wallet item.
|
||||
*/
|
||||
export default function WalletItemCard({ walletItem, payment }) {
|
||||
export default function WalletItemCard({ walletItem, payment, countries }) {
|
||||
const { userDetails } = useSelector((state) => state.userDetails);
|
||||
const accountType = userDetails?.account_type === "FAMILY";
|
||||
const dispatch = useDispatch();
|
||||
@@ -35,10 +35,15 @@ export default function WalletItemCard({ walletItem, payment }) {
|
||||
dispatch(tableReload({ type: "WALLETTABLE" }));
|
||||
};
|
||||
|
||||
const currentWalletCurrency = countries
|
||||
.map((country) => country)
|
||||
.filter((country) => country[0] === walletItem.country);
|
||||
|
||||
const image = walletItem.code
|
||||
? `${walletItem.code.toLowerCase()}.svg`
|
||||
: "default.png";
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -88,7 +93,7 @@ export default function WalletItemCard({ walletItem, payment }) {
|
||||
|
||||
{!accountType && (
|
||||
<WalletAction
|
||||
walletItem={walletItem}
|
||||
walletItem={{ ...walletItem, walletCountry: currentWalletCurrency }}
|
||||
payment={payment}
|
||||
openPopUp={openPopUp}
|
||||
/>
|
||||
|
||||
@@ -51,6 +51,7 @@ export default function PersonalInfoTab({
|
||||
coverImgInput,
|
||||
browseCoverImg,
|
||||
coverImgChangHandler,
|
||||
uploadStatus
|
||||
}) {
|
||||
let { userDetails } = useSelector((state) => state.userDetails);
|
||||
|
||||
@@ -361,7 +362,7 @@ export default function PersonalInfoTab({
|
||||
{/* inputs ends here */}
|
||||
</div>
|
||||
</div>
|
||||
{process.env.REACT_APP_SHOW_UPLOAD_PROFILE_PICTURE != 0 &&
|
||||
{/* {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">
|
||||
@@ -417,9 +418,11 @@ export default function PersonalInfoTab({
|
||||
</div>
|
||||
</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>
|
||||
</div>
|
||||
}
|
||||
{/* } */}
|
||||
</div>
|
||||
|
||||
<div className="content-footer w-full">
|
||||
|
||||
@@ -24,10 +24,12 @@ import {
|
||||
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
|
||||
|
||||
@@ -36,12 +38,68 @@ export default function Settings({ faq }) {
|
||||
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) => {
|
||||
setProfileImg(event.target.result);
|
||||
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]);
|
||||
}
|
||||
@@ -61,7 +119,6 @@ export default function Settings({ faq }) {
|
||||
}
|
||||
};
|
||||
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
// Tabs Handling
|
||||
const tabs = [
|
||||
{
|
||||
@@ -113,7 +170,7 @@ export default function Settings({ faq }) {
|
||||
iconName: "page-right",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
id: 9,
|
||||
name: "terms",
|
||||
title: "Terms and Conditions",
|
||||
iconName: "page-right",
|
||||
@@ -217,6 +274,7 @@ export default function Settings({ faq }) {
|
||||
coverImgChangHandler={coverImgChangHandler}
|
||||
browseCoverImg={browseCoverImg}
|
||||
coverImgInput={coverImgInput}
|
||||
uploadStatus={uploadStatus}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -351,7 +351,7 @@ const EditJobPopOut = ({
|
||||
className="w-[120px] h-[40px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
// className='w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'
|
||||
>
|
||||
Edit Job
|
||||
Save
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -578,13 +578,14 @@ class usersService {
|
||||
return this.postAuxEnd("/familyadd", postData);
|
||||
}
|
||||
|
||||
getFamilyUpdate() {
|
||||
getFamilyUpdate(reqdata) {
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
page: 0,
|
||||
limit: 100,
|
||||
...reqdata
|
||||
};
|
||||
return this.postAuxEnd("/familyupdate", postData);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user