@riosst100/pwa-marketplace 2.8.8 → 2.8.9

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.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/src/components/PaymentMethod/PaypalExpress/paypalExpress.js +3 -2
  3. package/src/components/PaymentMethod/Xendit/xendit.js +53 -0
  4. package/src/components/ProductReviewItem/index.js +1 -0
  5. package/src/components/ProductReviewItem/productReviewItem.js +67 -0
  6. package/src/components/SellerReview/sellerReview.js +21 -25
  7. package/src/components/VerifyEmailPage/index.js +1 -0
  8. package/src/components/VerifyEmailPage/verifyEmail.js +79 -0
  9. package/src/components/VerifyEmailPage/verifyEmail.module.css +71 -0
  10. package/src/intercept.js +8 -0
  11. package/src/overwrites/peregrine/lib/talons/CheckoutPage/checkoutPage.extended.gql.js +88 -0
  12. package/src/overwrites/peregrine/lib/talons/CheckoutPage/useCheckoutPage.js +124 -13
  13. package/src/overwrites/peregrine/lib/talons/CheckoutPage/xendit.gql.js +15 -0
  14. package/src/overwrites/venia-ui/lib/components/Checkbox/checkbox.module.css +2 -0
  15. package/src/overwrites/venia-ui/lib/components/CheckoutPage/BillingAddress/billingAddress.module.css +9 -1
  16. package/src/overwrites/venia-ui/lib/components/CheckoutPage/ItemsReview/itemsReview.module.css +3 -2
  17. package/src/overwrites/venia-ui/lib/components/CheckoutPage/OrderConfirmationPage/orderConfirmationPage.js +68 -44
  18. package/src/overwrites/venia-ui/lib/components/CheckoutPage/OrderConfirmationPage/orderConfirmationPage.module.css +102 -5
  19. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PaymentInformation/paymentInformation.module.css +6 -0
  20. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PaymentInformation/paymentMethodCollection.js +6 -20
  21. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PaymentInformation/paymentMethods.js +33 -2
  22. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PaymentInformation/paymentMethods.module.css +13 -3
  23. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PaymentInformation/summary.module.css +3 -1
  24. package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.module.css +14 -3
  25. package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/modalFormReview.js +2 -2
  26. package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/productReview.js +156 -38
  27. package/src/talons/PaymentMethod/PaypalExpress/usePaypalExpress.js +5 -1
@@ -13,10 +13,59 @@ import { setCheckoutState} from '@magento/peregrine/lib/store/actions/cart';
13
13
 
14
14
  import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
15
15
 
16
- import DEFAULT_OPERATIONS from '@magento/peregrine/lib/talons/CheckoutPage/checkoutPage.gql.js';
16
+ import DEFAULT_OPERATIONS from '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/CheckoutPage/checkoutPage.extended.gql.js';
17
17
 
18
18
  import CheckoutError from '@magento/peregrine/lib/talons/CheckoutPage/CheckoutError';
19
19
  import { useGoogleReCaptcha } from '@magento/peregrine/lib/hooks/useGoogleReCaptcha';
20
+ import { XENDIT_CREATE_INVOICE } from '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/CheckoutPage/xendit.gql';
21
+
22
+ // Lightweight UI helper: show a full-screen overlay when redirecting to Xendit
23
+ const XENDIT_OVERLAY_ID = 'xendit-redirect-overlay';
24
+ function showXenditRedirectOverlay() {
25
+ if (typeof document === 'undefined') return;
26
+ if (document.getElementById(XENDIT_OVERLAY_ID)) return;
27
+
28
+ const style = document.createElement('style');
29
+ style.type = 'text/css';
30
+ style.textContent = `@keyframes xendit-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`;
31
+ document.head.appendChild(style);
32
+
33
+ const overlay = document.createElement('div');
34
+ overlay.id = XENDIT_OVERLAY_ID;
35
+ overlay.setAttribute('data-cy', 'xendit-redirect-overlay');
36
+ overlay.style.cssText = [
37
+ 'position:fixed',
38
+ 'inset:0',
39
+ 'background:rgba(0,0,0,0.85)',
40
+ 'color:#fff',
41
+ 'display:flex',
42
+ 'flex-direction:column',
43
+ 'align-items:center',
44
+ 'justify-content:center',
45
+ 'z-index:2147483647',
46
+ 'text-align:center',
47
+ 'padding:24px'
48
+ ].join(';');
49
+
50
+ const spinner = document.createElement('div');
51
+ spinner.style.cssText = [
52
+ 'width:48px',
53
+ 'height:48px',
54
+ 'border:4px solid #ffffff',
55
+ 'border-top-color:transparent',
56
+ 'border-radius:50%',
57
+ 'animation:xendit-spin 1s linear infinite',
58
+ 'margin-bottom:16px'
59
+ ].join(';');
60
+
61
+ const text = document.createElement('div');
62
+ text.textContent = 'Redirecting you to Xendit payment page…';
63
+ text.style.cssText = 'font-size:16px; opacity:0.33;';
64
+
65
+ overlay.appendChild(spinner);
66
+ overlay.appendChild(text);
67
+ document.body.appendChild(overlay);
68
+ }
20
69
 
