@envive-ai/react-hooks 0.3.15-beta.1 → 0.3.15

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.
Files changed (87) hide show
  1. package/dist/application/commerce-api.cjs +38 -1
  2. package/dist/application/commerce-api.d.cts +13 -2
  3. package/dist/application/commerce-api.d.ts +13 -2
  4. package/dist/application/commerce-api.js +39 -2
  5. package/dist/application/models/index.d.cts +9 -9
  6. package/dist/application/models/index.d.ts +9 -9
  7. package/dist/application/utils/productRetrievalResponseToProductRetrievalResult.cjs +18 -0
  8. package/dist/application/utils/productRetrievalResponseToProductRetrievalResult.js +18 -0
  9. package/dist/atoms/app/index.d.cts +1 -1
  10. package/dist/atoms/app/index.d.ts +1 -1
  11. package/dist/atoms/app/variant.d.cts +6 -6
  12. package/dist/atoms/chat/chatState.d.cts +18 -18
  13. package/dist/atoms/chat/form.d.cts +3 -3
  14. package/dist/atoms/chat/form.d.ts +2 -2
  15. package/dist/atoms/chat/index.d.cts +3 -3
  16. package/dist/atoms/chat/index.d.ts +3 -3
  17. package/dist/atoms/chat/lastMessage.d.cts +2 -2
  18. package/dist/atoms/chat/lastMessage.d.ts +2 -2
  19. package/dist/atoms/chat/messageQueue.d.cts +6 -6
  20. package/dist/atoms/chat/messageQueue.d.ts +6 -6
  21. package/dist/atoms/chat/performanceMetrics.d.cts +7 -7
  22. package/dist/atoms/chat/performanceMetrics.d.ts +6 -6
  23. package/dist/atoms/chat/renderedWidgetRefs.d.cts +2 -2
  24. package/dist/atoms/chat/renderedWidgetRefs.d.ts +2 -2
  25. package/dist/atoms/chat/replies.d.cts +3 -3
  26. package/dist/atoms/chat/replies.d.ts +2 -2
  27. package/dist/atoms/chat/suggestions.d.cts +3 -3
  28. package/dist/atoms/chat/suggestions.d.ts +2 -2
  29. package/dist/atoms/envive/enviveConfig.d.cts +13 -13
  30. package/dist/atoms/envive/enviveConfig.d.ts +13 -13
  31. package/dist/atoms/globalSearch/globalSearch.d.cts +5 -5
  32. package/dist/atoms/globalSearch/globalSearch.d.ts +5 -5
  33. package/dist/atoms/org/customerService.d.cts +6 -6
  34. package/dist/atoms/org/customerService.d.ts +6 -6
  35. package/dist/atoms/org/graphqlConfig.d.cts +4 -4
  36. package/dist/atoms/org/graphqlConfig.d.ts +4 -4
  37. package/dist/atoms/org/newOrgConfigAtom.d.cts +2 -2
  38. package/dist/atoms/org/newOrgConfigAtom.d.ts +2 -2
  39. package/dist/atoms/org/orgAnalyticsConfig.d.cts +5 -5
  40. package/dist/atoms/org/orgAnalyticsConfig.d.ts +5 -5
  41. package/dist/atoms/search/chatSearch.d.cts +18 -18
  42. package/dist/atoms/search/chatSearch.d.ts +18 -18
  43. package/dist/atoms/search/searchAPI.d.cts +14 -14
  44. package/dist/atoms/search/searchAPI.d.ts +14 -14
  45. package/dist/atoms/widget/chatPreviewLoading.d.cts +2 -2
  46. package/dist/atoms/widget/chatPreviewLoading.d.ts +2 -2
  47. package/dist/contexts/graphqlContext/graphqlContext.d.cts +1 -1
  48. package/dist/contexts/graphqlContext/graphqlContext.d.ts +1 -1
  49. package/dist/contexts/salesAgentContext/chatAPI.cjs +5 -4
  50. package/dist/contexts/salesAgentContext/chatAPI.d.cts +3 -2
  51. package/dist/contexts/salesAgentContext/chatAPI.d.ts +3 -2
  52. package/dist/contexts/salesAgentContext/chatAPI.js +5 -4
  53. package/dist/contexts/salesAgentContext/salesAgentContext.cjs +4 -4
  54. package/dist/contexts/salesAgentContext/salesAgentContext.d.cts +3 -2
  55. package/dist/contexts/salesAgentContext/salesAgentContext.d.ts +3 -2
  56. package/dist/contexts/salesAgentContext/salesAgentContext.js +4 -4
  57. package/dist/contexts/systemSettingsContext/systemSettingsContext.d.ts +2 -2
  58. package/dist/contexts/types.d.cts +1 -1
  59. package/dist/contexts/types.d.ts +1 -1
  60. package/dist/contexts/typesV3.d.cts +1 -1
  61. package/dist/contexts/typesV3.d.ts +1 -1
  62. package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.cts +2 -2
  63. package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.ts +2 -2
  64. package/dist/hooks/ProductImageUrl/index.cjs +3 -0
  65. package/dist/hooks/ProductImageUrl/index.d.cts +2 -0
  66. package/dist/hooks/ProductImageUrl/index.d.ts +2 -0
  67. package/dist/hooks/ProductImageUrl/index.js +3 -0
  68. package/dist/hooks/ProductImageUrl/useProductImageUrl.cjs +33 -0
  69. package/dist/hooks/ProductImageUrl/useProductImageUrl.d.cts +9 -0
  70. package/dist/hooks/ProductImageUrl/useProductImageUrl.d.ts +9 -0
  71. package/dist/hooks/ProductImageUrl/useProductImageUrl.js +32 -0
  72. package/dist/hooks/Search/useSearch.d.cts +1 -1
  73. package/dist/hooks/Search/useSearch.d.ts +1 -1
  74. package/dist/hooks/WidgetInteraction/types.cjs +2 -1
  75. package/dist/hooks/WidgetInteraction/types.d.cts +2 -1
  76. package/dist/hooks/WidgetInteraction/types.d.ts +2 -1
  77. package/dist/hooks/WidgetInteraction/types.js +2 -1
  78. package/dist/hooks/utils.d.cts +1 -1
  79. package/dist/hooks/utils.d.ts +1 -1
  80. package/package.json +5 -1
  81. package/src/application/commerce-api.ts +51 -0
  82. package/src/application/utils/productRetrievalResponseToProductRetrievalResult.ts +21 -0
  83. package/src/contexts/salesAgentContext/chatAPI.ts +4 -3
  84. package/src/contexts/salesAgentContext/salesAgentContext.tsx +7 -6
  85. package/src/hooks/ProductImageUrl/index.ts +1 -0
  86. package/src/hooks/ProductImageUrl/useProductImageUrl.ts +35 -0
  87. package/src/hooks/WidgetInteraction/types.ts +1 -0
