@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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@riosst100/pwa-marketplace",
3
3
  "author": "riosst100@gmail.com",
4
- "version": "2.8.8",
4
+ "version": "2.8.9",
5
5
  "main": "src/index.js",
6
6
  "pwa-studio": {
7
7
  "targets": {
@@ -3,7 +3,7 @@ import {mergeClasses} from '@magento/venia-ui/lib/classify';
3
3
  import {shape, string, bool, func} from 'prop-types';
4
4
  import BillingAddress from '@magento/venia-ui/lib/components/CheckoutPage/BillingAddress';
5
5
 
6
- import {usePaypalExpress} from '../../talons/PaymentMethod/PaypalExpress/usePaypalExpress';
6
+ import {usePaypalExpress} from '@riosst100/pwa-marketplace/src/talons/PaymentMethod/PaypalExpress/usePaypalExpress';
7
7
  import defaultClasses from './paypalExpress.css';
8
8
  import {FormattedMessage} from 'react-intl';
9
9
 
@@ -56,7 +56,8 @@ PaypalExpress.propTypes = {
56
56
  shouldSubmit: bool.isRequired,
57
57
  onPaymentSuccess: func,
58
58
  onPaymentError: func,
59
- resetShouldSubmit: func.isRequired
59
+ resetShouldSubmit: func.isRequired,
60
+ currentSelectedPaymentMethod: string
60
61
  };
61
62
 
62
63
  export default PaypalExpress;
@@ -0,0 +1,53 @@
1
+ import React, { useEffect, useCallback } from 'react';
2
+ import { shape, string, bool, func } from 'prop-types';
3
+ import { mergeClasses } from '@magento/venia-ui/lib/classify';
4
+ import BillingAddress from '@magento/venia-ui/lib/components/CheckoutPage/BillingAddress';
5
+
6
+ // Keep styles minimal; reuse global utilities if needed
7
+ const defaultClasses = {};
8
+
9
+ /**
10
+ * Xendit payment component (minimal flow)
11
+ * - Assumes method is set via Radio change.
12
+ * - Syncs billing address and advances on submit.
13
+ * - Extend to add Xendit tokenization/redirect before calling onPaymentSuccess.
14
+ */
15
+ const Xendit = props => {
16
+ const classes = mergeClasses(defaultClasses, props.classes);
17
+ const { shouldSubmit, onPaymentSuccess, resetShouldSubmit } = props;
18
+
19
+ useEffect(() => {
20
+ if (shouldSubmit) {
21
+ onPaymentSuccess && onPaymentSuccess();
22
+ }
23
+ }, [shouldSubmit, onPaymentSuccess]);
24
+
25
+ const onBillingAddressChangedError = useCallback(() => {
26
+ resetShouldSubmit && resetShouldSubmit();
27
+ }, [resetShouldSubmit]);
28
+
29
+ const onBillingAddressChangedSuccess = useCallback(() => {
30
+ /* Hook: start Xendit tokenization here if required by your backend */
31
+ }, []);
32
+
33
+ return (
34
+ <div className={classes.root}>
35
+ <BillingAddress
36
+ shouldSubmit={shouldSubmit}
37
+ resetShouldSubmit={resetShouldSubmit}
38
+ onBillingAddressChangedError={onBillingAddressChangedError}
39
+ onBillingAddressChangedSuccess={onBillingAddressChangedSuccess}
40
+ />
41
+ </div>
42
+ );
43
+ };
44
+
45
+ Xendit.propTypes = {
46
+ classes: shape({ root: string }),
47
+ shouldSubmit: bool.isRequired,
48
+ onPaymentSuccess: func,
49
+ onPaymentError: func,
50
+ resetShouldSubmit: func.isRequired
51
+ };
52
+
53
+ export default Xendit;
@@ -0,0 +1 @@
1
+ export { default } from './productReviewItem';
@@ -0,0 +1,67 @@
1
+ import React, { useState } from 'react';
2
+ import Pagination from '../Pagination';
3
+ import { Star1 } from 'iconsax-react';
4
+
5
+ const ProductReviewItem = ({ reviews }) => {
6
+
7
+ // count stars
8
+ const getStarCounts = () => {
9
+ const counts = { 5: 0, 4: 0, 3: 0, 2: 0, 1: 0 };
10
+ if (reviews && reviews.items) {
11
+ reviews.items.forEach(item => {
12
+ if (counts[item.rating] !== undefined) {
13
+ counts[item.rating]++;
14
+ }
15
+ });
16
+ }
17
+ return counts;
18
+ };
19
+ const starCounts = getStarCounts();
20
+
21
+ const displayedReviews = reviews && reviews.items ? reviews.items : [];
22
+
23
+ return (
24
+ <>
25
+ <div className="flex-1">
26
+ <div className="space-y-4 mb-6">
27
+ {displayedReviews.map((review, index) => (
28
+ <div key={index} className="border border-[#E6E9EA] rounded-md p-4">
29
+ <div className="flex items-center mb-2">
30
+ <div className="w-10 h-10 rounded-full bg-indigo-600 text-white flex items-center justify-center font-bold mr-3">
31
+ Pict
32
+ </div>
33
+ <div>
34
+ <div className="font-medium">{review.name}</div>
35
+ <div className="text-gray-500 text-sm">{review.date}</div>
36
+ </div>
37
+ </div>
38
+
39
+ <div className="flex mb-3">
40
+ {[...Array(5)].map((_, i) => (
41
+ <Star1
42
+ key={i}
43
+ color={i < review.rating ? '#F7C317' : '#D9D9D9'}
44
+ size={16}
45
+ className={i < review.rating ? 'fill-[#F7C317]' : ''}
46
+ />
47
+ ))}
48
+ </div>
49
+ <p className="text-gray-700">{review.comment}</p>
50
+ </div>
51
+ ))}
52
+ </div>
53
+ <div className="flex justify-center">
54
+ {reviews && reviews.page_info && reviews.page_info.total_pages > 0 && (
55
+ <Pagination
56
+ currentPage={reviews.page_info.current_page}
57
+ totalPages={reviews.page_info.total_pages}
58
+ pageSize={reviews.page_info.page_size}
59
+ />
60
+ )}
61
+ </div>
62
+ </div>
63
+ </>
64
+ )
65
+ }
66
+
67
+ export default ProductReviewItem;
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import SellerReviewItem from '../SellerReviewItem';
3
3
  import Pagination from '../Pagination';
4
4
  import { Star1 } from 'iconsax-react';
@@ -41,6 +41,7 @@ const SellerReview = ({ seller }) => {
41
41
  // });
42
42
  // const { reviews, loading } = talonProps;
43
43
 
44
+ const [filter, setFilter] = useState('All');
44
45
  const reviews = dummyReviews;
45
46
 
46
47
  // count stars
@@ -55,9 +56,13 @@ const SellerReview = ({ seller }) => {
55
56
  }
56
57
  return counts;
57
58
  };
58
-
59
59
  const starCounts = getStarCounts();
60
60
 
61
+ // Filter reviews sesuai rating
62
+ const filteredReviews = filter === 'All'
63
+ ? reviews.items
64
+ : reviews.items.filter(item => item.rating === parseInt(filter));
65
+
61
66
  return (
62
67
  <>
63
68
  <div className='w-full'>
@@ -68,7 +73,6 @@ const SellerReview = ({ seller }) => {
68
73
  <div className='w-full flex items-start xs_flex-col lg_flex-row gap-[30px]'>
69
74
  <div className="w-full xs_max-w-full lg_max-w-[365px] border border-[#E6E9EA] rounded-md p-6">
70
75
  <div className="flex justify-between items-start mb-1">
71
- {/* Left - Star rating */}
72
76
  <div className="flex flex-col">
73
77
  <div className="flex items-center gap-1 mb-1">
74
78
  {[...Array(5)].map((_, i) => (
@@ -93,7 +97,6 @@ const SellerReview = ({ seller }) => {
93
97
  </div>
94
98
  </div>
95
99
 
96
- {/* Rating Bars */}
97
100
  <div className="mt-4">
98
101
  {[5, 4, 3, 2, 1].map(star => {
99
102
  const count = starCounts[star] || 0;
@@ -101,21 +104,17 @@ const SellerReview = ({ seller }) => {
101
104
 
102
105
  return (
103
106
  <div key={star} className="flex items-center mb-2">
104
- {/* Star number */}
105
107
  <div className="flex items-center mr-2">
106
108
  <Star1 color="#F7C317" size={14} className="fill-[#F7C317]" />
107
109
  <span className="text-sm ml-1">{star}</span>
108
110
  </div>
109
111
 
110
- {/* Progress bar */}
111
112
  <div className="relative h-[8px] flex-1 bg-[#E4EBF5] rounded-sm mr-2">
112
113
  <div
113
114
  className="absolute h-[8px] bg-[#FF7A00] rounded-sm"
114
115
  style={{width: `${percentage}%`}}
115
116
  />
116
117
  </div>
117
-
118
- {/* Percentage */}
119
118
  <span className="text-sm text-right">{percentage}%</span>
120
119
  </div>
121
120
  );
@@ -123,24 +122,25 @@ const SellerReview = ({ seller }) => {
123
122
  </div>
124
123
  </div>
125
124
 
126
- {/* Right Column - Reviews */}
127
125
  <div className="flex-1">
128
- {/* Filter */}
129
126
  <div className="flex items-center mb-6">
130
127
  <span className="font-medium mr-3">Filter By</span>
131
- <select className="border border-[#E6E9EA] rounded px-3 py-2 text-sm">
132
- <option>All Stars</option>
133
- <option>5 Stars</option>
134
- <option>4 Stars</option>
135
- <option>3 Stars</option>
136
- <option>2 Stars</option>
137
- <option>1 Stars</option>
128
+ <select
129
+ className="border border-[#E6E9EA] rounded px-3 py-2 text-sm"
130
+ value={filter}
131
+ onChange={e => setFilter(e.target.value)}
132
+ >
133
+ <option value="All">All Stars</option>
134
+ <option value="5">5 Stars</option>
135
+ <option value="4">4 Stars</option>
136
+ <option value="3">3 Stars</option>
137
+ <option value="2">2 Stars</option>
138
+ <option value="1">1 Stars</option>
138
139
  </select>
139
140
  </div>
140
-
141
- {/* Reviews List */}
141
+
142
142
  <div className="space-y-4 mb-6">
143
- {reviews && reviews.items && reviews.items.map((review, index) => (
143
+ {filteredReviews.map((review, index) => (
144
144
  <div key={index} className="border border-[#E6E9EA] rounded-md p-4">
145
145
  <div className="flex items-center mb-2">
146
146
  <div className="w-10 h-10 rounded-full bg-indigo-600 text-white flex items-center justify-center font-bold mr-3">
@@ -151,8 +151,7 @@ const SellerReview = ({ seller }) => {
151
151
  <div className="text-gray-500 text-sm">{review.date}</div>
152
152
  </div>
153
153
  </div>
154
-
155
- {/* Star Rating */}
154
+
156
155
  <div className="flex mb-3">
157
156
  {[...Array(5)].map((_, i) => (
158
157
  <Star1
@@ -163,14 +162,11 @@ const SellerReview = ({ seller }) => {
163
162
  />
164
163
  ))}
165
164
  </div>
166
-
167
- {/* Review Text */}
168
165
  <p className="text-gray-700">{review.comment}</p>
169
166
  </div>
170
167
  ))}
171
168
  </div>
172
169
 
173
- {/* Pagination */}
174
170
  <div className="flex justify-center">
175
171
  {reviews && reviews.page_info && reviews.page_info.total_pages > 0 && (
176
172
  <Pagination
@@ -0,0 +1 @@
1
+ export { default } from './verifyEmail';
@@ -0,0 +1,79 @@
1
+ import React from 'react';
2
+ import { useQuery } from '@apollo/client';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import { shape, string } from 'prop-types';
5
+ import { useStyle } from '@magento/venia-ui/lib/classify';
6
+ import defaultClasses from './verifyEmail.module.css';
7
+ import { GET_CUSTOMER_INFORMATION } from '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/AccountInformationPage/accountInformationPage.gql';
8
+
9
+
10
+ const VerifyEmailPage = props => {
11
+ const classes = useStyle(defaultClasses, props.classes);
12
+ const { data, loading } = useQuery(GET_CUSTOMER_INFORMATION);
13
+ const email = data?.customer?.email || '';
14
+
15
+ return (
16
+ <div className={classes.root}>
17
+ <div className={classes.card}>
18
+ <h2 className={classes.title}>
19
+ <FormattedMessage
20
+ id={'verifyEmail.title'}
21
+ defaultMessage={'Please verify your email'}
22
+ />
23
+ </h2>
24
+ <p className={classes.subtitle}>
25
+ <FormattedMessage
26
+ id={'verifyEmail.sentTo'}
27
+ defaultMessage={'You\'re almost there! We sent an email to'}
28
+ />
29
+ <br />
30
+ <span className={classes.email}>{loading ? '.......' : email}</span>
31
+ </p>
32
+ <p className={classes.instructions}>
33
+ <FormattedMessage
34
+ id={'verifyEmail.instructions'}
35
+ defaultMessage={'Just click on the link in that email to complete your signup. If you don\'t see it, you may need to check your spam folder.'}
36
+ />
37
+ </p>
38
+ <button
39
+ className={classes.resendButton}
40
+ type="button"
41
+ onClick={() => alert('Resend email logic goes here')}
42
+ >
43
+ <FormattedMessage
44
+ id={'verifyEmail.resend'}
45
+ defaultMessage={'Resend Email'}
46
+ />
47
+ </button>
48
+ <div className={classes.contactHelp}>
49
+ <FormattedMessage
50
+ id={'verifyEmail.needHelp'}
51
+ defaultMessage={'Need help?'}
52
+ />{' '}
53
+ <a href="/contact" className={classes.contactLink}>
54
+ <FormattedMessage
55
+ id={'verifyEmail.contactUs'}
56
+ defaultMessage={'Contact Us'}
57
+ />
58
+ </a>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ );
63
+ };
64
+
65
+ VerifyEmailPage.propTypes = {
66
+ classes: shape({
67
+ root: string,
68
+ card: string,
69
+ title: string,
70
+ subtitle: string,
71
+ email: string,
72
+ instructions: string,
73
+ resendButton: string,
74
+ contactHelp: string,
75
+ contactLink: string
76
+ })
77
+ };
78
+
79
+ export default VerifyEmailPage;
@@ -0,0 +1,71 @@
1
+ .root {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ justify-content: center;
6
+ min-height: 80vh;
7
+ background: #f8f9fa;
8
+ font-family: inherit;
9
+ }
10
+
11
+ .card {
12
+ background: #fff;
13
+ border-radius: 8px;
14
+ box-shadow: 0 2px 8px rgba(0,0,0,0.08);
15
+ padding: 32px 40px;
16
+ max-width: 700px;
17
+ width: 100%;
18
+ text-align: center;
19
+ }
20
+
21
+ .title {
22
+ margin-bottom: 16px;
23
+ color: #222;
24
+ font-size: 1.5rem;
25
+ font-weight: 600;
26
+ }
27
+
28
+ .subtitle {
29
+ margin-bottom: 8px;
30
+ color: #555;
31
+ font-size: 1rem;
32
+ }
33
+
34
+ .email {
35
+ font-weight: bold;
36
+ color: #eb5202;
37
+ }
38
+
39
+ .instructions {
40
+ margin-bottom: 16px;
41
+ color: #555;
42
+ font-size: 1rem;
43
+ }
44
+
45
+ .resendButton {
46
+ background: #eb5202;
47
+ color: #fff;
48
+ border: none;
49
+ border-radius: 4px;
50
+ padding: 10px 24px;
51
+ font-size: 16px;
52
+ cursor: pointer;
53
+ margin-bottom: 12px;
54
+ }
55
+ .resendButton:hover {
56
+ background: #ba4000;
57
+ border-color: #b84002;
58
+ box-shadow: 0 0 0 1px #b84002;
59
+ color: #fff;
60
+ text-decoration: none;
61
+
62
+ }
63
+ .contactHelp {
64
+ margin-top: 8px;
65
+ font-size: 14px;
66
+ }
67
+
68
+ .contactLink {
69
+ color: #eb5202;
70
+ text-decoration: underline;
71
+ }
package/src/intercept.js CHANGED
@@ -34,6 +34,7 @@ module.exports = targets => {
34
34
  plugin => plugin instanceof LocalizationPlugin
35
35
  );
36
36
 
37
+ // ...existing code...
37
38
  // Check if LocalizationPlugin is found
38
39
  if (localizationPlugin) {
39
40
  // Store the original mergeLocales function
@@ -86,6 +87,13 @@ module.exports = targets => {
86
87
  authed: true,
87
88
  redirectTo: "/sign-in"
88
89
  },
90
+ {
91
+ exact: true,
92
+ name: "VerifyEmailPage",
93
+ pattern: "/verify-email",
94
+ path: require.resolve("./components/VerifyEmailPage/index.js"),
95
+ authed: true,
96
+ },
89
97
  {
90
98
  exact: true,
91
99
  name: "SellerAccountRoute",
@@ -0,0 +1,88 @@
1
+ import { gql } from '@apollo/client';
2
+ import { CheckoutPageFragment } from '@magento/peregrine/lib/talons/CheckoutPage/checkoutPageFragments.gql';
3
+ import { ItemsReviewFragment } from '@magento/peregrine/lib/talons/CheckoutPage/ItemsReview/itemsReviewFragments.gql';
4
+
5
+ export const CREATE_CART = gql`
6
+ mutation createCart {
7
+ cartId: createEmptyCart
8
+ }
9
+ `;
10
+
11
+ export const PLACE_ORDER = gql`
12
+ mutation placeOrder($cartId: String!) {
13
+ placeOrder(input: { cart_id: $cartId }) {
14
+ order {
15
+ order_number
16
+ }
17
+ }
18
+ }
19
+ `;
20
+
21
+ // Extended to include selected_payment_method.code
22
+ export const GET_ORDER_DETAILS = gql`
23
+ query getOrderDetails($cartId: String!) {
24
+ cart(cart_id: $cartId) {
25
+ id
26
+ email
27
+ total_quantity
28
+ shipping_addresses {
29
+ firstname
30
+ lastname
31
+ street
32
+ city
33
+ region { label }
34
+ postcode
35
+ country { label }
36
+ selected_shipping_method {
37
+ amount { value currency }
38
+ carrier_title
39
+ method_title
40
+ }
41
+ }
42
+ selected_payment_method {
43
+ code
44
+ purchase_order_number
45
+ title
46
+ }
47
+ prices {
48
+ grand_total { value currency }
49
+ discounts {
50
+ amount { currency value }
51
+ label
52
+ }
53
+ }
54
+ ...ItemsReviewFragment
55
+ }
56
+ }
57
+ ${ItemsReviewFragment}
58
+ `;
59
+
60
+ export const GET_CHECKOUT_DETAILS = gql`
61
+ query getCheckoutDetails($cartId: String!) {
62
+ cart(cart_id: $cartId) {
63
+ id
64
+ ...CheckoutPageFragment
65
+ ...ItemsReviewFragment
66
+ }
67
+ }
68
+ ${CheckoutPageFragment}
69
+ ${ItemsReviewFragment}
70
+ `;
71
+
72
+ export const GET_CUSTOMER = gql`
73
+ query GetCustomerForCheckout {
74
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
75
+ customer {
76
+ default_shipping
77
+ firstname
78
+ }
79
+ }
80
+ `;
81
+
82
+ export default {
83
+ createCartMutation: CREATE_CART,
84
+ getCheckoutDetailsQuery: GET_CHECKOUT_DETAILS,
85
+ getCustomerQuery: GET_CUSTOMER,
86
+ getOrderDetailsQuery: GET_ORDER_DETAILS,
87
+ placeOrderMutation: PLACE_ORDER
88
+ };