Skip to content

Commit a81eac4

Browse files
committed
refactor: extract common instance creation logic in PayPal and Bizum components
- Extract createOrRenderPayPal function to eliminate 95% code duplication between initMoneiPayPal and updatePaypalAmount - Extract createOrRenderBizum function to eliminate duplication between initMoneiBizum and updateBizumAmount - Fix critical bug: Bizum updateBizumAmount was missing style property - Follow Apple/Google Pay pattern with single createOrRender function - Reduce code by 104 lines while improving maintainability - Both init and update functions now call the same instance creation logic
1 parent e2f74d9 commit a81eac4

File tree

2 files changed

+82
-186
lines changed

2 files changed

+82
-186
lines changed

assets/js/monei-block-checkout-bizum.js

Lines changed: 26 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@
3131
}, [] );
3232

3333
/**
34-
* Initialize MONEI Bizum instance once.
34+
* Create or re-render Bizum instance with specified amount
35+
* @param {number} amount - Payment amount in cents
3536
*/
36-
const initMoneiBizum = useCallback( () => {
37-
const currentTotal = cartTotals?.total_price
38-
? parseInt( cartTotals.total_price )
39-
: parseInt( bizumData.total * 100 );
40-
41-
lastAmountRef.current = currentTotal;
37+
const createOrRenderBizum = useCallback( ( amount ) => {
38+
// Clean up existing instance
39+
if (
40+
currentBizumInstanceRef.current &&
41+
typeof currentBizumInstanceRef.current.destroy === 'function'
42+
) {
43+
currentBizumInstanceRef.current.destroy();
44+
}
4245

4346
const container = document.getElementById( 'bizum-container' );
4447
if ( ! container ) {
@@ -56,7 +59,7 @@
5659
accountId: bizumData.accountId,
5760
sessionId: bizumData.sessionId,
5861
language: bizumData.language,
59-
amount: currentTotal,
62+
amount,
6063
currency: bizumData.currency,
6164
style: bizumData.bizumStyle || {},
6265
onSubmit( result ) {
@@ -93,7 +96,19 @@
9396
setTimeout( () => {
9497
setIsLoading( false );
9598
}, 1000 );
96-
}, [ cartTotals ] );
99+
}, [] );
100+
101+
/**
102+
* Initialize MONEI Bizum instance once.
103+
*/
104+
const initMoneiBizum = useCallback( () => {
105+
const currentTotal = cartTotals?.total_price
106+
? parseInt( cartTotals.total_price )
107+
: parseInt( bizumData.total * 100 );
108+
109+
lastAmountRef.current = currentTotal;
110+
createOrRenderBizum( currentTotal );
111+
}, [ cartTotals, createOrRenderBizum ] );
97112

98113
/**
99114
* Update the amount in the existing Bizum instance.
@@ -111,70 +126,9 @@
111126
lastAmountRef.current = currentTotal;
112127

113128
if ( currentBizumInstanceRef.current ) {
114-
const preservedToken = requestTokenRef.current;
115-
116-
if (
117-
typeof currentBizumInstanceRef.current.destroy ===
118-
'function'
119-
) {
120-
currentBizumInstanceRef.current.destroy();
121-
}
122-
123-
// Clear container
124-
const container = document.getElementById( 'bizum-container' );
125-
if ( container ) {
126-
// Show skeleton loading state
127-
setIsLoading( true );
128-
container.innerHTML = '';
129-
}
130-
131-
// Recreate with new amount
132-
currentBizumInstanceRef.current = monei.Bizum( {
133-
accountId: bizumData.accountId,
134-
sessionId: bizumData.sessionId,
135-
language: bizumData.language,
136-
amount: currentTotal,
137-
currency: bizumData.currency,
138-
onSubmit( result ) {
139-
if ( result.token ) {
140-
setError( '' );
141-
requestTokenRef.current = result.token;
142-
const placeOrderButton = document.querySelector(
143-
'.wc-block-components-button.wp-element-button.wc-block-components-checkout-place-order-button.wc-block-components-checkout-place-order-button'
144-
);
145-
if ( placeOrderButton ) {
146-
placeOrderButton.style.color = '';
147-
placeOrderButton.style.backgroundColor = '';
148-
placeOrderButton.disabled = false;
149-
placeOrderButton.click();
150-
} else {
151-
console.error(
152-
'Place Order button not found.'
153-
);
154-
}
155-
}
156-
},
157-
onError( error ) {
158-
const errorMessage =
159-
error.message ||
160-
`${ error.status || 'Error' } ${
161-
error.statusCode
162-
? `(${ error.statusCode })`
163-
: ''
164-
}`;
165-
setError( errorMessage );
166-
console.error( 'Bizum error:', error );
167-
},
168-
} );
169-
170-
currentBizumInstanceRef.current.render( container );
171-
172-
// Remove skeleton loading state after rendering
173-
setTimeout( () => {
174-
setIsLoading( false );
175-
}, 100 );
129+
createOrRenderBizum( currentTotal );
176130
}
177-
}, [ cartTotals ] );
131+
}, [ cartTotals, createOrRenderBizum ] );
178132

179133
useEffect( () => {
180134
// Don't modify the Place Order button if using redirect flow

assets/js/monei-block-checkout-paypal.js

Lines changed: 56 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -30,52 +30,11 @@
3030
return select( 'wc/store/cart' ).getCartTotals();
3131
}, [] );
3232

33-
useEffect( () => {
34-
// Don't modify the Place Order button if using redirect flow
35-
if ( isRedirectFlow ) {
36-
return;
37-
}
38-
39-
const placeOrderButton = document.querySelector(
40-
'.wc-block-components-checkout-place-order-button'
41-
);
42-
if ( activePaymentMethod === 'monei_paypal' ) {
43-
if ( placeOrderButton ) {
44-
//on hover over the button the text should not change color to white
45-
placeOrderButton.style.color = 'black';
46-
placeOrderButton.style.backgroundColor = '#ccc';
47-
placeOrderButton.disabled = true;
48-
}
49-
}
50-
return () => {
51-
if ( paypalInstanceRef.current ) {
52-
paypalInstanceRef.current.close();
53-
paypalInstanceRef.current = null;
54-
}
55-
if ( placeOrderButton ) {
56-
placeOrderButton.style.color = '';
57-
placeOrderButton.style.backgroundColor = '';
58-
placeOrderButton.disabled = false;
59-
}
60-
};
61-
}, [ activePaymentMethod, isRedirectFlow ] );
62-
6333
/**
64-
* Initialize MONEI PayPal component and handle token creation.
34+
* Create or re-render PayPal instance with specified amount
35+
* @param {number} amount - Payment amount in cents
6536
*/
66-
const initMoneiPayPal = useCallback( () => {
67-
// eslint-disable-next-line no-undef
68-
if ( typeof monei === 'undefined' || ! monei.PayPal ) {
69-
console.error( 'MONEI SDK is not available' );
70-
return;
71-
}
72-
73-
const currentTotal = cartTotals?.total_price
74-
? parseInt( cartTotals.total_price )
75-
: Math.round( paypalData.total * 100 );
76-
77-
lastAmountRef.current = currentTotal;
78-
37+
const createOrRenderPayPal = useCallback( ( amount ) => {
7938
// Clean up existing instance
8039
if ( paypalInstanceRef.current?.close ) {
8140
try {
@@ -103,12 +62,12 @@
10362
accountId: paypalData.accountId,
10463
sessionId: paypalData.sessionId,
10564
language: paypalData.language,
106-
amount: currentTotal,
65+
amount,
10766
currency: paypalData.currency,
10867
style: paypalData.paypalStyle || {},
10968
onSubmit( result ) {
11069
if ( result.token ) {
111-
setError( '' ); // Clear any previous errors
70+
setError( '' );
11271
requestTokenRef.current = result.token;
11372
const placeOrderButton = document.querySelector(
11473
'.wc-block-components-checkout-place-order-button'
@@ -141,7 +100,55 @@
141100
setTimeout( () => {
142101
setIsLoading( false );
143102
}, 1000 );
144-
}, [ cartTotals ] );
103+
}, [] );
104+
105+
useEffect( () => {
106+
// Don't modify the Place Order button if using redirect flow
107+
if ( isRedirectFlow ) {
108+
return;
109+
}
110+
111+
const placeOrderButton = document.querySelector(
112+
'.wc-block-components-checkout-place-order-button'
113+
);
114+
if ( activePaymentMethod === 'monei_paypal' ) {
115+
if ( placeOrderButton ) {
116+
//on hover over the button the text should not change color to white
117+
placeOrderButton.style.color = 'black';
118+
placeOrderButton.style.backgroundColor = '#ccc';
119+
placeOrderButton.disabled = true;
120+
}
121+
}
122+
return () => {
123+
if ( paypalInstanceRef.current ) {
124+
paypalInstanceRef.current.close();
125+
paypalInstanceRef.current = null;
126+
}
127+
if ( placeOrderButton ) {
128+
placeOrderButton.style.color = '';
129+
placeOrderButton.style.backgroundColor = '';
130+
placeOrderButton.disabled = false;
131+
}
132+
};
133+
}, [ activePaymentMethod, isRedirectFlow ] );
134+
135+
/**
136+
* Initialize MONEI PayPal component and handle token creation.
137+
*/
138+
const initMoneiPayPal = useCallback( () => {
139+
// eslint-disable-next-line no-undef
140+
if ( typeof monei === 'undefined' || ! monei.PayPal ) {
141+
console.error( 'MONEI SDK is not available' );
142+
return;
143+
}
144+
145+
const currentTotal = cartTotals?.total_price
146+
? parseInt( cartTotals.total_price )
147+
: Math.round( paypalData.total * 100 );
148+
149+
lastAmountRef.current = currentTotal;
150+
createOrRenderPayPal( currentTotal );
151+
}, [ cartTotals, createOrRenderPayPal ] );
145152

146153
/**
147154
* Update the amount in the existing PayPal instance
@@ -159,74 +166,9 @@
159166
lastAmountRef.current = currentTotal;
160167

161168
if ( paypalInstanceRef.current ) {
162-
// Clean up existing instance
163-
if ( paypalInstanceRef.current?.close ) {
164-
try {
165-
paypalInstanceRef.current.close();
166-
} catch ( e ) {
167-
// Silent fail
168-
}
169-
}
170-
171-
const paypalContainer =
172-
document.getElementById( 'paypal-container' );
173-
if ( ! paypalContainer ) {
174-
return;
175-
}
176-
177-
// Show skeleton loading state
178-
setIsLoading( true );
179-
180-
// Clear container
181-
paypalContainer.innerHTML = '';
182-
183-
// eslint-disable-next-line no-undef
184-
const paypalInstance = monei.PayPal( {
185-
accountId: paypalData.accountId,
186-
sessionId: paypalData.sessionId,
187-
language: paypalData.language,
188-
amount: currentTotal,
189-
currency: paypalData.currency,
190-
style: paypalData.paypalStyle || {},
191-
onSubmit( result ) {
192-
if ( result.token ) {
193-
setError( '' );
194-
requestTokenRef.current = result.token;
195-
const placeOrderButton = document.querySelector(
196-
'.wc-block-components-checkout-place-order-button'
197-
);
198-
if ( placeOrderButton ) {
199-
placeOrderButton.style.color = '';
200-
placeOrderButton.style.backgroundColor = '';
201-
placeOrderButton.disabled = false;
202-
placeOrderButton.click();
203-
} else {
204-
console.error(
205-
'Place Order button not found.'
206-
);
207-
}
208-
}
209-
},
210-
onError( error ) {
211-
const errorMessage =
212-
error.message ||
213-
`${ error.status || 'Error' } - ${
214-
error.statusMessage || 'Payment failed'
215-
}`;
216-
setError( errorMessage );
217-
console.error( 'PayPal error:', error );
218-
},
219-
} );
220-
221-
paypalInstance.render( paypalContainer );
222-
paypalInstanceRef.current = paypalInstance;
223-
224-
// Remove skeleton loading state after rendering
225-
setTimeout( () => {
226-
setIsLoading( false );
227-
}, 1000 );
169+
createOrRenderPayPal( currentTotal );
228170
}
229-
}, [ cartTotals ] );
171+
}, [ cartTotals, createOrRenderPayPal ] );
230172

231173
// Initialize on mount
232174
useEffect( () => {

0 commit comments

Comments
 (0)