@encatch/web-sdk 0.0.35 → 1.0.0-beta.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/README.md +140 -638
- package/dist/encatch.es.js +2 -0
- package/dist/encatch.es.js.map +1 -0
- package/dist/encatch.iife.js +2 -0
- package/dist/encatch.iife.js.map +1 -0
- package/dist/index.d.ts +191 -0
- package/package.json +32 -50
- package/dist-sdk/plugin/sdk/core-wrapper-BMvOyc0u.js +0 -22926
- package/dist-sdk/plugin/sdk/module-DC2Edddk.js +0 -481
- package/dist-sdk/plugin/sdk/module.js +0 -5
- package/dist-sdk/plugin/sdk/preview-sdk.html +0 -1182
- package/dist-sdk/plugin/sdk/vite.svg +0 -15
- package/dist-sdk/plugin/sdk/web-form-engine-core.css +0 -1
- package/index.d.ts +0 -207
- package/src/@types/encatch-type.ts +0 -111
- package/src/encatch-instance.ts +0 -161
- package/src/feedback-api-types.ts +0 -18
- package/src/hooks/useDevice.ts +0 -30
- package/src/hooks/useFeedbackInterval.ts +0 -71
- package/src/hooks/useFeedbackTriggers.ts +0 -342
- package/src/hooks/useFetchElligibleFeedbackConfiguration.ts +0 -363
- package/src/hooks/useFetchFeedbackConfigurationDetails.ts +0 -92
- package/src/hooks/usePageChangeTracker.ts +0 -88
- package/src/hooks/usePrepopulatedAnswers.ts +0 -123
- package/src/hooks/useRefineTextForm.ts +0 -55
- package/src/hooks/useSubmitFeedbackForm.ts +0 -134
- package/src/hooks/useUserSession.ts +0 -53
- package/src/module.tsx +0 -428
- package/src/store/formResponses.ts +0 -211
- package/src/utils/browser-details.ts +0 -36
- package/src/utils/duration-utils.ts +0 -158
- package/src/utils/feedback-frequency-storage.ts +0 -214
- package/src/utils/feedback-storage.ts +0 -166
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Answer } from "@encatch/schema";
|
|
2
|
-
|
|
3
|
-
interface Duration {
|
|
4
|
-
from: string;
|
|
5
|
-
to: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
interface TriggerProperties {
|
|
9
|
-
screens: string[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface PrepopulatedAnswer {
|
|
13
|
-
sectionIndex: number;
|
|
14
|
-
questionIndex: number;
|
|
15
|
-
value: Answer;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type { Duration, TriggerProperties,PrepopulatedAnswer };
|
package/src/hooks/useDevice.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { generateUUID, getDeviceInfo } from "../utils/browser-details";
|
|
2
|
-
import { DeviceInfo } from "@encatch/schema";
|
|
3
|
-
import { useState, useEffect } from "preact/hooks";
|
|
4
|
-
|
|
5
|
-
const DEVICE_STORAGE_KEY = "app_device";
|
|
6
|
-
|
|
7
|
-
export const useDevice = () => {
|
|
8
|
-
const [deviceId, setDeviceId] = useState<string | null>(null);
|
|
9
|
-
const [deviceInfo, setDeviceInfo] = useState<DeviceInfo | null>(null);
|
|
10
|
-
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
const storedId = localStorage.getItem(DEVICE_STORAGE_KEY);
|
|
13
|
-
let currentDeviceId: string;
|
|
14
|
-
|
|
15
|
-
if (storedId) {
|
|
16
|
-
setDeviceId(storedId);
|
|
17
|
-
currentDeviceId = storedId;
|
|
18
|
-
} else {
|
|
19
|
-
const newId = generateUUID();
|
|
20
|
-
localStorage.setItem(DEVICE_STORAGE_KEY, newId);
|
|
21
|
-
setDeviceId(newId);
|
|
22
|
-
currentDeviceId = newId;
|
|
23
|
-
}
|
|
24
|
-
const userAgent = navigator.userAgent;
|
|
25
|
-
const deviceInfo = getDeviceInfo(userAgent, currentDeviceId);
|
|
26
|
-
setDeviceInfo(deviceInfo);
|
|
27
|
-
}, []);
|
|
28
|
-
|
|
29
|
-
return { deviceId, deviceInfo };
|
|
30
|
-
};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from "preact/hooks";
|
|
2
|
-
|
|
3
|
-
const FEEDBACK_VISIBLE_KEY = "encatch_feedback_visible";
|
|
4
|
-
const FEEDBACK_INTERVAL_KEY = "encatch_feedback_interval";
|
|
5
|
-
|
|
6
|
-
export const useFeedbackInterval = () => {
|
|
7
|
-
const [feedbackInterval, setFeedbackInterval] = useState<number>(0);
|
|
8
|
-
const [isFeedbackVisible, setIsFeedbackVisible] = useState<boolean>(false);
|
|
9
|
-
const [lastVisibleTime, setLastVisibleTime] = useState<number | null>(null);
|
|
10
|
-
|
|
11
|
-
const canShowFeedbackModal = () => {
|
|
12
|
-
const currentInterval = feedbackInterval;
|
|
13
|
-
const lastVisible = lastVisibleTime;
|
|
14
|
-
|
|
15
|
-
if (!lastVisible || !currentInterval) {
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const timeSinceLastVisible = Date.now() - lastVisible;
|
|
20
|
-
const canShow = timeSinceLastVisible >= currentInterval;
|
|
21
|
-
|
|
22
|
-
return canShow;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const setFeedbackVisible = (visible: boolean) => {
|
|
26
|
-
setIsFeedbackVisible(visible);
|
|
27
|
-
if (visible) {
|
|
28
|
-
const timestamp = Date.now();
|
|
29
|
-
setLastVisibleTime(timestamp);
|
|
30
|
-
localStorage.setItem(FEEDBACK_VISIBLE_KEY, timestamp.toString());
|
|
31
|
-
} else {
|
|
32
|
-
setLastVisibleTime(null);
|
|
33
|
-
localStorage.removeItem(FEEDBACK_VISIBLE_KEY);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const updateFeedbackInterval = (interval: number) => {
|
|
38
|
-
// Convert minutes to milliseconds (interval * 60 * 1000)
|
|
39
|
-
const intervalInMs = interval * 60 * 1000;
|
|
40
|
-
setFeedbackInterval(intervalInMs);
|
|
41
|
-
localStorage.setItem(FEEDBACK_INTERVAL_KEY, intervalInMs.toString());
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
// Load stored interval
|
|
46
|
-
const storedInterval = localStorage.getItem(FEEDBACK_INTERVAL_KEY);
|
|
47
|
-
if (storedInterval) {
|
|
48
|
-
const interval = parseInt(storedInterval);
|
|
49
|
-
const intervalInMs = interval * 60 * 1000;
|
|
50
|
-
setFeedbackInterval(intervalInMs);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Check if feedback was recently shown
|
|
54
|
-
const storedLastVisible = localStorage.getItem(FEEDBACK_VISIBLE_KEY);
|
|
55
|
-
if (storedLastVisible) {
|
|
56
|
-
const timestamp = parseInt(storedLastVisible);
|
|
57
|
-
setLastVisibleTime(timestamp);
|
|
58
|
-
const timeSinceLastVisible = Date.now() - timestamp;
|
|
59
|
-
const currentInterval = feedbackInterval;
|
|
60
|
-
const isVisible = timeSinceLastVisible < currentInterval;
|
|
61
|
-
setIsFeedbackVisible(isVisible);
|
|
62
|
-
}
|
|
63
|
-
}, []);
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
canShowFeedbackModal,
|
|
67
|
-
setFeedbackVisible,
|
|
68
|
-
setFeedbackInterval: updateFeedbackInterval,
|
|
69
|
-
isFeedbackVisible
|
|
70
|
-
};
|
|
71
|
-
};
|
|
@@ -1,342 +0,0 @@
|
|
|
1
|
-
import { useState, useRef, useCallback } from "preact/hooks";
|
|
2
|
-
import {
|
|
3
|
-
TriggerProperties as BaseTriggerProperties,
|
|
4
|
-
} from "../feedback-api-types";
|
|
5
|
-
|
|
6
|
-
import jsonLogic from "json-logic-js";
|
|
7
|
-
import { match as pathMatch } from "path-to-regexp";
|
|
8
|
-
import { FeedbackConfigurationItem, QueryOutput, TriggerAction } from "@encatch/schema";
|
|
9
|
-
|
|
10
|
-
jsonLogic.add_operation("startsWith", (a: any, b: any) => {
|
|
11
|
-
if (typeof a !== "string" || typeof b !== "string") return false;
|
|
12
|
-
return a.startsWith(b);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
jsonLogic.add_operation("regex", (a: any, b: any) => {
|
|
16
|
-
if (typeof a !== "string" || typeof b !== "string") {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
return matchesDynamicRoute(a, b);
|
|
20
|
-
});
|
|
21
|
-
function matchesDynamicRoute(inputPath: string, routePattern: string): boolean {
|
|
22
|
-
try {
|
|
23
|
-
const matcher = pathMatch(routePattern, { decode: decodeURIComponent });
|
|
24
|
-
const result = matcher(inputPath);
|
|
25
|
-
return !!result;
|
|
26
|
-
} catch (error) {
|
|
27
|
-
console.error("[swat] pathMatch error", { inputPath, routePattern, error });
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
type TriggerConfig = {
|
|
32
|
-
feedbackConfigurationId: string;
|
|
33
|
-
eventName: string;
|
|
34
|
-
jsonLogicField: any;
|
|
35
|
-
thenAction: any;
|
|
36
|
-
isImportant: boolean;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
type WhenCondition = {
|
|
40
|
-
if: {
|
|
41
|
-
id: string;
|
|
42
|
-
event: string;
|
|
43
|
-
queryOutput: QueryOutput;
|
|
44
|
-
};
|
|
45
|
-
then: TriggerAction;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
type Segment = {
|
|
49
|
-
when: WhenCondition[];
|
|
50
|
-
isImportant?: boolean;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
interface ExtendedTriggerProperties extends BaseTriggerProperties {
|
|
54
|
-
isAuto: boolean;
|
|
55
|
-
segments: Segment[];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
type QueuedEvent = {
|
|
59
|
-
eventName: string;
|
|
60
|
-
properties?: Record<string, any>;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const useFeedbackTriggers = (
|
|
64
|
-
onTriggerMatch?: (configId: string, event: string) => void
|
|
65
|
-
) => {
|
|
66
|
-
|
|
67
|
-
const [pageLoadTriggers, setPageLoadTriggers] = useState<TriggerConfig[] | null>(null);
|
|
68
|
-
const [feedbackConfig, setFeedbackConfig] = useState<FeedbackConfigurationItem[] | null>(null);
|
|
69
|
-
const [customEventTriggers, setCustomEventTriggers] = useState<TriggerConfig[] | null>(null);
|
|
70
|
-
const [eventQueue, setEventQueue] = useState<QueuedEvent[]>([]);
|
|
71
|
-
const [canShowFeedbackModal, setCanShowFeedbackModal] = useState(false);
|
|
72
|
-
|
|
73
|
-
const [activeFeedbackConfig, setActiveFeedbackConfig] = useState<{
|
|
74
|
-
configId: string;
|
|
75
|
-
isImportant: boolean;
|
|
76
|
-
eventName: string;
|
|
77
|
-
} | null>(null);
|
|
78
|
-
|
|
79
|
-
const currentTimeoutIdRef = useRef<number | null>(null);
|
|
80
|
-
|
|
81
|
-
// Store triggers in refs to avoid stale closure issues
|
|
82
|
-
const pageLoadTriggersRef = useRef<TriggerConfig[] | null>(null);
|
|
83
|
-
const customEventTriggersRef = useRef<TriggerConfig[] | null>(null);
|
|
84
|
-
|
|
85
|
-
const showFeedbackByConfigId = (configId: string, event: string) => {
|
|
86
|
-
if (onTriggerMatch) {
|
|
87
|
-
onTriggerMatch(configId, event);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Exposes a function to manually trigger feedback modal based on scroll percentage.
|
|
93
|
-
* Instead of calculating scroll, uses the scroll value from WhenCondition.
|
|
94
|
-
* When the scroll percentage matches or exceeds, displays the modal.
|
|
95
|
-
*/
|
|
96
|
-
const triggeredFeedbacksRef = useRef(new Set<string>());
|
|
97
|
-
|
|
98
|
-
const capturePageScrollEvent = useCallback((scrollPercent: string) => {
|
|
99
|
-
let percentNum: number;
|
|
100
|
-
|
|
101
|
-
if (typeof scrollPercent === 'string') {
|
|
102
|
-
percentNum = parseFloat(scrollPercent.replace('%', ''));
|
|
103
|
-
} else {
|
|
104
|
-
percentNum = scrollPercent;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const configs = feedbackConfig || [];
|
|
108
|
-
|
|
109
|
-
for (const config of configs) {
|
|
110
|
-
if (triggeredFeedbacksRef.current.has(config.feedbackConfigurationId)) continue;
|
|
111
|
-
|
|
112
|
-
if (config.triggerProperties) {
|
|
113
|
-
const triggerProps = config.triggerProperties ;
|
|
114
|
-
for (const segment of triggerProps.segments) {
|
|
115
|
-
for (const whenItem of segment.when) {
|
|
116
|
-
let scrollValue = 0;
|
|
117
|
-
if (typeof whenItem.then.scroll === 'string') {
|
|
118
|
-
scrollValue = parseFloat(whenItem.then.scroll.replace('%', ''));
|
|
119
|
-
} else {
|
|
120
|
-
scrollValue = Number(whenItem.then.scroll);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
whenItem.then.triggerType === "scroll" &&
|
|
125
|
-
!isNaN(scrollValue) &&
|
|
126
|
-
percentNum >= scrollValue
|
|
127
|
-
) {
|
|
128
|
-
triggeredFeedbacksRef.current.add(config.feedbackConfigurationId);
|
|
129
|
-
onTriggerMatch?.(config.feedbackConfigurationId, whenItem.if.event);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}, [feedbackConfig, onTriggerMatch]);
|
|
137
|
-
|
|
138
|
-
const updateFeedbackConfigRef = useRef<(configs: FeedbackConfigurationItem[]) => void>();
|
|
139
|
-
|
|
140
|
-
updateFeedbackConfigRef.current = (configs: FeedbackConfigurationItem[]) => {
|
|
141
|
-
const pageLoadTriggersList: TriggerConfig[] = [];
|
|
142
|
-
const customEventTriggersList: TriggerConfig[] = [];
|
|
143
|
-
|
|
144
|
-
configs.forEach((config) => {
|
|
145
|
-
if (config.triggerProperties) {
|
|
146
|
-
const triggerProps =
|
|
147
|
-
config.triggerProperties as unknown as ExtendedTriggerProperties;
|
|
148
|
-
const { isAuto, segments } = triggerProps;
|
|
149
|
-
|
|
150
|
-
if (isAuto && segments) {
|
|
151
|
-
segments.forEach((seg: Segment) => {
|
|
152
|
-
if (seg.when) {
|
|
153
|
-
seg.when.forEach((whenItem: WhenCondition) => {
|
|
154
|
-
if (whenItem.if) {
|
|
155
|
-
const { event, queryOutput } = whenItem.if;
|
|
156
|
-
let jsonLogicField: any = queryOutput.jsonLogic;
|
|
157
|
-
|
|
158
|
-
// Parse jsonLogic if it's a string
|
|
159
|
-
if (typeof jsonLogicField === "string") {
|
|
160
|
-
if (jsonLogicField.trim() === "") {
|
|
161
|
-
console.warn("Empty jsonLogic string received");
|
|
162
|
-
jsonLogicField = null;
|
|
163
|
-
} else {
|
|
164
|
-
try {
|
|
165
|
-
jsonLogicField = JSON.parse(jsonLogicField);
|
|
166
|
-
} catch (e) {
|
|
167
|
-
console.warn("Failed to parse jsonLogic string:", jsonLogicField, e);
|
|
168
|
-
jsonLogicField = null;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Skip if jsonLogic is null, undefined, or an empty object
|
|
174
|
-
if (!jsonLogicField || (typeof jsonLogicField === 'object' && Object.keys(jsonLogicField).length === 0)) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const triggerConfig: TriggerConfig = {
|
|
179
|
-
feedbackConfigurationId: config.feedbackConfigurationId,
|
|
180
|
-
eventName: event,
|
|
181
|
-
jsonLogicField,
|
|
182
|
-
thenAction: whenItem.then,
|
|
183
|
-
isImportant: seg.isImportant ?? false,
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
if (event === "pageLoad") {
|
|
187
|
-
pageLoadTriggersList.push(triggerConfig);
|
|
188
|
-
} else {
|
|
189
|
-
customEventTriggersList.push(triggerConfig);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
// Update refs immediately so processTrigger can access fresh values
|
|
200
|
-
pageLoadTriggersRef.current = pageLoadTriggersList;
|
|
201
|
-
customEventTriggersRef.current = customEventTriggersList;
|
|
202
|
-
|
|
203
|
-
setPageLoadTriggers(pageLoadTriggersList);
|
|
204
|
-
setCustomEventTriggers(customEventTriggersList);
|
|
205
|
-
setFeedbackConfig(configs);
|
|
206
|
-
|
|
207
|
-
// Process any queued events now that we have the configuration
|
|
208
|
-
const queue = eventQueue;
|
|
209
|
-
if (queue.length > 0) {
|
|
210
|
-
queue.forEach(event => {
|
|
211
|
-
processTriggerRef.current?.(event.eventName, event.properties);
|
|
212
|
-
});
|
|
213
|
-
setEventQueue([]); // Clear the queue after processing
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
const processTriggerRef = useRef<(eventName: string, properties?: Record<string, any>) => void>();
|
|
218
|
-
|
|
219
|
-
processTriggerRef.current = (
|
|
220
|
-
eventName: string,
|
|
221
|
-
properties?: Record<string, any>
|
|
222
|
-
) => {
|
|
223
|
-
let identifiedTrigger: TriggerConfig | undefined;
|
|
224
|
-
|
|
225
|
-
if (eventName === "pageLoad") {
|
|
226
|
-
const pageTriggers = pageLoadTriggersRef.current;
|
|
227
|
-
if (pageTriggers) {
|
|
228
|
-
identifiedTrigger = pageTriggers.find((trigger) => {
|
|
229
|
-
let jsonLogicResult = false;
|
|
230
|
-
try {
|
|
231
|
-
const props = properties || {};
|
|
232
|
-
jsonLogicResult = jsonLogic.apply(trigger.jsonLogicField, props);
|
|
233
|
-
} catch (e) {
|
|
234
|
-
console.error('[swat] Error applying jsonLogic for pageLoad trigger:', {
|
|
235
|
-
configId: trigger.feedbackConfigurationId,
|
|
236
|
-
jsonLogicField: trigger.jsonLogicField,
|
|
237
|
-
error: e
|
|
238
|
-
});
|
|
239
|
-
jsonLogicResult = false;
|
|
240
|
-
}
|
|
241
|
-
const match = trigger.eventName === eventName && jsonLogicResult;
|
|
242
|
-
return match;
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
} else {
|
|
246
|
-
const customTriggers = customEventTriggersRef.current;
|
|
247
|
-
if (customTriggers) {
|
|
248
|
-
identifiedTrigger = customTriggers.find((trigger) => {
|
|
249
|
-
const eventMatches = trigger.eventName === eventName;
|
|
250
|
-
let jsonLogicResult = false;
|
|
251
|
-
try {
|
|
252
|
-
jsonLogicResult = jsonLogic.apply(trigger.jsonLogicField, properties || {});
|
|
253
|
-
} catch (e) {
|
|
254
|
-
console.error('[swat] Error applying jsonLogic for custom event trigger:', {
|
|
255
|
-
configId: trigger.feedbackConfigurationId,
|
|
256
|
-
eventName: trigger.eventName,
|
|
257
|
-
jsonLogicField: trigger.jsonLogicField,
|
|
258
|
-
error: e
|
|
259
|
-
});
|
|
260
|
-
jsonLogicResult = false;
|
|
261
|
-
}
|
|
262
|
-
const match = eventMatches && jsonLogicResult;
|
|
263
|
-
return match;
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (identifiedTrigger) {
|
|
269
|
-
// Allow delay triggers to bypass modal restrictions, but block other non-important triggers
|
|
270
|
-
const isDelayTrigger = identifiedTrigger.thenAction.triggerType === "delay";
|
|
271
|
-
if (!identifiedTrigger.isImportant && !canShowFeedbackModal && !isDelayTrigger) {
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const { triggerType, delay, scroll } = identifiedTrigger.thenAction;
|
|
276
|
-
if (activeFeedbackConfig && activeFeedbackConfig?.isImportant && identifiedTrigger.isImportant) {
|
|
277
|
-
setActiveFeedbackConfig({
|
|
278
|
-
configId: identifiedTrigger.feedbackConfigurationId,
|
|
279
|
-
isImportant: identifiedTrigger.isImportant,
|
|
280
|
-
eventName: identifiedTrigger.eventName
|
|
281
|
-
});
|
|
282
|
-
} else if (
|
|
283
|
-
activeFeedbackConfig &&
|
|
284
|
-
activeFeedbackConfig?.isImportant &&
|
|
285
|
-
!identifiedTrigger.isImportant
|
|
286
|
-
) {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (currentTimeoutIdRef.current !== null) {
|
|
291
|
-
clearTimeout(currentTimeoutIdRef.current);
|
|
292
|
-
currentTimeoutIdRef.current = null;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (triggerType === "immediately") {
|
|
296
|
-
showFeedbackByConfigId(identifiedTrigger.feedbackConfigurationId, identifiedTrigger.eventName);
|
|
297
|
-
setActiveFeedbackConfig(null);
|
|
298
|
-
} else if (triggerType === "delay") {
|
|
299
|
-
const delayInMs = delay * 1000; // Convert seconds to milliseconds
|
|
300
|
-
setActiveFeedbackConfig({
|
|
301
|
-
configId: identifiedTrigger.feedbackConfigurationId,
|
|
302
|
-
isImportant: identifiedTrigger.isImportant,
|
|
303
|
-
eventName: identifiedTrigger.eventName
|
|
304
|
-
});
|
|
305
|
-
currentTimeoutIdRef.current = window.setTimeout(() => {
|
|
306
|
-
showFeedbackByConfigId(identifiedTrigger.feedbackConfigurationId, identifiedTrigger.eventName);
|
|
307
|
-
setActiveFeedbackConfig(null);
|
|
308
|
-
currentTimeoutIdRef.current = null;
|
|
309
|
-
}, delayInMs);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
const invokeTrigger = (
|
|
315
|
-
eventName: string,
|
|
316
|
-
properties?: Record<string, any>,
|
|
317
|
-
canShowFeedbackModal?: boolean
|
|
318
|
-
) => {
|
|
319
|
-
setCanShowFeedbackModal(canShowFeedbackModal ?? true);
|
|
320
|
-
|
|
321
|
-
// If feedback configuration is not loaded yet, queue the event
|
|
322
|
-
if (!feedbackConfig) {
|
|
323
|
-
setEventQueue([...eventQueue, { eventName, properties }]);
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// If configuration is loaded, process the trigger
|
|
328
|
-
processTriggerRef.current?.(eventName, properties);
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
const updateFeedbackConfig = (configs: FeedbackConfigurationItem[]) => {
|
|
332
|
-
updateFeedbackConfigRef.current?.(configs);
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
return {
|
|
336
|
-
updateFeedbackConfig,
|
|
337
|
-
invokeTrigger,
|
|
338
|
-
pageLoadTriggers,
|
|
339
|
-
customEventTriggers,
|
|
340
|
-
capturePageScrollEvent,
|
|
341
|
-
};
|
|
342
|
-
};
|