@tagadapay/plugin-sdk 1.0.10 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/hooks/useCheckout.d.ts +6 -0
- package/dist/react/hooks/useCheckout.js +77 -1
- package/dist/react/hooks/useOrderBump.d.ts +30 -0
- package/dist/react/hooks/useOrderBump.js +97 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +1 -0
- package/dist/react/providers/TagadaProvider.d.ts +2 -8
- package/dist/react/providers/TagadaProvider.js +3 -46
- package/package.json +1 -1
|
@@ -273,6 +273,12 @@ export interface UseCheckoutResult {
|
|
|
273
273
|
shippingCountryChanged?: boolean;
|
|
274
274
|
billingCountryChanged?: boolean;
|
|
275
275
|
}>;
|
|
276
|
+
previewOrderSummary: (orderBumpOfferIds: string[], orderBumpType?: 'primary' | 'secondary' | 'vip') => Promise<{
|
|
277
|
+
savings: number;
|
|
278
|
+
savingsPct: number;
|
|
279
|
+
currency: string;
|
|
280
|
+
error?: any;
|
|
281
|
+
}>;
|
|
276
282
|
clear: () => void;
|
|
277
283
|
}
|
|
278
284
|
export declare function useCheckout(options?: UseCheckoutOptions): UseCheckoutResult;
|
|
@@ -3,7 +3,7 @@ import { useTagadaContext } from '../providers/TagadaProvider';
|
|
|
3
3
|
import { getCheckoutToken } from '../utils/urlUtils';
|
|
4
4
|
import { useCurrency } from '../hooks/useCurrency';
|
|
5
5
|
export function useCheckout(options = {}) {
|
|
6
|
-
const { apiService } = useTagadaContext();
|
|
6
|
+
const { apiService, updateCheckoutDebugData } = useTagadaContext();
|
|
7
7
|
const { code: currentCurrency } = useCurrency();
|
|
8
8
|
const [checkout, setCheckout] = useState(null);
|
|
9
9
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -21,6 +21,38 @@ export function useCheckout(options = {}) {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
}, []);
|
|
24
|
+
// Update debug data whenever checkout state changes with comprehensive information
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const debugData = checkout
|
|
27
|
+
? {
|
|
28
|
+
checkout,
|
|
29
|
+
sessionId: checkout.checkoutSession?.id,
|
|
30
|
+
checkoutToken: currentCheckoutTokenRef.current,
|
|
31
|
+
currency: checkout.summary?.currency,
|
|
32
|
+
totalAmount: checkout.summary?.totalAmount,
|
|
33
|
+
totalAdjustedAmount: checkout.summary?.totalAdjustedAmount,
|
|
34
|
+
promotionAmount: checkout.summary?.totalPromotionAmount,
|
|
35
|
+
itemsCount: checkout.summary?.items?.length || 0,
|
|
36
|
+
orderBumps: checkout.checkoutSession?.sessionLineItems?.filter((item) => item.isOrderBump) || [],
|
|
37
|
+
adjustments: checkout.summary?.adjustments || [],
|
|
38
|
+
isInitialized,
|
|
39
|
+
lastUpdated: new Date().toISOString(),
|
|
40
|
+
}
|
|
41
|
+
: null;
|
|
42
|
+
updateCheckoutDebugData(debugData, error, isLoading);
|
|
43
|
+
if (debugData) {
|
|
44
|
+
console.log('🐛 [useCheckout] Debug data updated for debug drawer', {
|
|
45
|
+
sessionId: debugData.sessionId,
|
|
46
|
+
totalAmount: debugData.totalAmount,
|
|
47
|
+
totalAdjustedAmount: debugData.totalAdjustedAmount,
|
|
48
|
+
promotionAmount: debugData.promotionAmount,
|
|
49
|
+
itemsCount: debugData.itemsCount,
|
|
50
|
+
orderBumpsCount: debugData.orderBumps?.length || 0,
|
|
51
|
+
adjustmentsCount: debugData.adjustments?.length || 0,
|
|
52
|
+
lastUpdated: debugData.lastUpdated,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}, [checkout, error, isLoading, isInitialized]); // Removed updateCheckoutDebugData from deps to prevent infinite loop
|
|
24
56
|
const init = useCallback(async (params) => {
|
|
25
57
|
// Don't allow init if we already have a checkout token
|
|
26
58
|
if (providedToken) {
|
|
@@ -85,6 +117,14 @@ export function useCheckout(options = {}) {
|
|
|
85
117
|
setCheckout(response);
|
|
86
118
|
currentCheckoutTokenRef.current = checkoutToken;
|
|
87
119
|
setIsInitialized(true);
|
|
120
|
+
console.log('📊 [useCheckout] Checkout data updated', {
|
|
121
|
+
sessionId: response.checkoutSession?.id,
|
|
122
|
+
totalAmount: response.summary?.totalAmount,
|
|
123
|
+
promotionAmount: response.summary?.totalPromotionAmount,
|
|
124
|
+
itemsCount: response.summary?.items?.length || 0,
|
|
125
|
+
orderBumpsCount: response.checkoutSession?.sessionLineItems?.filter((item) => item.isOrderBump)?.length || 0,
|
|
126
|
+
timestamp: new Date().toISOString(),
|
|
127
|
+
});
|
|
88
128
|
return response;
|
|
89
129
|
}
|
|
90
130
|
catch (err) {
|
|
@@ -100,7 +140,12 @@ export function useCheckout(options = {}) {
|
|
|
100
140
|
if (!currentCheckoutTokenRef.current) {
|
|
101
141
|
throw new Error('No checkout session to refresh');
|
|
102
142
|
}
|
|
143
|
+
console.log('🔄 [useCheckout] Refreshing checkout data...', {
|
|
144
|
+
checkoutToken: currentCheckoutTokenRef.current.substring(0, 8) + '...',
|
|
145
|
+
timestamp: new Date().toISOString(),
|
|
146
|
+
});
|
|
103
147
|
await getCheckout(currentCheckoutTokenRef.current);
|
|
148
|
+
console.log('✅ [useCheckout] Refresh completed, debug data will be updated automatically');
|
|
104
149
|
}, [getCheckout]);
|
|
105
150
|
const updateAddress = useCallback(async (data) => {
|
|
106
151
|
if (!checkout?.checkoutSession.id) {
|
|
@@ -280,7 +325,13 @@ export function useCheckout(options = {}) {
|
|
|
280
325
|
body: { orderBumpOfferId, selected },
|
|
281
326
|
});
|
|
282
327
|
if (response.success) {
|
|
328
|
+
console.log('🎯 [useCheckout] Order bump toggled successfully, refreshing checkout data...', {
|
|
329
|
+
orderBumpOfferId,
|
|
330
|
+
selected,
|
|
331
|
+
timestamp: new Date().toISOString(),
|
|
332
|
+
});
|
|
283
333
|
await refresh();
|
|
334
|
+
console.log('✅ [useCheckout] Order bump refresh completed, debug drawer should now show updated data');
|
|
284
335
|
}
|
|
285
336
|
return response;
|
|
286
337
|
}
|
|
@@ -325,6 +376,30 @@ export function useCheckout(options = {}) {
|
|
|
325
376
|
throw error;
|
|
326
377
|
}
|
|
327
378
|
}, [apiService, checkout?.checkoutSession.id, refresh]);
|
|
379
|
+
const previewOrderSummary = useCallback(async (orderBumpOfferIds, orderBumpType = 'vip') => {
|
|
380
|
+
if (!checkout?.checkoutSession.id) {
|
|
381
|
+
throw new Error('No checkout session available');
|
|
382
|
+
}
|
|
383
|
+
try {
|
|
384
|
+
const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkout.checkoutSession.id}/vip-preview`, {
|
|
385
|
+
method: 'POST',
|
|
386
|
+
body: {
|
|
387
|
+
orderBumpOfferIds,
|
|
388
|
+
orderBumpType,
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
return response;
|
|
392
|
+
}
|
|
393
|
+
catch (err) {
|
|
394
|
+
const error = err instanceof Error ? err : new Error('Failed to preview order summary');
|
|
395
|
+
return {
|
|
396
|
+
savings: 0,
|
|
397
|
+
savingsPct: 0,
|
|
398
|
+
currency: checkout?.summary?.currency ?? 'EUR',
|
|
399
|
+
error: error.message,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}, [apiService, checkout?.checkoutSession.id, checkout?.summary?.currency]);
|
|
328
403
|
const clear = useCallback(() => {
|
|
329
404
|
setCheckout(null);
|
|
330
405
|
setError(null);
|
|
@@ -380,6 +455,7 @@ export function useCheckout(options = {}) {
|
|
|
380
455
|
toggleOrderBump,
|
|
381
456
|
updateCustomer,
|
|
382
457
|
updateCustomerAndSessionInfo,
|
|
458
|
+
previewOrderSummary,
|
|
383
459
|
clear,
|
|
384
460
|
};
|
|
385
461
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface OrderBumpPreview {
|
|
2
|
+
savings: number;
|
|
3
|
+
savingsPct: number;
|
|
4
|
+
currency: string;
|
|
5
|
+
selectedOffers: {
|
|
6
|
+
productId: string | null;
|
|
7
|
+
variantId: string | null;
|
|
8
|
+
isSelected: boolean;
|
|
9
|
+
}[];
|
|
10
|
+
}
|
|
11
|
+
export interface UseOrderBumpOptions {
|
|
12
|
+
checkoutSessionId?: string;
|
|
13
|
+
offerId: string;
|
|
14
|
+
orderBumpType?: 'primary' | 'secondary' | 'vip';
|
|
15
|
+
autoPreview?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface UseOrderBumpResult {
|
|
18
|
+
isSelected: boolean;
|
|
19
|
+
preview: OrderBumpPreview | null;
|
|
20
|
+
savings: number | null;
|
|
21
|
+
isLoading: boolean;
|
|
22
|
+
isToggling: boolean;
|
|
23
|
+
error: Error | null;
|
|
24
|
+
toggle: (selected?: boolean) => Promise<{
|
|
25
|
+
success: boolean;
|
|
26
|
+
error?: any;
|
|
27
|
+
}>;
|
|
28
|
+
refreshPreview: () => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export declare function useOrderBump(options: UseOrderBumpOptions): UseOrderBumpResult;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
2
|
+
import { useTagadaContext } from '../providers/TagadaProvider';
|
|
3
|
+
export function useOrderBump(options) {
|
|
4
|
+
const { apiService } = useTagadaContext();
|
|
5
|
+
const { checkoutSessionId, offerId, orderBumpType = 'vip', autoPreview = true } = options;
|
|
6
|
+
const [isSelected, setIsSelected] = useState(false);
|
|
7
|
+
const [preview, setPreview] = useState(null);
|
|
8
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
9
|
+
const [isToggling, setIsToggling] = useState(false);
|
|
10
|
+
const [error, setError] = useState(null);
|
|
11
|
+
const refreshPreview = useCallback(async () => {
|
|
12
|
+
if (!checkoutSessionId)
|
|
13
|
+
return;
|
|
14
|
+
setIsLoading(true);
|
|
15
|
+
setError(null);
|
|
16
|
+
try {
|
|
17
|
+
const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/vip-preview`, {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
body: {
|
|
20
|
+
orderBumpOfferIds: [offerId],
|
|
21
|
+
orderBumpType,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
setPreview(response);
|
|
25
|
+
// Update isSelected based on preview data
|
|
26
|
+
const offerSelected = response.selectedOffers?.some((offer) => offer.isSelected);
|
|
27
|
+
setIsSelected(offerSelected ?? false);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
const error = err instanceof Error ? err : new Error('Failed to fetch preview');
|
|
31
|
+
setError(error);
|
|
32
|
+
console.error('Order bump preview failed:', error);
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
setIsLoading(false);
|
|
36
|
+
}
|
|
37
|
+
}, [checkoutSessionId, offerId, orderBumpType, apiService]);
|
|
38
|
+
const toggle = useCallback(async (selected) => {
|
|
39
|
+
if (!checkoutSessionId) {
|
|
40
|
+
throw new Error('No checkout session available');
|
|
41
|
+
}
|
|
42
|
+
const targetState = selected ?? !isSelected;
|
|
43
|
+
// Optimistic update
|
|
44
|
+
setIsSelected(targetState);
|
|
45
|
+
setIsToggling(true);
|
|
46
|
+
setError(null);
|
|
47
|
+
try {
|
|
48
|
+
const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/toggle-order-bump`, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
body: {
|
|
51
|
+
orderBumpOfferId: offerId,
|
|
52
|
+
selected: targetState,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
if (response.success) {
|
|
56
|
+
// Refresh preview to get updated savings
|
|
57
|
+
await refreshPreview();
|
|
58
|
+
return { success: true };
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Revert optimistic update
|
|
62
|
+
setIsSelected(!targetState);
|
|
63
|
+
return { success: false, error: response.error };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
// Revert optimistic update
|
|
68
|
+
setIsSelected(!targetState);
|
|
69
|
+
const error = err instanceof Error ? err : new Error('Failed to toggle order bump');
|
|
70
|
+
setError(error);
|
|
71
|
+
return { success: false, error: error.message };
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
setIsToggling(false);
|
|
75
|
+
}
|
|
76
|
+
}, [checkoutSessionId, offerId, isSelected, apiService, refreshPreview]);
|
|
77
|
+
// Auto-fetch preview on mount and when dependencies change
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (autoPreview && checkoutSessionId) {
|
|
80
|
+
refreshPreview().catch((error) => {
|
|
81
|
+
console.error('Auto-preview failed:', error);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}, [autoPreview, refreshPreview]);
|
|
85
|
+
// Calculate current savings
|
|
86
|
+
const savings = isSelected && preview?.savings ? preview.savings : preview?.savings || null;
|
|
87
|
+
return {
|
|
88
|
+
isSelected,
|
|
89
|
+
preview,
|
|
90
|
+
savings,
|
|
91
|
+
isLoading,
|
|
92
|
+
isToggling,
|
|
93
|
+
error,
|
|
94
|
+
toggle,
|
|
95
|
+
refreshPreview,
|
|
96
|
+
};
|
|
97
|
+
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { TagadaProvider } from './providers/TagadaProvider';
|
|
|
5
5
|
export { useCheckout } from './hooks/useCheckout';
|
|
6
6
|
export { useProducts } from './hooks/useProducts';
|
|
7
7
|
export { useOffers } from './hooks/useOffers';
|
|
8
|
+
export { useOrderBump } from './hooks/useOrderBump';
|
|
8
9
|
export { useSession } from './hooks/useSession';
|
|
9
10
|
export { useCurrency } from './hooks/useCurrency';
|
|
10
11
|
export { useCustomer } from './hooks/useCustomer';
|
|
@@ -19,6 +20,7 @@ export { useThreeds } from './hooks/useThreeds';
|
|
|
19
20
|
export { useThreedsModal } from './hooks/useThreedsModal';
|
|
20
21
|
export type { Customer, Session, AuthState, Locale, Currency, Store, Environment, EnvironmentConfig, Order, OrderItem, OrderSummary, OrderAddress, PickupPoint, } from './types';
|
|
21
22
|
export type { UseCheckoutOptions, UseCheckoutResult, CheckoutInitParams, CheckoutLineItem, CheckoutSession, CheckoutData, Promotion, } from './hooks/useCheckout';
|
|
23
|
+
export type { UseOrderBumpOptions, UseOrderBumpResult, OrderBumpPreview } from './hooks/useOrderBump';
|
|
22
24
|
export type { Payment, PollingOptions, PaymentPollingHook } from './hooks/usePaymentPolling';
|
|
23
25
|
export type { PaymentInstrument, ThreedsSession, ThreedsChallenge, ThreedsOptions, ThreedsHook, ThreedsProvider, } from './hooks/useThreeds';
|
|
24
26
|
export type { ApplePayToken, CardPaymentMethod, PaymentResponse, PaymentOptions, PaymentInstrumentResponse, PaymentHook, } from './hooks/usePayment';
|
package/dist/react/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { TagadaProvider } from './providers/TagadaProvider';
|
|
|
8
8
|
export { useCheckout } from './hooks/useCheckout';
|
|
9
9
|
export { useProducts } from './hooks/useProducts';
|
|
10
10
|
export { useOffers } from './hooks/useOffers';
|
|
11
|
+
export { useOrderBump } from './hooks/useOrderBump';
|
|
11
12
|
export { useSession } from './hooks/useSession';
|
|
12
13
|
export { useCurrency } from './hooks/useCurrency';
|
|
13
14
|
export { useCustomer } from './hooks/useCustomer';
|
|
@@ -39,17 +39,11 @@ interface TagadaProviderProps {
|
|
|
39
39
|
children: ReactNode;
|
|
40
40
|
environment?: Environment;
|
|
41
41
|
customApiConfig?: Partial<EnvironmentConfig>;
|
|
42
|
-
developmentMode?: boolean;
|
|
43
42
|
debugMode?: boolean;
|
|
44
43
|
storeId?: string;
|
|
45
44
|
accountId?: string;
|
|
46
|
-
mockData?: {
|
|
47
|
-
customer?: Partial<Customer>;
|
|
48
|
-
session?: Partial<Session>;
|
|
49
|
-
store?: Partial<Store>;
|
|
50
|
-
};
|
|
51
45
|
}
|
|
52
|
-
export declare function TagadaProvider({ children, environment, customApiConfig,
|
|
53
|
-
storeId, accountId,
|
|
46
|
+
export declare function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
|
|
47
|
+
storeId, accountId, }: TagadaProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
54
48
|
export declare function useTagadaContext(): TagadaContextValue;
|
|
55
49
|
export {};
|
|
@@ -29,8 +29,8 @@ const InitializationLoader = () => (_jsx("div", { style: {
|
|
|
29
29
|
}
|
|
30
30
|
` }) }));
|
|
31
31
|
const TagadaContext = createContext(null);
|
|
32
|
-
export function TagadaProvider({ children, environment, customApiConfig,
|
|
33
|
-
storeId, accountId,
|
|
32
|
+
export function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
|
|
33
|
+
storeId, accountId, }) {
|
|
34
34
|
const [isLoading, setIsLoading] = useState(true);
|
|
35
35
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
36
36
|
const [token, setToken] = useState(null);
|
|
@@ -284,49 +284,6 @@ storeId, accountId, mockData, }) {
|
|
|
284
284
|
try {
|
|
285
285
|
console.debug('[SDK] Initializing token...');
|
|
286
286
|
setIsLoading(true);
|
|
287
|
-
if (developmentMode) {
|
|
288
|
-
console.debug('[SDK] Development mode: Using mock data');
|
|
289
|
-
// Use mock data in development mode
|
|
290
|
-
if (mockData?.customer) {
|
|
291
|
-
setCustomer({
|
|
292
|
-
id: 'dev-customer-123',
|
|
293
|
-
email: 'dev@example.com',
|
|
294
|
-
firstName: 'John',
|
|
295
|
-
lastName: 'Doe',
|
|
296
|
-
phone: '+1234567890',
|
|
297
|
-
isAuthenticated: true,
|
|
298
|
-
role: 'authenticated',
|
|
299
|
-
...mockData.customer,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
if (mockData?.session) {
|
|
303
|
-
setSession({
|
|
304
|
-
sessionId: 'dev-session-123',
|
|
305
|
-
storeId: 'dev-store-123',
|
|
306
|
-
accountId: 'dev-account-123',
|
|
307
|
-
customerId: 'dev-customer-123',
|
|
308
|
-
role: 'authenticated',
|
|
309
|
-
isValid: true,
|
|
310
|
-
isLoading: false,
|
|
311
|
-
...mockData.session,
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
if (mockData?.store) {
|
|
315
|
-
setStore({
|
|
316
|
-
id: 'dev-store-123',
|
|
317
|
-
name: 'Development Store',
|
|
318
|
-
domain: 'dev.localhost',
|
|
319
|
-
currency: 'USD',
|
|
320
|
-
locale: 'en-US',
|
|
321
|
-
presentmentCurrencies: ['USD'],
|
|
322
|
-
chargeCurrencies: ['USD'],
|
|
323
|
-
...mockData.store,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
setIsInitialized(true);
|
|
327
|
-
setIsLoading(false);
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
287
|
// Check for existing token
|
|
331
288
|
const existingToken = getClientToken();
|
|
332
289
|
let tokenToUse = null;
|
|
@@ -374,7 +331,7 @@ storeId, accountId, mockData, }) {
|
|
|
374
331
|
}
|
|
375
332
|
};
|
|
376
333
|
void initializeToken();
|
|
377
|
-
}, [
|
|
334
|
+
}, [storeId, createAnonymousToken, initializeSession]);
|
|
378
335
|
// Update auth state when customer/session changes
|
|
379
336
|
useEffect(() => {
|
|
380
337
|
setAuth({
|