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.
Files changed (88) hide show
  1. package/dist/editor/blocks/defaults/clothing-minimal-home.d.ts.map +1 -1
  2. package/dist/editor/blocks/defaults/clothing-minimal-home.js +0 -17
  3. package/dist/editor/payaza-form/PayazaFormEditor.d.ts.map +1 -1
  4. package/dist/editor/payaza-form/PayazaFormEditor.js +0 -2
  5. package/dist/editor/payaza-form/data-transformer.d.ts.map +1 -1
  6. package/dist/editor/payaza-form/data-transformer.js +1 -8
  7. package/dist/editor/shared/useEditorChromeMetrics.js +1 -2
  8. package/dist/hooks/use-pdp-variation.d.ts +1 -13
  9. package/dist/hooks/use-pdp-variation.d.ts.map +1 -1
  10. package/dist/hooks/use-product-variation-selection.d.ts +1 -13
  11. package/dist/hooks/use-product-variation-selection.d.ts.map +1 -1
  12. package/dist/index.d.ts +8 -4
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +7 -4
  15. package/dist/layouts/booking/pages/ProductDetailPage.d.ts.map +1 -1
  16. package/dist/layouts/booking/pages/ProductDetailPage.js +2 -1
  17. package/dist/layouts/booking-agenda/pages/ProductDetailPage.d.ts.map +1 -1
  18. package/dist/layouts/booking-agenda/pages/ProductDetailPage.js +2 -1
  19. package/dist/layouts/clothing/components/ClothingHomePage.d.ts.map +1 -1
  20. package/dist/layouts/clothing/components/ClothingHomePage.js +7 -11
  21. package/dist/layouts/clothing/pages/ProductDetailPage.d.ts.map +1 -1
  22. package/dist/layouts/clothing/pages/ProductDetailPage.js +1 -1
  23. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.d.ts.map +1 -1
  24. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.js +1 -7
  25. package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.d.ts +1 -1
  26. package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.d.ts.map +1 -1
  27. package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.js +5 -21
  28. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.d.ts.map +1 -1
  29. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.js +1 -1
  30. package/dist/layouts/electronics/components/ElectronicsGridProductCard.d.ts.map +1 -1
  31. package/dist/layouts/electronics/components/ElectronicsGridProductCard.js +2 -2
  32. package/dist/layouts/electronics/pages/ProductDetailPage.d.ts.map +1 -1
  33. package/dist/layouts/electronics/pages/ProductDetailPage.js +2 -1
  34. package/dist/layouts/electronics-grid/components/ElectronicsGridProductCard.d.ts.map +1 -1
  35. package/dist/layouts/electronics-grid/components/ElectronicsGridProductCard.js +2 -2
  36. package/dist/layouts/electronics-grid/pages/ProductDetailPage.d.ts.map +1 -1
  37. package/dist/layouts/electronics-grid/pages/ProductDetailPage.js +2 -1
  38. package/dist/layouts/food/pages/MenuPage.d.ts.map +1 -1
  39. package/dist/layouts/food/pages/MenuPage.js +1 -0
  40. package/dist/layouts/food/pages/ProductDetailPage.d.ts.map +1 -1
  41. package/dist/layouts/food/pages/ProductDetailPage.js +2 -1
  42. package/dist/layouts/food-modern/components/FoodHomePageModern.js +1 -1
  43. package/dist/layouts/food-modern/pages/MenuPage.d.ts.map +1 -1
  44. package/dist/layouts/food-modern/pages/MenuPage.js +1 -0
  45. package/dist/layouts/food-modern/pages/ProductDetailPage.d.ts.map +1 -1
  46. package/dist/layouts/food-modern/pages/ProductDetailPage.js +2 -1
  47. package/dist/layouts/shared/components/PromoBanner.d.ts +4 -1
  48. package/dist/layouts/shared/components/PromoBanner.d.ts.map +1 -1
  49. package/dist/layouts/shared/components/PromoBanner.js +2 -2
  50. package/dist/layouts/shared/components/StoreCartSheet.d.ts.map +1 -1
  51. package/dist/layouts/shared/components/StoreCartSheet.js +4 -2
  52. package/dist/layouts/shared/components/StoreFooter.js +2 -2
  53. package/dist/layouts/shared/components/StoreHeader.js +4 -4
  54. package/dist/layouts/shared/pages/CartPage.d.ts.map +1 -1
  55. package/dist/layouts/shared/pages/CartPage.js +4 -28
  56. package/dist/layouts/shared/pages/CheckoutPage.d.ts.map +1 -1
  57. package/dist/layouts/shared/pages/CheckoutPage.js +203 -81
  58. package/dist/layouts/shared/pages/MaintenancePage.js +1 -1
  59. package/dist/layouts/shared/wrappers/ClothingLayout.js +5 -5
  60. package/dist/layouts/shared/wrappers/ClothingMinimalLayout.js +4 -4
  61. package/dist/layouts/shared/wrappers/ElectronicsLayout.js +4 -4
  62. package/dist/layouts/shared/wrappers/FoodModernLayout.js +4 -4
  63. package/dist/layouts/shared/wrappers/MotivationalLayout.js +4 -4
  64. package/dist/layouts/shared/wrappers/StandardLayout.js +4 -4
  65. package/dist/lib/cart-charge-currency.d.ts +16 -0
  66. package/dist/lib/cart-charge-currency.d.ts.map +1 -0
  67. package/dist/lib/cart-charge-currency.js +38 -0
  68. package/dist/lib/checkout-phone-validation.d.ts +3 -0
  69. package/dist/lib/checkout-phone-validation.d.ts.map +1 -0
  70. package/dist/lib/checkout-phone-validation.js +41 -0
  71. package/dist/lib/preview-data.d.ts.map +1 -1
  72. package/dist/lib/preview-data.js +2 -0
  73. package/dist/lib/rich-html.d.ts +1 -2
  74. package/dist/lib/rich-html.d.ts.map +1 -1
  75. package/dist/lib/services/fees.service.d.ts +40 -57
  76. package/dist/lib/services/fees.service.d.ts.map +1 -1
  77. package/dist/lib/services/fees.service.js +24 -120
  78. package/dist/lib/store-types.d.ts +27 -34
  79. package/dist/lib/store-types.d.ts.map +1 -1
  80. package/dist/lib/utils/fee-calculations.d.ts.map +1 -1
  81. package/dist/lib/utils/fee-calculations.js +23 -11
  82. package/dist/preview/LayoutPreview.d.ts.map +1 -1
  83. package/dist/preview/LayoutPreview.js +5 -22
  84. package/dist/styles/index.css +36 -0
  85. package/dist/utils/price-display.d.ts +3 -0
  86. package/dist/utils/price-display.d.ts.map +1 -0
  87. package/dist/utils/price-display.js +8 -0
  88. 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,3 @@