@@ -7,6 +7,7 @@ import {
7
7
  DefaultApi,
8
8
  FormType,
9
9
  InferenceApi,
10
+ ProductsApi,
10
11
  ReportSessionRequest,
11
12
  ResponseCategory,
12
13
  ResponseError,
@@ -16,6 +17,7 @@ import {
16
17
  V1OrgConfigGetSourceEnum,
17
18
  } from '@spiffy-ai/commerce-api-client';
18
19
  import type { Context } from '@spiffy-ai/commerce-api-client/dist/models/Context';
20
+ import type { ProductRetrievalResult } from 'src/atoms/search/types';
19
21
  import Logger from 'src/application/logging/logger';
20
22
  import {
21
23
  Message,
@@ -57,6 +59,7 @@ import { SessionRestartRequired } from 'src/types/exceptions/sessionExceptions';
57
59
  import { UnsupportedProductException } from 'src/types/exceptions/unsupportedProductExceptions';
58
60
  import { WidgetText } from './models/api/widgetText';
59
61
  import { WidgetTextRequest } from './models/api/widgetTextRequest';
62
+ import { productRetrievalResponseToProductRetrievalResult } from './utils/productRetrievalResponseToProductRetrievalResult';
60
63
  import { apiWidgetTextResponseToCoreWidgetText } from './utils/widgetTextFromApiWidgetTextResponse';
61
64
  import { coreWidgetTextRequestToApiRequest } from './utils/widgetTextRequestToApiRequest';
62
65
 
@@ -104,6 +107,8 @@ class CommerceApiClient {
104
107
 
105
108
  private readonly inferenceApi: InferenceApi;
106
109
 
110
+ private readonly productsApi: ProductsApi;
111
+
107
112
  private static instance: CommerceApiClient | undefined;
108
113
 
109
114
  private suggestionsAbortController = new AbortController();
@@ -135,6 +140,7 @@ class CommerceApiClient {
135
140
  this.defaultApi = new DefaultApi(config);
136
141
  this.inferenceApi = new InferenceApi(config);
137
142
  this.customerServiceApi = new CustomerServiceApi(config);
143
+ this.productsApi = new ProductsApi(config);
138
144
  }
139
145
 
140
146
  static resolveUrl = async (url: string) => {
@@ -437,6 +443,51 @@ class CommerceApiClient {
437
443
  return apiWidgetTextResponseToCoreWidgetText(apiRequest, response);
438
444
  };
439
445
 
446
+ /**
447
+ * Retrieves product details for the given product IDs via POST /v1/products/retrieve.
448
+ * Builds context from the current atom store (org, user, chat, etc.) and returns
449
+ * products in the shape expected by ProductRetrievalResult (camelCase attributes).
450
+ *
451
+ * @param productIds - List of product IDs to retrieve
452
+ * @returns ProductRetrievalResult with products and totalProductCount
453
+ */
454
+ static retrieveProducts = async (productIds: string[]): Promise<ProductRetrievalResult> => {
455
+ if (productIds.length === 0) {
456
+ return { products: [], totalProductCount: 0 };
457
+ }
458
+
459
+ try {
460
+ const atomStore = getAtomStore();
461
+ const orgShortName = atomStore.get(orgShortNameAtom);
462
+ const orgId = atomStore.get(orgIdAtom);
463
+ const userId = atomStore.get(userIdAtom);
464
+ const chatId = atomStore.get(chatIdAtom);
465
+ const source = atomStore.get(contextSourceAtom);
466
+ const env = atomStore.get(envAtom);
467
+
468
+ const context: Context = {
469
+ user_id: userId ?? '',
470
+ org_id: orgId ?? '',
471
+ org_short_name: orgShortName ?? '',
472
+ chat_id: chatId ?? '',
473
+ source: source ?? ContextSourceEnum.App,
474
+ env: (env as ContextEnvEnum) ?? ContextEnvEnum.Dev,
475
+ };
476
+
477
+ const response = await CommerceApiClient.getInstance().productsApi.v1ProductsRetrievePost({
478
+ ProductRetrievalRequest: {
479
+ context,
480
+ product_ids: productIds,
481
+ },
482
+ });
483
+
484
+ return productRetrievalResponseToProductRetrievalResult(response);
485
+ } catch (err) {
486
+ await throwSessionRestartRequiredIf('Failed to retrieve products', err);
487
+ return { products: [], totalProductCount: 0 };
488
+ }
489
+ };
490
+
440
491
  /**
441
492
  *
442
493
  * @param payload
@@ -0,0 +1,21 @@
1
+ import type { ProductRetrievalResponse } from '@spiffy-ai/commerce-api-client';
2
+ import { transformSnakeToCamel } from 'src/application/models/utils/snakeToCamelTransformer';
3
+ import type { SearchResponseProductAttributes } from 'src/application/models/api/response';
4
+ import type { ProductRetrievalResult } from 'src/atoms/search/types';
5
+
6
+ /**
7
+ * Maps the API response from /v1/products/retrieve to the core ProductRetrievalResult.
8
+ * Converts product attributes from snake_case to camelCase to match SearchResponseProductAttributes.
9
+ */
10
+ export function productRetrievalResponseToProductRetrievalResult(
11
+ apiResponse: ProductRetrievalResponse,
12
+ ): ProductRetrievalResult {
13
+ const products = (apiResponse.products ?? []).map(product =>
14
+ transformSnakeToCamel(product),
15
+ ) as SearchResponseProductAttributes['attributes'][];
16
+
17
+ return {
18
+ products,
19
+ totalProductCount: products.length,
20
+ };
21
+ }
@@ -48,7 +48,7 @@ export interface SalesAgentChatAPI {
48
48
  onFormResponseSubmitted: (form: FormSubmittedAttributes) => void;
49
49
  }
50
50
 
51
- export const useSalesAgentChatAPI = () => {
51
+ export const useSalesAgentChatAPI = (widget?: WidgetInteractionComponent) => {
52
52
  // TODO: Each of these functions will trigger both the necessary amplitude events and initiate the
53
53
  // necessary actions to trigger the backend API
54
54
  const context = useAtomValue(analyticsContextAtom);
@@ -58,6 +58,7 @@ export const useSalesAgentChatAPI = () => {
58
58
  const setFormSubmit = useSetAtom(formSubmitAtom);
59
59
  const { trackEvent } = useAmplitude();
60
60
  const { trackWidgetInteraction } = useWidgetInteraction();
61
+ const contextWidget = widget || WidgetInteractionComponent.FLOATING_CHAT;
61
62
 
62
63
  const logPageVisit = useCallback(
63
64
  ({ pageVisitCategory }: { pageVisitCategory: PageVisitCategory }) => {
@@ -113,7 +114,7 @@ export const useSalesAgentChatAPI = () => {
113
114
  trackWidgetInteraction({
114
115
  eventName: EnviveMetricsEventName.WidgetInteraction,
115
116
  trigger: {
116
- widget: WidgetInteractionComponent.FLOATING_CHAT,
117
+ widget: contextWidget,
117
118
  widget_interaction: WidgetInteractionType.SUGGESTION_CLICKED,
118
119
  widget_interaction_data: {
119
120
  suggestion_clicked: {
@@ -182,7 +183,7 @@ export const useSalesAgentChatAPI = () => {
182
183
  trackWidgetInteraction({
183
184
  eventName: EnviveMetricsEventName.WidgetInteraction,
184
185
  trigger: {
185
- widget: WidgetInteractionComponent.FLOATING_CHAT,
186
+ widget: contextWidget,
186
187
  widget_interaction: WidgetInteractionType.MESSAGE_SUBMITTED,
187
188
  widget_interaction_data: {
188
189
  message_submitted: {
@@ -1,9 +1,9 @@
1
+ import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
1
2
  import { useAtom, useAtomValue, useSetAtom } from 'jotai';
2
3
  import { ReactNode, createContext, useCallback, useEffect, useMemo, useRef } from 'react';
3
- import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
4
4
  import Logger from 'src/application/logging/logger';
5
- import { Message, MessageRole, MessageType } from 'src/application/models/message';
6
5
  import { NextMessageRequest, Suggestion, UserEvent } from 'src/application/models';
6
+ import { Message, MessageRole, MessageType } from 'src/application/models/message';
7
7
  import {
8
8
  initializedAtom,
9
9
  messagesAtom,
@@ -16,12 +16,13 @@ import {
16
16
  userEventQueueAtom,
17
17
  userQueueEventCountAtom,
18
18
  } from 'src/atoms/chat/messageQueue';
19
- import { useSystemSettingsContext } from 'src/hooks/SystemSettingsContext';
19
+ import { useSystemSettingsContext } from '../../hooks/SystemSettingsContext';
20
+ import { WidgetInteractionComponent } from '../../hooks/WidgetInteraction/types';
21
+ import { SalesAgentChatAPI, useSalesAgentChatAPI } from './chatAPI';
20
22
  import {
21
23
  buildFormSubmittedDisplayContent,
22
24
  createFormSubmittedUserMessage,
23
25
  } from './formSubmittedUtils';
24
- import { SalesAgentChatAPI, useSalesAgentChatAPI } from './chatAPI';
25
26
  import { useSalesAgentService } from './salesAgentService';
26
27
 
27
28
  export interface SalesAgent extends SalesAgentChatAPI {
@@ -203,7 +204,7 @@ export const SalesAgentProvider: React.FC<SalesAgentProviderProps> = ({
203
204
  return <SalesAgentContext.Provider value={undefined}>{children}</SalesAgentContext.Provider>;
204
205
  };
205
206
 
206
- export const useSalesAgent = (): SalesAgent => {
207
+ export const useSalesAgent = (contextWidget?: WidgetInteractionComponent): SalesAgent => {
207
208
  const messages = useAtomValue(messagesAtom);
208
209
  const suggestions = useAtomValue(suggestionsAtom);
209
210
  const pendingMessages = useAtomValue(userEventQueueAtom);
@@ -216,7 +217,7 @@ export const useSalesAgent = (): SalesAgent => {
216
217
  onSuggestionClicked,
217
218
  onTypedMessageSubmitted,
218
219
  onFormResponseSubmitted,
219
- } = useSalesAgentChatAPI();
220
+ } = useSalesAgentChatAPI(contextWidget);
220
221
 
221
222
  const salesAgent: SalesAgent = useMemo(() => {
222
223
  return {
@@ -0,0 +1 @@
1
+ export * from './useProductImageUrl';
@@ -0,0 +1,35 @@
1
+ import { useEffect, useState } from 'react';
2
+ import CommerceApiClient from 'src/application/commerce-api';
3
+
4
+ /**
5
+ * Fetches the product image URL for the given product ID via CommerceApiClient.retrieveProducts.
6
+ * Returns undefined while loading, on error, or when productId is not provided.
7
+ */
8
+ export const useProductImageUrl = (productId: string | undefined): string | undefined => {
9
+ const [imageUrl, setImageUrl] = useState<string | undefined>(undefined);
10
+
11
+ useEffect(() => {
12
+ if (!productId) {
13
+ setImageUrl(undefined);
14
+ return undefined;
15
+ }
16
+ let cancelled = false;
17
+ CommerceApiClient.retrieveProducts([productId]).then(
18
+ result => {
19
+ if (!cancelled && result.products?.length > 0) {
20
+ setImageUrl(result.products[0].imageUrl);
21
+ } else if (!cancelled) {
22
+ setImageUrl(undefined);
23
+ }
24
+ },
25
+ () => {
26
+ if (!cancelled) setImageUrl(undefined);
27
+ },
28
+ );
29
+ return () => {
30
+ cancelled = true;
31
+ };
32
+ }, [productId]);
33
+
34
+ return imageUrl;
35
+ };
@@ -36,6 +36,7 @@ export enum WidgetInteractionComponent {
36
36
  EMBEDDED_WIDGET = 'embedded_widget',
37
37
  SUGGESTION_BAR = 'suggestion_bar',
38
38
  FLOATING_BUTTON = 'floating_button',
39
+ FULL_PAGE_SALES_AGENT = 'full_page_sales_agent',
39
40
  SOCIAL_PROOF = 'social_proof',
40
41
  CHAT_PREVIEW = 'chat_preview',
41
42
  FLOATING_CHAT = 'floating_chat',