@heycater/qualification-funnel 1.4.10 → 1.4.12
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/heycater-funnel.iife.js +3 -3
- package/dist/index.cjs.js +26 -26
- package/dist/index.esm.js +59 -29
- package/package.json +12 -3
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var _a;
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import React__default, { createContext, useContext, useMemo, useReducer, useCallback, useEffect, useRef, useState, isValidElement, cloneElement, Children, forwardRef } from "react";
|
|
4
|
+
import React__default, { createContext, useContext, useMemo, useReducer, useCallback, useEffect, useRef, useState, isValidElement, cloneElement, Children, forwardRef, useLayoutEffect } from "react";
|
|
5
5
|
import { darken as darken$1, lighten as lighten$1, ButtonBase as ButtonBase$2, Typography as Typography$1, useMediaQuery, Input as Input$1, IconButton as IconButton$2, useTheme as useTheme$1, FormControlLabel, Tooltip, Menu, Hidden, SnackbarContent, Snackbar, TextField, CircularProgress, Modal, ThemeProvider as ThemeProvider$1, StylesProvider as StylesProvider$1, CssBaseline } from "@material-ui/core";
|
|
6
6
|
import { useTranslation, initReactI18next, I18nextProvider } from "react-i18next";
|
|
7
7
|
import styled, { css as css$1, createGlobalStyle, ThemeProvider } from "styled-components";
|
|
@@ -11047,9 +11047,12 @@ function trackAnswerSelected(context, answer) {
|
|
|
11047
11047
|
if (context.city) {
|
|
11048
11048
|
properties.city = context.city;
|
|
11049
11049
|
}
|
|
11050
|
-
captureEvent("
|
|
11050
|
+
captureEvent("qf_v2_answer_selected", properties);
|
|
11051
11051
|
}
|
|
11052
11052
|
function trackFormSubmitted(context, metadata) {
|
|
11053
|
+
if (!context.session_id) {
|
|
11054
|
+
console.warn("[Tracking] trackFormSubmitted called with empty session_id", context);
|
|
11055
|
+
}
|
|
11053
11056
|
const properties = {
|
|
11054
11057
|
funnel_mode: context.funnel_mode,
|
|
11055
11058
|
session_id: context.session_id,
|
|
@@ -11062,9 +11065,12 @@ function trackFormSubmitted(context, metadata) {
|
|
|
11062
11065
|
if (context.city) {
|
|
11063
11066
|
properties.city = context.city;
|
|
11064
11067
|
}
|
|
11065
|
-
captureEvent("
|
|
11068
|
+
captureEvent("qf_v2_form_submitted", properties);
|
|
11066
11069
|
}
|
|
11067
11070
|
function trackCompleted(context) {
|
|
11071
|
+
if (!context.session_id) {
|
|
11072
|
+
console.warn("[Tracking] trackCompleted called with empty session_id", context);
|
|
11073
|
+
}
|
|
11068
11074
|
const properties = {
|
|
11069
11075
|
funnel_mode: context.funnel_mode,
|
|
11070
11076
|
session_id: context.session_id,
|
|
@@ -11076,9 +11082,12 @@ function trackCompleted(context) {
|
|
|
11076
11082
|
if (context.city) {
|
|
11077
11083
|
properties.city = context.city;
|
|
11078
11084
|
}
|
|
11079
|
-
captureEvent("
|
|
11085
|
+
captureEvent("qf_v2_completed", properties);
|
|
11080
11086
|
}
|
|
11081
11087
|
function trackAbandoned(context, lastStep) {
|
|
11088
|
+
if (!context.session_id) {
|
|
11089
|
+
console.warn("[Tracking] trackAbandoned called with empty session_id", context);
|
|
11090
|
+
}
|
|
11082
11091
|
const properties = {
|
|
11083
11092
|
funnel_mode: context.funnel_mode,
|
|
11084
11093
|
session_id: context.session_id,
|
|
@@ -11092,7 +11101,7 @@ function trackAbandoned(context, lastStep) {
|
|
|
11092
11101
|
if (context.city) {
|
|
11093
11102
|
properties.city = context.city;
|
|
11094
11103
|
}
|
|
11095
|
-
captureEvent("
|
|
11104
|
+
captureEvent("qf_v2_abandoned", properties);
|
|
11096
11105
|
}
|
|
11097
11106
|
function trackStarted(context, initialStepId) {
|
|
11098
11107
|
const properties = {
|
|
@@ -11100,11 +11109,11 @@ function trackStarted(context, initialStepId) {
|
|
|
11100
11109
|
session_id: context.session_id,
|
|
11101
11110
|
initial_step: initialStepId
|
|
11102
11111
|
};
|
|
11103
|
-
captureEvent("
|
|
11112
|
+
captureEvent("qf_v2_started", properties);
|
|
11104
11113
|
}
|
|
11105
11114
|
const TrackingContext = createContext(null);
|
|
11106
11115
|
function TrackingProvider({
|
|
11107
|
-
|
|
11116
|
+
funnelContextRef,
|
|
11108
11117
|
updateContext,
|
|
11109
11118
|
currentStepId,
|
|
11110
11119
|
children
|
|
@@ -11121,12 +11130,12 @@ function TrackingProvider({
|
|
|
11121
11130
|
const questions2 = (schemaStep == null ? void 0 : schemaStep.questions) || [];
|
|
11122
11131
|
const questionIndex = questions2.findIndex((q2) => q2.id === questionId);
|
|
11123
11132
|
const isLastQuestion = questionIndex === questions2.length - 1;
|
|
11124
|
-
const sessionKey = `
|
|
11133
|
+
const sessionKey = `qf_v2_started_${funnelContextRef.current.session_id}`;
|
|
11125
11134
|
if (typeof sessionStorage !== "undefined") {
|
|
11126
11135
|
const hasStarted = sessionStorage.getItem(sessionKey);
|
|
11127
11136
|
if (!hasStarted) {
|
|
11128
11137
|
sessionStorage.setItem(sessionKey, "true");
|
|
11129
|
-
trackStarted(
|
|
11138
|
+
trackStarted(funnelContextRef.current, currentStepId);
|
|
11130
11139
|
}
|
|
11131
11140
|
}
|
|
11132
11141
|
if (questionId === "service_type") {
|
|
@@ -11141,7 +11150,7 @@ function TrackingProvider({
|
|
|
11141
11150
|
} else if (questionId === "city") {
|
|
11142
11151
|
updateContext({ city: value });
|
|
11143
11152
|
}
|
|
11144
|
-
trackAnswerSelected(
|
|
11153
|
+
trackAnswerSelected(funnelContextRef.current, {
|
|
11145
11154
|
step_id: step2.id,
|
|
11146
11155
|
step_index: stepIndex,
|
|
11147
11156
|
question_id: questionId,
|
|
@@ -11149,20 +11158,23 @@ function TrackingProvider({
|
|
|
11149
11158
|
is_last_question: isLastQuestion
|
|
11150
11159
|
});
|
|
11151
11160
|
},
|
|
11152
|
-
[
|
|
11161
|
+
[funnelContextRef, currentStepId, state, updateContext]
|
|
11153
11162
|
);
|
|
11154
|
-
return /* @__PURE__ */ jsx(TrackingContext.Provider, { value: {
|
|
11163
|
+
return /* @__PURE__ */ jsx(TrackingContext.Provider, { value: { funnelContextRef, currentStepId, trackAnswer }, children });
|
|
11155
11164
|
}
|
|
11156
11165
|
function useTracking() {
|
|
11157
11166
|
const context = useContext(TrackingContext);
|
|
11158
11167
|
if (!context) {
|
|
11159
|
-
|
|
11160
|
-
|
|
11168
|
+
const defaultRef = {
|
|
11169
|
+
current: {
|
|
11161
11170
|
session_id: "",
|
|
11162
11171
|
funnel_mode: "embedded",
|
|
11163
11172
|
service_type: "",
|
|
11164
11173
|
total_steps: 0
|
|
11165
|
-
}
|
|
11174
|
+
}
|
|
11175
|
+
};
|
|
11176
|
+
return {
|
|
11177
|
+
funnelContextRef: defaultRef,
|
|
11166
11178
|
currentStepId: "",
|
|
11167
11179
|
trackAnswer: () => {
|
|
11168
11180
|
}
|
|
@@ -26660,7 +26672,7 @@ function RequestForm({ header = null }) {
|
|
|
26660
26672
|
}
|
|
26661
26673
|
handleDeliveryAddressChange();
|
|
26662
26674
|
}, [deliveryAddress]);
|
|
26663
|
-
const {
|
|
26675
|
+
const { funnelContextRef } = useTracking();
|
|
26664
26676
|
const handleSubmit = async (values2) => {
|
|
26665
26677
|
var _a3;
|
|
26666
26678
|
handleDisableCTA(true);
|
|
@@ -26676,10 +26688,10 @@ function RequestForm({ header = null }) {
|
|
|
26676
26688
|
if (success) {
|
|
26677
26689
|
setIsActualUkLead(isUkLead);
|
|
26678
26690
|
setShowLeadSuccess(true);
|
|
26679
|
-
trackFormSubmitted(
|
|
26691
|
+
trackFormSubmitted(funnelContextRef.current, {
|
|
26680
26692
|
is_uk_lead: isUkLead
|
|
26681
26693
|
});
|
|
26682
|
-
trackCompleted(
|
|
26694
|
+
trackCompleted(funnelContextRef.current);
|
|
26683
26695
|
return;
|
|
26684
26696
|
} else {
|
|
26685
26697
|
console.error("[HeyCater Funnel] Expected success screen but got success=false. Result:", response);
|
|
@@ -26706,10 +26718,10 @@ function RequestForm({ header = null }) {
|
|
|
26706
26718
|
redirectRoute = `/${router.locale}/account/external/requests/${opportunity.id}`;
|
|
26707
26719
|
}
|
|
26708
26720
|
}
|
|
26709
|
-
trackFormSubmitted(
|
|
26721
|
+
trackFormSubmitted(funnelContextRef.current, {
|
|
26710
26722
|
is_logged_in: !!currentUserAccount
|
|
26711
26723
|
});
|
|
26712
|
-
trackCompleted(
|
|
26724
|
+
trackCompleted(funnelContextRef.current);
|
|
26713
26725
|
actions.setRequest(values2);
|
|
26714
26726
|
redirectToCustomerAccountRequest(redirectRoute);
|
|
26715
26727
|
};
|
|
@@ -29791,7 +29803,7 @@ const LoadingIndicator = ({ variant }) => {
|
|
|
29791
29803
|
const WrapperBox = styled(Box)`
|
|
29792
29804
|
color: var(--embedded-text-color, inherit);
|
|
29793
29805
|
`;
|
|
29794
|
-
function useAbandonmentTracking(
|
|
29806
|
+
function useAbandonmentTracking(funnelContextRef, state) {
|
|
29795
29807
|
const hasTrackedAbandonmentRef = useRef(false);
|
|
29796
29808
|
const hasCompletedRef = useRef(false);
|
|
29797
29809
|
useEffect(() => {
|
|
@@ -29811,7 +29823,7 @@ function useAbandonmentTracking(funnelContext, state) {
|
|
|
29811
29823
|
const handleAbandonment = () => {
|
|
29812
29824
|
if (hasTrackedAbandonmentRef.current) return;
|
|
29813
29825
|
if (hasCompletedRef.current) return;
|
|
29814
|
-
trackAbandoned(
|
|
29826
|
+
trackAbandoned(funnelContextRef.current, {
|
|
29815
29827
|
step_id: stateSnapshot.stepId,
|
|
29816
29828
|
step_index: stateSnapshot.stepIndex
|
|
29817
29829
|
});
|
|
@@ -29832,8 +29844,7 @@ function useAbandonmentTracking(funnelContext, state) {
|
|
|
29832
29844
|
};
|
|
29833
29845
|
}, [
|
|
29834
29846
|
state.status,
|
|
29835
|
-
"qualification" in state && "step" in state.qualification ? state.qualification.step.id : null
|
|
29836
|
-
funnelContext
|
|
29847
|
+
"qualification" in state && "step" in state.qualification ? state.qualification.step.id : null
|
|
29837
29848
|
]);
|
|
29838
29849
|
}
|
|
29839
29850
|
const EmbeddedFunnel = React__default.forwardRef(
|
|
@@ -29859,22 +29870,41 @@ const EmbeddedFunnel = React__default.forwardRef(
|
|
|
29859
29870
|
});
|
|
29860
29871
|
const updateContext = useCallback((patch) => {
|
|
29861
29872
|
funnelContext.current = { ...funnelContext.current, ...patch };
|
|
29873
|
+
if (typeof sessionStorage !== "undefined" && funnelContext.current.session_id) {
|
|
29874
|
+
try {
|
|
29875
|
+
sessionStorage.setItem(
|
|
29876
|
+
`funnel_context_${funnelContext.current.session_id}`,
|
|
29877
|
+
JSON.stringify(funnelContext.current)
|
|
29878
|
+
);
|
|
29879
|
+
} catch (e2) {
|
|
29880
|
+
}
|
|
29881
|
+
}
|
|
29862
29882
|
}, []);
|
|
29863
29883
|
useEffect(() => {
|
|
29864
29884
|
cleanupOldTrackingSessions();
|
|
29865
29885
|
}, []);
|
|
29866
|
-
|
|
29886
|
+
useLayoutEffect(() => {
|
|
29867
29887
|
var _a3, _b2, _c2;
|
|
29868
29888
|
if (!("qualification" in state)) return;
|
|
29869
29889
|
const sessionId = ((_a3 = state.qualification.sessionInfo) == null ? void 0 : _a3.sessionId) || "";
|
|
29870
29890
|
const totalSteps = state.qualification.steps.filter((s3) => !s3.disabled).length;
|
|
29871
29891
|
const serviceType = ((_b2 = state.qualification.answers) == null ? void 0 : _b2.service_type) || "";
|
|
29872
29892
|
const city = (_c2 = state.qualification.answers) == null ? void 0 : _c2.city;
|
|
29893
|
+
let restoredContext = null;
|
|
29894
|
+
if (typeof sessionStorage !== "undefined" && sessionId) {
|
|
29895
|
+
try {
|
|
29896
|
+
const stored = sessionStorage.getItem(`funnel_context_${sessionId}`);
|
|
29897
|
+
if (stored) {
|
|
29898
|
+
restoredContext = JSON.parse(stored);
|
|
29899
|
+
}
|
|
29900
|
+
} catch (e2) {
|
|
29901
|
+
}
|
|
29902
|
+
}
|
|
29873
29903
|
updateContext({
|
|
29874
29904
|
session_id: sessionId,
|
|
29875
29905
|
total_steps: totalSteps,
|
|
29876
|
-
service_type: serviceType,
|
|
29877
|
-
...city
|
|
29906
|
+
service_type: (restoredContext == null ? void 0 : restoredContext.service_type) || serviceType,
|
|
29907
|
+
...(restoredContext == null ? void 0 : restoredContext.city) || city ? { city: (restoredContext == null ? void 0 : restoredContext.city) || city } : {}
|
|
29878
29908
|
});
|
|
29879
29909
|
}, [
|
|
29880
29910
|
"qualification" in state ? (_a2 = state.qualification.sessionInfo) == null ? void 0 : _a2.sessionId : null,
|
|
@@ -29892,7 +29922,7 @@ const EmbeddedFunnel = React__default.forwardRef(
|
|
|
29892
29922
|
});
|
|
29893
29923
|
}
|
|
29894
29924
|
}, [state.status]);
|
|
29895
|
-
useAbandonmentTracking(funnelContext
|
|
29925
|
+
useAbandonmentTracking(funnelContext, state);
|
|
29896
29926
|
const toNextStep2 = useCallback(() => {
|
|
29897
29927
|
actions.nextStep();
|
|
29898
29928
|
}, [actions]);
|
|
@@ -29944,7 +29974,7 @@ const EmbeddedFunnel = React__default.forwardRef(
|
|
|
29944
29974
|
return /* @__PURE__ */ jsx(
|
|
29945
29975
|
TrackingProvider,
|
|
29946
29976
|
{
|
|
29947
|
-
|
|
29977
|
+
funnelContextRef: funnelContext,
|
|
29948
29978
|
updateContext,
|
|
29949
29979
|
currentStepId: stepId,
|
|
29950
29980
|
children: /* @__PURE__ */ jsxs(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heycater/qualification-funnel",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Heycater embedded qualification funnel widget",
|
|
6
6
|
"main": "dist/index.cjs.js",
|
|
@@ -32,7 +32,10 @@
|
|
|
32
32
|
"preview": "vite preview",
|
|
33
33
|
"prepublishOnly": "npm run clean && npm run build",
|
|
34
34
|
"lint": "npx eslint ./src",
|
|
35
|
-
"type-check": "tsc --noEmit"
|
|
35
|
+
"type-check": "tsc --noEmit",
|
|
36
|
+
"test": "vitest",
|
|
37
|
+
"test:ui": "vitest --ui",
|
|
38
|
+
"test:coverage": "vitest --coverage"
|
|
36
39
|
},
|
|
37
40
|
"peerDependencies": {
|
|
38
41
|
"@bugsnag/js": "^7.5.4",
|
|
@@ -66,6 +69,9 @@
|
|
|
66
69
|
},
|
|
67
70
|
"devDependencies": {
|
|
68
71
|
"@svgr/rollup": "^8.1.0",
|
|
72
|
+
"@testing-library/react": "^12.1.5",
|
|
73
|
+
"@testing-library/react-hooks": "^8.0.1",
|
|
74
|
+
"@testing-library/user-event": "^14.5.0",
|
|
69
75
|
"@types/google.maps": "^3.54.1",
|
|
70
76
|
"@types/lodash": "^4.17.0",
|
|
71
77
|
"@types/node": "20.3.2",
|
|
@@ -74,6 +80,8 @@
|
|
|
74
80
|
"@types/react-dom": "^17.0.2",
|
|
75
81
|
"@types/styled-components": "^5.1.26",
|
|
76
82
|
"@vitejs/plugin-react": "^4.2.1",
|
|
83
|
+
"@vitest/ui": "^1.0.0",
|
|
84
|
+
"happy-dom": "^12.10.3",
|
|
77
85
|
"react": "^17.0.2",
|
|
78
86
|
"react-dom": "^17.0.2",
|
|
79
87
|
"rollup-plugin-visualizer": "^6.0.5",
|
|
@@ -81,6 +89,7 @@
|
|
|
81
89
|
"typescript": "5.1.3",
|
|
82
90
|
"vite": "^5.0.10",
|
|
83
91
|
"vite-plugin-dts": "^3.7.0",
|
|
84
|
-
"vite-plugin-static-copy": "^3.1.4"
|
|
92
|
+
"vite-plugin-static-copy": "^3.1.4",
|
|
93
|
+
"vitest": "^1.0.0"
|
|
85
94
|
}
|
|
86
95
|
}
|