@riosst100/pwa-marketplace 3.0.1 → 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.
- package/i18n/en_US.json +3 -3
- package/i18n/id_ID.json +2 -2
- package/package.json +1 -1
- package/src/componentOverrideMapping.js +2 -0
- package/src/components/SellerCoupon/index.js +1 -0
- package/src/components/SellerCoupon/sellerCoupon.js +41 -6
- package/src/components/SellerCoupon/sellerCoupon.module.css +22 -0
- package/src/components/SellerCoupon/sellerCouponCheckout.js +36 -19
- package/src/components/SellerCoupon/sellerCouponCheckout.shimmer.js +21 -0
- package/src/overwrites/peregrine/lib/talons/CartPage/PriceSummary/usePriceSummary.js +2 -2
- package/src/overwrites/peregrine/lib/talons/CartPage/useCartPage.js +121 -0
- package/src/overwrites/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/couponCode.js +24 -27
- package/src/overwrites/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/couponCode.module.css +2 -0
- package/src/overwrites/venia-ui/lib/components/CartPage/PriceSummary/priceSummary.js +14 -5
- package/src/overwrites/venia-ui/lib/components/CartPage/cartPage.js +0 -7
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/OrderSummary/orderSummary.js +4 -0
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/PriceAdjustments/priceAdjustments.js +65 -57
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/PriceAdjustments/priceAdjustments.module.css +29 -0
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.js +2 -2
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.module.css +2 -0
- package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/Reviews/index.js +1 -0
- package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/Reviews/reviewModal.js +316 -0
- package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/Reviews/starInput.js +33 -0
- package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/orderHistoryPage.js +29 -2
- package/src/overwrites/venia-ui/lib/components/OrderHistoryPage/orderRow.js +70 -34
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/modalFormReview.js +8 -8
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/productReview.js +4 -27
- package/src/talons/ReviewModal/reviewModal.gql.js +45 -0
- package/src/talons/ReviewModal/useReviewModal.js +87 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
2
|
import { arrayOf, number, shape, string } from 'prop-types';
|
|
3
3
|
import { ChevronDown, ChevronUp } from 'react-feather';
|
|
4
4
|
import { FormattedMessage, useIntl } from 'react-intl';
|
|
@@ -17,7 +17,7 @@ import PlaceholderImage from '@magento/venia-ui/lib/components/Image/placeholder
|
|
|
17
17
|
import { Link, useHistory } from 'react-router-dom';
|
|
18
18
|
|
|
19
19
|
const OrderRow = props => {
|
|
20
|
-
const { order } = props;
|
|
20
|
+
const { order, setReviewOrder } = props;
|
|
21
21
|
const { formatMessage } = useIntl();
|
|
22
22
|
const history = useHistory();
|
|
23
23
|
const {
|
|
@@ -179,9 +179,22 @@ const OrderRow = props => {
|
|
|
179
179
|
});
|
|
180
180
|
};
|
|
181
181
|
|
|
182
|
+
const handleWriteReview = useCallback(( order ) => {
|
|
183
|
+
console.log('order',order)
|
|
184
|
+
if (order) {
|
|
185
|
+
setReviewOrder(order);
|
|
186
|
+
}
|
|
187
|
+
}, [setReviewOrder]);
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
// ReviewModal
|
|
191
|
+
|
|
182
192
|
return (
|
|
183
193
|
<li className={classes.root}>
|
|
184
|
-
<div className='flex flex-col md_flex-row md_items-start justify-between mb-2.5'
|
|
194
|
+
<div className='flex flex-col md_flex-row md_items-start justify-between mb-2.5' style={{
|
|
195
|
+
"borderBottom": "1px solid #e6e9ea",
|
|
196
|
+
"paddingBottom": "10px"
|
|
197
|
+
}}>
|
|
185
198
|
<div className='flex flex-col ml-[14px] mt-[5px]'>
|
|
186
199
|
<div className="flex gap-x-[15px] flex-col">
|
|
187
200
|
<div className='flex gap-x-[5px] items-center'>
|
|
@@ -202,13 +215,16 @@ const OrderRow = props => {
|
|
|
202
215
|
</div>
|
|
203
216
|
</div>
|
|
204
217
|
</div>
|
|
205
|
-
<div className='flex flex-col md_flex-
|
|
206
|
-
<div className='flex flex-col ml-[5px] gap-y-[
|
|
218
|
+
<div className='flex flex-col md_flex-column justify-between mb-0'>
|
|
219
|
+
<div className='flex flex-col ml-[5px] gap-y-[10px]'>
|
|
207
220
|
{/* Per-item horizontal flex: image + detail */}
|
|
208
221
|
{items && items.length > 0 && items.map((it, idx) => {
|
|
209
222
|
const { url, label } = getThumbnailForSku(it.product_sku, it.product_name, idx);
|
|
210
223
|
return (
|
|
211
|
-
<div key={it.id || idx} className='flex flex-row gap-4 mb-
|
|
224
|
+
<div key={it.id || idx} className='flex flex-row gap-4 mb-1 justify-between' style={{
|
|
225
|
+
"borderBottom": "1px solid #e6e9ea",
|
|
226
|
+
"paddingBottom": "10px"
|
|
227
|
+
}}>
|
|
212
228
|
<div className={classes.productImage}>
|
|
213
229
|
{url ? (
|
|
214
230
|
<img
|
|
@@ -222,15 +238,16 @@ const OrderRow = props => {
|
|
|
222
238
|
)}
|
|
223
239
|
</div>
|
|
224
240
|
<div className='flex flex-col gap-1 pb-2 last_pb-0 max-w-[375px]'>
|
|
225
|
-
<div className={cn(classes.productName, 'text-[
|
|
241
|
+
<div className={cn(classes.productName, 'text-[14px] font-medium')}>
|
|
226
242
|
<span>{it.product_name}</span>
|
|
227
243
|
</div>
|
|
228
|
-
<div className="text-[
|
|
229
|
-
<span>
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
244
|
+
<div className="text-[12px]">
|
|
245
|
+
<span>x{`${it.quantity_ordered}`}</span>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
<div class="flex flex-col gap-1 pb-2 last_pb-0 justify-center">
|
|
249
|
+
<div class="text-[14px] text-blue-700">
|
|
250
|
+
<span><Price currencyCode={it?.product_sale_price?.currency} value={it?.product_sale_price?.value} /></span>
|
|
234
251
|
</div>
|
|
235
252
|
</div>
|
|
236
253
|
</div>
|
|
@@ -238,45 +255,64 @@ const OrderRow = props => {
|
|
|
238
255
|
})}
|
|
239
256
|
</div>
|
|
240
257
|
{/* Right column: bottom-aligned Order Total + CTA */}
|
|
241
|
-
<div className='flex flex-col items-end gap-
|
|
242
|
-
<div className="md_text-right">
|
|
243
|
-
<span className="text-[
|
|
258
|
+
<div className='flex flex-col items-end gap-4 md_pl-10 md_self-end mr-4 mb-1 pt-2'>
|
|
259
|
+
<div className="md_text-right flex flex-row gap-5 items-center">
|
|
260
|
+
<span className="text-[14px] text-gray-200 block mb-1">
|
|
244
261
|
<FormattedMessage
|
|
245
262
|
id={'orderRow.orderTotalText'}
|
|
246
263
|
defaultMessage={'Order Total'}
|
|
247
|
-
|
|
264
|
+
/>:
|
|
248
265
|
</span>
|
|
249
|
-
<div className="text-lg font-medium">{orderTotalPrice}</div>
|
|
266
|
+
<div className="text-lg font-medium text-blue-700">{orderTotalPrice}</div>
|
|
250
267
|
</div>
|
|
251
268
|
<div className="flex flex-row gap-2 w-full justify-end items-center">
|
|
269
|
+
{showNewReturnButton && (
|
|
270
|
+
<>
|
|
271
|
+
{/* <ReviewModal order={reviewOrder} /> */}
|
|
272
|
+
<span className="bg-blue-700 hover:bg-white hover:text-blue-700 hover:border hover:border-blue-700 rounded-full px-[30px] py-[8px] text-[13px] font-medium text-white transition-all duration-300 ease-in-out" onClick={() => handleWriteReview(order)}>
|
|
273
|
+
<FormattedMessage
|
|
274
|
+
id={'orderRow.ViewTransactionDetail'}
|
|
275
|
+
defaultMessage={'Write a Review'}
|
|
276
|
+
/>
|
|
277
|
+
</span>
|
|
278
|
+
</>
|
|
279
|
+
)}
|
|
252
280
|
<Link
|
|
253
281
|
to={{
|
|
254
282
|
pathname: `/order-history/view/${orderNumber}`,
|
|
255
283
|
state: { order }
|
|
256
284
|
}}
|
|
257
285
|
>
|
|
258
|
-
<span className="bg-blue-700 hover:bg-white hover:text-blue-700 hover:border hover:border-blue-700 rounded-full px-[30px] py-[
|
|
286
|
+
<span className="bg-blue-700 hover:bg-white hover:text-blue-700 hover:border hover:border-blue-700 rounded-full px-[30px] py-[8px] text-[13px] font-medium text-white transition-all duration-300 ease-in-out">
|
|
259
287
|
<FormattedMessage
|
|
260
288
|
id={'orderRow.ViewTransactionDetail'}
|
|
261
|
-
defaultMessage={'View Order
|
|
289
|
+
defaultMessage={'View Order'}
|
|
262
290
|
/>
|
|
263
291
|
</span>
|
|
264
292
|
</Link>
|
|
265
293
|
{showNewReturnButton && (
|
|
266
|
-
|
|
267
|
-
className=
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
294
|
+
<>
|
|
295
|
+
<span className="bg-white border border-blue-700 bg-white text-blue-700 hover:bg-blue-50 hover:text-blue-700 hover:border-blue-700 rounded-full px-[30px] py-[8px] text-[13px] font-medium text-white transition-all duration-300 ease-in-out">
|
|
296
|
+
<FormattedMessage
|
|
297
|
+
id={'orderRow.ReturnItems'}
|
|
298
|
+
defaultMessage={'Return Items'}
|
|
299
|
+
/>
|
|
300
|
+
</span>
|
|
301
|
+
{/* <div
|
|
302
|
+
className={cn(
|
|
303
|
+
"cursor-pointer ",
|
|
304
|
+
"rounded-full px-[10px] py-[3px] text-[13px] font-medium transition-all duration-300 ease-in-out flex items-center gap-2"
|
|
305
|
+
)}
|
|
306
|
+
onClick={handleNewReturn}
|
|
307
|
+
title={formatMessage({ id: 'orderRow.returnProduct', defaultMessage: 'Return Product' })}
|
|
308
|
+
>
|
|
309
|
+
<ConvertCard size={20} color="#f26313" />
|
|
310
|
+
<FormattedMessage
|
|
311
|
+
id={'orderRow.ReturnItems'}
|
|
312
|
+
defaultMessage={'Return Items'}
|
|
313
|
+
/>
|
|
314
|
+
</div> */}
|
|
315
|
+
</>
|
|
280
316
|
)}
|
|
281
317
|
</div>
|
|
282
318
|
</div>
|
package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/modalFormReview.js
CHANGED
|
@@ -9,17 +9,17 @@ import StarRating from './starInput';
|
|
|
9
9
|
|
|
10
10
|
import { primary900 } from '@riosst100/pwa-marketplace/src/theme/vars';
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
const {
|
|
12
|
+
const ModalFormReview = (props) => {
|
|
13
|
+
const { reviewOrder, setReviewOrder, ratingsMetadata = [], loadingRatingsMetadata, onSubmit, submitting, defaultNickname } = props;
|
|
14
14
|
|
|
15
15
|
const [formState, setFormState] = useState({ nickname: defaultNickname || '' });
|
|
16
16
|
|
|
17
17
|
useEffect(() => {
|
|
18
|
-
if (
|
|
18
|
+
if (reviewOrder && defaultNickname && !formState.nickname) {
|
|
19
19
|
setFormState(prev => ({ ...prev, nickname: defaultNickname }));
|
|
20
20
|
}
|
|
21
21
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
22
|
-
}, [
|
|
22
|
+
}, [reviewOrder, defaultNickname]);
|
|
23
23
|
|
|
24
24
|
// ratings: [{ id, value_id }]
|
|
25
25
|
const [ratings, setRatings] = useState([]);
|
|
@@ -45,7 +45,7 @@ const modalFormReview = (props) => {
|
|
|
45
45
|
return (
|
|
46
46
|
<>
|
|
47
47
|
<Modal
|
|
48
|
-
|
|
48
|
+
reviewOrder={reviewOrder}
|
|
49
49
|
className="modal_form_review !p-[30px] md_min-w-[650px]"
|
|
50
50
|
>
|
|
51
51
|
<div className='form_review-container'>
|
|
@@ -53,7 +53,7 @@ const modalFormReview = (props) => {
|
|
|
53
53
|
<div className='text-lg text-black font-medium'>
|
|
54
54
|
Write Review
|
|
55
55
|
</div>
|
|
56
|
-
<button onClick={() => {
|
|
56
|
+
<button onClick={() => { setReviewOrder(!reviewOrder) }} >
|
|
57
57
|
<X size={24} color={primary900} />
|
|
58
58
|
</button>
|
|
59
59
|
</div>
|
|
@@ -145,7 +145,7 @@ const modalFormReview = (props) => {
|
|
|
145
145
|
classes={{
|
|
146
146
|
content: 'capitalize text-[16px] font-medium'
|
|
147
147
|
}}
|
|
148
|
-
onClick={() =>
|
|
148
|
+
onClick={() => setReviewOrder(false)}
|
|
149
149
|
type="button"
|
|
150
150
|
>
|
|
151
151
|
Cancel
|
|
@@ -168,4 +168,4 @@ const modalFormReview = (props) => {
|
|
|
168
168
|
);
|
|
169
169
|
};
|
|
170
170
|
|
|
171
|
-
export default
|
|
171
|
+
export default ModalFormReview;
|
package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/productReview.js
CHANGED
|
@@ -2,9 +2,6 @@ import React, { useState } from 'react'
|
|
|
2
2
|
import Review from '@riosst100/pwa-marketplace/src/components/ProductReviewItem';
|
|
3
3
|
import { Star1 } from 'iconsax-react';
|
|
4
4
|
import Button from '../../Button';
|
|
5
|
-
import ModalFormReview from './modalFormReview';
|
|
6
|
-
|
|
7
|
-
|
|
8
5
|
|
|
9
6
|
const productReview = (props) => {
|
|
10
7
|
const {
|
|
@@ -56,29 +53,9 @@ const productReview = (props) => {
|
|
|
56
53
|
if (!reviewsData || !reviewsData.items.length) {
|
|
57
54
|
return (
|
|
58
55
|
<>
|
|
59
|
-
|
|
60
|
-
open={open}
|
|
61
|
-
setOpen={setOpen}
|
|
62
|
-
defaultNickname={defaultNickname}
|
|
63
|
-
ratingsMetadata={ratingsMetadataData?.productReviewRatingsMetadata?.items || []}
|
|
64
|
-
loadingRatingsMetadata={loadingRatingsMetadata}
|
|
65
|
-
onSubmit={async (formValues) => {
|
|
66
|
-
setSubmitting(true);
|
|
67
|
-
const input = {
|
|
68
|
-
nickname: formValues.nickname,
|
|
69
|
-
summary: formValues.summary,
|
|
70
|
-
text: formValues.review,
|
|
71
|
-
sku: product?.sku,
|
|
72
|
-
ratings: formValues.ratings
|
|
73
|
-
};
|
|
74
|
-
const result = await handleSubmitReview(input);
|
|
75
|
-
setSubmitting(false);
|
|
76
|
-
if (result.success) setOpen(false);
|
|
77
|
-
}}
|
|
78
|
-
submitting={submitting}
|
|
79
|
-
/>
|
|
56
|
+
|
|
80
57
|
<div className={className}>
|
|
81
|
-
<div className="flex items-center justify-between mb-6">
|
|
58
|
+
{/* <div className="flex items-center justify-between mb-6">
|
|
82
59
|
<div />
|
|
83
60
|
<Button
|
|
84
61
|
priority='low'
|
|
@@ -89,8 +66,8 @@ const productReview = (props) => {
|
|
|
89
66
|
>
|
|
90
67
|
Write a review
|
|
91
68
|
</Button>
|
|
92
|
-
</div>
|
|
93
|
-
<div className="text-center py-8 text-gray-
|
|
69
|
+
</div> */}
|
|
70
|
+
<div className="text-center py-8 text-gray-600 text-[14px]">No reviews yet.</div>
|
|
94
71
|
</div>
|
|
95
72
|
</>
|
|
96
73
|
);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { gql } from '@apollo/client';
|
|
2
|
+
|
|
3
|
+
const GET_PRODUCT_REVIEW_RATINGS_METADATA = gql`
|
|
4
|
+
query getProductReviewRatingsMetadata {
|
|
5
|
+
productReviewRatingsMetadata {
|
|
6
|
+
items {
|
|
7
|
+
id
|
|
8
|
+
name
|
|
9
|
+
values {
|
|
10
|
+
value
|
|
11
|
+
value_id
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const CREATE_PRODUCT_REVIEW = gql`
|
|
19
|
+
mutation CreateProductReview($input: CreateProductReviewInput!) {
|
|
20
|
+
createProductReview(input: $input) {
|
|
21
|
+
review {
|
|
22
|
+
average_rating
|
|
23
|
+
created_at
|
|
24
|
+
nickname
|
|
25
|
+
product {
|
|
26
|
+
uuid: uid
|
|
27
|
+
uid
|
|
28
|
+
name
|
|
29
|
+
sku
|
|
30
|
+
}
|
|
31
|
+
ratings_breakdown {
|
|
32
|
+
name
|
|
33
|
+
value
|
|
34
|
+
}
|
|
35
|
+
summary
|
|
36
|
+
text
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
createProductReview: CREATE_PRODUCT_REVIEW,
|
|
44
|
+
getProductReviewRatingsMetadata: GET_PRODUCT_REVIEW_RATINGS_METADATA
|
|
45
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useCallback, useMemo } from 'react';
|
|
2
|
+
import { useToasts } from '@magento/peregrine/lib';
|
|
3
|
+
import { useMutation, useQuery } from '@apollo/client';
|
|
4
|
+
import { useUserContext } from '@magento/peregrine/lib/context/user';
|
|
5
|
+
import { useHistory } from 'react-router-dom';
|
|
6
|
+
import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
|
|
7
|
+
import defaultOperations from '@magento/peregrine/lib/talons/ProductFullDetail/productFullDetail.gql';
|
|
8
|
+
import productReviewOperations from './reviewModal.gql';
|
|
9
|
+
|
|
10
|
+
export const useReviewModal = props => {
|
|
11
|
+
const { reviewOrder, setSubmitting } = props;
|
|
12
|
+
|
|
13
|
+
const history = useHistory();
|
|
14
|
+
|
|
15
|
+
const handleToastAction = useCallback(
|
|
16
|
+
(removeToast) => {
|
|
17
|
+
history.push('/cart');
|
|
18
|
+
removeToast();
|
|
19
|
+
},
|
|
20
|
+
[history]
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const [, { addToast }] = useToasts();
|
|
24
|
+
|
|
25
|
+
const operations = mergeOperations(defaultOperations, props.operations);
|
|
26
|
+
|
|
27
|
+
// Query for ratings metadata
|
|
28
|
+
const { data: ratingsMetadata, loading: loadingRatingsMetadata } = useQuery(
|
|
29
|
+
productReviewOperations.getProductReviewRatingsMetadata,
|
|
30
|
+
{ fetchPolicy: 'network-only' }
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Mutation for creating review (allow partial data with errors)
|
|
34
|
+
const [createProductReview, { loading: loadingCreateReview, error: errorCreateReview }] = useMutation(
|
|
35
|
+
productReviewOperations.createProductReview,
|
|
36
|
+
{ errorPolicy: 'all' }
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Handler for submitting review with robust toast handling
|
|
40
|
+
const handleSubmitReview = async (formValues) => {
|
|
41
|
+
try {
|
|
42
|
+
setSubmitting(true)
|
|
43
|
+
|
|
44
|
+
const result = await createProductReview({
|
|
45
|
+
variables: { input: formValues },
|
|
46
|
+
errorPolicy: 'all'
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const gqlErrors = result?.errors || [];
|
|
50
|
+
const review = result?.data?.createProductReview?.review;
|
|
51
|
+
|
|
52
|
+
if (gqlErrors.length > 0 || !review) {
|
|
53
|
+
const message = gqlErrors[0]?.message || 'Failed to submit review!';
|
|
54
|
+
addToast({ type: 'error', message });
|
|
55
|
+
return { success: false, error: gqlErrors };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
addToast({ type: 'success', message: 'Review submitted successfully!' });
|
|
59
|
+
return { success: true };
|
|
60
|
+
} catch (e) {
|
|
61
|
+
addToast({ type: 'error', message: e?.message || 'Failed to submit review!' });
|
|
62
|
+
return { success: false, error: e };
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const [{ currentUser }] = useUserContext();
|
|
67
|
+
|
|
68
|
+
const defaultNickname = useMemo(() => {
|
|
69
|
+
if (!currentUser) return '';
|
|
70
|
+
const first = currentUser.firstname || '';
|
|
71
|
+
const last = currentUser.lastname || '';
|
|
72
|
+
const full = `${first} ${last}`.trim();
|
|
73
|
+
if (full) return full;
|
|
74
|
+
const email = currentUser.email || '';
|
|
75
|
+
return email ? email.split('@')[0] : '';
|
|
76
|
+
}, [currentUser]);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
ratingsMetadata: ratingsMetadata?.productReviewRatingsMetadata?.items[0] || null,
|
|
80
|
+
loadingRatingsMetadata,
|
|
81
|
+
handleSubmitReview,
|
|
82
|
+
loadingCreateReview,
|
|
83
|
+
errorCreateReview,
|
|
84
|
+
defaultNickname,
|
|
85
|
+
handleToastAction
|
|
86
|
+
};
|
|
87
|
+
};
|