@sazito/checkout 0.1.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/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/chunks/labels-BlMZkOsV.cjs +1646 -0
- package/dist/chunks/labels-BlMZkOsV.cjs.map +1 -0
- package/dist/chunks/labels-ChywPk2i.js +1613 -0
- package/dist/chunks/labels-ChywPk2i.js.map +1 -0
- package/dist/chunks/use-checkout-Cvp_K3UW.cjs +69 -0
- package/dist/chunks/use-checkout-Cvp_K3UW.cjs.map +1 -0
- package/dist/chunks/use-checkout-E0O8HsSs.js +63 -0
- package/dist/chunks/use-checkout-E0O8HsSs.js.map +1 -0
- package/dist/core/index.cjs +40 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +482 -0
- package/dist/core/index.d.ts +482 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/next/index.cjs +845 -0
- package/dist/next/index.cjs.map +1 -0
- package/dist/next/index.d.cts +427 -0
- package/dist/next/index.d.ts +427 -0
- package/dist/next/index.js +834 -0
- package/dist/next/index.js.map +1 -0
- package/dist/react/index.cjs +17 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +376 -0
- package/dist/react/index.d.ts +376 -0
- package/dist/react/index.js +7 -0
- package/dist/react/index.js.map +1 -0
- package/dist/styles.css +1696 -0
- package/package.json +98 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import { Cart, Invoice, ApplicableShippingMethods, InvoiceItem, ShippingRate, PaymentMethod, Order, SazitoClient, CredentialsManager, SazitoResponse, PaymentGateway, ShippingAssignment } from '@sazito/client-sdk';
|
|
2
|
+
export { ApplicableShippingMethods, Cart, CartProduct, Invoice, InvoiceItem, InvoiceShippingAddress, ItemShippingRate, Order, PaymentAction, PaymentGateway, PaymentMethod, ShippingAddress, ShippingAddressInput, ShippingAssignment, ShippingItem, ShippingMethod, ShippingRate } from '@sazito/client-sdk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Checkout domain types.
|
|
6
|
+
*
|
|
7
|
+
* The package re-exports the SDK data models (camelCase) and layers
|
|
8
|
+
* checkout-specific state, config, events and effects on top.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** How a discount code changes the order. */
|
|
12
|
+
type DiscountKind = 'percentage' | 'fixed_amount' | 'free_shipping' | 'unknown';
|
|
13
|
+
/**
|
|
14
|
+
* A successfully applied discount code with its detected type. The API only
|
|
15
|
+
* reports discount codes as totals on the invoice, so the type is inferred by
|
|
16
|
+
* `classifyAppliedDiscount` (selectors) — `unknown` when nothing measurable
|
|
17
|
+
* changed yet (e.g. a free-shipping code applied before a rate is selected).
|
|
18
|
+
*/
|
|
19
|
+
interface AppliedDiscount {
|
|
20
|
+
code: string;
|
|
21
|
+
kind: DiscountKind;
|
|
22
|
+
/** Amount taken off the items total by this code. */
|
|
23
|
+
amount: number;
|
|
24
|
+
/** Percentage discounts only: the detected integer percent. */
|
|
25
|
+
percent?: number;
|
|
26
|
+
/** Shipping cost removed by the code. */
|
|
27
|
+
shippingSaved?: number;
|
|
28
|
+
}
|
|
29
|
+
/** Regions are not re-exported by the SDK top level; mirror the shape here. */
|
|
30
|
+
interface CheckoutCity {
|
|
31
|
+
id: number;
|
|
32
|
+
name: string;
|
|
33
|
+
latitude: number;
|
|
34
|
+
longitude: number;
|
|
35
|
+
}
|
|
36
|
+
interface CheckoutRegion {
|
|
37
|
+
id: number;
|
|
38
|
+
name: string;
|
|
39
|
+
cities: CheckoutCity[];
|
|
40
|
+
}
|
|
41
|
+
type CheckoutLocale = 'fa' | 'en';
|
|
42
|
+
type CheckoutDirection = 'rtl' | 'ltr';
|
|
43
|
+
/** Interactive steps in order. `result` is the terminal post-payment screen. */
|
|
44
|
+
type CheckoutStep = 'cart' | 'shipping' | 'payment' | 'result';
|
|
45
|
+
/** Coarse engine status used to drive spinners / disabled states. */
|
|
46
|
+
type CheckoutStatus = 'idle' | 'bootstrapping' | 'working' | 'redirecting' | 'polling' | 'error';
|
|
47
|
+
type CheckoutResultStatus = 'success' | 'failed' | 'pending' | 'stock_violated';
|
|
48
|
+
interface CheckoutTheme {
|
|
49
|
+
/** Primary accent (buttons, active states). CSS color. */
|
|
50
|
+
accent?: string;
|
|
51
|
+
/** Foreground used on top of the accent. CSS color. */
|
|
52
|
+
accentForeground?: string;
|
|
53
|
+
/** Soft accent surface used for selected rows and focus-adjacent states. */
|
|
54
|
+
accentSoft?: string;
|
|
55
|
+
/** Checkout page background. */
|
|
56
|
+
background?: string;
|
|
57
|
+
/** Primary text color. */
|
|
58
|
+
foreground?: string;
|
|
59
|
+
/** Muted surface background. */
|
|
60
|
+
muted?: string;
|
|
61
|
+
/** Secondary text color. */
|
|
62
|
+
mutedForeground?: string;
|
|
63
|
+
/** Borders and dividers. */
|
|
64
|
+
border?: string;
|
|
65
|
+
/** Form, product, and shipping card background. */
|
|
66
|
+
card?: string;
|
|
67
|
+
/** Order-summary sidebar background. */
|
|
68
|
+
summaryBackground?: string;
|
|
69
|
+
/** Error and destructive-state color. */
|
|
70
|
+
danger?: string;
|
|
71
|
+
/** Success and completed-state color. */
|
|
72
|
+
success?: string;
|
|
73
|
+
/** Base corner radius in px. */
|
|
74
|
+
radius?: number;
|
|
75
|
+
/** Font family. Defaults to `inherit` so the host font flows through. */
|
|
76
|
+
fontFamily?: string;
|
|
77
|
+
}
|
|
78
|
+
/** Seed credentials so checkout can attach to an already-built cart. */
|
|
79
|
+
interface CheckoutCredentials {
|
|
80
|
+
cart?: {
|
|
81
|
+
id?: number;
|
|
82
|
+
identifier: string;
|
|
83
|
+
};
|
|
84
|
+
invoice?: {
|
|
85
|
+
id: number;
|
|
86
|
+
identifier: string;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
interface CheckoutConfig {
|
|
90
|
+
locale?: CheckoutLocale;
|
|
91
|
+
direction?: CheckoutDirection;
|
|
92
|
+
theme?: CheckoutTheme;
|
|
93
|
+
/** URL for the "continue shopping" / back-to-store action. */
|
|
94
|
+
continueShoppingUrl?: string;
|
|
95
|
+
/** URL the gateway returns to after payment. Defaults to current URL. */
|
|
96
|
+
returnUrl?: string;
|
|
97
|
+
/** Pending-payment poll interval in ms (default 15000). */
|
|
98
|
+
pollIntervalMs?: number;
|
|
99
|
+
/** Currency label override (defaults per-locale). */
|
|
100
|
+
currencyLabel?: string;
|
|
101
|
+
onEvent?: (event: CheckoutEvent) => void;
|
|
102
|
+
}
|
|
103
|
+
/** The guest contact + address form. */
|
|
104
|
+
interface AddressFormValues {
|
|
105
|
+
firstName: string;
|
|
106
|
+
lastName: string;
|
|
107
|
+
mobilePhone: string;
|
|
108
|
+
email: string;
|
|
109
|
+
phoneNumber: string;
|
|
110
|
+
regionId: number | null;
|
|
111
|
+
cityId: number | null;
|
|
112
|
+
postalCode: string;
|
|
113
|
+
address: string;
|
|
114
|
+
description: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A shippable group: a set of invoice items shipped together, with the rates
|
|
118
|
+
* the customer can switch between and the currently selected rate.
|
|
119
|
+
*/
|
|
120
|
+
interface ShippingGroup {
|
|
121
|
+
key: string;
|
|
122
|
+
title: string;
|
|
123
|
+
itemIds: Array<number | string>;
|
|
124
|
+
items: InvoiceItem[];
|
|
125
|
+
rates: ShippingRate[];
|
|
126
|
+
selectedRateId: number | null;
|
|
127
|
+
}
|
|
128
|
+
interface CheckoutResult {
|
|
129
|
+
status: CheckoutResultStatus;
|
|
130
|
+
order?: Order;
|
|
131
|
+
message?: string;
|
|
132
|
+
}
|
|
133
|
+
interface CheckoutError {
|
|
134
|
+
message: string;
|
|
135
|
+
code?: CheckoutErrorCode;
|
|
136
|
+
status?: number;
|
|
137
|
+
step?: CheckoutStep;
|
|
138
|
+
}
|
|
139
|
+
type CheckoutErrorCode = 'no_cart' | 'no_invoice' | 'min_basket' | 'rate_limited' | 'cart_invalid' | 'invoice_locked' | 'stock_violated' | 'shipping_required' | 'address_required' | 'payment_failed' | 'network' | 'validation' | 'unknown';
|
|
140
|
+
/** Per-region async flags so the UI can show targeted spinners. */
|
|
141
|
+
interface CheckoutFlags {
|
|
142
|
+
bootstrapping: boolean;
|
|
143
|
+
updatingCart: boolean;
|
|
144
|
+
savingAddress: boolean;
|
|
145
|
+
loadingShipping: boolean;
|
|
146
|
+
selectingRate: boolean;
|
|
147
|
+
applyingDiscount: boolean;
|
|
148
|
+
loadingPayments: boolean;
|
|
149
|
+
placingOrder: boolean;
|
|
150
|
+
}
|
|
151
|
+
interface CheckoutState {
|
|
152
|
+
step: CheckoutStep;
|
|
153
|
+
status: CheckoutStatus;
|
|
154
|
+
locale: CheckoutLocale;
|
|
155
|
+
direction: CheckoutDirection;
|
|
156
|
+
cart: Cart | null;
|
|
157
|
+
invoice: Invoice | null;
|
|
158
|
+
regions: CheckoutRegion[];
|
|
159
|
+
addressForm: AddressFormValues;
|
|
160
|
+
/** Shop-level requirement loaded from the checkout configuration. */
|
|
161
|
+
postalCodeMandatory: boolean;
|
|
162
|
+
/** Shop-level requirement loaded from the checkout configuration. */
|
|
163
|
+
emailMandatory: boolean;
|
|
164
|
+
/** Whether the saved address on the invoice matches the current form. */
|
|
165
|
+
addressDirty: boolean;
|
|
166
|
+
applicable: ApplicableShippingMethods | null;
|
|
167
|
+
shippingGroups: ShippingGroup[];
|
|
168
|
+
paymentMethods: PaymentMethod[];
|
|
169
|
+
selectedPaymentMethodId: number | null;
|
|
170
|
+
discountCode: string;
|
|
171
|
+
appliedDiscountCode: string | null;
|
|
172
|
+
/** Type + saved amounts of the applied code; null when no code is applied. */
|
|
173
|
+
appliedDiscount: AppliedDiscount | null;
|
|
174
|
+
/** Inline error for the discount field; not shown in the global banner. */
|
|
175
|
+
discountError: string | null;
|
|
176
|
+
result: CheckoutResult | null;
|
|
177
|
+
error: CheckoutError | null;
|
|
178
|
+
flags: CheckoutFlags;
|
|
179
|
+
}
|
|
180
|
+
type CheckoutEventName = 'checkout_viewed' | 'step_viewed' | 'address_submitted' | 'shipping_rate_selected' | 'discount_applied' | 'discount_removed' | 'payment_method_selected' | 'payment_initiated' | 'payment_succeeded' | 'payment_failed' | 'payment_pending';
|
|
181
|
+
interface CheckoutEvent {
|
|
182
|
+
name: CheckoutEventName;
|
|
183
|
+
step?: CheckoutStep;
|
|
184
|
+
value?: number;
|
|
185
|
+
metadata?: Record<string, unknown>;
|
|
186
|
+
timestamp: number;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Side-effects the pure engine asks the host to perform. The default browser
|
|
190
|
+
* executor handles all of these; a host may override (SSR / native / tests).
|
|
191
|
+
*/
|
|
192
|
+
type CheckoutEffect = {
|
|
193
|
+
type: 'redirect';
|
|
194
|
+
url: string;
|
|
195
|
+
} | {
|
|
196
|
+
type: 'post-form';
|
|
197
|
+
url: string;
|
|
198
|
+
fields: Record<string, string>;
|
|
199
|
+
} | {
|
|
200
|
+
type: 'emit';
|
|
201
|
+
event: CheckoutEvent;
|
|
202
|
+
};
|
|
203
|
+
type CheckoutEffectExecutor = (effect: CheckoutEffect) => void;
|
|
204
|
+
/** Options for constructing the engine. */
|
|
205
|
+
interface CheckoutEngineOptions {
|
|
206
|
+
client?: unknown;
|
|
207
|
+
credentials?: CheckoutCredentials;
|
|
208
|
+
config?: CheckoutConfig;
|
|
209
|
+
}
|
|
210
|
+
/** Public command surface exposed to UI bindings. */
|
|
211
|
+
interface CheckoutActions {
|
|
212
|
+
/** Load cart + invoice and derive initial state. */
|
|
213
|
+
start(): Promise<void>;
|
|
214
|
+
goToStep(step: CheckoutStep): void;
|
|
215
|
+
next(): Promise<void>;
|
|
216
|
+
back(): void;
|
|
217
|
+
/** Cart review edits — update a line quantity or remove a line. */
|
|
218
|
+
updateItemQuantity(cartProductId: number | string, variantId: number, quantity: number): Promise<void>;
|
|
219
|
+
removeItem(cartProductId: number | string, variantId: number): Promise<void>;
|
|
220
|
+
setAddressField<K extends keyof AddressFormValues>(key: K, value: AddressFormValues[K]): void;
|
|
221
|
+
submitAddress(): Promise<boolean>;
|
|
222
|
+
selectShippingRate(groupKey: string, rateId: number): Promise<void>;
|
|
223
|
+
setDiscountCode(code: string): void;
|
|
224
|
+
applyDiscount(): Promise<void>;
|
|
225
|
+
removeDiscount(): Promise<void>;
|
|
226
|
+
selectPaymentMethod(id: number): void;
|
|
227
|
+
placeOrder(): Promise<void>;
|
|
228
|
+
/** Resolve a return from the payment gateway (query params from the URL). */
|
|
229
|
+
resolvePaymentReturn(params: Record<string, string>): Promise<void>;
|
|
230
|
+
reset(): void;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
interface CheckoutEngine {
|
|
234
|
+
getState(): CheckoutState;
|
|
235
|
+
subscribe(listener: () => void): () => void;
|
|
236
|
+
actions: CheckoutActions;
|
|
237
|
+
setEffectExecutor(executor: CheckoutEffectExecutor): void;
|
|
238
|
+
destroy(): void;
|
|
239
|
+
}
|
|
240
|
+
declare function createCheckoutEngine(options: CheckoutEngineOptions): CheckoutEngine;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Minimal zero-dependency observable store.
|
|
244
|
+
*
|
|
245
|
+
* `getState` returns the current immutable snapshot; `setState` shallow-merges
|
|
246
|
+
* a partial (or applies an updater) and notifies subscribers. Designed to plug
|
|
247
|
+
* straight into React's `useSyncExternalStore`.
|
|
248
|
+
*/
|
|
249
|
+
interface Store<T> {
|
|
250
|
+
getState(): T;
|
|
251
|
+
setState(partial: Partial<T> | ((prev: T) => Partial<T>)): void;
|
|
252
|
+
subscribe(listener: () => void): () => void;
|
|
253
|
+
}
|
|
254
|
+
declare function createStore<T extends object>(initialState: T): Store<T>;
|
|
255
|
+
|
|
256
|
+
interface CheckoutSdkBinding {
|
|
257
|
+
client: SazitoClient;
|
|
258
|
+
credentials: CredentialsManager;
|
|
259
|
+
hasCart(): boolean;
|
|
260
|
+
hasInvoice(): boolean;
|
|
261
|
+
}
|
|
262
|
+
declare function createSdkBinding(options: CheckoutEngineOptions): CheckoutSdkBinding;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Side-effect types + the default browser executor.
|
|
266
|
+
*
|
|
267
|
+
* The engine never touches the DOM directly; it emits effects and a host-
|
|
268
|
+
* provided executor performs them. This keeps the engine SSR-safe and testable.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Build the default browser executor. `onEvent` (from config) receives `emit`
|
|
273
|
+
* effects so analytics adapters can subscribe.
|
|
274
|
+
*/
|
|
275
|
+
declare function createBrowserEffectExecutor(config?: CheckoutConfig): CheckoutEffectExecutor;
|
|
276
|
+
/** A no-op executor for SSR / tests. */
|
|
277
|
+
declare const noopEffectExecutor: CheckoutEffectExecutor;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Typed event bus helpers.
|
|
281
|
+
*/
|
|
282
|
+
|
|
283
|
+
declare function makeEvent(name: CheckoutEventName, data?: {
|
|
284
|
+
step?: CheckoutStep;
|
|
285
|
+
value?: number;
|
|
286
|
+
metadata?: Record<string, unknown>;
|
|
287
|
+
}): CheckoutEvent;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Error taxonomy + mapping from SDK responses to typed checkout errors.
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
type SdkError = NonNullable<SazitoResponse<unknown>['error']>;
|
|
294
|
+
declare function messageForCode(code: CheckoutErrorCode, locale: CheckoutLocale): string;
|
|
295
|
+
declare function fromSdkError(error: SdkError, locale: CheckoutLocale, step?: CheckoutStep): CheckoutError;
|
|
296
|
+
declare function makeError(code: CheckoutErrorCode, locale: CheckoutLocale, step?: CheckoutStep): CheckoutError;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Locale-aware number / currency formatting.
|
|
300
|
+
* Amounts are integer Toman values from the Sazito API.
|
|
301
|
+
*/
|
|
302
|
+
|
|
303
|
+
declare function toPersianDigits(input: string): string;
|
|
304
|
+
declare function toEnglishDigits(input: string): string;
|
|
305
|
+
declare function formatNumber(value: number, locale: CheckoutLocale): string;
|
|
306
|
+
/**
|
|
307
|
+
* Format a percentage with up to `maxDecimals` digits, trimming trailing zeros.
|
|
308
|
+
* Keeps small fractions visible (e.g. 0.02%) where `formatNumber` would round to 0.
|
|
309
|
+
*/
|
|
310
|
+
declare function formatPercent(value: number, locale: CheckoutLocale, maxDecimals?: number): string;
|
|
311
|
+
declare function defaultCurrencyLabel(locale: CheckoutLocale): string;
|
|
312
|
+
declare function formatMoney(value: number, locale: CheckoutLocale, currencyLabel?: string): string;
|
|
313
|
+
/**
|
|
314
|
+
* Normalize an Iranian phone number to the 11-digit 0XXXXXXXXXX format.
|
|
315
|
+
* Accepts: 09..., +989..., 00989..., 989..., 9... (10 digits without leading 0)
|
|
316
|
+
*/
|
|
317
|
+
declare function normalizeIranianPhone(raw: string): string;
|
|
318
|
+
declare function isValidIranianPhone(s: string): boolean;
|
|
319
|
+
declare function isValidIranianMobile(s: string): boolean;
|
|
320
|
+
/** Free price shown when a rate / delivery costs nothing. */
|
|
321
|
+
declare function formatPrice(value: number, locale: CheckoutLocale, currencyLabel?: string): string;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* UI strings (fa/en) and domain label helpers (payment gateways, shipping).
|
|
325
|
+
*/
|
|
326
|
+
|
|
327
|
+
interface Strings {
|
|
328
|
+
stepCart: string;
|
|
329
|
+
stepShipping: string;
|
|
330
|
+
stepPayment: string;
|
|
331
|
+
stepReview: string;
|
|
332
|
+
stepResult: string;
|
|
333
|
+
/** Mobile header title for the shipping step. */
|
|
334
|
+
stepShippingInfo: string;
|
|
335
|
+
/** Mobile header progress, e.g. "مرحله ۲ از ۳" / "Step 2 of 3". */
|
|
336
|
+
stepOf: (current: string, total: string) => string;
|
|
337
|
+
next: string;
|
|
338
|
+
placeOrder: string;
|
|
339
|
+
saveShippingDetails: string;
|
|
340
|
+
continueToPayment: string;
|
|
341
|
+
finalizeOrder: string;
|
|
342
|
+
finishPurchase: string;
|
|
343
|
+
back: string;
|
|
344
|
+
continueShopping: string;
|
|
345
|
+
orderSummary: string;
|
|
346
|
+
subtotal: string;
|
|
347
|
+
shipping: string;
|
|
348
|
+
discount: string;
|
|
349
|
+
credit: string;
|
|
350
|
+
vat: string;
|
|
351
|
+
total: string;
|
|
352
|
+
totalAmount: string;
|
|
353
|
+
free: string;
|
|
354
|
+
quantity: string;
|
|
355
|
+
optional: string;
|
|
356
|
+
cartTitle: string;
|
|
357
|
+
cartEmpty: string;
|
|
358
|
+
cartEmptyHint: string;
|
|
359
|
+
remove: string;
|
|
360
|
+
itemDiscount: (amount: string) => string;
|
|
361
|
+
yourSavings: string;
|
|
362
|
+
contactInfo: string;
|
|
363
|
+
firstName: string;
|
|
364
|
+
lastName: string;
|
|
365
|
+
mobilePhone: string;
|
|
366
|
+
email: string;
|
|
367
|
+
phoneNumber: string;
|
|
368
|
+
region: string;
|
|
369
|
+
city: string;
|
|
370
|
+
postalCode: string;
|
|
371
|
+
addressLine: string;
|
|
372
|
+
description: string;
|
|
373
|
+
selectRegion: string;
|
|
374
|
+
selectCity: string;
|
|
375
|
+
shippingMethod: string;
|
|
376
|
+
shippingMethods: string;
|
|
377
|
+
shippingMethodsHint: string;
|
|
378
|
+
digitalNoShipping: string;
|
|
379
|
+
errorRequired: string;
|
|
380
|
+
errorMobilePhone: string;
|
|
381
|
+
errorEmail: string;
|
|
382
|
+
changeTo: string;
|
|
383
|
+
productCount: (n: string) => string;
|
|
384
|
+
paymentMethod: string;
|
|
385
|
+
discountCode: string;
|
|
386
|
+
discountPlaceholder: string;
|
|
387
|
+
apply: string;
|
|
388
|
+
applied: string;
|
|
389
|
+
discountPercentOff: (percent: string) => string;
|
|
390
|
+
discountAmountOff: (amount: string) => string;
|
|
391
|
+
discountFreeShipping: string;
|
|
392
|
+
reviewTitle: string;
|
|
393
|
+
reviewContact: string;
|
|
394
|
+
reviewAddress: string;
|
|
395
|
+
reviewShipping: string;
|
|
396
|
+
reviewPayment: string;
|
|
397
|
+
payNow: string;
|
|
398
|
+
edit: string;
|
|
399
|
+
paymentSuccess: string;
|
|
400
|
+
paymentFailed: string;
|
|
401
|
+
paymentPending: string;
|
|
402
|
+
paymentPendingHint: string;
|
|
403
|
+
orderNumber: string;
|
|
404
|
+
tryAgain: string;
|
|
405
|
+
loading: string;
|
|
406
|
+
processing: string;
|
|
407
|
+
redirecting: string;
|
|
408
|
+
}
|
|
409
|
+
declare function strings(locale: CheckoutLocale): Strings;
|
|
410
|
+
/** Visual family of a payment method — drives the icon shown in the UI. */
|
|
411
|
+
type PaymentMethodKind = 'card' | 'cod' | 'bnpl' | 'wallet' | 'gateway' | 'free';
|
|
412
|
+
interface PaymentMethodInfo {
|
|
413
|
+
title: string;
|
|
414
|
+
description: string;
|
|
415
|
+
kind: PaymentMethodKind;
|
|
416
|
+
}
|
|
417
|
+
/** Human label for a payment gateway code. Online gateways fall back generically. */
|
|
418
|
+
declare function paymentMethodLabel(code: PaymentGateway, locale: CheckoutLocale): string;
|
|
419
|
+
/** Title + description + visual family for a payment gateway code. */
|
|
420
|
+
declare function paymentMethodInfo(code: PaymentGateway, locale: CheckoutLocale): PaymentMethodInfo;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Pure derivations over invoice / shipping data: shipping groups, summary
|
|
424
|
+
* lines, address form mapping and validation. No SDK calls, no side-effects.
|
|
425
|
+
*/
|
|
426
|
+
|
|
427
|
+
declare function emptyAddressForm(): AddressFormValues;
|
|
428
|
+
declare function addressFormFromInvoice(invoice: Invoice | null): AddressFormValues;
|
|
429
|
+
declare function isAddressComplete(form: AddressFormValues, needsShipping: boolean, postalCodeMandatory?: boolean, emailMandatory?: boolean): boolean;
|
|
430
|
+
/** Has the form diverged from what's saved on the invoice? */
|
|
431
|
+
declare function isAddressDirty(form: AddressFormValues, invoice: Invoice | null): boolean;
|
|
432
|
+
/**
|
|
433
|
+
* Group invoice items into shippable bundles with their switchable rates and
|
|
434
|
+
* the currently selected rate. Digital-only invoices yield an empty list.
|
|
435
|
+
*
|
|
436
|
+
* The Sazito API returns:
|
|
437
|
+
* groupedShippingRates — all applicable rates per "bundle" (keyed by group ID)
|
|
438
|
+
* itemsShippingRate — one entry per item with its DEFAULT/current rate
|
|
439
|
+
*
|
|
440
|
+
* The default rate ID in itemsShippingRate may NOT match any rate in
|
|
441
|
+
* groupedShippingRates (different IDs for the same method type). We therefore
|
|
442
|
+
* assign items by the currently ASSIGNED rate from invoice.shippingItems first,
|
|
443
|
+
* then fall back to the default rate, and finally use positional assignment
|
|
444
|
+
* (all physical items in the single group when there is only one group).
|
|
445
|
+
*/
|
|
446
|
+
declare function deriveShippingGroups(invoice: Invoice | null, applicable: ApplicableShippingMethods | null): ShippingGroup[];
|
|
447
|
+
/** Build the API payload from the current group selections. */
|
|
448
|
+
declare function buildShippingAssignments(groups: ShippingGroup[]): ShippingAssignment[];
|
|
449
|
+
/** True once every shippable group has a selected rate. */
|
|
450
|
+
declare function isShippingComplete(invoice: Invoice | null, groups: ShippingGroup[]): boolean;
|
|
451
|
+
/**
|
|
452
|
+
* The documented API contract has no discount "type" field — codes only show
|
|
453
|
+
* up as totals on the invoice. Classify by comparing the invoice before/after
|
|
454
|
+
* the code was applied:
|
|
455
|
+
* - shipping got cheaper, items total unchanged → free shipping
|
|
456
|
+
* - items total dropped by a near-integer % → percentage
|
|
457
|
+
* - items total dropped by anything else → fixed amount
|
|
458
|
+
* If the backend ever sends an explicit type on the discount usage
|
|
459
|
+
* (`discount_type` / `amount_type`), trust it over the heuristics.
|
|
460
|
+
* `before` is null when the code was restored from a saved invoice; deltas
|
|
461
|
+
* then fall back to the absolute totals and free shipping is undetectable.
|
|
462
|
+
*/
|
|
463
|
+
declare function classifyAppliedDiscount(before: Invoice | null, after: Invoice, code: string): AppliedDiscount;
|
|
464
|
+
type SummaryLineKey = 'subtotal' | 'discount' | 'shipping' | 'credit' | 'vat';
|
|
465
|
+
interface SummaryLine {
|
|
466
|
+
key: SummaryLineKey;
|
|
467
|
+
amount: number;
|
|
468
|
+
negative?: boolean;
|
|
469
|
+
free?: boolean;
|
|
470
|
+
/** Discount line only: amount as a percentage of subtotal (rounded). */
|
|
471
|
+
percent?: number;
|
|
472
|
+
}
|
|
473
|
+
interface CheckoutSummary {
|
|
474
|
+
lines: SummaryLine[];
|
|
475
|
+
total: number;
|
|
476
|
+
}
|
|
477
|
+
declare function selectSummary(invoice: Invoice | null): CheckoutSummary;
|
|
478
|
+
/** Items that don't require shipping (digital), for display in the shipping step. */
|
|
479
|
+
declare function selectDigitalItems(invoice: Invoice | null, groups: ShippingGroup[], applicable: ApplicableShippingMethods | null): InvoiceItem[];
|
|
480
|
+
|
|
481
|
+
export { addressFormFromInvoice, buildShippingAssignments, classifyAppliedDiscount, createBrowserEffectExecutor, createCheckoutEngine, createSdkBinding, createStore, defaultCurrencyLabel, deriveShippingGroups, emptyAddressForm, formatMoney, formatNumber, formatPercent, formatPrice, fromSdkError, isAddressComplete, isAddressDirty, isShippingComplete, isValidIranianMobile, isValidIranianPhone, makeError, makeEvent, messageForCode, noopEffectExecutor, normalizeIranianPhone, paymentMethodInfo, paymentMethodLabel, selectDigitalItems, selectSummary, strings, toEnglishDigits, toPersianDigits };
|
|
482
|
+
export type { AddressFormValues, AppliedDiscount, CheckoutActions, CheckoutCity, CheckoutConfig, CheckoutCredentials, CheckoutDirection, CheckoutEffect, CheckoutEffectExecutor, CheckoutEngine, CheckoutEngineOptions, CheckoutError, CheckoutErrorCode, CheckoutEvent, CheckoutEventName, CheckoutFlags, CheckoutLocale, CheckoutRegion, CheckoutResult, CheckoutResultStatus, CheckoutSdkBinding, CheckoutState, CheckoutStatus, CheckoutStep, CheckoutSummary, CheckoutTheme, DiscountKind, PaymentMethodInfo, PaymentMethodKind, ShippingGroup, Store, Strings, SummaryLine, SummaryLineKey };
|