@tagadapay/plugin-sdk 2.7.20 → 2.7.21

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.
@@ -95,13 +95,32 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
95
95
  { id: 'session', label: 'Session' },
96
96
  { id: 'auth', label: 'Auth' },
97
97
  ];
98
+ // Add funnel tab if funnel is active
99
+ const funnelTab = context.debugFunnel.isActive ? [{ id: 'funnel', label: 'Funnel' }] : [];
100
+ // Debug: Log comprehensive debug drawer state
101
+ if (isOpen) {
102
+ console.group('🐛 [DebugDrawer] Comprehensive State Check');
103
+ console.log('1️⃣ Debug Mode:', context.debugMode);
104
+ console.log('2️⃣ Funnel Debug State:', {
105
+ isActive: context.debugFunnel.isActive,
106
+ hasData: !!context.debugFunnel.data,
107
+ hasError: !!context.debugFunnel.error,
108
+ isLoading: context.debugFunnel.isLoading,
109
+ lastUpdated: context.debugFunnel.lastUpdated,
110
+ });
111
+ console.log('3️⃣ Funnel Data (if any):', context.debugFunnel.data);
112
+ console.log('4️⃣ Funnel Error (if any):', context.debugFunnel.error);
113
+ console.log('5️⃣ Update Function Available:', typeof context.updateFunnelDebugData);
114
+ console.log('6️⃣ Will show Funnel tab:', funnelTab.length > 0);
115
+ console.groupEnd();
116
+ }
98
117
  // Add checkout tab if checkout is active
99
118
  const checkoutTab = context.debugCheckout.isActive ? [{ id: 'checkout', label: 'Checkout' }] : [];
100
119
  // Add items tab if checkout has summary data
101
120
  const itemsTab = context.debugCheckout.isActive && context.debugCheckout.data?.checkout?.summary
102
121
  ? [{ id: 'items', label: 'Items' }]
103
122
  : [];