21
70
  export const CHECKOUT_STEP = {
22
71
  SHIPPING_ADDRESS: 1,
@@ -115,6 +164,12 @@ export const useCheckoutPage = (props = {}) => {
115
164
  }
116
165
  ] = useMutation(placeOrderMutation);
117
166
 
167
+ // Xendit: create invoice after successful placeOrder
168
+ const [
169
+ xenditCreateInvoice,
170
+ { data: xenditInvoiceData, loading: xenditInvoiceLoading, error: xenditInvoiceError }
171
+ ] = useMutation(XENDIT_CREATE_INVOICE);
172
+
118
173
  const [
119
174
  getOrderDetails,
120
175
  { data: orderDetailsData, loading: orderDetailsLoading }
@@ -237,6 +292,9 @@ export const useCheckoutPage = (props = {}) => {
237
292
  }, [checkoutStep]);
238
293
 
239
294
  const [isPlacingOrder, setIsPlacingOrder] = useState(false);
295
+ // When true, we intentionally hide the OrderConfirmationPage (orderNumber)
296
+ // to allow external payment (Xendit) to complete first.
297
+ const [suppressOrderConfirmation, setSuppressOrderConfirmation] = useState(false);
240
298
 
241
299
  const handlePlaceOrder = useCallback(async () => {
242
300
  // Fetch order details and then use an effect to actually place the
@@ -273,20 +331,68 @@ export const useCheckoutPage = (props = {}) => {
273
331
  async function placeOrderAndCleanup() {
274
332
  try {
275
333
  const reCaptchaData = await generateReCaptchaData();
276
-
277
- await placeOrder({
334
+ // Execute placeOrder and get the order number directly from the response
335
+ const placeOrderResult = await placeOrder({
278
336
  variables: {
279
337
  cartId
280
338
  },
281
339
  ...reCaptchaData
282
340
  });
283
- // Cleanup stale cart and customer info.
284
- await removeCart();
285
- await apolloClient.clearCacheData(apolloClient, 'cart');
286
341
 
287
- await createCart({
288
- fetchCartId
289
- });
342
+ const orderNumber =
343
+ placeOrderResult?.data?.placeOrder?.order?.order_number;
344
+ // If payment is Xendit, create invoice and redirect BEFORE cleaning up cart
345
+ const selectedPayment = orderDetailsData?.cart?.selected_payment_method;
346
+ const paymentCode = selectedPayment?.code;
347
+ const paymentTitle = selectedPayment?.title;
348
+ const isXendit =
349
+ (paymentCode && paymentCode.toLowerCase() === 'xendit') ||
350
+ (paymentTitle && paymentTitle.toLowerCase().includes('xendit'));
351
+ if (isXendit && orderNumber) {
352
+ try {
353
+ // Prevent success page from rendering; we'll redirect to Xendit first
354
+ setSuppressOrderConfirmation(true);
355
+ const res = await xenditCreateInvoice({
356
+ variables: { orderId: orderNumber }
357
+ });
358
+ const payload = res?.data?.xenditCreateInvoice;
359
+ const url = payload?.invoice_url;
360
+ if (url) {
361
+ // Show overlay to inform user before redirecting
362
+ showXenditRedirectOverlay();
363
+ // Perform cart cleanup before redirecting away
364
+ try {
365
+ await removeCart();
366
+ await apolloClient.clearCacheData(apolloClient, 'cart');
367
+ await createCart({ fetchCartId });
368
+ } catch (cleanupErr) {
369
+ // eslint-disable-next-line no-console
370
+ console.warn('Cleanup before Xendit redirect failed', cleanupErr);
371
+ }
372
+ // Give the browser a brief moment to paint the overlay
373
+ setTimeout(() => {
374
+ // Redirect in the SAME TAB per requested flow
375
+ window.location.assign(url);
376
+ }, 2000);
377
+ } else {
378
+ // eslint-disable-next-line no-console
379
+ console.warn(
380
+ 'Xendit: invoice_url missing in response'
381
+ );
382
+ }
383
+ } catch (err) {
384
+ // eslint-disable-next-line no-console
385
+ console.error(
386
+ 'Xendit: failed to create invoice',
387
+ err
388
+ );
389
+ }
390
+ } else {
391
+ // Non-Xendit: proceed with normal cleanup
392
+ await removeCart();
393
+ await apolloClient.clearCacheData(apolloClient, 'cart');
394
+ await createCart({ fetchCartId });
395
+ }
290
396
  } catch (err) {
291
397
  console.error(
292
398
  'An error occurred during when placing the order',
@@ -365,7 +471,11 @@ export const useCheckoutPage = (props = {}) => {
365
471
  type: 'CHECKOUT_PLACE_ORDER_BUTTON_CLICKED',
366
472
  payload: eventPayload
367
473
  });
368
- } else if (placeOrderData && orderDetailsData?.cart.id === cartId) {
474
+ } else if (
475
+ placeOrderData &&
476
+ orderDetailsData?.cart.id === cartId &&
477
+ !suppressOrderConfirmation
478
+ ) {
369
479
  dispatch({
370
480
  type: 'ORDER_CONFIRMATION_PAGE_VIEW',
371
481
  payload: {
@@ -386,6 +496,7 @@ export const useCheckoutPage = (props = {}) => {
386
496
  dispatch,
387
497
  placeOrderData,
388
498
  isPlacingOrder,
499
+ suppressOrderConfirmation,
389
500
  reviewOrderButtonClicked
390
501
  ]);
391
502
 
@@ -408,9 +519,9 @@ export const useCheckoutPage = (props = {}) => {
408
519
  isUpdating,
409
520
  orderDetailsData,
410
521
  orderDetailsLoading,
411
- orderNumber:
412
- (placeOrderData && placeOrderData.placeOrder.order.order_number) ||
413
- null,
522
+ orderNumber: suppressOrderConfirmation
523
+ ? null
524
+ : (placeOrderData && placeOrderData.placeOrder.order.order_number) || null,
414
525
  placeOrderLoading,
415
526
  placeOrderButtonClicked,
416
527
  setCheckoutStep,
@@ -0,0 +1,15 @@
1
+ import { gql } from '@apollo/client';
2
+
3
+ export const XENDIT_CREATE_INVOICE = gql`
4
+ mutation xenditCreateInvoice($orderId: String!) {
5
+ xenditCreateInvoice(input: { order_id: $orderId }) {
6
+ invoice_url
7
+ mode
8
+ xendit_qrcode_external_id
9
+ }
10
+ }
11
+ `;
12
+
13
+ export default {
14
+ XENDIT_CREATE_INVOICE
15
+ };
@@ -10,6 +10,8 @@
10
10
  composes: text-colorDefault from global;
11
11
  grid-template-areas: 'input label';
12
12
  grid-template-columns: min-content 1fr;
13
+ margin-left: 5px;
14
+ margin-top: 5px;
13
15
  }
14
16
 
15
17
  .input {
@@ -23,7 +23,10 @@
23
23
 
24
24
  composes: lg_col-end-span1 from global;
25
25
  }
26
-
26
+ .cardTitle{
27
+ font-weight: 500;
28
+ font-size: 16px;
29
+ }
27
30
  .country,
28
31
  .street1,
29
32
  .street2,
@@ -33,4 +36,9 @@
33
36
  .postal_code,
34
37
  .phone_number {
35
38
  composes: col-end-span2 from global;
39
+ margin-left: 5px;
36
40
  }
41
+ .address_check{
42
+ margin-top: 5px;
43
+ margin-left: 5px;
44
+ }
@@ -1,7 +1,8 @@
1
1
  .items_review_container {
2
- composes: border-2 from global;
2
+ composes: border-1 from global;
3
3
  composes: border-solid from global;
4
- composes: border-subtle from global;
4
+ /* composes: border-subtle from global; */
5
+ border: 1px solid #E6E9EA;
5
6
  composes: rounded-md from global;
6
7
  min-height: 2rem;
7
8
  }
@@ -5,6 +5,7 @@ import { useOrderConfirmationPage } from '@magento/peregrine/lib/talons/Checkout
5
5
 
6
6
  import { useStyle } from '@magento/venia-ui/lib/classify';
7
7
  import { StoreTitle } from '@magento/venia-ui/lib/components/Head';
8
+ import { Link } from 'react-router-dom';
8
9
  import CreateAccount from './createAccount';
9
10
  import ItemsReview from '../ItemsReview';
10
11
  import defaultClasses from './orderConfirmationPage.module.css';
@@ -63,6 +64,8 @@ const OrderConfirmationPage = props => {
63
64
  const nameString = `${firstname} ${lastname}`;
64
65
  const additionalAddressString = `${city}, ${region} ${postcode} ${country}`;
65
66
 
67
+ // copy button removed per request
68
+
66
69
  return (
67
70
  <div className={classes.root} data-cy="OrderConfirmationPage-root">
68
71
  <StoreTitle>
@@ -72,52 +75,73 @@ const OrderConfirmationPage = props => {
72
75
  })}
73
76
  </StoreTitle>
74
77
  <div className={classes.mainContainer}>
75
- <h2
76
- data-cy="OrderConfirmationPage-header"
77
- className={classes.heading}
78
- >
79
- <FormattedMessage
80
- id={'checkoutPage.thankYou'}
81
- defaultMessage={'Thank you for your order!'}
82
- />
83
- </h2>
84
- <div
85
- data-cy="OrderConfirmationPage-orderNumber"
86
- className={classes.orderNumber}
87
- >
88
- <FormattedMessage
89
- id={'checkoutPage.orderNumber'}
90
- defaultMessage={'Order Number: {orderNumber}'}
91
- values={{ orderNumber }}
92
- />
93
- </div>
94
- <div
95
- data-cy="OrderConfirmationPage-shippingInfoHeading"
96
- className={classes.shippingInfoHeading}
97
- >
98
- <FormattedMessage
99
- id={'global.shippingInformation'}
100
- defaultMessage={'Shipping Information'}
101
- />
102
- </div>
103
- <div className={classes.shippingInfo}>
104
- <span className={classes.email}>{email}</span>
105
- <span className={classes.name}>{nameString}</span>
106
- {streetRows}
107
- <span className={classes.addressAdditional}>
108
- {additionalAddressString}
109
- </span>
78
+ <div className={classes.successHeader}>
79
+ <div className={classes.iconCheck} aria-hidden="true">
80
+ <svg width="48" height="48" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
81
+ <circle cx="12" cy="12" r="11" stroke="currentColor" strokeWidth="2" opacity="0.4" />
82
+ <path d="M7 12.5L10.2 16L17 8" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
83
+ </svg>
84
+ </div>
85
+ <h2
86
+ data-cy="OrderConfirmationPage-header"
87
+ className={classes.heading}
88
+ >
89
+ <FormattedMessage
90
+ id={'checkoutPage.thankYou'}
91
+ defaultMessage={'Thank you for your order!'}
92
+ />
93
+ </h2>
94
+ <div
95
+ data-cy="OrderConfirmationPage-orderNumber"
96
+ className={classes.orderNumberRow}
97
+ >
98
+ <div className={classes.orderNumberText}>
99
+ <FormattedMessage
100
+ id={'checkoutPage.orderNumber'}
101
+ defaultMessage={'Order Number: {orderNumber}'}
102
+ values={{ orderNumber }}
103
+ />
104
+ </div>
105
+ </div>
106
+ <div className={classes.actions}>
107
+ <Link to="/" className={classes.primaryAction} data-cy="OrderConfirmationPage-continueShopping">
108
+ <FormattedMessage id={'checkoutPage.continueShopping'} defaultMessage={'Continue Shopping'} />
109
+ </Link>
110
+ </div>
110
111
  </div>
111
- <div
112
- data-cy="OrderConfirmationPage-shippingMethodHeading"
113
- className={classes.shippingMethodHeading}
114
- >
115
- <FormattedMessage
116
- id={'global.shippingMethod'}
117
- defaultMessage={'Shipping Method'}
118
- />
112
+ <div className={classes.detailsGrid}>
113
+ <div className={classes.card}>
114
+ <div
115
+ data-cy="OrderConfirmationPage-shippingInfoHeading"
116
+ className={classes.cardHeading}
117
+ >
118
+ <FormattedMessage
119
+ id={'global.shippingInformation'}
120
+ defaultMessage={'Shipping Information'}
121
+ />
122
+ </div>
123
+ <div className={classes.shippingInfo}>
124
+ <span className={classes.email}>{email}</span>
125
+ <span className={classes.name}>{nameString}</span>
126
+ {streetRows}
127
+ <span className={classes.addressAdditional}>
128
+ {additionalAddressString}
129
+ </span>
130
+ </div>
131
+ </div>
132
+ <div className={classes.card}>
133
+ <div
134
+ data-cy="OrderConfirmationPage-shippingMethodHeading"
135
+ className={classes.cardHeading}
136
+ >
137
+ <FormattedMessage
138
+ id={'global.shippingMethod'}
139
+ defaultMessage={'Shipping Method'}
140
+ />
141
+ </div>
142
+ <div className={classes.shippingMethod}>{shippingMethod}</div>
143
+ </div>
119
144
  </div>
120
- <div className={classes.shippingMethod}>{shippingMethod}</div>
121
145
  <div className={classes.itemsReview}>
122
146
  <ItemsReview data={data} />
123
147
  </div>
@@ -1,4 +1,3 @@
1
- /* prettier-ignore */
2
1
  .root {
3
2
  composes: gap-xs from global;
4
3
  composes: grid from global;
@@ -9,17 +8,17 @@
9
8
  composes: px-sm from global;
10
9
  composes: py-sm from global;
11
10
 
12
- composes: lg_gap-md from global;
11
+ /* composes: lg_gap-md from global; */
13
12
  /* TODO @TW: review (B7) */
14
- composes: lg_grid-cols-[2fr,1fr] from global;
13
+ /* composes: lg_grid-cols-[2fr,1fr] from global;
15
14
  composes: lg_px-lg from global;
16
- composes: lg_py-md from global;
15
+ composes: lg_py-md from global; */
17
16
  }
18
17
 
19
18
  .mainContainer {
20
19
  composes: col-start-1 from global;
21
20
  composes: grid from global;
22
- composes: gap-y-xs from global;
21
+ composes: gap-y-sm from global;
23
22
  }
24
23
 
25
24
  .sidebarContainer {
@@ -44,6 +43,72 @@
44
43
  composes: header;
45
44
  }
46
45
 
46
+ .successHeader {
47
+ composes: grid from global;
48
+ composes: gap-y-xs from global;
49
+ composes: rounded-md from global;
50
+ composes: border from global;
51
+ border-color: #E6E9EA;
52
+ composes: bg-surface from global;
53
+ composes: p-md from global;
54
+ composes: text-center from global;
55
+ }
56
+
57
+ .iconCheck {
58
+ composes: mx-auto from global;
59
+ composes: h-14 from global;
60
+ composes: w-14 from global;
61
+ color: #f76b1c;
62
+ }
63
+
64
+ .orderNumberRow {
65
+ composes: flex from global;
66
+ composes: items-center from global;
67
+ composes: justify-center from global;
68
+ composes: gap-x-xs from global;
69
+ }
70
+
71
+ .orderNumberText {
72
+ composes: header;
73
+ }
74
+
75
+ .copyBtn {
76
+ composes: text-sm from global;
77
+ composes: px-sm from global;
78
+ composes: py-2xs from global;
79
+ composes: rounded from global;
80
+ composes: border from global;
81
+ composes: border-subtle from global;
82
+ composes: hover_bg-subtle from global;
83
+ }
84
+
85
+ .actions {
86
+ composes: flex from global;
87
+ composes: gap-x-xs from global;
88
+ composes: justify-center from global;
89
+ }
90
+
91
+ .primaryAction {
92
+ composes: inline-flex from global;
93
+ composes: items-center from global;
94
+ composes: justify-center from global;
95
+ composes: px-lg from global;
96
+ composes: py-xs from global;
97
+ composes: rounded-full from global;
98
+ composes: font-semibold from global;
99
+ color: #fff;
100
+ background: #f76b1c;
101
+ border: 1px solid #f76b1c;
102
+ }
103
+
104
+ .primaryAction:hover {
105
+ color: #fff;
106
+ background: #f26313;
107
+ border: 1px solid #f26313;
108
+ }
109
+
110
+ .secondaryAction { display: none; }
111
+
47
112
  .shippingInfoHeading {
48
113
  composes: header;
49
114
  }
@@ -68,3 +133,35 @@
68
133
  .additionalText {
69
134
  composes: text;
70
135
  }
136
+
137
+ .detailsGrid {
138
+ composes: grid from global;
139
+ composes: gap-sm from global;
140
+ composes: md_grid-cols-2 from global;
141
+ }
142
+
143
+ .card {
144
+ composes: rounded-md from global;
145
+ composes: border from global;
146
+ border-color: #E6E9EA;
147
+ composes: bg-surface from global;
148
+ composes: p-md from global;
149
+ }
150
+
151
+ .cardHeading {
152
+ composes: header;
153
+ composes: mb-2xs from global;
154
+ }
155
+
156
+ .itemsReview {
157
+ composes: rounded-md from global;
158
+ composes: border from global;
159
+ border-color: #E6E9EA;
160
+ composes: bg-surface from global;
161
+ composes: p-md from global;
162
+ }
163
+
164
+ .heading {
165
+ composes: font-bold from global;
166
+ composes: text-2xl from global;
167
+ }
@@ -20,4 +20,10 @@
20
20
  composes: border-0 from global;
21
21
 
22
22
  composes: lg_border from global;
23
+ }
24
+
25
+ .cardTitle {
26
+ composes: font-medium from global;
27
+ composes: text-[16px] from global;
28
+ composes: ml-[5px] from global;
23
29
  }
@@ -1,23 +1,9 @@
1
1
  /**
2
- * This file is augmented at build time using the @magento/venia-ui build
3
- * target "checkoutPagePaymentTypes", which allows third-party modules to
4
- * add new payment component mappings for the checkout page.
2
+ * Delegate to Venia's canonical payment method collection so build-target
3
+ * augmentation (checkoutPagePaymentTypes) from third-party integrations works.
5
4
  *
6
- * @see [Payment definition object]{@link PaymentDefinition}
7
- */
8
- export default {};
9
-
10
- /**
11
- * A payment definition object that describes a payment in your storefront.
12
- *
13
- * @typedef {Object} PaymentDefinition
14
- * @property {string} paymentCode is use to map your payment
15
- * @property {string} importPath Resolvable path to the component the
16
- * Route component will render
17
- *
18
- * @example <caption>A custom payment method</caption>
19
- * const myCustomPayment = {
20
- * paymentCode: 'cc',
21
- * importPath: '@partner/module/path_to_your_component'
22
- * }
5
+ * Note: Keeping a local empty object here prevents integrations like
6
+ * Stripe/MultiSafepay from registering their UI components, resulting in
7
+ * "There was an error loading payments" on checkout.
23
8
  */
9
+ export { default } from '@magento/venia-ui/lib/components/CheckoutPage/PaymentInformation/paymentMethodCollection';
@@ -37,7 +37,30 @@ const PaymentMethods = props => {
37
37
  return null;
38
38
  }
39
39
 
40
- console.log('payments', payments)
40
+ // Warn if Magento exposes payment methods that don't have a mapped UI component.
41
+ const knownCodes = Object.keys(payments);
42
+ const unknownMethods = availablePaymentMethods.filter(
43
+ ({ code }) => !knownCodes.includes(code)
44
+ );
45
+ if (unknownMethods.length) {
46
+ // eslint-disable-next-line no-console
47
+ console.warn(
48
+ 'Checkout: Ditemukan metode pembayaran yang belum dipetakan:',
49
+ unknownMethods.map(m => m.code),
50
+ '\nPastikan metode tersebut terdaftar melalui target build Venia "checkoutPagePaymentTypes" atau ditambahkan ke paymentMethodCollection.'
51
+ );
52
+ }
53
+
54
+ // Title fallback map to ensure labels are always visible.
55
+ const TITLE_FALLBACK = {
56
+ braintree: 'Credit/Debit Card',
57
+ paypal_express: 'PayPal Express Checkout',
58
+ paypal_express_bml: 'PayPal Credit',
59
+ checkmo: 'Check / Money Order',
60
+ xendit: 'Xendit',
61
+ cc: 'Credit Card',
62
+ free: 'Free'
63
+ };
41
64
 
42
65
  const radios = availablePaymentMethods
43
66
  .map(({ code, title }) => {
@@ -48,6 +71,7 @@ const PaymentMethods = props => {
48
71
 
49
72
  const id = `paymentMethod--${code}`;
50
73
  const isSelected = currentSelectedPaymentMethod === code;
74
+ const displayTitle = title || TITLE_FALLBACK[code] || code;
51
75
  const PaymentMethodComponent = payments[code];
52
76
  const renderedComponent = isSelected ? (
53
77
  <PaymentMethodComponent
@@ -55,6 +79,7 @@ const PaymentMethods = props => {
55
79
  onPaymentError={onPaymentError}
56
80
  resetShouldSubmit={resetShouldSubmit}
57
81
  shouldSubmit={shouldSubmit}
82
+ currentSelectedPaymentMethod={currentSelectedPaymentMethod}
58
83
  />
59
84
  ) : null;
60
85
 
@@ -62,7 +87,7 @@ const PaymentMethods = props => {
62
87
  <div key={code} className={classes.payment_method}>
63
88
  <Radio
64
89
  id={id}
65
- label={title}
90
+ label={displayTitle}
66
91
  value={code}
67
92
  classes={{
68
93
  label: classes.radio_label
@@ -95,6 +120,12 @@ const PaymentMethods = props => {
95
120
 
96
121
  return (
97
122
  <div className={classes.root}>
123
+ <h5 className={classes.cardTitle}>
124
+ {formatMessage({
125
+ id: 'checkoutPage.paymentInformation',
126
+ defaultMessage: 'Payment Information'
127
+ })}
128
+ </h5>
98
129
  <RadioGroup
99
130
  classes={{ root: classes.radio_group }}
100
131
  field="selectedPaymentMethod"
@@ -1,7 +1,8 @@
1
1
  .root {
2
2
  composes: grid from global;
3
- composes: p-md from global;
3
+ /* composes: p-md from global; */
4
4
  composes: pb-s from global;
5
+ padding: 1rem;
5
6
  }
6
7
 
7
8
  .radio_group {
@@ -10,10 +11,11 @@
10
11
 
11
12
  .payment_method {
12
13
  composes: border-b from global;
13
- composes: border-solid from global;
14
- composes: border-subtle from global;
14
+ /* composes: border-solid from global; */
15
+ /* composes: border-subtle from global; */
15
16
  composes: pb-xs from global;
16
17
  composes: pt-xs from global;
18
+ border-color: lightgray;
17
19
  }
18
20
 
19
21
  /* TODO @TW: cannot compose */
@@ -32,3 +34,11 @@
32
34
  composes: gap-2xs from global;
33
35
  composes: text-error from global;
34
36
  }
37
+ .cardTitle{
38
+ font-weight: 500;
39
+ font-size: 16px;
40
+ }
41
+ .address_check{
42
+ margin-left: 5px;
43
+ margin-top: 5px;
44
+ }