@envive-ai/react-hooks 0.3.1 → 0.3.2
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/application/commerce-api.cjs +4 -4
- package/dist/application/commerce-api.js +4 -4
- package/dist/application/models/api/response.d.cts +1 -1
- package/dist/application/models/api/response.d.ts +1 -1
- package/dist/application/models/frontendConfig.d.cts +1 -1
- package/dist/application/models/frontendConfig.d.ts +1 -1
- package/dist/application/models/guards/api/isApiFormResponse.cjs +1 -1
- package/dist/application/models/guards/api/isApiFormResponse.js +1 -1
- package/dist/application/models/guards/api/isApiFormSubmittedResponseAttributes.cjs +1 -1
- package/dist/application/models/guards/api/isApiFormSubmittedResponseAttributes.js +1 -1
- package/dist/application/models/guards/api/isApiOrderResponseAttributes.cjs +2 -2
- package/dist/application/models/guards/api/isApiOrderResponseAttributes.js +2 -2
- package/dist/application/models/guards/api/isApiProductResponseAttributes.cjs +1 -1
- package/dist/application/models/guards/api/isApiProductResponseAttributes.js +1 -1
- package/dist/application/models/guards/api/isApiResponse.cjs +1 -1
- package/dist/application/models/guards/api/isApiResponse.js +1 -1
- package/dist/application/models/guards/api/isApiSearchEventAttributes.cjs +2 -2
- package/dist/application/models/guards/api/isApiSearchEventAttributes.js +2 -2
- package/dist/application/models/message.cjs +1 -1
- package/dist/application/models/message.d.cts +1 -1
- package/dist/application/models/message.d.ts +1 -1
- package/dist/application/models/message.js +1 -1
- package/dist/application/models/validators/validateGraphQLColorsConfig.cjs +2 -1
- package/dist/application/models/validators/validateGraphQLColorsConfig.js +2 -1
- package/dist/application/models/validators/validateGraphQLFrontendConfig.cjs +1 -1
- package/dist/application/models/validators/validateGraphQLFrontendConfig.d.cts +1 -1
- package/dist/application/models/validators/validateGraphQLFrontendConfig.d.ts +1 -1
- package/dist/application/models/validators/validateGraphQLFrontendConfig.js +1 -1
- package/dist/application/utils/analyticsUtils.cjs +2 -2
- package/dist/application/utils/analyticsUtils.js +2 -2
- package/dist/application/utils/domObserver.cjs +1 -1
- package/dist/application/utils/domObserver.js +1 -1
- package/dist/application/utils/elementObserver.cjs +1 -1
- package/dist/application/utils/elementObserver.js +1 -1
- package/dist/application/utils/mutationHelper.cjs +2 -2
- package/dist/application/utils/mutationHelper.js +2 -2
- package/dist/application/utils/nodeSelector.cjs +5 -2
- package/dist/application/utils/nodeSelector.js +5 -2
- package/dist/application/utils/stringUtils.cjs +1 -1
- package/dist/application/utils/stringUtils.js +1 -1
- package/dist/atoms/app/index.cjs +1 -1
- package/dist/atoms/app/index.d.cts +1 -1
- package/dist/atoms/app/index.d.ts +1 -1
- package/dist/atoms/app/index.js +1 -1
- package/dist/atoms/app/variant.cjs +1 -1
- package/dist/atoms/app/variant.d.cts +3 -3
- package/dist/atoms/app/variant.d.ts +3 -3
- package/dist/atoms/app/variant.js +1 -1
- package/dist/atoms/chat/chatState.d.cts +15 -15
- package/dist/atoms/chat/chatState.d.ts +15 -15
- package/dist/atoms/chat/form.d.cts +2 -2
- package/dist/atoms/chat/form.d.ts +2 -2
- package/dist/atoms/chat/index.cjs +1 -1
- package/dist/atoms/chat/index.d.ts +3 -3
- package/dist/atoms/chat/index.js +1 -1
- package/dist/atoms/chat/lastMessage.d.cts +2 -2
- package/dist/atoms/chat/lastMessage.d.ts +2 -2
- package/dist/atoms/chat/messageQueue.cjs +1 -1
- package/dist/atoms/chat/messageQueue.js +1 -1
- package/dist/atoms/chat/performanceMetrics.d.cts +6 -6
- package/dist/atoms/chat/performanceMetrics.d.ts +6 -6
- package/dist/atoms/chat/renderedWidgetRefs.d.cts +2 -2
- package/dist/atoms/chat/renderedWidgetRefs.d.ts +2 -2
- package/dist/atoms/chat/replies.cjs +2 -2
- package/dist/atoms/chat/replies.d.cts +2 -2
- package/dist/atoms/chat/replies.d.ts +2 -2
- package/dist/atoms/chat/replies.js +2 -2
- package/dist/atoms/chat/suggestions.d.cts +2 -2
- package/dist/atoms/chat/suggestions.d.ts +2 -2
- package/dist/atoms/globalSearch/globalSearch.cjs +3 -1
- package/dist/atoms/globalSearch/globalSearch.d.cts +10 -7
- package/dist/atoms/globalSearch/globalSearch.d.ts +10 -7
- package/dist/atoms/globalSearch/globalSearch.js +3 -2
- package/dist/atoms/globalSearch/index.cjs +1 -0
- package/dist/atoms/globalSearch/index.d.cts +2 -2
- package/dist/atoms/globalSearch/index.d.ts +2 -2
- package/dist/atoms/globalSearch/index.js +2 -2
- package/dist/atoms/org/customerService.d.cts +7 -7
- package/dist/atoms/org/customerService.d.ts +6 -6
- package/dist/atoms/org/graphqlConfig.cjs +1 -1
- package/dist/atoms/org/graphqlConfig.d.cts +5 -5
- package/dist/atoms/org/graphqlConfig.d.ts +5 -5
- package/dist/atoms/org/graphqlConfig.js +1 -1
- package/dist/atoms/org/newOrgConfigAtom.d.cts +2 -2
- package/dist/atoms/org/newOrgConfigAtom.d.ts +2 -2
- package/dist/atoms/org/orgAnalyticsConfig.cjs +1 -1
- package/dist/atoms/org/orgAnalyticsConfig.d.cts +6 -6
- package/dist/atoms/org/orgAnalyticsConfig.d.ts +6 -6
- package/dist/atoms/org/orgAnalyticsConfig.js +1 -1
- package/dist/atoms/search/chatSearch.d.cts +17 -17
- package/dist/atoms/search/chatSearch.d.ts +17 -17
- package/dist/atoms/search/searchAPI.cjs +1 -1
- package/dist/atoms/search/searchAPI.d.cts +14 -14
- package/dist/atoms/search/searchAPI.d.ts +14 -14
- package/dist/atoms/search/searchAPI.js +1 -1
- package/dist/atoms/search/searchServiceAdapter.cjs +1 -1
- package/dist/atoms/search/searchServiceAdapter.js +1 -1
- package/dist/atoms/search/types.d.cts +1 -1
- package/dist/atoms/search/types.d.ts +1 -1
- package/dist/atoms/search/utils.d.cts +1 -1
- package/dist/atoms/search/utils.d.ts +1 -1
- package/dist/contexts/amplitudeContext/amplitudeContext.cjs +6 -6
- package/dist/contexts/amplitudeContext/amplitudeContext.js +6 -6
- package/dist/contexts/cdnContext/cdnContext.cjs +1 -1
- package/dist/contexts/cdnContext/cdnContext.js +1 -1
- package/dist/contexts/chatContext/chatContext.cjs +4 -4
- package/dist/contexts/chatContext/chatContext.js +4 -4
- package/dist/contexts/enviveConfigContext/enviveConfigContext.cjs +2 -3
- package/dist/contexts/enviveConfigContext/enviveConfigContext.js +2 -3
- package/dist/contexts/enviveContext/enviveContext.cjs +52 -0
- package/dist/contexts/enviveContext/enviveContext.d.cts +31 -0
- package/dist/contexts/enviveContext/enviveContext.d.ts +31 -0
- package/dist/contexts/enviveContext/enviveContext.js +51 -0
- package/dist/contexts/enviveContext/index.cjs +5 -0
- package/dist/contexts/enviveContext/index.d.cts +3 -0
- package/dist/contexts/enviveContext/index.d.ts +3 -0
- package/dist/contexts/enviveContext/index.js +4 -0
- package/dist/contexts/enviveContext/types.cjs +11 -0
- package/dist/contexts/enviveContext/types.d.cts +8 -0
- package/dist/contexts/enviveContext/types.d.ts +8 -0
- package/dist/contexts/enviveContext/types.js +10 -0
- package/dist/contexts/featureFlagContext/featureFlagContext.cjs +2 -2
- package/dist/contexts/featureFlagContext/featureFlagContext.js +2 -2
- package/dist/contexts/featureFlagServiceContext/featureFlagServiceContext.cjs +2 -2
- package/dist/contexts/featureFlagServiceContext/featureFlagServiceContext.js +2 -2
- package/dist/contexts/graphqlContext/graphqlContext.cjs +3 -3
- package/dist/contexts/graphqlContext/graphqlContext.js +3 -3
- package/dist/contexts/localStorageContext/localStorageContext.cjs +1 -1
- package/dist/contexts/localStorageContext/localStorageContext.js +1 -1
- package/dist/contexts/newOrgConfigContext/newOrgConfigContext.cjs +1 -1
- package/dist/contexts/newOrgConfigContext/newOrgConfigContext.js +1 -1
- package/dist/contexts/searchContext/searchContext.cjs +1 -1
- package/dist/contexts/searchContext/searchContext.js +1 -1
- package/dist/contexts/sessionStorageContext/sessionStorageContext.cjs +1 -1
- package/dist/contexts/sessionStorageContext/sessionStorageContext.js +1 -1
- package/dist/contexts/types.cjs +1 -1
- package/dist/contexts/types.d.cts +1 -1
- package/dist/contexts/types.d.ts +1 -1
- package/dist/contexts/types.js +1 -1
- package/dist/contexts/userIdentityContext/userIdentityContext.cjs +1 -1
- package/dist/contexts/userIdentityContext/userIdentityContext.js +1 -1
- package/dist/events/index.cjs +2 -4
- package/dist/events/index.js +2 -4
- package/dist/hooks/AmplitudeOperations/useAmplitudeOperations.cjs +1 -1
- package/dist/hooks/AmplitudeOperations/useAmplitudeOperations.js +1 -1
- package/dist/hooks/Debounce/useDebounce.cjs +1 -1
- package/dist/hooks/Debounce/useDebounce.js +1 -1
- package/dist/hooks/ElementObserver/useElementObserver.cjs +2 -2
- package/dist/hooks/ElementObserver/useElementObserver.js +2 -2
- package/dist/hooks/IdentifyUser/useIdentifyUser.cjs +1 -1
- package/dist/hooks/IdentifyUser/useIdentifyUser.js +1 -1
- package/dist/hooks/ImageResolver/useImageResolver.cjs +2 -2
- package/dist/hooks/ImageResolver/useImageResolver.js +2 -2
- package/dist/hooks/IsSmallScreen/useIsSmallScreen.cjs +1 -1
- package/dist/hooks/IsSmallScreen/useIsSmallScreen.js +1 -1
- package/dist/hooks/LocalStorageOperations/useLocalStorageOperations.cjs +11 -3
- package/dist/hooks/LocalStorageOperations/useLocalStorageOperations.js +11 -3
- package/dist/hooks/Search/useRecommendedProducts.cjs +1 -1
- package/dist/hooks/Search/useRecommendedProducts.js +1 -1
- package/dist/hooks/Search/useSearch.cjs +6 -3
- package/dist/hooks/Search/useSearch.d.cts +3 -1
- package/dist/hooks/Search/useSearch.d.ts +3 -1
- package/dist/hooks/Search/useSearch.js +7 -4
- package/dist/hooks/Search/useSearchInput.cjs +1 -1
- package/dist/hooks/Search/useSearchInput.js +1 -1
- package/dist/hooks/SearchOperations/useSearchOperations.cjs +1 -1
- package/dist/hooks/SearchOperations/useSearchOperations.d.cts +1 -1
- package/dist/hooks/SearchOperations/useSearchOperations.d.ts +1 -1
- package/dist/hooks/SearchOperations/useSearchOperations.js +1 -1
- package/dist/hooks/SessionStorageOperations/useSessionStorageOperations.cjs +1 -1
- package/dist/hooks/SessionStorageOperations/useSessionStorageOperations.js +1 -1
- package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.cjs +1 -1
- package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.js +1 -1
- package/dist/hooks/utils.cjs +3 -3
- package/dist/hooks/utils.d.ts +1 -1
- package/dist/hooks/utils.js +3 -3
- package/package.json +25 -6
- package/src/application/commerce-api.ts +12 -10
- package/src/application/models/api/nextMessageRequest.ts +2 -0
- package/src/application/models/api/response.ts +4 -4
- package/src/application/models/api/search.ts +1 -2
- package/src/application/models/api/userEvent.ts +1 -2
- package/src/application/models/frontendConfig.ts +2 -2
- package/src/application/models/guards/api/isApiOrderResponseAttributes.ts +8 -4
- package/src/application/models/guards/api/isApiSearchEventAttributes.ts +1 -1
- package/src/application/models/index.ts +1 -0
- package/src/application/models/message.ts +5 -5
- package/src/application/models/utilityTypes/delimiterCase.ts +1 -0
- package/src/application/models/validators/validateGraphQLColorsConfig.ts +2 -1
- package/src/application/models/validators/validateGraphQLFrontendConfig.ts +1 -1
- package/src/application/models/variantInfo/variantInfo.ts +3 -0
- package/src/application/utils/analyticsUtils.ts +3 -3
- package/src/application/utils/domObserver.ts +1 -0
- package/src/application/utils/elementObserver.ts +1 -0
- package/src/application/utils/mutationHelper.ts +3 -1
- package/src/application/utils/nodeSelector.ts +7 -1
- package/src/application/utils/stringUtils.ts +1 -0
- package/src/atoms/app/index.ts +17 -6
- package/src/atoms/app/variant.ts +11 -13
- package/src/atoms/chat/__tests__/messageQueue.test.spec.ts +61 -0
- package/src/atoms/chat/index.ts +8 -8
- package/src/atoms/chat/messageQueue.ts +2 -48
- package/src/atoms/chat/replies.ts +3 -3
- package/src/atoms/org/graphqlConfig.ts +0 -1
- package/src/atoms/org/orgAnalyticsConfig.ts +1 -1
- package/src/atoms/search/searchAPI.ts +1 -1
- package/src/atoms/search/searchServiceAdapter.ts +1 -1
- package/src/contexts/amplitudeContext/__tests__/amplitudeContext.test.tsx +4 -3
- package/src/contexts/amplitudeContext/amplitudeContext.tsx +5 -5
- package/src/contexts/cdnContext/cdnContext.tsx +1 -1
- package/src/contexts/enviveConfigContext/__tests__/enviveConfigContext.test.tsx +2 -3
- package/src/contexts/enviveConfigContext/enviveConfigContext.tsx +3 -3
- package/src/contexts/enviveContext/enviveContext.tsx +89 -0
- package/src/contexts/enviveContext/index.ts +2 -0
- package/src/contexts/enviveContext/types.ts +4 -0
- package/src/contexts/featureFlagContext/featureFlagContext.tsx +1 -1
- package/src/contexts/featureFlagServiceContext/featureFlagServiceContext.tsx +1 -1
- package/src/contexts/graphqlContext/__tests__/graphqlContext.test.tsx +7 -5
- package/src/contexts/graphqlContext/graphqlContext.tsx +1 -5
- package/src/contexts/hardcopyContext/hardcopyContext.tsx +70 -0
- package/src/contexts/hardcopyContext/index.ts +1 -0
- package/src/contexts/localStorageContext/__tests__/localStorageContext.test.tsx +9 -3
- package/src/contexts/localStorageContext/localStorageContext.tsx +1 -1
- package/src/contexts/newOrgConfigContext/__tests__/newOrgConfigContext.test.tsx +2 -3
- package/src/contexts/newOrgConfigContext/newOrgConfigContext.tsx +1 -1
- package/src/contexts/pageContext/__tests__/pageContext.test.tsx +666 -0
- package/src/contexts/pageContext/index.ts +2 -0
- package/src/contexts/pageContext/mapping.ts +38 -0
- package/src/contexts/pageContext/pageContext.tsx +78 -0
- package/src/contexts/pageContext/types.ts +27 -0
- package/src/contexts/salesAgentContext/chatAPI.ts +75 -0
- package/src/contexts/salesAgentContext/index.ts +3 -0
- package/src/contexts/salesAgentContext/salesAgentContext.tsx +128 -0
- package/src/contexts/salesAgentContext/salesAgentService.ts +197 -0
- package/src/contexts/searchContext/__tests__/searchContext.test.tsx +14 -15
- package/src/contexts/searchContext/searchContext.tsx +1 -1
- package/src/contexts/sessionStorageContext/sessionStorageContext.tsx +1 -1
- package/src/contexts/systemSettingsContext/__tests__/systemSettingsContext.test.tsx +7 -6
- package/src/contexts/types.ts +20 -22
- package/src/contexts/userIdentityContext/__tests__/userIdentityContext.test.tsx +3 -8
- package/src/contexts/userIdentityContext/userIdentityContext.tsx +1 -1
- package/src/events/index.ts +5 -7
- package/src/hooks/AmplitudeOperations/useAmplitudeOperations.ts +1 -1
- package/src/hooks/Debounce/useDebounce.ts +1 -1
- package/src/hooks/ElementObserver/useElementObserver.ts +2 -1
- package/src/hooks/GraphQLConfig/useGraphQLConfig.ts +4 -2
- package/src/hooks/IdentifyUser/useIdentifyUser.ts +1 -1
- package/src/hooks/ImageResolver/useImageResolver.ts +2 -0
- package/src/hooks/IsSmallScreen/useIsSmallScreen.ts +1 -1
- package/src/hooks/LocalStorageOperations/useLocalStorageOperations.ts +20 -4
- package/src/hooks/Search/__tests__/useSearch.test.tsx +15 -10
- package/src/hooks/Search/useRecommendedProducts.ts +2 -2
- package/src/hooks/Search/useSearchInput.ts +1 -1
- package/src/hooks/SearchOperations/useSearchOperations.ts +2 -2
- package/src/hooks/SessionStorageOperations/useSessionStorageOperations.ts +1 -1
- package/src/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.ts +2 -2
- package/src/hooks/utils.ts +3 -2
- package/src/contexts/chatContext/chatContext.tsx +0 -463
- package/src/contexts/chatContext/index.ts +0 -1
package/src/atoms/app/variant.ts
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { atomWithStorage } from 'jotai/utils';
|
|
2
2
|
import { atom } from 'jotai';
|
|
3
|
-
import { SupportedEventResponse, PageVisitCategory } from '@spiffy-ai/commerce-api-client';
|
|
4
3
|
import {
|
|
5
|
-
|
|
4
|
+
PageVisitCategory,
|
|
5
|
+
SupportedEventResponse,
|
|
6
|
+
UserEvent,
|
|
7
|
+
} from '@spiffy-ai/commerce-api-client';
|
|
8
|
+
import {
|
|
6
9
|
PDPVariantInfo,
|
|
7
10
|
PLPVariantInfo,
|
|
11
|
+
PageVisitVariantInfo,
|
|
8
12
|
VariantInfo,
|
|
9
13
|
VariantTypeEnum,
|
|
10
14
|
} from 'src/application/models';
|
|
11
15
|
import { sessionStorageUtil } from 'src/atoms/atomStore';
|
|
12
16
|
|
|
13
|
-
export interface SupportedEvent
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
> {
|
|
17
|
+
export interface SupportedEvent extends Pick<
|
|
18
|
+
SupportedEventResponse,
|
|
19
|
+
'supported' | 'ready' | 'category' | 'collections' | 'top_category'
|
|
20
|
+
> {
|
|
18
21
|
numberOfReviews: number | undefined;
|
|
19
22
|
merchant_tags?: string[];
|
|
20
23
|
}
|
|
@@ -88,12 +91,7 @@ export interface UrlResolverResponse {
|
|
|
88
91
|
variant_type: string;
|
|
89
92
|
specific_details: UrlResolvingPDPConfig | UrlResolvingPLPConfig | UrlResolvingGenericConfig;
|
|
90
93
|
ready: boolean;
|
|
91
|
-
user_event?:
|
|
92
|
-
event_id?: string;
|
|
93
|
-
attributes?: PDPAttributes | PLPAttributes;
|
|
94
|
-
category?: string;
|
|
95
|
-
created_at?: string;
|
|
96
|
-
};
|
|
94
|
+
user_event?: UserEvent;
|
|
97
95
|
page_variant?: BackendPageVariantConfig;
|
|
98
96
|
}
|
|
99
97
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
|
|
2
|
+
import { createStore } from 'jotai';
|
|
3
|
+
import { UserEvent } from 'src/application/models';
|
|
4
|
+
import {
|
|
5
|
+
clearUserEventAtom,
|
|
6
|
+
processUserEventAtom,
|
|
7
|
+
queueUserEventAtom,
|
|
8
|
+
userEventQueueAtom,
|
|
9
|
+
userQueueEventCountAtom,
|
|
10
|
+
} from 'src/atoms/chat/messageQueue';
|
|
11
|
+
|
|
12
|
+
const userEvent1 = {
|
|
13
|
+
eventId: '123',
|
|
14
|
+
category: UserEventCategory.AppLoaded,
|
|
15
|
+
createdAt: 'now',
|
|
16
|
+
} satisfies UserEvent;
|
|
17
|
+
const userEvent2 = {
|
|
18
|
+
eventId: '456',
|
|
19
|
+
category: UserEventCategory.AppLoaded,
|
|
20
|
+
createdAt: 'now',
|
|
21
|
+
} satisfies UserEvent;
|
|
22
|
+
|
|
23
|
+
describe('eventQueue', () => {
|
|
24
|
+
it('should be able to enqueue items and show them in the queue', () => {
|
|
25
|
+
const store = createStore();
|
|
26
|
+
store.set(queueUserEventAtom, userEvent1);
|
|
27
|
+
expect(store.get(userEventQueueAtom)).toEqual([userEvent1]);
|
|
28
|
+
expect(store.get(userQueueEventCountAtom)).toBe(1);
|
|
29
|
+
});
|
|
30
|
+
it('should be able to mark eventQueue items as processed and remove them from the queue', () => {
|
|
31
|
+
const store = createStore();
|
|
32
|
+
store.set(queueUserEventAtom, userEvent1);
|
|
33
|
+
store.set(queueUserEventAtom, userEvent2);
|
|
34
|
+
expect(store.get(userEventQueueAtom)).toEqual([userEvent1, userEvent2]);
|
|
35
|
+
expect(store.get(userQueueEventCountAtom)).toBe(2);
|
|
36
|
+
store.set(processUserEventAtom, ['123']);
|
|
37
|
+
expect(store.get(userEventQueueAtom)).toEqual([userEvent2]);
|
|
38
|
+
expect(store.get(userQueueEventCountAtom)).toBe(1);
|
|
39
|
+
});
|
|
40
|
+
it('should be able to mark non-existent eventQueue items as procesed without an exception being raised', () => {
|
|
41
|
+
const store = createStore();
|
|
42
|
+
store.set(queueUserEventAtom, userEvent1);
|
|
43
|
+
store.set(queueUserEventAtom, userEvent2);
|
|
44
|
+
expect(store.get(userEventQueueAtom)).toEqual([userEvent1, userEvent2]);
|
|
45
|
+
expect(store.get(userQueueEventCountAtom)).toBe(2);
|
|
46
|
+
store.set(processUserEventAtom, ['foo']);
|
|
47
|
+
expect(store.get(userEventQueueAtom)).toEqual([userEvent1, userEvent2]);
|
|
48
|
+
expect(store.get(userQueueEventCountAtom)).toBe(2);
|
|
49
|
+
});
|
|
50
|
+
it('should be able to clear all eventQueue items', () => {
|
|
51
|
+
const store = createStore();
|
|
52
|
+
expect(store.get(userQueueEventCountAtom)).toBe(0);
|
|
53
|
+
store.set(queueUserEventAtom, userEvent1);
|
|
54
|
+
store.set(queueUserEventAtom, userEvent2);
|
|
55
|
+
expect(store.get(userEventQueueAtom)).toEqual([userEvent1, userEvent2]);
|
|
56
|
+
expect(store.get(userQueueEventCountAtom)).toBe(2);
|
|
57
|
+
store.set(clearUserEventAtom);
|
|
58
|
+
expect(store.get(userEventQueueAtom)).toEqual([]);
|
|
59
|
+
expect(store.get(userQueueEventCountAtom)).toBe(0);
|
|
60
|
+
});
|
|
61
|
+
});
|
package/src/atoms/chat/index.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { atom } from 'jotai';
|
|
2
2
|
import {
|
|
3
|
-
responseStreamingAtom,
|
|
4
|
-
suggestionsLoadingAtom,
|
|
5
|
-
messagesAtom,
|
|
6
|
-
userQueryAtom,
|
|
7
|
-
replyEventCategoryAtom,
|
|
8
|
-
userHasRepliedAtom,
|
|
9
3
|
askQuestionBtnClickedAtom,
|
|
10
|
-
suggestionsAtom,
|
|
11
4
|
chatIsOpenAtom,
|
|
12
5
|
chatOnToggleAtom,
|
|
13
|
-
|
|
6
|
+
messagesAtom,
|
|
7
|
+
replyEventCategoryAtom,
|
|
8
|
+
responseStreamingAtom,
|
|
14
9
|
suggestionAtom,
|
|
10
|
+
suggestionsAtom,
|
|
11
|
+
suggestionsLoadingAtom,
|
|
12
|
+
userEventsAtom,
|
|
13
|
+
userHasRepliedAtom,
|
|
14
|
+
userQueryAtom,
|
|
15
15
|
} from './chatState';
|
|
16
16
|
|
|
17
17
|
export * from './chatState';
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { atom } from 'jotai';
|
|
2
|
-
import {
|
|
3
|
-
import { GenerationParams, NextMessageRequest, UserEvent } from 'src/application/models';
|
|
4
|
-
import { getAtomStore } from 'src/atoms/atomStore/atomStore';
|
|
5
|
-
import { userIdAtom, chatIdAtom } from 'src/atoms/app';
|
|
6
|
-
import { orgShortNameAtom, contextSourceAtom, envAtom } from 'src/atoms/envive/enviveConfig';
|
|
7
|
-
import { orgIdAtom, featureFlagServiceAtom } from 'src/atoms/org/graphqlConfig';
|
|
2
|
+
import { UserEvent } from 'src/application/models';
|
|
8
3
|
|
|
9
4
|
const internalUserEventQueueAtom = atom<UserEvent[]>([]);
|
|
10
5
|
|
|
@@ -43,46 +38,5 @@ export const processUserEventAtom = atom(null, (get, set, eventIds: string[]) =>
|
|
|
43
38
|
set(internalUserEventQueueAtom, remaining);
|
|
44
39
|
});
|
|
45
40
|
|
|
46
|
-
export const userQueueEventCountAtom = atom(get => get(userEventQueueAtom).length);
|
|
47
|
-
|
|
48
|
-
import { ContextSourceEnum, ContextEnvEnum } from '@spiffy-ai/commerce-api-client'; // Import necessary enums
|
|
41
|
+
export const userQueueEventCountAtom = atom(get => get(userEventQueueAtom).length); // Import necessary enums
|
|
49
42
|
// import type { Context } from "@spiffy-ai/commerce-api-client/dist/models/Context"; // Import Context type
|
|
50
|
-
|
|
51
|
-
export const createResponsePayload = ({
|
|
52
|
-
userEvents,
|
|
53
|
-
generationParams,
|
|
54
|
-
}: {
|
|
55
|
-
userEvents: UserEvent[];
|
|
56
|
-
generationParams?: GenerationParams;
|
|
57
|
-
}): NextMessageRequest => {
|
|
58
|
-
const atomStore = getAtomStore();
|
|
59
|
-
const orgShortName = atomStore.get(orgShortNameAtom);
|
|
60
|
-
const orgId = atomStore.get(orgIdAtom);
|
|
61
|
-
const userId = atomStore.get(userIdAtom);
|
|
62
|
-
const chatId = atomStore.get(chatIdAtom);
|
|
63
|
-
const source = atomStore.get(contextSourceAtom);
|
|
64
|
-
const env = atomStore.get(envAtom);
|
|
65
|
-
|
|
66
|
-
const featureFlagService = atomStore.get(featureFlagServiceAtom);
|
|
67
|
-
|
|
68
|
-
const context = {
|
|
69
|
-
userId: userId ?? '',
|
|
70
|
-
org_id: orgId ?? '',
|
|
71
|
-
org_short_name: orgShortName ?? '',
|
|
72
|
-
chat_id: chatId ?? '',
|
|
73
|
-
source: source ?? ContextSourceEnum.App,
|
|
74
|
-
env: (env as ContextEnvEnum) ?? ContextEnvEnum.Dev,
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const featureFlags = featureFlagService?.featureFlagService?.getFeatureFlags() || {};
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
id: uuid(),
|
|
81
|
-
context,
|
|
82
|
-
userEvents,
|
|
83
|
-
featureFlags: Object.fromEntries(
|
|
84
|
-
Object.entries(featureFlags).filter(([, isEnabled]) => isEnabled),
|
|
85
|
-
), // Convert back to Record<string, boolean>
|
|
86
|
-
generationParams,
|
|
87
|
-
};
|
|
88
|
-
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { atom } from 'jotai';
|
|
2
2
|
import { Message, MessageType } from 'src/application/models';
|
|
3
3
|
import {
|
|
4
|
-
userHasRepliedAtom,
|
|
5
4
|
messagesAtom,
|
|
6
|
-
userQueryAtom,
|
|
7
5
|
replyEventCategoryAtom,
|
|
6
|
+
userHasRepliedAtom,
|
|
7
|
+
userQueryAtom,
|
|
8
8
|
} from 'src/atoms/chat';
|
|
9
9
|
import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
|
|
10
|
-
import { queueUserEventAtom } from './messageQueue';
|
|
11
10
|
import { SpiffyMetricsEventName } from 'src/contexts/amplitudeContext/amplitudeContext';
|
|
12
11
|
import { amplitudeTrackEventAtom } from 'src/atoms/amplitude/amplitudeTrackEventAtom';
|
|
12
|
+
import { queueUserEventAtom } from './messageQueue';
|
|
13
13
|
|
|
14
14
|
type HandleReplyParams = {
|
|
15
15
|
message: Message;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { atom } from 'jotai';
|
|
2
2
|
import { ColorMapping } from 'src/application/models/colorsConfig';
|
|
3
3
|
import { FrontendConfig } from 'src/application/models/frontendConfig';
|
|
4
|
-
import { orgShortNameAtom } from '../envive/enviveConfig';
|
|
5
4
|
import { FeatureFlagContextType } from 'src/contexts/featureFlagServiceContext/featureFlagServiceContext'; // Import FeatureFlagContextType from new context
|
|
6
5
|
|
|
7
6
|
export const internalGraphQLColorsConfigAtom = atom<ColorMapping | undefined>(undefined);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { atom } from 'jotai';
|
|
2
|
-
import {
|
|
2
|
+
import { SearchParams, SearchResult } from 'src/application/models/api/search';
|
|
3
3
|
import { ProductSorting } from './types';
|
|
4
4
|
import { ProductFilters } from './productFilters';
|
|
5
5
|
import { ProductSorter } from './productSorter';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SearchParams, SearchResult } from 'src/application/models/api/search';
|
|
2
2
|
|
|
3
3
|
// This will be set by the SearchProvider when it initializes
|
|
4
4
|
let searchServiceFunction: ((params: SearchParams) => Promise<SearchResult>) | null = null;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, waitFor
|
|
2
|
+
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
3
3
|
import { Provider, useStore } from 'jotai';
|
|
4
|
-
import { AmplitudeProvider, useAmplitude, SpiffyMetricsEventName } from '../amplitudeContext';
|
|
5
4
|
import {
|
|
6
5
|
UserIdentityProvider,
|
|
7
6
|
useUserIdentity,
|
|
@@ -11,7 +10,7 @@ import { EnviveConfigProvider } from 'src/contexts/enviveConfigContext/enviveCon
|
|
|
11
10
|
import { FeatureFlagServiceProvider } from 'src/contexts/featureFlagServiceContext/featureFlagServiceContext';
|
|
12
11
|
import { userIdAtom } from 'src/atoms/app';
|
|
13
12
|
import Logger from 'src/application/logging/logger';
|
|
14
|
-
import {
|
|
13
|
+
import { AmplitudeProvider, SpiffyMetricsEventName, useAmplitude } from '../amplitudeContext';
|
|
15
14
|
|
|
16
15
|
// Mock the Logger to avoid console output in tests
|
|
17
16
|
// vi.spyOn(Logger, "logInfo").mockImplementation(() => {});
|
|
@@ -62,6 +61,7 @@ const MockAmplitudeComponent: React.FC = () => {
|
|
|
62
61
|
<div data-testid="is-ready">{amplitude.isReady.toString()}</div>
|
|
63
62
|
<button
|
|
64
63
|
data-testid="track-event-button"
|
|
64
|
+
type="button"
|
|
65
65
|
onClick={() =>
|
|
66
66
|
amplitude.trackEvent({
|
|
67
67
|
eventName: SpiffyMetricsEventName.ChatUserMessageInput,
|
|
@@ -373,6 +373,7 @@ describe('AmplitudeProvider with UserIdentityContext', () => {
|
|
|
373
373
|
return (
|
|
374
374
|
<button
|
|
375
375
|
data-testid="track-multiple"
|
|
376
|
+
type="button"
|
|
376
377
|
onClick={trackMultiple}
|
|
377
378
|
>
|
|
378
379
|
Track Multiple
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext,
|
|
1
|
+
import React, { createContext, useCallback, useContext, useEffect, useMemo } from 'react';
|
|
2
2
|
import { useAtomValue } from 'jotai';
|
|
3
3
|
import { createInstance } from '@amplitude/analytics-browser';
|
|
4
4
|
import { FeatureGates } from 'src/application/models/featureGates';
|
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
amplitudeApiKeyAtom,
|
|
9
9
|
contextSourceAtom,
|
|
10
10
|
dataResidencyAtom,
|
|
11
|
+
envAtom,
|
|
11
12
|
identifyingPrefixAtom,
|
|
12
13
|
} from 'src/atoms/envive/enviveConfig';
|
|
13
14
|
import { LocalStorageKeys, useLocalStorage } from 'src/contexts/localStorageContext';
|
|
14
15
|
import { orgAnalyticsGoogleAnalyticsConfigAtom } from 'src/atoms/org/orgAnalyticsConfig';
|
|
15
16
|
import { userIdAtom } from 'src/atoms/app';
|
|
16
|
-
import { envAtom } from 'src/atoms/envive/enviveConfig';
|
|
17
17
|
import Logger from 'src/application/logging/logger';
|
|
18
18
|
import type {
|
|
19
19
|
BrowserClient,
|
|
@@ -162,8 +162,8 @@ export const AmplitudeProvider: React.FC<{ children: React.ReactNode }> = ({ chi
|
|
|
162
162
|
const amplitudeSessionReplayInit = useCallback((): boolean => {
|
|
163
163
|
const isEnabled = Boolean(
|
|
164
164
|
orgShortName === OrgShortName.UniqueVintage &&
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
featureFlagService?.isClientSessionEnabled() &&
|
|
166
|
+
featureFlagService?.isFeatureGateEnabled(FeatureGates.IsNewFeatureEnabled),
|
|
167
167
|
);
|
|
168
168
|
const sampleRate = 1;
|
|
169
169
|
|
|
@@ -358,7 +358,7 @@ export const AmplitudeProvider: React.FC<{ children: React.ReactNode }> = ({ chi
|
|
|
358
358
|
if (window.dataLayer) {
|
|
359
359
|
(window.dataLayer as any[]).push({
|
|
360
360
|
event: decoratedEventName,
|
|
361
|
-
eventProps
|
|
361
|
+
eventProps,
|
|
362
362
|
});
|
|
363
363
|
}
|
|
364
364
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
3
|
-
import { Provider } from 'jotai';
|
|
4
|
-
import { useAtomValue } from 'jotai';
|
|
5
|
-
import { EnviveConfigProvider, useEnviveConfig } from '../enviveConfigContext';
|
|
3
|
+
import { Provider, useAtomValue } from 'jotai';
|
|
6
4
|
import { enviveConfigAtom } from 'src/atoms/envive/enviveConfig';
|
|
7
5
|
import Logger from 'src/application/logging/logger';
|
|
6
|
+
import { EnviveConfigProvider, useEnviveConfig } from '../enviveConfigContext';
|
|
8
7
|
|
|
9
8
|
// Mock the Logger to avoid console output in tests
|
|
10
9
|
vi.spyOn(Logger, 'logDebug').mockImplementation(() => {});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
1
|
+
import React, { ReactNode, createContext, useEffect } from 'react';
|
|
2
|
+
import { useAtomValue, useSetAtom } from 'jotai';
|
|
3
3
|
import { enviveConfigAtom } from 'src/atoms/envive/enviveConfig';
|
|
4
4
|
import Logger from 'src/application/logging/logger';
|
|
5
5
|
import { OrgConfigFeatureGate } from 'src/application/models/api/orgConfigResults';
|
|
@@ -82,5 +82,5 @@ export const EnviveConfigProvider: React.FC<EnviveConfigProviderProps> = ({
|
|
|
82
82
|
export const useEnviveConfig = (): EnviveConfig => {
|
|
83
83
|
const config = useAtomValue(enviveConfigAtom);
|
|
84
84
|
|
|
85
|
-
return config
|
|
85
|
+
return config || {};
|
|
86
86
|
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ReactNode, createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
import { OrgConfigFeatureGate } from 'src/application/models/api/orgConfigResults';
|
|
4
|
+
import { AmplitudeProvider } from '../amplitudeContext';
|
|
5
|
+
import { EnviveConfigProvider } from '../enviveConfigContext';
|
|
6
|
+
import { EnviveCssProvider } from '../enviveCssContext';
|
|
7
|
+
import { FeatureFlagServiceProvider } from '../featureFlagServiceContext';
|
|
8
|
+
import { GraphQLProvider } from '../graphqlContext';
|
|
9
|
+
import { LocalStorageProvider } from '../localStorageContext';
|
|
10
|
+
import { NewOrgConfigProvider } from '../newOrgConfigContext';
|
|
11
|
+
import { UserIdentityProvider } from '../userIdentityContext';
|
|
12
|
+
import { EnviveAgent } from './types';
|
|
13
|
+
import { SearchProvider } from '../searchContext';
|
|
14
|
+
import { SalesAgentProvider } from '../salesAgentContext/salesAgentContext';
|
|
15
|
+
import { SystemSettingsContextProvider } from '../systemSettingsContext';
|
|
16
|
+
|
|
17
|
+
const EnviveContext = createContext<null>(null);
|
|
18
|
+
|
|
19
|
+
interface AgentWrapperProps {
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
enabledAgents: EnviveAgent[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface EnviveProviderProps extends AgentWrapperProps {
|
|
25
|
+
amplitudeApiKey?: string;
|
|
26
|
+
dataResidency?: string;
|
|
27
|
+
env?: string;
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
reactAppName?: string;
|
|
30
|
+
cdnUrl?: string;
|
|
31
|
+
contextSource?: string;
|
|
32
|
+
orgLevelApiKey?: string;
|
|
33
|
+
orgShortName?: string;
|
|
34
|
+
identifyingPrefix: string;
|
|
35
|
+
featureOverrides?: Record<string, boolean>;
|
|
36
|
+
variantUrlOverride?: string;
|
|
37
|
+
variantInfoOverride?: any;
|
|
38
|
+
show?: boolean;
|
|
39
|
+
publicKey?: string;
|
|
40
|
+
featureGates?: OrgConfigFeatureGate[]; // New prop for feature gates
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const SearchAgentWrapper: React.FC<AgentWrapperProps> = ({ children, enabledAgents }) => {
|
|
44
|
+
if (!enabledAgents.includes(EnviveAgent.SearchAgent)) {
|
|
45
|
+
return children;
|
|
46
|
+
}
|
|
47
|
+
return <SearchProvider>{children}</SearchProvider>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const SalesAgentWrapper: React.FC<AgentWrapperProps> = ({ children, enabledAgents }) => {
|
|
51
|
+
if (!enabledAgents.includes(EnviveAgent.SalesAgent)) {
|
|
52
|
+
return children;
|
|
53
|
+
}
|
|
54
|
+
return (
|
|
55
|
+
<SystemSettingsContextProvider>
|
|
56
|
+
<SalesAgentProvider>{children}</SalesAgentProvider>
|
|
57
|
+
</SystemSettingsContextProvider>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const EnviveProvider: React.FC<EnviveProviderProps> = ({
|
|
62
|
+
children,
|
|
63
|
+
enabledAgents,
|
|
64
|
+
...config
|
|
65
|
+
}) => (
|
|
66
|
+
<EnviveContext.Provider value={null}>
|
|
67
|
+
<EnviveConfigProvider {...config}>
|
|
68
|
+
<GraphQLProvider>
|
|
69
|
+
<NewOrgConfigProvider>
|
|
70
|
+
<LocalStorageProvider>
|
|
71
|
+
<FeatureFlagServiceProvider featureGates={[]}>
|
|
72
|
+
<UserIdentityProvider>
|
|
73
|
+
<AmplitudeProvider>
|
|
74
|
+
<EnviveCssProvider>
|
|
75
|
+
<SearchAgentWrapper enabledAgents={enabledAgents}>
|
|
76
|
+
<SalesAgentWrapper enabledAgents={enabledAgents}>
|
|
77
|
+
{children}
|
|
78
|
+
</SalesAgentWrapper>
|
|
79
|
+
</SearchAgentWrapper>
|
|
80
|
+
</EnviveCssProvider>
|
|
81
|
+
</AmplitudeProvider>
|
|
82
|
+
</UserIdentityProvider>
|
|
83
|
+
</FeatureFlagServiceProvider>
|
|
84
|
+
</LocalStorageProvider>
|
|
85
|
+
</NewOrgConfigProvider>
|
|
86
|
+
</GraphQLProvider>
|
|
87
|
+
</EnviveConfigProvider>
|
|
88
|
+
</EnviveContext.Provider>
|
|
89
|
+
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext,
|
|
1
|
+
import React, { createContext, useCallback, useContext, useMemo } from 'react';
|
|
2
2
|
import Logger from 'src/application/logging/logger';
|
|
3
3
|
import { StatsigFeatureGate } from '@spiffy-ai/commerce-api-client';
|
|
4
4
|
import { FeatureGates } from 'src/application/models/featureGates';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext, useMemo
|
|
1
|
+
import React, { ReactNode, createContext, useContext, useMemo } from 'react';
|
|
2
2
|
import { OrgConfigFeatureGate } from 'src/application/models/api/orgConfigResults';
|
|
3
3
|
import { FeatureGates } from 'src/application/models/featureGates';
|
|
4
4
|
import Logger from 'src/application/logging/logger';
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, waitFor
|
|
3
|
-
import { Provider } from 'jotai';
|
|
4
|
-
import { useAtomValue } from 'jotai';
|
|
5
|
-
import { GraphQLProvider, useGraphQLClient } from '../graphqlContext';
|
|
2
|
+
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
3
|
+
import { Provider, useAtomValue } from 'jotai';
|
|
6
4
|
import { EnviveConfigProvider } from 'src/contexts/enviveConfigContext/enviveConfigContext';
|
|
7
|
-
import {
|
|
5
|
+
import { baseUrlAtom, orgLevelApiKeyAtom } from 'src/atoms/envive/enviveConfig';
|
|
8
6
|
import Logger from 'src/application/logging/logger';
|
|
9
7
|
import { getMerchantOrgIdQuery } from 'src/application/models/graphql/queries/getMerchantOrgIdQuery';
|
|
8
|
+
import { GraphQLProvider, useGraphQLClient } from '../graphqlContext';
|
|
10
9
|
|
|
11
10
|
// Mock the Logger to avoid console output in tests
|
|
12
11
|
vi.spyOn(Logger, 'logDebug').mockImplementation(() => {});
|
|
@@ -25,6 +24,7 @@ const MockGraphQLComponent: React.FC = () => {
|
|
|
25
24
|
<div data-testid="is-ready">{client.isReady.toString()}</div>
|
|
26
25
|
<button
|
|
27
26
|
data-testid="execute-query-btn"
|
|
27
|
+
type="button"
|
|
28
28
|
onClick={async () => {
|
|
29
29
|
try {
|
|
30
30
|
const result = await client.executeQuery('query { test }');
|
|
@@ -38,6 +38,7 @@ const MockGraphQLComponent: React.FC = () => {
|
|
|
38
38
|
</button>
|
|
39
39
|
<button
|
|
40
40
|
data-testid="get-org-id-btn"
|
|
41
|
+
type="button"
|
|
41
42
|
onClick={async () => {
|
|
42
43
|
try {
|
|
43
44
|
const orgId = await client.getOrgId();
|
|
@@ -51,6 +52,7 @@ const MockGraphQLComponent: React.FC = () => {
|
|
|
51
52
|
</button>
|
|
52
53
|
<button
|
|
53
54
|
data-testid="get-config-btn"
|
|
55
|
+
type="button"
|
|
54
56
|
onClick={async () => {
|
|
55
57
|
try {
|
|
56
58
|
const config = await client.getColorsAndFrontendConfig();
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { ReactNode, createContext, useCallback, useContext, useMemo } from 'react';
|
|
2
2
|
import { useAtomValue } from 'jotai';
|
|
3
3
|
import { baseUrlAtom, orgLevelApiKeyAtom } from 'src/atoms/envive/enviveConfig';
|
|
4
4
|
import { getMerchantOrgIdQuery } from 'src/application/models/graphql/queries/getMerchantOrgIdQuery';
|
|
5
5
|
import { validateGraphQLOrgId } from 'src/application/models/validators/validateGraphQLOrgId';
|
|
6
6
|
import {
|
|
7
|
-
getMerchantColorsQuery,
|
|
8
7
|
GetMerchantColorsQueryData,
|
|
9
|
-
getMerchantFrontendConfigQuery,
|
|
10
8
|
GetMerchantFrontendConfigQueryData,
|
|
11
9
|
} from 'src/application/models/graphql';
|
|
12
|
-
import { validateGraphQLColorsConfig } from 'src/application/models/validators/validateGraphQLColorsConfig';
|
|
13
|
-
import { validateGraphQLFrontendConfig } from 'src/application/models/validators/validateGraphQLFrontendConfig';
|
|
14
10
|
import { ColorMapping } from 'src/application/models/colorsConfig';
|
|
15
11
|
import { FrontendConfig } from 'src/application/models/frontendConfig';
|
|
16
12
|
import Logger from 'src/application/logging/logger';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { UserEvent } from '@spiffy-ai/commerce-api-client';
|
|
2
|
+
import { ReactNode, createContext, useCallback, useContext, useMemo } from 'react';
|
|
3
|
+
import Logger from 'src/application/logging/logger';
|
|
4
|
+
import { WidgetTypeV3 } from '../types';
|
|
5
|
+
|
|
6
|
+
interface HardcopyRequest {
|
|
7
|
+
widgetType: WidgetTypeV3;
|
|
8
|
+
userEvent: UserEvent;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type HardcopyResponse = {
|
|
12
|
+
language: string;
|
|
13
|
+
values: Record<string, string | string[]>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
interface HardcopyContextType {
|
|
17
|
+
getHardcopy: (HardcopyRequest: HardcopyRequest) => Promise<HardcopyResponse>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// These are just sample responses for the sake of testing.
|
|
21
|
+
// As we start to build the actual widgets we should determine what the actual
|
|
22
|
+
// values and their names should be.
|
|
23
|
+
const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> = {
|
|
24
|
+
[WidgetTypeV3.SuggestionBarV3]: {
|
|
25
|
+
language: 'en',
|
|
26
|
+
values: {
|
|
27
|
+
suggestionBarButtons: ['Button 1', 'Button 2', 'Button 3'],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
[WidgetTypeV3.ChatPreviewV3]: {
|
|
31
|
+
language: 'en',
|
|
32
|
+
values: {
|
|
33
|
+
chatPreviewTitle: 'Chat Preview Title',
|
|
34
|
+
typewriterTextPrefix: 'Want to know',
|
|
35
|
+
typewriterTexts: ['more about this product?', 'what others are saying?', 'how to use it?'],
|
|
36
|
+
suggestionButtons: ['Button 1', 'Button 2', 'Button 3'],
|
|
37
|
+
footerText: 'Ask me anything...',
|
|
38
|
+
|
|
39
|
+
chatPreviewDescription: 'Chat Preview Description',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const HardcopyContext = createContext<HardcopyContextType | undefined>(undefined);
|
|
45
|
+
|
|
46
|
+
export const HardcopyProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
|
|
47
|
+
const languages = useMemo(() => navigator.languages, []);
|
|
48
|
+
|
|
49
|
+
const getHardcopy = useCallback(async (request: HardcopyRequest): Promise<HardcopyResponse> => {
|
|
50
|
+
Logger.logInfo('hardcopyContext | retrieving hardcopy', languages);
|
|
51
|
+
const response = MOCK_HARDCOPY_RESPONSE[request.widgetType];
|
|
52
|
+
Logger.logInfo('hardcopyContext | returning hardcopy response', response);
|
|
53
|
+
if (!response) {
|
|
54
|
+
throw new Error(`No hardcopy response found for widget type: ${request.widgetType}`);
|
|
55
|
+
}
|
|
56
|
+
return response;
|
|
57
|
+
}, []);
|
|
58
|
+
|
|
59
|
+
const value = useMemo(() => ({ getHardcopy }), [getHardcopy]);
|
|
60
|
+
|
|
61
|
+
return <HardcopyContext.Provider value={value}>{children}</HardcopyContext.Provider>;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const useHardcopy = () => {
|
|
65
|
+
const context = useContext(HardcopyContext);
|
|
66
|
+
if (!context) {
|
|
67
|
+
throw new Error('useHardcopy must be used within a HardcopyProvider');
|
|
68
|
+
}
|
|
69
|
+
return context;
|
|
70
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './hardcopyContext';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, waitFor
|
|
3
|
-
import { LocalStorageProvider, useLocalStorage, LocalStorageKeys } from '../localStorageContext';
|
|
2
|
+
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
4
3
|
import Logger from 'src/application/logging/logger';
|
|
5
4
|
import { LocalStorageEventListener } from 'src/application/models/localStorageEventListener';
|
|
5
|
+
import { LocalStorageKeys, LocalStorageProvider, useLocalStorage } from '../localStorageContext';
|
|
6
6
|
|
|
7
7
|
// Mock the Logger to avoid console output in tests
|
|
8
8
|
vi.spyOn(Logger, 'logDebug').mockImplementation(() => {});
|
|
@@ -56,6 +56,7 @@ const MockLocalStorageComponent: React.FC = () => {
|
|
|
56
56
|
<div data-testid="event-received">{eventReceived.toString()}</div>
|
|
57
57
|
<button
|
|
58
58
|
data-testid="set-item-btn"
|
|
59
|
+
type="button"
|
|
59
60
|
onClick={() => {
|
|
60
61
|
setItem('test-key', 'test-value');
|
|
61
62
|
setTestValue(getItem('test-key'));
|
|
@@ -65,6 +66,7 @@ const MockLocalStorageComponent: React.FC = () => {
|
|
|
65
66
|
</button>
|
|
66
67
|
<button
|
|
67
68
|
data-testid="set-spiffy-on-true-btn"
|
|
69
|
+
type="button"
|
|
68
70
|
onClick={() => {
|
|
69
71
|
setSpiffyOnFeatureFlag(true);
|
|
70
72
|
setSpiffyOnValue(getSpiffyOnFeatureFlag());
|
|
@@ -74,6 +76,7 @@ const MockLocalStorageComponent: React.FC = () => {
|
|
|
74
76
|
</button>
|
|
75
77
|
<button
|
|
76
78
|
data-testid="set-spiffy-on-false-btn"
|
|
79
|
+
type="button"
|
|
77
80
|
onClick={() => {
|
|
78
81
|
setSpiffyOnFeatureFlag(false);
|
|
79
82
|
setSpiffyOnValue(getSpiffyOnFeatureFlag());
|
|
@@ -83,6 +86,7 @@ const MockLocalStorageComponent: React.FC = () => {
|
|
|
83
86
|
</button>
|
|
84
87
|
<button
|
|
85
88
|
data-testid="trigger-event-btn"
|
|
89
|
+
type="button"
|
|
86
90
|
onClick={() => {
|
|
87
91
|
setItem('test-listener-key', 'event-value');
|
|
88
92
|
}}
|
|
@@ -479,7 +483,9 @@ describe('LocalStorageProvider', () => {
|
|
|
479
483
|
});
|
|
480
484
|
|
|
481
485
|
// Wait a bit to ensure listener is attached
|
|
482
|
-
await new Promise(resolve =>
|
|
486
|
+
await new Promise(resolve => {
|
|
487
|
+
setTimeout(resolve, 50);
|
|
488
|
+
});
|
|
483
489
|
|
|
484
490
|
await act(async () => {
|
|
485
491
|
screen.getByTestId('trigger-event-btn').click();
|