104
- const tabs = [...baseTabs, ...checkoutTab, ...itemsTab, { id: 'raw', label: 'Raw Data' }];
123
+ const tabs = [...baseTabs, ...funnelTab, ...checkoutTab, ...itemsTab, { id: 'raw', label: 'Raw Data' }];
105
124
  return (_jsxs(_Fragment, { children: [_jsx("div", { style: {
106
125
  position: 'fixed',
107
126
  top: 0,
@@ -169,7 +188,66 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
169
188
  border: '1px solid #374151',
170
189
  borderRadius: '6px',
171
190
  marginTop: '16px',
172
- }, children: [_jsx("h4", { style: { margin: '0 0 8px 0', color: '#f59e0b', fontSize: '14px' }, children: "Development Mode" }), _jsxs("p", { style: { margin: '0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Configuration is loaded from ", _jsx("code", { style: { color: '#60a5fa' }, children: "/.local.json" }), " and", ' ', _jsxs("code", { style: { color: '#60a5fa' }, children: ["/config/", pluginConfig.config?.configName || 'default', ".tgd.json"] })] }), _jsxs("p", { style: { margin: '8px 0 0 0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Local config variant:", ' ', _jsx("code", { style: { color: '#f59e0b' }, children: pluginConfig.config?.configName || 'default' })] })] }))] })), activeTab === 'store' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Store Configuration" }), context.store ? (_jsx(TreeView, { data: context.store, name: "store" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No store data available" }))] })), activeTab === 'session' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Session Data" }), context.session ? (_jsx(TreeView, { data: context.session, name: "session" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No session data available" }))] })), activeTab === 'auth' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Authentication State" }), _jsx(TreeView, { data: context.auth, name: "auth" }), context.customer && (_jsxs(_Fragment, { children: [_jsx("h4", { style: { margin: '24px 0 12px 0', color: '#60a5fa' }, children: "Customer Data" }), _jsx(TreeView, { data: context.customer, name: "customer" })] }))] })), activeTab === 'items' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Items & Discounts" }), context.debugCheckout.data?.checkout?.summary ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Summary" }), _jsxs("div", { style: { display: 'grid', gap: '8px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Currency:" }), _jsx("span", { style: { color: '#f59e0b' }, children: context.debugCheckout.data.checkout.summary.currency })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Subtotal:" }), _jsx("span", { style: { color: '#9ca3af' }, children: (() => {
191
+ }, children: [_jsx("h4", { style: { margin: '0 0 8px 0', color: '#f59e0b', fontSize: '14px' }, children: "Development Mode" }), _jsxs("p", { style: { margin: '0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Configuration is loaded from ", _jsx("code", { style: { color: '#60a5fa' }, children: "/.local.json" }), " and", ' ', _jsxs("code", { style: { color: '#60a5fa' }, children: ["/config/", pluginConfig.config?.configName || 'default', ".tgd.json"] })] }), _jsxs("p", { style: { margin: '8px 0 0 0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Local config variant:", ' ', _jsx("code", { style: { color: '#f59e0b' }, children: pluginConfig.config?.configName || 'default' })] })] }))] })), activeTab === 'store' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Store Configuration" }), context.store ? (_jsx(TreeView, { data: context.store, name: "store" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No store data available" }))] })), activeTab === 'session' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Session Data" }), context.session ? (_jsx(TreeView, { data: context.session, name: "session" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No session data available" }))] })), activeTab === 'auth' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Authentication State" }), _jsx(TreeView, { data: context.auth, name: "auth" }), context.customer && (_jsxs(_Fragment, { children: [_jsx("h4", { style: { margin: '24px 0 12px 0', color: '#60a5fa' }, children: "Customer Data" }), _jsx(TreeView, { data: context.customer, name: "customer" })] }))] })), activeTab === 'funnel' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Funnel Navigation" }), context.debugFunnel.isActive && context.debugFunnel.data ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Current Funnel" }), _jsxs("div", { style: { display: 'grid', gap: '8px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Funnel Name:" }), _jsx("span", { style: { color: '#10b981', fontWeight: 'bold' }, children: context.debugFunnel.data.funnel?.name || 'Unknown' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Funnel ID:" }), _jsx("span", { style: { color: '#60a5fa', fontSize: '12px' }, children: context.debugFunnel.data.funnel?.id || 'N/A' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Total Steps:" }), _jsx("span", { style: { color: '#f59e0b' }, children: context.debugFunnel.data.funnel?.steps?.length || 0 })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Visited Steps:" }), _jsx("span", { style: { color: '#8b5cf6' }, children: context.debugFunnel.data.session?.totalStepsVisited || 0 })] }), context.debugFunnel.data.session?.cycleDetected && (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Cycle Detected:" }), _jsx("span", { style: { color: '#ef4444', fontWeight: 'bold' }, children: "\u26A0\uFE0F Yes" })] }))] })] }), context.debugFunnel.data.funnel?.steps && (_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsxs("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: ["Funnel Steps (", context.debugFunnel.data.funnel.steps.length, ")"] }), _jsx("div", { style: { display: 'grid', gap: '12px' }, children: context.debugFunnel.data.funnel.steps.map((step, index) => {
192
+ // Get current step ID from debug funnel data
193
+ const currentStepId = context.debugFunnel.data.session?.currentStepId;
194
+ // Determine if this is the current step
195
+ const isCurrent = step.id === currentStepId;
196
+ // Determine if this step was visited
197
+ const wasVisited = context.debugFunnel.data.session?.visitedSteps?.includes(step.id);
198
+ return (_jsxs("div", { style: {
199
+ border: isCurrent ? '2px solid #10b981' : '1px solid #374151',
200
+ borderRadius: '8px',
201
+ padding: '12px',
202
+ backgroundColor: isCurrent ? '#064e3b' : '#111827',
203
+ position: 'relative',
204
+ }, children: [isCurrent && (_jsx("div", { style: {
205
+ position: 'absolute',
206
+ top: '8px',
207
+ right: '8px',
208
+ backgroundColor: '#10b981',
209
+ color: '#000',
210
+ padding: '2px 8px',
211
+ borderRadius: '4px',
212
+ fontSize: '10px',
213
+ fontWeight: 'bold',
214
+ }, children: "CURRENT" })), wasVisited && !isCurrent && (_jsx("div", { style: {
215
+ position: 'absolute',
216
+ top: '8px',
217
+ right: '8px',
218
+ backgroundColor: '#8b5cf6',
219
+ color: '#fff',
220
+ padding: '2px 8px',
221
+ borderRadius: '4px',
222
+ fontSize: '10px',
223
+ fontWeight: 'bold',
224
+ }, children: "VISITED" })), _jsxs("div", { style: {
225
+ marginBottom: '8px',
226
+ marginRight: wasVisited || isCurrent ? '80px' : '0',
227
+ }, children: [_jsxs("div", { style: {
228
+ color: isCurrent ? '#6ee7b7' : '#f9fafb',
229
+ fontWeight: 'bold',
230
+ marginBottom: '4px',
231
+ fontSize: '14px',
232
+ }, children: [step.name || `Step ${index + 1}`, step.isEntry && (_jsx("span", { style: {
233
+ marginLeft: '8px',
234
+ fontSize: '10px',
235
+ backgroundColor: '#3b82f6',
236
+ color: '#fff',
237
+ padding: '2px 6px',
238
+ borderRadius: '4px',
239
+ }, children: "ENTRY" }))] }), _jsxs("div", { style: { fontSize: '11px', color: '#9ca3af' }, children: ["Type: ", step.type, " \u2022 Index: ", step.index, step.row !== undefined && ` • Row: ${step.row}`] }), step.url && (_jsxs("div", { style: { fontSize: '11px', color: '#60a5fa', marginTop: '4px' }, children: ["URL: ", step.url] }))] }), step.conditions && (_jsxs("div", { style: {
240
+ backgroundColor: '#1f2937',
241
+ padding: '8px',
242
+ borderRadius: '4px',
243
+ marginTop: '8px',
244
+ }, children: [_jsx("div", { style: {
245
+ fontSize: '10px',
246
+ color: '#60a5fa',
247
+ fontWeight: 'bold',
248
+ marginBottom: '4px',
249
+ }, children: "Conditions:" }), _jsx(TreeView, { data: step.conditions, name: "conditions", maxLevel: 2 })] })), _jsxs("div", { style: { fontSize: '9px', color: '#6b7280', marginTop: '8px' }, children: ["ID: ", step.id] })] }, step.id || index));
250
+ }) })] })), _jsxs("div", { children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Full Funnel Data" }), _jsx(TreeView, { data: context.debugFunnel.data, name: "funnelDebugData", maxLevel: 3 })] })] })) : (_jsxs("p", { style: { color: '#6b7280' }, children: ["No funnel data available. Use the ", _jsx("code", { children: "useFunnel" }), " hook to activate funnel tracking."] }))] })), activeTab === 'items' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Items & Discounts" }), context.debugCheckout.data?.checkout?.summary ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Summary" }), _jsxs("div", { style: { display: 'grid', gap: '8px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Currency:" }), _jsx("span", { style: { color: '#f59e0b' }, children: context.debugCheckout.data.checkout.summary.currency })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Subtotal:" }), _jsx("span", { style: { color: '#9ca3af' }, children: (() => {
173
251
  try {
174
252
  return context.money.formatMoney(Number(context.debugCheckout.data.checkout.summary.subtotalAmount) || 0, String(context.debugCheckout.data.checkout.summary.currency) || 'USD', context.locale.locale);
175
253
  }
@@ -1,8 +1,91 @@
1
- export interface FunnelEvent {
2
- type: string;
3
- data?: any;
1
+ /**
2
+ * Funnel event types enum
3
+ *
4
+ * Special types:
5
+ * - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
6
+ * - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
7
+ *
8
+ * Common types (for logging/tracking):
9
+ * - Any string value is accepted, but these are commonly used examples
10
+ */
11
+ export declare enum FunnelEventType {
12
+ DIRECT_NAVIGATION = "direct_navigation",
13
+ BACK_NAVIGATION = "back_navigation",
14
+ PAYMENT_SUCCESS = "payment_success",
15
+ CUSTOM = "custom"
16
+ }
17
+ /**
18
+ * Data structures for specific event types
19
+ */
20
+ export type NextEvent<T> = T & {
21
+ [key: string]: any;
22
+ };
23
+ export interface DirectNavigationEventData {
24
+ targetStepId: string;
25
+ }
26
+ export interface BackNavigationEventData {
27
+ targetStepId: string;
28
+ }
29
+ export interface QuizCompletedEventData {
30
+ quiz: {
31
+ score: number;
32
+ [key: string]: any;
33
+ };
34
+ }
35
+ export interface OfferAcceptedEventData {
36
+ offer: {
37
+ accepted: boolean;
38
+ offerId?: string;
39
+ [key: string]: any;
40
+ };
41
+ }
42
+ export interface FormSubmitEventData {
43
+ [key: string]: any;
44
+ }
45
+ export interface PaymentSuccessEventData {
46
+ payment?: {
47
+ status: 'success';
48
+ amount: number;
49
+ currency: string;
50
+ orderId?: string;
51
+ transactionId?: string;
52
+ timestamp?: string;
53
+ [key: string]: any;
54
+ };
55
+ order?: {
56
+ id: string;
57
+ amount: number;
58
+ currency: string;
59
+ [key: string]: any;
60
+ };
61
+ paymentId?: string;
62
+ [key: string]: any;
63
+ }
64
+ /**
65
+ * Base properties shared by all FunnelEvent types
66
+ */
67
+ interface BaseFunnelEvent {
68
+ /**
69
+ * Event timestamp
70
+ */
4
71
  timestamp?: Date;
5
72
  }
73
+ /**
74
+ * Discriminated union for FunnelEvent based on event type
75
+ */
76
+ export type FunnelEvent = BaseFunnelEvent & (({
77
+ type: FunnelEventType.DIRECT_NAVIGATION;
78
+ data: NextEvent<DirectNavigationEventData>;
79
+ }) | ({
80
+ type: FunnelEventType.BACK_NAVIGATION;
81
+ data: NextEvent<BackNavigationEventData>;
82
+ }) | ({
83
+ type: FunnelEventType.PAYMENT_SUCCESS;
84
+ data?: NextEvent<PaymentSuccessEventData>;
85
+ }) | ({
86
+ type: FunnelEventType.CUSTOM;
87
+ data?: NextEvent<any>;
88
+ }));
6
89
  export interface FunnelNavigationAction {
7
90
  type: 'redirect' | 'replace' | 'push' | 'external' | 'none';
8
91
  url?: string;
@@ -68,3 +151,4 @@ export declare function useSimpleFunnel(funnelId: string, initialStepId?: string
68
151
  goToStep: (stepId: string) => Promise<any>;
69
152
  isLoading: boolean;
70
153
  };
154
+ export {};
@@ -1,5 +1,23 @@
1
- import { useState, useCallback, useEffect } from 'react';
1
+ import { useCallback, useEffect, useState } from 'react';
2
2
  import { useTagadaContext } from '../providers/TagadaProvider';
3
+ /**
4
+ * Funnel event types enum
5
+ *
6
+ * Special types:
7
+ * - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
8
+ * - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
9
+ *
10
+ * Common types (for logging/tracking):
11
+ * - Any string value is accepted, but these are commonly used examples
12
+ */
13
+ export var FunnelEventType;
14
+ (function (FunnelEventType) {
15
+ // Special navigation types
16
+ FunnelEventType["DIRECT_NAVIGATION"] = "direct_navigation";
17
+ FunnelEventType["BACK_NAVIGATION"] = "back_navigation";
18
+ FunnelEventType["PAYMENT_SUCCESS"] = "payment_success";
19
+ FunnelEventType["CUSTOM"] = "custom";
20
+ })(FunnelEventType || (FunnelEventType = {}));
3
21
  /**
4
22
  * React Hook for Funnel Navigation (Plugin SDK Version)
5
23
  *
@@ -7,7 +25,7 @@ import { useTagadaContext } from '../providers/TagadaProvider';
7
25
  * Integrates with TagadaPay authentication and plugin routing.
8
26
  */
9
27
  export function useFunnel(options) {
10
- const { auth, apiService, store } = useTagadaContext();
28
+ const { auth, apiService, store, updateFunnelDebugData, debugMode } = useTagadaContext();
11
29
  const [isLoading, setIsLoading] = useState(false);
12
30
  const [isInitialized, setIsInitialized] = useState(false);
13
31
  const [context, setContext] = useState(null);
@@ -19,6 +37,35 @@ export function useFunnel(options) {
19
37
  const urlFunnelId = urlParams.get('funnelId') || undefined;
20
38
  const effectiveFunnelId = urlFunnelId || options.funnelId;
21
39
  // Removed checkExistingSession - now handled in single initialize call
40
+ /**
41
+ * Fetch funnel session with debug data (debug mode only)
42
+ */
43
+ const fetchFunnelDebugData = useCallback(async (sessionId) => {
44
+ if (!debugMode) {
45
+ console.log('🐛 [useFunnel] Debug mode is OFF, skipping debug data fetch');
46
+ return;
47
+ }
48
+ console.log('🐛 [useFunnel] Fetching debug data for session:', sessionId);
49
+ try {
50
+ const response = await apiService.fetch(`/api/v1/funnel/session/${sessionId}`, {
51
+ method: 'GET',
52
+ params: {
53
+ includeDebugData: 'true',
54
+ },
55
+ });
56
+ console.log('🐛 [useFunnel] Debug data response:', response);
57
+ if (response.success && response.debugData) {
58
+ updateFunnelDebugData(response.debugData, null, false);
59
+ console.log('🐛 [useFunnel] Debug data updated successfully:', response.debugData);
60
+ }
61
+ else {
62
+ console.warn('🐛 [useFunnel] No debug data in response');
63
+ }
64
+ }
65
+ catch (error) {
66
+ console.error('🐛 [useFunnel] Failed to fetch funnel debug data:', error);
67
+ }
68
+ }, [apiService, debugMode, updateFunnelDebugData]);
22
69
  /**
23
70
  * Set funnel session cookie
24
71
  */
@@ -91,6 +138,19 @@ export function useFunnel(options) {
91
138
  // Set session cookie for persistence across page reloads
92
139
  setSessionCookie(response.context.sessionId);
93
140
  console.log(`🍪 Funnel: Initialized new session for funnel ${effectiveFunnelId || 'default'}`, response.context);
141
+ // Fetch debug data if in debug mode
142
+ console.log('🐛 [useFunnel INIT] Checking debug mode:', {
143
+ debugMode,
144
+ sessionId: response.context.sessionId,
145
+ hasUpdateFunction: typeof updateFunnelDebugData,
146
+ });
147
+ if (debugMode) {
148
+ console.log('🐛 [useFunnel INIT] Debug mode is ON, calling fetchFunnelDebugData...');
149
+ void fetchFunnelDebugData(response.context.sessionId);
150
+ }
151
+ else {
152
+ console.warn('🐛 [useFunnel INIT] Debug mode is OFF, will not fetch debug data');
153
+ }
94
154
  }
95
155
  else {
96
156
  throw new Error(response.error || 'Failed to initialize funnel session');
@@ -108,7 +168,7 @@ export function useFunnel(options) {
108
168
  finally {
109
169
  setIsLoading(false);
110
170
  }
111
- }, [auth.session?.customerId, store?.id, effectiveFunnelId, apiService, options.onError]);
171
+ }, [auth.session?.customerId, store?.id, effectiveFunnelId, apiService, options.onError, debugMode, fetchFunnelDebugData]);
112
172
  /**
113
173
  * Navigate to next step based on event
114
174
  */
@@ -177,6 +237,18 @@ export function useFunnel(options) {
177
237
  performNavigation(updatedAction);
178
238
  }
179
239
  console.log(`🍪 Funnel: Navigated from ${context.currentStepId} to ${result.stepId}`);
240
+ // Fetch debug data if in debug mode
241
+ console.log('🐛 [useFunnel NAV] After navigation, checking debug mode:', {
242
+ debugMode,
243
+ sessionId: newContext.sessionId,
244
+ });
245
+ if (debugMode && newContext.sessionId) {
246
+ console.log('🐛 [useFunnel NAV] Fetching debug data after navigation...');
247
+ void fetchFunnelDebugData(newContext.sessionId);
248
+ }
249
+ else {
250
+ console.warn('🐛 [useFunnel NAV] Not fetching debug data:', { debugMode, hasSessionId: !!newContext.sessionId });
251
+ }
180
252
  return result;
181
253
  }
182
254
  else {
@@ -193,13 +265,13 @@ export function useFunnel(options) {
193
265
  finally {
194
266
  setIsLoading(false);
195
267
  }
196
- }, [context, apiService, options.onNavigate, options.onError]);
268
+ }, [context, apiService, options.onNavigate, options.onError, debugMode, fetchFunnelDebugData]);
197
269
  /**
198
270
  * Go directly to a specific step (bypass conditions)
199
271
  */
200
272
  const goToStep = useCallback(async (stepId) => {
201
273
  return next({
202
- type: 'direct_navigation',
274
+ type: FunnelEventType.DIRECT_NAVIGATION,
203
275
  data: { targetStepId: stepId },
204
276
  timestamp: new Date()
205
277
  });
@@ -29,6 +29,14 @@ interface TagadaContextValue {
29
29
  lastUpdated: Date | null;
30
30
  };
31
31
  updateCheckoutDebugData: (data: any, error?: Error | null, isLoading?: boolean) => void;
32
+ debugFunnel: {
33
+ isActive: boolean;
34
+ data: any;
35
+ error: Error | null;
36
+ isLoading: boolean;
37
+ lastUpdated: Date | null;
38
+ };
39
+ updateFunnelDebugData: (data: any, error?: Error | null, isLoading?: boolean) => void;
32
40
  refreshCoordinator: {
33
41
  registerCheckoutRefresh: (refreshFn: () => Promise<void>) => void;
34
42
  registerOrderBumpRefresh: (refreshFn: () => Promise<void>) => void;
@@ -198,6 +198,14 @@ rawPluginConfig, }) {
198
198
  isLoading: false,
199
199
  lastUpdated: null,
200
200
  });
201
+ // Initialize debug funnel state
202
+ const [debugFunnel, setDebugFunnel] = useState({
203
+ isActive: false,
204
+ data: null,
205
+ error: null,
206
+ isLoading: false,
207
+ lastUpdated: null,
208
+ });
201
209
  // Initialize auth state
202
210
  const [auth, setAuth] = useState({
203
211
  isAuthenticated: false,
@@ -518,6 +526,16 @@ rawPluginConfig, }) {
518
526
  lastUpdated: new Date(),
519
527
  });
520
528
  },
