Skip to content

Commit fda37d4

Browse files
committed
Refactor apple-google and cc scripts into react components
1 parent 116fbfb commit fda37d4

File tree

7 files changed

+901
-707
lines changed

7 files changed

+901
-707
lines changed
Lines changed: 104 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,136 @@
1-
.monei-fieldset {
2-
border: none;
3-
padding: 0;
4-
margin-bottom: 5px;
5-
margin-left:0;
6-
width: 100%;
7-
overflow: visible;
1+
/* Card Input Container */
2+
.monei-card-input {
3+
padding: 12px;
4+
border: 1px solid #ddd;
5+
border-radius: 4px;
6+
background: #fff;
7+
transition: border-color 0.2s ease;
8+
margin-bottom: 12px;
89
}
9-
.monei-fieldset p {
10-
margin-top:0;
10+
11+
.monei-card-input.is-focused {
12+
border-color: #007cba;
13+
box-shadow: 0 0 0 1px #007cba;
14+
}
15+
16+
.monei-card-input.is-invalid {
17+
border-color: #cc1818;
1118
}
1219

20+
/* Cardholder Name Input */
1321
.monei-input {
14-
padding: 0 10px;
15-
color: #2b2d2f;
16-
border: 1px solid hsla(0,0%,7%,.8);
17-
border-radius: 4px;
18-
background-color: #fff;
19-
font-size: 1em;
20-
text-align: start;
2122
width: 100%;
22-
height:50px;
23-
line-height: 1.2;
24-
box-sizing: border-box;
25-
position: relative;
26-
}
27-
.monei-card-input {
28-
margin-top:16px;
29-
color: #2b2d2f;
30-
border: 1px solid hsla(0,0%,7%,.8);
23+
padding: 12px;
24+
border: 1px solid #ddd;
3125
border-radius: 4px;
32-
background-color: #fff;
33-
height:50px;
34-
display: flex;
35-
align-items: center;
36-
box-sizing: border-box;
26+
font-size: 16px;
27+
transition: border-color 0.2s ease;
3728
}
3829

39-
.monei-card-input::placeholder,
40-
.monei-input::placeholder {
41-
color: hsla(0, 0%, 7%, .7);
30+
.monei-input:focus {
31+
outline: none;
32+
border-color: #007cba;
33+
box-shadow: 0 0 0 1px #007cba;
4234
}
43-
.monei-card-input::-webkit-input-placeholder,
44-
.monei-input::-webkit-input-placeholder {
45-
color: hsla(0, 0%, 7%, .7);
35+
36+
.monei-input.has-error {
37+
border-color: #cc1818;
38+
}
39+
40+
.monei-input:disabled {
41+
background-color: #f5f5f5;
42+
cursor: not-allowed;
4643
}
47-
.monei-card-input::-moz-placeholder,
48-
.monei-input::-moz-placeholder {
49-
color: hsla(0, 0%, 7%, .7);
44+
45+
/* Error Messages */
46+
.wc-block-components-validation-error {
47+
color: #cc1818;
48+
font-size: 0.875em;
49+
margin-top: 4px;
50+
margin-bottom: 8px;
5051
}
5152

53+
/* Payment Request Container */
5254
.monei-payment-request-container {
53-
width: 100%;
5455
min-height: 50px;
5556
display: flex;
56-
justify-content: center;
5757
align-items: center;
58-
overflow: visible;
58+
justify-content: center;
59+
border-radius: 4px;
60+
background: #fff;
61+
margin-bottom: 12px;
5962
}
6063

61-
[id^="zoid-monei-payment-request-"] {
62-
height: 50px !important;
63-
}
64-
[id^="zoid-monei-card-input-"] {
65-
box-sizing: border-box;
66-
}
64+
/* Label Container */
6765
.monei-label-container {
6866
display: flex;
6967
align-items: center;
68+
gap: 8px;
7069
}
70+
7171
.monei-text {
72-
flex-shrink: 0; /* The text will take up all available space */
72+
font-weight: 500;
7373
}
7474

7575
.monei-logo {
76-
margin-left: 15px;
77-
margin-right:0;
78-
padding-right:0;
79-
height:24px;
76+
display: inline-flex;
77+
align-items: center;
8078
}
8179

8280
.monei-logo img {
81+
height: 24px;
8382
width: auto;
8483
}
8584

85+
/* Fieldset */
86+
.monei-fieldset {
87+
border: none;
88+
padding: 0;
89+
margin: 0;
90+
}
91+
92+
.monei-card-fieldset {
93+
margin-top: 12px;
94+
}
95+
96+
/* Loading State */
97+
.monei-loading {
98+
text-align: center;
99+
padding: 20px;
100+
color: #666;
101+
}
102+
103+
/* Processing State */
104+
.monei-processing {
105+
opacity: 0.6;
106+
pointer-events: none;
107+
}
108+
109+
/* Animation for smooth transitions */
110+
.monei-input-container {
111+
position: relative;
112+
margin-bottom: 16px;
113+
}
114+
115+
/* Apple/Google Pay Button Adjustments */
116+
#payment-request-container {
117+
width: 100%;
118+
}
119+
120+
/* Place Order Button States */
121+
.wc-block-components-checkout-place-order-button:disabled {
122+
cursor: not-allowed;
123+
opacity: 0.6;
124+
}
125+
126+
/* Responsive Design */
127+
@media (max-width: 480px) {
128+
.monei-input,
129+
.monei-card-input {
130+
font-size: 16px; /* Prevents zoom on iOS */
131+
}
132+
133+
.monei-payment-request-container {
134+
min-height: 60px;
135+
}
136+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { getPlaceOrderButton, useButtonStateManager } from '../helpers/monei-shared-utils';
2+
3+
/**
4+
* Create Apple/Google Pay label
5+
* @param {Object} moneiData - Configuration data
6+
* @returns {React.Element}
7+
*/
8+
export const createAppleGoogleLabel = ( moneiData ) => {
9+
const isApple = window.ApplePaySession?.canMakePayments?.();
10+
const appleEnabled = moneiData.logo_apple !== false;
11+
const googleEnabled = moneiData.logo_google !== false;
12+
13+
let logo = googleEnabled ? moneiData.logo_google : false;
14+
logo = isApple && appleEnabled ? moneiData.logo_apple : logo;
15+
16+
const title = isApple && appleEnabled ? 'Apple Pay' : 'Google Pay';
17+
const shouldShowLogo = ( isApple && moneiData?.logo_apple ) ||
18+
( ! isApple && moneiData?.logo_google );
19+
20+
return (
21+
<div className="monei-label-container">
22+
<span className="monei-text">{ title }</span>
23+
{ shouldShowLogo && (
24+
<div className="monei-logo">
25+
<img src={ logo } alt="" />
26+
</div>
27+
) }
28+
</div>
29+
);
30+
};
31+
32+
/**
33+
* Shared Apple/Google Pay Content Component
34+
* @param {Object} props - Component props
35+
* @returns {React.Element}
36+
*/
37+
export const MoneiAppleGoogleContent = ( props ) => {
38+
const { useEffect, useRef } = wp.element;
39+
const { responseTypes } = props.emitResponse;
40+
const { onPaymentSetup } = props.eventRegistration;
41+
const { activePaymentMethod } = props;
42+
const moneiData = props.moneiData || wc.wcSettings.getSetting( 'monei_apple_google_data' );
43+
44+
const paymentRequestRef = useRef( null );
45+
const isActive = activePaymentMethod === ( props.paymentMethodId || 'monei_apple_google' );
46+
47+
const buttonManager = useButtonStateManager( {
48+
isActive,
49+
emitResponse: props.emitResponse,
50+
tokenFieldName: 'monei_payment_request_token',
51+
errorMessage: moneiData.tokenErrorString
52+
} );
53+
54+
/**
55+
* Initialize MONEI Payment Request
56+
*/
57+
const initPaymentRequest = () => {
58+
if ( typeof monei === 'undefined' || ! monei.PaymentRequest ) {
59+
console.error( 'MONEI SDK is not available' );
60+
return;
61+
}
62+
63+
// Clean up existing instance
64+
if ( paymentRequestRef.current?.close ) {
65+
try {
66+
paymentRequestRef.current.close();
67+
} catch ( e ) {
68+
// Silent fail
69+
}
70+
}
71+
72+
const paymentRequest = monei.PaymentRequest( {
73+
accountId: moneiData.accountId,
74+
sessionId: moneiData.sessionId,
75+
language: moneiData.language,
76+
amount: parseInt( moneiData.total * 100 ),
77+
currency: moneiData.currency,
78+
onSubmit( result ) {
79+
if ( result.token ) {
80+
buttonManager.enableCheckout( result.token );
81+
}
82+
},
83+
onError( error ) {
84+
console.error( error );
85+
}
86+
} );
87+
88+
const container = document.getElementById( 'payment-request-container' );
89+
if ( container ) {
90+
paymentRequest.render( container );
91+
paymentRequestRef.current = paymentRequest;
92+
}
93+
};
94+
95+
// Initialize on mount
96+
useEffect( () => {
97+
initPaymentRequest();
98+
99+
return () => {
100+
if ( paymentRequestRef.current?.close ) {
101+
try {
102+
paymentRequestRef.current.close();
103+
} catch ( e ) {
104+
// Silent cleanup
105+
}
106+
}
107+
};
108+
}, [] );
109+
110+
// Setup payment hook
111+
useEffect( () => {
112+
const unsubscribe = onPaymentSetup( () => {
113+
return buttonManager.getPaymentData();
114+
} );
115+
116+
return () => unsubscribe();
117+
}, [ onPaymentSetup, buttonManager.tokenRef.current ] );
118+
119+
return (
120+
<fieldset className="monei-fieldset monei-payment-request-fieldset">
121+
<div
122+
id="payment-request-container"
123+
className="monei-payment-request-container"
124+
>
125+
{ /* Payment button will be rendered here */ }
126+
</div>
127+
<input
128+
type="hidden"
129+
id="monei_payment_token"
130+
name="monei_payment_token"
131+
value=""
132+
/>
133+
<div id="monei-card-error" className="monei-error" />
134+
</fieldset>
135+
);
136+
};

0 commit comments

Comments
 (0)