@seamlessdocs/payment-modals 1.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +13 -0
- package/.eslintrc.json +11 -0
- package/.idea/PaymentModals.iml +8 -0
- package/.idea/codeStyles/Project.xml +44 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.prettierrc +4 -0
- package/README.md +1 -0
- package/build/payment-modals.js +52 -0
- package/config/env.js +93 -0
- package/config/jest/cssTransform.js +14 -0
- package/config/jest/fileTransform.js +40 -0
- package/config/modules.js +88 -0
- package/config/paths.js +90 -0
- package/config/pnpTs.js +35 -0
- package/config/webpack.config.js +656 -0
- package/config/webpackDevServer.config.js +104 -0
- package/index.css +11 -0
- package/index.html +137 -0
- package/package.json +58 -0
- package/scripts/build.js +191 -0
- package/scripts/start.js +145 -0
- package/scripts/test.js +53 -0
- package/src/Components/ACHPaymentModal/ACHPaymentModal.module.css +118 -0
- package/src/Components/ACHPaymentModal/Form/FieldContainer/FieldContainer.module.css +40 -0
- package/src/Components/ACHPaymentModal/Form/FieldContainer/index.jsx +60 -0
- package/src/Components/ACHPaymentModal/Form/Form.module.css +81 -0
- package/src/Components/ACHPaymentModal/Form/index.jsx +189 -0
- package/src/Components/ACHPaymentModal/index.jsx +83 -0
- package/src/Components/ChooseModal/ChooseModal.module.css +114 -0
- package/src/Components/ChooseModal/index.jsx +34 -0
- package/src/Components/EmptyModal/index.jsx +7 -0
- package/src/Components/ErrorModal/ErrorModal.module.css +64 -0
- package/src/Components/ErrorModal/index.jsx +35 -0
- package/src/Components/ErrorOptionalModal/index.jsx +9 -0
- package/src/Components/Modal/Modal.module.css +29 -0
- package/src/Components/Modal/index.jsx +13 -0
- package/src/Components/PayNowModal/index.jsx +27 -0
- package/src/Components/ProcessingModal/ProcessingModal.module.css +50 -0
- package/src/Components/ProcessingModal/index.jsx +25 -0
- package/src/Components/SelectPaymentModal/SelectPaymentModal.module.css +212 -0
- package/src/Components/SelectPaymentModal/index.jsx +117 -0
- package/src/Components/SuccessModal/SuccessModal.module.css +34 -0
- package/src/Components/SuccessModal/index.jsx +23 -0
- package/src/OpenViewStyles.css +16 -0
- package/src/assets/img/back.svg +3 -0
- package/src/assets/img/bank-account.svg +7 -0
- package/src/assets/img/credit-card.svg +36 -0
- package/src/assets/img/error-icon.svg +1 -0
- package/src/assets/img/error.svg +3 -0
- package/src/assets/img/loader.svg +3 -0
- package/src/assets/img/lock-icon.svg +3 -0
- package/src/assets/img/logo.svg +6 -0
- package/src/assets/img/processing.gif +0 -0
- package/src/assets/img/success.svg +4 -0
- package/src/assets/img/valid-icon.svg +1 -0
- package/src/index.jsx +93 -0
- package/webpack.config.js +78 -0
package/scripts/test.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Do this as the first thing so that any code reading it knows the right env.
|
|
4
|
+
process.env.BABEL_ENV = 'test';
|
|
5
|
+
process.env.NODE_ENV = 'test';
|
|
6
|
+
process.env.PUBLIC_URL = '';
|
|
7
|
+
|
|
8
|
+
// Makes the script crash on unhandled rejections instead of silently
|
|
9
|
+
// ignoring them. In the future, promise rejections that are not handled will
|
|
10
|
+
// terminate the Node.js process with a non-zero exit code.
|
|
11
|
+
process.on('unhandledRejection', err => {
|
|
12
|
+
throw err;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Ensure environment variables are read.
|
|
16
|
+
require('../config/env');
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const jest = require('jest');
|
|
20
|
+
const execSync = require('child_process').execSync;
|
|
21
|
+
let argv = process.argv.slice(2);
|
|
22
|
+
|
|
23
|
+
function isInGitRepository() {
|
|
24
|
+
try {
|
|
25
|
+
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
|
|
26
|
+
return true;
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isInMercurialRepository() {
|
|
33
|
+
try {
|
|
34
|
+
execSync('hg --cwd . root', { stdio: 'ignore' });
|
|
35
|
+
return true;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Watch unless on CI or explicitly running all tests
|
|
42
|
+
if (
|
|
43
|
+
!process.env.CI &&
|
|
44
|
+
argv.indexOf('--watchAll') === -1 &&
|
|
45
|
+
argv.indexOf('--watchAll=false') === -1
|
|
46
|
+
) {
|
|
47
|
+
// https://github.com/facebook/create-react-app/issues/5210
|
|
48
|
+
const hasSourceControl = isInGitRepository() || isInMercurialRepository();
|
|
49
|
+
argv.push(hasSourceControl ? '--watch' : '--watchAll');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
jest.run(argv);
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
.modalContainer {
|
|
2
|
+
overflow-y: auto;
|
|
3
|
+
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
max-width: 600px;
|
|
6
|
+
height: 100%;
|
|
7
|
+
max-height: calc(100vh - 150px);
|
|
8
|
+
|
|
9
|
+
border-radius: none;
|
|
10
|
+
background: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.modal {
|
|
14
|
+
display: flex;
|
|
15
|
+
|
|
16
|
+
border-radius: 6px;
|
|
17
|
+
background: #fff;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.backIcon {
|
|
21
|
+
margin-right: 8px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.backTextContainer {
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
|
|
28
|
+
margin-bottom: 10px;
|
|
29
|
+
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
|
|
32
|
+
color: white;
|
|
33
|
+
|
|
34
|
+
font-size: 13px;
|
|
35
|
+
line-height: 16px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.paymentInfoContainer {
|
|
39
|
+
flex-shrink: 0;
|
|
40
|
+
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
width: 165px;
|
|
43
|
+
padding: 10px;
|
|
44
|
+
|
|
45
|
+
border-radius: 6px 0px 0px 6px;
|
|
46
|
+
background: #e2e5ea;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.paymentFormContainer {
|
|
50
|
+
flex-grow: 1;
|
|
51
|
+
|
|
52
|
+
padding: 35px 45px 0px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.paymentInfoWrapper {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
|
|
59
|
+
height: 100%;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.achTitle {
|
|
63
|
+
margin-bottom: 5px;
|
|
64
|
+
|
|
65
|
+
text-align: center;
|
|
66
|
+
|
|
67
|
+
color: #2c2f32;
|
|
68
|
+
|
|
69
|
+
font-size: 18px;
|
|
70
|
+
font-weight: bold;
|
|
71
|
+
line-height: 22px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.descriptionContainer {
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-direction: column;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.achDescription {
|
|
80
|
+
padding-bottom: 5px;
|
|
81
|
+
|
|
82
|
+
text-align: center;
|
|
83
|
+
|
|
84
|
+
color: #7e909f;
|
|
85
|
+
border-bottom: 2px solid white;
|
|
86
|
+
|
|
87
|
+
font-size: 13px;
|
|
88
|
+
font-weight: 500;
|
|
89
|
+
line-height: 16px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.totalAmount {
|
|
93
|
+
margin: 25px 0 0;
|
|
94
|
+
|
|
95
|
+
text-align: center;
|
|
96
|
+
|
|
97
|
+
color: #1f53ac;
|
|
98
|
+
|
|
99
|
+
font-size: 23px;
|
|
100
|
+
font-weight: bold;
|
|
101
|
+
line-height: 28px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.feeInfo {
|
|
105
|
+
margin: 13px 0 0;
|
|
106
|
+
|
|
107
|
+
text-align: center;
|
|
108
|
+
|
|
109
|
+
color: #7e909f;
|
|
110
|
+
|
|
111
|
+
font-size: 13px;
|
|
112
|
+
font-weight: 500;
|
|
113
|
+
line-height: 16px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.moneyValue {
|
|
117
|
+
word-break: break-all;
|
|
118
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
.fieldContainer {
|
|
2
|
+
position: relative;
|
|
3
|
+
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
padding: 10px;
|
|
6
|
+
|
|
7
|
+
border: 1px solid #d7e0e8;
|
|
8
|
+
border-radius: 5px;
|
|
9
|
+
background: #ffffff;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.fieldName {
|
|
13
|
+
margin: 0 0 5px;
|
|
14
|
+
|
|
15
|
+
text-align: left;
|
|
16
|
+
|
|
17
|
+
color: #081424;
|
|
18
|
+
|
|
19
|
+
font-size: 11px;
|
|
20
|
+
font-weight: bold;
|
|
21
|
+
line-height: 13px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.validationIcon {
|
|
25
|
+
position: absolute;
|
|
26
|
+
top: 0;
|
|
27
|
+
right: 0;
|
|
28
|
+
|
|
29
|
+
margin: 8px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.invalidField {
|
|
33
|
+
background: #fbf3f2;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.tooltip{
|
|
37
|
+
padding: 8px;
|
|
38
|
+
|
|
39
|
+
text-align: center;
|
|
40
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import ReactTooltip from 'react-tooltip';
|
|
5
|
+
|
|
6
|
+
import { Field } from 'formik';
|
|
7
|
+
|
|
8
|
+
import errorIcon from '../../../../assets/img/error-icon.svg';
|
|
9
|
+
import validIcon from '../../../../assets/img/valid-icon.svg';
|
|
10
|
+
|
|
11
|
+
import styles from './FieldContainer.module.css';
|
|
12
|
+
|
|
13
|
+
const FieldContainer = ({ name, label, children }) => {
|
|
14
|
+
return (
|
|
15
|
+
<Field name={name}>
|
|
16
|
+
{({ field, meta }) => (
|
|
17
|
+
<div
|
|
18
|
+
className={classNames(styles.fieldContainer, {
|
|
19
|
+
[styles.invalidField]: meta.touched && meta.error
|
|
20
|
+
})}
|
|
21
|
+
>
|
|
22
|
+
<div className={styles.fieldName}>{label}</div>
|
|
23
|
+
{meta.touched && meta.error && (
|
|
24
|
+
<>
|
|
25
|
+
<img
|
|
26
|
+
data-tip
|
|
27
|
+
data-for={name}
|
|
28
|
+
className={styles.validationIcon}
|
|
29
|
+
src={errorIcon}
|
|
30
|
+
alt="error"
|
|
31
|
+
/>
|
|
32
|
+
<ReactTooltip
|
|
33
|
+
className={styles.tooltip}
|
|
34
|
+
id={name}
|
|
35
|
+
place="top"
|
|
36
|
+
type="dark"
|
|
37
|
+
effect="solid"
|
|
38
|
+
>
|
|
39
|
+
<span>{meta.error}</span>
|
|
40
|
+
</ReactTooltip>
|
|
41
|
+
</>
|
|
42
|
+
)}
|
|
43
|
+
{meta.touched && !meta.error && (
|
|
44
|
+
<img className={styles.validationIcon} src={validIcon} alt="valid" />
|
|
45
|
+
)}
|
|
46
|
+
|
|
47
|
+
{children(field)}
|
|
48
|
+
</div>
|
|
49
|
+
)}
|
|
50
|
+
</Field>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
FieldContainer.propTypes = {
|
|
55
|
+
name: PropTypes.string.isRequired,
|
|
56
|
+
label: PropTypes.string.isRequired,
|
|
57
|
+
children: PropTypes.func.isRequired
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default FieldContainer;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
.fullNameContainer {
|
|
2
|
+
width: 100%;
|
|
3
|
+
margin-bottom: 13px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.input {
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: auto !important;
|
|
9
|
+
margin: 0 !important;
|
|
10
|
+
padding: 0 !important;
|
|
11
|
+
|
|
12
|
+
opacity: 0.7;
|
|
13
|
+
color: #081424 !important;
|
|
14
|
+
border: none !important;
|
|
15
|
+
outline: none !important;
|
|
16
|
+
background: transparent;
|
|
17
|
+
background-color: transparent !important;
|
|
18
|
+
box-shadow: none !important;
|
|
19
|
+
|
|
20
|
+
font-size: 16px !important;
|
|
21
|
+
line-height: 19px !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.routingNumberContainer {
|
|
25
|
+
margin-right: 7px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.numberInfoContainer {
|
|
29
|
+
display: flex;
|
|
30
|
+
|
|
31
|
+
margin-bottom: 13px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.submitBtn {
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
width: 100%;
|
|
37
|
+
padding: 15px;
|
|
38
|
+
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
|
|
41
|
+
color: #ffffff;
|
|
42
|
+
border: 1px solid #2c508d;
|
|
43
|
+
border-radius: 5px;
|
|
44
|
+
background: #1f53ac;
|
|
45
|
+
|
|
46
|
+
font-size: 16px;
|
|
47
|
+
font-weight: bold;
|
|
48
|
+
line-height: 19px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.lockIcon {
|
|
52
|
+
margin-right: 10px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.summaryError {
|
|
56
|
+
visibility: hidden;
|
|
57
|
+
|
|
58
|
+
margin: 0;
|
|
59
|
+
padding: 9px 30px 9px;
|
|
60
|
+
|
|
61
|
+
text-align: center;
|
|
62
|
+
|
|
63
|
+
color: #d0021b;
|
|
64
|
+
|
|
65
|
+
font-size: 16px;
|
|
66
|
+
line-height: 18px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.summaryErrorVisible {
|
|
70
|
+
visibility: visible;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@media (max-width: 600px) {
|
|
74
|
+
.numberInfoContainer {
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.routingNumberContainer {
|
|
79
|
+
margin: 0 0 13px;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import Select from 'react-select';
|
|
5
|
+
import { Formik, Form } from 'formik';
|
|
6
|
+
|
|
7
|
+
import FieldContainer from './FieldContainer';
|
|
8
|
+
|
|
9
|
+
import lockIcon from '../../../assets/img/lock-icon.svg';
|
|
10
|
+
|
|
11
|
+
import styles from './Form.module.css';
|
|
12
|
+
|
|
13
|
+
const ACCOUNT_TYPES = [
|
|
14
|
+
{ value: 'checkingPersonal', label: 'Checking (Personal)' },
|
|
15
|
+
{ value: 'savingsPersonal', label: 'Savings (Personal)' },
|
|
16
|
+
{ value: 'checkingBusiness', label: 'Checking (Business)' },
|
|
17
|
+
{ value: 'savingBusiness', label: 'Saving (Business)' }
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const SELECT_CUSTOM_STYLES = {
|
|
21
|
+
control: provided => ({
|
|
22
|
+
...provided,
|
|
23
|
+
minHeight: 'auto',
|
|
24
|
+
border: 'none',
|
|
25
|
+
fontsize: '16px',
|
|
26
|
+
lineHeight: '19px',
|
|
27
|
+
color: '#081424',
|
|
28
|
+
opacity: '0.7',
|
|
29
|
+
boxShadow: 'none',
|
|
30
|
+
backgroundColor: 'transparent',
|
|
31
|
+
'&:hover': {
|
|
32
|
+
border: 'none',
|
|
33
|
+
boxShadow: 'none'
|
|
34
|
+
}
|
|
35
|
+
}),
|
|
36
|
+
singleValue: provided => ({ ...provided, margin: '0' }),
|
|
37
|
+
placeholder: provided => ({ ...provided, margin: '0' }),
|
|
38
|
+
valueContainer: provided => ({ ...provided, padding: '0' }),
|
|
39
|
+
indicatorContainer: provided => ({ ...provided, padding: '0' }),
|
|
40
|
+
dropdownIndicator: provided => ({
|
|
41
|
+
...provided,
|
|
42
|
+
padding: '0',
|
|
43
|
+
color: '#1F53AC',
|
|
44
|
+
'&:hover': {
|
|
45
|
+
color: '#1F53AC'
|
|
46
|
+
}
|
|
47
|
+
}),
|
|
48
|
+
menuList: provided => ({
|
|
49
|
+
...provided,
|
|
50
|
+
fontsize: '16px',
|
|
51
|
+
lineHeight: '19px',
|
|
52
|
+
color: '#081424',
|
|
53
|
+
textAlign: 'left'
|
|
54
|
+
}),
|
|
55
|
+
input: provided => ({
|
|
56
|
+
...provided,
|
|
57
|
+
'& input': {
|
|
58
|
+
height: 'auto !important',
|
|
59
|
+
lineHeight: 'normal !important'
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const validate = values => {
|
|
65
|
+
const errors = {};
|
|
66
|
+
|
|
67
|
+
if (!values.firstName) {
|
|
68
|
+
errors.firstName = 'Required field';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!values.lastName) {
|
|
72
|
+
errors.lastName = 'Required field';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!values.accountType) {
|
|
76
|
+
errors.accountType = 'Required field';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!values.routingNumber) {
|
|
80
|
+
errors.routingNumber = 'Required field';
|
|
81
|
+
} else if (!/^\d+$/.test(values.routingNumber)) {
|
|
82
|
+
errors.routingNumber = 'Must be a number';
|
|
83
|
+
} else if (values.routingNumber.toString().length !== 9) {
|
|
84
|
+
errors.routingNumber = 'Routing number structure is not valid';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!values.accountNumber) {
|
|
88
|
+
errors.accountNumber = 'Required field';
|
|
89
|
+
} else if (!/^\d+$/.test(values.accountNumber)) {
|
|
90
|
+
errors.accountNumber = 'Must be a number';
|
|
91
|
+
} else if (
|
|
92
|
+
values.accountNumber.toString().length < 9 ||
|
|
93
|
+
values.accountNumber.toString().length > 12
|
|
94
|
+
) {
|
|
95
|
+
errors.accountNumber = 'Account number structure is not valid';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return errors;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const ACHForm = ({ onPay }) => {
|
|
102
|
+
return (
|
|
103
|
+
<Formik
|
|
104
|
+
initialValues={{
|
|
105
|
+
firstName: '',
|
|
106
|
+
lastName: '',
|
|
107
|
+
accountNumber: '',
|
|
108
|
+
routingNumber: '',
|
|
109
|
+
accountType: null
|
|
110
|
+
}}
|
|
111
|
+
validate={validate}
|
|
112
|
+
onSubmit={values => {
|
|
113
|
+
onPay(
|
|
114
|
+
values.firstName,
|
|
115
|
+
values.lastName,
|
|
116
|
+
values.routingNumber,
|
|
117
|
+
values.accountNumber,
|
|
118
|
+
values.accountType.value
|
|
119
|
+
);
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
{({ isValid, submitCount, setFieldValue, setFieldTouched }) => (
|
|
123
|
+
<Form>
|
|
124
|
+
<div className={styles.fullNameContainer}>
|
|
125
|
+
<FieldContainer name="firstName" label="First Name">
|
|
126
|
+
{field => <input className={styles.input} type="text" {...field} />}
|
|
127
|
+
</FieldContainer>
|
|
128
|
+
</div>
|
|
129
|
+
<div className={styles.fullNameContainer}>
|
|
130
|
+
<FieldContainer name="lastName" label="Last Name">
|
|
131
|
+
{field => <input className={styles.input} type="text" {...field} />}
|
|
132
|
+
</FieldContainer>
|
|
133
|
+
</div>
|
|
134
|
+
<div className={styles.numberInfoContainer}>
|
|
135
|
+
<div className={styles.routingNumberContainer}>
|
|
136
|
+
<FieldContainer name="routingNumber" label="Routing #">
|
|
137
|
+
{field => <input className={styles.input} type="text" {...field} />}
|
|
138
|
+
</FieldContainer>
|
|
139
|
+
</div>
|
|
140
|
+
<div className={styles.accountNumberContainer}>
|
|
141
|
+
<FieldContainer name="accountNumber" label="Account #">
|
|
142
|
+
{field => <input className={styles.input} type="text" {...field} />}
|
|
143
|
+
</FieldContainer>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div className={styles.fullNameContainer}>
|
|
148
|
+
<FieldContainer name="accountType" label="Account Type">
|
|
149
|
+
{field => (
|
|
150
|
+
<Select
|
|
151
|
+
styles={SELECT_CUSTOM_STYLES}
|
|
152
|
+
value={field.value}
|
|
153
|
+
placeholder="Select Account Type ..."
|
|
154
|
+
onChange={option => {
|
|
155
|
+
setFieldTouched('accountType');
|
|
156
|
+
setFieldValue('accountType', option);
|
|
157
|
+
}}
|
|
158
|
+
options={ACCOUNT_TYPES}
|
|
159
|
+
components={{
|
|
160
|
+
IndicatorSeparator: () => null
|
|
161
|
+
}}
|
|
162
|
+
/>
|
|
163
|
+
)}
|
|
164
|
+
</FieldContainer>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<button className={styles.submitBtn} type="submit">
|
|
168
|
+
<img className={styles.lockIcon} src={lockIcon} alt="lock payment" />
|
|
169
|
+
Authorize Payment
|
|
170
|
+
</button>
|
|
171
|
+
|
|
172
|
+
<div
|
|
173
|
+
className={classNames(styles.summaryError, {
|
|
174
|
+
[styles.summaryErrorVisible]: !!submitCount && !isValid
|
|
175
|
+
})}
|
|
176
|
+
>
|
|
177
|
+
Please correct invalid fields
|
|
178
|
+
</div>
|
|
179
|
+
</Form>
|
|
180
|
+
)}
|
|
181
|
+
</Formik>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
ACHForm.propTypes = {
|
|
186
|
+
onPay: PropTypes.func.isRequired
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export default ACHForm;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import Modal from '../Modal';
|
|
5
|
+
import ACHForm from './Form';
|
|
6
|
+
|
|
7
|
+
import backIcon from '../../assets/img/back.svg';
|
|
8
|
+
|
|
9
|
+
import styles from './ACHPaymentModal.module.css';
|
|
10
|
+
|
|
11
|
+
const ACHPaymentModal = ({
|
|
12
|
+
amount,
|
|
13
|
+
totalAmount,
|
|
14
|
+
feeAmount,
|
|
15
|
+
description,
|
|
16
|
+
feeName,
|
|
17
|
+
onPay,
|
|
18
|
+
onClose
|
|
19
|
+
}) => {
|
|
20
|
+
return (
|
|
21
|
+
<Modal className={styles.modalContainer}>
|
|
22
|
+
<div
|
|
23
|
+
className={styles.backTextContainer}
|
|
24
|
+
onClick={onClose}
|
|
25
|
+
onKeyDown={onClose}
|
|
26
|
+
role="button"
|
|
27
|
+
tabIndex="0"
|
|
28
|
+
>
|
|
29
|
+
<img className={styles.backIcon} src={backIcon} alt="back" />
|
|
30
|
+
Back to form
|
|
31
|
+
</div>
|
|
32
|
+
<div className={styles.modal}>
|
|
33
|
+
<div className={styles.paymentInfoContainer}>
|
|
34
|
+
<div className={styles.paymentInfoWrapper}>
|
|
35
|
+
<div>
|
|
36
|
+
<div className={styles.descriptionContainer}>
|
|
37
|
+
<span className={styles.achTitle}>ACH Payment</span>
|
|
38
|
+
<span className={styles.achDescription}>{description}</span>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div className={styles.totalAmount}>
|
|
42
|
+
<currency>$</currency>
|
|
43
|
+
<money className={styles.moneyValue}>{Number(totalAmount).toFixed(2)}</money>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
{!!feeAmount && (
|
|
47
|
+
<div className={styles.feeInfo}>
|
|
48
|
+
<currency>$</currency>
|
|
49
|
+
<money className={styles.moneyValue}>{Number(amount).toFixed(2)}</money>
|
|
50
|
+
{' submission + '}
|
|
51
|
+
<currency>$</currency>
|
|
52
|
+
<money>{Number(feeAmount).toFixed(2)}</money>
|
|
53
|
+
{` ${feeName || 'processing fee'}`}
|
|
54
|
+
</div>
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
<div className={styles.paymentFormContainer}>
|
|
60
|
+
<ACHForm onPay={onPay} />
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</Modal>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
ACHPaymentModal.propTypes = {
|
|
68
|
+
onPay: PropTypes.func.isRequired,
|
|
69
|
+
onClose: PropTypes.func.isRequired,
|
|
70
|
+
amount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
|
71
|
+
totalAmount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
|
72
|
+
description: PropTypes.string,
|
|
73
|
+
feeName: PropTypes.string,
|
|
74
|
+
feeAmount: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
ACHPaymentModal.defaultProps = {
|
|
78
|
+
feeAmount: '',
|
|
79
|
+
description: '',
|
|
80
|
+
feeName: ''
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default ACHPaymentModal;
|