@cartbase/storefront 0.2.0 → 0.3.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.
- package/package.json +1 -1
- package/src/api/carts.ts +5 -3
- package/src/api/checkout.ts +91 -40
- package/src/api/integrations.ts +4 -17
- package/src/cart-drawer/labels-bg.ts +1 -1
- package/src/cart-drawer/labels.ts +119 -119
- package/src/cart-drawer/summary-breakdown.tsx +197 -196
- package/src/checkout/checkout-client.tsx +13 -10
- package/src/checkout/index.ts +0 -1
- package/src/checkout/labels-bg.ts +1 -1
- package/src/checkout/labels.ts +263 -263
- package/src/checkout/order-summary.tsx +45 -45
- package/src/checkout/payment-method-list.tsx +92 -32
- package/src/checkout/use-checkout-orchestration.ts +96 -86
- package/src/lib/payment-constants.ts +53 -66
- package/src/order/labels-bg.ts +39 -39
- package/src/order/labels.ts +79 -79
- package/src/order/order-completed-template.tsx +17 -9
- package/src/order/order-payment-card.tsx +26 -35
- package/src/order/order-totals.tsx +250 -245
|
@@ -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
|
|
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
|
|
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
|
-
* -
|
|
74
|
-
* `
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
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
|
-
/**
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
/**
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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,
|
|
@@ -794,20 +793,20 @@ export function useCheckoutOrchestration({
|
|
|
794
793
|
// ── Payment ─────────────────────────────────────────────────────────
|
|
795
794
|
const [paymentError, setPaymentError] = useState<string | null>(null)
|
|
796
795
|
|
|
797
|
-
const hasCard = !!effectiveAvailablePaymentMethods?.some(
|
|
798
|
-
isStripeLike(m.id)
|
|
799
|
-
)
|
|
800
|
-
const hasCod = !!effectiveAvailablePaymentMethods?.some(
|
|
801
|
-
(m) => isCodLikeId(m.id) || m.id === "pp_manual"
|
|
796
|
+
const hasCard = !!effectiveAvailablePaymentMethods?.some(
|
|
797
|
+
(m) => "id" in m && isStripeLike(m.id)
|
|
802
798
|
)
|
|
803
|
-
const cardId =
|
|
804
|
-
|
|
799
|
+
const cardId = (
|
|
800
|
+
effectiveAvailablePaymentMethods?.find(
|
|
801
|
+
(m) => "id" in m && isStripeLike(m.id)
|
|
802
|
+
) as { id: string } | undefined
|
|
805
803
|
)?.id
|
|
806
|
-
//
|
|
807
|
-
//
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
-
|
|
804
|
+
// The offline tab = a merchant METHOD (the COD switch, else the first
|
|
805
|
+
// manual method) — sessions initiate by payment_method_id, provider NULL.
|
|
806
|
+
const offlineMethod = findOfflineMethod(effectiveAvailablePaymentMethods)
|
|
807
|
+
const hasCod = !!offlineMethod
|
|
808
|
+
const codMethodId = offlineMethod?.payment_method_id
|
|
809
|
+
const offlineIsCodKind = offlineMethod?.kind === "cod"
|
|
811
810
|
|
|
812
811
|
// Default tab: card when available, else COD. The eager-session model
|
|
813
812
|
// used to seed from the cart's pending session provider; in the
|
|
@@ -816,14 +815,15 @@ export function useCheckoutOrchestration({
|
|
|
816
815
|
hasCard ? "card" : "cod"
|
|
817
816
|
)
|
|
818
817
|
|
|
819
|
-
// Optimistic
|
|
820
|
-
// totals row shows the predicted fee BEFORE the server applies
|
|
821
|
-
//
|
|
818
|
+
// Optimistic method-fee state. Painted instantly on tab toggle so the
|
|
819
|
+
// totals row shows the predicted fee BEFORE the server applies it (at
|
|
820
|
+
// prepare, when the method session is minted). Any method may carry a
|
|
821
|
+
// fee — the prediction reads the selected entry's own fee_amount.
|
|
822
822
|
// Three values:
|
|
823
823
|
// - null → no prediction; render whatever the cart says
|
|
824
|
-
// - 0 → predict no fee (toggling
|
|
825
|
-
// - positive → predict the fee at this amount
|
|
826
|
-
const [
|
|
824
|
+
// - 0 → predict no fee (toggling to a fee-less tender)
|
|
825
|
+
// - positive → predict the fee at this amount
|
|
826
|
+
const [optimisticMethodFee, setOptimisticMethodFee] = useState<number | null>(
|
|
827
827
|
null
|
|
828
828
|
)
|
|
829
829
|
|
|
@@ -840,30 +840,28 @@ export function useCheckoutOrchestration({
|
|
|
840
840
|
setPaymentTab(tab)
|
|
841
841
|
setPaymentError(null)
|
|
842
842
|
|
|
843
|
-
// Optimistic
|
|
844
|
-
//
|
|
845
|
-
//
|
|
846
|
-
//
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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
|
-
}
|
|
843
|
+
// Optimistic fee prediction so the totals row updates instantly —
|
|
844
|
+
// the selected METHOD entry carries its own fee; processors charge
|
|
845
|
+
// none. Mirrors the server exactly (resolveMethodFee reads the same
|
|
846
|
+
// row the listing serialized).
|
|
847
|
+
if (offlineMethod) {
|
|
848
|
+
const fee = Number(offlineMethod.fee_amount ?? 0)
|
|
849
|
+
setOptimisticMethodFee(tab === "cod" && fee > 0 ? fee : 0)
|
|
857
850
|
}
|
|
858
851
|
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
852
|
+
const tender =
|
|
853
|
+
tab === "card"
|
|
854
|
+
? cardId
|
|
855
|
+
? { provider_id: cardId }
|
|
856
|
+
: null
|
|
857
|
+
: codMethodId
|
|
858
|
+
? { payment_method_id: codMethodId }
|
|
859
|
+
: null
|
|
860
|
+
if (tender) {
|
|
861
|
+
void syncPaymentAmountApi(client, cart.id, tender).catch(() => {})
|
|
864
862
|
}
|
|
865
863
|
},
|
|
866
|
-
[cart.
|
|
864
|
+
[cart.id, client, cardId, codMethodId, offlineMethod]
|
|
867
865
|
)
|
|
868
866
|
|
|
869
867
|
// Shipping selection is client state only. No addShippingMethod call,
|
|
@@ -1088,26 +1086,26 @@ export function useCheckoutOrchestration({
|
|
|
1088
1086
|
// start = cart.total (covers subtotal + tax + any already-written
|
|
1089
1087
|
// shipping/fee)
|
|
1090
1088
|
// if optimisticShippingCost set: replace cart.shipping_total with it
|
|
1091
|
-
// if
|
|
1092
|
-
// (
|
|
1093
|
-
//
|
|
1089
|
+
// if optimisticMethodFee set: replace cart.payment_method_fee_total
|
|
1090
|
+
// with it (the fee is CART-LEVEL decoration folded into total,
|
|
1091
|
+
// not a fee line item)
|
|
1094
1092
|
// When nothing is optimistic, this collapses to cart.total.
|
|
1095
1093
|
const optimisticTotal = useMemo(() => {
|
|
1096
|
-
const
|
|
1094
|
+
const realMethodFeeAmount = cart?.payment_method_fee_total ?? 0
|
|
1097
1095
|
let total = cart?.total ?? 0
|
|
1098
1096
|
if (optimisticShippingCost !== null) {
|
|
1099
1097
|
total = total - (cart?.shipping_total ?? 0) + optimisticShippingCost
|
|
1100
1098
|
}
|
|
1101
|
-
if (
|
|
1102
|
-
total = total -
|
|
1099
|
+
if (optimisticMethodFee !== null && optimisticMethodFee !== undefined) {
|
|
1100
|
+
total = total - realMethodFeeAmount + optimisticMethodFee
|
|
1103
1101
|
}
|
|
1104
1102
|
return total
|
|
1105
1103
|
}, [
|
|
1106
1104
|
cart?.total,
|
|
1107
1105
|
cart?.shipping_total,
|
|
1108
|
-
cart?.
|
|
1106
|
+
cart?.payment_method_fee_total,
|
|
1109
1107
|
optimisticShippingCost,
|
|
1110
|
-
|
|
1108
|
+
optimisticMethodFee,
|
|
1111
1109
|
])
|
|
1112
1110
|
|
|
1113
1111
|
// ── Optimistic total in cents (for Stripe Elements deferred-intent) ─
|
|
@@ -1157,9 +1155,18 @@ export function useCheckoutOrchestration({
|
|
|
1157
1155
|
if (!shippingMethodId) {
|
|
1158
1156
|
throw new Error("No shipping method selected")
|
|
1159
1157
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1158
|
+
// The tender: card tab → the processor; offline tab → the merchant
|
|
1159
|
+
// method (provider-less session, pp_* kill).
|
|
1160
|
+
const tender =
|
|
1161
|
+
paymentTab === "card"
|
|
1162
|
+
? cardId
|
|
1163
|
+
? { payment_provider: cardId }
|
|
1164
|
+
: null
|
|
1165
|
+
: codMethodId
|
|
1166
|
+
? { payment_method_id: codMethodId }
|
|
1167
|
+
: null
|
|
1168
|
+
if (!tender) {
|
|
1169
|
+
throw new Error("No payment method available")
|
|
1163
1170
|
}
|
|
1164
1171
|
|
|
1165
1172
|
return {
|
|
@@ -1175,7 +1182,7 @@ export function useCheckoutOrchestration({
|
|
|
1175
1182
|
},
|
|
1176
1183
|
shipping_method_id: shippingMethodId,
|
|
1177
1184
|
carrier_metadata: carrierMetadata,
|
|
1178
|
-
|
|
1185
|
+
...tender,
|
|
1179
1186
|
}
|
|
1180
1187
|
}, [
|
|
1181
1188
|
formData,
|
|
@@ -1184,7 +1191,7 @@ export function useCheckoutOrchestration({
|
|
|
1184
1191
|
selectedBoxnowLocker,
|
|
1185
1192
|
paymentTab,
|
|
1186
1193
|
cardId,
|
|
1187
|
-
|
|
1194
|
+
codMethodId,
|
|
1188
1195
|
])
|
|
1189
1196
|
|
|
1190
1197
|
// ── Buy click ───────────────────────────────────────────────────────
|
|
@@ -1229,7 +1236,7 @@ export function useCheckoutOrchestration({
|
|
|
1229
1236
|
cart_id: cart.id,
|
|
1230
1237
|
paymentTab,
|
|
1231
1238
|
cardId,
|
|
1232
|
-
|
|
1239
|
+
codMethodId,
|
|
1233
1240
|
selectedShippingMethod,
|
|
1234
1241
|
selectedEcontOffice: selectedEcontOffice
|
|
1235
1242
|
? { code: selectedEcontOffice.code, name: selectedEcontOffice.name }
|
|
@@ -1268,7 +1275,8 @@ export function useCheckoutOrchestration({
|
|
|
1268
1275
|
// eslint-disable-next-line no-console
|
|
1269
1276
|
console.log("[buy-click] PAYLOAD →", payload)
|
|
1270
1277
|
logError?.("other", "buy_click_payload", {
|
|
1271
|
-
provider_id: payload.payment_provider,
|
|
1278
|
+
provider_id: payload.payment_provider ?? null,
|
|
1279
|
+
payment_method_id: payload.payment_method_id ?? null,
|
|
1272
1280
|
shipping_method_id: payload.shipping_method_id,
|
|
1273
1281
|
carrier_metadata_keys: Object.keys(payload.carrier_metadata ?? {}),
|
|
1274
1282
|
country_code: payload.shipping_address.country_code,
|
|
@@ -1420,7 +1428,7 @@ export function useCheckoutOrchestration({
|
|
|
1420
1428
|
cart.id,
|
|
1421
1429
|
paymentTab,
|
|
1422
1430
|
cardId,
|
|
1423
|
-
|
|
1431
|
+
codMethodId,
|
|
1424
1432
|
selectedShippingMethod,
|
|
1425
1433
|
selectedEcontOffice,
|
|
1426
1434
|
selectedBoxnowLocker,
|
|
@@ -1478,12 +1486,14 @@ export function useCheckoutOrchestration({
|
|
|
1478
1486
|
hasCard,
|
|
1479
1487
|
hasCod,
|
|
1480
1488
|
cardId,
|
|
1481
|
-
|
|
1489
|
+
/** The offline tab's method (the COD switch or a manual method). */
|
|
1490
|
+
codMethodId,
|
|
1491
|
+
offlineMethod,
|
|
1482
1492
|
paymentError,
|
|
1483
1493
|
setPaymentError,
|
|
1484
1494
|
deliveryReady,
|
|
1485
|
-
|
|
1486
|
-
|
|
1495
|
+
optimisticMethodFee,
|
|
1496
|
+
setOptimisticMethodFee,
|
|
1487
1497
|
handlePaymentTab,
|
|
1488
1498
|
handlePaymentElementChange,
|
|
1489
1499
|
|
|
@@ -1,66 +1,53 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Payment
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
}
|
package/src/order/labels-bg.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
+
}
|