chore: front end improvments
This commit is contained in:
@@ -287,14 +287,18 @@
|
||||
"AUTH_PROCESSING": "Authenticating with Meta...",
|
||||
"WAITING_FOR_BUSINESS_INFO": "Please complete business setup in the Meta window...",
|
||||
"PROCESSING": "Setting up your WhatsApp Business Account...",
|
||||
"PROCESSING_DESC": "Please wait while we configure your WhatsApp Business Account. This may take a few moments.",
|
||||
"LOADING_SDK": "Loading Facebook SDK...",
|
||||
"CANCELLED": "WhatsApp signup was cancelled",
|
||||
"STEP_AUTH": "Step 1: Authenticating with Meta",
|
||||
"STEP_BUSINESS": "Step 2: Selecting business account",
|
||||
"STEP_CREATING": "Step 3: Creating WhatsApp channel",
|
||||
"SUCCESS_TITLE": "WhatsApp Business Account Connected!",
|
||||
"SUCCESS_DESC": "Your WhatsApp Business Account has been successfully connected. Please provide a name for your inbox to complete the setup."
|
||||
"SUCCESS_DESC": "Your WhatsApp Business Account has been successfully connected. Please provide a name for your inbox to complete the setup.",
|
||||
"WAITING_FOR_AUTH": "Waiting for authentication...",
|
||||
"INVALID_BUSINESS_DATA": "Invalid business data received from Facebook. Please try again.",
|
||||
"SIGNUP_ERROR": "Signup error occurred",
|
||||
"AUTH_NOT_COMPLETED": "Authentication not completed. Please restart the process.",
|
||||
"SUCCESS_FALLBACK": "WhatsApp Business Account has been successfully configured"
|
||||
},
|
||||
"API": {
|
||||
"ERROR_MESSAGE": "We were not able to save the WhatsApp channel"
|
||||
|
||||
+331
-333
@@ -1,340 +1,349 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import router from '../../../../index';
|
||||
import Auth from 'dashboard/api/auth';
|
||||
import Icon from 'next/icon/Icon.vue';
|
||||
import NextButton from 'next/button/Button.vue';
|
||||
import LoadingState from 'dashboard/components/widgets/LoadingState.vue';
|
||||
import whatsappIcon from 'dashboard/assets/images/whatsapp.png';
|
||||
|
||||
export default {
|
||||
components: { Icon, NextButton },
|
||||
data() {
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
|
||||
const fbSdkLoaded = ref(false);
|
||||
const isProcessing = ref(false);
|
||||
const processingMessage = ref('');
|
||||
const authCodeReceived = ref(false);
|
||||
const currentStep = ref('initial');
|
||||
const authCode = ref(null);
|
||||
const businessData = ref(null);
|
||||
const isAuthenticating = ref(false);
|
||||
const hasSignupStarted = ref(false);
|
||||
|
||||
const authHeaders = computed(() => {
|
||||
if (Auth.hasAuthCookie()) {
|
||||
const {
|
||||
'access-token': accessToken,
|
||||
'token-type': tokenType,
|
||||
client,
|
||||
expiry,
|
||||
uid,
|
||||
} = Auth.getAuthData();
|
||||
return {
|
||||
fbSdkLoaded: false,
|
||||
isProcessing: false,
|
||||
processingMessage: '',
|
||||
authCodeReceived: false,
|
||||
currentStep: 'initial', // 'initial', 'auth_received', 'processing', 'completed'
|
||||
authCode: null,
|
||||
businessData: null, // Store business data when received
|
||||
'access-token': accessToken,
|
||||
'token-type': tokenType,
|
||||
client,
|
||||
expiry,
|
||||
uid,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
});
|
||||
|
||||
const benefits = computed(() => [
|
||||
{
|
||||
key: 'EASY_SETUP',
|
||||
text: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.EASY_SETUP'),
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({ uiFlags: 'inboxes/getUIFlags' }),
|
||||
isLoading() {
|
||||
return this.isProcessing || this.uiFlags.isCreating;
|
||||
},
|
||||
authHeaders() {
|
||||
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 {};
|
||||
},
|
||||
{
|
||||
key: 'SECURE_AUTH',
|
||||
text: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.SECURE_AUTH'),
|
||||
},
|
||||
mounted() {
|
||||
this.loadFacebookSdk();
|
||||
window.addEventListener('message', this.handleSignupMessage);
|
||||
{
|
||||
key: 'AUTO_CONFIG',
|
||||
text: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.AUTO_CONFIG'),
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('message', this.handleSignupMessage);
|
||||
},
|
||||
methods: {
|
||||
loadFacebookSdk() {
|
||||
if (window.FB) {
|
||||
this.fbSdkLoaded = true;
|
||||
return;
|
||||
}
|
||||
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?.fbApiVersion || 'v21.0',
|
||||
});
|
||||
this.fbSdkLoaded = true;
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
},
|
||||
]);
|
||||
|
||||
launchEmbeddedSignup() {
|
||||
if (!window.FB) {
|
||||
this.loadFacebookSdk();
|
||||
setTimeout(() => this.launchEmbeddedSignup(), 1000);
|
||||
return;
|
||||
}
|
||||
const showLoader = computed(() => hasSignupStarted.value || isProcessing.value);
|
||||
|
||||
this.currentStep = 'auth_processing';
|
||||
this.processingMessage = this.$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.AUTH_PROCESSING'
|
||||
);
|
||||
const handleSignupError = data => {
|
||||
currentStep.value = 'initial';
|
||||
isProcessing.value = false;
|
||||
authCodeReceived.value = false;
|
||||
isAuthenticating.value = false;
|
||||
hasSignupStarted.value = false;
|
||||
|
||||
// Following Facebook's embedded signup documentation
|
||||
window.FB.login(this.fbLoginCallback, {
|
||||
config_id: window.chatwootConfig?.whatsappConfigurationId,
|
||||
response_type: 'code',
|
||||
override_default_response_type: true,
|
||||
extras: {
|
||||
setup: {},
|
||||
featureType: '', // Leave empty for default flow
|
||||
sessionInfoVersion: '3',
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
fbLoginCallback(response) {
|
||||
if (response.authResponse && response.authResponse.code) {
|
||||
// Authorization code received from Facebook
|
||||
this.authCode = response.authResponse.code;
|
||||
this.authCodeReceived = true;
|
||||
this.currentStep = 'auth_received';
|
||||
this.processingMessage = this.$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.WAITING_FOR_BUSINESS_INFO'
|
||||
);
|
||||
|
||||
// Check if we already have business data and process immediately
|
||||
if (this.businessData) {
|
||||
this.completeSignupFlow(this.businessData);
|
||||
}
|
||||
} else if (response.error) {
|
||||
this.handleSignupError({ error: response.error });
|
||||
} else {
|
||||
this.currentStep = 'initial';
|
||||
this.isProcessing = false;
|
||||
useAlert(this.$t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED'));
|
||||
}
|
||||
},
|
||||
|
||||
handleSignupMessage(event) {
|
||||
// Handle Facebook embedded signup message events
|
||||
try {
|
||||
const originUrl = new URL(event.origin);
|
||||
const allowedHosts = ['facebook.com', 'www.facebook.com'];
|
||||
if (!allowedHosts.includes(originUrl.hostname)) return;
|
||||
} catch (error) {
|
||||
// Invalid origin URL, reject the event
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
if (data.type === 'WA_EMBEDDED_SIGNUP') {
|
||||
this.handleEmbeddedSignupData(data);
|
||||
}
|
||||
} catch (error) {
|
||||
// Handle non-JSON messages silently
|
||||
}
|
||||
},
|
||||
|
||||
async handleEmbeddedSignupData(data) {
|
||||
// Handle different embedded signup events per Facebook documentation
|
||||
if (data.event === 'FINISH') {
|
||||
// Facebook might send business data in different structures
|
||||
let businessData = data.data;
|
||||
|
||||
// If data.data doesn't exist, try other possible structures
|
||||
if (!businessData) {
|
||||
businessData = data.business_data || data.details || data;
|
||||
}
|
||||
|
||||
// Validate we have the required business information
|
||||
if (
|
||||
businessData &&
|
||||
(businessData.business_id || businessData.businessId) &&
|
||||
(businessData.waba_id || businessData.wabaId)
|
||||
) {
|
||||
// Normalize the data structure to match our backend expectations
|
||||
const normalizedData = {
|
||||
business_id: businessData.business_id || businessData.businessId,
|
||||
waba_id: businessData.waba_id || businessData.wabaId,
|
||||
phone_number_id:
|
||||
businessData.phone_number_id ||
|
||||
businessData.phoneNumberId ||
|
||||
businessData.phone_id,
|
||||
};
|
||||
|
||||
// Store business data
|
||||
this.businessData = normalizedData;
|
||||
// Check if we already have auth code and process immediately
|
||||
if (this.authCodeReceived && this.authCode) {
|
||||
await this.completeSignupFlow(normalizedData);
|
||||
} else {
|
||||
this.currentStep = 'waiting_for_auth';
|
||||
this.processingMessage = 'Waiting for authentication...';
|
||||
}
|
||||
} else {
|
||||
this.handleSignupError({
|
||||
error:
|
||||
'Invalid business data received from Facebook. Please try again.',
|
||||
});
|
||||
}
|
||||
} else if (data.event === 'CANCEL') {
|
||||
this.handleSignupCancellation(data);
|
||||
} else if (data.event === 'error') {
|
||||
this.handleSignupError({
|
||||
error: data.error_message || 'Signup error occurred',
|
||||
error_id: data.error_id,
|
||||
session_id: data.session_id,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async completeSignupFlow(businessData) {
|
||||
if (!this.authCodeReceived || !this.authCode) {
|
||||
this.handleSignupError({
|
||||
error: 'Authentication not completed. Please restart the process.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentStep = 'processing';
|
||||
this.isProcessing = true;
|
||||
this.processingMessage = this.$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.PROCESSING'
|
||||
);
|
||||
|
||||
try {
|
||||
// Send both auth code and business info together (synchronous flow)
|
||||
const accountId = this.$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'),
|
||||
...this.authHeaders,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
account_id: accountId,
|
||||
code: this.authCode,
|
||||
business_id: businessData.business_id,
|
||||
waba_id: businessData.waba_id,
|
||||
phone_number_id: businessData.phone_number_id,
|
||||
}),
|
||||
});
|
||||
|
||||
const responseData = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
// Clear the stored auth code for security
|
||||
this.authCode = null;
|
||||
|
||||
// Handle synchronous success response
|
||||
this.handleSignupSuccess(responseData);
|
||||
} else {
|
||||
throw new Error(responseData.message || responseData.error);
|
||||
}
|
||||
} catch (error) {
|
||||
this.handleSignupError({ error: error.message });
|
||||
}
|
||||
},
|
||||
|
||||
handleSignupCancellation(data) {
|
||||
this.currentStep = 'initial';
|
||||
this.isProcessing = false;
|
||||
this.authCodeReceived = false;
|
||||
|
||||
let message = this.$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED'
|
||||
);
|
||||
if (data.data?.current_step) {
|
||||
message += ` (Step: ${data.data.current_step})`;
|
||||
}
|
||||
|
||||
useAlert(message);
|
||||
},
|
||||
|
||||
handleSignupSuccess(inboxData) {
|
||||
this.currentStep = 'completed';
|
||||
this.isProcessing = false;
|
||||
|
||||
// Update the store with the new inbox data
|
||||
if (inboxData && inboxData.id) {
|
||||
// Add the new inbox to the store
|
||||
this.$store.commit('inboxes/ADD_INBOXES', inboxData);
|
||||
|
||||
useAlert(this.$t('INBOX_MGMT.FINISH.MESSAGE'));
|
||||
|
||||
router.replace({
|
||||
name: 'settings_inboxes_add_agents',
|
||||
params: {
|
||||
page: 'new',
|
||||
inbox_id: inboxData.id,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// Fallback if inbox data is not properly formatted
|
||||
useAlert('WhatsApp Business Account has been successfully configured');
|
||||
router.replace({
|
||||
name: 'settings_inbox_list',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleSignupError(data) {
|
||||
this.currentStep = 'initial';
|
||||
this.isProcessing = false;
|
||||
this.authCodeReceived = false;
|
||||
|
||||
const errorMessage =
|
||||
data.error ||
|
||||
data.message ||
|
||||
this.$t('INBOX_MGMT.ADD.WHATSAPP.API.ERROR_MESSAGE');
|
||||
useAlert(errorMessage);
|
||||
},
|
||||
|
||||
resetSignupFlow() {
|
||||
this.currentStep = 'initial';
|
||||
this.isProcessing = false;
|
||||
this.authCodeReceived = false;
|
||||
this.processingMessage = '';
|
||||
this.authCode = null;
|
||||
this.businessData = null;
|
||||
},
|
||||
},
|
||||
const errorMessage =
|
||||
data.error ||
|
||||
data.message ||
|
||||
t('INBOX_MGMT.ADD.WHATSAPP.API.ERROR_MESSAGE');
|
||||
useAlert(errorMessage);
|
||||
};
|
||||
|
||||
const handleSignupCancellation = data => {
|
||||
currentStep.value = 'initial';
|
||||
isProcessing.value = false;
|
||||
authCodeReceived.value = false;
|
||||
isAuthenticating.value = false;
|
||||
hasSignupStarted.value = false;
|
||||
|
||||
let message = t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.CANCELLED');
|
||||
if (data.data?.current_step) {
|
||||
message += ` (Step: ${data.data.current_step})`;
|
||||
}
|
||||
|
||||
useAlert(message);
|
||||
};
|
||||
|
||||
const handleSignupSuccess = inboxData => {
|
||||
currentStep.value = 'completed';
|
||||
isProcessing.value = false;
|
||||
isAuthenticating.value = false;
|
||||
|
||||
// Update the store with the new inbox data
|
||||
if (inboxData && inboxData.id) {
|
||||
// Add the new inbox to the store
|
||||
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 {
|
||||
// Fallback if inbox data is not properly formatted
|
||||
useAlert(t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.SUCCESS_FALLBACK'));
|
||||
router.replace({
|
||||
name: 'settings_inbox_list',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const completeSignupFlow = async businessDataParam => {
|
||||
if (!authCodeReceived.value || !authCode.value) {
|
||||
handleSignupError({
|
||||
error: t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.AUTH_NOT_COMPLETED'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
currentStep.value = 'processing';
|
||||
isProcessing.value = true;
|
||||
processingMessage.value = t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.PROCESSING'
|
||||
);
|
||||
|
||||
try {
|
||||
// Send both auth code and business info together (synchronous flow)
|
||||
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) {
|
||||
// Clear the stored auth code for security
|
||||
authCode.value = null;
|
||||
|
||||
// Handle synchronous success response
|
||||
handleSignupSuccess(responseData);
|
||||
} else {
|
||||
throw new Error(responseData.message || responseData.error);
|
||||
}
|
||||
} catch (error) {
|
||||
handleSignupError({ error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
const handleEmbeddedSignupData = async data => {
|
||||
// Handle different embedded signup events per Facebook documentation
|
||||
if (data.event === 'FINISH') {
|
||||
// Facebook might send business data in different structures
|
||||
let businessDataLocal = data.data;
|
||||
|
||||
// If data.data doesn't exist, try other possible structures
|
||||
if (!businessDataLocal) {
|
||||
businessDataLocal = data.business_data || data.details || data;
|
||||
}
|
||||
|
||||
// Validate we have the required business information
|
||||
if (
|
||||
businessDataLocal &&
|
||||
(businessDataLocal.business_id || businessDataLocal.businessId) &&
|
||||
(businessDataLocal.waba_id || businessDataLocal.wabaId)
|
||||
) {
|
||||
// Normalize the data structure to match our backend expectations
|
||||
const normalizedData = {
|
||||
business_id:
|
||||
businessDataLocal.business_id || businessDataLocal.businessId,
|
||||
waba_id: businessDataLocal.waba_id || businessDataLocal.wabaId,
|
||||
phone_number_id:
|
||||
businessDataLocal.phone_number_id ||
|
||||
businessDataLocal.phoneNumberId ||
|
||||
businessDataLocal.phone_id,
|
||||
};
|
||||
|
||||
// Store business data
|
||||
businessData.value = normalizedData;
|
||||
// Check if we already have auth code and process immediately
|
||||
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'
|
||||
),
|
||||
});
|
||||
}
|
||||
} else if (data.event === 'CANCEL') {
|
||||
handleSignupCancellation(data);
|
||||
} else if (data.event === 'error') {
|
||||
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 fbLoginCallback = response => {
|
||||
if (response.authResponse && response.authResponse.code) {
|
||||
// Authorization code received from Facebook
|
||||
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'
|
||||
);
|
||||
|
||||
// Check if we already have business data and process immediately
|
||||
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 handleSignupMessage = event => {
|
||||
// Handle Facebook embedded signup message events
|
||||
try {
|
||||
const originUrl = new URL(event.origin);
|
||||
const allowedHosts = ['facebook.com', 'www.facebook.com'];
|
||||
if (!allowedHosts.includes(originUrl.hostname)) return;
|
||||
} catch (error) {
|
||||
// Invalid origin URL, reject the event
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
if (data.type === 'WA_EMBEDDED_SIGNUP') {
|
||||
handleEmbeddedSignupData(data);
|
||||
}
|
||||
} catch (error) {
|
||||
// Handle non-JSON messages silently
|
||||
}
|
||||
};
|
||||
|
||||
const loadFacebookSdk = () => {
|
||||
if (window.FB) {
|
||||
fbSdkLoaded.value = true;
|
||||
return;
|
||||
}
|
||||
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?.fbApiVersion || 'v21.0',
|
||||
});
|
||||
fbSdkLoaded.value = true;
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
};
|
||||
|
||||
const launchEmbeddedSignup = () => {
|
||||
hasSignupStarted.value = true;
|
||||
processingMessage.value = t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.AUTH_PROCESSING'
|
||||
);
|
||||
|
||||
if (!window.FB) {
|
||||
loadFacebookSdk();
|
||||
setTimeout(() => launchEmbeddedSignup(), 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
isAuthenticating.value = true;
|
||||
currentStep.value = 'auth_processing';
|
||||
|
||||
// Following Facebook's embedded signup documentation
|
||||
window.FB.login(fbLoginCallback, {
|
||||
config_id: window.chatwootConfig?.whatsappConfigurationId,
|
||||
response_type: 'code',
|
||||
override_default_response_type: true,
|
||||
extras: {
|
||||
setup: {},
|
||||
featureType: '', // Leave empty for default flow
|
||||
sessionInfoVersion: '3',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadFacebookSdk();
|
||||
window.addEventListener('message', handleSignupMessage);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('message', handleSignupMessage);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<div v-if="isProcessing" class="py-8 text-center">
|
||||
<div class="mb-4">
|
||||
<div
|
||||
class="w-12 h-12 mx-auto border-b-2 border-blue-600 rounded-full animate-spin"
|
||||
/>
|
||||
</div>
|
||||
<h3 class="mb-2 text-lg font-medium text-slate-800 dark:text-slate-100">
|
||||
{{ processingMessage }}
|
||||
</h3>
|
||||
<p class="text-slate-600 dark:text-slate-300">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.PROCESSING_DESC') }}
|
||||
</p>
|
||||
</div>
|
||||
<LoadingState v-if="showLoader" :message="processingMessage" />
|
||||
|
||||
<div>
|
||||
<div v-else>
|
||||
<div class="flex flex-col items-start mb-4 text-left">
|
||||
<div class="flex justify-start mb-5">
|
||||
<div class="flex items-center justify-center w-12 h-12 rounded-lg">
|
||||
<img
|
||||
src="dashboard/assets/images/whatsapp.png"
|
||||
:src="whatsappIcon"
|
||||
:alt="$t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.WHATSAPP_CLOUD')"
|
||||
class="object-contain w-10 h-10"
|
||||
/>
|
||||
@@ -350,30 +359,19 @@ export default {
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2 mb-8">
|
||||
<div class="flex items-center gap-2 text-sm text-slate-11">
|
||||
<div
|
||||
v-for="benefit in benefits"
|
||||
:key="benefit.key"
|
||||
class="flex items-center gap-2 text-sm text-slate-11"
|
||||
>
|
||||
<Icon icon="i-lucide-check" class="text-slate-11" />
|
||||
{{
|
||||
$t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.EASY_SETUP')
|
||||
}}
|
||||
</div>
|
||||
<div class="flex items-center gap-2 text-sm text-slate-11">
|
||||
<Icon icon="i-lucide-check" class="text-slate-11" />
|
||||
<span>
|
||||
{{
|
||||
$t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.SECURE_AUTH')
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 text-sm text-slate-11">
|
||||
<Icon icon="i-lucide-check" class="text-slate-11" />
|
||||
{{
|
||||
$t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.AUTO_CONFIG')
|
||||
}}
|
||||
{{ benefit.text }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NextButton
|
||||
:disabled="!fbSdkLoaded"
|
||||
:disabled="!fbSdkLoaded || isAuthenticating"
|
||||
:loading="isAuthenticating"
|
||||
faded
|
||||
slate
|
||||
@click="launchEmbeddedSignup"
|
||||
|
||||
Reference in New Issue
Block a user