chore: final fixes

This commit is contained in:
Muhsin Keloth
2025-06-11 15:20:41 +05:30
parent 6e1c3ee176
commit 9d86792468
15 changed files with 133 additions and 619 deletions
@@ -1,52 +0,0 @@
export function useWhatsappApiRequest() {
const createSignupPayload = (authCode, store, businessDataParam) => {
const accountId = store.getters.getCurrentAccountId;
return {
account_id: accountId,
code: authCode.value,
business_id: businessDataParam.business_id,
waba_id: businessDataParam.waba_id,
phone_number_id: businessDataParam.phone_number_id,
};
};
const createFetchOptions = (payload, authHeaders) => {
return {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': document
.querySelector('meta[name="csrf-token"]')
?.getAttribute('content'),
...authHeaders.value,
},
body: JSON.stringify(payload),
};
};
const makeSignupRequest = async (payload, authHeaders) => {
const options = createFetchOptions(payload, authHeaders);
return fetch('/whatsapp/embedded_signup', options);
};
const processApiResponse = async (
response,
authCode,
handleSignupSuccess
) => {
const responseData = await response.json();
if (response.ok) {
authCode.value = null;
handleSignupSuccess(responseData);
} else {
throw new Error(responseData.message || responseData.error);
}
};
return {
createSignupPayload,
makeSignupRequest,
processApiResponse,
};
}
@@ -1,33 +0,0 @@
import { computed } from 'vue';
import Auth from 'dashboard/api/auth';
export function useWhatsappAuth() {
const authHeaders = computed(() => {
if (!Auth.hasAuthCookie()) return {};
const {
'access-token': accessToken,
'token-type': tokenType,
client,
expiry,
uid,
} = Auth.getAuthData();
return {
'access-token': accessToken,
'token-type': tokenType,
client,
expiry,
uid,
};
});
const validateAuthRequirements = (authCodeReceived, authCode) => {
return authCodeReceived.value && authCode.value;
};
return {
authHeaders,
validateAuthRequirements,
};
}
@@ -1,54 +0,0 @@
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,
};
}
@@ -1,100 +0,0 @@
import { useWhatsappSignupValidation } from './useWhatsappSignupValidation';
import { useWhatsappSignupState } from './useWhatsappSignupState';
import { useWhatsappSignupHandlers } from './useWhatsappSignupHandlers';
import { useWhatsappSignupApi } from './useWhatsappSignupApi';
import { useWhatsappFacebookSDK } from './useWhatsappFacebookSDK';
import { useWhatsappMessageHandler } from './useWhatsappMessageHandler';
export function useWhatsappComposableOrchestrator({ store, router, t }) {
// Validation composable
const { isValidBusinessData, normalizeBusinessData } =
useWhatsappSignupValidation();
// State composable
const {
fbSdkLoaded,
isProcessing,
processingMessage,
authCodeReceived,
currentStep,
authCode,
businessData,
isAuthenticating,
hasSignupStarted,
resetState,
} = useWhatsappSignupState();
// Handlers composable
const { handleSignupError, handleSignupCancellation, handleSignupSuccess } =
useWhatsappSignupHandlers({
currentStep,
isProcessing,
isAuthenticating,
resetState,
store,
router,
t,
});
// API composable
const { completeSignupFlow } = useWhatsappSignupApi({
authCodeReceived,
authCode,
currentStep,
isProcessing,
processingMessage,
store,
t,
handleSignupError,
handleSignupSuccess,
});
// Facebook SDK composable
const { loadFacebookSdk, launchEmbeddedSignup } = useWhatsappFacebookSDK({
fbSdkLoaded,
hasSignupStarted,
processingMessage,
isProcessing,
isAuthenticating,
currentStep,
authCode,
authCodeReceived,
businessData,
completeSignupFlow,
handleSignupError,
t,
});
// Message handler composable
const { handleSignupMessage } = useWhatsappMessageHandler({
isValidBusinessData,
normalizeBusinessData,
businessData,
authCodeReceived,
authCode,
completeSignupFlow,
currentStep,
processingMessage,
handleSignupError,
handleSignupCancellation,
t,
});
return {
// State
fbSdkLoaded,
isProcessing,
processingMessage,
authCodeReceived,
currentStep,
authCode,
businessData,
isAuthenticating,
hasSignupStarted,
// Methods
loadFacebookSdk,
launchEmbeddedSignup,
handleSignupMessage,
};
}
@@ -1,27 +0,0 @@
import { computed } from 'vue';
export function useWhatsappComputed({ t, hasSignupStarted, isProcessing }) {
const benefits = computed(() => [
{
key: 'EASY_SETUP',
text: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.EASY_SETUP'),
},
{
key: 'SECURE_AUTH',
text: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.SECURE_AUTH'),
},
{
key: 'AUTO_CONFIG',
text: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.AUTO_CONFIG'),
},
]);
const showLoader = computed(
() => hasSignupStarted.value || isProcessing.value
);
return {
benefits,
showLoader,
};
}
@@ -1,58 +0,0 @@
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,
};
}
@@ -1,5 +1,4 @@
import { useWhatsappSDKHelpers } from './useWhatsappSDKHelpers';
import { useWhatsappAuthCallbacks } from './useWhatsappAuthCallbacks';
import { useAlert } from 'dashboard/composables';
export function useWhatsappFacebookSDK({
fbSdkLoaded,
@@ -15,46 +14,56 @@ export function useWhatsappFacebookSDK({
handleSignupError,
t,
}) {
const { createFacebookScript, createLoginOptions } = useWhatsappSDKHelpers();
const { fbLoginCallback } = useWhatsappAuthCallbacks({
authCode,
authCodeReceived,
currentStep,
processingMessage,
isProcessing,
isAuthenticating,
hasSignupStarted,
businessData,
completeSignupFlow,
handleSignupError,
t,
});
const loadFacebookSdk = () => {
if (window.FB) {
fbSdkLoaded.value = true;
return;
}
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 = () => {
window.FB.init({
appId: window.chatwootConfig?.whatsappAppId,
status: true,
xfbml: true,
version: window.chatwootConfig?.whatsappApiVersion || 'v22.0',
});
fbSdkLoaded.value = true;
};
document.body.appendChild(script);
};
const setSignupProcessingState = () => {
const fbLoginCallback = response => {
if (response.authResponse && response.authResponse.code) {
authCode.value = response.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);
}
} else if (response.error) {
handleSignupError({ error: response.error });
} else {
currentStep.value = 'initial';
isProcessing.value = false;
isAuthenticating.value = false;
hasSignupStarted.value = false;
useAlert(t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED'));
}
};
const launchEmbeddedSignup = () => {
hasSignupStarted.value = true;
processingMessage.value = t(
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.AUTH_PROCESSING'
);
};
const executeSignup = () => {
isAuthenticating.value = true;
currentStep.value = 'auth_processing';
const options = createLoginOptions();
window.FB.login(fbLoginCallback, options);
};
const launchEmbeddedSignup = () => {
setSignupProcessingState();
if (!window.FB) {
loadFacebookSdk();
@@ -62,7 +71,19 @@ export function useWhatsappFacebookSDK({
return;
}
executeSignup();
isAuthenticating.value = true;
currentStep.value = 'auth_processing';
window.FB.login(fbLoginCallback, {
config_id: window.chatwootConfig?.whatsappConfigurationId,
response_type: 'code',
override_default_response_type: true,
extras: {
setup: {},
featureType: '',
sessionInfoVersion: '3',
},
});
};
return {
@@ -1,19 +0,0 @@
export function useWhatsappLifecycle({ loadFacebookSdk, handleSignupMessage }) {
const setupMessageListener = () => {
window.addEventListener('message', handleSignupMessage);
};
const cleanupMessageListener = () => {
window.removeEventListener('message', handleSignupMessage);
};
const initialize = () => {
loadFacebookSdk();
setupMessageListener();
};
return {
initialize,
cleanupMessageListener,
};
}
@@ -1,60 +0,0 @@
import { useWhatsappMessageValidation } from './useWhatsappMessageValidation';
import { useWhatsappEventProcessors } from './useWhatsappEventProcessors';
export function useWhatsappMessageHandler({
isValidBusinessData,
normalizeBusinessData,
businessData,
authCodeReceived,
authCode,
completeSignupFlow,
currentStep,
processingMessage,
handleSignupError,
handleSignupCancellation,
t,
}) {
const { validateMessageOrigin, parseMessageData, isWhatsappSignupMessage } =
useWhatsappMessageValidation();
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 => {
const processor = eventProcessorMap[data.event];
if (processor) {
await processor(data);
}
};
const handleSignupMessage = event => {
if (!validateMessageOrigin(event.origin)) return;
const data = parseMessageData(event.data);
if (isWhatsappSignupMessage(data)) {
handleEmbeddedSignupData(data);
}
};
return {
handleSignupMessage,
};
}
@@ -1,29 +0,0 @@
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,
};
}
@@ -1,37 +0,0 @@
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,
};
}
@@ -1,6 +1,5 @@
import { useWhatsappAuth } from './useWhatsappAuth';
import { useWhatsappApiRequest } from './useWhatsappApiRequest';
import { useWhatsappSignupFlow } from './useWhatsappSignupFlow';
import { computed } from 'vue';
import Auth from 'dashboard/api/auth';
export function useWhatsappSignupApi({
authCodeReceived,
@@ -13,33 +12,70 @@ export function useWhatsappSignupApi({
handleSignupError,
handleSignupSuccess,
}) {
const { authHeaders, validateAuthRequirements } = useWhatsappAuth();
const { createSignupPayload, makeSignupRequest, processApiResponse } =
useWhatsappApiRequest();
const { setProcessingState, handleAuthError, handleRequestError } =
useWhatsappSignupFlow({
currentStep,
isProcessing,
processingMessage,
t,
});
const authHeaders = computed(() => {
if (Auth.hasAuthCookie()) {
const {
'access-token': accessToken,
'token-type': tokenType,
client,
expiry,
uid,
} = Auth.getAuthData();
return {
'access-token': accessToken,
'token-type': tokenType,
client,
expiry,
uid,
};
}
return {};
});
const completeSignupFlow = async businessDataParam => {
if (!validateAuthRequirements(authCodeReceived, authCode)) {
handleAuthError(handleSignupError, t);
if (!authCodeReceived.value || !authCode.value) {
handleSignupError({
error: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.AUTH_NOT_COMPLETED'),
});
return;
}
setProcessingState();
currentStep.value = 'processing';
isProcessing.value = true;
processingMessage.value = t(
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.PROCESSING'
);
try {
const payload = createSignupPayload(authCode, store, businessDataParam);
const response = await makeSignupRequest(payload, authHeaders);
await processApiResponse(response, authCode, handleSignupSuccess);
const accountId = store.getters.getCurrentAccountId;
const response = await fetch('/whatsapp/embedded_signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': document
.querySelector('meta[name="csrf-token"]')
?.getAttribute('content'),
...authHeaders.value,
},
body: JSON.stringify({
account_id: accountId,
code: authCode.value,
business_id: businessDataParam.business_id,
waba_id: businessDataParam.waba_id,
phone_number_id: businessDataParam.phone_number_id,
}),
});
const responseData = await response.json();
if (response.ok) {
authCode.value = null;
handleSignupSuccess(responseData);
} else {
throw new Error(responseData.message || responseData.error);
}
} catch (error) {
handleRequestError(error, handleSignupError);
handleSignupError({ error: error.message });
}
};
@@ -1,32 +0,0 @@
export function useWhatsappSignupFlow({
currentStep,
isProcessing,
processingMessage,
t,
}) {
const setProcessingState = () => {
currentStep.value = 'processing';
isProcessing.value = true;
processingMessage.value = t(
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.PROCESSING'
);
};
const handleAuthError = (handleSignupError, translator) => {
handleSignupError({
error: translator(
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.AUTH_NOT_COMPLETED'
),
});
};
const handleRequestError = (error, handleSignupError) => {
handleSignupError({ error: error.message });
};
return {
setProcessingState,
handleAuthError,
handleRequestError,
};
}
@@ -1,5 +1,4 @@
import { useAlert } from 'dashboard/composables';
import { useWhatsappSuccessHandler } from './useWhatsappSuccessHandler';
export function useWhatsappSignupHandlers({
currentStep,
@@ -10,34 +9,21 @@ export function useWhatsappSignupHandlers({
router,
t,
}) {
const { handleValidInboxData, handleInvalidInboxData } =
useWhatsappSuccessHandler({ store, router, t });
const getErrorMessage = data => {
return (
data.error ||
data.message ||
t('INBOX_MGMT.ADD.WHATSAPP.API.ERROR_MESSAGE')
);
};
const getCancellationMessage = data => {
let message = t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED');
if (data.data?.current_step) {
message += ` (Step: ${data.data.current_step})`;
}
return message;
};
const handleSignupError = data => {
resetState();
const errorMessage = getErrorMessage(data);
const errorMessage =
data.error ||
data.message ||
t('INBOX_MGMT.ADD.WHATSAPP.API.ERROR_MESSAGE');
useAlert(errorMessage);
};
const handleSignupCancellation = data => {
resetState();
const message = getCancellationMessage(data);
let message = t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED');
if (data.data?.current_step) {
message += ` (Step: ${data.data.current_step})`;
}
useAlert(message);
};
@@ -46,10 +32,21 @@ export function useWhatsappSignupHandlers({
isProcessing.value = false;
isAuthenticating.value = false;
if (inboxData?.id) {
handleValidInboxData(inboxData);
if (inboxData && inboxData.id) {
store.commit('inboxes/ADD_INBOXES', inboxData);
useAlert(t('INBOX_MGMT.FINISH.MESSAGE'));
router.replace({
name: 'settings_inboxes_add_agents',
params: {
page: 'new',
inbox_id: inboxData.id,
},
});
} else {
handleInvalidInboxData();
useAlert(t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.SUCCESS_FALLBACK'));
router.replace({
name: 'settings_inbox_list',
});
}
};
@@ -1,39 +0,0 @@
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,
};
}