66 */
77
88import React , { useEffect } from 'react'
9- import useScript from '@salesforce/retail- react-app/app/hooks/use-script '
9+ import { Helmet } from 'react-helmet '
1010import { useUsid } from '@salesforce/commerce-sdk-react'
1111import PropTypes from 'prop-types'
1212import { useTheme } from '@salesforce/retail-react-app/app/components/shared/ui'
13+ import {
14+ validateCommerceAgentSettings ,
15+ isEnabled
16+ } from '@salesforce/retail-react-app/app/utils/shopper-agent-validation'
1317
1418const onClient = typeof window !== 'undefined'
1519
16- // Function to initialize embedded messaging
20+ /**
21+ * Initializes the embedded messaging service with the provided configuration.
22+ * This function sets up the embedded messaging bootstrap with the specified
23+ * parameters and handles any initialization errors gracefully.
24+ *
25+ * @param {string } salesforceOrgId - The Salesforce organization ID
26+ * @param {string } embeddedServiceDeploymentName - The name of the embedded service deployment
27+ * @param {string } embeddedServiceDeploymentUrl - The URL of the embedded service deployment
28+ * @param {string } scrt2Url - The URL for the SCRT2 script
29+ * @param {string } locale - The locale for the embedded messaging service
30+ * @example
31+ * initEmbeddedMessaging(
32+ * '00D1234567890ABC',
33+ * 'MIAW_Guided_Shopper_production',
34+ * 'https://myorg.salesforce.com/ESWMIAWGuidedShopper',
35+ * 'https://myorg.salesforce-scrt.com',
36+ * 'en-US'
37+ * )
38+ */
1739const initEmbeddedMessaging = (
1840 salesforceOrgId ,
1941 embeddedServiceDeploymentName ,
@@ -43,16 +65,35 @@ const initEmbeddedMessaging = (
4365 }
4466}
4567
68+ /**
69+ * Custom hook to manage the embedded messaging service initialization.
70+ * This hook monitors when the embedded messaging script is available and
71+ * initializes the service with the provided configuration.
72+ *
73+ * @param {string } salesforceOrgId - The Salesforce organization ID
74+ * @param {string } embeddedServiceDeploymentName - The name of the embedded service deployment
75+ * @param {string } embeddedServiceDeploymentUrl - The URL of the embedded service deployment
76+ * @param {string } scrt2Url - The URL for the SCRT2 script
77+ * @param {string } locale - The locale for the embedded messaging service
78+ * @example
79+ * useMiaw(
80+ * '00D1234567890ABC',
81+ * 'MIAW_Guided_Shopper_production',
82+ * 'https://myorg.salesforce.com/ESWMIAWGuidedShopper',
83+ * 'https://myorg.salesforce-scrt.com',
84+ * 'en-US'
85+ * )
86+ */
4687function useMiaw (
47- scriptLoadStatus ,
4888 salesforceOrgId ,
4989 embeddedServiceDeploymentName ,
5090 embeddedServiceDeploymentUrl ,
5191 scrt2Url ,
5292 locale
5393) {
5494 useEffect ( ( ) => {
55- if ( scriptLoadStatus . loaded && ! scriptLoadStatus . error ) {
95+ // Check if the embedded messaging script has been loaded and is available
96+ if ( onClient && window . embeddedservice_bootstrap ) {
5697 initEmbeddedMessaging (
5798 salesforceOrgId ,
5899 embeddedServiceDeploymentName ,
@@ -62,7 +103,6 @@ function useMiaw(
62103 )
63104 }
64105 } , [
65- scriptLoadStatus ,
66106 salesforceOrgId ,
67107 embeddedServiceDeploymentName ,
68108 embeddedServiceDeploymentUrl ,
@@ -71,31 +111,27 @@ function useMiaw(
71111 ] )
72112}
73113
74- function validateCommerceAgentSettings ( commerceAgent ) {
75- const requiredFields = [
76- 'enabled' ,
77- 'askAgentOnSearch' ,
78- 'embeddedServiceName' ,
79- 'embeddedServiceEndpoint' ,
80- 'scriptSourceUrl' ,
81- 'scrt2Url' ,
82- 'salesforceOrgId' ,
83- 'commerceOrgId' ,
84- 'siteId'
85- ]
86-
87- const isValid = requiredFields . every ( ( key ) => typeof commerceAgent [ key ] === 'string' )
88- if ( ! isValid ) {
89- console . error ( 'Invalid commerce agent settings.' )
90- }
91- return isValid
92- }
93-
94- function isEnabled ( enabled ) {
95- return enabled === 'true' && onClient
96- }
97-
98- function ShopperAgentWindow ( { commerceAgentConfiguration, locale, basketId} ) {
114+ /**
115+ * ShopperAgentWindow component that handles the embedded messaging service initialization
116+ * and event management. This component is responsible for:
117+ * - Loading the embedded messaging script via Helmet
118+ * - Setting up event listeners for embedded messaging events
119+ * - Managing pre-chat fields and basket context
120+ * - Handling z-index management for the chat widget
121+ *
122+ * @param {Object } props - Component props
123+ * @param {Object } props.commerceAgentConfiguration - Commerce agent configuration object
124+ * @param {string } props.basketId - The basket ID for the embedded messaging script
125+ * @param {string } props.locale - The locale for the embedded messaging script
126+ * @returns {JSX.Element } Helmet component with embedded messaging script
127+ * @example
128+ * <ShopperAgentWindow
129+ * commerceAgentConfiguration={config}
130+ * basketId="4a67cda5b1b9325a29207854c1"
131+ * locale="en-US"
132+ * />
133+ */
134+ const ShopperAgentWindow = ( { commerceAgentConfiguration, locale, basketId} ) => {
99135 const theme = useTheme ( )
100136 const {
101137 embeddedServiceName,
@@ -109,15 +145,23 @@ function ShopperAgentWindow({commerceAgentConfiguration, locale, basketId}) {
109145
110146 const { usid} = useUsid ( )
111147
148+ /**
149+ * Sets up event listeners for embedded messaging events.
150+ * This effect handles:
151+ * - onEmbeddedMessagingReady: Sets initial pre-chat fields
152+ * - onEmbeddedMessagingWindowMaximized: Manages z-index for chat widget
153+ */
112154 useEffect ( ( ) => {
113155 const handleEmbeddedMessagingReady = ( ) => {
114- window . embeddedservice_bootstrap . prechatAPI . setHiddenPrechatFields ( {
115- SiteId : siteId ,
116- Locale : locale ,
117- OrganizationId : commerceOrgId ,
118- UsId : usid ,
119- IsCartMgmtSupported : true
120- } )
156+ if ( window . embeddedservice_bootstrap ?. prechatAPI ) {
157+ window . embeddedservice_bootstrap . prechatAPI . setHiddenPrechatFields ( {
158+ SiteId : siteId ,
159+ Locale : locale ,
160+ OrganizationId : commerceOrgId ,
161+ UsId : usid ,
162+ IsCartMgmtSupported : true
163+ } )
164+ }
121165 }
122166
123167 const handleEmbeddedMessagingWindowMaximized = ( ) => {
@@ -146,12 +190,18 @@ function ShopperAgentWindow({commerceAgentConfiguration, locale, basketId}) {
146190 }
147191 } , [ commerceAgentConfiguration , usid , theme . zIndices . sticky ] )
148192
149- // whenever the basketId changes, update the hidden prechat fields
193+ /**
194+ * Updates basket ID in pre-chat fields when basket changes.
195+ * This effect listens for the embedded messaging button click event
196+ * and updates the basket ID in the pre-chat fields.
197+ */
150198 useEffect ( ( ) => {
151199 const handleEmbeddedMessagingButtonClicked = ( ) => {
152- window . embeddedservice_bootstrap . prechatAPI . setHiddenPrechatFields ( {
153- BasketId : basketId
154- } )
200+ if ( window . embeddedservice_bootstrap ?. prechatAPI ) {
201+ window . embeddedservice_bootstrap . prechatAPI . setHiddenPrechatFields ( {
202+ BasketId : basketId
203+ } )
204+ }
155205 }
156206
157207 window . addEventListener (
@@ -168,20 +218,19 @@ function ShopperAgentWindow({commerceAgentConfiguration, locale, basketId}) {
168218 }
169219 } , [ basketId ] )
170220
171- // Load the embedded messaging script
172- const scriptLoadStatus = useScript ( scriptSourceUrl )
173-
174221 // Initialize the embedded messaging service
175- useMiaw (
176- scriptLoadStatus ,
177- salesforceOrgId ,
178- embeddedServiceName ,
179- embeddedServiceEndpoint ,
180- scrt2Url ,
181- locale
182- )
222+ useMiaw ( salesforceOrgId , embeddedServiceName , embeddedServiceEndpoint , scrt2Url , locale )
183223
184- return null
224+ return (
225+ < Helmet >
226+ < script
227+ id = "embedded-messaging-script"
228+ src = { scriptSourceUrl }
229+ async
230+ type = "text/javascript"
231+ />
232+ </ Helmet >
233+ )
185234}
186235
187236ShopperAgentWindow . propTypes = {
@@ -191,12 +240,29 @@ ShopperAgentWindow.propTypes = {
191240}
192241
193242/**
194- * ShopperAgent component that initializes and manages the embedded messaging service
243+ * ShopperAgent component that initializes and manages the embedded messaging service.
244+ * This is the main component that:
245+ * - Validates the commerce agent configuration
246+ * - Checks if the feature is enabled
247+ * - Ensures basket loading is complete
248+ * - Renders the ShopperAgentWindow when all conditions are met
249+ *
250+ * The component follows a conditional rendering pattern where it only renders
251+ * the embedded messaging functionality when all prerequisites are satisfied.
252+ *
195253 * @param {Object } props - Component props
196- * @param {Object } props.commerceAgentConfiguration - Commerce agent settings
254+ * @param {Object } props.commerceAgentConfiguration - Commerce agent configuration object
197255 * @param {string } props.basketId - The basket ID for the embedded messaging script
198256 * @param {string } props.locale - The locale for the embedded messaging script
199- * @returns {JSX.Element } The ShopperAgent component
257+ * @param {boolean } props.basketDoneLoading - Whether the basket has finished loading
258+ * @returns {JSX.Element|null } The ShopperAgent component or null if conditions not met
259+ * @example
260+ * <ShopperAgent
261+ * commerceAgentConfiguration={config}
262+ * basketId="4a67cda5b1b9325a29207854c1"
263+ * locale="en-US"
264+ * basketDoneLoading={true}
265+ * />
200266 */
201267function ShopperAgent ( { commerceAgentConfiguration, basketId, locale, basketDoneLoading} ) {
202268 const { enabled} = commerceAgentConfiguration
0 commit comments