@riosst100/pwa-marketplace 3.0.3 → 3.0.5
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 +1 -0
- package/src/components/CrossSeller/item.js +3 -4
- package/src/components/LinkToOtherStores/index.js +4 -4
- package/src/components/OrderDetail/components/itemsOrdered.js +1 -6
- package/src/components/ProductListTab/productListTab.js +1 -1
- package/src/components/RMAPage/components/productItem.js +13 -43
- 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/components/commons/Select/index.js +8 -4
- package/src/overwrites/peregrine/lib/talons/CartPage/PriceSummary/priceSummaryFragments.gql.js +3 -0
- package/src/overwrites/peregrine/lib/talons/CartPage/PriceSummary/usePriceSummary.js +2 -2
- package/src/overwrites/peregrine/lib/talons/CartPage/ProductListing/productListingFragments.gql.js +4 -0
- package/src/overwrites/peregrine/lib/talons/CheckoutPage/checkoutPage.extended.gql.js +20 -1
- package/src/overwrites/peregrine/lib/talons/FilterSidebar/useFilterSidebar.js +3 -3
- package/src/overwrites/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js +7 -8
- package/src/overwrites/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js +5 -0
- package/src/overwrites/venia-ui/lib/components/Breadcrumbs/breadcrumbs.js +20 -1
- 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/ProductListing/product.js +41 -1
- package/src/overwrites/venia-ui/lib/components/CartPage/ProductListing/product.module.css +1 -1
- package/src/overwrites/venia-ui/lib/components/CartPage/ProductListingBySeller/productListingBySeller.js +41 -8
- package/src/overwrites/venia-ui/lib/components/CartPage/cartPage.js +0 -7
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/ItemsReview/item.js +43 -2
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/ItemsReview/item.module.css +36 -0
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/ItemsReview/itemsReview.js +8 -2
- 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 +9 -4
- package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.module.css +2 -0
- package/src/overwrites/venia-ui/lib/components/FilterModal/CurrentFilters/currentFilters.js +1 -1
- package/src/overwrites/venia-ui/lib/components/FilterSidebar/filterSidebar.js +1 -1
- package/src/overwrites/venia-ui/lib/components/Gallery/item.js +2 -10
- package/src/overwrites/venia-ui/lib/components/Gallery/item.module.css +5 -4
- 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/CustomAttributes/customAttributes.js +10 -2
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/modalFormReview.js +8 -8
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/preOrderDetail.js +195 -37
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/components/productReview.js +4 -27
- package/src/overwrites/venia-ui/lib/components/ProductFullDetail/productFullDetail.js +194 -63
- package/src/talons/ProductContent/productContent.gql.js +11 -1
- package/src/talons/ProductContent/useProductContent.js +14 -2
- package/src/talons/ReviewModal/reviewModal.gql.js +45 -0
- package/src/talons/ReviewModal/useReviewModal.js +87 -0
- package/src/components/RMAPage/components/productItem.css +0 -15
- package/src/components/RMAPage/components/productItem.module.css +0 -15
|
@@ -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">
|
|
@@ -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>
|
|
@@ -13,14 +13,22 @@ const CustomAttributes = props => {
|
|
|
13
13
|
const { customAttributes, showLabels } = props;
|
|
14
14
|
const classes = useStyle(defaultClasses, props.classes);
|
|
15
15
|
|
|
16
|
+
const systemAttributes = [
|
|
17
|
+
'term_and_conditions',
|
|
18
|
+
'sale',
|
|
19
|
+
'sku'
|
|
20
|
+
];
|
|
21
|
+
|
|
16
22
|
const list = useMemo(
|
|
17
23
|
() =>
|
|
18
24
|
customAttributes.reduce((previousAttribute, currentAttribute) => {
|
|
25
|
+
console.log('currentAttribute',currentAttribute)
|
|
26
|
+
const attrCode = currentAttribute.attribute_metadata?.code;
|
|
19
27
|
const usedInComponents =
|
|
20
28
|
currentAttribute.attribute_metadata?.used_in_components ||
|
|
21
29
|
[];
|
|
22
30
|
// Visible on front attributes only
|
|
23
|
-
if (usedInComponents.includes(IS_VISIBLE_ON_FRONT)) {
|
|
31
|
+
if (!systemAttributes.includes(attrCode) && usedInComponents.includes(IS_VISIBLE_ON_FRONT)) {
|
|
24
32
|
const attributeContent = (
|
|
25
33
|
<li
|
|
26
34
|
key={currentAttribute.attribute_metadata.uid}
|
|
@@ -38,7 +46,7 @@ const CustomAttributes = props => {
|
|
|
38
46
|
|
|
39
47
|
return previousAttribute;
|
|
40
48
|
}, []),
|
|
41
|
-
[classes, customAttributes, showLabels]
|
|
49
|
+
[classes, customAttributes, showLabels, systemAttributes]
|
|
42
50
|
);
|
|
43
51
|
|
|
44
52
|
if (list.length === 0) {
|
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/preOrderDetail.js
CHANGED
|
@@ -1,58 +1,216 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import Divider from '@riosst100/pwa-marketplace/src/components/Divider';
|
|
4
|
+
import Select from '@riosst100/pwa-marketplace/src/components/commons/Select';
|
|
4
5
|
|
|
5
6
|
const preOrderInfo = (props) => {
|
|
6
|
-
const { className,
|
|
7
|
-
|
|
8
|
-
const preorderData = productDetails ? productDetails.preorder : null;
|
|
7
|
+
const { className, preOrder, preOrderDate, preOrderDeposite, preOrderNote, preOrderPaymentType, releaseDate, onPaymentTypeChange, paymentTypeOptions = [] } = props;
|
|
9
8
|
|
|
10
|
-
const isPreOrder =
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const isPreOrder = typeof preOrder === 'string'
|
|
10
|
+
? preOrder.trim().toLowerCase() === 'pre orders'
|
|
11
|
+
: !!(preOrder && preOrder.is_preorder);
|
|
12
|
+
|
|
13
|
+
const normalizePaymentType = (value = '') => {
|
|
14
|
+
const normalized = value.toString().trim().toLowerCase();
|
|
15
|
+
|
|
16
|
+
if (normalized === 'full payment') {
|
|
17
|
+
return 'full';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (normalized === 'deposit' || normalized === 'full') {
|
|
21
|
+
return normalized;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return '';
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const initialPaymentType = useMemo(
|
|
28
|
+
() => normalizePaymentType(preOrderPaymentType),
|
|
29
|
+
[preOrderPaymentType]
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const [selectedPaymentType, setSelectedPaymentType] = useState(initialPaymentType || 'full');
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
setSelectedPaymentType(initialPaymentType || 'full');
|
|
36
|
+
}, [initialPaymentType]);
|
|
37
|
+
|
|
38
|
+
// Propagate initial and subsequent selection to parent so submit has value
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (typeof onPaymentTypeChange === 'function' && selectedPaymentType) {
|
|
41
|
+
onPaymentTypeChange(selectedPaymentType);
|
|
42
|
+
}
|
|
43
|
+
}, [selectedPaymentType, onPaymentTypeChange]);
|
|
44
|
+
|
|
45
|
+
const normalizedPaymentOptions = useMemo(() => {
|
|
46
|
+
return paymentTypeOptions.reduce((acc, option) => {
|
|
47
|
+
const normalizedValue = normalizePaymentType(option.value);
|
|
48
|
+
if (!normalizedValue) {
|
|
49
|
+
return acc;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (acc.find(item => item.value === normalizedValue)) {
|
|
53
|
+
return acc;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const label = option.label || (normalizedValue === 'full' ? 'Full Payment' : 'Deposit');
|
|
57
|
+
acc.push({ label, value: normalizedValue });
|
|
58
|
+
return acc;
|
|
59
|
+
}, []);
|
|
60
|
+
}, [paymentTypeOptions]);
|
|
61
|
+
|
|
62
|
+
const paymentOptions = useMemo(() => {
|
|
63
|
+
const optionsToUse = normalizedPaymentOptions;
|
|
64
|
+
|
|
65
|
+
if (!optionsToUse.length) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (initialPaymentType === 'full') {
|
|
70
|
+
return optionsToUse.filter(option => option.value === 'full');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (initialPaymentType === 'deposit') {
|
|
74
|
+
return optionsToUse;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return optionsToUse;
|
|
78
|
+
}, [initialPaymentType, normalizedPaymentOptions]);
|
|
79
|
+
|
|
80
|
+
const handlePaymentTypeChange = (event) => {
|
|
81
|
+
if (!paymentOptions.length) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const nextValue = event.target.value;
|
|
86
|
+
const availableValues = paymentOptions.map(option => option.value);
|
|
87
|
+
const appliedValue = availableValues.includes(nextValue)
|
|
88
|
+
? nextValue
|
|
89
|
+
: availableValues[0];
|
|
90
|
+
|
|
91
|
+
setSelectedPaymentType(appliedValue);
|
|
92
|
+
|
|
93
|
+
if (typeof onPaymentTypeChange === 'function') {
|
|
94
|
+
onPaymentTypeChange(appliedValue);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const formatDate = (value) => {
|
|
99
|
+
if (!value) {
|
|
100
|
+
return '-';
|
|
101
|
+
}
|
|
13
102
|
|
|
14
|
-
|
|
103
|
+
const parsed = value instanceof Date ? value : new Date(value);
|
|
104
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
105
|
+
return '-';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const day = String(parsed.getDate()).padStart(2, '0');
|
|
109
|
+
const month = String(parsed.getMonth() + 1).padStart(2, '0');
|
|
110
|
+
const year = parsed.getFullYear();
|
|
111
|
+
|
|
112
|
+
return `${day}/${month}/${year}`;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const preOrderNotes = preOrderNote || null;
|
|
116
|
+
const preOrderAvailableDate = releaseDate || null;
|
|
117
|
+
const preOrderClosingDate = preOrderDate || null;
|
|
118
|
+
|
|
119
|
+
const normalizeDeposit = (value) => {
|
|
120
|
+
if (!value && value !== 0) {
|
|
121
|
+
return '-';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const numeric = typeof value === 'number'
|
|
125
|
+
? value
|
|
126
|
+
: Number.parseFloat(value.toString().replace(/[^0-9.-]/g, ''));
|
|
127
|
+
|
|
128
|
+
if (Number.isNaN(numeric)) {
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Tampilkan sebagai persentase tanpa 0 di belakang koma dan tambahkan '%'
|
|
133
|
+
// Contoh: 10.00 -> '10%'; 12.5 -> '12.5%'; 12.50 -> '12.5%'
|
|
134
|
+
let str = numeric.toString();
|
|
135
|
+
if (str.includes('.')) {
|
|
136
|
+
// hapus trailing zeros di desimal
|
|
137
|
+
str = str.replace(/\.0+$/,'');
|
|
138
|
+
str = str.replace(/\.(\d*[1-9])0+$/,'.$1');
|
|
139
|
+
}
|
|
140
|
+
return `${str}%`;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const depositValue = normalizeDeposit(preOrderDeposite);
|
|
144
|
+
const showDepositRow = selectedPaymentType === 'deposit';
|
|
145
|
+
|
|
146
|
+
const isPreOrderClosed = (() => {
|
|
147
|
+
if (!preOrderClosingDate) return false;
|
|
148
|
+
|
|
149
|
+
const parsed = preOrderClosingDate instanceof Date
|
|
150
|
+
? preOrderClosingDate
|
|
151
|
+
: new Date(preOrderClosingDate);
|
|
152
|
+
|
|
153
|
+
if (Number.isNaN(parsed.getTime())) return false;
|
|
154
|
+
|
|
155
|
+
parsed.setHours(23, 59, 59, 999);
|
|
156
|
+
return new Date().getTime() > parsed.getTime();
|
|
157
|
+
})();
|
|
15
158
|
|
|
16
159
|
return isPreOrder ? (
|
|
17
160
|
<>
|
|
18
161
|
<div
|
|
19
162
|
className={cn(
|
|
20
|
-
'flex flex-col border border-gray-100 rounded-lg p-5 gap-
|
|
163
|
+
'flex flex-col border border-gray-100 rounded-lg p-5 m-4 gap-4 bg-white',
|
|
21
164
|
className
|
|
22
165
|
)}
|
|
23
166
|
>
|
|
24
|
-
<div className='
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
167
|
+
<div className='text-[16px] font-semibold text-colorDefault'>
|
|
168
|
+
Pre Order Details
|
|
169
|
+
</div>
|
|
170
|
+
<div className='flex flex-col gap-3'>
|
|
171
|
+
{showDepositRow && (
|
|
172
|
+
<>
|
|
173
|
+
<div className='flex justify-between text-[13px] text-gray-600'>
|
|
174
|
+
<span className='font-medium text-gray-500'>Deposit:</span>
|
|
175
|
+
<span className='font-medium text-colorDefault'>{depositValue}</span>
|
|
176
|
+
</div>
|
|
177
|
+
<Divider className='h-px w-full bg-gray-100' />
|
|
178
|
+
</>
|
|
179
|
+
)}
|
|
180
|
+
<div className='flex justify-between items-center text-[13px] text-gray-600 gap-4'>
|
|
181
|
+
<span className='font-medium text-gray-500'>Payment Type:</span>
|
|
182
|
+
<Select
|
|
183
|
+
wrapperClassname='justify-end w-full max-w-[180px]'
|
|
184
|
+
className='w-full text-[13px]'
|
|
185
|
+
options={paymentOptions}
|
|
186
|
+
value={selectedPaymentType}
|
|
187
|
+
onChange={handlePaymentTypeChange}
|
|
188
|
+
showPlaceholder={false}
|
|
189
|
+
/>
|
|
33
190
|
</div>
|
|
34
|
-
<Divider className=
|
|
35
|
-
<div className='flex
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
</div>
|
|
39
|
-
<div className='text-[16px] font-medium text-colorDefault text-center'>
|
|
40
|
-
31, March 2024
|
|
41
|
-
</div>
|
|
191
|
+
<Divider className='h-px w-full bg-gray-100' />
|
|
192
|
+
<div className='flex justify-between text-[13px] text-gray-600'>
|
|
193
|
+
<span className='font-medium text-gray-500'>Pre Order Closing Date:</span>
|
|
194
|
+
<span className='font-medium text-colorDefault'>{formatDate(preOrderClosingDate)}</span>
|
|
42
195
|
</div>
|
|
43
|
-
<Divider className=
|
|
44
|
-
<div className='flex
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
</div>
|
|
48
|
-
<div className='text-[16px] font-medium text-colorDefault text-center'>
|
|
49
|
-
40%
|
|
50
|
-
</div>
|
|
196
|
+
<Divider className='h-px w-full bg-gray-100' />
|
|
197
|
+
<div className='flex justify-between text-[13px] text-gray-600'>
|
|
198
|
+
<span className='font-medium text-gray-500'>Release Date:</span>
|
|
199
|
+
<span className='font-medium text-colorDefault'>{formatDate(preOrderAvailableDate)}</span>
|
|
51
200
|
</div>
|
|
201
|
+
<Divider className='h-px w-full bg-gray-100' />
|
|
202
|
+
<div className='flex justify-between text-[13px] text-gray-600'>
|
|
203
|
+
<span className='font-medium text-gray-500'>Note:</span>
|
|
204
|
+
<span className='font-medium text-colorDefault text-right'>
|
|
205
|
+
{preOrderNotes || '-'}
|
|
206
|
+
</span>
|
|
207
|
+
</div>
|
|
208
|
+
{isPreOrderClosed && (
|
|
209
|
+
<div className='mt-1 text-[12px] text-red-500 font-medium'>
|
|
210
|
+
Pre order is closed. You can no longer place a pre-order for this product.
|
|
211
|
+
</div>
|
|
212
|
+
)}
|
|
52
213
|
</div>
|
|
53
|
-
{preOrderNotes && <p>
|
|
54
|
-
Notes : {preOrderNotes}
|
|
55
|
-
</p>}
|
|
56
214
|
</div>
|
|
57
215
|
</>
|
|
58
216
|
) : ''
|