@riosst100/pwa-marketplace 3.0.3 → 3.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.
Files changed (32) hide show
  1. package/i18n/en_US.json +3 -3
  2. package/i18n/id_ID.json +2 -2
  3. package/package.json +1 -1
  4. package/src/componentOverrideMapping.js +1 -0
  5. package/src/components/OrderDetail/components/itemsOrdered.js +1 -6
  6. package/src/components/RMAPage/components/productItem.js +13 -43
  7. package/src/components/SellerCoupon/index.js +1 -0
  8. package/src/components/SellerCoupon/sellerCoupon.js +41 -6
  9. package/src/components/SellerCoupon/sellerCoupon.module.css +22 -0
  10. package/src/components/SellerCoupon/sellerCouponCheckout.js +36 -19
  11. package/src/components/SellerCoupon/sellerCouponCheckout.shimmer.js +21 -0
  12. package/src/overwrites/peregrine/lib/talons/CartPage/PriceSummary/usePriceSummary.js +2 -2
  13. package/src/overwrites/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/couponCode.js +24 -27
  14. package/src/overwrites/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/couponCode.module.css +2 -0
  15. package/src/overwrites/venia-ui/lib/components/CartPage/PriceSummary/priceSummary.js +14 -5
  16. package/src/overwrites/venia-ui/lib/components/CartPage/cartPage.js +0 -7
  17. package/src/overwrites/venia-ui/lib/components/CheckoutPage/OrderSummary/orderSummary.js +4 -0
  18. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PriceAdjustments/priceAdjustments.js +65 -57
  19. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PriceAdjustments/priceAdjustments.module.css +29 -0
  20. package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.js +2 -2
  21. package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.module.css +2 -0
  22. package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/Reviews/index.js +1 -0
  23. package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/Reviews/reviewModal.js +316 -0
  24. package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/Reviews/starInput.js +33 -0
  25. package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/orderHistoryPage.js +29 -2
  26. package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/orderRow.js +70 -34
  27. package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/modalFormReview.js +8 -8
  28. package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/productReview.js +4 -27
  29. package/src/talons/ReviewModal/reviewModal.gql.js +45 -0
  30. package/src/talons/ReviewModal/useReviewModal.js +87 -0
  31. package/src/components/RMAPage/components/productItem.css +0 -15
  32. package/src/components/RMAPage/components/productItem.module.css +0 -15
@@ -7,6 +7,9 @@ import defaultClasses from './orderSummary.module.css';
7
7
 
