480 lines
26 KiB
React
480 lines
26 KiB
React
import React,{useEffect, useState} from 'react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import InputCom from '../Helpers/Inputs/InputCom';
|
|
import PaginatedList from '../Pagination/PaginatedList';
|
|
import { handlePagingFunc } from '../Pagination/HandlePagination';
|
|
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
|
import usersService from '../../services/UsersService';
|
|
|
|
import { Form, Formik } from "formik";
|
|
import * as Yup from "yup";
|
|
|
|
const validationSchema = Yup.object().shape({
|
|
name: Yup.string()
|
|
.min(3, "Minimum 3 characters")
|
|
.max(50, "Maximum 50 characters")
|
|
.required("Name is required"),
|
|
cardNum: Yup.string()
|
|
.min(3, "Minimum 3 characters")
|
|
.max(25, "Maximum 25 characters")
|
|
.required("Card Number is required"),
|
|
code: Yup.string()
|
|
.min(3, "Minimum 3 characters")
|
|
.max(25, "Maximum 25 characters")
|
|
.required("Postal Code is required"),
|
|
state: Yup.string()
|
|
.min(3, "Minimum 3 characters")
|
|
.max(25, "Maximum 25 characters")
|
|
.required("State is required"),
|
|
address: Yup.string()
|
|
.min(3, "Minimum 3 characters")
|
|
.max(50, "Maximum 50 characters")
|
|
.required("Address is required"),
|
|
expirationYear: Yup.string()
|
|
.min(4, "Minimum 4 characters")
|
|
.max(4, "Maximum 4 characters")
|
|
.required("Expiration Year is required"),
|
|
expirationMonth: Yup.string()
|
|
.min(1, "Minimum 1 characters")
|
|
.max(2, "Maximum 2 characters")
|
|
.required("Expiration Month is required"),
|
|
cvv: Yup.string()
|
|
.min(3, "Minimum 3 characters")
|
|
.max(4, "Maximum 4 characters")
|
|
.required("CVV Year is required"),
|
|
});
|
|
|
|
const initialValues = {
|
|
name: '',
|
|
cardNum: '',
|
|
code: '',
|
|
state: '',
|
|
address: '',
|
|
expirationYear: '',
|
|
expirationMonth: '',
|
|
cvv: ''
|
|
};
|
|
|
|
|
|
function AddFundDollars(props) {
|
|
const navigate = useNavigate()
|
|
let apiCall = new usersService()
|
|
|
|
let [tab, setTab] = useState("previous"); //STATE FOR SWITCHING BETWEEN TABS
|
|
|
|
let [prevCardDetails, setPrevCardDetails] = useState(null) // STATE TO HOLD PREVIOUS CARD SELECTED
|
|
|
|
let [payListCard, setPayListCard] = useState({loading: true, data:[]}) //USER PREVIOUS CARDS
|
|
|
|
const [currentPage, setCurrentPage] = useState(0);
|
|
const indexOfFirstItem = Number(currentPage);
|
|
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
|
const currentPreviousCards = payListCard?.data?.slice(indexOfFirstItem, indexOfLastItem);
|
|
|
|
const handlePagination = (e) => {
|
|
handlePagingFunc(e,setCurrentPage)
|
|
}
|
|
|
|
// FUNCTION TO SUBMIT
|
|
const handleSubmit = (values, helpers) => {
|
|
props.setInputError('')
|
|
if(!props.input || props.input == '0'){
|
|
props.setInputError('Please Enter Amount')
|
|
return setTimeout(()=>{props.setInputError('')}, 5000)
|
|
}
|
|
|
|
if(isNaN(props.input)){
|
|
props.setInputError('Amount must be a Number')
|
|
return setTimeout(()=>{props.setInputError('')}, 5000)
|
|
}
|
|
if(tab == 'previous'){
|
|
const stateData = {amount: Number(props.input), currency: 'dollars'}
|
|
navigate('confirm-add-fund', {state: stateData}) // State will change later dummy for now
|
|
}
|
|
if(tab == 'new'){
|
|
const stateData = {amount: Number(props.input), currency: 'dollars', ...values}
|
|
navigate('confirm-add-fund', {state: stateData}) // State will change later dummy for now
|
|
}
|
|
props.setInput('')
|
|
}
|
|
|
|
useEffect(()=>{
|
|
apiCall.payListCard().then(res => {
|
|
setPayListCard({loading: false, data: res.data.result_list})
|
|
}).catch(err => {
|
|
console.log('PAYCARDLIST ERROR', err)
|
|
setPayListCard({loading: false, data: []})
|
|
})
|
|
}, [])
|
|
|
|
return (
|
|
<>
|
|
<h1 className='mb-2 text-xl font-bold text-dark-gray dark:text-white'>Payment Method</h1>
|
|
<div className="w-full">
|
|
{/* switch button */}
|
|
<div className="my-1 flex items-center border-b border-slate-300">
|
|
<button
|
|
name="previous"
|
|
onClick={(e) => setTab(e.target.name)}
|
|
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
|
|
tab == "previous" ? "border-sky-blue" : "border-slate-300"
|
|
} tracking-wide transition duration-200`}
|
|
>
|
|
Previous Cards
|
|
</button>
|
|
<button
|
|
name="new"
|
|
onClick={(e) => setTab(e.target.name)}
|
|
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
|
|
tab == "new" ? "border-sky-blue" : "border-slate-300"
|
|
} tracking-wide transition duration-200`}
|
|
>
|
|
Add New Card
|
|
</button>
|
|
</div>
|
|
{/* END OF switch button */}
|
|
|
|
{/* previous tab */}
|
|
{tab == 'previous' ?
|
|
<div className="p-4 previous-details w-full border min-h-[300px] flex flex-col justify-between items-center">
|
|
{ payListCard.loading ?
|
|
<LoadingSpinner size='10' color='sky-blue' />
|
|
:
|
|
payListCard?.data?.length ?
|
|
<table className="my-3 w-full">
|
|
<tbody>
|
|
{currentPreviousCards.map((item, index)=>(
|
|
<tr key={index} className={index != 0 && 'border-t-2'}>
|
|
<td>
|
|
<div className='my-2 flex items-center gap-5'>
|
|
<input type="radio" className='w-8 h-8' name='card' value='value' />
|
|
<div className='card-details'>
|
|
<h1 className='text-lg font-bold text-dark-gray dark:text-white tracking-wide'>{item.description} Card</h1>
|
|
<p className='text-base font-bold text-dark-gray dark:text-white tracking-wide'>Bank **************{item.digits}</p>
|
|
<div className='w-full sm:flex items-center gap-5'>
|
|
<p className='text-base font-bold text-dark-gray dark:text-white tracking-wide'>{item.added}</p>
|
|
<p className='text-sm font-bold text-green-700 dark:text-white tracking-wide'>Verified</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<button
|
|
// onClick={handleSubmit}
|
|
type="button"
|
|
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
>
|
|
<span className="text-white">Manage</span>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
))
|
|
}
|
|
</tbody>
|
|
</table>
|
|
:
|
|
<div className='w-full flex flex-col items-center'>
|
|
<p className='my-5 text-base font-bold text-dark-gray dark:text-white tracking-wide'>No Previous Card Found!</p>
|
|
<button
|
|
onClick={()=> setTab('new')}
|
|
type="button"
|
|
className="my-5 px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
>
|
|
<span className="text-white">Add Card</span>
|
|
</button>
|
|
</div>
|
|
}
|
|
{/* PAGINATION BUTTON */}
|
|
<div className='w-full'>
|
|
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= payListCard?.data?.length ? true : false} data={payListCard?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
|
|
</div>
|
|
{/* END OF PAGINATION BUTTON */}
|
|
</div>
|
|
:
|
|
<div className="new-details w-full min-h-[300px] border-t">
|
|
<div className="w-full flex flex-col justify-between">
|
|
<Formik
|
|
initialValues={initialValues}
|
|
validationSchema={validationSchema}
|
|
onSubmit={handleSubmit}
|
|
>
|
|
{(props) => {
|
|
return (
|
|
<Form>
|
|
<div className="flex flex-col-reverse sm:flex-row">
|
|
<div className="flex-1 sm:mr-10">
|
|
<div className="fields w-full">
|
|
{/* inputs starts here */}
|
|
{/* Name */}
|
|
<div className="field w-full my-6">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
spanTag='*'
|
|
label="Name on Card"
|
|
type="text"
|
|
name="name"
|
|
placeholder="DUMMY NAME"
|
|
value={props.values.name}
|
|
inputHandler={props.handleChange}
|
|
blurHandler={props.handleBlur}
|
|
/>
|
|
{props.errors.name && props.touched.name && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.name}
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
{/* CARD NUMBER */}
|
|
<div className="field w-full mb-6">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
spanTag='*'
|
|
iconName='master-card visa-card atm-card'
|
|
label="Card Number"
|
|
type="text"
|
|
name="cardNum"
|
|
placeholder="Enter Card Number"
|
|
value={props.values.cardNum}
|
|
inputHandler={props.handleChange}
|
|
blurHandler={props.handleBlur}
|
|
/>
|
|
{props.errors.cardNum && props.touched.cardNum && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.cardNum}
|
|
</p>
|
|
)}
|
|
</div>
|
|
{/* EXPIRE YEAR, YEAR AND CVV */}
|
|
<div className="sm:grid gap-5 grid-cols-3 mb-6">
|
|
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
|
<div className="select-option">
|
|
<div className={`flex items-center justify-between mb-2.5`}>
|
|
<label
|
|
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
|
htmlFor='expiration'
|
|
>Expiration Month <span className="text-red-700 text-sm tracking-wide">*</span></label>
|
|
</div>
|
|
<div
|
|
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`}
|
|
>
|
|
<select
|
|
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#f5f8fa] focus:ring-0 focus:outline-none`}
|
|
value={props.values.expirationMonth}
|
|
onChange={props.handleChange}
|
|
onBlur={props.handleBlur}
|
|
name='expirationMonth'
|
|
>
|
|
<option value=''>Select...</option>
|
|
{expireMonth?.length &&
|
|
expireMonth.map((item, index) => (
|
|
<option key={index} value={item.value}>{item.name}</option>
|
|
))
|
|
}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
{props.errors.expirationMonth && props.touched.expirationMonth && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.expirationMonth}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
|
<div className="select-option">
|
|
<div className={`flex items-center justify-between mb-2.5`}>
|
|
<label
|
|
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
|
htmlFor='expiration'
|
|
>Expiration Year <span className="text-red-700 text-sm tracking-wide">*</span>
|
|
</label>
|
|
</div>
|
|
<div
|
|
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`}
|
|
>
|
|
<select
|
|
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#f5f8fa] focus:ring-0 focus:outline-none`}
|
|
value={props.values.expirationYear}
|
|
onChange={props.handleChange}
|
|
onBlur={props.handleBlur}
|
|
name='expirationYear'
|
|
>
|
|
<option value=''>Select...</option>
|
|
{expireYear?.length &&
|
|
expireYear.map((item, index) => (
|
|
<option key={index} value={item}>{item}</option>
|
|
))
|
|
}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
{props.errors.expirationYear && props.touched.expirationYear && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.expirationYear}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div className="field w-full col-span-1">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
spanTag='*'
|
|
iconName='atm-card'
|
|
label="CVV"
|
|
type="text"
|
|
name="cvv"
|
|
placeholder="CVV"
|
|
value={props.values.cvv}
|
|
inputHandler={props.handleChange}
|
|
blurHandler={props.handleBlur}
|
|
/>
|
|
{props.errors.cvv && props.touched.cvv && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.cvv}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
{/* Address */}
|
|
<div className="field w-full my-6">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
spanTag='*'
|
|
label="Billing Address"
|
|
type="text"
|
|
name="address"
|
|
placeholder="Billing Address"
|
|
value={props.values.Address}
|
|
inputHandler={props.handleChange}
|
|
blurHandler={props.handleBlur}
|
|
/>
|
|
{props.errors.address && props.touched.address && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.address}
|
|
</p>
|
|
)}
|
|
</div>
|
|
{/* postal code and state */}
|
|
<div className="sm:grid gap-5 grid-cols-3 mb-6">
|
|
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
spanTag='*'
|
|
label="Postal Code"
|
|
type="text"
|
|
name="code"
|
|
placeholder="Postal Code"
|
|
value={props.values.code}
|
|
inputHandler={props.handleChange}
|
|
blurHandler={props.handleBlur}
|
|
/>
|
|
{props.errors.code && props.touched.code && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.code}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div className="field w-full col-span-1">
|
|
<InputCom
|
|
fieldClass="px-6"
|
|
spanTag='*'
|
|
label="State"
|
|
type="text"
|
|
name="state"
|
|
placeholder="State"
|
|
value={props.values.state}
|
|
inputHandler={props.handleChange}
|
|
blurHandler={props.handleBlur}
|
|
/>
|
|
{props.errors.state && props.touched.state && (
|
|
<p className="text-sm text-red-500">
|
|
{props.errors.state}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* <div className="w-full">
|
|
{requestStatus.message != "" && (
|
|
<p
|
|
className={`text-center text-base ${
|
|
requestStatus.status ? "text-green-800" : "text-red-600"
|
|
}`}
|
|
>
|
|
{requestStatus.message}
|
|
</p>
|
|
)}
|
|
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
|
<div className="flex items-center space-x-4 mr-9">
|
|
<Link
|
|
to="/"
|
|
className="text-18 text-light-red tracking-wide "
|
|
>
|
|
<span className="border-b dark:border-[#5356fb29] border-light-red">
|
|
{" "}
|
|
Cancel
|
|
</span>
|
|
</Link>
|
|
|
|
{requestStatus.loading ? (
|
|
<LoadingSpinner size="8" color="sky-blue" />
|
|
) : (
|
|
<button
|
|
type="submit"
|
|
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
>
|
|
Update Profile
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div> */}
|
|
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
|
|
<button
|
|
type="submit"
|
|
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
>
|
|
<span className="text-white">Continue</span>
|
|
</button>
|
|
</div>
|
|
</Form>
|
|
);
|
|
}}
|
|
</Formik>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
{ tab == 'previous' &&
|
|
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
|
|
<button
|
|
onClick={handleSubmit}
|
|
type="button"
|
|
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
>
|
|
<span className="text-white">Continue</span>
|
|
</button>
|
|
</div>
|
|
}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default AddFundDollars
|
|
|
|
|
|
// FORMS ARRAY OF EXPIRATION YEAR FOR CARD
|
|
const expireYear = []
|
|
let currentYear = new Date().getFullYear()
|
|
for(let i=0; i<=6; i++){
|
|
expireYear.push(currentYear + i)
|
|
}
|
|
|
|
// FORMS ARRAY OF EXPIRATION MONTH FOR CARD
|
|
let month = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
|
const expireMonth = []
|
|
for(let i=0; i<month.length; i++){
|
|
expireMonth.push({name:month[i], value:i+1})
|
|
} |