storefront-layouts 1.0.13 → 1.0.15
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/editor/blocks/defaults/clothing-minimal-home.d.ts.map +1 -1
- package/dist/editor/blocks/defaults/clothing-minimal-home.js +0 -17
- package/dist/editor/payaza-form/PayazaFormEditor.d.ts.map +1 -1
- package/dist/editor/payaza-form/PayazaFormEditor.js +0 -2
- package/dist/editor/payaza-form/data-transformer.d.ts.map +1 -1
- package/dist/editor/payaza-form/data-transformer.js +1 -8
- package/dist/editor/shared/useEditorChromeMetrics.js +1 -2
- package/dist/hooks/use-pdp-variation.d.ts +1 -13
- package/dist/hooks/use-pdp-variation.d.ts.map +1 -1
- package/dist/hooks/use-product-variation-selection.d.ts +1 -13
- package/dist/hooks/use-product-variation-selection.d.ts.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/layouts/booking/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/booking/pages/ProductDetailPage.js +2 -1
- package/dist/layouts/booking-agenda/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/booking-agenda/pages/ProductDetailPage.js +2 -1
- package/dist/layouts/clothing/components/ClothingHomePage.d.ts.map +1 -1
- package/dist/layouts/clothing/components/ClothingHomePage.js +7 -11
- package/dist/layouts/clothing/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/clothing/pages/ProductDetailPage.js +1 -1
- package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.d.ts.map +1 -1
- package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.js +1 -7
- package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.d.ts +1 -1
- package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.d.ts.map +1 -1
- package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.js +5 -21
- package/dist/layouts/clothing-minimal/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/clothing-minimal/pages/ProductDetailPage.js +1 -1
- package/dist/layouts/electronics/components/ElectronicsGridProductCard.d.ts.map +1 -1
- package/dist/layouts/electronics/components/ElectronicsGridProductCard.js +2 -2
- package/dist/layouts/electronics/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/electronics/pages/ProductDetailPage.js +2 -1
- package/dist/layouts/electronics-grid/components/ElectronicsGridProductCard.d.ts.map +1 -1
- package/dist/layouts/electronics-grid/components/ElectronicsGridProductCard.js +2 -2
- package/dist/layouts/electronics-grid/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/electronics-grid/pages/ProductDetailPage.js +2 -1
- package/dist/layouts/food/pages/MenuPage.d.ts.map +1 -1
- package/dist/layouts/food/pages/MenuPage.js +1 -0
- package/dist/layouts/food/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/food/pages/ProductDetailPage.js +2 -1
- package/dist/layouts/food-modern/components/FoodHomePageModern.js +1 -1
- package/dist/layouts/food-modern/pages/MenuPage.d.ts.map +1 -1
- package/dist/layouts/food-modern/pages/MenuPage.js +1 -0
- package/dist/layouts/food-modern/pages/ProductDetailPage.d.ts.map +1 -1
- package/dist/layouts/food-modern/pages/ProductDetailPage.js +2 -1
- package/dist/layouts/shared/components/PromoBanner.d.ts +4 -1
- package/dist/layouts/shared/components/PromoBanner.d.ts.map +1 -1
- package/dist/layouts/shared/components/PromoBanner.js +2 -2
- package/dist/layouts/shared/components/StoreCartSheet.d.ts.map +1 -1
- package/dist/layouts/shared/components/StoreCartSheet.js +4 -2
- package/dist/layouts/shared/components/StoreFooter.js +2 -2
- package/dist/layouts/shared/components/StoreHeader.js +4 -4
- package/dist/layouts/shared/pages/CartPage.d.ts.map +1 -1
- package/dist/layouts/shared/pages/CartPage.js +4 -28
- package/dist/layouts/shared/pages/CheckoutPage.d.ts.map +1 -1
- package/dist/layouts/shared/pages/CheckoutPage.js +203 -81
- package/dist/layouts/shared/pages/MaintenancePage.js +1 -1
- package/dist/layouts/shared/wrappers/ClothingLayout.js +5 -5
- package/dist/layouts/shared/wrappers/ClothingMinimalLayout.js +4 -4
- package/dist/layouts/shared/wrappers/ElectronicsLayout.js +4 -4
- package/dist/layouts/shared/wrappers/FoodModernLayout.js +4 -4
- package/dist/layouts/shared/wrappers/MotivationalLayout.js +4 -4
- package/dist/layouts/shared/wrappers/StandardLayout.js +4 -4
- package/dist/lib/cart-charge-currency.d.ts +16 -0
- package/dist/lib/cart-charge-currency.d.ts.map +1 -0
- package/dist/lib/cart-charge-currency.js +38 -0
- package/dist/lib/checkout-phone-validation.d.ts +3 -0
- package/dist/lib/checkout-phone-validation.d.ts.map +1 -0
- package/dist/lib/checkout-phone-validation.js +41 -0
- package/dist/lib/preview-data.d.ts.map +1 -1
- package/dist/lib/preview-data.js +2 -0
- package/dist/lib/rich-html.d.ts +1 -2
- package/dist/lib/rich-html.d.ts.map +1 -1
- package/dist/lib/services/fees.service.d.ts +40 -57
- package/dist/lib/services/fees.service.d.ts.map +1 -1
- package/dist/lib/services/fees.service.js +24 -120
- package/dist/lib/store-types.d.ts +27 -34
- package/dist/lib/store-types.d.ts.map +1 -1
- package/dist/lib/utils/fee-calculations.d.ts.map +1 -1
- package/dist/lib/utils/fee-calculations.js +23 -11
- package/dist/preview/LayoutPreview.d.ts.map +1 -1
- package/dist/preview/LayoutPreview.js +5 -22
- package/dist/styles/index.css +36 -0
- package/dist/utils/price-display.d.ts +3 -0
- package/dist/utils/price-display.d.ts.map +1 -0
- package/dist/utils/price-display.js +8 -0
- package/package.json +2 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type CartChargeCurrencyLine = {
|
|
2
|
+
currency?: string;
|
|
3
|
+
product?: {
|
|
4
|
+
currency?: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
export type CartChargeCurrencyResult = {
|
|
8
|
+
currency: string;
|
|
9
|
+
mixed: boolean;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Charge currency for cart / checkout totals. Uses line-item currencies first;
|
|
13
|
+
* store default and buyer cookie apply only when the cart has no priced currency.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveCartChargeCurrency(items: CartChargeCurrencyLine[], storeDefault?: string): CartChargeCurrencyResult;
|
|
16
|
+
//# sourceMappingURL=cart-charge-currency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart-charge-currency.d.ts","sourceRoot":"","sources":["../../src/lib/cart-charge-currency.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAgBF;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,sBAAsB,EAAE,EAC/B,YAAY,CAAC,EAAE,MAAM,GACpB,wBAAwB,CA6B1B"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const CURRENCY_CODE = /^[A-Z]{3}$/;
|
|
2
|
+
function normalizeCurrencyCode(value) {
|
|
3
|
+
const normalized = String(value ?? '').trim().toUpperCase();
|
|
4
|
+
return CURRENCY_CODE.test(normalized) ? normalized : undefined;
|
|
5
|
+
}
|
|
6
|
+
function readFxBuyerCurrencyCookie() {
|
|
7
|
+
if (process.env.NEXT_PUBLIC_FX_CONVERSION_ENABLED !== 'true') {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
if (typeof document === 'undefined')
|
|
11
|
+
return undefined;
|
|
12
|
+
const match = document.cookie.match(/(?:^|; )shopaza_currency=([^;]+)/);
|
|
13
|
+
return normalizeCurrencyCode(match?.[1]);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Charge currency for cart / checkout totals. Uses line-item currencies first;
|
|
17
|
+
* store default and buyer cookie apply only when the cart has no priced currency.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveCartChargeCurrency(items, storeDefault) {
|
|
20
|
+
const fallback = normalizeCurrencyCode(storeDefault) || 'USD';
|
|
21
|
+
const lineCurrencies = items
|
|
22
|
+
.map((item) => normalizeCurrencyCode(item.currency) ?? normalizeCurrencyCode(item.product?.currency))
|
|
23
|
+
.filter((code) => Boolean(code));
|
|
24
|
+
if (lineCurrencies.length === 0) {
|
|
25
|
+
const cookie = readFxBuyerCurrencyCookie();
|
|
26
|
+
return { currency: cookie ?? fallback, mixed: false };
|
|
27
|
+
}
|
|
28
|
+
const unique = [...new Set(lineCurrencies)];
|
|
29
|
+
if (unique.length === 1) {
|
|
30
|
+
return { currency: unique[0], mixed: false };
|
|
31
|
+
}
|
|
32
|
+
const counts = {};
|
|
33
|
+
for (const code of lineCurrencies) {
|
|
34
|
+
counts[code] = (counts[code] || 0) + 1;
|
|
35
|
+
}
|
|
36
|
+
const mostCommon = Object.entries(counts).reduce((best, entry) => entry[1] > best[1] ? entry : best)[0];
|
|
37
|
+
return { currency: mostCommon, mixed: true };
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout-phone-validation.d.ts","sourceRoot":"","sources":["../../src/lib/checkout-phone-validation.ts"],"names":[],"mappings":"AAWA,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,GAAG,SAAS,CA4BpB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PhoneNumberUtil } from 'google-libphonenumber';
|
|
2
|
+
let phoneUtil = null;
|
|
3
|
+
function getPhoneUtil() {
|
|
4
|
+
if (!phoneUtil) {
|
|
5
|
+
phoneUtil = PhoneNumberUtil.getInstance();
|
|
6
|
+
}
|
|
7
|
+
return phoneUtil;
|
|
8
|
+
}
|
|
9
|
+
export function sanitizeCheckoutPhoneInput(value) {
|
|
10
|
+
return value.replace(/[a-zA-Z]/g, '');
|
|
11
|
+
}
|
|
12
|
+
export function getCheckoutPhoneValidationError(phone, regionCode) {
|
|
13
|
+
const trimmed = phone.trim();
|
|
14
|
+
if (!trimmed)
|
|
15
|
+
return 'Phone is required';
|
|
16
|
+
if (/[a-zA-Z]/.test(trimmed))
|
|
17
|
+
return 'Phone number cannot contain letters';
|
|
18
|
+
if (!regionCode) {
|
|
19
|
+
return 'Select a country before entering your phone number';
|
|
20
|
+
}
|
|
21
|
+
if (regionCode === 'NG' && !trimmed.startsWith('+')) {
|
|
22
|
+
const digits = trimmed.replace(/\D/g, '');
|
|
23
|
+
if (digits.length === 11 && !digits.startsWith('0')) {
|
|
24
|
+
return 'Use 11 digits starting with 0 (e.g. 08001234567) or include +234';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const util = getPhoneUtil();
|
|
28
|
+
try {
|
|
29
|
+
const parsed = util.parse(trimmed, regionCode);
|
|
30
|
+
if (!util.isValidNumber(parsed)) {
|
|
31
|
+
if (!util.isPossibleNumber(parsed)) {
|
|
32
|
+
return 'Phone number length is not valid for the selected country';
|
|
33
|
+
}
|
|
34
|
+
return 'Enter a valid phone number for the selected country';
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return 'Enter a valid phone number for the selected country';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview-data.d.ts","sourceRoot":"","sources":["../../src/lib/preview-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;GASG;AAEH;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,CAgShD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,CA2XpD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,
|
|
1
|
+
{"version":3,"file":"preview-data.d.ts","sourceRoot":"","sources":["../../src/lib/preview-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;GASG;AAEH;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,CAgShD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,WAAW,CA2XpD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,CAmPnD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,WAAW,CA+JtD;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,WAAW,CA4O3D;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,WAAW,CA2JzD;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,WAAW,CAme3D;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,WAAW,CAiSvD;AAED;;GAEG;AACH,wBAAgB,iCAAiC,IAAI,WAAW,CAiP/D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAiCzE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqBvE"}
|
package/dist/lib/preview-data.js
CHANGED
package/dist/lib/rich-html.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
export declare const PAYAZA_RICH_HTML_POLICY_VERSION = "1";
|
|
2
|
-
/** Normalized shape persisted/passed for a Payaza rich-text field. */
|
|
3
2
|
export interface PayazaRichTextStored {
|
|
4
3
|
sanitizedHtml: string;
|
|
5
4
|
policyVersion: string;
|
|
6
|
-
plainText
|
|
5
|
+
plainText?: string;
|
|
7
6
|
rawHtml?: string;
|
|
8
7
|
updatedAt?: string;
|
|
9
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-html.d.ts","sourceRoot":"","sources":["../../src/lib/rich-html.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,+BAA+B,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"rich-html.d.ts","sourceRoot":"","sources":["../../src/lib/rich-html.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,+BAA+B,MAAM,CAAC;AACnD,MAAM,WAAW,oBAAoB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,8DAA8D;AAC9D,wBAAgB,wBAAwB,CAAC,GAAG,KAAA,OAsB3C;AA6BD,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,MAAM,KAAA,UAkC5C;AACD,qEAAqE;AACrE,wBAAgB,0BAA0B,CAAC,IAAI,KAAA,UAe9C;AACD,wBAAgB,wBAAwB,CAAC,KAAK,KAAA,OAO7C;AACD,+DAA+D;AAC/D,wBAAgB,4BAA4B,CAAC,GAAG,KAAA;;;;EAgB/C;AACD,wBAAgB,wBAAwB,CAAC,GAAG,KAAA,OAkB3C;AACD,+DAA+D;AAC/D,wBAAgB,sBAAsB,CAAC,GAAG,KAAA,EAAE,aAAa,KAAA,OAKxD;AACD,yEAAyE;AACzE,wBAAgB,mCAAmC,CAAC,SAAS,KAAA,EAAE,OAAO,KAAA;;;;;;EAUrE;AACD,8DAA8D;AAC9D,wBAAgB,qCAAqC,CAAC,KAAK,KAAA,EAAE,OAAO,KAAA;;;;;;EAEnE;AACD,uEAAuE;AACvE,wBAAgB,6BAA6B,CAAC,GAAG,KAAA,OAOhD;AACD,wBAAgB,uBAAuB,CAAC,CAAC,KAAA,WAKxC;AAmDD,wBAAgB,mBAAmB,CAAC,GAAG,KAAA,WAGtC;AACD,wBAAgB,4BAA4B,CAAC,GAAG,KAAA,EAAE,aAAa,SAAK,OAMnE;AACD,uEAAuE;AACvE,wBAAgB,4BAA4B,CAAC,GAAG,KAAA,OAO/C;AACD,yEAAyE;AACzE,wBAAgB,yBAAyB,CAAC,CAAC,KAAA,OAG1C"}
|
|
@@ -1,85 +1,68 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface FeeCalculationRequest {
|
|
2
|
+
storeId: string;
|
|
3
|
+
subtotal: number;
|
|
4
|
+
currency: string;
|
|
5
|
+
orderType?: 'product' | 'service' | 'mixed';
|
|
6
|
+
shippingCost?: number;
|
|
7
|
+
}
|
|
2
8
|
export interface CheckoutFeeLine {
|
|
3
9
|
key: string;
|
|
4
10
|
label: string;
|
|
5
11
|
amount: number;
|
|
6
|
-
source
|
|
12
|
+
source: 'merchant' | 'platform';
|
|
7
13
|
type?: string;
|
|
8
14
|
chargeId?: string;
|
|
9
15
|
}
|
|
10
16
|
export interface PlatformCharge {
|
|
11
|
-
chargeId: string;
|
|
12
17
|
label: string;
|
|
13
18
|
type: string;
|
|
14
19
|
amount: number;
|
|
15
20
|
rate?: number;
|
|
16
|
-
|
|
17
|
-
export interface MerchantFeesSection {
|
|
18
|
-
configuredBy: 'store_fee_settings';
|
|
19
|
-
tax: number;
|
|
20
|
-
serviceCharge: number;
|
|
21
|
-
total: number;
|
|
22
|
-
lines: CheckoutFeeLine[];
|
|
23
|
-
}
|
|
24
|
-
export interface PlatformFeesSection {
|
|
25
|
-
configuredBy: 'backoffice';
|
|
26
|
-
collectionFeePayer: 'customer' | 'merchant';
|
|
27
|
-
charges: PlatformCharge[];
|
|
28
|
-
total: number;
|
|
29
|
-
customerTotal: number;
|
|
30
|
-
lines: CheckoutFeeLine[];
|
|
21
|
+
chargeId: string;
|
|
31
22
|
}
|
|
32
23
|
export interface CheckoutFeeBreakdown {
|
|
33
24
|
subtotal: number;
|
|
34
25
|
shipping: number;
|
|
35
|
-
merchant:
|
|
36
|
-
|
|
26
|
+
merchant: {
|
|
27
|
+
configuredBy?: string;
|
|
28
|
+
tax: number;
|
|
29
|
+
serviceCharge: number;
|
|
30
|
+
total: number;
|
|
31
|
+
lines?: CheckoutFeeLine[];
|
|
32
|
+
};
|
|
33
|
+
platform: {
|
|
34
|
+
configuredBy?: string;
|
|
35
|
+
collectionFeePayer: 'customer' | 'merchant';
|
|
36
|
+
charges: PlatformCharge[];
|
|
37
|
+
total: number;
|
|
38
|
+
customerTotal: number;
|
|
39
|
+
lines?: CheckoutFeeLine[];
|
|
40
|
+
};
|
|
37
41
|
customerLines: CheckoutFeeLine[];
|
|
38
42
|
totalPayable: number;
|
|
39
43
|
}
|
|
40
|
-
export interface FeeCalculationRequest {
|
|
41
|
-
storeId: string;
|
|
42
|
-
subtotal: number;
|
|
43
|
-
currency: string;
|
|
44
|
-
orderType?: 'product' | 'service' | 'mixed';
|
|
45
|
-
shippingCost?: number;
|
|
46
|
-
}
|
|
47
44
|
export interface FeeCalculationResponse {
|
|
48
|
-
feeBreakdown
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
type: string;
|
|
52
|
-
amount: number;
|
|
53
|
-
rate?: number;
|
|
54
|
-
chargeId: string;
|
|
55
|
-
}>;
|
|
45
|
+
feeBreakdown: CheckoutFeeBreakdown;
|
|
46
|
+
/** Legacy response fields retained for callers that still use them. */
|
|
47
|
+
charges?: PlatformCharge[];
|
|
56
48
|
totalCharges?: number;
|
|
57
|
-
actualPlatformFee?: number;
|
|
58
|
-
collectionFeePayer?: 'customer' | 'merchant';
|
|
59
|
-
shopazaCharges?: FeeCalculationResponse['charges'];
|
|
60
|
-
merchantServiceCharge?: number;
|
|
61
|
-
tax?: number;
|
|
62
|
-
totalCollectibleFees?: number;
|
|
63
49
|
}
|
|
64
50
|
export declare const EMPTY_CHECKOUT_FEE_BREAKDOWN: CheckoutFeeBreakdown;
|
|
65
|
-
export declare function normalizeCheckoutFeeBreakdown(
|
|
66
|
-
export interface BatchFeeCalculationStoreRequest {
|
|
67
|
-
storeId: string;
|
|
68
|
-
subtotal: number;
|
|
69
|
-
orderType?: 'product' | 'service' | 'mixed';
|
|
70
|
-
shippingCost?: number;
|
|
71
|
-
}
|
|
72
|
-
export interface BatchFeeCalculationResult {
|
|
73
|
-
storeId: string;
|
|
74
|
-
feeBreakdown?: CheckoutFeeBreakdown;
|
|
75
|
-
error?: string;
|
|
76
|
-
}
|
|
51
|
+
export declare function normalizeCheckoutFeeBreakdown(response: FeeCalculationResponse | Partial<FeeCalculationResponse>, subtotal: number, shipping: number): CheckoutFeeBreakdown;
|
|
77
52
|
export declare const feesService: {
|
|
78
|
-
calculateFees(data: FeeCalculationRequest): Promise<FeeCalculationResponse>;
|
|
79
53
|
/**
|
|
80
|
-
*
|
|
81
|
-
* breakdown per store, instead of firing one /calculate call per store from the client.
|
|
54
|
+
* Calculate fees for an order
|
|
82
55
|
*/
|
|
83
|
-
|
|
56
|
+
calculateFees(data: FeeCalculationRequest): Promise<FeeCalculationResponse>;
|
|
57
|
+
calculateFeesBatch(stores: Array<{
|
|
58
|
+
storeId: string;
|
|
59
|
+
subtotal: number;
|
|
60
|
+
orderType?: FeeCalculationRequest["orderType"];
|
|
61
|
+
shippingCost?: number;
|
|
62
|
+
}>, currency: string): Promise<Array<{
|
|
63
|
+
storeId: string;
|
|
64
|
+
feeBreakdown?: CheckoutFeeBreakdown;
|
|
65
|
+
error?: string;
|
|
66
|
+
}>>;
|
|
84
67
|
};
|
|
85
68
|
//# sourceMappingURL=fees.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fees.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/fees.service.ts"],"names":[],"mappings":"AAEA,MAAM,
|
|
1
|
+
{"version":3,"file":"fees.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/fees.service.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE;QACR,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,GAAG,EAAE,MAAM,CAAC;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE;QACR,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,kBAAkB,EAAE,UAAU,GAAG,UAAU,CAAC;QAC5C,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;KAC3B,CAAC;IACF,aAAa,EAAE,eAAe,EAAE,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,oBAAoB,CAAC;IACnC,uEAAuE;IACvE,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,4BAA4B,EAAE,oBAO1C,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,EAClE,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,oBAAoB,CAwBtB;AAED,eAAO,MAAM,WAAW;IACtB;;OAEG;wBACuB,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;+BAYvE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,YACjH,MAAM,GACf,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,oBAAoB,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAS5F,CAAC"}
|
|
@@ -1,131 +1,40 @@
|
|
|
1
1
|
import { api } from '../api';
|
|
2
|
-
const emptyMerchantSection = () => ({
|
|
3
|
-
configuredBy: 'store_fee_settings',
|
|
4
|
-
tax: 0,
|
|
5
|
-
serviceCharge: 0,
|
|
6
|
-
total: 0,
|
|
7
|
-
lines: [],
|
|
8
|
-
});
|
|
9
|
-
const emptyPlatformSection = () => ({
|
|
10
|
-
configuredBy: 'backoffice',
|
|
11
|
-
collectionFeePayer: 'customer',
|
|
12
|
-
charges: [],
|
|
13
|
-
total: 0,
|
|
14
|
-
customerTotal: 0,
|
|
15
|
-
lines: [],
|
|
16
|
-
});
|
|
17
2
|
export const EMPTY_CHECKOUT_FEE_BREAKDOWN = {
|
|
18
3
|
subtotal: 0,
|
|
19
4
|
shipping: 0,
|
|
20
|
-
merchant:
|
|
21
|
-
platform:
|
|
5
|
+
merchant: { configuredBy: 'store_fee_settings', tax: 0, serviceCharge: 0, total: 0, lines: [] },
|
|
6
|
+
platform: { configuredBy: 'backoffice', collectionFeePayer: 'merchant', charges: [], total: 0, customerTotal: 0, lines: [] },
|
|
22
7
|
customerLines: [],
|
|
23
8
|
totalPayable: 0,
|
|
24
9
|
};
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const tax = Number(legacy.tax) || 0;
|
|
38
|
-
const serviceCharge = Number(legacy.merchantServiceCharge) || 0;
|
|
39
|
-
const collectionFeePayer = legacy.collectionFeePayer === 'merchant' ? 'merchant' : 'customer';
|
|
40
|
-
const shopazaCharges = (legacy.shopazaCharges ??
|
|
41
|
-
legacy.charges ??
|
|
42
|
-
[])
|
|
43
|
-
.map((charge) => ({
|
|
44
|
-
chargeId: charge.chargeId || charge.label,
|
|
45
|
-
label: charge.label,
|
|
46
|
-
type: charge.type || 'FIXED',
|
|
47
|
-
amount: Number(charge.amount) || 0,
|
|
48
|
-
rate: charge.rate,
|
|
49
|
-
}))
|
|
50
|
-
.filter((charge) => charge.amount > 0);
|
|
51
|
-
const platformTotal = Number(legacy.actualPlatformFee) ||
|
|
52
|
-
shopazaCharges.reduce((sum, charge) => sum + charge.amount, 0);
|
|
53
|
-
const customerTotal = Number(legacy.customerPlatformFee) ||
|
|
54
|
-
Number(legacy.totalCharges) ||
|
|
55
|
-
(collectionFeePayer === 'customer' ? platformTotal : 0);
|
|
56
|
-
const merchantLines = [];
|
|
57
|
-
if (tax > 0)
|
|
58
|
-
merchantLines.push({ key: 'vat', label: 'VAT', amount: tax, source: 'merchant' });
|
|
59
|
-
if (serviceCharge > 0) {
|
|
60
|
-
merchantLines.push({
|
|
61
|
-
key: 'service_charge',
|
|
62
|
-
label: 'Service charge',
|
|
63
|
-
amount: serviceCharge,
|
|
64
|
-
source: 'merchant',
|
|
65
|
-
});
|
|
10
|
+
export function normalizeCheckoutFeeBreakdown(response, subtotal, shipping) {
|
|
11
|
+
const value = response?.feeBreakdown;
|
|
12
|
+
if (value?.merchant && value.platform) {
|
|
13
|
+
return {
|
|
14
|
+
...EMPTY_CHECKOUT_FEE_BREAKDOWN,
|
|
15
|
+
...value,
|
|
16
|
+
subtotal: Number(value.subtotal) || subtotal,
|
|
17
|
+
shipping: Number(value.shipping) || shipping,
|
|
18
|
+
customerLines: value.customerLines || [],
|
|
19
|
+
merchant: { ...EMPTY_CHECKOUT_FEE_BREAKDOWN.merchant, ...value.merchant },
|
|
20
|
+
platform: { ...EMPTY_CHECKOUT_FEE_BREAKDOWN.platform, ...value.platform },
|
|
21
|
+
};
|
|
66
22
|
}
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
tax,
|
|
70
|
-
serviceCharge,
|
|
71
|
-
total: tax + serviceCharge,
|
|
72
|
-
lines: merchantLines,
|
|
73
|
-
};
|
|
74
|
-
const platform = {
|
|
75
|
-
configuredBy: 'backoffice',
|
|
76
|
-
collectionFeePayer,
|
|
77
|
-
charges: shopazaCharges,
|
|
78
|
-
total: platformTotal,
|
|
79
|
-
customerTotal,
|
|
80
|
-
lines: collectionFeePayer === 'customer'
|
|
81
|
-
? shopazaCharges.map((charge) => ({
|
|
82
|
-
key: `platform:${charge.chargeId}`,
|
|
83
|
-
label: charge.label || 'Collection fee',
|
|
84
|
-
amount: charge.amount,
|
|
85
|
-
source: 'platform',
|
|
86
|
-
type: charge.type,
|
|
87
|
-
chargeId: charge.chargeId,
|
|
88
|
-
}))
|
|
89
|
-
: [],
|
|
90
|
-
};
|
|
91
|
-
const customerLines = legacy.customerLines ??
|
|
92
|
-
legacy.lines ??
|
|
93
|
-
[
|
|
94
|
-
...merchant.lines,
|
|
95
|
-
...(shipping > 0
|
|
96
|
-
? [{ key: 'shipping', label: 'Shipping', amount: shipping, source: 'merchant' }]
|
|
97
|
-
: []),
|
|
98
|
-
...platform.lines,
|
|
99
|
-
];
|
|
23
|
+
const charges = response?.charges || [];
|
|
24
|
+
const totalCharges = Number(response?.totalCharges) || charges.reduce((sum, charge) => sum + (Number(charge.amount) || 0), 0);
|
|
100
25
|
return {
|
|
26
|
+
...EMPTY_CHECKOUT_FEE_BREAKDOWN,
|
|
101
27
|
subtotal,
|
|
102
28
|
shipping,
|
|
103
|
-
|
|
104
|
-
platform,
|
|
105
|
-
|
|
106
|
-
totalPayable: Number(legacy.totalPayable) ||
|
|
107
|
-
subtotal + merchant.total + shipping + platform.customerTotal,
|
|
29
|
+
platform: { ...EMPTY_CHECKOUT_FEE_BREAKDOWN.platform, charges, total: totalCharges, customerTotal: totalCharges },
|
|
30
|
+
customerLines: charges.map((charge) => ({ key: charge.chargeId, label: charge.label, amount: charge.amount, source: 'platform', type: charge.type, chargeId: charge.chargeId })),
|
|
31
|
+
totalPayable: subtotal + shipping + totalCharges,
|
|
108
32
|
};
|
|
109
33
|
}
|
|
110
|
-
export function normalizeCheckoutFeeBreakdown(result, fallbackSubtotal = 0, fallbackShipping = 0) {
|
|
111
|
-
if (result.feeBreakdown) {
|
|
112
|
-
if (isConsolidatedBreakdown(result.feeBreakdown)) {
|
|
113
|
-
return result.feeBreakdown;
|
|
114
|
-
}
|
|
115
|
-
return normalizeLegacyBreakdown(result.feeBreakdown, fallbackSubtotal, fallbackShipping);
|
|
116
|
-
}
|
|
117
|
-
return normalizeLegacyBreakdown({
|
|
118
|
-
subtotal: fallbackSubtotal,
|
|
119
|
-
shipping: fallbackShipping,
|
|
120
|
-
tax: result.tax,
|
|
121
|
-
merchantServiceCharge: result.merchantServiceCharge,
|
|
122
|
-
collectionFeePayer: result.collectionFeePayer,
|
|
123
|
-
shopazaCharges: result.charges ?? result.shopazaCharges,
|
|
124
|
-
customerPlatformFee: result.totalCharges,
|
|
125
|
-
actualPlatformFee: result.actualPlatformFee,
|
|
126
|
-
}, fallbackSubtotal, fallbackShipping);
|
|
127
|
-
}
|
|
128
34
|
export const feesService = {
|
|
35
|
+
/**
|
|
36
|
+
* Calculate fees for an order
|
|
37
|
+
*/
|
|
129
38
|
async calculateFees(data) {
|
|
130
39
|
const response = await api.post('/fees/calculate', data);
|
|
131
40
|
if (response.data.status === 'success') {
|
|
@@ -133,15 +42,10 @@ export const feesService = {
|
|
|
133
42
|
}
|
|
134
43
|
throw new Error(response.data.message || 'Failed to calculate fees');
|
|
135
44
|
},
|
|
136
|
-
/**
|
|
137
|
-
* Fee preview for a cart spanning multiple stores — one HTTP round trip that returns a
|
|
138
|
-
* breakdown per store, instead of firing one /calculate call per store from the client.
|
|
139
|
-
*/
|
|
140
45
|
async calculateFeesBatch(stores, currency) {
|
|
141
46
|
const response = await api.post('/fees/calculate-batch', { stores, currency });
|
|
142
|
-
if (response.data.status === 'success')
|
|
47
|
+
if (response.data.status === 'success')
|
|
143
48
|
return response.data.data.results;
|
|
144
|
-
}
|
|
145
49
|
throw new Error(response.data.message || 'Failed to calculate fees');
|
|
146
50
|
},
|
|
147
51
|
};
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
export type StoreLayoutType = 'food' | 'food-modern' | 'clothing' | 'clothing-minimal' | 'booking' | 'booking-agenda' | 'electronics' | 'electronics-grid' | 'motivational-speaker';
|
|
2
|
+
export interface StoreProductVariant {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
value: string;
|
|
6
|
+
price?: number;
|
|
7
|
+
compareAtPrice?: number;
|
|
8
|
+
sku?: string;
|
|
9
|
+
isActive?: boolean;
|
|
10
|
+
attributes?: Record<string, string>;
|
|
11
|
+
stock?: number;
|
|
12
|
+
availableStock?: number;
|
|
13
|
+
inStock?: boolean;
|
|
14
|
+
images?: string[] | string;
|
|
15
|
+
}
|
|
2
16
|
export interface StoreBranding {
|
|
3
17
|
primaryColor: string;
|
|
4
18
|
secondaryColor?: string;
|
|
@@ -72,32 +86,20 @@ export interface StoreProduct {
|
|
|
72
86
|
category?: string;
|
|
73
87
|
brand?: string;
|
|
74
88
|
inStock: boolean;
|
|
75
|
-
sku?: string;
|
|
76
|
-
currency?: string;
|
|
77
89
|
trackInventory?: boolean;
|
|
78
90
|
availableStock?: number;
|
|
79
91
|
lowStockThreshold?: number;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
variants?:
|
|
83
|
-
id: string;
|
|
84
|
-
name: string;
|
|
85
|
-
value: string;
|
|
86
|
-
price?: number;
|
|
87
|
-
sku?: string;
|
|
88
|
-
isActive?: boolean;
|
|
89
|
-
attributes?: Record<string, string>;
|
|
90
|
-
stock?: number;
|
|
91
|
-
inStock?: boolean;
|
|
92
|
-
images?: string[] | string;
|
|
93
|
-
compareAtPrice?: number;
|
|
94
|
-
}>;
|
|
92
|
+
sku?: string;
|
|
93
|
+
currency?: string;
|
|
94
|
+
variants?: StoreProductVariant[];
|
|
95
95
|
specifications?: Record<string, string>;
|
|
96
96
|
rating?: number;
|
|
97
97
|
reviewCount?: number;
|
|
98
98
|
reviews?: ProductReview[];
|
|
99
99
|
isActive?: boolean;
|
|
100
100
|
status?: 'active' | 'inactive' | 'draft';
|
|
101
|
+
isLimitedTimeOffer?: boolean;
|
|
102
|
+
limitedTimeOfferEndsAt?: string | Date | null;
|
|
101
103
|
}
|
|
102
104
|
export interface StoreService {
|
|
103
105
|
id: string;
|
|
@@ -209,6 +211,7 @@ export interface TestimonialsSection {
|
|
|
209
211
|
}
|
|
210
212
|
export interface StoreConfig {
|
|
211
213
|
id: string;
|
|
214
|
+
storeId?: string;
|
|
212
215
|
slug: string;
|
|
213
216
|
name: string;
|
|
214
217
|
description: string;
|
|
@@ -326,7 +329,6 @@ export interface BenefitItem {
|
|
|
326
329
|
}
|
|
327
330
|
export interface StoreLayoutConfig {
|
|
328
331
|
isPreview?: boolean;
|
|
329
|
-
/** Payaza editor inline style overrides, keyed by `${pageId}::${sectionKey}`. */
|
|
330
332
|
payazaSectionStyles?: Record<string, Record<string, string>>;
|
|
331
333
|
hero?: {
|
|
332
334
|
show: boolean;
|
|
@@ -467,6 +469,8 @@ export interface StoreLayoutConfig {
|
|
|
467
469
|
title?: string;
|
|
468
470
|
subtitle?: string;
|
|
469
471
|
items?: TestimonialItem[];
|
|
472
|
+
limit?: number;
|
|
473
|
+
showRatings?: boolean;
|
|
470
474
|
quote?: string;
|
|
471
475
|
author?: string;
|
|
472
476
|
role?: string;
|
|
@@ -561,7 +565,9 @@ export interface StoreLayoutConfig {
|
|
|
561
565
|
};
|
|
562
566
|
};
|
|
563
567
|
pages?: {
|
|
568
|
+
[key: string]: any;
|
|
564
569
|
about?: {
|
|
570
|
+
[key: string]: any;
|
|
565
571
|
title?: string;
|
|
566
572
|
heroImage?: string;
|
|
567
573
|
content?: string;
|
|
@@ -579,9 +585,6 @@ export interface StoreLayoutConfig {
|
|
|
579
585
|
aboutContent?: any;
|
|
580
586
|
statsSection?: any;
|
|
581
587
|
contactSection?: any;
|
|
582
|
-
aboutHero?: any;
|
|
583
|
-
ourStory?: any;
|
|
584
|
-
contactInfoSection?: any;
|
|
585
588
|
};
|
|
586
589
|
team?: {
|
|
587
590
|
title?: string;
|
|
@@ -610,18 +613,9 @@ export interface StoreLayoutConfig {
|
|
|
610
613
|
}>;
|
|
611
614
|
};
|
|
612
615
|
services?: {
|
|
616
|
+
[key: string]: any;
|
|
613
617
|
title?: string;
|
|
614
618
|
description?: string;
|
|
615
|
-
hero?: any;
|
|
616
|
-
servicesHeader?: any;
|
|
617
|
-
servicesGrid?: any;
|
|
618
|
-
};
|
|
619
|
-
book?: {
|
|
620
|
-
bookingHeader?: any;
|
|
621
|
-
bookingForm?: any;
|
|
622
|
-
};
|
|
623
|
-
serviceDetail?: {
|
|
624
|
-
serviceDetail?: any;
|
|
625
619
|
};
|
|
626
620
|
faq?: {
|
|
627
621
|
title?: string;
|
|
@@ -635,10 +629,9 @@ export interface StoreLayoutConfig {
|
|
|
635
629
|
productsGrid?: any;
|
|
636
630
|
};
|
|
637
631
|
categories?: {
|
|
632
|
+
[key: string]: any;
|
|
638
633
|
categoriesHeader?: any;
|
|
639
634
|
categoryGrid?: any;
|
|
640
|
-
/** Legacy alias some persisted configs use in place of categoryGrid. */
|
|
641
|
-
categoriesGrid?: any;
|
|
642
635
|
};
|
|
643
636
|
categoryDetail?: {
|
|
644
637
|
categoryDetail?: any;
|
|
@@ -657,6 +650,7 @@ export interface StoreLayoutConfig {
|
|
|
657
650
|
showRelatedProducts?: boolean;
|
|
658
651
|
};
|
|
659
652
|
contact?: {
|
|
653
|
+
[key: string]: any;
|
|
660
654
|
contact?: any;
|
|
661
655
|
contactHeader?: any;
|
|
662
656
|
contactForm?: any;
|
|
@@ -667,7 +661,6 @@ export interface StoreLayoutConfig {
|
|
|
667
661
|
subtitle?: string;
|
|
668
662
|
infoTitle?: string;
|
|
669
663
|
infoDescription?: string;
|
|
670
|
-
reservationForm?: any;
|
|
671
664
|
};
|
|
672
665
|
menu?: {
|
|
673
666
|
menuHeader?: any;
|