From 6e1c3ee1760e791887149349a9acc547ff9ec43b Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Wed, 11 Jun 2025 15:07:43 +0530 Subject: [PATCH] chore: add more helpers --- .../whatsapp/useWhatsappAuthCallbacks.js | 54 +++++++++++ .../whatsapp/useWhatsappEventProcessors.js | 58 ++++++++++++ .../whatsapp/useWhatsappFacebookSDK.js | 88 ++++-------------- .../whatsapp/useWhatsappMessageHandler.js | 90 ++++++------------- .../whatsapp/useWhatsappMessageValidation.js | 29 ++++++ .../whatsapp/useWhatsappSDKHelpers.js | 37 ++++++++ .../whatsapp/useWhatsappSignupHandlers.js | 35 +------- .../whatsapp/useWhatsappSuccessHandler.js | 39 ++++++++ 8 files changed, 266 insertions(+), 164 deletions(-) create mode 100644 app/javascript/dashboard/composables/whatsapp/useWhatsappAuthCallbacks.js create mode 100644 app/javascript/dashboard/composables/whatsapp/useWhatsappEventProcessors.js create mode 100644 app/javascript/dashboard/composables/whatsapp/useWhatsappMessageValidation.js create mode 100644 app/javascript/dashboard/composables/whatsapp/useWhatsappSDKHelpers.js create mode 100644 app/javascript/dashboard/composables/whatsapp/useWhatsappSuccessHandler.js diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappAuthCallbacks.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappAuthCallbacks.js new file mode 100644 index 000000000..101069b47 --- /dev/null +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappAuthCallbacks.js @@ -0,0 +1,54 @@ +import { useAlert } from 'dashboard/composables'; + +export function useWhatsappAuthCallbacks({ + authCode, + authCodeReceived, + currentStep, + processingMessage, + isProcessing, + isAuthenticating, + hasSignupStarted, + businessData, + completeSignupFlow, + handleSignupError, + t, +}) { + const handleSuccessfulAuth = authResponse => { + authCode.value = authResponse.code; + authCodeReceived.value = true; + currentStep.value = 'auth_received'; + processingMessage.value = t( + 'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.WAITING_FOR_BUSINESS_INFO' + ); + + if (businessData.value) { + completeSignupFlow(businessData.value); + } + }; + + const handleAuthError = error => { + handleSignupError({ error }); + }; + + const handleAuthCancellation = () => { + currentStep.value = 'initial'; + isProcessing.value = false; + isAuthenticating.value = false; + hasSignupStarted.value = false; + useAlert(t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED')); + }; + + const fbLoginCallback = response => { + if (response.authResponse?.code) { + handleSuccessfulAuth(response.authResponse); + } else if (response.error) { + handleAuthError(response.error); + } else { + handleAuthCancellation(); + } + }; + + return { + fbLoginCallback, + }; +} diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappEventProcessors.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappEventProcessors.js new file mode 100644 index 000000000..550a23807 --- /dev/null +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappEventProcessors.js @@ -0,0 +1,58 @@ +export function useWhatsappEventProcessors({ + isValidBusinessData, + normalizeBusinessData, + businessData, + authCodeReceived, + authCode, + completeSignupFlow, + currentStep, + processingMessage, + handleSignupError, + handleSignupCancellation, + t, +}) { + const processFinishEvent = async data => { + const businessDataLocal = + data.data || data.business_data || data.details || data; + + if (isValidBusinessData(businessDataLocal)) { + const normalizedData = normalizeBusinessData(businessDataLocal); + businessData.value = normalizedData; + + if (authCodeReceived.value && authCode.value) { + await completeSignupFlow(normalizedData); + } else { + currentStep.value = 'waiting_for_auth'; + processingMessage.value = t( + 'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.WAITING_FOR_AUTH' + ); + } + } else { + handleSignupError({ + error: t( + 'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.INVALID_BUSINESS_DATA' + ), + }); + } + }; + + const processErrorEvent = data => { + handleSignupError({ + error: + data.error_message || + t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.SIGNUP_ERROR'), + error_id: data.error_id, + session_id: data.session_id, + }); + }; + + const processCancelEvent = data => { + handleSignupCancellation(data); + }; + + return { + processFinishEvent, + processErrorEvent, + processCancelEvent, + }; +} diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappFacebookSDK.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappFacebookSDK.js index 4f55452e2..046b3baba 100644 --- a/app/javascript/dashboard/composables/whatsapp/useWhatsappFacebookSDK.js +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappFacebookSDK.js @@ -1,4 +1,5 @@ -import { useAlert } from 'dashboard/composables'; +import { useWhatsappSDKHelpers } from './useWhatsappSDKHelpers'; +import { useWhatsappAuthCallbacks } from './useWhatsappAuthCallbacks'; export function useWhatsappFacebookSDK({ fbSdkLoaded, @@ -14,66 +15,28 @@ export function useWhatsappFacebookSDK({ handleSignupError, t, }) { - const initializeFacebookSDK = () => { - window.FB.init({ - appId: window.chatwootConfig?.whatsappAppId, - status: true, - xfbml: true, - version: window.chatwootConfig?.whatsappApiVersion || 'v22.0', - }); - fbSdkLoaded.value = true; - }; + const { createFacebookScript, createLoginOptions } = useWhatsappSDKHelpers(); - const createFacebookScript = () => { - const script = document.createElement('script'); - script.src = 'https://connect.facebook.net/en_US/sdk.js'; - script.async = true; - script.defer = true; - script.onload = initializeFacebookSDK; - document.body.appendChild(script); - }; + const { fbLoginCallback } = useWhatsappAuthCallbacks({ + authCode, + authCodeReceived, + currentStep, + processingMessage, + isProcessing, + isAuthenticating, + hasSignupStarted, + businessData, + completeSignupFlow, + handleSignupError, + t, + }); const loadFacebookSdk = () => { if (window.FB) { fbSdkLoaded.value = true; return; } - createFacebookScript(); - }; - - const handleSuccessfulAuth = authResponse => { - authCode.value = authResponse.code; - authCodeReceived.value = true; - currentStep.value = 'auth_received'; - processingMessage.value = t( - 'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.WAITING_FOR_BUSINESS_INFO' - ); - - if (businessData.value) { - completeSignupFlow(businessData.value); - } - }; - - const handleAuthError = error => { - handleSignupError({ error }); - }; - - const handleAuthCancellation = () => { - currentStep.value = 'initial'; - isProcessing.value = false; - isAuthenticating.value = false; - hasSignupStarted.value = false; - useAlert(t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED')); - }; - - const fbLoginCallback = response => { - if (response.authResponse?.code) { - handleSuccessfulAuth(response.authResponse); - } else if (response.error) { - handleAuthError(response.error); - } else { - handleAuthCancellation(); - } + createFacebookScript(fbSdkLoaded); }; const setSignupProcessingState = () => { @@ -83,24 +46,9 @@ export function useWhatsappFacebookSDK({ ); }; - const setAuthenticatingState = () => { + const executeSignup = () => { isAuthenticating.value = true; currentStep.value = 'auth_processing'; - }; - - const createLoginOptions = () => ({ - config_id: window.chatwootConfig?.whatsappConfigurationId, - response_type: 'code', - override_default_response_type: true, - extras: { - setup: {}, - featureType: '', - sessionInfoVersion: '3', - }, - }); - - const executeSignup = () => { - setAuthenticatingState(); const options = createLoginOptions(); window.FB.login(fbLoginCallback, options); }; diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappMessageHandler.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappMessageHandler.js index 000c0c60e..5131e557c 100644 --- a/app/javascript/dashboard/composables/whatsapp/useWhatsappMessageHandler.js +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappMessageHandler.js @@ -1,3 +1,6 @@ +import { useWhatsappMessageValidation } from './useWhatsappMessageValidation'; +import { useWhatsappEventProcessors } from './useWhatsappEventProcessors'; + export function useWhatsappMessageHandler({ isValidBusinessData, normalizeBusinessData, @@ -11,73 +14,34 @@ export function useWhatsappMessageHandler({ handleSignupCancellation, t, }) { - const processFinishEvent = async data => { - const businessDataLocal = - data.data || data.business_data || data.details || data; + const { validateMessageOrigin, parseMessageData, isWhatsappSignupMessage } = + useWhatsappMessageValidation(); - if (isValidBusinessData(businessDataLocal)) { - const normalizedData = normalizeBusinessData(businessDataLocal); - businessData.value = normalizedData; - - if (authCodeReceived.value && authCode.value) { - await completeSignupFlow(normalizedData); - } else { - currentStep.value = 'waiting_for_auth'; - processingMessage.value = t( - 'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.WAITING_FOR_AUTH' - ); - } - } else { - handleSignupError({ - error: t( - 'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.INVALID_BUSINESS_DATA' - ), - }); - } - }; - - const processErrorEvent = data => { - handleSignupError({ - error: - data.error_message || - t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.SIGNUP_ERROR'), - error_id: data.error_id, - session_id: data.session_id, + const { processFinishEvent, processErrorEvent, processCancelEvent } = + useWhatsappEventProcessors({ + isValidBusinessData, + normalizeBusinessData, + businessData, + authCodeReceived, + authCode, + completeSignupFlow, + currentStep, + processingMessage, + handleSignupError, + handleSignupCancellation, + t, }); + + const eventProcessorMap = { + FINISH: processFinishEvent, + CANCEL: processCancelEvent, + error: processErrorEvent, }; const handleEmbeddedSignupData = async data => { - switch (data.event) { - case 'FINISH': - await processFinishEvent(data); - break; - case 'CANCEL': - handleSignupCancellation(data); - break; - case 'error': - processErrorEvent(data); - break; - default: - // Handle unknown events silently - break; - } - }; - - const validateMessageOrigin = origin => { - try { - const originUrl = new URL(origin); - const allowedHosts = ['facebook.com', 'www.facebook.com']; - return allowedHosts.includes(originUrl.hostname); - } catch (error) { - return false; - } - }; - - const parseMessageData = data => { - try { - return JSON.parse(data); - } catch (error) { - return null; + const processor = eventProcessorMap[data.event]; + if (processor) { + await processor(data); } }; @@ -85,7 +49,7 @@ export function useWhatsappMessageHandler({ if (!validateMessageOrigin(event.origin)) return; const data = parseMessageData(event.data); - if (data?.type === 'WA_EMBEDDED_SIGNUP') { + if (isWhatsappSignupMessage(data)) { handleEmbeddedSignupData(data); } }; diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappMessageValidation.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappMessageValidation.js new file mode 100644 index 000000000..a35c1f5be --- /dev/null +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappMessageValidation.js @@ -0,0 +1,29 @@ +export function useWhatsappMessageValidation() { + const validateMessageOrigin = origin => { + try { + const originUrl = new URL(origin); + const allowedHosts = ['facebook.com', 'www.facebook.com']; + return allowedHosts.includes(originUrl.hostname); + } catch (error) { + return false; + } + }; + + const parseMessageData = data => { + try { + return JSON.parse(data); + } catch (error) { + return null; + } + }; + + const isWhatsappSignupMessage = data => { + return data?.type === 'WA_EMBEDDED_SIGNUP'; + }; + + return { + validateMessageOrigin, + parseMessageData, + isWhatsappSignupMessage, + }; +} diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappSDKHelpers.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappSDKHelpers.js new file mode 100644 index 000000000..699ac4748 --- /dev/null +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappSDKHelpers.js @@ -0,0 +1,37 @@ +export function useWhatsappSDKHelpers() { + const initializeFacebookSDK = fbSdkLoaded => { + window.FB.init({ + appId: window.chatwootConfig?.whatsappAppId, + status: true, + xfbml: true, + version: window.chatwootConfig?.whatsappApiVersion || 'v22.0', + }); + fbSdkLoaded.value = true; + }; + + const createFacebookScript = fbSdkLoaded => { + const script = document.createElement('script'); + script.src = 'https://connect.facebook.net/en_US/sdk.js'; + script.async = true; + script.defer = true; + script.onload = () => initializeFacebookSDK(fbSdkLoaded); + document.body.appendChild(script); + }; + + const createLoginOptions = () => ({ + config_id: window.chatwootConfig?.whatsappConfigurationId, + response_type: 'code', + override_default_response_type: true, + extras: { + setup: {}, + featureType: '', + sessionInfoVersion: '3', + }, + }); + + return { + initializeFacebookSDK, + createFacebookScript, + createLoginOptions, + }; +} diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappSignupHandlers.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappSignupHandlers.js index 9cc4fae06..5abbc9a63 100644 --- a/app/javascript/dashboard/composables/whatsapp/useWhatsappSignupHandlers.js +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappSignupHandlers.js @@ -1,4 +1,5 @@ import { useAlert } from 'dashboard/composables'; +import { useWhatsappSuccessHandler } from './useWhatsappSuccessHandler'; export function useWhatsappSignupHandlers({ currentStep, @@ -9,6 +10,9 @@ export function useWhatsappSignupHandlers({ router, t, }) { + const { handleValidInboxData, handleInvalidInboxData } = + useWhatsappSuccessHandler({ store, router, t }); + const getErrorMessage = data => { return ( data.error || @@ -37,37 +41,6 @@ export function useWhatsappSignupHandlers({ useAlert(message); }; - const navigateToAgentSelection = inboxId => { - router.replace({ - name: 'settings_inboxes_add_agents', - params: { - page: 'new', - inbox_id: inboxId, - }, - }); - }; - - const navigateToInboxList = () => { - router.replace({ - name: 'settings_inbox_list', - }); - }; - - const updateStoreWithInbox = inboxData => { - store.commit('inboxes/ADD_INBOXES', inboxData); - useAlert(t('INBOX_MGMT.FINISH.MESSAGE')); - }; - - const handleValidInboxData = inboxData => { - updateStoreWithInbox(inboxData); - navigateToAgentSelection(inboxData.id); - }; - - const handleInvalidInboxData = () => { - useAlert(t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.SUCCESS_FALLBACK')); - navigateToInboxList(); - }; - const handleSignupSuccess = inboxData => { currentStep.value = 'completed'; isProcessing.value = false; diff --git a/app/javascript/dashboard/composables/whatsapp/useWhatsappSuccessHandler.js b/app/javascript/dashboard/composables/whatsapp/useWhatsappSuccessHandler.js new file mode 100644 index 000000000..7e386a120 --- /dev/null +++ b/app/javascript/dashboard/composables/whatsapp/useWhatsappSuccessHandler.js @@ -0,0 +1,39 @@ +import { useAlert } from 'dashboard/composables'; + +export function useWhatsappSuccessHandler({ store, router, t }) { + const navigateToAgentSelection = inboxId => { + router.replace({ + name: 'settings_inboxes_add_agents', + params: { + page: 'new', + inbox_id: inboxId, + }, + }); + }; + + const navigateToInboxList = () => { + router.replace({ + name: 'settings_inbox_list', + }); + }; + + const updateStoreWithInbox = inboxData => { + store.commit('inboxes/ADD_INBOXES', inboxData); + useAlert(t('INBOX_MGMT.FINISH.MESSAGE')); + }; + + const handleValidInboxData = inboxData => { + updateStoreWithInbox(inboxData); + navigateToAgentSelection(inboxData.id); + }; + + const handleInvalidInboxData = () => { + useAlert(t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.SUCCESS_FALLBACK')); + navigateToInboxList(); + }; + + return { + handleValidInboxData, + handleInvalidInboxData, + }; +}