@cartbase/storefront 0.2.0 → 0.4.0

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.
@@ -23,9 +23,11 @@ import {
23
23
  prepareCheckout,
24
24
  refreshPaymentIfTerminal as refreshPaymentIfTerminalApi,
25
25
  syncPaymentAmount as syncPaymentAmountApi,
26
+ isMethodEntry,
26
27
  type PrepareCheckoutInput,
27
28
  type RefreshPaymentResult,
28
- type StorePaymentProvider,
29
+ type StorePaymentEntry,
30
+ type StorePaymentMethodEntry,
29
31
  type StoreShippingOption,
30
32
  type SyncPaymentAmountResult,
31
33
  } from "../api/checkout"
@@ -35,8 +37,7 @@ import {
35
37
  type StoreCustomer,
36
38
  type UpdateCustomerInput,
37
39
  } from "../api/customers"
38
- import type { PublicCodConfig } from "../api/integrations"
39
- import { isManual, isStripeLike } from "../lib/payment-constants"
40
+ import { isStripeLike } from "../lib/payment-constants"
40
41
  import compareAddresses from "./compare-addresses"
41
42
  import { translateAddressError } from "./address-error-copy"
42
43
  import { translatePaymentError } from "./payment-error-copy"
@@ -70,13 +71,14 @@ import type { BoxNowLocker } from "../api/integrations"
70
71
  * entirely — the cart completes on the gift session alone. The @1click
71
72
  * original threw on a missing client_secret; Cartbase treats
72
73
  * null-secret + null-provider as the documented gift path.
73
- * - COD fee: Cartbase's fee is CART-LEVEL decoration (`cod_fee_total` /
74
- * `cod_fee_label`, folded into `cart.total` while a live pp_cod session
75
- * exists) not a metadata-flagged line item. The optimistic-fee math
76
- * reads `cart.cod_fee_total`; the prediction comes from the
77
- * integrations config `cod` block (never hardcoded).
78
- * - Provider ids: `pp_stripe` / `pp_cod` / `pp_manual` exactly
79
- * (lib/payment-constants + the pp_cod resolution below).
74
+ * - The payment method fee: CART-LEVEL decoration
75
+ * (`payment_method_fee_total` / `payment_method_fee_label`, folded into
76
+ * `cart.total` while a live method session exists) not a
77
+ * metadata-flagged line item. ANY method may carry a fee; the optimistic
78
+ * prediction reads `fee_amount` off the selected LISTING entry (the
79
+ * integrations `cod` block died 2026-08-11).
80
+ * - Processor ids: `pp_stripe` exactly (lib/payment-constants); merchant
81
+ * methods have no provider id — sessions ride `payment_method_id`.
80
82
  * - `logCheckoutError`/`logEvent` (Supabase-side sinks in @1click) have no
81
83
  * Cartbase store endpoint — the hook takes an optional `logError` callback
82
84
  * so stores wire their own sink; all production log points are kept.
@@ -93,11 +95,10 @@ import type { BoxNowLocker } from "../api/integrations"
93
95
  * class of fork-rot bug structurally impossible.
94
96
  */
95
97
 
96
- /** COD checkout config the integrations `cod` block (api/integrations). */
97
- export type CheckoutCodConfig = PublicCodConfig | null
98
-
99
- /** Minimal provider row the hook accepts (SDK DTO or bare `{id}`). */
100
- export type PaymentProviderLike = StorePaymentProvider | { id: string }
98
+ /** A payable entry the hook accepts: a processor row (`{id}`) or a
99
+ * merchant-method row (`{payment_method_id, name, kind}`) — the two wire
100
+ * shapes of GET /api/store/payment-providers since the pp_* kill. */
101
+ export type PaymentProviderLike = StorePaymentEntry | { id: string }
101
102
 
