storefront-layouts 1.0.15 → 1.0.16
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/dist/layouts/shared/pages/CheckoutPage.d.ts.map +1 -1
- package/dist/layouts/shared/pages/CheckoutPage.js +72 -13
- package/dist/lib/services/shipping.service.d.ts +6 -0
- package/dist/lib/services/shipping.service.d.ts.map +1 -1
- package/dist/lib/services/shipping.service.js +10 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckoutPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/shared/pages/CheckoutPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiChD,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA8LD,wBAAgB,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,iBAAiB,+
|
|
1
|
+
{"version":3,"file":"CheckoutPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/shared/pages/CheckoutPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiChD,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA8LD,wBAAgB,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,iBAAiB,+BA+rD9D"}
|
|
@@ -241,6 +241,11 @@ export function CheckoutPage({ storeConfig }) {
|
|
|
241
241
|
const [freeShippingEnabled, setFreeShippingEnabled] = useState(false);
|
|
242
242
|
const [feePreview, setFeePreview] = useState(null);
|
|
243
243
|
const [isCalculatingFees, setIsCalculatingFees] = useState(false);
|
|
244
|
+
const [storeShippingCheckout, setStoreShippingCheckout] = useState({
|
|
245
|
+
enabled: false,
|
|
246
|
+
resolved: false,
|
|
247
|
+
});
|
|
248
|
+
const lastFeePreviewKeyRef = useRef(null);
|
|
244
249
|
const [formData, setFormData] = useState({
|
|
245
250
|
email: '',
|
|
246
251
|
firstName: '',
|
|
@@ -537,6 +542,10 @@ export function CheckoutPage({ storeConfig }) {
|
|
|
537
542
|
setFreeShippingEnabled(false);
|
|
538
543
|
return;
|
|
539
544
|
}
|
|
545
|
+
if (!storeShippingCheckout.resolved || !storeShippingCheckout.enabled) {
|
|
546
|
+
setIsCalculatingShipping(false);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
540
549
|
setIsCalculatingShipping(true);
|
|
541
550
|
setShippingError(null);
|
|
542
551
|
try {
|
|
@@ -609,17 +618,51 @@ export function CheckoutPage({ storeConfig }) {
|
|
|
609
618
|
const total = feePreview?.totalPayable ?? fallbackTotal;
|
|
610
619
|
const customerFeeLines = (feePreview?.customerLines ?? []).filter((line) => line.key !== 'shipping');
|
|
611
620
|
const shippingEnabledForCheckout = storeConfig.settings?.shippingEnabled !== false;
|
|
612
|
-
const
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
621
|
+
const checkoutShippingUiActive = shippingEnabledForCheckout &&
|
|
622
|
+
storeShippingCheckout.resolved &&
|
|
623
|
+
storeShippingCheckout.enabled;
|
|
624
|
+
const feePreviewShippingCost = checkoutShippingUiActive ? safeShipping : 0;
|
|
625
|
+
useEffect(() => {
|
|
626
|
+
if (!storeConfig.id || !shippingEnabledForCheckout) {
|
|
627
|
+
setStoreShippingCheckout({ enabled: false, resolved: true });
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
let cancelled = false;
|
|
631
|
+
void shippingService.getStoreShippingStatus(storeConfig.id).then((status) => {
|
|
632
|
+
if (!cancelled) {
|
|
633
|
+
setStoreShippingCheckout({ enabled: status.enabled, resolved: true });
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
return () => {
|
|
637
|
+
cancelled = true;
|
|
638
|
+
};
|
|
639
|
+
}, [storeConfig.id, shippingEnabledForCheckout]);
|
|
640
|
+
useEffect(() => {
|
|
641
|
+
if (checkoutShippingUiActive)
|
|
642
|
+
return;
|
|
643
|
+
setIsCalculatingShipping(false);
|
|
644
|
+
setShippingMethods([]);
|
|
645
|
+
setSelectedShippingMethod(null);
|
|
646
|
+
setShippingError(null);
|
|
647
|
+
}, [checkoutShippingUiActive]);
|
|
648
|
+
const showOrderSummaryShippingLine = checkoutShippingUiActive &&
|
|
649
|
+
shouldShowOrderSummaryShippingLine({
|
|
650
|
+
shippingEnabled: true,
|
|
651
|
+
isCalculating: isCalculatingShipping,
|
|
652
|
+
selectedMethod: selectedShippingMethod,
|
|
653
|
+
});
|
|
654
|
+
const showShippingMethodSection = checkoutShippingUiActive &&
|
|
618
655
|
Boolean(formData.city && formData.country) &&
|
|
619
656
|
(isCalculatingShipping || Boolean(shippingError) || shippingMethods.length > 0);
|
|
620
657
|
useEffect(() => {
|
|
621
658
|
if (!storeConfig.id || safeSubtotal <= 0 || !currency) {
|
|
622
659
|
setFeePreview(null);
|
|
660
|
+
lastFeePreviewKeyRef.current = null;
|
|
661
|
+
setIsCalculatingFees(false);
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const requestKey = `${storeConfig.id}:${safeSubtotal.toFixed(2)}:${currency}:${feePreviewShippingCost.toFixed(2)}`;
|
|
665
|
+
if (requestKey === lastFeePreviewKeyRef.current && feePreview) {
|
|
623
666
|
return;
|
|
624
667
|
}
|
|
625
668
|
let cancelled = false;
|
|
@@ -629,18 +672,21 @@ export function CheckoutPage({ storeConfig }) {
|
|
|
629
672
|
const response = await feesService.calculateFees({
|
|
630
673
|
storeId: storeConfig.id,
|
|
631
674
|
subtotal: safeSubtotal,
|
|
632
|
-
shippingCost:
|
|
675
|
+
shippingCost: feePreviewShippingCost,
|
|
633
676
|
currency,
|
|
634
677
|
orderType: 'product',
|
|
635
678
|
});
|
|
636
|
-
if (!cancelled)
|
|
679
|
+
if (!cancelled) {
|
|
637
680
|
setFeePreview(response.feeBreakdown);
|
|
681
|
+
lastFeePreviewKeyRef.current = requestKey;
|
|
682
|
+
}
|
|
638
683
|
}
|
|
639
684
|
catch (error) {
|
|
640
|
-
// Checkout creation recalculates fees authoritatively; preserve a usable fallback preview.
|
|
641
685
|
console.warn('[Checkout] Fee preview unavailable:', error);
|
|
642
|
-
if (!cancelled)
|
|
686
|
+
if (!cancelled) {
|
|
643
687
|
setFeePreview(null);
|
|
688
|
+
lastFeePreviewKeyRef.current = null;
|
|
689
|
+
}
|
|
644
690
|
}
|
|
645
691
|
finally {
|
|
646
692
|
if (!cancelled)
|
|
@@ -651,7 +697,7 @@ export function CheckoutPage({ storeConfig }) {
|
|
|
651
697
|
cancelled = true;
|
|
652
698
|
window.clearTimeout(timer);
|
|
653
699
|
};
|
|
654
|
-
}, [currency,
|
|
700
|
+
}, [currency, feePreview, feePreviewShippingCost, safeSubtotal, storeConfig.id]);
|
|
655
701
|
// Debug logging in development
|
|
656
702
|
if (process.env.NODE_ENV === 'development' && safeSubtotal > 0 && total === 0) {
|
|
657
703
|
console.warn('[CheckoutPage] Total calculation issue detected:', {
|
|
@@ -667,7 +713,11 @@ export function CheckoutPage({ storeConfig }) {
|
|
|
667
713
|
}
|
|
668
714
|
// Debounced shipping calculation when address changes
|
|
669
715
|
useEffect(() => {
|
|
670
|
-
if (!
|
|
716
|
+
if (!storeShippingCheckout.resolved ||
|
|
717
|
+
!checkoutShippingUiActive ||
|
|
718
|
+
!formData.city ||
|
|
719
|
+
!formData.country ||
|
|
720
|
+
checkoutItems.length === 0) {
|
|
671
721
|
return;
|
|
672
722
|
}
|
|
673
723
|
const timer = setTimeout(() => {
|
|
@@ -675,7 +725,16 @@ export function CheckoutPage({ storeConfig }) {
|
|
|
675
725
|
}, 500); // Debounce 500ms
|
|
676
726
|
return () => clearTimeout(timer);
|
|
677
727
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
678
|
-
}, [
|
|
728
|
+
}, [
|
|
729
|
+
storeShippingCheckout.resolved,
|
|
730
|
+
checkoutShippingUiActive,
|
|
731
|
+
formData.city,
|
|
732
|
+
formData.country,
|
|
733
|
+
formData.postalCode,
|
|
734
|
+
checkoutItems.length,
|
|
735
|
+
subtotal,
|
|
736
|
+
currency,
|
|
737
|
+
]);
|
|
679
738
|
const validateForm = () => {
|
|
680
739
|
const newErrors = {};
|
|
681
740
|
const emailError = getCheckoutEmailValidationError(formData.email);
|
|
@@ -23,6 +23,11 @@ export interface DeliveryStatus {
|
|
|
23
23
|
enabled: boolean;
|
|
24
24
|
providers: Record<string, boolean>;
|
|
25
25
|
}
|
|
26
|
+
export interface StoreShippingCheckoutStatus {
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
automatedShipping: boolean;
|
|
29
|
+
manualZones: boolean;
|
|
30
|
+
}
|
|
26
31
|
export interface TaxCalculation {
|
|
27
32
|
tax: number;
|
|
28
33
|
taxRate: number;
|
|
@@ -52,6 +57,7 @@ export declare const shippingService: {
|
|
|
52
57
|
* Check if delivery is globally enabled and which providers are active.
|
|
53
58
|
* Returns a safe default (disabled) on error — callers should fall back gracefully.
|
|
54
59
|
*/
|
|
60
|
+
getStoreShippingStatus(storeId: string): Promise<StoreShippingCheckoutStatus>;
|
|
55
61
|
getDeliveryStatus(storeId: string): Promise<DeliveryStatus>;
|
|
56
62
|
/**
|
|
57
63
|
* Calculate tax
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shipping.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/shipping.service.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,eAAe;IAC1B;;OAEG;4BAC2B;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,GAAG,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YACb,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQhC;;;OAGG;+
|
|
1
|
+
{"version":3,"file":"shipping.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/shipping.service.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,eAAe;IAC1B;;OAEG;4BAC2B;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,GAAG,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YACb,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQhC;;;OAGG;oCACmC,MAAM,GAAG,OAAO,CAAC,2BAA2B,CAAC;+BAalD,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAYjE;;OAEG;uBACsB;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;CAOvG,CAAC"}
|
|
@@ -14,6 +14,16 @@ export const shippingService = {
|
|
|
14
14
|
* Check if delivery is globally enabled and which providers are active.
|
|
15
15
|
* Returns a safe default (disabled) on error — callers should fall back gracefully.
|
|
16
16
|
*/
|
|
17
|
+
async getStoreShippingStatus(storeId) {
|
|
18
|
+
try {
|
|
19
|
+
const response = await api.get('/shipping/status', { params: { storeId } });
|
|
20
|
+
if (response.data.status === 'success') {
|
|
21
|
+
return response.data.data;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (_) { }
|
|
25
|
+
return { enabled: false, automatedShipping: false, manualZones: false };
|
|
26
|
+
},
|
|
17
27
|
async getDeliveryStatus(storeId) {
|
|
18
28
|
try {
|
|
19
29
|
const response = await api.get('/delivery/status', {
|