@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
|
@@ -189,11 +189,11 @@ export const useFilterSidebar = props => {
|
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
191
|
'label': 'Preorder',
|
|
192
|
-
'value': '
|
|
192
|
+
'value': 'card_pre_orders',
|
|
193
193
|
'path': '',
|
|
194
194
|
'options': [
|
|
195
|
-
{'value':'0','label':'
|
|
196
|
-
{'value':'1','label':'
|
|
195
|
+
{'value':'0','label':'','title':''},
|
|
196
|
+
{'value':'1','label':'Pre Orders','title':'Pre Orders'}
|
|
197
197
|
]
|
|
198
198
|
},
|
|
199
199
|
{
|
|
@@ -579,7 +579,7 @@ export const useProductFullDetail = props => {
|
|
|
579
579
|
|
|
580
580
|
const handleAddToCart = useCallback(
|
|
581
581
|
async formValues => {
|
|
582
|
-
const { quantity } = formValues;
|
|
582
|
+
const { quantity, preorder } = formValues;
|
|
583
583
|
|
|
584
584
|
/*
|
|
585
585
|
@deprecated in favor of general addProductsToCart mutation. Will support until the next MAJOR.
|
|
@@ -636,15 +636,13 @@ export const useProductFullDetail = props => {
|
|
|
636
636
|
product: {
|
|
637
637
|
sku: product.sku,
|
|
638
638
|
quantity
|
|
639
|
-
}
|
|
640
|
-
entered_options: [
|
|
641
|
-
{
|
|
642
|
-
uid: product.uid,
|
|
643
|
-
value: product.name
|
|
644
|
-
}
|
|
645
|
-
]
|
|
639
|
+
}
|
|
646
640
|
};
|
|
647
641
|
|
|
642
|
+
if (preorder && Object.keys(preorder).length) {
|
|
643
|
+
variables.product.preorder = preorder;
|
|
644
|
+
}
|
|
645
|
+
|
|
648
646
|
if (selectedOptionsArray.length) {
|
|
649
647
|
variables.product.selected_options = selectedOptionsArray;
|
|
650
648
|
}
|
|
@@ -721,6 +719,7 @@ export const useProductFullDetail = props => {
|
|
|
721
719
|
price_range: product?.price_range,
|
|
722
720
|
sku: productSku,
|
|
723
721
|
publish_status: product.publish_status,
|
|
722
|
+
custom_table_metadata: product.custom_table_metadata,
|
|
724
723
|
term_and_conditions: product.term_and_conditions,
|
|
725
724
|
link_to_other_stores: product.link_to_other_stores,
|
|
726
725
|
shipping_policy: product.shipping_policy,
|
|
@@ -22,7 +22,7 @@ import { useLocation } from 'react-router-dom';
|
|
|
22
22
|
const Breadcrumbs = props => {
|
|
23
23
|
const classes = useStyle(defaultClasses, props.classes);
|
|
24
24
|
|
|
25
|
-
const { categoryId, currentProduct, customPage, currentFilter } = props;
|
|
25
|
+
const { categoryId, currentProduct, customPage, currentFilter, currentProductCustomTableMetadata, customAttributesDetails } = props;
|
|
26
26
|
|
|
27
27
|
const talonProps = useBreadcrumbs({ categoryId });
|
|
28
28
|
|
|
@@ -103,6 +103,25 @@ const Breadcrumbs = props => {
|
|
|
103
103
|
|
|
104
104
|
const params = removeShopbyParam(search);
|
|
105
105
|
|
|
106
|
+
if (currentProductCustomTableMetadata) {
|
|
107
|
+
const mainAttrCode = currentProductCustomTableMetadata.mainAttrCode;
|
|
108
|
+
const mainAttrVal = currentProductCustomTableMetadata.mainAttrVal;
|
|
109
|
+
const mainAttrLabel = currentProductCustomTableMetadata.mainAttrLabel;
|
|
110
|
+
|
|
111
|
+
filterBreadcrumbsElement.push(
|
|
112
|
+
<Fragment>
|
|
113
|
+
<span className={classes.divider}>{DELIMITER}</span>
|
|
114
|
+
<Link
|
|
115
|
+
className={classes.link}
|
|
116
|
+
to={resourceUrl('/' + currentCategoryPath + '?' + mainAttrCode + '[filter]=' + mainAttrLabel + ',' + mainAttrVal)}
|
|
117
|
+
onClick={handleClick}
|
|
118
|
+
>
|
|
119
|
+
{mainAttrLabel}
|
|
120
|
+
</Link>
|
|
121
|
+
</Fragment>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
106
125
|
currentFilter && currentFilter.length && currentFilter.map((filter, index) => {
|
|
107
126
|
currentProduct ? (
|
|
108
127
|
filterBreadcrumbsElement.push(
|
package/src/overwrites/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/couponCode.js
CHANGED
|
@@ -93,31 +93,31 @@ const CouponCode = props => {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
if (data.cart.applied_coupons) {
|
|
96
|
-
const codes = data.cart.applied_coupons.map(({ code }) => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
});
|
|
96
|
+
// const codes = data.cart.applied_coupons.map(({ code }) => {
|
|
97
|
+
// return (
|
|
98
|
+
// <Fragment key={code}>
|
|
99
|
+
// <span>{code}</span>
|
|
100
|
+
// <LinkButton
|
|
101
|
+
// className={classes.removeButton}
|
|
102
|
+
// disabled={removingCoupon}
|
|
103
|
+
// data-cy="CouponCode-removeCouponButton"
|
|
104
|
+
// onClick={() => {
|
|
105
|
+
// handleRemoveCoupon(code);
|
|
106
|
+
// }}
|
|
107
|
+
// onKeyDown={() => {
|
|
108
|
+
// handleRemoveCouponOnEnter(code);
|
|
109
|
+
// }}
|
|
110
|
+
// >
|
|
111
|
+
// <FormattedMessage
|
|
112
|
+
// id={'couponCode.removeButton'}
|
|
113
|
+
// defaultMessage={'Remove'}
|
|
114
|
+
// />
|
|
115
|
+
// </LinkButton>
|
|
116
|
+
// </Fragment>
|
|
117
|
+
// );
|
|
118
|
+
// });
|
|
119
119
|
|
|
120
|
-
return
|
|
120
|
+
return '';
|
|
121
121
|
} else {
|
|
122
122
|
const errorMessage = deriveErrorMessage([
|
|
123
123
|
errors.get('applyCouponMutation')
|
|
@@ -160,9 +160,6 @@ const CouponCode = props => {
|
|
|
160
160
|
priority={'normal'}
|
|
161
161
|
type={'submit'}
|
|
162
162
|
onKeyDown={handleApplyCouponOnEnter}
|
|
163
|
-
classes={{
|
|
164
|
-
content: 'gap-1.5 grid-flow-col inline-grid items-center justify-center justify-items-center capitalize font-medium'
|
|
165
|
-
}}
|
|
166
163
|
>
|
|
167
164
|
<FormattedMessage
|
|
168
165
|
id={'couponCode.apply'}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
.entryForm,
|
|
3
3
|
.entryFormError {
|
|
4
4
|
composes: gap-x-sm from global;
|
|
5
|
+
composes: pb-2 from global;
|
|
5
6
|
composes: grid from global;
|
|
6
7
|
composes: grid-cols-autoLast from global;
|
|
7
8
|
}
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
/* switch to rows. */
|
|
15
16
|
grid-template-columns: unset;
|
|
16
17
|
grid-template-rows: 1fr 1fr;
|
|
18
|
+
composes: pb-2 from global;
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
|
|
@@ -10,6 +10,7 @@ import GiftCardSummary from './giftCardSummary';
|
|
|
10
10
|
import GiftOptionsSummary from './giftOptionsSummary';
|
|
11
11
|
import ShippingSummary from './shippingSummary';
|
|
12
12
|
import TaxSummary from './taxSummary';
|
|
13
|
+
import Shimmer from '@magento/venia-ui/lib/components/Shimmer';
|
|
13
14
|
import cn from 'classnames';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -74,9 +75,10 @@ const PriceSummary = props => {
|
|
|
74
75
|
|
|
75
76
|
const isPriceUpdating = isUpdating || isLoading;
|
|
76
77
|
const priceClass = isPriceUpdating ? classes.priceUpdating : classes.price;
|
|
77
|
-
const totalPriceClass =
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
const totalPriceClass = classes.totalPrice;
|
|
79
|
+
// const totalPriceClass = isPriceUpdating
|
|
80
|
+
// ? classes.priceUpdating
|
|
81
|
+
// : classes.totalPrice;
|
|
80
82
|
|
|
81
83
|
const totalPriceLabel = isCheckout
|
|
82
84
|
? formatMessage({
|
|
@@ -88,7 +90,7 @@ const PriceSummary = props => {
|
|
|
88
90
|
defaultMessage: 'Estimated Total'
|
|
89
91
|
});
|
|
90
92
|
|
|
91
|
-
const proceedToCheckoutButton = (
|
|
93
|
+
const proceedToCheckoutButton = !isCheckout && (
|
|
92
94
|
<div className={cn(classes.checkoutButton_container, 'block !mt-6 !min-h-auto')}>
|
|
93
95
|
<Button
|
|
94
96
|
disabled={isPriceUpdating}
|
|
@@ -127,8 +129,15 @@ const PriceSummary = props => {
|
|
|
127
129
|
);
|
|
128
130
|
|
|
129
131
|
return (
|
|
130
|
-
<div className={cn(classes.root, 'pb-6 px-3')} data-cy="PriceSummary-root">
|
|
132
|
+
<div className={cn(classes.root, isCheckout ? 'pb-0 px-3' : 'pb-6 px-3')} data-cy="PriceSummary-root">
|
|
131
133
|
{isCheckout && (
|
|
134
|
+
isPriceUpdating ? <>
|
|
135
|
+
<Shimmer width="100%" height="20px" />
|
|
136
|
+
<Shimmer width="100%" height="20px" />
|
|
137
|
+
<Shimmer width="100%" height="20px" />
|
|
138
|
+
<Shimmer width="100%" height="20px" />
|
|
139
|
+
<Shimmer width="100%" height="20px" />
|
|
140
|
+
</> :
|
|
132
141
|
<div>
|
|
133
142
|
<ul>
|
|
134
143
|
<li className={classes.lineItems}>
|
|
@@ -30,7 +30,6 @@ const HeartIcon = <Heart size="16" color="#909090" />;
|
|
|
30
30
|
|
|
31
31
|
const Product = props => {
|
|
32
32
|
const { item } = props;
|
|
33
|
-
|
|
34
33
|
const { formatMessage } = useIntl();
|
|
35
34
|
const talonProps = useProduct({
|
|
36
35
|
operations: {
|
|
@@ -123,8 +122,49 @@ const Product = props => {
|
|
|
123
122
|
</Link>
|
|
124
123
|
<div className='flex flex-col'>
|
|
125
124
|
<div className={cn(classes.name, 'text-[14px] font-normal max-w-[260px]')} data-cy="Product-name">
|
|
125
|
+
{item.is_preorder && (
|
|
126
|
+
<span className="inline-flex items-center gap-1 px-2 py-[2px] mb-3 rounded-full bg-blue-600 text-white border border-blue-700 text-[11px] font-medium">
|
|
127
|
+
Preorder
|
|
128
|
+
</span>
|
|
129
|
+
)}
|
|
130
|
+
<br/>
|
|
126
131
|
<Link to={itemLink}>{name}</Link>
|
|
127
132
|
</div>
|
|
133
|
+
{item.is_preorder && (
|
|
134
|
+
<div className="mt-2 flex flex-col gap-1" aria-label="Preorder information">
|
|
135
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
136
|
+
<span className="text-[11px] text-amber-800">
|
|
137
|
+
Release: {(() => {
|
|
138
|
+
const rd = item?.product?.release_date;
|
|
139
|
+
if (!rd) return '-';
|
|
140
|
+
const d = new Date(rd);
|
|
141
|
+
if (isNaN(d.getTime())) return rd;
|
|
142
|
+
const dd = String(d.getDate()).padStart(2, '0');
|
|
143
|
+
const mm = String(d.getMonth() + 1).padStart(2, '0');
|
|
144
|
+
const yyyy = d.getFullYear();
|
|
145
|
+
return `${dd}/${mm}/${yyyy}`;
|
|
146
|
+
})()}
|
|
147
|
+
</span>
|
|
148
|
+
{item.pre_order_payment_type === 'deposit' && item.pre_order_deposit != null && (
|
|
149
|
+
<span className="text-[11px] text-amber-800">
|
|
150
|
+
{(() => {
|
|
151
|
+
const raw = item.pre_order_deposit;
|
|
152
|
+
const n = typeof raw === 'number' ? raw : Number.parseFloat(String(raw).replace(/[^0-9.-]/g,''));
|
|
153
|
+
if (!Number.isFinite(n)) {
|
|
154
|
+
return `Deposit: ${raw}`;
|
|
155
|
+
}
|
|
156
|
+
let str = n.toString();
|
|
157
|
+
if (str.includes('.')) {
|
|
158
|
+
str = str.replace(/\.0+$/,'');
|
|
159
|
+
str = str.replace(/\.(\d*[1-9])0+$/,'.$1');
|
|
160
|
+
}
|
|
161
|
+
return `Deposit: ${str}%`;
|
|
162
|
+
})()}
|
|
163
|
+
</span>
|
|
164
|
+
)}
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
)}
|
|
128
168
|
<ProductOptions
|
|
129
169
|
options={options}
|
|
130
170
|
classes={{
|
|
@@ -80,7 +80,46 @@ const ProductListingBySeller = props => {
|
|
|
80
80
|
wishlistConfig={wishlistConfig}
|
|
81
81
|
/>
|
|
82
82
|
));
|
|
83
|
-
|
|
83
|
+
// Helpers for currency + subtotal formatting
|
|
84
|
+
const aggregateSubtotal = items => {
|
|
85
|
+
let total = 0;
|
|
86
|
+
let currency = null;
|
|
87
|
+
for (const it of items) {
|
|
88
|
+
const priceObj = it?.prices?.price;
|
|
89
|
+
if (priceObj) {
|
|
90
|
+
if (!currency) currency = priceObj.currency;
|
|
91
|
+
const unit = Number(priceObj.value) || 0;
|
|
92
|
+
const qty = Number(it?.quantity) || 0;
|
|
93
|
+
total += unit * qty;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { total, currency };
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const formatMoney = (value, currency) => {
|
|
100
|
+
if (value == null || !isFinite(value)) return '-';
|
|
101
|
+
if (!currency) return value.toFixed(2);
|
|
102
|
+
try {
|
|
103
|
+
const locale = currency === 'IDR' ? 'id-ID' : (currency === 'SGD' ? 'en-SG' : 'en-US');
|
|
104
|
+
const opts = currency === 'IDR'
|
|
105
|
+
? { style: 'currency', currency, minimumFractionDigits: 0, maximumFractionDigits: 0 }
|
|
106
|
+
: { style: 'currency', currency, minimumFractionDigits: 2, maximumFractionDigits: 2 };
|
|
107
|
+
let formatted = new Intl.NumberFormat(locale, opts).format(value);
|
|
108
|
+
if (currency === 'SGD') {
|
|
109
|
+
formatted = 'SGD ' + formatted
|
|
110
|
+
.replace(/^S?\$/,'')
|
|
111
|
+
.replace(/^SGD\s*/,'')
|
|
112
|
+
.trim();
|
|
113
|
+
}
|
|
114
|
+
return formatted;
|
|
115
|
+
} catch (e) {
|
|
116
|
+
return currency + ' ' + value.toFixed(2);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const { total: subtotalValue, currency: detectedCurrency } = aggregateSubtotal(items);
|
|
121
|
+
const displayCurrency = detectedCurrency || seller.seller_currency || 'SGD';
|
|
122
|
+
const formattedSubtotal = formatMoney(subtotalValue, displayCurrency);
|
|
84
123
|
const priceSummary = hasItems ? (
|
|
85
124
|
<PriceSummary isProceedToCheckout={isProceedToCheckout} setIsProceedToCheckout={setIsProceedToCheckout} setIsCartUpdating={setIsCartUpdating} isUpdating={isCartUpdating} sellerUrl={seller.seller_url} />
|
|
86
125
|
) : null;
|
|
@@ -103,13 +142,7 @@ const ProductListingBySeller = props => {
|
|
|
103
142
|
{productComponents}
|
|
104
143
|
<div className={classes.subtotalContainer}>
|
|
105
144
|
<div className={classes.subtotalLabel}>Subtotal:</div>
|
|
106
|
-
<div className={classes.subtotalAmount}>
|
|
107
|
-
{seller.seller_currency || 'SGD'} {items.reduce((total, item) => {
|
|
108
|
-
const itemPrice = item?.prices?.price?.value || 0;
|
|
109
|
-
const quantity = item?.quantity || 0;
|
|
110
|
-
return total + (itemPrice * quantity);
|
|
111
|
-
}, 0).toFixed(2)}
|
|
112
|
-
</div>
|
|
145
|
+
<div className={classes.subtotalAmount}>{formattedSubtotal}</div>
|
|
113
146
|
</div>
|
|
114
147
|
<div className={classes.summary_container}>
|
|
115
148
|
<div className={classes.summary_contents}>
|
|
@@ -75,10 +75,6 @@ const CartPage = props => {
|
|
|
75
75
|
return fullPageLoadingIndicator;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
const priceSummary = hasItems ? (
|
|
79
|
-
<PriceSummary isUpdating={isCartUpdating} />
|
|
80
|
-
) : null;
|
|
81
|
-
|
|
82
78
|
const productListing = hasItems ? (
|
|
83
79
|
<ProductListing
|
|
84
80
|
onAddToWishlistSuccess={onAddToWishlistSuccess}
|
|
@@ -132,9 +128,6 @@ const CartPage = props => {
|
|
|
132
128
|
{priceAdjustments}
|
|
133
129
|
</div> */}
|
|
134
130
|
{/* <div className={classes.summary_container}>
|
|
135
|
-
<div className={classes.summary_contents}>
|
|
136
|
-
{priceSummary}
|
|
137
|
-
</div>
|
|
138
131
|
</div> */}
|
|
139
132
|
</div>
|
|
140
133
|
</div>
|
|
@@ -15,11 +15,35 @@ const Item = props => {
|
|
|
15
15
|
quantity,
|
|
16
16
|
configurable_options,
|
|
17
17
|
isHidden,
|
|
18
|
-
configurableThumbnailSource
|
|
18
|
+
configurableThumbnailSource,
|
|
19
|
+
// Preorder-related fields passed via {...item}
|
|
20
|
+
is_preorder,
|
|
21
|
+
pre_order_payment_type,
|
|
22
|
+
pre_order_deposit,
|
|
23
|
+
release_date
|
|
19
24
|
} = props;
|
|
20
25
|
const classes = useStyle(defaultClasses, propClasses);
|
|
21
26
|
const className = isHidden ? classes.root_hidden : classes.root_visible;
|
|
22
27
|
const configured_variant = configuredVariant(configurable_options, product);
|
|
28
|
+
const formatDate = value => {
|
|
29
|
+
if (!value) return '-';
|
|
30
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
31
|
+
if (Number.isNaN(d.getTime())) return '-';
|
|
32
|
+
const dd = String(d.getDate()).padStart(2, '0');
|
|
33
|
+
const mm = String(d.getMonth() + 1).padStart(2, '0');
|
|
34
|
+
const yyyy = d.getFullYear();
|
|
35
|
+
return `${dd}/${mm}/${yyyy}`;
|
|
36
|
+
};
|
|
37
|
+
const formatDepositPercent = raw => {
|
|
38
|
+
const n = typeof raw === 'number' ? raw : Number.parseFloat(String(raw).replace(/[^0-9.-]/g,''));
|
|
39
|
+
if (!Number.isFinite(n)) return raw;
|
|
40
|
+
let str = n.toString();
|
|
41
|
+
if (str.includes('.')) {
|
|
42
|
+
str = str.replace(/\.0+$/,'');
|
|
43
|
+
str = str.replace(/\.(\d*[1-9])0+$/,'.$1');
|
|
44
|
+
}
|
|
45
|
+
return `${str}%`;
|
|
46
|
+
};
|
|
23
47
|
return (
|
|
24
48
|
<div className={className}>
|
|
25
49
|
<Image
|
|
@@ -33,7 +57,24 @@ const Item = props => {
|
|
|
33
57
|
: product.thumbnail.url
|
|
34
58
|
}
|
|
35
59
|
/>
|
|
36
|
-
<
|
|
60
|
+
<div className={classes.headerRow}>
|
|
61
|
+
{is_preorder && (
|
|
62
|
+
<span className={classes.preorderBadge}>Preorder</span>
|
|
63
|
+
)}
|
|
64
|
+
<span className={classes.name}>{product.name}</span>
|
|
65
|
+
</div>
|
|
66
|
+
{is_preorder && (
|
|
67
|
+
<div className={classes.preorderMeta} aria-label="Preorder information">
|
|
68
|
+
<span className={classes.metaItem}>
|
|
69
|
+
Release: {formatDate(typeof release_date !== 'undefined' ? release_date : product?.release_date)}
|
|
70
|
+
</span>
|
|
71
|
+
{pre_order_payment_type === 'deposit' && pre_order_deposit != null && (
|
|
72
|
+
<span className={classes.metaItem}>
|
|
73
|
+
Deposit: {formatDepositPercent(pre_order_deposit)}
|
|
74
|
+
</span>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
37
78
|
<ProductOptions
|
|
38
79
|
options={configurable_options}
|
|
39
80
|
classes={{
|
|
@@ -63,3 +63,39 @@
|
|
|
63
63
|
grid-column: 2 / span 1;
|
|
64
64
|
grid-row: 2 / span 1;
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
.headerRow {
|
|
68
|
+
grid-column: 2 / span 1;
|
|
69
|
+
grid-row: 1 / span 1;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: 8px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.preorderBadge {
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
gap: 4px;
|
|
78
|
+
padding: 2px 8px;
|
|
79
|
+
border-radius: 9999px;
|
|
80
|
+
background: #f26313; /* orange accent for visibility */
|
|
81
|
+
color: #fff;
|
|
82
|
+
border: 1px solid #f26313;
|
|
83
|
+
font-size: 10px;
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
margin-bottom: 5px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.preorderMeta {
|
|
89
|
+
grid-column: 2 / span 1;
|
|
90
|
+
grid-row: 2 / span 1;
|
|
91
|
+
margin-top: 4px;
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-wrap: wrap;
|
|
94
|
+
gap: 12px;
|
|
95
|
+
color: #000; /* amber-ish */
|
|
96
|
+
font-size: 11px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.metaItem {
|
|
100
|
+
display: inline-block;
|
|
101
|
+
}
|
|
@@ -15,8 +15,8 @@ import defaultClasses from './itemsReview.module.css';
|
|
|
15
15
|
* @param {Object} props.data an optional static data object to render instead of making a query for data.
|
|
16
16
|
*/
|
|
17
17
|
const ItemsReview = props => {
|
|
18
|
-
const { classes: propClasses } = props;
|
|
19
|
-
|
|
18
|
+
const { classes: propClasses, isPreorder, preOrderDeposit, preOrderPaymentType, releaseDate } = props;
|
|
19
|
+
|
|
20
20
|
const classes = useStyle(defaultClasses, propClasses);
|
|
21
21
|
|
|
22
22
|
const talonProps = useItemsReview({
|
|
@@ -38,6 +38,12 @@ const ItemsReview = props => {
|
|
|
38
38
|
{...item}
|
|
39
39
|
isHidden={!showAllItems && index >= 2}
|
|
40
40
|
configurableThumbnailSource={configurableThumbnailSource}
|
|
41
|
+
// Forward explicit preorder values from parent if provided
|
|
42
|
+
is_preorder={typeof isPreorder !== 'undefined' ? isPreorder : item.is_preorder}
|
|
43
|
+
pre_order_payment_type={typeof preOrderPaymentType !== 'undefined' ? preOrderPaymentType : item.pre_order_payment_type}
|
|
44
|
+
pre_order_deposit={typeof preOrderDeposit !== 'undefined' ? preOrderDeposit : item.pre_order_deposit}
|
|
45
|
+
// release_date may come from parent or item.product
|
|
46
|
+
release_date={typeof releaseDate !== 'undefined' ? releaseDate : (item?.product?.release_date)}
|
|
41
47
|
/>
|
|
42
48
|
));
|
|
43
49
|
|
|
@@ -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
|
};
|