@sikka/hawa 0.0.3 → 0.0.4
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/.github/workflows/hawa-publish-push.yml +45 -0
- package/.github/workflows/hawa-publish.yml +2 -0
- package/es/index.es.js +1 -0
- package/lib/index.js +1 -0
- package/package.json +18 -8
- package/rollup.config.js +2 -2
- package/src/Assets/images/card-background/1.jpeg +0 -0
- package/src/Assets/images/card-background/10.jpeg +0 -0
- package/src/Assets/images/card-background/11.jpeg +0 -0
- package/src/Assets/images/card-background/12.jpeg +0 -0
- package/src/Assets/images/card-background/13.jpeg +0 -0
- package/src/Assets/images/card-background/14.jpeg +0 -0
- package/src/Assets/images/card-background/15.jpeg +0 -0
- package/src/Assets/images/card-background/16.jpeg +0 -0
- package/src/Assets/images/card-background/17.jpeg +0 -0
- package/src/Assets/images/card-background/18.jpeg +0 -0
- package/src/Assets/images/card-background/19.jpeg +0 -0
- package/src/Assets/images/card-background/2.jpeg +0 -0
- package/src/Assets/images/card-background/20.jpeg +0 -0
- package/src/Assets/images/card-background/21.jpeg +0 -0
- package/src/Assets/images/card-background/22.jpeg +0 -0
- package/src/Assets/images/card-background/23.jpeg +0 -0
- package/src/Assets/images/card-background/24.jpeg +0 -0
- package/src/Assets/images/card-background/25.jpeg +0 -0
- package/src/Assets/images/card-background/3.jpeg +0 -0
- package/src/Assets/images/card-background/4.jpeg +0 -0
- package/src/Assets/images/card-background/5.jpeg +0 -0
- package/src/Assets/images/card-background/6.jpeg +0 -0
- package/src/Assets/images/card-background/7.jpeg +0 -0
- package/src/Assets/images/card-background/8.jpeg +0 -0
- package/src/Assets/images/card-background/9.jpeg +0 -0
- package/src/Assets/images/card-type/amex.png +0 -0
- package/src/Assets/images/card-type/diners.png +0 -0
- package/src/Assets/images/card-type/discover.png +0 -0
- package/src/Assets/images/card-type/mastercard.png +0 -0
- package/src/Assets/images/card-type/troy.png +0 -0
- package/src/Assets/images/card-type/unionpay.png +0 -0
- package/src/Assets/images/card-type/visa.png +0 -0
- package/src/blocks/Payment/Form/CForm.js +326 -0
- package/src/blocks/Payment/Form/Card.js +242 -0
- package/src/blocks/Payment/Gateway/GooglePay.js +251 -0
- package/src/blocks/Payment/Gateway/Payfort.js +90 -0
- package/src/blocks/Payment/Gateway/Paypal.js +138 -0
- package/src/blocks/Payment/Gateway/Wallet.js +149 -0
- package/src/blocks/Payment/PaymentMethod.js +132 -0
- package/src/blocks/index.js +13 -0
- package/src/index.js +2 -1
- package/src/styles.scss +679 -0
- package/tools/build-styles.js +17 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import React, { useEffect, useState, useRef } from "react";
|
|
2
|
+
import sha256 from "crypto-js/sha256";
|
|
3
|
+
import Button from "@material-ui/core/Button";
|
|
4
|
+
import CircularProgress from "@material-ui/core/CircularProgress";
|
|
5
|
+
import useTranslation from "next-translate/useTranslation";
|
|
6
|
+
import axios from "axios";
|
|
7
|
+
|
|
8
|
+
const currentYear = new Date().getFullYear();
|
|
9
|
+
const monthsArr = Array.from({ length: 12 }, (x, i) => {
|
|
10
|
+
const month = i + 1;
|
|
11
|
+
return month <= 9 ? "0" + month : month;
|
|
12
|
+
});
|
|
13
|
+
const yearsArr = Array.from({ length: 9 }, (_x, i) => currentYear + i);
|
|
14
|
+
|
|
15
|
+
export default function CForm({
|
|
16
|
+
cardHolder,
|
|
17
|
+
cardMonth,
|
|
18
|
+
cardYear,
|
|
19
|
+
cardCvv,
|
|
20
|
+
onUpdateState,
|
|
21
|
+
cardNumberRef,
|
|
22
|
+
cardHolderRef,
|
|
23
|
+
cardDateRef,
|
|
24
|
+
cardCvvRef,
|
|
25
|
+
onCardInputFocus,
|
|
26
|
+
onCardInputBlur,
|
|
27
|
+
children,
|
|
28
|
+
selectedPaymentMethod,
|
|
29
|
+
transaction
|
|
30
|
+
}) {
|
|
31
|
+
const payfortFormref = useRef();
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
33
|
+
const [cardNumber, setCardNumber] = useState("");
|
|
34
|
+
const [accessCode, setAccessCode] = useState("");
|
|
35
|
+
const [merchantIdentifier, setMerchantIdentifier] = useState("");
|
|
36
|
+
const [shaRequestPassphrase, setSHARequestPassphrase] = useState("");
|
|
37
|
+
const [expiryDate, setExpiryDate] = useState("");
|
|
38
|
+
const [signature, setSignature] = useState("");
|
|
39
|
+
const [ip, setIP] = useState("");
|
|
40
|
+
const { t, lang } = useTranslation("common");
|
|
41
|
+
|
|
42
|
+
const handleFormChange = (event) => {
|
|
43
|
+
const { name, value } = event.target;
|
|
44
|
+
|
|
45
|
+
onUpdateState(name, value);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const getData = async () => {
|
|
49
|
+
const res = await axios.get("https://geolocation-db.com/json/");
|
|
50
|
+
console.log(res.data);
|
|
51
|
+
setIP(res.data.IPv4);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const generateSignature = () => {
|
|
55
|
+
// Calculate request signature
|
|
56
|
+
let shaString = "";
|
|
57
|
+
|
|
58
|
+
// array request
|
|
59
|
+
let arrData = {
|
|
60
|
+
access_code: process.env.NEXT_PUBLIC_QAWAIM_SOFTWARE_PAYFOR_ACCESS_TOKEN,
|
|
61
|
+
language: lang,
|
|
62
|
+
merchant_identifier:
|
|
63
|
+
process.env.NEXT_PUBLIC_QAWAIM_SOFTWARE_PAYFOR_MERCHANT_ID,
|
|
64
|
+
merchant_reference: "",
|
|
65
|
+
return_url: `${process.env.NEXT_PUBLIC_QAWAIM_USER_PORTAL_URL}/aps_online/response`,
|
|
66
|
+
service_command: "TOKENIZATION"
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
if (
|
|
70
|
+
transaction &&
|
|
71
|
+
transaction?.getTransactionByIDInvoice?.transaction_payment_token
|
|
72
|
+
) {
|
|
73
|
+
arrData.token_name =
|
|
74
|
+
transaction?.getTransactionByIDInvoice?.transaction_payment_token;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log("arrData=", arrData);
|
|
78
|
+
|
|
79
|
+
shaString = `${process.env.NEXT_PUBLIC_QAWAIM_SOFTWARE_PAYFOR_SHA_REQUEST_PHRASE}${shaString}`;
|
|
80
|
+
for (const [key, value] of Object.entries(arrData)) {
|
|
81
|
+
shaString = `${shaString}${key}=${value}`;
|
|
82
|
+
}
|
|
83
|
+
shaString = `${shaString}${process.env.NEXT_PUBLIC_QAWAIM_SOFTWARE_PAYFOR_SHA_REQUEST_PHRASE}`;
|
|
84
|
+
|
|
85
|
+
console.log("shaString=", shaString);
|
|
86
|
+
|
|
87
|
+
// your request signature
|
|
88
|
+
let signature = sha256(shaString);
|
|
89
|
+
|
|
90
|
+
console.log("signature=", signature);
|
|
91
|
+
setSignature(signature);
|
|
92
|
+
};
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (selectedPaymentMethod && selectedPaymentMethod !== "APPLEPAY") {
|
|
95
|
+
getData();
|
|
96
|
+
generateSignature();
|
|
97
|
+
}
|
|
98
|
+
}, [selectedPaymentMethod, accessCode, shaRequestPassphrase]);
|
|
99
|
+
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (cardMonth && cardYear) {
|
|
102
|
+
setExpiryDate(`${cardYear.substring(2)}${cardMonth}`);
|
|
103
|
+
}
|
|
104
|
+
}, [cardMonth, cardYear]);
|
|
105
|
+
|
|
106
|
+
// TODO: We can improve the regex check with a better approach like in the card component.
|
|
107
|
+
const onCardNumberChange = (event) => {
|
|
108
|
+
let { value, name } = event.target;
|
|
109
|
+
let cardNumber = value;
|
|
110
|
+
value = value.replace(/\D/g, "");
|
|
111
|
+
if (/^3[47]\d{0,13}$/.test(value)) {
|
|
112
|
+
cardNumber = value
|
|
113
|
+
.replace(/(\d{4})/, "$1 ")
|
|
114
|
+
.replace(/(\d{4}) (\d{6})/, "$1 $2 ");
|
|
115
|
+
} else if (/^3(?:0[0-5]|[68]\d)\d{0,11}$/.test(value)) {
|
|
116
|
+
// diner's club, 14 digits
|
|
117
|
+
cardNumber = value
|
|
118
|
+
.replace(/(\d{4})/, "$1 ")
|
|
119
|
+
.replace(/(\d{4}) (\d{6})/, "$1 $2 ");
|
|
120
|
+
} else if (/^\d{0,16}$/.test(value)) {
|
|
121
|
+
// regular cc number, 16 digits
|
|
122
|
+
cardNumber = value
|
|
123
|
+
.replace(/(\d{4})/, "$1 ")
|
|
124
|
+
.replace(/(\d{4}) (\d{4})/, "$1 $2 ")
|
|
125
|
+
.replace(/(\d{4}) (\d{4}) (\d{4})/, "$1 $2 $3 ");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
setCardNumber(cardNumber.trimRight());
|
|
129
|
+
onUpdateState(name, cardNumber);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const onCvvFocus = (event) => {
|
|
133
|
+
onUpdateState("isCardFlipped", true);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const onCvvBlur = (event) => {
|
|
137
|
+
onUpdateState("isCardFlipped", false);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const handlePayfortForm = (e) => {
|
|
141
|
+
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// NOTE: Currently the cursor on the card number field gets reset if we remove a number, the code bellow was used
|
|
145
|
+
// in class components, need to transform this to work with functional components.
|
|
146
|
+
// getSnapshotBeforeUpdate() {
|
|
147
|
+
// return this.props.cardNumberRef.current.selectionStart;
|
|
148
|
+
// }
|
|
149
|
+
|
|
150
|
+
// const componentDidUpdate = function (prevProps, prevState, cursorIdx) {
|
|
151
|
+
// const node = cardNumberRef.current;
|
|
152
|
+
// const { cardNumber: cardNum } = state;
|
|
153
|
+
// const { cardNumber: prevCardNum } = prevState;
|
|
154
|
+
// if (
|
|
155
|
+
// cardNum.length > prevCardNum.length &&
|
|
156
|
+
// cardNum[cursorIdx - 1] === ' '
|
|
157
|
+
// ) {
|
|
158
|
+
// cursorIdx += 1;
|
|
159
|
+
// } else if (prevCardNum[cursorIdx - 1] === ' ') {
|
|
160
|
+
// cursorIdx -= 1;
|
|
161
|
+
// }
|
|
162
|
+
// node.selectionStart = node.selectionEnd = cursorIdx;
|
|
163
|
+
// };
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<div className="card-form">
|
|
167
|
+
<div className="card-list">{children}</div>
|
|
168
|
+
<div className="card-form__inner">
|
|
169
|
+
<div className="card-input">
|
|
170
|
+
<label htmlFor="cardNumber" className="card-input__label">
|
|
171
|
+
{t("cardNumber")}
|
|
172
|
+
</label>
|
|
173
|
+
<input
|
|
174
|
+
type="tel"
|
|
175
|
+
name="cardNumber"
|
|
176
|
+
className="card-input__input"
|
|
177
|
+
autoComplete="off"
|
|
178
|
+
onChange={onCardNumberChange}
|
|
179
|
+
maxLength="19"
|
|
180
|
+
ref={cardNumberRef}
|
|
181
|
+
onFocus={(e) => onCardInputFocus(e, "cardNumber")}
|
|
182
|
+
onBlur={onCardInputBlur}
|
|
183
|
+
value={cardNumber}
|
|
184
|
+
/>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<div className="card-input">
|
|
188
|
+
<label htmlFor="cardName" className="card-input__label">
|
|
189
|
+
{t("cardHolder")}
|
|
190
|
+
</label>
|
|
191
|
+
<input
|
|
192
|
+
type="text"
|
|
193
|
+
className="card-input__input"
|
|
194
|
+
autoComplete="off"
|
|
195
|
+
name="cardHolder"
|
|
196
|
+
onChange={handleFormChange}
|
|
197
|
+
ref={cardHolderRef}
|
|
198
|
+
onFocus={(e) => onCardInputFocus(e, "cardHolder")}
|
|
199
|
+
onBlur={onCardInputBlur}
|
|
200
|
+
/>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<div className="card-form__row">
|
|
204
|
+
<div className="card-form__col">
|
|
205
|
+
<div className="card-form__group">
|
|
206
|
+
<label htmlFor="cardMonth" className="card-input__label">
|
|
207
|
+
{t("cardExpiration")}
|
|
208
|
+
</label>
|
|
209
|
+
<select
|
|
210
|
+
className="card-input__input -select"
|
|
211
|
+
value={cardMonth}
|
|
212
|
+
name="cardMonth"
|
|
213
|
+
onChange={handleFormChange}
|
|
214
|
+
ref={cardDateRef}
|
|
215
|
+
onFocus={(e) => onCardInputFocus(e, "cardDate")}
|
|
216
|
+
onBlur={onCardInputBlur}
|
|
217
|
+
>
|
|
218
|
+
<option value="" disabled>
|
|
219
|
+
{t("cardMonth")}
|
|
220
|
+
</option>
|
|
221
|
+
|
|
222
|
+
{monthsArr.map((val, index) => (
|
|
223
|
+
<option key={index} value={val}>
|
|
224
|
+
{val}
|
|
225
|
+
</option>
|
|
226
|
+
))}
|
|
227
|
+
</select>
|
|
228
|
+
<select
|
|
229
|
+
name="cardYear"
|
|
230
|
+
className="card-input__input -select"
|
|
231
|
+
value={cardYear}
|
|
232
|
+
onChange={handleFormChange}
|
|
233
|
+
onFocus={(e) => onCardInputFocus(e, "cardDate")}
|
|
234
|
+
onBlur={onCardInputBlur}
|
|
235
|
+
>
|
|
236
|
+
<option value="" disabled>
|
|
237
|
+
{t("cardYear")}
|
|
238
|
+
</option>
|
|
239
|
+
|
|
240
|
+
{yearsArr.map((val, index) => (
|
|
241
|
+
<option key={index} value={val}>
|
|
242
|
+
{val}
|
|
243
|
+
</option>
|
|
244
|
+
))}
|
|
245
|
+
</select>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
<div className="card-form__col -cvv">
|
|
249
|
+
<div className="card-input">
|
|
250
|
+
<label htmlFor="cardCvv" className="card-input__label">
|
|
251
|
+
{t("cvv")}
|
|
252
|
+
</label>
|
|
253
|
+
<input
|
|
254
|
+
type="tel"
|
|
255
|
+
className="card-input__input"
|
|
256
|
+
maxLength="4"
|
|
257
|
+
autoComplete="off"
|
|
258
|
+
name="cardCvv"
|
|
259
|
+
onChange={handleFormChange}
|
|
260
|
+
onFocus={onCvvFocus}
|
|
261
|
+
onBlur={onCvvBlur}
|
|
262
|
+
ref={cardCvvRef}
|
|
263
|
+
/>
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
</div>
|
|
267
|
+
<div className="card-input" style={{ marginTop: "20px" }}>
|
|
268
|
+
<form
|
|
269
|
+
ref={payfortFormref}
|
|
270
|
+
action={`${process.env.NEXT_PUBLIC_QAWAIM_SOFTWARE_PAYFOR_ENVIRONMENT_URL}`}
|
|
271
|
+
method="POST"
|
|
272
|
+
>
|
|
273
|
+
<input type="hidden" name="access_code" value={`${accessCode}`} />
|
|
274
|
+
<input type="hidden" name="card_holder_name" value={cardHolder} />
|
|
275
|
+
<input
|
|
276
|
+
type="hidden"
|
|
277
|
+
name="card_number"
|
|
278
|
+
value={cardNumber.replace(/\s/g, "")}
|
|
279
|
+
/>
|
|
280
|
+
<input type="hidden" name="card_security_code" value={cardCvv} />
|
|
281
|
+
<input type="hidden" name="expiry_date" value={expiryDate} />
|
|
282
|
+
<input type="hidden" name="language" value={lang} />
|
|
283
|
+
<input
|
|
284
|
+
type="hidden"
|
|
285
|
+
name="merchant_identifier"
|
|
286
|
+
value={`${merchantIdentifier}`}
|
|
287
|
+
/>
|
|
288
|
+
<input type="hidden" name="merchant_reference" value={""} />
|
|
289
|
+
<input type="hidden" name="remember_me" value="NO" />
|
|
290
|
+
<input
|
|
291
|
+
type="hidden"
|
|
292
|
+
name="return_url"
|
|
293
|
+
value={`${process.env.NEXT_PUBLIC_QAWAIM_USER_PORTAL_URL}/aps_online/register`}
|
|
294
|
+
/>
|
|
295
|
+
<input type="hidden" name="service_command" value="TOKENIZATION" />
|
|
296
|
+
<input type="hidden" name="signature" value={signature} />
|
|
297
|
+
{transaction &&
|
|
298
|
+
transaction?.getTransactionByIDInvoice
|
|
299
|
+
?.transaction_payment_token && (
|
|
300
|
+
<input
|
|
301
|
+
type="hidden"
|
|
302
|
+
name="token_name"
|
|
303
|
+
value={
|
|
304
|
+
transaction?.getTransactionByIDInvoice
|
|
305
|
+
?.transaction_payment_token
|
|
306
|
+
}
|
|
307
|
+
/>
|
|
308
|
+
)}
|
|
309
|
+
</form>
|
|
310
|
+
<Button variant="contained" color="primary" fullWidth onClick={handlePayfortForm}>
|
|
311
|
+
{loading ? (
|
|
312
|
+
<CircularProgress
|
|
313
|
+
variant="indeterminate"
|
|
314
|
+
style={{ color: "white", display: "none" }}
|
|
315
|
+
size={25}
|
|
316
|
+
/>
|
|
317
|
+
) : (
|
|
318
|
+
<span className="pay-new-btn-txt">{t("pay-now")}</span>
|
|
319
|
+
)}
|
|
320
|
+
</Button>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
|
2
|
+
import {
|
|
3
|
+
CSSTransition,
|
|
4
|
+
TransitionGroup,
|
|
5
|
+
SwitchTransition
|
|
6
|
+
} from "react-transition-group";
|
|
7
|
+
|
|
8
|
+
const CARDS = {
|
|
9
|
+
visa: "^4",
|
|
10
|
+
amex: "^(34|37)",
|
|
11
|
+
mastercard: "^5[1-5]",
|
|
12
|
+
discover: "^6011",
|
|
13
|
+
unionpay: "^62",
|
|
14
|
+
troy: "^9792",
|
|
15
|
+
diners: "^(30[0-5]|36)"
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const cardBackgroundName = () => {
|
|
19
|
+
let random = Math.floor(Math.random() * 25 + 1);
|
|
20
|
+
return `${random}.jpeg`;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const BACKGROUND_IMG = cardBackgroundName();
|
|
24
|
+
|
|
25
|
+
const Card = ({
|
|
26
|
+
cardHolder,
|
|
27
|
+
cardNumber,
|
|
28
|
+
cardMonth,
|
|
29
|
+
cardYear,
|
|
30
|
+
cardCvv,
|
|
31
|
+
isCardFlipped,
|
|
32
|
+
currentFocusedElm,
|
|
33
|
+
onCardElementClick,
|
|
34
|
+
cardNumberRef,
|
|
35
|
+
cardHolderRef,
|
|
36
|
+
cardDateRef
|
|
37
|
+
}) => {
|
|
38
|
+
const [style, setStyle] = useState(null);
|
|
39
|
+
|
|
40
|
+
const cardType = (cardNumber) => {
|
|
41
|
+
const number = cardNumber;
|
|
42
|
+
let re;
|
|
43
|
+
for (const [card, pattern] of Object.entries(CARDS)) {
|
|
44
|
+
re = new RegExp(pattern);
|
|
45
|
+
if (number.match(re) != null) {
|
|
46
|
+
return card;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return "visa"; // default type
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const useCardType = useMemo(() => {
|
|
54
|
+
return cardType(cardNumber);
|
|
55
|
+
}, [cardNumber]);
|
|
56
|
+
|
|
57
|
+
const outlineElementStyle = (element) => {
|
|
58
|
+
return element
|
|
59
|
+
? {
|
|
60
|
+
width: `${element.offsetWidth}px`,
|
|
61
|
+
height: `${element.offsetHeight}px`,
|
|
62
|
+
transform: `translateX(${element.offsetLeft}px) translateY(${element.offsetTop}px)`
|
|
63
|
+
}
|
|
64
|
+
: null;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (currentFocusedElm) {
|
|
69
|
+
const style = outlineElementStyle(currentFocusedElm.current);
|
|
70
|
+
setStyle(style);
|
|
71
|
+
}
|
|
72
|
+
}, [currentFocusedElm]);
|
|
73
|
+
|
|
74
|
+
const maskCardNumber = (cardNumber) => {
|
|
75
|
+
let cardNumberArr = cardNumber.split("");
|
|
76
|
+
cardNumberArr.forEach((val, index) => {
|
|
77
|
+
if (index > 4 && index < 14) {
|
|
78
|
+
if (cardNumberArr[index] !== " ") {
|
|
79
|
+
cardNumberArr[index] = "*";
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return cardNumberArr;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className={"card-item " + (isCardFlipped ? "-active" : "")}>
|
|
89
|
+
<div className="card-item__side -front">
|
|
90
|
+
<div
|
|
91
|
+
className={`card-item__focus ${currentFocusedElm ? `-active` : ``}`}
|
|
92
|
+
style={style}
|
|
93
|
+
/>
|
|
94
|
+
<div className="card-item__cover">
|
|
95
|
+
<img
|
|
96
|
+
alt=""
|
|
97
|
+
src={`/card-background/${BACKGROUND_IMG}`}
|
|
98
|
+
className="card-item__bg"
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div className="card-item__wrapper">
|
|
103
|
+
<div className="card-item__top">
|
|
104
|
+
<img src={"/chip.png"} alt="" className="card-item__chip" />
|
|
105
|
+
<div className="card-item__type">
|
|
106
|
+
<img
|
|
107
|
+
alt={useCardType}
|
|
108
|
+
src={`/card-type/${useCardType}.png`}
|
|
109
|
+
className="card-item__typeImg"
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<label
|
|
115
|
+
className="card-item__number"
|
|
116
|
+
ref={cardNumberRef}
|
|
117
|
+
onClick={() => onCardElementClick("cardNumber")}
|
|
118
|
+
>
|
|
119
|
+
<TransitionGroup className="slide-fade-up" component="div">
|
|
120
|
+
{cardNumber ? (
|
|
121
|
+
maskCardNumber(cardNumber).map((val, index) => (
|
|
122
|
+
<CSSTransition
|
|
123
|
+
classNames="slide-fade-up"
|
|
124
|
+
timeout={250}
|
|
125
|
+
key={index}
|
|
126
|
+
>
|
|
127
|
+
<div className="card-item__numberItem">{val}</div>
|
|
128
|
+
</CSSTransition>
|
|
129
|
+
))
|
|
130
|
+
) : (
|
|
131
|
+
<CSSTransition classNames="slide-fade-up" timeout={250}>
|
|
132
|
+
<div className="card-item__numberItem">#</div>
|
|
133
|
+
</CSSTransition>
|
|
134
|
+
)}
|
|
135
|
+
</TransitionGroup>
|
|
136
|
+
</label>
|
|
137
|
+
<div className="card-item__content">
|
|
138
|
+
<label
|
|
139
|
+
className="card-item__info"
|
|
140
|
+
onClick={() => onCardElementClick("cardHolder")}
|
|
141
|
+
ref={cardHolderRef}
|
|
142
|
+
>
|
|
143
|
+
<div className="card-item__holder">Card Holder</div>
|
|
144
|
+
<div className="card-item__name">
|
|
145
|
+
<TransitionGroup component="div" className="slide-fade-up">
|
|
146
|
+
{cardHolder === "FULL NAME" ? (
|
|
147
|
+
<CSSTransition classNames="slide-fade-up" timeout={250}>
|
|
148
|
+
<div>FULL NAME</div>
|
|
149
|
+
</CSSTransition>
|
|
150
|
+
) : (
|
|
151
|
+
cardHolder.split("").map((val, index) => (
|
|
152
|
+
<CSSTransition
|
|
153
|
+
timeout={250}
|
|
154
|
+
classNames="slide-fade-right"
|
|
155
|
+
key={index}
|
|
156
|
+
>
|
|
157
|
+
<span className="card-item__nameItem">{val}</span>
|
|
158
|
+
</CSSTransition>
|
|
159
|
+
))
|
|
160
|
+
)}
|
|
161
|
+
</TransitionGroup>
|
|
162
|
+
</div>
|
|
163
|
+
</label>
|
|
164
|
+
<div
|
|
165
|
+
className="card-item__date"
|
|
166
|
+
onClick={() => onCardElementClick("cardDate")}
|
|
167
|
+
ref={cardDateRef}
|
|
168
|
+
>
|
|
169
|
+
<label className="card-item__dateTitle">Expires</label>
|
|
170
|
+
<label className="card-item__dateItem">
|
|
171
|
+
<SwitchTransition in-out>
|
|
172
|
+
<CSSTransition
|
|
173
|
+
classNames="slide-fade-up"
|
|
174
|
+
timeout={200}
|
|
175
|
+
key={cardMonth}
|
|
176
|
+
>
|
|
177
|
+
<span>{!cardMonth ? "MM" : cardMonth} </span>
|
|
178
|
+
</CSSTransition>
|
|
179
|
+
</SwitchTransition>
|
|
180
|
+
</label>
|
|
181
|
+
/
|
|
182
|
+
<label htmlFor="cardYear" className="card-item__dateItem">
|
|
183
|
+
<SwitchTransition out-in>
|
|
184
|
+
<CSSTransition
|
|
185
|
+
classNames="slide-fade-up"
|
|
186
|
+
timeout={250}
|
|
187
|
+
key={cardYear}
|
|
188
|
+
>
|
|
189
|
+
<span>
|
|
190
|
+
{!cardYear ? "YY" : cardYear.toString().substr(-2)}
|
|
191
|
+
</span>
|
|
192
|
+
</CSSTransition>
|
|
193
|
+
</SwitchTransition>
|
|
194
|
+
</label>
|
|
195
|
+
</div>
|
|
196
|
+
<div
|
|
197
|
+
className="card-item__date"
|
|
198
|
+
onClick={() => onCardElementClick("cardDate")}
|
|
199
|
+
ref={cardDateRef}
|
|
200
|
+
></div>
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
<div className="card-item__side -back">
|
|
206
|
+
<div className="card-item__cover">
|
|
207
|
+
<img
|
|
208
|
+
alt=""
|
|
209
|
+
src={`/card-background/${BACKGROUND_IMG}`}
|
|
210
|
+
className="card-item__bg"
|
|
211
|
+
/>
|
|
212
|
+
</div>
|
|
213
|
+
<div className="card-item__band" />
|
|
214
|
+
<div className="card-item__cvv">
|
|
215
|
+
<div className="card-item__cvvTitle">CVV</div>
|
|
216
|
+
<div className="card-item__cvvBand">
|
|
217
|
+
<TransitionGroup>
|
|
218
|
+
{cardCvv.split("").map((val, index) => (
|
|
219
|
+
<CSSTransition
|
|
220
|
+
classNames="zoom-in-out"
|
|
221
|
+
key={index}
|
|
222
|
+
timeout={250}
|
|
223
|
+
>
|
|
224
|
+
<span>*</span>
|
|
225
|
+
</CSSTransition>
|
|
226
|
+
))}
|
|
227
|
+
</TransitionGroup>
|
|
228
|
+
</div>
|
|
229
|
+
<div className="card-item__type">
|
|
230
|
+
<img
|
|
231
|
+
alt="card-type"
|
|
232
|
+
src={"/card-type/visa.png"}
|
|
233
|
+
className="card-item__typeImg"
|
|
234
|
+
/>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
export default Card;
|