8
8
  const OrderSummary = props => {
9
9
  const classes = useStyle(defaultClasses, props.classes);
10
+
11
+ const { placeOrderButton } = props
12
+
10
13
  return (
11
14
  <div data-cy="OrderSummary-root" className={classes.root}>
12
15
  <h2 aria-live="polite" className="text-[16px] font-medium mb-4">
@@ -26,6 +29,7 @@ const OrderSummary = props => {
26
29
  }
27
30
  `}
28
31
  </style>
32
+ {placeOrderButton}
29
33
  </div>
30
34
  );
31
35
  };
@@ -5,15 +5,17 @@ import { useMutation, useQuery } from '@apollo/client';
5
5
  import { useCartContext } from '@magento/peregrine/lib/context/cart';
6
6
 
7
7
  import { useStyle } from '@magento/venia-ui/lib/classify';
8
- import LoadingIndicator from '@magento/venia-ui/lib/components/LoadingIndicator';
9
8
  import { Accordion, Section } from '@magento/venia-ui/lib/components/Accordion';
10
9
  import SellerCouponCheckout from '@riosst100/pwa-marketplace/src/components/SellerCoupon/sellerCouponCheckout';
11
10
  import couponCodeOperations from '@magento/peregrine/lib/talons/CartPage/PriceAdjustments/CouponCode/couponCode.gql';
12
11
  import GiftCardSection from '@magento/venia-ui/lib/components/CartPage/PriceAdjustments/giftCardSection';
13
12
  import GiftOptionsSection from '@magento/venia-ui/lib/components/CartPage/PriceAdjustments/giftOptionsSection';
14
-
13
+ import CouponCode from '@magento/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode';
14
+ import Shimmer from '@magento/venia-ui/lib/components/Shimmer';
15
15
  import defaultClasses from './priceAdjustments.module.css';
16
16
  import cn from 'classnames';
17
+ import LoadingIndicator from '@magento/venia-ui/lib/components/LoadingIndicator';
18
+ import { FormattedMessage } from 'react-intl';
17
19
 
18
20
  /**
19
21
  * PriceAdjustments component for the Checkout page.
@@ -32,7 +34,8 @@ const PriceAdjustments = props => {
32
34
  couponCodeOperations.getAppliedCouponsQuery,
33
35
  { variables: { cartId }, skip: !cartId }
34
36
  );
35
- const [sectionOpen, setSectionOpen] = useState(false);
37
+ const [sectionOpen, setSectionOpen] = useState(true);
38
+ const [couponModalOpen, setCouponModalOpen] = useState(false);
36
39
 
37
40
  const handleApplyFromClaim = useCallback(async (item) => {
38
41
  if (!item?.code || !cartId) return;
@@ -48,6 +51,10 @@ const PriceAdjustments = props => {
48
51
  }
49
52
  }, [applyCoupon, cartId, setPageIsUpdating]);
50
53
 
54
+ const handleViewCoupons = useCallback(() => {
55
+ setCouponModalOpen(true);
56
+ }, [setCouponModalOpen]);
57
+
51
58
  const handleRemoveCoupon = useCallback(async () => {
52
59
  if (!cartId) return;
53
60
  try {
@@ -64,62 +71,63 @@ const PriceAdjustments = props => {
64
71
 
65
72
  return (
66
73
  <div className={classes.root}>
67
- <Accordion
68
- canOpenMultiple={true}
69
- classes={{
70
- root: 'w-full'
71
- }}
72
- >
73
- <Section
74
- data-cy="PriceAdjustments-couponCodeSection"
75
- id={'coupon_code'}
76
- title={formatMessage({
74
+ <div className={classes.coupon_container}>
75
+ <h5 className={classes.cardTitle}>
76
+ {formatMessage({
77
77
  id: 'checkoutPage.couponCode',
78
- defaultMessage: 'Apply Coupon Code'
78
+ defaultMessage: 'Apply Coupon'
79
79
  })}
80
- classes={{
81
- root: cn('border border-gray-100 rounded-md max-w-[400px] p-2.5'),
82
- title: 'text-[16px] font-medium cursor-pointer',
83
- title_wrapper: 'gap-sm grid grid-cols-1 grid-flow-col h-[38px] items-center justify-items-start',
84
- contents_container: 'p-0'
85
- }}
86
- onClick={() => setSectionOpen(prev => !prev)}
87
- >
88
- <Suspense fallback={<LoadingIndicator />}>
89
- {sectionOpen && (
90
- <SellerCouponCheckout
91
- couponData={couponData}
92
- couponLoading={couponLoading || applyingCoupon || appliedLoading || removingCoupon}
93
- couponError={couponError}
94
- autoOpen={true}
95
- closeOnClaim={true}
96
- onSelectCoupon={handleApplyFromClaim}
97
- onTriggerRender={() => null}
98
- />
99
- )}
100
- {appliedCoupons.length > 0 && (
101
- <div className="mt-3 flex items-center gap-2 flex-wrap">
102
- {appliedCoupons.map(c => (
103
- <div key={c.code} className="flex items-center gap-2 bg-[#fff8f1] border border-[#ffb891] rounded px-2 py-1 text-sm font-medium text-[#f76b1c]">
104
- <span>{c.code}</span>
105
- <button
106
- type="button"
107
- onClick={handleRemoveCoupon}
108
- disabled={removingCoupon}
109
- className="text-[#a94442] hover:text-[#f26313] disabled:opacity-50"
110
- aria-label={formatMessage({ id: 'checkoutPage.removeCoupon', defaultMessage: 'Remove coupon' })}
111
- >
112
- ×
113
- </button>
114
- </div>
115
- ))}
116
- </div>
117
- )}
118
- </Suspense>
119
- </Section>
120
- <GiftCardSection setIsCartUpdating={setPageIsUpdating} />
121
- <GiftOptionsSection />
122
- </Accordion>
80
+ </h5>
81
+ {applyingCoupon || appliedLoading ? <LoadingIndicator classes={{ root: classes.loading }}>
82
+ <FormattedMessage
83
+ id={'checkoutPage.loadingApplyingCoupon'}
84
+ defaultMessage={'Applying Coupon'}
85
+ />
86
+ </LoadingIndicator> : removingCoupon ? <LoadingIndicator classes={{ root: classes.loading }}>
87
+ <FormattedMessage
88
+ id={'checkoutPage.loadingRemovingCoupon'}
89
+ defaultMessage={'Removing Coupon'}
90
+ />
91
+ </LoadingIndicator> :
92
+ <Suspense fallback={<LoadingIndicator />}>
93
+ <CouponCode setIsCartUpdating={setPageIsUpdating} />
94
+ {appliedCoupons.length > 0 && (
95
+ <div className="mt-3 flex items-center gap-2 flex-wrap">
96
+ {appliedCoupons.map(c => {
97
+ const coupon = couponData.sellerCoupons.items.find(item => item.code === c.code);
98
+ return <div key={c.code} className="flex items-center gap-2 bg-[#fff8f1] border border-[#ffb891] rounded px-2 py-1 text-sm font-medium text-[#f76b1c]">
99
+ <span>{coupon.name} ({coupon.code})</span>
100
+ <button
101
+ type="button"
102
+ onClick={handleRemoveCoupon}
103
+ disabled={removingCoupon}
104
+ className="text-[#a94442] hover:text-[#f26313] disabled:opacity-50"
105
+ aria-label={formatMessage({ id: 'checkoutPage.removeCoupon', defaultMessage: 'Remove coupon' })}
106
+ >
107
+ ×
108
+ </button>
109
+ </div>
110
+ })}
111
+ </div>
112
+ )}
113
+ {!appliedCoupons.length && couponData?.sellerCoupons?.items.length ? <button class="p-2 text-[13px] text-blue-700 border border-solid cursor-pointer rounded-full w-full mt-4" onClick={handleViewCoupons}>Select coupon to apply</button> : ''}
114
+ {couponModalOpen && (
115
+ <SellerCouponCheckout
116
+ couponData={couponData}
117
+ couponLoading={couponLoading || applyingCoupon || appliedLoading || removingCoupon}
118
+ couponError={couponError}
119
+ autoOpen={true}
120
+ closeOnClaim={true}
121
+ couponModalOpen={couponModalOpen}
122
+ setCouponModalOpen={setCouponModalOpen}
123
+ onSelectCoupon={handleApplyFromClaim}
124
+ onTriggerRender={() => null}
125
+ />
126
+ )}
127
+ </Suspense>}
128
+ </div>
129
+ <GiftCardSection setIsCartUpdating={setPageIsUpdating} />
130
+ <GiftOptionsSection />
123
131
  </div>
124
132
  );
125
133
  };
@@ -1,2 +1,31 @@
1
1
  .root {
2
+ composes: gap-xs from global;
3
+ composes: grid from global;
4
+ composes: grid-cols-1 from global;
2
5
  }
6
+
7
+ .coupon_container {
8
+ composes: border from global;
9
+ composes: p-4 from global;
10
+ composes: pb-6 from global;
11
+ composes: border-gray-100 from global;
12
+ composes: rounded-md from global;
13
+ }
14
+
15
+ .loading {
16
+ composes: root from '@magento/venia-ui/lib/components/LoadingIndicator/indicator.module.css';
17
+
18
+ composes: text-center from global;
19
+ }
20
+
21
+ .heading {
22
+ composes: border-0 from global;
23
+
24
+ composes: lg_border from global;
25
+ }
26
+
27
+ .cardTitle {
28
+ composes: font-medium from global;
29
+ composes: text-[16px] from global;
30
+ composes: mb-4 from global;
31
+ }
@@ -345,7 +345,7 @@ const CheckoutPage = props => {
345
345
  : '')
346
346
  }
347
347
  >
348
- <OrderSummary isUpdating={isUpdating} />
348
+ <OrderSummary isUpdating={isUpdating} placeOrderButton={placeOrderButton} />
349
349
  {itemsReview}
350
350
  </div>
351
351
  );
@@ -430,7 +430,7 @@ const CheckoutPage = props => {
430
430
  {priceAdjustmentsSection}
431
431
  {reviewOrderButton}
432
432
  {orderSummary}
433
- {placeOrderButton}
433
+ {/* {placeOrderButton} */}
434
434
  <GoogleReCaptcha {...recaptchaWidgetProps} />
435
435
  </div>
436
436
  );
@@ -190,6 +190,8 @@
190
190
  grid-column: 1 / span 1;
191
191
  composes: m-auto from global;
192
192
  text-transform: capitalize;
193
+ composes: w-full from global;
194
+ composes: mt-4 from global;
193
195
  }
194
196
  .place_order_button:hover,
195
197
  .place_order_button:focus,
@@ -0,0 +1 @@
1
+ export { default as ReviewModal } from './reviewModal';
@@ -0,0 +1,316 @@
1
+ import React, { useMemo, useState, useEffect } from 'react';
2
+ import Modal from '@riosst100/pwa-marketplace/src/components/Modal';
3
+ import { X } from 'react-feather';
4
+ import { Text } from 'informed';
5
+
6
+ import Field from '@magento/venia-ui/lib/components/Field';
7
+ // import TextInput from '@magento/venia-ui/lib/components/TextInput';
8
+ import Button from '@magento/venia-ui/lib/components/Button';
9
+ import { isRequired } from '@magento/venia-ui/lib/util/formValidators';
10
+ import StarRating from './starInput';
11
+
12
+ import { primary900 } from '@riosst100/pwa-marketplace/src/theme/vars';
13
+ import { useReviewModal } from '@riosst100/pwa-marketplace/src/talons/ReviewModal/useReviewModal';
14
+ import { useStyle } from '@magento/venia-ui/lib/classify';
15
+ import defaultClasses from '../orderRow.module.css';
16
+ import cn from 'classnames';
17
+
18
+ import { arrayOf, number, shape, string } from 'prop-types';
19
+ import { ChevronDown, ChevronUp } from 'react-feather';
20
+ import { FormattedMessage, useIntl } from 'react-intl';
21
+ import Price from '@magento/venia-ui/lib/components/Price';
22
+
23
+ import Icon from '@magento/venia-ui/lib/components/Icon';
24
+ import CollapsedImageGallery from '../collapsedImageGallery';
25
+ import OrderProgressBar from '../orderProgressBar';
26
+ import OrderDetails from '../OrderDetails';
27
+ import { Verify, Shop, ConvertCard } from 'iconsax-react';
28
+ import PlaceholderImage from '@magento/venia-ui/lib/components/Image/placeholderImage';
29
+ import { Link, useHistory } from 'react-router-dom';
30
+
31
+ const ReviewModal = (props) => {
32
+ const { reviewOrder, setReviewOrder } = props;
33
+
34
+ const [submitting, setSubmitting] = useState(false)
35
+
36
+ const classes = useStyle(defaultClasses, props.classes);
37
+
38
+ const talonProps = useReviewModal({ reviewOrder, setSubmitting });
39
+
40
+ const {
41
+ ratingsMetadata,
42
+ loadingRatingsMetadata,
43
+ handleSubmitReview,
44
+ loadingCreateReview,
45
+ errorCreateReview,
46
+ defaultNickname,
47
+ handleToastAction
48
+ } = talonProps;
49
+
50
+ const [formState, setFormState] = useState({ nickname: defaultNickname || '' });
51
+
52
+ useEffect(() => {
53
+ if (reviewOrder && defaultNickname && !formState.nickname) {
54
+ setFormState(prev => ({ ...prev, nickname: defaultNickname }));
55
+ }
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ }, [reviewOrder, defaultNickname]);
58
+
59
+ // ratings: [{ id, value_id }]
60
+ const [ratings, setRatings] = useState(null);
61
+
62
+ const handleRatingChange = (id, value_id) => {
63
+ // setRatings(prev => {
64
+ // const filtered = prev.filter(r => r.id !== id);
65
+ // return [...filtered, { id, value_id }];
66
+ // });
67
+ setRatings(value_id)
68
+ };
69
+
70
+ const handleChange = (field, value) => {
71
+ setFormState(prev => ({ ...prev, [field]: value }));
72
+ };
73
+
74
+ const handleSubmit = async (e) => {
75
+ e.preventDefault();
76
+ // if (onSubmit) {
77
+ // onSubmit({ ...formState, ratings });
78
+ // }
79
+ console.log('formState',formState)
80
+ console.log('e',e)
81
+ setSubmitting(true);
82
+ const input = {
83
+ nickname: formState.nickname,
84
+ summary: formState.summary,
85
+ text: formState.review,
86
+ sku: e.target.sku.value,
87
+ ratings: [{
88
+ id: ratingsMetadata.id,
89
+ value_id: ratings
90
+ }]
91
+ };
92
+ const result = await handleSubmitReview(input);
93
+ setSubmitting(false);
94
+ if (result.success) setReviewOrder(null);
95
+ };
96
+
97
+ // Helper to resolve a product image by SKU with graceful fallback, now prefers product_image_url from order.items
98
+ const getThumbnailForSku = (sku, fallbackLabel, idx) => {
99
+ let url = null;
100
+ let label = fallbackLabel;
101
+ // Prefer product_image_url from order.items if present and is a non-empty string
102
+ if (reviewOrder && reviewOrder.items && reviewOrder.items[idx] && typeof reviewOrder.items[idx].product_image_url === 'string' && reviewOrder.items[idx].product_image_url.trim() !== '') {
103
+ url = reviewOrder.items[idx].product_image_url;
104
+ } else if (imagesData && typeof imagesData === 'object') {
105
+ const byKey = sku && imagesData[sku];
106
+ const byValue = !byKey && sku
107
+ ? Object.values(imagesData).find(entry => entry?.sku === sku)
108
+ : null;
109
+ const chosen = byKey || byValue;
110
+ if (chosen?.thumbnail?.url && typeof chosen.thumbnail.url === 'string' && chosen.thumbnail.url.trim() !== '') {
111
+ url = chosen.thumbnail.url;
112
+ label = chosen.thumbnail.label || label;
113
+ }
114
+ }
115
+ // If url is not a non-empty string, fallback to null (will trigger placeholder)
116
+ if (typeof url !== 'string' || url.trim() === '') {
117
+ url = null;
118
+ }
119
+ return { url, label };
120
+ };
121
+
122
+ console.log('ratings',ratings)
123
+
124
+ const ratingStars = useMemo(() => {
125
+ console.log('ratingsMetadata22',ratingsMetadata)
126
+ if (!ratingsMetadata) {
127
+ return '';
128
+ }
129
+
130
+ // Find value (1-5) for selected value_id
131
+ const selectedValue = ratings && ratingsMetadata.values.find(v => v.value_id === ratings) || '';
132
+ console.log('selectedValue',selectedValue)
133
+
134
+ let starButtons = [];
135
+
136
+ [1,2,3,4,5].map(star => {
137
+ const valObj = ratingsMetadata.values.find(v => v.value === String(star));
138
+ console.log('String(star)',String(star))
139
+ console.log('valObj',valObj)
140
+ if (valObj) {
141
+ starButtons.push(
142
+ <button
143
+ key={valObj.value_id}
144
+ type="button"
145
+ aria-label={`${star} star${star > 1 ? 's' : ''}`}
146
+ className={`focus:outline-none ${selectedValue.value == star ? 'text-yellow-400' : 'text-gray-300'}`}
147
+ onClick={() => handleRatingChange(ratingsMetadata.id, valObj.value_id)}
148
+ >
149
+ <svg xmlns="http://www.w3.org/2000/svg" fill={selectedValue.value >= star ? '#F7C317' : '#D9D9D9'} viewBox="0 0 20 20" width="25" height="25">
150
+ <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.286 3.967a1 1 0 00.95.69h4.175c.969 0 1.371 1.24.588 1.81l-3.38 2.455a1 1 0 00-.364 1.118l1.287 3.966c.3.922-.755 1.688-1.54 1.118l-3.38-2.454a1 1 0 00-1.175 0l-3.38 2.454c-.784.57-1.838-.196-1.54-1.118l1.287-3.966a1 1 0 00-.364-1.118L2.05 9.394c-.783-.57-.38-1.81.588-1.81h4.175a1 1 0 00.95-.69l1.286-3.967z" />
151
+ </svg>
152
+ </button>
153
+ );
154
+ }
155
+ });
156
+
157
+ return (
158
+ <div className="mb-2">
159
+ <label className="block mb-1 font-bold text-gray-700">{ratingsMetadata.name}</label>
160
+ <div className="flex items-center gap-1">
161
+ {starButtons}
162
+ </div>
163
+ </div>
164
+ );
165
+ }, [ratingsMetadata, ratings]);
166
+
167
+ return (
168
+ <>
169
+ <Modal
170
+ open={reviewOrder}
171
+ className="modal_form_review !p-[30px] md_min-w-[650px]"
172
+ >
173
+ <div className='form_review-container'>
174
+ <div className='header_title-modal flex justify-between mb-5'>
175
+ <div className='text-lg text-black font-medium'>
176
+ Write Review
177
+ </div>
178
+ <button onClick={() => { setReviewOrder(!reviewOrder) }} >
179
+ <X size={24} color={primary900} />
180
+ </button>
181
+ </div>
182
+
183
+ {/* <Field id="nickname_field" label={'Nickname'}>
184
+ <input
185
+ id="nickname"
186
+ name="nickname"
187
+ type="text"
188
+ required
189
+ readOnly
190
+ value={formState.nickname || ''}
191
+ onChange={e => handleChange('nickname', e.target.value)}
192
+ data-cy="nickname"
193
+ aria-label={'nickname'}
194
+ placeholder={'e.g John Doe'}
195
+ className="border border-gray-100 rounded px-3 py-2 bg-gray-50 cursor-not-allowed"
196
+ aria-readonly="true"
197
+ />
198
+ </Field> */}
199
+ {/* Ratings breakdown from metadata */}
200
+ {reviewOrder && reviewOrder.items && reviewOrder.items.length > 0 && reviewOrder.items.map((it, idx) => {
201
+ const { url, label } = getThumbnailForSku(it.product_sku, it.product_name, idx);
202
+ return (
203
+ <>
204
+ <form className="flex flex-col gap-y-3" onSubmit={handleSubmit}>
205
+ <div key={it.id || idx} className='flex flex-row gap-4 mb-1 justify-between' style={{
206
+ "borderBottom": "1px solid #e6e9ea",
207
+ "paddingBottom": "10px"
208
+ }}>
209
+ <div className={classes.productImage}>
210
+ {url ? (
211
+ <img
212
+ src={url}
213
+ alt={label}
214
+ width={80}
215
+ className={classes.thumbnail}
216
+ />
217
+ ) : (
218
+ <PlaceholderImage alt={it.product_name} classes={{ root: classes.thumbnail }} width={60} />
219
+ )}
220
+ </div>
221
+ <div className='flex flex-col gap-1 pb-2 last_pb-0 max-w-[375px]'>
222
+ <div className={cn(classes.productName, 'text-[14px] font-medium')}>
223
+ <span>{it.product_name}</span>
224
+ </div>
225
+ <div className="text-[12px]">
226
+ <span>x{`${it.quantity_ordered}`}</span>
227
+ </div>
228
+ </div>
229
+ <div class="flex flex-col gap-1 pb-2 last_pb-0 justify-center">
230
+ <div class="text-[14px] text-blue-700">
231
+ <span><Price currencyCode={it?.product_sale_price?.currency} value={it?.product_sale_price?.value} /></span>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ <div className="flex flex-col gap-y-3">
236
+ {loadingRatingsMetadata ? (
237
+ <div>Loading ratings...</div>
238
+ ) : ratingStars}
239
+ </div>
240
+ <input type="hidden" id="sku" name="sku" value={it.product_sku} />
241
+ {/* <Field id="summary_field" label={'Summary'}>
242
+ <input
243
+ id="summary"
244
+ name="summary"
245
+ type="text"
246
+ required
247
+ value={formState.summary || ''}
248
+ onChange={e => handleChange('summary', e.target.value)}
249
+ data-cy="summary"
250
+ aria-label={'summary'}
251
+ placeholder={'Summary of your rating'}
252
+ className="border border-gray-100 rounded px-3 py-2"
253
+ />
254
+ </Field> */}
255
+ <Field id="summary_field" label={'Summary'}>
256
+ <input
257
+ id="summary"
258
+ name="summary"
259
+ type="text"
260
+ required
261
+ value={formState.summary || ''}
262
+ onChange={e => handleChange('summary', e.target.value)}
263
+ data-cy="summary"
264
+ aria-label={'summary'}
265
+ placeholder={'Summary of your rating'}
266
+ className="border border-gray-100 rounded px-3 py-2"
267
+ />
268
+ </Field>
269
+ <Field id="review_field" label={'Review'}>
270
+ <textarea
271
+ id="review"
272
+ name="review"
273
+ required
274
+ value={formState.review || ''}
275
+ onChange={e => handleChange('review', e.target.value)}
276
+ data-cy="review"
277
+ aria-label={'review'}
278
+ placeholder={'Let us know your thoughts'}
279
+ className="border border-gray-100 rounded px-3 py-2"
280
+ rows={3}
281
+ />
282
+ </Field>
283
+ <div className='actions flex justify-end gap-x-2.5 mt-4'>
284
+ {/* <Button
285
+ priority='low'
286
+ classes={{
287
+ content: 'capitalize text-[16px] font-medium'
288
+ }}
289
+ onClick={() => setReviewOrder(false)}
290
+ type="button"
291
+ >
292
+ Cancel
293
+ </Button> */}
294
+ <Button
295
+ priority='high'
296
+ classes={{
297
+ content: 'capitalize text-[16px] font-medium'
298
+ }}
299
+ type="submit"
300
+ disabled={submitting}
301
+ >
302
+ {submitting ? 'Submitting...' : 'Submit Review'}
303
+ </Button>
304
+ </div>
305
+ </form>
306
+ </>
307
+ );
308
+ })}
309
+
310
+ </div>
311
+ </Modal>
312
+ </>
313
+ );
314
+ };
315
+
316
+ export default ReviewModal;
@@ -0,0 +1,33 @@
1
+ import React, { useState } from 'react';
2
+
3
+ const StarRating = ({ totalStars = 5, rating, onRatingChange }) => {
4
+ const [hover, setHover] = useState(0);
5
+
6
+ const handleClick = (newRating) => {
7
+ onRatingChange(newRating);
8
+ };
9
+
10
+ return (
11
+ <div className="star-rating flex flex-row gap-x-1">
12
+ {[...Array(totalStars)].map((star, index) => {
13
+ const ratingClass = index < (hover || rating) ? 'filled text-yellow-400' : 'empty text-gray-400';
14
+ return (
15
+ <span
16
+ key={index}
17
+ className={`star ${ratingClass}`}
18
+ onMouseEnter={() => setHover(index + 1)}
19
+ onMouseLeave={() => setHover(0)}
20
+ onClick={() => handleClick(index + 1)}
21
+ >
22
+ <svg className={ratingClass} width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
23
+ <path d="M8.00887 2.04754L9.03554 4.10087C9.17554 4.38671 9.54887 4.66087 9.86387 4.71337L11.7247 5.02254C12.9147 5.22087 13.1947 6.08421 12.3372 6.93587L10.8905 8.38254C10.6455 8.62754 10.5114 9.10004 10.5872 9.43837L11.0014 11.2292C11.328 12.6467 10.5755 13.195 9.32137 12.4542L7.5772 11.4217C7.2622 11.235 6.74304 11.235 6.4222 11.4217L4.67804 12.4542C3.4297 13.195 2.67137 12.6409 2.99804 11.2292L3.4122 9.43837C3.48804 9.10004 3.35387 8.62754 3.10887 8.38254L1.6622 6.93587C0.810536 6.08421 1.0847 5.22087 2.2747 5.02254L4.13554 4.71337C4.4447 4.66087 4.81804 4.38671 4.95804 4.10087L5.9847 2.04754C6.5447 0.933372 7.4547 0.933372 8.00887 2.04754Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" />
24
+ </svg>
25
+
26
+ </span>
27
+ );
28
+ })}
29
+ </div>
30
+ );
31
+ };
32
+
33
+ export default StarRating;
@@ -1,4 +1,4 @@
1
- import React, { useMemo, useEffect } from 'react';
1
+ import React, { useMemo, useEffect, useState } from 'react';
2
2
  import { useIntl, FormattedMessage } from 'react-intl';
3
3
  import {
4
4
  Search as SearchIcon,
@@ -25,6 +25,7 @@ import ResetButton from './resetButton';
25
25
  import { SearchNormal } from 'iconsax-react';
26
26
  import cn from 'classnames';
27
27
  import Pagination from '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/Pagination';
28
+ import { ReviewModal } from './Reviews'
28
29
 
29
30
  const errorIcon = (
30
31
  <Icon
@@ -52,6 +53,8 @@ const OrderHistoryPage = props => {
52
53
  } = talonProps;
53
54
  const [, { addToast }] = useToasts();
54
55
  const { formatMessage } = useIntl();
56
+ const [reviewOrder, setReviewOrder] = useState(null);
57
+
55
58
  const PAGE_TITLE = formatMessage({
56
59
  id: 'orderHistoryPage.pageTitleText',
57
60
  defaultMessage: 'My Orders'
@@ -73,7 +76,7 @@ const OrderHistoryPage = props => {
73
76
 
74
77
  const orderRows = useMemo(() => {
75
78
  return orders.map(order => {
76
- return <OrderRow key={order.id} order={order} />;
79
+ return <OrderRow setReviewOrder={setReviewOrder} key={order.id} order={order} />;
77
80
  });
78
81
  }, [orders]);
79
82
 
@@ -163,8 +166,32 @@ const OrderHistoryPage = props => {
163
166
  }
164
167
  }, [addToast, errorMessage]);
165
168
 
169
+ console.log('reviewOrder',reviewOrder)
170
+
166
171
  return (
167
172
  <OrderHistoryContextProvider>
173
+ <ReviewModal
174
+ // open={open}
175
+ setReviewOrder={setReviewOrder}
176
+ reviewOrder={reviewOrder}
177
+ // defaultNickname={defaultNickname}
178
+ // ratingsMetadata={ratingsMetadataData?.productReviewRatingsMetadata?.items || []}
179
+ // loadingRatingsMetadata={loadingRatingsMetadata}
180
+ // onSubmit={async (formValues) => {
181
+ // setSubmitting(true);
182
+ // const input = {
183
+ // nickname: formValues.nickname,
184
+ // summary: formValues.summary,
185
+ // text: formValues.review,
186
+ // sku: product?.sku,
187
+ // ratings: formValues.ratings
188
+ // };
189
+ // const result = await handleSubmitReview(input);
190
+ // setSubmitting(false);
191
+ // if (result.success) setOpen(false);
192
+ // }}
193
+ // submitting={submitting}
194
+ />
168
195
  <div className={classes.root}>
169
196
  <StoreTitle>{PAGE_TITLE}</StoreTitle>
170
197
  <div aria-live="polite" className="text-xl font-medium text-left">