102
103
  export type CheckoutLogError = (
103
104
  errorType: string,
@@ -128,13 +129,6 @@ export type UseCheckoutOrchestrationOptions = {
128
129
  methods: PaymentProviderLike[] | null,
129
130
  selectedShippingOption: StoreShippingOption | null
130
131
  ) => PaymentProviderLike[] | null
131
- /**
132
- * Optional cash-on-delivery configuration — pass the integrations config
133
- * `cod` block (`getIntegrationsConfig(client).cod`). When present, the
134
- * hook paints `optimisticCodFee` on tab-toggle so the totals row updates
135
- * before the server-side fee (applied at prepare) arrives.
136
- */
137
- codConfig?: CheckoutCodConfig
138
132
  /**
139
133
  * Order-confirmed redirect path template (`{id}` → order.id,
140
134
  * `{country}` → shipping country). Falls back to the CheckoutProvider
@@ -194,12 +188,18 @@ const REQUIRED_ADDRESS_FIELDS = [
194
188
  */
195
189
  const ADDRESS_AUTO_SAVE_DEBOUNCE_MS = 600
196
190
 
197
- /** Cartbase COD provider resolution: `pp_cod` exactly, with the Medusa-era
198
- * `pp_system_default*` prefix kept as fallback (lib/payment-constants),
199
- * and `pp_manual` accepted as the offline tab when no true COD provider
200
- * is enabled. Fee prediction only ever applies via `codConfig` (pp_cod). */
201
- const isCodLikeId = (id?: string): boolean =>
202
- !!id && (id === "pp_cod" || isManual(id))
191
+ /** The offline tab's tender: a merchant METHOD entry (pp_* kill). The COD
192
+ * method (kind 'cod') wins; any manual method serves as the offline tab
193
+ * when no COD switch is on. The entry carries its own fee for prediction. */
194
+ const findOfflineMethod = (
195
+ entries: PaymentProviderLike[] | null | undefined
196
+ ): StorePaymentMethodEntry | null => {
197
+ const methods = (entries ?? []).filter(
198
+ (m): m is Extract<PaymentProviderLike, { payment_method_id: string }> =>
199
+ "payment_method_id" in m && isMethodEntry(m as StorePaymentEntry)
200
+ )
201
+ return methods.find((m) => m.kind === "cod") ?? methods[0] ?? null
202
+ }
203
203
 
204
204
  /**
205
205
  * Snapshot the address-relevant subset of formData. Used to skip
@@ -250,7 +250,6 @@ export function useCheckoutOrchestration({
250
250
  countryCode = "",
251
251
  countries,
252
252
  paymentMethodFilter,
253
- codConfig,
254
253
  orderConfirmedPath: orderConfirmedPathProp,
255
254
  onOrderPlaced,
256
255
  resolveTrackingMetadata,
@@ -678,13 +677,11 @@ export function useCheckoutOrchestration({
678
677
  string | null
679
678
  >(cart?.shipping_methods?.at(-1)?.shipping_option_id || null)
680
679
 
680
+ // Every listed option is offerable: the Medusa-era pickup filter read an
681
+ // embedded fulfillment_set the Cartbase API never sends (it never fired),
682
+ // and the concept itself died in the shipping vocabulary trial.
681
683
  const shippingMethods = useMemo(
682
- () =>
683
- (availableShippingMethods ?? []).filter(
684
- (sm) =>
685
- (sm as { service_zone?: { fulfillment_set?: { type?: string } } })
686
- .service_zone?.fulfillment_set?.type !== "pickup"
687
- ),
684
+ () => availableShippingMethods ?? [],
688
685
  [availableShippingMethods]
689
686
  )
690
687
 
@@ -794,20 +791,20 @@ export function useCheckoutOrchestration({
794
791
  // ── Payment ─────────────────────────────────────────────────────────
795
792
  const [paymentError, setPaymentError] = useState<string | null>(null)
796
793
 
797
- const hasCard = !!effectiveAvailablePaymentMethods?.some((m) =>
798
- isStripeLike(m.id)
794
+ const hasCard = !!effectiveAvailablePaymentMethods?.some(
795
+ (m) => "id" in m && isStripeLike(m.id)
799
796
  )
800
- const hasCod = !!effectiveAvailablePaymentMethods?.some(
801
- (m) => isCodLikeId(m.id) || m.id === "pp_manual"
802
- )
803
- const cardId = effectiveAvailablePaymentMethods?.find((m) =>
804
- isStripeLike(m.id)
797
+ const cardId = (
798
+ effectiveAvailablePaymentMethods?.find(
799
+ (m) => "id" in m && isStripeLike(m.id)
800
+ ) as { id: string } | undefined
805
801
  )?.id
806
- // Prefer the true COD provider; fall back to pp_manual so single-
807
- // provider stores still get an offline tab.
808
- const codId =
809
- effectiveAvailablePaymentMethods?.find((m) => isCodLikeId(m.id))?.id ??
810
- effectiveAvailablePaymentMethods?.find((m) => m.id === "pp_manual")?.id
802
+ // The offline tab = a merchant METHOD (the COD switch, else the first
803
+ // manual method) sessions initiate by payment_method_id, provider NULL.
804
+ const offlineMethod = findOfflineMethod(effectiveAvailablePaymentMethods)
805
+ const hasCod = !!offlineMethod
806
+ const codMethodId = offlineMethod?.payment_method_id
807
+ const offlineIsCodKind = offlineMethod?.kind === "cod"
811
808
 
812
809
  // Default tab: card when available, else COD. The eager-session model
813
810
  // used to seed from the cart's pending session provider; in the
@@ -816,14 +813,15 @@ export function useCheckoutOrchestration({
816
813
  hasCard ? "card" : "cod"
817
814
  )
818
815
 
819
- // Optimistic COD-fee state. Painted instantly on tab toggle so the
820
- // totals row shows the predicted fee BEFORE the server applies the
821
- // native fee (Cartbase: at prepare, when the pp_cod session is minted).
816
+ // Optimistic method-fee state. Painted instantly on tab toggle so the
817
+ // totals row shows the predicted fee BEFORE the server applies it (at
818
+ // prepare, when the method session is minted). Any method may carry a
819
+ // fee — the prediction reads the selected entry's own fee_amount.
822
820
  // Three values:
823
821
  // - null → no prediction; render whatever the cart says
824
- // - 0 → predict no fee (toggling away from COD)
825
- // - positive → predict the fee at this amount (toggling to COD)
826
- const [optimisticCodFee, setOptimisticCodFee] = useState<number | null>(
822
+ // - 0 → predict no fee (toggling to a fee-less tender)
823
+ // - positive → predict the fee at this amount
824
+ const [optimisticMethodFee, setOptimisticMethodFee] = useState<number | null>(
827
825
  null
828
826
  )
829
827
 
@@ -840,30 +838,28 @@ export function useCheckoutOrchestration({
840
838
  setPaymentTab(tab)
841
839
  setPaymentError(null)
842
840
 
843
- // Optimistic COD-fee prediction so the totals row updates instantly.
844
- // Currency must match the configured fee currency or the backend
845
- // skips the fee at apply time, so we mirror that gate here. The
846
- // prediction ONLY applies when the offline tab is the true pp_cod
847
- // provider — pp_manual carries no fee.
848
- if (codConfig) {
849
- const codCurrencyMatches =
850
- codConfig.fee_currency.toLowerCase() ===
851
- (cart.currency_code || "").toLowerCase()
852
- if (tab === "cod" && codCurrencyMatches && codId === "pp_cod") {
853
- setOptimisticCodFee(codConfig.fee_amount)
854
- } else {
855
- setOptimisticCodFee(0)
856
- }
841
+ // Optimistic fee prediction so the totals row updates instantly
842
+ // the selected METHOD entry carries its own fee; processors charge
843
+ // none. Mirrors the server exactly (resolveMethodFee reads the same
844
+ // row the listing serialized).
845
+ if (offlineMethod) {
846
+ const fee = Number(offlineMethod.fee_amount ?? 0)
847
+ setOptimisticMethodFee(tab === "cod" && fee > 0 ? fee : 0)
857
848
  }
858
849
 
859
- const provider = tab === "card" ? cardId : codId
860
- if (provider) {
861
- void syncPaymentAmountApi(client, cart.id, {
862
- provider_id: provider,
863
- }).catch(() => {})
850
+ const tender =
851
+ tab === "card"
852
+ ? cardId
853
+ ? { provider_id: cardId }
854
+ : null
855
+ : codMethodId
856
+ ? { payment_method_id: codMethodId }
857
+ : null
858
+ if (tender) {
859
+ void syncPaymentAmountApi(client, cart.id, tender).catch(() => {})
864
860
  }
865
861
  },
866
- [cart.currency_code, cart.id, client, codConfig, cardId, codId]
862
+ [cart.id, client, cardId, codMethodId, offlineMethod]
867
863
  )
868
864
 
869
865
  // Shipping selection is client state only. No addShippingMethod call,
@@ -1088,26 +1084,26 @@ export function useCheckoutOrchestration({
1088
1084
  // start = cart.total (covers subtotal + tax + any already-written
1089
1085
  // shipping/fee)
1090
1086
  // if optimisticShippingCost set: replace cart.shipping_total with it
1091
- // if optimisticCodFee set: replace cart.cod_fee_total with it
1092
- // (Cartbase: the COD fee is CART-LEVEL decoration folded into total,
1093
- // not a fee line item)
1087
+ // if optimisticMethodFee set: replace cart.payment_method_fee_total
1088
+ // with it (the fee is CART-LEVEL decoration folded into total,
1089
+ // not a fee line item)
1094
1090
  // When nothing is optimistic, this collapses to cart.total.
1095
1091
  const optimisticTotal = useMemo(() => {
1096
- const realCodFeeAmount = cart?.cod_fee_total ?? 0
1092
+ const realMethodFeeAmount = cart?.payment_method_fee_total ?? 0
1097
1093
  let total = cart?.total ?? 0
1098
1094
  if (optimisticShippingCost !== null) {
1099
1095
  total = total - (cart?.shipping_total ?? 0) + optimisticShippingCost
1100
1096
  }
1101
- if (optimisticCodFee !== null && optimisticCodFee !== undefined) {
1102
- total = total - realCodFeeAmount + optimisticCodFee
1097
+ if (optimisticMethodFee !== null && optimisticMethodFee !== undefined) {
1098
+ total = total - realMethodFeeAmount + optimisticMethodFee
1103
1099
  }
1104
1100
  return total
1105
1101
  }, [
1106
1102
  cart?.total,
1107
1103
  cart?.shipping_total,
1108
- cart?.cod_fee_total,
1104
+ cart?.payment_method_fee_total,
1109
1105
  optimisticShippingCost,
1110
- optimisticCodFee,
1106
+ optimisticMethodFee,
1111
1107
  ])
1112
1108
 
1113
1109
  // ── Optimistic total in cents (for Stripe Elements deferred-intent) ─
@@ -1157,9 +1153,18 @@ export function useCheckoutOrchestration({
1157
1153
  if (!shippingMethodId) {
1158
1154
  throw new Error("No shipping method selected")
1159
1155
  }
1160
- const paymentProvider = paymentTab === "card" ? cardId : codId
1161
- if (!paymentProvider) {
1162
- throw new Error("No payment provider available")
1156
+ // The tender: card tab the processor; offline tab → the merchant
1157
+ // method (provider-less session, pp_* kill).
1158
+ const tender =
1159
+ paymentTab === "card"
1160
+ ? cardId
1161
+ ? { payment_provider: cardId }
1162
+ : null
1163
+ : codMethodId
1164
+ ? { payment_method_id: codMethodId }
1165
+ : null
1166
+ if (!tender) {
1167
+ throw new Error("No payment method available")
1163
1168
  }
1164
1169
 
1165
1170
  return {
@@ -1175,7 +1180,7 @@ export function useCheckoutOrchestration({
1175
1180
  },
1176
1181
  shipping_method_id: shippingMethodId,
1177
1182
  carrier_metadata: carrierMetadata,
1178
- payment_provider: paymentProvider,
1183
+ ...tender,
1179
1184
  }
1180
1185
  }, [
1181
1186
  formData,
@@ -1184,7 +1189,7 @@ export function useCheckoutOrchestration({
1184
1189
  selectedBoxnowLocker,
1185
1190
  paymentTab,
1186
1191
  cardId,
1187
- codId,
1192
+ codMethodId,
1188
1193
  ])
1189
1194
 
1190
1195
  // ── Buy click ───────────────────────────────────────────────────────
@@ -1229,7 +1234,7 @@ export function useCheckoutOrchestration({
1229
1234
  cart_id: cart.id,
1230
1235
  paymentTab,
1231
1236
  cardId,
1232
- codId,
1237
+ codMethodId,
1233
1238
  selectedShippingMethod,
1234
1239
  selectedEcontOffice: selectedEcontOffice
1235
1240
  ? { code: selectedEcontOffice.code, name: selectedEcontOffice.name }
@@ -1268,7 +1273,8 @@ export function useCheckoutOrchestration({
1268
1273
  // eslint-disable-next-line no-console
1269
1274
  console.log("[buy-click] PAYLOAD →", payload)
1270
1275
  logError?.("other", "buy_click_payload", {
1271
- provider_id: payload.payment_provider,
1276
+ provider_id: payload.payment_provider ?? null,
1277
+ payment_method_id: payload.payment_method_id ?? null,
1272
1278
  shipping_method_id: payload.shipping_method_id,
1273
1279
  carrier_metadata_keys: Object.keys(payload.carrier_metadata ?? {}),
1274
1280
  country_code: payload.shipping_address.country_code,
@@ -1420,7 +1426,7 @@ export function useCheckoutOrchestration({
1420
1426
  cart.id,
1421
1427
  paymentTab,
1422
1428
  cardId,
1423
- codId,
1429
+ codMethodId,
1424
1430
  selectedShippingMethod,
1425
1431
  selectedEcontOffice,
1426
1432
  selectedBoxnowLocker,
@@ -1478,12 +1484,14 @@ export function useCheckoutOrchestration({
1478
1484
  hasCard,
1479
1485
  hasCod,
1480
1486
  cardId,
1481
- codId,
1487
+ /** The offline tab's method (the COD switch or a manual method). */
1488
+ codMethodId,
1489
+ offlineMethod,
1482
1490
  paymentError,
1483
1491
  setPaymentError,
1484
1492
  deliveryReady,
1485
- optimisticCodFee,
1486
- setOptimisticCodFee,
1493
+ optimisticMethodFee,
1494
+ setOptimisticMethodFee,
1487
1495
  handlePaymentTab,
1488
1496
  handlePaymentElementChange,
1489
1497
 
@@ -1,66 +1,53 @@
1
- /**
2
- * Payment provider helpers — identifier sniffing for store payment sessions.
3
- *
4
- * Ported from `@1click/ui/src/lib/payment-constants.ts` (v2.3.1) and
5
- * translated to the Cartbase provider-id seam (code truth:
6
- * `src/lib/stripe/providers.ts isStripeProviderId` matches exactly
7
- * `"pp_stripe" | "stripe"`; the accepted checkout ids are
8
- * `pp_stripe | pp_cod | pp_manual` — docs/contracts/store-api.md).
9
- * `pp_system_default` is the RETIRED legacy manual twin (payments-registry
10
- * card): no longer provisioned, hidden from merchants, kept here only so
11
- * historic orders keep rendering. The Medusa-era prefixes (`pp_stripe_*`,
12
- * `pp_medusa-*`) are kept as fallbacks so components ported later keep
13
- * working against either wire.
14
- *
15
- * Intentionally ships NO icons stores render their own icons via their
16
- * own icon set. The library stays free of icon-kit imports at this layer.
17
- */
18
-
19
- /**
20
- * True if the provider id is a Stripe-backed card payment provider.
21
- * Cartbase's canonical ids first (`pp_stripe` / `stripe`), then the
22
- * Medusa-era prefixes (`pp_stripe_*`, `pp_medusa-*`).
23
- */
24
- export const isStripeLike = (providerId?: string): boolean => {
25
- return Boolean(
26
- providerId &&
27
- (providerId === "pp_stripe" ||
28
- providerId === "stripe" ||
29
- providerId.startsWith("pp_stripe_") ||
30
- providerId.startsWith("pp_medusa-"))
31
- )
32
- }
33
-
34
- /** True if the provider id is PayPal. */
35
- export const isPaypal = (providerId?: string): boolean => {
36
- return Boolean(providerId?.startsWith("pp_paypal"))
37
- }
38
-
39
- /**
40
- * True if the provider id is an offline/manual provider: `pp_manual` (the
41
- * id checkout actually charges — payments-registry card) with the retired
42
- * `pp_system_default*` legacy twin as fallback for historic orders. COD is
43
- * NOT manual — `pp_cod` has its own id and its own fee flow.
44
- */
45
- export const isManual = (providerId?: string): boolean => {
46
- return Boolean(
47
- providerId &&
48
- (providerId === "pp_manual" || providerId.startsWith("pp_system_default"))
49
- )
50
- }
51
-
52
- export const paymentInfoMap: Record<
53
- string,
54
- { title: string; icon: React.JSX.Element | null }
55
- > = {
56
- pp_stripe: { title: "Credit / debit card", icon: null },
57
- pp_stripe_stripe: { title: "Credit / debit card", icon: null },
58
- "pp_medusa-payments_default": { title: "Credit / debit card", icon: null },
59
- "pp_stripe-ideal_stripe": { title: "iDeal", icon: null },
60
- "pp_stripe-bancontact_stripe": { title: "Bancontact", icon: null },
61
- pp_paypal_paypal: { title: "PayPal", icon: null },
62
- pp_cod: { title: "Cash on delivery", icon: null },
63
- pp_manual: { title: "Manual payment", icon: null },
64
- // Retired legacy manual twin — historic orders only (payments-registry).
65
- pp_system_default: { title: "Manual payment", icon: null },
66
- }
1
+ /**
2
+ * Payment tender helpers — identifier sniffing for store payment sessions.
3
+ *
4
+ * The Cartbase wire has exactly TWO tender shapes since the pp_* kill
5
+ * (20260811250000, no-payment-method-by-default card):
6
+ *
7
+ * - a PROCESSOR the merchant connected `provider_id` (`pp_stripe`
8
+ * today; PayPal etc. as integrations land);
9
+ * - a merchant-operated PAYMENT METHOD `payment_method_id` + `name` +
10
+ * `kind` (`manual` for Bank transfer / Pay in store, `cod` for the
11
+ * collection-on-delivery switch). Its session carries `provider_id`
12
+ * NULL; the merchant's NAME is the display everywhere.
13
+ *
14
+ * The dead ids (`pp_cod`, `pp_manual`, `pp_system_default`) are gone from
15
+ * the wire and from this module. The Medusa-era Stripe prefixes
16
+ * (`pp_stripe_*`, `pp_medusa-*`) are kept as fallbacks so components
17
+ * ported later keep working against either wire.
18
+ *
19
+ * Intentionally ships NO icons — stores render their own icons via their
20
+ * own icon set. The library stays free of icon-kit imports at this layer.
21
+ */
22
+
23
+ /**
24
+ * True if the provider id is a Stripe-backed card payment provider.
25
+ * Cartbase's canonical ids first (`pp_stripe` / `stripe`), then the
26
+ * Medusa-era prefixes (`pp_stripe_*`, `pp_medusa-*`).
27
+ */
28
+ export const isStripeLike = (providerId?: string | null): boolean => {
29
+ return Boolean(
30
+ providerId &&
31
+ (providerId === "pp_stripe" ||
32
+ providerId === "stripe" ||
33
+ providerId.startsWith("pp_stripe_") ||
34
+ providerId.startsWith("pp_medusa-"))
35
+ )
36
+ }
37
+
38
+ /** True if the provider id is PayPal. */
39
+ export const isPaypal = (providerId?: string | null): boolean => {
40
+ return Boolean(providerId?.startsWith("pp_paypal"))
41
+ }
42
+
43
+ export const paymentInfoMap: Record<
44
+ string,
45
+ { title: string; icon: React.JSX.Element | null }
46
+ > = {
47
+ pp_stripe: { title: "Credit / debit card", icon: null },
48
+ pp_stripe_stripe: { title: "Credit / debit card", icon: null },
49
+ "pp_medusa-payments_default": { title: "Credit / debit card", icon: null },
50
+ "pp_stripe-ideal_stripe": { title: "iDeal", icon: null },
51
+ "pp_stripe-bancontact_stripe": { title: "Bancontact", icon: null },
52
+ pp_paypal_paypal: { title: "PayPal", icon: null },
53
+ }
@@ -1,39 +1,39 @@
1
- import type { OrderLabels } from "./labels"
2
-
3
- /**
4
- * Bulgarian order labels — the Alenika/mindpages production copy, ported
5
- * from `@1click/ui/src/order/labels-bg.ts` (v2.3.1) + `tracking`.
6
- */
7
- export const bulgarianOrderLabels: OrderLabels = {
8
- orderConfirmed: "Поръчката е потвърдена",
9
- confirmationSent: "Изпратихме потвърждение на",
10
- orderNumber: "Поръчка",
11
- orderDate: "Дата",
12
- summary: "Обобщение на поръчката",
13
- subtotal: "Междинна сума",
14
- shipping: "Доставка",
15
- discount: "Отстъпка",
16
- tax: "ДДС",
17
- total: "Общо",
18
- codFee: "Такса наложен платеж",
19
- contactInfo: "Данни за контакт",
20
- delivery: "Доставка",
21
- paymentMethod: "Метод на плащане",
22
- paymentMethodTitles: {
23
- card: "Кредитна / дебитна карта",
24
- cod: "Наложен платеж",
25
- manual: "Друг начин на плащане",
26
- paypal: "PayPal",
27
- },
28
- needHelp: "Имате нужда от помощ?",
29
- contactUs: "Свържете се с нас",
30
- returnsExchanges: "Връщания и замени",
31
- orderPlaced: "Приета",
32
- processing: "Обработка",
33
- shipped: "Изпратена",
34
- delivered: "Доставена",
35
- free: "БЕЗПЛАТНА",
36
- continueShopping: "Продължи пазаруването",
37
- qty: "бр.",
38
- tracking: "Проследяване",
39
- }
1
+ import type { OrderLabels } from "./labels"
2
+
3
+ /**
4
+ * Bulgarian order labels — the Alenika/mindpages production copy, ported
5
+ * from `@1click/ui/src/order/labels-bg.ts` (v2.3.1) + `tracking`.
6
+ */
7
+ export const bulgarianOrderLabels: OrderLabels = {
8
+ orderConfirmed: "Поръчката е потвърдена",
9
+ confirmationSent: "Изпратихме потвърждение на",
10
+ orderNumber: "Поръчка",
11
+ orderDate: "Дата",
12
+ summary: "Обобщение на поръчката",
13
+ subtotal: "Междинна сума",
14
+ shipping: "Доставка",
15
+ discount: "Отстъпка",
16
+ tax: "ДДС",
17
+ total: "Общо",
18
+ paymentMethodFee: "Такса за плащане",
19
+ contactInfo: "Данни за контакт",
20
+ delivery: "Доставка",
21
+ paymentMethod: "Метод на плащане",
22
+ paymentMethodTitles: {
23
+ card: "Кредитна / дебитна карта",
24
+ cod: "Наложен платеж",
25
+ manual: "Друг начин на плащане",
26
+ paypal: "PayPal",
27
+ },
28
+ needHelp: "Имате нужда от помощ?",
29
+ contactUs: "Свържете се с нас",
30
+ returnsExchanges: "Връщания и замени",
31
+ orderPlaced: "Приета",
32
+ processing: "Обработка",
33
+ shipped: "Изпратена",
34
+ delivered: "Доставена",
35
+ free: "БЕЗПЛАТНА",
36
+ continueShopping: "Продължи пазаруването",
37
+ qty: "бр.",
38
+ tracking: "Проследяване",
39
+ }