@tagadapay/plugin-sdk 2.6.4 → 2.6.6
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/components/GooglePayButton.d.ts +12 -0
- package/dist/react/components/GooglePayButton.js +340 -0
- package/dist/react/components/index.d.ts +3 -2
- package/dist/react/components/index.js +3 -2
- package/dist/react/hooks/useApplePay.js +38 -10
- package/dist/react/hooks/useGoogleAutocomplete.d.ts +2 -0
- package/dist/react/hooks/useGoogleAutocomplete.js +18 -2
- package/dist/react/hooks/useGooglePay.d.ts +22 -0
- package/dist/react/hooks/useGooglePay.js +32 -0
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +3 -1
- package/dist/react/types/apple-pay.d.ts +0 -25
- package/dist/v2/core/googleAutocomplete.d.ts +2 -0
- package/dist/v2/core/googleAutocomplete.js +21 -8
- package/dist/v2/core/resources/checkout.d.ts +70 -2
- package/dist/v2/core/resources/discounts.d.ts +53 -0
- package/dist/v2/core/resources/discounts.js +29 -0
- package/dist/v2/core/resources/expressPaymentMethods.d.ts +56 -0
- package/dist/v2/core/resources/expressPaymentMethods.js +27 -0
- package/dist/v2/core/resources/index.d.ts +7 -4
- package/dist/v2/core/resources/index.js +7 -4
- package/dist/v2/core/resources/shippingRates.d.ts +36 -0
- package/dist/v2/core/resources/shippingRates.js +23 -0
- package/dist/v2/core/resources/vipOffers.d.ts +37 -0
- package/dist/v2/core/resources/vipOffers.js +27 -0
- package/dist/v2/core/utils/order.d.ts +1 -0
- package/dist/v2/core/utils/pluginConfig.d.ts +6 -6
- package/dist/v2/index.d.ts +12 -9
- package/dist/v2/index.js +3 -3
- package/dist/v2/react/components/ApplePayButton.d.ts +141 -0
- package/dist/v2/react/components/ApplePayButton.js +320 -0
- package/dist/v2/react/components/GooglePayButton.d.ts +19 -0
- package/dist/v2/react/components/GooglePayButton.js +355 -0
- package/dist/v2/react/hooks/useApiQuery.d.ts +4 -1
- package/dist/v2/react/hooks/useApiQuery.js +4 -1
- package/dist/v2/react/hooks/useDiscountsQuery.d.ts +30 -0
- package/dist/v2/react/hooks/useDiscountsQuery.js +175 -0
- package/dist/v2/react/hooks/useExpressPaymentMethods.d.ts +12 -0
- package/dist/v2/react/hooks/useExpressPaymentMethods.js +17 -0
- package/dist/v2/react/hooks/useGoogleAutocomplete.d.ts +2 -0
- package/dist/v2/react/hooks/useGoogleAutocomplete.js +18 -2
- package/dist/v2/react/hooks/useShippingRatesQuery.d.ts +22 -0
- package/dist/v2/react/hooks/useShippingRatesQuery.js +134 -0
- package/dist/v2/react/hooks/useVipOffersQuery.d.ts +72 -0
- package/dist/v2/react/hooks/useVipOffersQuery.js +140 -0
- package/dist/v2/react/index.d.ts +30 -17
- package/dist/v2/react/index.js +18 -10
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +59 -0
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +165 -0
- package/package.json +1 -1
|
@@ -150,6 +150,8 @@ export function useGoogleAutocomplete(options) {
|
|
|
150
150
|
locality: '',
|
|
151
151
|
administrativeAreaLevel1: '',
|
|
152
152
|
administrativeAreaLevel1Long: '',
|
|
153
|
+
administrativeAreaLevel2: '',
|
|
154
|
+
administrativeAreaLevel2Long: '',
|
|
153
155
|
country: '',
|
|
154
156
|
postalCode: '',
|
|
155
157
|
};
|
|
@@ -164,8 +166,13 @@ export function useGoogleAutocomplete(options) {
|
|
|
164
166
|
if (types.includes('locality')) {
|
|
165
167
|
extracted.locality = component.long_name;
|
|
166
168
|
}
|
|
167
|
-
if (types.includes('administrative_area_level_2')
|
|
168
|
-
extracted.
|
|
169
|
+
if (types.includes('administrative_area_level_2')) {
|
|
170
|
+
extracted.administrativeAreaLevel2 = component.short_name;
|
|
171
|
+
extracted.administrativeAreaLevel2Long = component.long_name;
|
|
172
|
+
// Use level_2 as fallback for locality if locality is not set
|
|
173
|
+
if (!extracted.locality) {
|
|
174
|
+
extracted.locality = component.long_name;
|
|
175
|
+
}
|
|
169
176
|
}
|
|
170
177
|
if (types.includes('administrative_area_level_1')) {
|
|
171
178
|
extracted.administrativeAreaLevel1 = component.short_name;
|
|
@@ -178,6 +185,15 @@ export function useGoogleAutocomplete(options) {
|
|
|
178
185
|
extracted.postalCode = component.long_name;
|
|
179
186
|
}
|
|
180
187
|
});
|
|
188
|
+
// For countries like France where administrative_area_level_1 (région) may be missing,
|
|
189
|
+
// use administrative_area_level_2 (département) as the primary state/province value
|
|
190
|
+
// We prefer the long_name (e.g., "Bouches-du-Rhône") over short_name (e.g., "13")
|
|
191
|
+
// because it's more likely to match our state database entries
|
|
192
|
+
if (!extracted.administrativeAreaLevel1 && extracted.administrativeAreaLevel2) {
|
|
193
|
+
// Use long name as the primary value (e.g., "Bouches-du-Rhône" instead of "13")
|
|
194
|
+
extracted.administrativeAreaLevel1 = extracted.administrativeAreaLevel2Long || extracted.administrativeAreaLevel2;
|
|
195
|
+
extracted.administrativeAreaLevel1Long = extracted.administrativeAreaLevel2Long;
|
|
196
|
+
}
|
|
181
197
|
return extracted;
|
|
182
198
|
}, []);
|
|
183
199
|
// Clear predictions
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shipping Rates Hook using TanStack Query
|
|
3
|
+
* Simplified shipping rates management with automatic cache invalidation
|
|
4
|
+
*/
|
|
5
|
+
import { CheckoutData } from '../../core/resources/checkout';
|
|
6
|
+
import { ShippingRate } from '../../core/resources/shippingRates';
|
|
7
|
+
export interface UseShippingRatesQueryOptions {
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
checkout?: CheckoutData;
|
|
10
|
+
onSuccess?: () => void;
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface UseShippingRatesQueryResult {
|
|
14
|
+
shippingRates: ShippingRate[] | undefined;
|
|
15
|
+
selectedRate: ShippingRate | undefined;
|
|
16
|
+
selectRate: (rateId: string) => Promise<void>;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
error: Error | null;
|
|
19
|
+
clearError: () => void;
|
|
20
|
+
refetch: () => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare function useShippingRatesQuery(options?: UseShippingRatesQueryOptions): UseShippingRatesQueryResult;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shipping Rates Hook using TanStack Query
|
|
3
|
+
* Simplified shipping rates management with automatic cache invalidation
|
|
4
|
+
*/
|
|
5
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
7
|
+
import { ShippingRatesResource } from '../../core/resources/shippingRates';
|
|
8
|
+
import { getGlobalApiClient } from './useApiQuery';
|
|
9
|
+
export function useShippingRatesQuery(options = {}) {
|
|
10
|
+
const { sessionId, checkout, onSuccess, enabled = true } = options;
|
|
11
|
+
const queryClient = useQueryClient();
|
|
12
|
+
// Create shipping rates resource client
|
|
13
|
+
const shippingRatesResource = useMemo(() => {
|
|
14
|
+
try {
|
|
15
|
+
return new ShippingRatesResource(getGlobalApiClient());
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
throw new Error('Failed to initialize shipping rates resource: ' +
|
|
19
|
+
(error instanceof Error ? error.message : 'Unknown error'));
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
// Use sessionId from options or checkout
|
|
23
|
+
const effectiveSessionId = sessionId || checkout?.checkoutSession?.id;
|
|
24
|
+
// Track if we've synced the initial selection from checkout
|
|
25
|
+
const hasSyncedInitialSelectionRef = useRef(false);
|
|
26
|
+
// Main shipping rates query
|
|
27
|
+
const { data: shippingRatesData, isLoading: isFetching, error: fetchError, refetch: refetchRates, } = useQuery({
|
|
28
|
+
queryKey: ['shipping-rates', effectiveSessionId],
|
|
29
|
+
queryFn: () => shippingRatesResource.getShippingRates(effectiveSessionId),
|
|
30
|
+
enabled: enabled && !!effectiveSessionId,
|
|
31
|
+
staleTime: 30000, // 30 seconds
|
|
32
|
+
refetchOnWindowFocus: false,
|
|
33
|
+
select: (data) => {
|
|
34
|
+
// Order rates: free ones first, then by ascending amount
|
|
35
|
+
const sortedRates = [...data.rates].sort((a, b) => {
|
|
36
|
+
if (a.isFree && !b.isFree)
|
|
37
|
+
return -1;
|
|
38
|
+
if (!a.isFree && b.isFree)
|
|
39
|
+
return 1;
|
|
40
|
+
return (a.amount ?? 0) - (b.amount ?? 0);
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
...data,
|
|
44
|
+
rates: sortedRates,
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
// Get sorted shipping rates from query data
|
|
49
|
+
const shippingRates = shippingRatesData?.rates;
|
|
50
|
+
// Get selected rate from checkout data
|
|
51
|
+
const checkoutSelectedRateId = checkout?.checkoutSession?.shippingRate?.id;
|
|
52
|
+
// Set shipping rate mutation
|
|
53
|
+
const setShippingRateMutation = useMutation({
|
|
54
|
+
mutationFn: ({ rateId }) => {
|
|
55
|
+
if (!effectiveSessionId) {
|
|
56
|
+
throw new Error('No session ID available');
|
|
57
|
+
}
|
|
58
|
+
return shippingRatesResource.setShippingRate(effectiveSessionId, rateId);
|
|
59
|
+
},
|
|
60
|
+
onSuccess: async () => {
|
|
61
|
+
// Invalidate both shipping rates and checkout queries
|
|
62
|
+
if (effectiveSessionId) {
|
|
63
|
+
await Promise.all([
|
|
64
|
+
queryClient.invalidateQueries({ queryKey: ['shipping-rates', effectiveSessionId] }),
|
|
65
|
+
queryClient.invalidateQueries({ queryKey: ['checkout'] }),
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
// Call onSuccess callback if provided
|
|
69
|
+
if (onSuccess) {
|
|
70
|
+
onSuccess();
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
// Select rate function
|
|
75
|
+
const selectRate = useCallback(async (rateId) => {
|
|
76
|
+
await setShippingRateMutation.mutateAsync({ rateId });
|
|
77
|
+
}, [setShippingRateMutation]);
|
|
78
|
+
// Auto-select cheapest rate when:
|
|
79
|
+
// 1. Rates are loaded
|
|
80
|
+
// 2. No rate is currently selected in checkout
|
|
81
|
+
// 3. We haven't already auto-selected
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (shippingRates &&
|
|
84
|
+
shippingRates.length > 0 &&
|
|
85
|
+
!checkoutSelectedRateId &&
|
|
86
|
+
!hasSyncedInitialSelectionRef.current &&
|
|
87
|
+
!setShippingRateMutation.isPending) {
|
|
88
|
+
// Find the cheapest shipping rate
|
|
89
|
+
const cheapestRate = shippingRates.reduce((min, rate) => {
|
|
90
|
+
// Prioritize isFree rates first
|
|
91
|
+
if (rate.isFree && !min.isFree)
|
|
92
|
+
return rate;
|
|
93
|
+
if (!rate.isFree && min.isFree)
|
|
94
|
+
return min;
|
|
95
|
+
// If both are free or both are not free, compare by amount
|
|
96
|
+
return rate.amount < min.amount ? rate : min;
|
|
97
|
+
}, shippingRates[0]);
|
|
98
|
+
console.log('[useShippingRatesQuery] Auto-selecting cheapest rate:', cheapestRate);
|
|
99
|
+
// Mark as synced before making the call to prevent multiple calls
|
|
100
|
+
hasSyncedInitialSelectionRef.current = true;
|
|
101
|
+
// Auto-select the cheapest rate
|
|
102
|
+
void selectRate(cheapestRate.id);
|
|
103
|
+
}
|
|
104
|
+
}, [shippingRates, checkoutSelectedRateId, selectRate, setShippingRateMutation.isPending]);
|
|
105
|
+
// Reset sync flag when session changes
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
hasSyncedInitialSelectionRef.current = false;
|
|
108
|
+
}, [effectiveSessionId]);
|
|
109
|
+
// Find the selected rate from shipping rates based on checkout data
|
|
110
|
+
const selectedRate = useMemo(() => {
|
|
111
|
+
if (!shippingRates || !checkoutSelectedRateId)
|
|
112
|
+
return undefined;
|
|
113
|
+
return shippingRates.find((rate) => rate.id === checkoutSelectedRateId);
|
|
114
|
+
}, [shippingRates, checkoutSelectedRateId]);
|
|
115
|
+
// Refetch function
|
|
116
|
+
const refetch = useCallback(async () => {
|
|
117
|
+
await refetchRates();
|
|
118
|
+
}, [refetchRates]);
|
|
119
|
+
// Clear error function
|
|
120
|
+
const clearError = useCallback(() => {
|
|
121
|
+
// TanStack Query doesn't provide a direct way to clear errors
|
|
122
|
+
// We can trigger a refetch which will clear the error
|
|
123
|
+
void refetch();
|
|
124
|
+
}, [refetch]);
|
|
125
|
+
return {
|
|
126
|
+
shippingRates,
|
|
127
|
+
selectedRate,
|
|
128
|
+
selectRate,
|
|
129
|
+
isLoading: isFetching || setShippingRateMutation.isPending,
|
|
130
|
+
error: (fetchError || setShippingRateMutation.error),
|
|
131
|
+
clearError,
|
|
132
|
+
refetch,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VIP Offers Hook using TanStack Query
|
|
3
|
+
* Simplified VIP offer management with automatic cache invalidation
|
|
4
|
+
*/
|
|
5
|
+
import { VipOffer, VipPreviewResponse } from '../../core/resources/vipOffers';
|
|
6
|
+
export interface UseVipOffersQueryOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Checkout session ID for VIP offers
|
|
9
|
+
*/
|
|
10
|
+
sessionId?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Array of VIP offer IDs to manage
|
|
13
|
+
*/
|
|
14
|
+
vipOfferIds: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Whether to automatically fetch VIP preview on mount
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Callback when VIP offers are selected
|
|
22
|
+
*/
|
|
23
|
+
onSelectSuccess?: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Callback when VIP offers are cancelled
|
|
26
|
+
*/
|
|
27
|
+
onCancelSuccess?: () => void;
|
|
28
|
+
}
|
|
29
|
+
export interface UseVipOffersQueryResult {
|
|
30
|
+
/**
|
|
31
|
+
* Array of VIP offers
|
|
32
|
+
*/
|
|
33
|
+
vipOffers: VipOffer[];
|
|
34
|
+
/**
|
|
35
|
+
* VIP preview data including savings and selected offers
|
|
36
|
+
*/
|
|
37
|
+
vipPreview: VipPreviewResponse | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Loading state for VIP preview
|
|
40
|
+
*/
|
|
41
|
+
isLoadingVipPreview: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether any VIP offers are currently selected
|
|
44
|
+
*/
|
|
45
|
+
hasVip: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Check if a specific VIP offer is selected
|
|
48
|
+
*/
|
|
49
|
+
isOfferSelected: (offer: VipOffer) => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Select all VIP offers
|
|
52
|
+
*/
|
|
53
|
+
selectVipOffers: () => Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Cancel/deselect all VIP offers
|
|
56
|
+
*/
|
|
57
|
+
cancelVipOffers: () => Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Refresh VIP preview data
|
|
60
|
+
*/
|
|
61
|
+
refreshVipPreview: () => Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Loading state for select/cancel operations
|
|
64
|
+
*/
|
|
65
|
+
isSelecting: boolean;
|
|
66
|
+
isCanceling: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Error state
|
|
69
|
+
*/
|
|
70
|
+
error: Error | null;
|
|
71
|
+
}
|
|
72
|
+
export declare function useVipOffersQuery(options: UseVipOffersQueryOptions): UseVipOffersQueryResult;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VIP Offers Hook using TanStack Query
|
|
3
|
+
* Simplified VIP offer management with automatic cache invalidation
|
|
4
|
+
*/
|
|
5
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
6
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
7
|
+
import { VipOffersResource } from '../../core/resources/vipOffers';
|
|
8
|
+
import { getGlobalApiClient } from './useApiQuery';
|
|
9
|
+
export function useVipOffersQuery(options) {
|
|
10
|
+
const { sessionId, vipOfferIds, enabled = true, onSelectSuccess, onCancelSuccess } = options;
|
|
11
|
+
const queryClient = useQueryClient();
|
|
12
|
+
// Create VIP offers resource client
|
|
13
|
+
const vipOffersResource = useMemo(() => {
|
|
14
|
+
try {
|
|
15
|
+
return new VipOffersResource(getGlobalApiClient());
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
throw new Error('Failed to initialize VIP offers resource: ' +
|
|
19
|
+
(error instanceof Error ? error.message : 'Unknown error'));
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
// Convert offer IDs to VipOffer objects
|
|
23
|
+
const vipOffers = useMemo(() => {
|
|
24
|
+
return vipOfferIds.map((id) => ({
|
|
25
|
+
id,
|
|
26
|
+
productId: '', // These will be populated from preview data
|
|
27
|
+
variantId: '', // These will be populated from preview data
|
|
28
|
+
}));
|
|
29
|
+
}, [vipOfferIds]);
|
|
30
|
+
// Main VIP preview query
|
|
31
|
+
const { data: vipPreview, isLoading: isLoadingVipPreview, error: fetchError, refetch: refetchPreview, } = useQuery({
|
|
32
|
+
queryKey: ['vip-preview', sessionId, vipOfferIds],
|
|
33
|
+
queryFn: () => vipOffersResource.getVipPreview(sessionId, vipOfferIds),
|
|
34
|
+
enabled: enabled && !!sessionId && vipOfferIds.length > 0,
|
|
35
|
+
staleTime: 30000, // 30 seconds
|
|
36
|
+
refetchOnWindowFocus: false,
|
|
37
|
+
});
|
|
38
|
+
// Check if a specific VIP offer is selected
|
|
39
|
+
const isOfferSelected = useCallback((offer) => {
|
|
40
|
+
if (!vipPreview?.selectedOffers)
|
|
41
|
+
return false;
|
|
42
|
+
return vipPreview.selectedOffers.some((selected) => selected.productId === offer.productId &&
|
|
43
|
+
selected.variantId === offer.variantId &&
|
|
44
|
+
selected.isSelected);
|
|
45
|
+
}, [vipPreview?.selectedOffers]);
|
|
46
|
+
// Calculate hasVip based on selected offers
|
|
47
|
+
const hasVip = useMemo(() => {
|
|
48
|
+
return vipPreview?.selectedOffers?.some((offer) => offer.isSelected) ?? false;
|
|
49
|
+
}, [vipPreview?.selectedOffers]);
|
|
50
|
+
// Toggle order bump mutation
|
|
51
|
+
const toggleMutation = useMutation({
|
|
52
|
+
mutationFn: ({ offerId, selected }) => {
|
|
53
|
+
if (!sessionId) {
|
|
54
|
+
throw new Error('No session ID available');
|
|
55
|
+
}
|
|
56
|
+
return vipOffersResource.toggleOrderBump(sessionId, offerId, selected);
|
|
57
|
+
},
|
|
58
|
+
onSuccess: async () => {
|
|
59
|
+
// Invalidate both VIP preview and checkout queries
|
|
60
|
+
if (sessionId) {
|
|
61
|
+
await Promise.all([
|
|
62
|
+
queryClient.invalidateQueries({ queryKey: ['vip-preview', sessionId] }),
|
|
63
|
+
queryClient.invalidateQueries({ queryKey: ['checkout'] }),
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
// Track operation states
|
|
69
|
+
const [isSelecting, setIsSelecting] = useState(false);
|
|
70
|
+
const [isCanceling, setIsCanceling] = useState(false);
|
|
71
|
+
// Select all VIP offers
|
|
72
|
+
const selectVipOffers = useCallback(async () => {
|
|
73
|
+
if (!sessionId)
|
|
74
|
+
return;
|
|
75
|
+
setIsSelecting(true);
|
|
76
|
+
try {
|
|
77
|
+
// Toggle all offers that aren't already selected
|
|
78
|
+
const togglePromises = vipOffers
|
|
79
|
+
.filter((offer) => !isOfferSelected(offer))
|
|
80
|
+
.map((offer) => toggleMutation.mutateAsync({ offerId: offer.id, selected: true }));
|
|
81
|
+
await Promise.all(togglePromises);
|
|
82
|
+
// Refresh preview to get updated data
|
|
83
|
+
await refetchPreview();
|
|
84
|
+
// Call success callback
|
|
85
|
+
if (onSelectSuccess) {
|
|
86
|
+
onSelectSuccess();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error('Failed to select VIP offers:', error);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
setIsSelecting(false);
|
|
95
|
+
}
|
|
96
|
+
}, [sessionId, vipOffers, isOfferSelected, toggleMutation, refetchPreview, onSelectSuccess]);
|
|
97
|
+
// Cancel all VIP offers
|
|
98
|
+
const cancelVipOffers = useCallback(async () => {
|
|
99
|
+
if (!sessionId)
|
|
100
|
+
return;
|
|
101
|
+
setIsCanceling(true);
|
|
102
|
+
try {
|
|
103
|
+
// Toggle all offers to deselected
|
|
104
|
+
const togglePromises = vipOffers.map((offer) => toggleMutation.mutateAsync({ offerId: offer.id, selected: false }));
|
|
105
|
+
await Promise.all(togglePromises);
|
|
106
|
+
// Refresh preview to get updated data
|
|
107
|
+
await refetchPreview();
|
|
108
|
+
// Call success callback
|
|
109
|
+
if (onCancelSuccess) {
|
|
110
|
+
onCancelSuccess();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.error('Failed to cancel VIP offers:', error);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
setIsCanceling(false);
|
|
119
|
+
}
|
|
120
|
+
}, [sessionId, vipOffers, toggleMutation, refetchPreview, onCancelSuccess]);
|
|
121
|
+
// Refresh VIP preview
|
|
122
|
+
const refreshVipPreview = useCallback(async () => {
|
|
123
|
+
await refetchPreview();
|
|
124
|
+
}, [refetchPreview]);
|
|
125
|
+
// Combine errors
|
|
126
|
+
const error = (fetchError || toggleMutation.error);
|
|
127
|
+
return {
|
|
128
|
+
vipOffers,
|
|
129
|
+
vipPreview,
|
|
130
|
+
isLoadingVipPreview,
|
|
131
|
+
hasVip,
|
|
132
|
+
isOfferSelected,
|
|
133
|
+
selectVipOffers,
|
|
134
|
+
cancelVipOffers,
|
|
135
|
+
refreshVipPreview,
|
|
136
|
+
isSelecting,
|
|
137
|
+
isCanceling,
|
|
138
|
+
error,
|
|
139
|
+
};
|
|
140
|
+
}
|
package/dist/v2/react/index.d.ts
CHANGED
|
@@ -2,37 +2,50 @@
|
|
|
2
2
|
* React hooks and components for TagadaPay Plugin SDK v2
|
|
3
3
|
* Uses core functions for business logic
|
|
4
4
|
*/
|
|
5
|
+
export { ExpressPaymentMethodsProvider } from './providers/ExpressPaymentMethodsProvider';
|
|
5
6
|
export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
|
|
7
|
+
export { ApplePayButton } from './components/ApplePayButton';
|
|
8
|
+
export { GooglePayButton } from './components/GooglePayButton';
|
|
6
9
|
export { useCheckoutToken } from './hooks/useCheckoutToken';
|
|
7
|
-
export {
|
|
8
|
-
export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
|
|
10
|
+
export { useExpressPaymentMethods } from './hooks/useExpressPaymentMethods';
|
|
9
11
|
export { useGeoLocation } from './hooks/useGeoLocation';
|
|
10
|
-
export {
|
|
12
|
+
export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
|
|
13
|
+
export { getAvailableLanguages, useCountryOptions, useISOData, useLanguageImport, useRegionOptions } from './hooks/useISOData';
|
|
14
|
+
export { usePluginConfig } from './hooks/usePluginConfig';
|
|
15
|
+
export { queryKeys, useApiMutation, useApiQuery, useInvalidateQuery, usePreloadQuery } from './hooks/useApiQuery';
|
|
11
16
|
export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
|
|
17
|
+
export { useCurrency } from './hooks/useCurrency';
|
|
18
|
+
export { useDiscountsQuery as useDiscounts } from './hooks/useDiscountsQuery';
|
|
19
|
+
export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
|
|
12
20
|
export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
|
|
13
|
-
export { usePromotionsQuery as usePromotions } from './hooks/usePromotionsQuery';
|
|
14
|
-
export { useProductsQuery as useProducts } from './hooks/useProductsQuery';
|
|
15
21
|
export { useOrderQuery as useOrder } from './hooks/useOrderQuery';
|
|
16
|
-
export { usePostPurchasesQuery as usePostPurchases } from './hooks/usePostPurchasesQuery';
|
|
17
|
-
export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
|
|
18
22
|
export { usePaymentQuery as usePayment } from './hooks/usePaymentQuery';
|
|
23
|
+
export { usePostPurchasesQuery as usePostPurchases } from './hooks/usePostPurchasesQuery';
|
|
24
|
+
export { useProductsQuery as useProducts } from './hooks/useProductsQuery';
|
|
25
|
+
export { usePromotionsQuery as usePromotions } from './hooks/usePromotionsQuery';
|
|
26
|
+
export { useShippingRatesQuery as useShippingRates } from './hooks/useShippingRatesQuery';
|
|
19
27
|
export { useThreeds } from './hooks/useThreeds';
|
|
20
28
|
export { useThreedsModal } from './hooks/useThreedsModal';
|
|
21
|
-
export {
|
|
22
|
-
export { useApiQuery, useApiMutation, useInvalidateQuery, usePreloadQuery, queryKeys } from './hooks/useApiQuery';
|
|
29
|
+
export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
|
|
23
30
|
export type { UseCheckoutTokenOptions, UseCheckoutTokenResult } from './hooks/useCheckoutToken';
|
|
31
|
+
export type { ExpressPaymentMethodsContextType, ExpressPaymentMethodsProviderProps } from './hooks/useExpressPaymentMethods';
|
|
32
|
+
export type { ApplePayButtonProps } from './components/ApplePayButton';
|
|
33
|
+
export type { GooglePayButtonProps } from './components/GooglePayButton';
|
|
34
|
+
export type { GeoLocationData, UseGeoLocationOptions, UseGeoLocationReturn } from './hooks/useGeoLocation';
|
|
35
|
+
export type { ExtractedAddress, GooglePlaceDetails, GooglePrediction, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
|
|
36
|
+
export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
|
|
24
37
|
export type { UsePluginConfigOptions, UsePluginConfigResult } from './hooks/usePluginConfig';
|
|
25
|
-
export type { UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult, GooglePrediction, GooglePlaceDetails, ExtractedAddress } from './hooks/useGoogleAutocomplete';
|
|
26
|
-
export type { UseGeoLocationOptions, UseGeoLocationReturn, GeoLocationData } from './hooks/useGeoLocation';
|
|
27
|
-
export type { UseISODataResult, ISOCountry, ISORegion } from './hooks/useISOData';
|
|
28
38
|
export type { UseCheckoutQueryOptions as UseCheckoutOptions, UseCheckoutQueryResult as UseCheckoutResult } from './hooks/useCheckoutQuery';
|
|
39
|
+
export type { UseDiscountsQueryOptions as UseDiscountsOptions, UseDiscountsQueryResult as UseDiscountsResult } from './hooks/useDiscountsQuery';
|
|
40
|
+
export type { UseOffersQueryOptions as UseOffersOptions, UseOffersQueryResult as UseOffersResult } from './hooks/useOffersQuery';
|
|
29
41
|
export type { UseOrderBumpQueryOptions as UseOrderBumpOptions, UseOrderBumpQueryResult as UseOrderBumpResult } from './hooks/useOrderBumpQuery';
|
|
30
|
-
export type { UsePromotionsQueryOptions as UsePromotionsOptions, UsePromotionsQueryResult as UsePromotionsResult } from './hooks/usePromotionsQuery';
|
|
31
|
-
export type { UseProductsQueryOptions as UseProductsOptions, UseProductsQueryResult as UseProductsResult } from './hooks/useProductsQuery';
|
|
32
42
|
export type { UseOrderQueryOptions as UseOrderOptions, UseOrderQueryResult as UseOrderResult } from './hooks/useOrderQuery';
|
|
33
|
-
export type { UsePostPurchasesQueryOptions as UsePostPurchasesOptions, UsePostPurchasesQueryResult as UsePostPurchasesResult } from './hooks/usePostPurchasesQuery';
|
|
34
|
-
export type { UseOffersQueryOptions as UseOffersOptions, UseOffersQueryResult as UseOffersResult } from './hooks/useOffersQuery';
|
|
35
43
|
export type { PaymentHook as UsePaymentResult } from './hooks/usePaymentQuery';
|
|
36
|
-
export type {
|
|
44
|
+
export type { UsePostPurchasesQueryOptions as UsePostPurchasesOptions, UsePostPurchasesQueryResult as UsePostPurchasesResult } from './hooks/usePostPurchasesQuery';
|
|
45
|
+
export type { UseProductsQueryOptions as UseProductsOptions, UseProductsQueryResult as UseProductsResult } from './hooks/useProductsQuery';
|
|
46
|
+
export type { UsePromotionsQueryOptions as UsePromotionsOptions, UsePromotionsQueryResult as UsePromotionsResult } from './hooks/usePromotionsQuery';
|
|
47
|
+
export type { UseShippingRatesQueryOptions as UseShippingRatesOptions, UseShippingRatesQueryResult as UseShippingRatesResult } from './hooks/useShippingRatesQuery';
|
|
48
|
+
export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
|
|
49
|
+
export type { UseVipOffersQueryOptions as UseVipOffersOptions, UseVipOffersQueryResult as UseVipOffersResult } from './hooks/useVipOffersQuery';
|
|
37
50
|
export { formatMoney } from '../../react/utils/money';
|
|
38
51
|
export type OrderItem = import('../core/utils/order').OrderLineItem;
|
package/dist/v2/react/index.js
CHANGED
|
@@ -2,26 +2,34 @@
|
|
|
2
2
|
* React hooks and components for TagadaPay Plugin SDK v2
|
|
3
3
|
* Uses core functions for business logic
|
|
4
4
|
*/
|
|
5
|
-
//
|
|
5
|
+
// Providers
|
|
6
|
+
export { ExpressPaymentMethodsProvider } from './providers/ExpressPaymentMethodsProvider';
|
|
6
7
|
export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
|
|
8
|
+
// Components
|
|
9
|
+
export { ApplePayButton } from './components/ApplePayButton';
|
|
10
|
+
export { GooglePayButton } from './components/GooglePayButton';
|
|
7
11
|
// Hooks
|
|
8
12
|
export { useCheckoutToken } from './hooks/useCheckoutToken';
|
|
9
|
-
export {
|
|
10
|
-
export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
|
|
13
|
+
export { useExpressPaymentMethods } from './hooks/useExpressPaymentMethods';
|
|
11
14
|
export { useGeoLocation } from './hooks/useGeoLocation';
|
|
12
|
-
export {
|
|
15
|
+
export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
|
|
16
|
+
export { getAvailableLanguages, useCountryOptions, useISOData, useLanguageImport, useRegionOptions } from './hooks/useISOData';
|
|
17
|
+
export { usePluginConfig } from './hooks/usePluginConfig';
|
|
13
18
|
// TanStack Query hooks (recommended)
|
|
19
|
+
export { queryKeys, useApiMutation, useApiQuery, useInvalidateQuery, usePreloadQuery } from './hooks/useApiQuery';
|
|
14
20
|
export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
|
|
21
|
+
export { useCurrency } from './hooks/useCurrency';
|
|
22
|
+
export { useDiscountsQuery as useDiscounts } from './hooks/useDiscountsQuery';
|
|
23
|
+
export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
|
|
15
24
|
export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
|
|
16
|
-
export { usePromotionsQuery as usePromotions } from './hooks/usePromotionsQuery';
|
|
17
|
-
export { useProductsQuery as useProducts } from './hooks/useProductsQuery';
|
|
18
25
|
export { useOrderQuery as useOrder } from './hooks/useOrderQuery';
|
|
19
|
-
export { usePostPurchasesQuery as usePostPurchases } from './hooks/usePostPurchasesQuery';
|
|
20
|
-
export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
|
|
21
26
|
export { usePaymentQuery as usePayment } from './hooks/usePaymentQuery';
|
|
27
|
+
export { usePostPurchasesQuery as usePostPurchases } from './hooks/usePostPurchasesQuery';
|
|
28
|
+
export { useProductsQuery as useProducts } from './hooks/useProductsQuery';
|
|
29
|
+
export { usePromotionsQuery as usePromotions } from './hooks/usePromotionsQuery';
|
|
30
|
+
export { useShippingRatesQuery as useShippingRates } from './hooks/useShippingRatesQuery';
|
|
22
31
|
export { useThreeds } from './hooks/useThreeds';
|
|
23
32
|
export { useThreedsModal } from './hooks/useThreedsModal';
|
|
24
|
-
export {
|
|
25
|
-
export { useApiQuery, useApiMutation, useInvalidateQuery, usePreloadQuery, queryKeys } from './hooks/useApiQuery';
|
|
33
|
+
export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
|
|
26
34
|
// Re-export utilities from main react
|
|
27
35
|
export { formatMoney } from '../../react/utils/money';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express Payment Methods Context Provider using v2 Architecture
|
|
3
|
+
* Manages express payment methods (Apple Pay, Google Pay, PayPal, Klarna)
|
|
4
|
+
*/
|
|
5
|
+
import React, { ReactNode } from 'react';
|
|
6
|
+
import { CheckoutData } from '../../core/resources/checkout';
|
|
7
|
+
import { Address, PaymentMethod } from '../../core/resources/expressPaymentMethods';
|
|
8
|
+
type ExpressOrderLineItem = {
|
|
9
|
+
label: string;
|
|
10
|
+
amount: string;
|
|
11
|
+
};
|
|
12
|
+
type ExpressShippingMethod = {
|
|
13
|
+
label: string;
|
|
14
|
+
amount: string;
|
|
15
|
+
identifier: string;
|
|
16
|
+
detail: string;
|
|
17
|
+
};
|
|
18
|
+
interface ExpressPaymentMethodsContextType {
|
|
19
|
+
paymentMethods: PaymentMethod[] | undefined;
|
|
20
|
+
applePayPaymentMethod?: PaymentMethod;
|
|
21
|
+
googlePayPaymentMethod?: PaymentMethod;
|
|
22
|
+
paypalPaymentMethod?: PaymentMethod;
|
|
23
|
+
klarnaPaymentMethod?: PaymentMethod;
|
|
24
|
+
availableExpressPaymentMethodIds: string[];
|
|
25
|
+
setAvailableExpressPaymentMethodIds: (value: string[]) => void;
|
|
26
|
+
handleAddExpressId: (id: string) => void;
|
|
27
|
+
shippingMethods: ExpressShippingMethod[];
|
|
28
|
+
lineItems: ExpressOrderLineItem[];
|
|
29
|
+
reComputeOrderSummary: () => Promise<{
|
|
30
|
+
lineItems: ExpressOrderLineItem[];
|
|
31
|
+
total: {
|
|
32
|
+
label: string;
|
|
33
|
+
amount: string;
|
|
34
|
+
};
|
|
35
|
+
shippingMethods: ExpressShippingMethod[];
|
|
36
|
+
} | undefined>;
|
|
37
|
+
updateCheckoutSessionValues: (input: {
|
|
38
|
+
data: {
|
|
39
|
+
shippingAddress: Address;
|
|
40
|
+
billingAddress?: Address | null;
|
|
41
|
+
};
|
|
42
|
+
}) => Promise<void>;
|
|
43
|
+
updateCustomerEmail: (input: {
|
|
44
|
+
data: {
|
|
45
|
+
email: string;
|
|
46
|
+
};
|
|
47
|
+
}) => Promise<void>;
|
|
48
|
+
loading?: boolean;
|
|
49
|
+
error: string | null;
|
|
50
|
+
setError: (error: string | null) => void;
|
|
51
|
+
}
|
|
52
|
+
interface ExpressPaymentMethodsProviderProps {
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
customerId?: string;
|
|
55
|
+
checkout?: CheckoutData;
|
|
56
|
+
}
|
|
57
|
+
export declare const ExpressPaymentMethodsContext: React.Context<ExpressPaymentMethodsContextType | undefined>;
|
|
58
|
+
export declare const ExpressPaymentMethodsProvider: React.FC<ExpressPaymentMethodsProviderProps>;
|
|
59
|
+
export type { ExpressPaymentMethodsContextType, ExpressPaymentMethodsProviderProps };
|