1
+ export declare function sanitizeCheckoutPhoneInput(value: string): string;
2
+ export declare function getCheckoutPhoneValidationError(phone: string, regionCode: string | undefined): string | undefined;
3
+ //# sourceMappingURL=checkout-phone-validation.d.ts.map
@@ -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,CAiPnD;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"}
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"}
@@ -809,6 +809,8 @@ export function getBookingPreviewData() {
809
809
  testimonials: {
810
810
  show: true,
811
811
  title: 'What Our Clients Say',
812
+ limit: 3,
813
+ showRatings: true,
812
814
  items: [
813
815
  {
814
816
  id: 't1',
@@ -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: string;
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;AAEnD,sEAAsE;AACtE,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;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
+ {"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 type FeeSource = 'merchant' | 'platform';
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?: FeeSource;
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: MerchantFeesSection;
36
- platform: PlatformFeesSection;
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?: CheckoutFeeBreakdown;
49
- charges?: Array<{
50
- label: string;
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(result: FeeCalculationResponse, fallbackSubtotal?: number, fallbackShipping?: number): CheckoutFeeBreakdown;
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
- * Fee preview for a cart spanning multiple stores — one HTTP round trip that returns a
81
- * breakdown per store, instead of firing one /calculate call per store from the client.
54
+ * Calculate fees for an order
82
55
  */
83
- calculateFeesBatch(stores: BatchFeeCalculationStoreRequest[], currency: string): Promise<BatchFeeCalculationResult[]>;
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":"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"}
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: emptyMerchantSection(),
21
- platform: emptyPlatformSection(),
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 isConsolidatedBreakdown(value) {
26
- if (!value || typeof value !== 'object')
27
- return false;
28
- const record = value;
29
- return (typeof record.merchant === 'object' &&
30
- record.merchant !== null &&
31
- typeof record.platform === 'object' &&
32
- record.platform !== null);
33
- }
34
- function normalizeLegacyBreakdown(legacy, fallbackSubtotal, fallbackShipping) {
35
- const subtotal = Number(legacy.subtotal) || fallbackSubtotal;
36
- const shipping = Number(legacy.shipping) || fallbackShipping;
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 merchant = {
68
- configuredBy: 'store_fee_settings',
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
- merchant,
104
- platform,
105
- customerLines,
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
- isLimitedTimeOffer?: boolean;
81
- limitedTimeOfferEndsAt?: string | Date | null;
82
- variants?: Array<{
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;