Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 11b96e56da | |||
| daad9d18ec | |||
| 3c842f6606 | |||
| 23ef007bb1 | |||
| a9b9a17381 | |||
| d5e66618aa | |||
| 2e89f07ee2 | |||
| 1a51bcf0b5 | |||
| f1ee5150a9 | |||
| 9db7f5c985 | |||
| d56363276b | |||
| 5a9b49559b | |||
| fbc8228977 | |||
| a1140f7006 | |||
| f3561ff0fb | |||
| 42b792ab9d | |||
| 1e3a166172 | |||
| e1c6cb357e | |||
| 1aa64fba1f | |||
| 4f0a6f67c3 | |||
| 4f863f7b1d | |||
| b66f9d7ced | |||
| 493f209162 | |||
| b0a287c6a8 | |||
| 8c00b157ad |
@@ -74,3 +74,9 @@ REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
|
|||||||
|
|
||||||
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
|
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
|
||||||
#apigate.orion.g1.wrenchboard.com:76.209.103.227
|
#apigate.orion.g1.wrenchboard.com:76.209.103.227
|
||||||
|
|
||||||
|
|
||||||
|
REACT_APP_MAX_CREDIT_CARDS=4
|
||||||
|
REACT_APP_MAX_CREDIT_BANK_ACCOUNT=4
|
||||||
|
|
||||||
|
REACT_APP_MAX_FAMILY_MEMBERS=8
|
||||||
@@ -46,3 +46,8 @@ REACT_APP_LOGOUT_TEXT="Sign Out"
|
|||||||
|
|
||||||
REACT_APP_APPLE_SOCIAL_LOGIN=0
|
REACT_APP_APPLE_SOCIAL_LOGIN=0
|
||||||
REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
|
REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
|
||||||
|
|
||||||
|
REACT_APP_MAX_CREDIT_CARDS=4
|
||||||
|
REACT_APP_MAX_CREDIT_BANK_ACCOUNT=4
|
||||||
|
|
||||||
|
REACT_APP_MAX_FAMILY_MEMBERS=8
|
||||||
@@ -52,3 +52,8 @@ REACT_APP_TOTAL_NUM_FILE=4
|
|||||||
REACT_APP_LOGOUT_TEXT="Sign Out"
|
REACT_APP_LOGOUT_TEXT="Sign Out"
|
||||||
REACT_APP_APPLE_SOCIAL_LOGIN=0
|
REACT_APP_APPLE_SOCIAL_LOGIN=0
|
||||||
REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
|
REACT_APP_LINKEDIN_SOCIAL_LOGIN=0
|
||||||
|
|
||||||
|
REACT_APP_MAX_CREDIT_CARDS=4
|
||||||
|
REACT_APP_MAX_CREDIT_BANK_ACCOUNT=4
|
||||||
|
|
||||||
|
REACT_APP_MAX_FAMILY_MEMBERS=8
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
|
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
import AuthLayout from "../AuthLayout";
|
import AuthLayout from "../AuthLayout";
|
||||||
|
|
||||||
export default function SignUp() {
|
export default function SignUp() {
|
||||||
|
const queryParams = new URLSearchParams(location?.search);
|
||||||
|
const country = queryParams.get("cnt")?.toUpperCase();
|
||||||
|
|
||||||
|
const {pathname} = useLocation()
|
||||||
|
const currentPath = country ? `${pathname}?cnt=${country.toLowerCase()}`:pathname // Determines the new pathname is country query params exist
|
||||||
|
|
||||||
const [signUpLoading, setSignUpLoading] = useState(false);
|
const [signUpLoading, setSignUpLoading] = useState(false);
|
||||||
const [checked, setValue] = useState(false);
|
const [checked, setValue] = useState(false);
|
||||||
// for the catch error
|
// for the catch error
|
||||||
const [msgError, setMsgError] = useState("");
|
const [msgError, setMsgError] = useState("");
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [countries, setCountries] = useState([]);
|
const [countries, setCountries] = useState({loading:true, data:[]});
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
country: "",
|
country: country? country : "",
|
||||||
first_name: "",
|
first_name: "",
|
||||||
last_name: "",
|
last_name: "",
|
||||||
email: "",
|
email: "",
|
||||||
@@ -45,9 +51,18 @@ export default function SignUp() {
|
|||||||
try {
|
try {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const { signup_country } = await res.data;
|
const { signup_country } = await res.data;
|
||||||
setCountries(signup_country);
|
// setCountries(signup_country);
|
||||||
|
if(country){ // IF LINK/PATHNAME HAS CNT QUERY VALUE
|
||||||
|
let cnt = signup_country.filter(item => item[0]==country) // test to see country passed in query param exist from list of countries supplied by API
|
||||||
|
if(!cnt.length){ // IF CNT EMPTY, SET FORMDATA COUNTRY BACK TO EMPTY STRING: RE: THIS IS BCOS WE INITAIL SET COUNTRY VALUE IN FORMDATA, IF COUNTRY PARAM IS PRESENT IN LINK
|
||||||
|
setFormData(prev => ({...prev, country: ''}))
|
||||||
|
return setCountries({loading: false, data: signup_country});
|
||||||
|
}
|
||||||
|
return setCountries({loading: false, data: cnt});
|
||||||
|
}
|
||||||
|
setCountries({loading: false, data:signup_country});
|
||||||
} else if (res.data.result !== 100) {
|
} else if (res.data.result !== 100) {
|
||||||
setCountries("Nothing see here!");
|
setCountries({loading: false, data:[]});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
@@ -134,7 +149,7 @@ export default function SignUp() {
|
|||||||
<AuthLayout slogan="Welcome to WrenchBoard">
|
<AuthLayout slogan="Welcome to WrenchBoard">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<Link to="#">
|
<Link to={currentPath}>
|
||||||
<img
|
<img
|
||||||
src={WrenchBoard}
|
src={WrenchBoard}
|
||||||
alt="wrenchboard"
|
alt="wrenchboard"
|
||||||
@@ -172,6 +187,7 @@ export default function SignUp() {
|
|||||||
name="country"
|
name="country"
|
||||||
value={formData.country}
|
value={formData.country}
|
||||||
inputHandler={handleInputChange}
|
inputHandler={handleInputChange}
|
||||||
|
disable={country && countries?.data?.length <= 1 ? true : false}
|
||||||
/>
|
/>
|
||||||
<div className="input-fl-name mb-5 sm:flex w-full sm:space-x-6 ">
|
<div className="input-fl-name mb-5 sm:flex w-full sm:space-x-6 ">
|
||||||
<div className="input-item sm:w-1/2 w-full mb-5 sm:mb-0">
|
<div className="input-item sm:w-1/2 w-full mb-5 sm:mb-0">
|
||||||
@@ -306,6 +322,7 @@ export default function SignUp() {
|
|||||||
<div className="signin-area mb-1">
|
<div className="signin-area mb-1">
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<button
|
<button
|
||||||
|
disabled={countries.loading}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleSignUp}
|
onClick={handleSignUp}
|
||||||
className={`rounded-[0.475rem] mb-6 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={`rounded-[0.475rem] mb-6 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`}
|
||||||
@@ -333,6 +350,7 @@ const SelectOption = ({
|
|||||||
inputHandler,
|
inputHandler,
|
||||||
value,
|
value,
|
||||||
data, // passing the data from parent
|
data, // passing the data from parent
|
||||||
|
disable
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="input-com mb-7">
|
<div className="input-com mb-7">
|
||||||
@@ -346,19 +364,39 @@ const SelectOption = ({
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<select
|
<select
|
||||||
|
disabled={disable}
|
||||||
name={name}
|
name={name}
|
||||||
id={name}
|
id={name}
|
||||||
className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent "
|
className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent "
|
||||||
onChange={inputHandler}
|
onChange={inputHandler}
|
||||||
value={value}
|
value={value}
|
||||||
>
|
>
|
||||||
|
{data?.data?.length > 1 ?
|
||||||
|
<>
|
||||||
<option value={""}>Select your Country</option>
|
<option value={""}>Select your Country</option>
|
||||||
{data?.length > 0 &&
|
{data?.data?.map((item, idx) => (
|
||||||
data?.map((item, idx) => (
|
|
||||||
<option value={item[0]} key={idx}>
|
<option value={item[0]} key={idx}>
|
||||||
{item[1]}
|
{item[1]}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
|
</>
|
||||||
|
:
|
||||||
|
data?.data?.length == 1 ?
|
||||||
|
data?.data?.map((item, idx) => (
|
||||||
|
<option value={item[0]} key={idx}>
|
||||||
|
{item[1]}
|
||||||
|
</option>
|
||||||
|
))
|
||||||
|
:
|
||||||
|
data?.data?.length < 1 && data.loading ?
|
||||||
|
<option value=''>
|
||||||
|
Loading...
|
||||||
|
</option>
|
||||||
|
:
|
||||||
|
<option value=''>
|
||||||
|
No Country Found!
|
||||||
|
</option>
|
||||||
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,29 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import dataImage1 from "../../assets/images/data-table-user-1.png";
|
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||||
import PaginatedList from "../Pagination/PaginatedList";
|
import PaginatedList from "../Pagination/PaginatedList";
|
||||||
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
import familyImage from '../../assets/images/no-family-side.png'
|
import familyImage from "../../assets/images/no-family-side.png";
|
||||||
|
import { formatDateString } from "../../lib";
|
||||||
import localImgLoad from "../../lib/localImgLoad";
|
import localImgLoad from "../../lib/localImgLoad";
|
||||||
|
|
||||||
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
|
export default function FamilyTable({
|
||||||
|
className,
|
||||||
|
familyList,
|
||||||
|
loader,
|
||||||
|
popUpHandler,
|
||||||
|
}) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
const indexOfFirstItem = Number(currentPage);
|
const indexOfFirstItem = Number(currentPage);
|
||||||
const indexOfLastItem =
|
const indexOfLastItem =
|
||||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||||
const currentFamilyList = familyList?.slice(indexOfFirstItem, indexOfLastItem);
|
const currentFamilyList = familyList?.slice(
|
||||||
|
indexOfFirstItem,
|
||||||
|
indexOfLastItem
|
||||||
|
);
|
||||||
|
|
||||||
const handlePagination = (e) => {
|
const handlePagination = (e) => {
|
||||||
handlePagingFunc(e, setCurrentPage);
|
handlePagingFunc(e, setCurrentPage);
|
||||||
@@ -32,15 +40,12 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
|
|||||||
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
|
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
|
||||||
<LoadingSpinner size="16" color="sky-blue" />
|
<LoadingSpinner size="16" color="sky-blue" />
|
||||||
</div>
|
</div>
|
||||||
)
|
) : familyList?.length > 0 ? (
|
||||||
:
|
|
||||||
familyList?.length > 0 ?
|
|
||||||
(
|
|
||||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
|
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
|
||||||
<thead className="sticky top-0">
|
<thead className="sticky top-0">
|
||||||
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
|
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
|
||||||
<th className="py-4">Name</th>
|
<th className="py-4">Name</th>
|
||||||
<th className="py-4 text-center">Last Login</th>
|
{/* <th className="py-4 text-center">Last Login</th> */}
|
||||||
<th className="py-4 text-center">No of Tasks</th>
|
<th className="py-4 text-center">No of Tasks</th>
|
||||||
<th className="py-4 text-right"></th>
|
<th className="py-4 text-right"></th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -55,10 +60,13 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
|
|||||||
last_login,
|
last_login,
|
||||||
task_count,
|
task_count,
|
||||||
family_uid,
|
family_uid,
|
||||||
banner
|
banner,
|
||||||
} = props;
|
} = props;
|
||||||
let addedDate = added?.split(" ")[0];
|
let addedDate = added?.split(" ")[0];
|
||||||
let LoginDate = last_login?.split(" ")[0];
|
let LoginDate =
|
||||||
|
last_login === ""
|
||||||
|
? "never logged in"
|
||||||
|
: formatDateString(last_login);
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
||||||
@@ -84,16 +92,22 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
|
|||||||
{addedDate}
|
{addedDate}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span className="text-sm text-thin-light-gray">
|
||||||
|
Last Login:{" "}
|
||||||
|
<span className="text-purple ml-1">
|
||||||
|
{LoginDate}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="text-center py-4 px-2">
|
{/* <td className="text-center py-4 px-2">
|
||||||
<div className="flex space-x-1 items-center justify-center">
|
<div className="flex space-x-1 items-center justify-center">
|
||||||
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
||||||
{LoginDate}
|
{LoginDate}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td> */}
|
||||||
<td className="text-center py-4 px-2">
|
<td className="text-center py-4 px-2">
|
||||||
<div className="flex space-x-1 items-center justify-center">
|
<div className="flex space-x-1 items-center justify-center">
|
||||||
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
||||||
@@ -116,16 +130,15 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
})
|
})}
|
||||||
}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
)
|
) : (
|
||||||
:
|
|
||||||
(
|
|
||||||
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
|
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
|
||||||
<div className="p-2 w-full md:w-1/2">
|
<div className="p-2 w-full md:w-1/2">
|
||||||
<p className="mb-4 p-3 md:p-16">Add your family, assign tasks, and get the whole team engaged.</p>
|
<p className="mb-4 p-3 md:p-16">
|
||||||
|
Add your family, assign tasks, and get the whole team engaged.
|
||||||
|
</p>
|
||||||
<button
|
<button
|
||||||
onClick={popUpHandler}
|
onClick={popUpHandler}
|
||||||
type="button"
|
type="button"
|
||||||
@@ -135,11 +148,10 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-2 w-full md:w-1/2">
|
<div className="p-2 w-full md:w-1/2">
|
||||||
<img className='w-full' src={familyImage} alt="Add Family" />
|
<img className="w-full" src={familyImage} alt="Add Family" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
{/* PAGINATION BUTTON */}
|
{/* PAGINATION BUTTON */}
|
||||||
<PaginatedList
|
<PaginatedList
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default function InputCom({
|
|||||||
maxLength = 45,
|
maxLength = 45,
|
||||||
minLength = 0,
|
minLength = 0,
|
||||||
direction,
|
direction,
|
||||||
|
tabIndex,
|
||||||
error,
|
error,
|
||||||
}) {
|
}) {
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
@@ -100,6 +101,7 @@ export default function InputCom({
|
|||||||
onInput={onInput}
|
onInput={onInput}
|
||||||
minLength={minLengthValidation()}
|
minLength={minLengthValidation()}
|
||||||
maxLength={maxLengthValidation()}
|
maxLength={maxLengthValidation()}
|
||||||
|
tabIndex={tabIndex}
|
||||||
// pattern={inputPatterns()}
|
// pattern={inputPatterns()}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
readOnly={disable}
|
readOnly={disable}
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ export default function HomeActivities({ className }) {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="header w-full sm:flex justify-between items-center mb-5">
|
<div className="header w-full sm:flex justify-between items-center mb-5">
|
||||||
<div className="flex space-x-2 items-center mb-2 sm:mb-0">
|
<div className="flex space-x-2 items-center mb-4 sm:mb-0">
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="text-center text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
|
||||||
Recent Activities
|
Recent Activities
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,9 +79,13 @@ export default function HomeActivities({ className }) {
|
|||||||
{/*</tr>*/}
|
{/*</tr>*/}
|
||||||
|
|
||||||
{recentActivitiesData.loading ? (
|
{recentActivitiesData.loading ? (
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
<div className="h-[100px] w-full flex justify-center items-center">
|
<div className="h-[100px] w-full flex justify-center items-center">
|
||||||
<LoadingSpinner color="sky-blue" size="16" />
|
<LoadingSpinner color="sky-blue" size="16" />
|
||||||
</div>
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
) : recentActivitiesData.data ? (
|
) : recentActivitiesData.data ? (
|
||||||
recentActivitiesData.data?.map((item) => {
|
recentActivitiesData.data?.map((item) => {
|
||||||
let addedDate = item?.added?.split(" ")[0];
|
let addedDate = item?.added?.split(" ")[0];
|
||||||
@@ -90,15 +94,15 @@ export default function HomeActivities({ className }) {
|
|||||||
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
||||||
key={item.uid}
|
key={item.uid}
|
||||||
>
|
>
|
||||||
<td className=" py-8">
|
<td className="py-3">
|
||||||
<div className="flex space-x-2 items-center">
|
<div className="flex space-x-2 items-center">
|
||||||
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
{/* <div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
||||||
<img
|
<img
|
||||||
src={dataImage1}
|
src={dataImage1}
|
||||||
alt="data"
|
alt="data"
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||||
{item.title ? item.title : "Title"}
|
{item.title ? item.title : "Title"}
|
||||||
@@ -110,8 +114,8 @@ export default function HomeActivities({ className }) {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className="text-right py-4">
|
<td className="text-right py-3">
|
||||||
<div className="flex space-x-1 items-center justify-center">
|
<div className="flex space-x-1 items-center justify-end">
|
||||||
<span className="text-base text-dark-gray dark:text-white font-medium">
|
<span className="text-base text-dark-gray dark:text-white font-medium">
|
||||||
{item.added ? addedDate : ""}
|
{item.added ? addedDate : ""}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ const initialValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function AddFundDollars(props) {
|
function AddFundDollars(props) {
|
||||||
|
let MaxNoOfCards = process.env.REACT_APP_MAX_CREDIT_CARDS // HOLDS THE VALUE OF THE MAX NUMBER OF CARDS USER CAN ADD
|
||||||
|
|
||||||
const apiCall = new usersService();
|
const apiCall = new usersService();
|
||||||
let countryWallet = props.walletItem.country;
|
let countryWallet = props.walletItem.country;
|
||||||
const [tab, setTab] = useState("previous");
|
const [tab, setTab] = useState("previous");
|
||||||
@@ -240,7 +242,7 @@ function AddFundDollars(props) {
|
|||||||
<label
|
<label
|
||||||
onClick={() => setTab("new")}
|
onClick={() => setTab("new")}
|
||||||
htmlFor="new"
|
htmlFor="new"
|
||||||
className="cursor-pointer flex items-center gap-1"
|
className={`cursor-pointer flex items-center gap-1 ${payListCards.data.length >= MaxNoOfCards ? 'pointer-events-none':''}`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="new"
|
id="new"
|
||||||
@@ -251,7 +253,7 @@ function AddFundDollars(props) {
|
|||||||
tab == "new" ? "" : ""
|
tab == "new" ? "" : ""
|
||||||
} tracking-wide transition duration-200`}
|
} tracking-wide transition duration-200`}
|
||||||
/>
|
/>
|
||||||
Add New Card
|
Add New Card {payListCards.data.length >= MaxNoOfCards && <span className="text-[14px] text-red-500">Max Reached</span>}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -314,6 +316,11 @@ function AddFundDollars(props) {
|
|||||||
|
|
||||||
{tab === "new" && (
|
{tab === "new" && (
|
||||||
<div className="new-details w-full max-h-[22rem]">
|
<div className="new-details w-full max-h-[22rem]">
|
||||||
|
{payListCards.loading ?
|
||||||
|
<div className="pt-10 flex w-full h-full justify-center items-center">
|
||||||
|
<LoadingSpinner size='10' color='sky-blue' />
|
||||||
|
</div>
|
||||||
|
:payListCards.data.length < MaxNoOfCards ?
|
||||||
<div className="w-full flex flex-col justify-between">
|
<div className="w-full flex flex-col justify-between">
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
@@ -553,6 +560,9 @@ function AddFundDollars(props) {
|
|||||||
}}
|
}}
|
||||||
</Formik>
|
</Formik>
|
||||||
</div>
|
</div>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,13 +26,17 @@ function AddFundPop({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
// Clear any previous input error and set the loading spinner to be shown
|
||||||
setInputError("");
|
setInputError("");
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: { awaitConfirm: { loader: true } },
|
show: { awaitConfirm: { loader: true } },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Perform validation checks on the input amount
|
||||||
if (!input || input === "0") {
|
if (!input || input === "0") {
|
||||||
|
// Handle input validation error
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: { awaitConfirm: { loader: false } },
|
show: { awaitConfirm: { loader: false } },
|
||||||
@@ -43,12 +47,18 @@ function AddFundPop({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Number(input) * 100 > Number(walletItem?.transfer_limit)) {
|
if (Number(input) * 100 > Number(walletItem?.transfer_limit)) {
|
||||||
|
// Handle credit limit exceeded error
|
||||||
|
setConfirmCredit((prev) => ({
|
||||||
|
...prev,
|
||||||
|
show: { awaitConfirm: { loader: false } },
|
||||||
|
}));
|
||||||
setInputError("Credit limit has been exceeded");
|
setInputError("Credit limit has been exceeded");
|
||||||
setTimeout(() => setInputError(""), 5000);
|
setTimeout(() => setInputError(""), 5000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNaN(input)) {
|
if (isNaN(input)) {
|
||||||
|
// Handle invalid input error
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: { awaitConfirm: { loader: false } },
|
show: { awaitConfirm: { loader: false } },
|
||||||
@@ -58,14 +68,17 @@ function AddFundPop({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare state data for API call
|
||||||
let stateData = {
|
let stateData = {
|
||||||
amount: Number(input) * 100,
|
amount: Number(input) * 100,
|
||||||
currency: walletItem?.code,
|
currency: walletItem?.code,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
// Make API call to start credit process
|
||||||
const res = await apiCall.getStartCredit(stateData);
|
const res = await apiCall.getStartCredit(stateData);
|
||||||
|
|
||||||
if (res.data.internal_return < 0) {
|
if (res.data.internal_return < 0) {
|
||||||
|
// Handle API error
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: { awaitConfirm: { loader: false } },
|
show: { awaitConfirm: { loader: false } },
|
||||||
@@ -75,6 +88,7 @@ function AddFundPop({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update state with response data
|
||||||
const _response = res.data;
|
const _response = res.data;
|
||||||
stateData.amount = Number(input);
|
stateData.amount = Number(input);
|
||||||
stateData.currency = currency;
|
stateData.currency = currency;
|
||||||
@@ -91,6 +105,7 @@ function AddFundPop({
|
|||||||
}));
|
}));
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Handle API call error
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: { awaitConfirm: { loader: false } },
|
show: { awaitConfirm: { loader: false } },
|
||||||
@@ -116,6 +131,7 @@ function AddFundPop({
|
|||||||
placeholder="0"
|
placeholder="0"
|
||||||
value={input}
|
value={input}
|
||||||
inputHandler={handleChange}
|
inputHandler={handleChange}
|
||||||
|
tabIndex={0}
|
||||||
/>
|
/>
|
||||||
<p className="text-base text-red-500 italic h-5">
|
<p className="text-base text-red-500 italic h-5">
|
||||||
{inputError && inputError}
|
{inputError && inputError}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import React from "react";
|
/**
|
||||||
|
* Renders a modal with information about a credit transaction.
|
||||||
|
* @returns {JSX.Element} - The rendered modal component.
|
||||||
|
*/
|
||||||
function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
||||||
const { data } = confirmCredit;
|
const { data } = confirmCredit;
|
||||||
|
const isSuccess =
|
||||||
|
data?.result === "Charge success" || data?.status === "successful";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logout-modal-body w-full flex flex-col items-center">
|
<div className="logout-modal-body w-full flex flex-col items-center">
|
||||||
<div className="content-wrapper w-full h-[32rem]">
|
<div className="content-wrapper w-full h-[32rem]">
|
||||||
@@ -11,60 +16,49 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
<div className="field w-full mb-3 min-h-[45px]">
|
<div className="field w-full mb-3 min-h-[45px]">
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col gap-4 ${
|
className={`flex flex-col gap-4 ${
|
||||||
data?.result !== "Charge success" &&
|
!isSuccess && "h-[328px] items-center justify-center"
|
||||||
"h-[328px] items-center justify-center"
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{/* Success Icon for now */}
|
|
||||||
<div className="flex items-center w-full justify-center">
|
<div className="flex items-center w-full justify-center">
|
||||||
{data?.result == "Charge success" ||
|
|
||||||
data?.status == "successful" ? (
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="100"
|
width="100"
|
||||||
height="100"
|
height="100"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="green"
|
stroke={isSuccess ? "green" : "red"}
|
||||||
stroke-width="2"
|
strokeWidth="2"
|
||||||
stroke-linecap="round"
|
strokeLinecap="round"
|
||||||
stroke-linejoin="round"
|
strokeLinejoin="round"
|
||||||
className="feather feather-check-circle"
|
className={`feather ${
|
||||||
|
isSuccess ? "feather-check-circle" : "feather-x-circle"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
|
{isSuccess ? (
|
||||||
|
<>
|
||||||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
||||||
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
||||||
</svg>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<svg
|
<>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
width="100"
|
|
||||||
height="100"
|
|
||||||
stroke="red"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
className="feather feather-x-circle"
|
|
||||||
>
|
|
||||||
<circle cx="12" cy="12" r="10"></circle>
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
<line x1="15" y1="9" x2="9" y2="15"></line>
|
<line x1="15" y1="9" x2="9" y2="15"></line>
|
||||||
<line x1="9" y1="9" x2="15" y2="15"></line>
|
<line x1="9" y1="9" x2="15" y2="15"></line>
|
||||||
</svg>
|
</>
|
||||||
)}
|
)}
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={`flex items-center`}>
|
<div className="flex items-center">
|
||||||
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{data?.result == "Charge success" ||
|
{isSuccess
|
||||||
data?.status == "successful"
|
|
||||||
? "Credit was Successful!"
|
? "Credit was Successful!"
|
||||||
: "Credit was Unsuccessful"}
|
: "Credit was Unsuccessful"}
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data?.internal_return >= 0 &&
|
{data?.internal_return >= 0 &&
|
||||||
data?.result !== "Charge failed" ? (
|
data?.result !== "Charge failed" && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-8">
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
@@ -82,7 +76,7 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
Wallet Balance
|
Wallet Balance
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{data?.curr_balance}
|
{data?.curr_balance * 0.01}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -95,7 +89,7 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : null}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,84 +1,102 @@
|
|||||||
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
|
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import debounce from "../../../hooks/debounce";
|
import debounce from "../../../hooks/debounce";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
import { tableReload } from "../../../store/TableReloads";
|
|
||||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a React component that displays the description and last four digits of a payment card.
|
||||||
|
*/
|
||||||
function ThePaymentText({ value, type }) {
|
function ThePaymentText({ value, type }) {
|
||||||
const cardDetails = value;
|
const { cardNum } = value;
|
||||||
value.description =
|
let description = value.description;
|
||||||
type === "new"
|
let digits = value.digits;
|
||||||
? cardDetails.cardNum[0] === "4"
|
|
||||||
? "Visa"
|
if (type === "new") {
|
||||||
: cardDetails.cardNum[0] == "5"
|
const firstDigit = cardNum[0];
|
||||||
? "Master"
|
if (firstDigit === "4") {
|
||||||
: "ATM"
|
description = "Visa";
|
||||||
: value.description;
|
} else if (firstDigit === "5") {
|
||||||
value.digits = type === "new" ? cardDetails.cardNum.slice(-4) : value.digits;
|
description = "Master";
|
||||||
|
} else {
|
||||||
|
description = "ATM";
|
||||||
|
}
|
||||||
|
digits = cardNum.slice(-4);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="my-2 flex items-center gap-5">
|
<div className="my-2 flex items-center gap-5">
|
||||||
<div className="card-details flex items-center gap-3">
|
<div className="card-details flex items-center gap-3">
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1 space-x-1">
|
<h1 className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1 space-x-1">
|
||||||
{value.description} Card
|
{description} Card
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
|
<p className="text-xl font-normal text-dark-gray dark:text-white tracking-wide">
|
||||||
Bank **************{value.digits}
|
Bank **************{digits}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the amount of a transaction in a specific currency.
|
||||||
|
* @returns {JSX.Element} - The rendered component.
|
||||||
|
*/
|
||||||
function AmountSection({ currency, amount, country }) {
|
function AmountSection({ currency, amount, country }) {
|
||||||
const formattedAmount = Number(amount).toFixed(2);
|
const formattedAmount = amount?.toFixed(2);
|
||||||
|
const gapClassName = country === "US" ? "gap-14" : "gap-4";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={`flex items-center ${gapClassName}`}>
|
||||||
className={`flex items-center ${country == "US" ? "gap-14" : "gap-4"}`}
|
|
||||||
>
|
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
Amount({currency})
|
Amount({currency})
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{formattedAmount}
|
{formattedAmount}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the transaction fee for a payment.
|
||||||
|
* @returns {JSX.Element} - Rendered JSX displaying the transaction fee with the label "Transaction Fee".
|
||||||
|
*/
|
||||||
function TransactionFeeSection({ currency, fee, country }) {
|
function TransactionFeeSection({ currency, fee, country }) {
|
||||||
const formattedFee = Number(fee).toFixed(2);
|
const formattedFee = (+fee).toFixed(2);
|
||||||
|
const gapClass = country === "US" ? "gap-[2.7rem]" : "gap-4";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={`flex items-center border-b border-gray-600 ${gapClass}`}>
|
||||||
className={`flex items-center border-b border-gray-600 ${
|
|
||||||
country == "US" ? "gap-[2.7rem]" : "gap-4"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
Transaction Fee
|
Transaction Fee
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{formattedFee}
|
{formattedFee}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the total amount by adding the `amount` and `fee` values together.
|
||||||
|
* Formats the total amount to two decimal places and displays it.
|
||||||
|
* @returns {JSX.Element} - The TotalSection component.
|
||||||
|
*/
|
||||||
function TotalSection({ currency, amount, fee, country }) {
|
function TotalSection({ currency, amount, fee, country }) {
|
||||||
const total = Number(amount) + Number(fee);
|
const total = Number(amount) + Number(fee);
|
||||||
const formattedTotal = total.toFixed(2);
|
const formattedTotal = total?.toFixed(2);
|
||||||
|
|
||||||
|
const gap = country === "US" ? "gap-[8rem]" : "gap-[6.3rem]";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={`flex items-center ${gap}`}>
|
||||||
className={`flex items-center ${
|
|
||||||
country == "US" ? "gap-[8rem]" : "gap-[6.3rem]"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
Total
|
Total
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{formattedTotal}
|
{formattedTotal}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -102,8 +120,6 @@ function ConfirmAddFund({
|
|||||||
|
|
||||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const [requestStatus, setRequestStatus] = useState({
|
const [requestStatus, setRequestStatus] = useState({
|
||||||
message: "",
|
message: "",
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -127,7 +143,7 @@ function ConfirmAddFund({
|
|||||||
logo: "https://www.wrenchboard.com/assets/images/wrench-500-500-icon.png",
|
logo: "https://www.wrenchboard.com/assets/images/wrench-500-500-icon.png",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
//debugger;
|
|
||||||
const fwConfig = {
|
const fwConfig = {
|
||||||
...config,
|
...config,
|
||||||
text: "Proceed",
|
text: "Proceed",
|
||||||
@@ -162,8 +178,6 @@ function ConfirmAddFund({
|
|||||||
status: false,
|
status: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return dispatch(tableReload({ type: "WALLETTABLE" }));
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setRequestStatus({
|
setRequestStatus({
|
||||||
@@ -188,10 +202,27 @@ function ConfirmAddFund({
|
|||||||
|
|
||||||
const debouncedSuccessPayment = debounce(onSuccessPayment, 5000);
|
const debouncedSuccessPayment = debounce(onSuccessPayment, 5000);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the process of making a payment using a previously saved card.
|
||||||
|
* Updates the state to show a loader while the payment is being processed,
|
||||||
|
* sends a request to the server to make the payment, and updates the state with the response.
|
||||||
|
* If the payment is successful, it also dispatches an action to reload the wallet table.
|
||||||
|
*/
|
||||||
const handlePrevCard = async () => {
|
const handlePrevCard = async () => {
|
||||||
|
try {
|
||||||
|
// Show loader while the payment is being processed
|
||||||
|
setConfirmCredit((prev) => ({
|
||||||
|
...prev,
|
||||||
|
show: {
|
||||||
|
acceptConfirm: { loader: true },
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Extract necessary data from confirmCredit and confirmCardDetails objects
|
||||||
const { amount, credit_reference, currency } = __confirmData;
|
const { amount, credit_reference, currency } = __confirmData;
|
||||||
const { card_uid } = __confirmCardDetails;
|
const { card_uid } = __confirmCardDetails;
|
||||||
|
|
||||||
|
// Create request data object with required parameters for making the payment
|
||||||
const reqData = {
|
const reqData = {
|
||||||
amount: amount * 100,
|
amount: amount * 100,
|
||||||
card_uid,
|
card_uid,
|
||||||
@@ -199,16 +230,12 @@ function ConfirmAddFund({
|
|||||||
currency,
|
currency,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
// Send request to server to make the payment using getPaidPrevCard method of usersService
|
||||||
setConfirmCredit((prev) => ({
|
|
||||||
...prev,
|
|
||||||
show: {
|
|
||||||
acceptConfirm: { loader: true },
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
const res = await apiURL.getPaidPrevCard(reqData);
|
const res = await apiURL.getPaidPrevCard(reqData);
|
||||||
const _response = res.data;
|
const _response = res.data;
|
||||||
if (res.data.internal_return < 0) {
|
|
||||||
|
// If internal_return value in the response is less than 0, hide the loader and return
|
||||||
|
if (_response.internal_return < 0) {
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: {
|
show: {
|
||||||
@@ -218,6 +245,7 @@ function ConfirmAddFund({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update state to show the acceptConfirm state and the response data
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@@ -227,9 +255,9 @@ function ConfirmAddFund({
|
|||||||
},
|
},
|
||||||
data: _response,
|
data: _response,
|
||||||
}));
|
}));
|
||||||
dispatch(tableReload({ type: "WALLETTABLE" }));
|
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Handle error and hide the loader
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: {
|
show: {
|
||||||
@@ -240,11 +268,26 @@ function ConfirmAddFund({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the payment process when a new card is used.
|
||||||
|
* @async
|
||||||
|
*/
|
||||||
const handleNewCard = async () => {
|
const handleNewCard = async () => {
|
||||||
|
try {
|
||||||
|
// Extract necessary data from __confirmData and __confirmCardDetails
|
||||||
const { amount, credit_reference, uid } = __confirmData;
|
const { amount, credit_reference, uid } = __confirmData;
|
||||||
const { address, cardNum, cvv, expirationMonth, expirationYear } =
|
const { address, cardNum, cvv, expirationMonth, expirationYear } =
|
||||||
__confirmCardDetails;
|
__confirmCardDetails;
|
||||||
|
|
||||||
|
// Set loading state to indicate payment is being processed
|
||||||
|
setConfirmCredit((prev) => ({
|
||||||
|
...prev,
|
||||||
|
show: {
|
||||||
|
acceptConfirm: { loader: true },
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Prepare request data
|
||||||
const reqData = {
|
const reqData = {
|
||||||
amount: amount * 100,
|
amount: amount * 100,
|
||||||
cardnumber: cardNum.replace(/\s/g, ""),
|
cardnumber: cardNum.replace(/\s/g, ""),
|
||||||
@@ -257,16 +300,13 @@ function ConfirmAddFund({
|
|||||||
uid,
|
uid,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
// Send request to server to process payment
|
||||||
setConfirmCredit((prev) => ({
|
|
||||||
...prev,
|
|
||||||
show: {
|
|
||||||
acceptConfirm: { loader: true },
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
const res = await apiURL.getPaidNewCard(reqData);
|
const res = await apiURL.getPaidNewCard(reqData);
|
||||||
const _response = res.data;
|
const _response = res.data;
|
||||||
|
|
||||||
|
// Handle response from server
|
||||||
if (res.data.internal_return < 0) {
|
if (res.data.internal_return < 0) {
|
||||||
|
// Payment could not be completed
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: {
|
show: {
|
||||||
@@ -275,9 +315,8 @@ function ConfirmAddFund({
|
|||||||
},
|
},
|
||||||
data: _response,
|
data: _response,
|
||||||
}));
|
}));
|
||||||
return;
|
} else {
|
||||||
}
|
// Payment was successful
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@@ -287,9 +326,10 @@ function ConfirmAddFund({
|
|||||||
},
|
},
|
||||||
data: _response,
|
data: _response,
|
||||||
}));
|
}));
|
||||||
dispatch(tableReload({ type: "WALLETTABLE" }));
|
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Handle error during payment process
|
||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: {
|
show: {
|
||||||
@@ -362,7 +402,7 @@ function ConfirmAddFund({
|
|||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
Reference No
|
Reference No
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{__confirmData?.credit_reference}
|
{__confirmData?.credit_reference}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import CompleteConfirmCredit from "./CompleteConfirmCredit";
|
|||||||
import ConfirmAddFund from "./ConfirmAddFund";
|
import ConfirmAddFund from "./ConfirmAddFund";
|
||||||
|
|
||||||
const CreditPopup = ({ details, onClose, situation, walletItem }) => {
|
const CreditPopup = ({ details, onClose, situation, walletItem }) => {
|
||||||
let [input, setInput] = useState("");
|
const [input, setInput] = useState("");
|
||||||
const [confirmCredit, setConfirmCredit] = useState({
|
const [confirmCredit, setConfirmCredit] = useState({
|
||||||
show: {
|
show: {
|
||||||
awaitConfirm: { loader: false, state: false },
|
awaitConfirm: { loader: false, state: false },
|
||||||
@@ -15,6 +15,20 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
|
|||||||
data: {},
|
data: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getTitle = () => {
|
||||||
|
if (confirmCredit?.show?.acceptConfirm?.state) {
|
||||||
|
if (confirmCredit?.data?.internal_return < 0) {
|
||||||
|
return "Credit Unsuccessful";
|
||||||
|
} else {
|
||||||
|
return "Credit Add Completed";
|
||||||
|
}
|
||||||
|
} else if (confirmCredit?.show?.awaitConfirm?.state) {
|
||||||
|
return "Confirm Credit Add";
|
||||||
|
} else {
|
||||||
|
return "Add Credit";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalCom
|
<ModalCom
|
||||||
action={onClose}
|
action={onClose}
|
||||||
@@ -24,23 +38,9 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
|
|||||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||||
{confirmCredit?.show?.acceptConfirm?.state &&
|
|
||||||
(confirmCredit?.data?.internal_return < 0
|
|
||||||
// ||
|
|
||||||
// confirmCredit?.data?.status !== "successful"
|
|
||||||
) ? (
|
|
||||||
"Credit Unsuccessful"
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{confirmCredit?.show?.acceptConfirm?.loader
|
{confirmCredit?.show?.acceptConfirm?.loader
|
||||||
? "Confirming Credit..."
|
? "Confirming Credit..."
|
||||||
: confirmCredit?.show?.awaitConfirm?.state
|
: getTitle()}
|
||||||
? "Confirm Credit Add"
|
|
||||||
: confirmCredit?.show?.acceptConfirm?.state
|
|
||||||
? "Credit Add Completed"
|
|
||||||
: "Add Credit"}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ function NairaWithdraw({
|
|||||||
state,
|
state,
|
||||||
setShowConfirmNairaWithdraw,
|
setShowConfirmNairaWithdraw,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
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 apiCall = new usersService();
|
||||||
const [tab, setTab] = useState("previous");
|
const [tab, setTab] = useState("previous");
|
||||||
let [requestStatus, setRequestStatus] = useState(false);
|
let [requestStatus, setRequestStatus] = useState(false);
|
||||||
@@ -422,7 +424,7 @@ function NairaWithdraw({
|
|||||||
<label
|
<label
|
||||||
onClick={() => setTab("new")}
|
onClick={() => setTab("new")}
|
||||||
htmlFor="new"
|
htmlFor="new"
|
||||||
className="cursor-pointer flex items-center gap-1"
|
className={`cursor-pointer flex items-center gap-1 ${recipients.data.length >= MaxNoOfBanks ? 'pointer-events-none':''}`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="new"
|
id="new"
|
||||||
@@ -434,7 +436,7 @@ function NairaWithdraw({
|
|||||||
tab == "new" ? "" : ""
|
tab == "new" ? "" : ""
|
||||||
} tracking-wide transition duration-200`}
|
} tracking-wide transition duration-200`}
|
||||||
/>
|
/>
|
||||||
New Account{" "}
|
New Account{" "} {recipients.data.length >= MaxNoOfBanks && <span className="text-[14px] text-red-500">Max Reached</span>}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -522,6 +524,11 @@ function NairaWithdraw({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{tab == "new" && (
|
{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' />
|
||||||
|
</div>
|
||||||
|
:recipients.data.length < MaxNoOfBanks ?
|
||||||
<div className="w-full mt-3 rounded-md bg-slate-100">
|
<div className="w-full mt-3 rounded-md bg-slate-100">
|
||||||
<div className="relative fields w-full flex flex-col p-4">
|
<div className="relative fields w-full flex flex-col p-4">
|
||||||
<div className="flex flex-[2] min-h-[52px]">
|
<div className="flex flex-[2] min-h-[52px]">
|
||||||
@@ -789,6 +796,8 @@ function NairaWithdraw({
|
|||||||
{/* end of inputs for new accounts */}
|
{/* end of inputs for new accounts */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
:
|
||||||
|
<div className="mt-3 flex w-full h-[188px] justify-center items-center"></div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import WalletItemCard from "./WalletItemCard";
|
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 }) {
|
||||||
|
const { loading, data } = wallet;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<div className="my-wallet-wrapper w-full mb-10">
|
<div className="my-wallet-wrapper w-full mb-10">
|
||||||
<div className="main-wrapper w-full">
|
<div className="main-wrapper w-full">
|
||||||
<div className="balance-inquery w-full lg:grid grid-cols-[repeat(auto-fill,_minmax(325px,_1fr))] gap-5 mb-11 h-[22rem]">
|
<div className="balance-inquery w-full lg:grid grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-[22rem]">
|
||||||
{wallet.loading ? (
|
{loading ? (
|
||||||
<div className="w-full h-full flex items-center justify-center">
|
<div className="w-full h-full flex items-center justify-center">
|
||||||
<LoadingSpinner size="16" color="sky-blue" />
|
<LoadingSpinner size="16" color="sky-blue" />
|
||||||
</div>
|
</div>
|
||||||
) : wallet.data.length ? (
|
) : (
|
||||||
wallet.data.map((item, index) => (
|
data.length > 0 && data.map((item) => (
|
||||||
<div key={item.wallet_uid} className="lg:w-full h-full mb-10 lg:mb-0">
|
<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} />
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
) : null}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ export default function WalletHeader(props) {
|
|||||||
//props.myWalletList.result_list
|
//props.myWalletList.result_list
|
||||||
let { pathname } = useLocation();
|
let { pathname } = useLocation();
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
|
||||||
|
const onWalletClick = () => {
|
||||||
|
if (pathname == "/my-wallet")
|
||||||
|
props.setBalanceDropdown.toggle();
|
||||||
|
else navigate("/my-wallet", { replace: true });
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
|
<div className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
|
||||||
@@ -49,6 +55,7 @@ export default function WalletHeader(props) {
|
|||||||
<li
|
<li
|
||||||
key={index}
|
key={index}
|
||||||
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
|
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
|
||||||
|
onClick={onWalletClick}
|
||||||
>
|
>
|
||||||
<div className="sm:flex justify-between items-center">
|
<div className="sm:flex justify-between items-center">
|
||||||
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
|
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
|
||||||
@@ -56,7 +63,7 @@ export default function WalletHeader(props) {
|
|||||||
<img src={localImgLoad(`images/currency/${image}`)} className="w-14 h-14" alt="" />
|
<img src={localImgLoad(`images/currency/${image}`)} className="w-14 h-14" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div className="name">
|
<div className="name">
|
||||||
<p className="text-base text-dark-gray dark:text-white font-medium">
|
<p className="text-2xl font-bold text-dark-gray dark:text-white">
|
||||||
{value.description}
|
{value.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -178,11 +185,7 @@ export default function WalletHeader(props) {
|
|||||||
</button> */}
|
</button> */}
|
||||||
<Link
|
<Link
|
||||||
to="/my-wallet"
|
to="/my-wallet"
|
||||||
onClick={() => {
|
onClick={onWalletClick}
|
||||||
if (pathname == "/my-wallet")
|
|
||||||
props.setBalanceDropdown.toggle();
|
|
||||||
else navigate("/my-wallet", { replace: true });
|
|
||||||
}}
|
|
||||||
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
className="w-[122px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
>
|
>
|
||||||
Manage
|
Manage
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import background from "../../assets/images/bg-sky-blue.jpg"; //shape/balance-bg.svg";
|
import background from "../../assets/images/bg-sky-blue.jpg"; //shape/balance-bg.svg";
|
||||||
import localImgLoad from "../../lib/localImgLoad";
|
import localImgLoad from "../../lib/localImgLoad";
|
||||||
|
import { tableReload } from "../../store/TableReloads";
|
||||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||||
import CreditPopup from "./Popup/CreditPopup";
|
import CreditPopup from "./Popup/CreditPopup";
|
||||||
import WalletAction from "./WalletAction";
|
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 }) {
|
||||||
// const [eth] = useState(90);
|
const { userDetails } = useSelector((state) => state.userDetails);
|
||||||
// const [btc] = useState(85);
|
const accountType = userDetails?.account_type === 'FAMILY';
|
||||||
// const [ltc] = useState(20);
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
|
||||||
let accountType = userDetails?.account_type == "FAMILY";
|
|
||||||
|
|
||||||
// Credit popup
|
|
||||||
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
|
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the credit popup.
|
||||||
|
* @param {Object} value - The value object.
|
||||||
|
*/
|
||||||
const openPopUp = (value) => {
|
const openPopUp = (value) => {
|
||||||
setCreditPopup({
|
setCreditPopup({
|
||||||
show: true,
|
show: true,
|
||||||
@@ -23,29 +27,32 @@ export default function WalletItemCard({ walletItem, payment }) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the credit popup and dispatches a table reload action.
|
||||||
|
*/
|
||||||
const closePopUp = () => {
|
const closePopUp = () => {
|
||||||
setCreditPopup({ show: false, data: {} });
|
setCreditPopup({ show: false, data: {} });
|
||||||
|
dispatch(tableReload({ type: 'WALLETTABLE' }));
|
||||||
};
|
};
|
||||||
|
|
||||||
let image = walletItem.code
|
const image = walletItem.code
|
||||||
? `${walletItem.code.toLocaleLowerCase()}.svg`
|
? `${walletItem.code.toLowerCase()}.svg`
|
||||||
: "default.png"; // HOLDS THE VALUE NAME PROPERTY FOR IMAGE ICON
|
: 'default.png';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 px-8 pt-9 pb-20`}
|
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between"
|
||||||
style={{
|
style={{
|
||||||
background: `url(${background}) 0% 0% / cover no-repeat`,
|
background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <div className="w-[350px]"> */}
|
|
||||||
<div className="wallet w-full flex justify-between items-start gap-3">
|
<div className="wallet w-full flex justify-between items-start gap-3">
|
||||||
<div className="min-w-[100px] min-h-[100px] max-w-[100px] max-h-[100px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
|
<div className="min-w-[100px] min-h-[100px] max-w-[150px] max-h-[150px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
|
||||||
<img
|
<img
|
||||||
src={localImgLoad(`images/currency/${image}`)}
|
src={localImgLoad(`images/currency/${image}`)}
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
alt="curreny-icon"
|
alt="currency-icon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="balance w-full mt-2 flex justify-center">
|
<div className="balance w-full mt-2 flex justify-center">
|
||||||
@@ -53,41 +60,41 @@ export default function WalletItemCard({ walletItem, payment }) {
|
|||||||
<p className="text-lg text-white opacity-[70%] tracking-wide mb-6">
|
<p className="text-lg text-white opacity-[70%] tracking-wide mb-6">
|
||||||
Current Balance
|
Current Balance
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[44px] font-bold text-white tracking-wide leading-10 mb-2">
|
<p className="text-[44px] lg:text-[62px] font-bold text-white tracking-wide leading-10 xxs:scale-100 lg:scale-100 xl:scale-125">
|
||||||
{PriceFormatter(
|
{PriceFormatter(
|
||||||
walletItem.amount * 0.01,
|
walletItem.amount * 0.01,
|
||||||
walletItem.code,
|
walletItem.code,
|
||||||
undefined,
|
undefined,
|
||||||
"text-[2rem]"
|
'text-[2rem]'
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="my-5 text-lg text-white tracking-wide flex justify-center items-center gap-2">
|
<p className="text-lg text-white tracking-wide flex justify-center items-center gap-8">
|
||||||
HOLDINGS :{" "}
|
HOLDINGS :{' '}
|
||||||
<span className="mt-1">
|
<span className="xxs:scale-100 lg:scale-100 xl:scale-125">
|
||||||
{PriceFormatter(
|
{PriceFormatter(
|
||||||
walletItem.escrow * 0.01,
|
walletItem.escrow * 0.01,
|
||||||
walletItem.code,
|
walletItem.code,
|
||||||
undefined,
|
undefined,
|
||||||
"text-[2rem]"
|
'text-[2rem]'
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
{/* for white underline */}
|
|
||||||
<div className="my-2 w-full h-[1px] bg-white"></div>
|
<div className="my-2 w-full h-[1px] bg-white"></div>
|
||||||
|
|
||||||
{!accountType ? (
|
{!accountType && (
|
||||||
<WalletAction
|
<WalletAction
|
||||||
walletItem={walletItem}
|
walletItem={walletItem}
|
||||||
payment={payment}
|
payment={payment}
|
||||||
openPopUp={openPopUp}
|
openPopUp={openPopUp}
|
||||||
/>
|
/>
|
||||||
) : null}
|
)}
|
||||||
{/* </div> */}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{creditPopup.show && (
|
{creditPopup.show && (
|
||||||
<CreditPopup
|
<CreditPopup
|
||||||
details={creditPopup.data}
|
details={creditPopup.data}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ export default function Layout({ children }) {
|
|||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<circle cx="68" cy="68" r="68" fill="#5356FB" />
|
<circle cx="68" cy="68" r="68" fill="#4687ba" />
|
||||||
<path
|
<path
|
||||||
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
|
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ function DeleteCardPopout({action, situation, data, setReloadCardList}) {
|
|||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<circle cx="68" cy="68" r="68" fill="#5356FB" />
|
<circle cx="68" cy="68" r="68" fill="#4687ba" />
|
||||||
<path
|
<path
|
||||||
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
|
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ function DeleteJobPopout({ details, onClose, situation }) {
|
|||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<circle cx="68" cy="68" r="68" fill="#5356FB" />
|
<circle cx="68" cy="68" r="68" fill="#4687ba" />
|
||||||
<path
|
<path
|
||||||
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
|
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
|
|||||||
+24
-1
@@ -1,4 +1,4 @@
|
|||||||
export default function formattedDate(dateString) {
|
export function formattedDate(dateString) {
|
||||||
const parts = dateString.split(" ");
|
const parts = dateString.split(" ");
|
||||||
const datePart = parts[0];
|
const datePart = parts[0];
|
||||||
const timePart = parts[1];
|
const timePart = parts[1];
|
||||||
@@ -15,3 +15,26 @@ export default function formattedDate(dateString) {
|
|||||||
|
|
||||||
return new Date(year, month - 1, day, hour, minute);
|
return new Date(year, month - 1, day, hour, minute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatDateString(inputDateString) {
|
||||||
|
// Parse the input date string
|
||||||
|
const parsedDate = new Date(inputDateString);
|
||||||
|
|
||||||
|
// Get day, month, year, and time components
|
||||||
|
const day = parsedDate.toLocaleDateString(undefined, { weekday: "long" });
|
||||||
|
const month = parsedDate.toLocaleDateString(undefined, { month: "short" });
|
||||||
|
const date = parsedDate.toLocaleDateString(undefined, { day: "numeric" });
|
||||||
|
const year = parsedDate.toLocaleDateString(undefined, { year: "numeric" });
|
||||||
|
|
||||||
|
// Get the time in 12-hour format with 'AM' or 'PM'
|
||||||
|
const hours = parsedDate.getHours();
|
||||||
|
const minutes = parsedDate.getMinutes();
|
||||||
|
const time = `${hours % 12 || 12}:${minutes.toString().padStart(2, "0")} ${
|
||||||
|
hours < 12 ? "AM" : "PM"
|
||||||
|
}`;
|
||||||
|
|
||||||
|
// Combine the components into the desired format
|
||||||
|
const formattedDate = `${day}, ${month} ${date} ${year} - ${time}`;
|
||||||
|
|
||||||
|
return formattedDate;
|
||||||
|
}
|
||||||
+2
-1
@@ -1,12 +1,13 @@
|
|||||||
import ClearCookies from "./ClearCookies";
|
import ClearCookies from "./ClearCookies";
|
||||||
import checkAndSetError from "./checkAndSetError";
|
import checkAndSetError from "./checkAndSetError";
|
||||||
import formattedDate from "./fomattedDate";
|
import { formatDateString, formattedDate } from "./fomattedDate";
|
||||||
import getTimeAgo from "./getTimeAgo";
|
import getTimeAgo from "./getTimeAgo";
|
||||||
import localImgLoad from "./localImgLoad";
|
import localImgLoad from "./localImgLoad";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ClearCookies,
|
ClearCookies,
|
||||||
checkAndSetError,
|
checkAndSetError,
|
||||||
|
formatDateString,
|
||||||
formattedDate,
|
formattedDate,
|
||||||
getTimeAgo,
|
getTimeAgo,
|
||||||
localImgLoad,
|
localImgLoad,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
|||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { Navigate, Outlet, useNavigate } from "react-router-dom";
|
import { Navigate, Outlet, useNavigate } from "react-router-dom";
|
||||||
import LoadingSpinner from "../components/Spinners/LoadingSpinner";
|
import LoadingSpinner from "../components/Spinners/LoadingSpinner";
|
||||||
import formattedDate from "../lib/fomattedDate";
|
|
||||||
import usersService from "../services/UsersService";
|
import usersService from "../services/UsersService";
|
||||||
import { commonHeadBanner } from "../store/CommonHeadBanner";
|
import { commonHeadBanner } from "../store/CommonHeadBanner";
|
||||||
import { recentActivitiesData } from "../store/RecentActivitiesData";
|
import { recentActivitiesData } from "../store/RecentActivitiesData";
|
||||||
@@ -11,6 +10,7 @@ import { updateJobs } from "../store/jobLists";
|
|||||||
import { updateNotifications } from "../store/notifications";
|
import { updateNotifications } from "../store/notifications";
|
||||||
import { updateUserJobList } from "../store/userJobList";
|
import { updateUserJobList } from "../store/userJobList";
|
||||||
import { updateWalletDetails } from "../store/walletDetails";
|
import { updateWalletDetails } from "../store/walletDetails";
|
||||||
|
import { formattedDate } from "../lib";
|
||||||
|
|
||||||
const AuthRoute = ({ redirectPath = "/login", children }) => {
|
const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||||
const apiCall = useMemo(() => new usersService(), []);
|
const apiCall = useMemo(() => new usersService(), []);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from "react";
|
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
|
|
||||||
class SiteService {
|
class SiteService {
|
||||||
@@ -17,7 +16,7 @@ class SiteService {
|
|||||||
|
|
||||||
// Contact Data{POST}
|
// Contact Data{POST}
|
||||||
contactData() {
|
contactData() {
|
||||||
return this.postAuxEnd("/contact", null)
|
return this.postAuxEnd("/contact", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
faqData() {
|
faqData() {
|
||||||
@@ -29,7 +28,14 @@ class SiteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addFamily(reqData) {
|
addFamily(reqData) {
|
||||||
return this.postAuxEnd('/familyadd', reqData)
|
var postData = {
|
||||||
|
uid: localStorage.getItem("uid"),
|
||||||
|
member_id: localStorage.getItem("member_id"),
|
||||||
|
sessionid: localStorage.getItem("session_token"),
|
||||||
|
action: 22015,
|
||||||
|
...reqData,
|
||||||
|
};
|
||||||
|
return this.postAuxEnd("/familyadd", postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
familyListings(reqData) {
|
familyListings(reqData) {
|
||||||
@@ -37,9 +43,9 @@ class SiteService {
|
|||||||
uid: localStorage.getItem("uid"),
|
uid: localStorage.getItem("uid"),
|
||||||
member_id: localStorage.getItem("member_id"),
|
member_id: localStorage.getItem("member_id"),
|
||||||
sessionid: localStorage.getItem("session_token"),
|
sessionid: localStorage.getItem("session_token"),
|
||||||
...reqData
|
...reqData,
|
||||||
};
|
};
|
||||||
return this.postAuxEnd('/familylist', postData)
|
return this.postAuxEnd("/familylist", postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
assignJobTask(reqData) {
|
assignJobTask(reqData) {
|
||||||
@@ -47,9 +53,9 @@ class SiteService {
|
|||||||
uid: localStorage.getItem("uid"),
|
uid: localStorage.getItem("uid"),
|
||||||
member_id: localStorage.getItem("member_id"),
|
member_id: localStorage.getItem("member_id"),
|
||||||
sessionid: localStorage.getItem("session_token"),
|
sessionid: localStorage.getItem("session_token"),
|
||||||
...reqData
|
...reqData,
|
||||||
};
|
};
|
||||||
return this.postAuxEnd('/assigntask', postData)
|
return this.postAuxEnd("/assigntask", postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------- -----
|
//---------------------------------------- -----
|
||||||
|
|||||||
Reference in New Issue
Block a user