529
+ debugFunnel,
530
+ updateFunnelDebugData: (data, error, isLoading) => {
531
+ setDebugFunnel({
532
+ isActive: true,
533
+ data,
534
+ error: error ?? null,
535
+ isLoading: isLoading ?? false,
536
+ lastUpdated: new Date(),
537
+ });
538
+ },
521
539
  refreshCoordinator,
522
540
  money: {
523
541
  formatMoney,
@@ -544,6 +562,7 @@ rawPluginConfig, }) {
544
562
  pluginConfig,
545
563
  configLoading,
546
564
  debugCheckout,
565
+ debugFunnel,
547
566
  refreshCoordinator,
548
567
  ]);
549
568
  // Determine if we should show loading
@@ -2,9 +2,57 @@
2
2
  * Funnel Resource - API client for funnel navigation and session management
3
3
  */
4
4
  import { ApiClient } from './apiClient';
5
- export interface FunnelEvent {
6
- type: string;
7
- data?: any;
5
+ /**
6
+ * Funnel event types enum
7
+ *
8
+ * Special types:
9
+ * - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
10
+ * - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
11
+ *
12
+ * Common types (for logging/tracking):
13
+ * - Any string value is accepted, but these are commonly used examples
14
+ */
15
+ export declare enum FunnelEventType {
16
+ DIRECT_NAVIGATION = "direct_navigation",
17
+ BACK_NAVIGATION = "back_navigation",
18
+ PAYMENT_SUCCESS = "payment_success",
19
+ CUSTOM = "custom"
20
+ }
21
+ /**
22
+ * Data structures for specific event types
23
+ */
24
+ export type NextEvent<T> = T & {
25
+ [key: string]: any;
26
+ };
27
+ export interface DirectNavigationEventData {
28
+ targetStepId: string;
29
+ }
30
+ export interface BackNavigationEventData {
31
+ targetStepId: string;
32
+ }
33
+ export interface PaymentSuccessEventData {
34
+ payment: {
35
+ id: string;
36
+ status: string;
37
+ transactionId?: string;
38
+ timestamp?: string;
39
+ [key: string]: any;
40
+ };
41
+ order: {
42
+ id: string;
43
+ amount: number;
44
+ currency: string;
45
+ [key: string]: any;
46
+ };
47
+ [key: string]: any;
48
+ }
49
+ /**
50
+ * Base properties shared by all FunnelEvent types
51
+ */
52
+ interface BaseFunnelEvent {
53
+ /**
54
+ * Event timestamp (ISO string format)
55
+ */
8
56
  timestamp?: string;
9
57
  /**
10
58
  * Current URL for session synchronization (browser back/forward handling)
@@ -13,6 +61,22 @@ export interface FunnelEvent {
13
61
  */
14
62
  currentUrl?: string;
15
63
  }
64
+ /**
65
+ * Discriminated union for FunnelEvent based on event type
66
+ */
67
+ export type FunnelAction = BaseFunnelEvent & (({
68
+ type: FunnelEventType.DIRECT_NAVIGATION;
69
+ data: NextEvent<DirectNavigationEventData>;
70
+ }) | ({
71
+ type: FunnelEventType.BACK_NAVIGATION;
72
+ data: NextEvent<BackNavigationEventData>;
73
+ }) | ({
74
+ type: FunnelEventType.PAYMENT_SUCCESS;
75
+ data: NextEvent<PaymentSuccessEventData>;
76
+ }) | ({
77
+ type: FunnelEventType.CUSTOM;
78
+ data?: NextEvent<any>;
79
+ }));
16
80
  export interface FunnelNavigationAction {
17
81
  type: 'redirect' | 'replace' | 'push' | 'external' | 'none';
18
82
  url?: string;
@@ -63,7 +127,7 @@ export interface FunnelInitializeResponse {
63
127
  }
64
128
  export interface FunnelNavigateRequest {
65
129
  sessionId: string;
66
- event: FunnelEvent;
130
+ event: FunnelAction;
67
131
  contextUpdates?: Partial<SimpleFunnelContext>;
68
132
  /**
69
133
  * Current URL for URL-to-Step mapping (browser back/forward sync)
@@ -129,9 +193,11 @@ export declare class FunnelResource {
129
193
  * @param sessionId - The session ID to fetch
130
194
  * @param currentUrl - Optional current URL for session synchronization on page load
131
195
  */
132
- getSession(sessionId: string, currentUrl?: string): Promise<{
196
+ getSession(sessionId: string, currentUrl?: string, includeDebugData?: boolean): Promise<{
133
197
  success: boolean;
134
198
  context?: SimpleFunnelContext;
199
+ debugData?: any;
135
200
  error?: string;
136
201
  }>;
137
202
  }
203
+ export {};
@@ -1,6 +1,24 @@
1
1
  /**
2
2
  * Funnel Resource - API client for funnel navigation and session management
3
3
  */
4
+ /**
5
+ * Funnel event types enum
6
+ *
7
+ * Special types:
8
+ * - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
9
+ * - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
10
+ *
11
+ * Common types (for logging/tracking):
12
+ * - Any string value is accepted, but these are commonly used examples
13
+ */
14
+ export var FunnelEventType;
15
+ (function (FunnelEventType) {
16
+ // Special navigation types
17
+ FunnelEventType["DIRECT_NAVIGATION"] = "direct_navigation";
18
+ FunnelEventType["BACK_NAVIGATION"] = "back_navigation";
19
+ FunnelEventType["PAYMENT_SUCCESS"] = "payment_success";
20
+ FunnelEventType["CUSTOM"] = "custom";
21
+ })(FunnelEventType || (FunnelEventType = {}));
4
22
  export class FunnelResource {
5
23
  constructor(apiClient) {
6
24
  this.apiClient = apiClient;
@@ -34,9 +52,15 @@ export class FunnelResource {
34
52
  * @param sessionId - The session ID to fetch
35
53
  * @param currentUrl - Optional current URL for session synchronization on page load
36
54
  */
37
- async getSession(sessionId, currentUrl) {
38
- const params = currentUrl ? new URLSearchParams({ currentUrl }) : undefined;
39
- const url = `/api/v1/funnel/session/${sessionId}${params ? `?${params}` : ''}`;
55
+ async getSession(sessionId, currentUrl, includeDebugData) {
56
+ const params = new URLSearchParams();
57
+ if (currentUrl) {
58
+ params.append('currentUrl', currentUrl);
59
+ }
60
+ if (includeDebugData) {
61
+ params.append('includeDebugData', 'true');
62
+ }
63
+ const url = `/api/v1/funnel/session/${sessionId}${params.toString() ? `?${params}` : ''}`;
40
64
  return this.apiClient.get(url);
41
65
  }
42
66
  }
@@ -21,8 +21,9 @@ export type { ShippingRate, ShippingRatesResponse } from './core/resources/shipp
21
21
  export type { ApplyDiscountResponse, Discount, DiscountCodeValidation, RemoveDiscountResponse } from './core/resources/discounts';
22
22
  export type { ToggleOrderBumpResponse, VipOffer, VipPreviewResponse } from './core/resources/vipOffers';
23
23
  export type { StoreConfig } from './core/resources/storeConfig';
24
- export type { FunnelContextUpdateRequest, FunnelContextUpdateResponse, FunnelEvent, FunnelInitializeRequest, FunnelInitializeResponse, FunnelNavigateRequest, FunnelNavigateResponse, FunnelNavigationAction, FunnelNavigationResult, SimpleFunnelContext } from './core/resources/funnel';
25
- export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
24
+ export { FunnelEventType } from './core/resources/funnel';
25
+ export type { BackNavigationEventData, DirectNavigationEventData, FunnelContextUpdateRequest, FunnelContextUpdateResponse, FunnelAction as FunnelEvent, FunnelInitializeRequest, FunnelInitializeResponse, FunnelNavigateRequest, FunnelNavigateResponse, FunnelNavigationAction, FunnelNavigationResult, NextEvent, PaymentSuccessEventData, SimpleFunnelContext } from './core/resources/funnel';
26
+ export { ApplePayButton, ExpressPaymentMethodsProvider, GooglePayButton, TagadaProvider, formatMoney, getAvailableLanguages, queryKeys, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useISOData, useInvalidateQuery, useLanguageImport, useLogin, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
26
27
  export type { TranslateFunction, TranslationText, UseTranslationOptions, UseTranslationResult } from './react/hooks/useTranslation';
27
28
  export type { ClubOffer, ClubOfferItem, ClubOfferLineItem, ClubOfferSummary, UseClubOffersOptions, UseClubOffersResult } from './react/hooks/useClubOffers';
28
29
  export type { UseLoginOptions, UseLoginResult } from './react/hooks/useLogin';
package/dist/v2/index.js CHANGED
@@ -13,5 +13,6 @@ export * from './core/utils/pluginConfig';
13
13
  export * from './core/utils/products';
14
14
  // Path remapping helpers (framework-agnostic)
15
15
  export * from './core/pathRemapping';
16
+ export { FunnelEventType } from './core/resources/funnel';
16
17
  // React exports (hooks and components only, types are exported above)
17
- export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
18
+ export { ApplePayButton, ExpressPaymentMethodsProvider, GooglePayButton, TagadaProvider, formatMoney, getAvailableLanguages, queryKeys, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useISOData, useInvalidateQuery, useLanguageImport, useLogin, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';