feat: add Whatsapp embedded signup API
This commit is contained in:
@@ -222,6 +222,7 @@
|
||||
"DESC": "Start supporting your customers via WhatsApp.",
|
||||
"PROVIDERS": {
|
||||
"LABEL": "API Provider",
|
||||
"WHATSAPP_EMBEDDED": "WhatsApp Business (Embedded Signup)",
|
||||
"TWILIO": "Twilio",
|
||||
"WHATSAPP_CLOUD": "WhatsApp Cloud",
|
||||
"360_DIALOG": "360Dialog"
|
||||
@@ -264,6 +265,28 @@
|
||||
"WEBHOOK_VERIFICATION_TOKEN": "Webhook Verification Token"
|
||||
},
|
||||
"SUBMIT_BUTTON": "Create WhatsApp Channel",
|
||||
"EMBEDDED_SIGNUP": {
|
||||
"TITLE": "Quick Setup with Meta",
|
||||
"DESC": "Connect your WhatsApp Business Account directly through Meta's secure signup flow.",
|
||||
"BENEFITS": {
|
||||
"TITLE": "Benefits of Embedded Signup:",
|
||||
"EASY_SETUP": "One-click setup with no manual configuration required",
|
||||
"SECURE_AUTH": "Secure OAuth-based authentication with Meta",
|
||||
"AUTO_CONFIG": "Automatic webhook and phone number configuration"
|
||||
},
|
||||
"SUBMIT_BUTTON": "Connect with WhatsApp Business",
|
||||
"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."
|
||||
},
|
||||
"API": {
|
||||
"ERROR_MESSAGE": "We were not able to save the WhatsApp channel"
|
||||
}
|
||||
|
||||
+3
-77
@@ -1,12 +1,10 @@
|
||||
<script>
|
||||
/* eslint-env browser */
|
||||
/* global FB */
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useVuelidate } from '@vuelidate/core';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { required } from '@vuelidate/validators';
|
||||
import router from '../../../../index';
|
||||
import { loadScript } from 'dashboard/helper/DOMHelpers';
|
||||
import { isPhoneE164OrEmpty, isNumber } from 'shared/helpers/Validators';
|
||||
|
||||
import NextButton from 'dashboard/components-next/button/Button.vue';
|
||||
@@ -37,73 +35,8 @@ export default {
|
||||
phoneNumberId: { required, isNumber },
|
||||
businessAccountId: { required, isNumber },
|
||||
},
|
||||
mounted() {
|
||||
this.initializeFacebookSDK();
|
||||
},
|
||||
|
||||
methods: {
|
||||
async initializeFacebookSDK() {
|
||||
try {
|
||||
await this.loadFBsdk();
|
||||
this.runFBInit();
|
||||
} catch (error) {
|
||||
useAlert(this.$t('INBOX_MGMT.DETAILS.ERROR_FB_LOADING'));
|
||||
}
|
||||
},
|
||||
|
||||
runFBInit() {
|
||||
FB.init({
|
||||
appId: window.chatwootConfig.fbAppId,
|
||||
xfbml: true,
|
||||
version: window.chatwootConfig.fbApiVersion,
|
||||
status: true,
|
||||
});
|
||||
window.fbSDKLoaded = true;
|
||||
FB.AppEvents.logPageView();
|
||||
},
|
||||
|
||||
async loadFBsdk() {
|
||||
return loadScript('https://connect.facebook.net/en_US/sdk.js', {
|
||||
id: 'facebook-jssdk',
|
||||
});
|
||||
},
|
||||
|
||||
fbLoginCallback(response) {
|
||||
console.log('fbLoginCallback', response);
|
||||
if (response.authResponse) {
|
||||
const code = response.authResponse.code;
|
||||
// Handle the code here
|
||||
this.handleWhatsAppCode(code);
|
||||
} else {
|
||||
useAlert(this.$t('INBOX_MGMT.DETAILS.ERROR_FB_AUTH'));
|
||||
}
|
||||
},
|
||||
|
||||
handleWhatsAppCode(code) {
|
||||
// TODO: Implement code handling logic
|
||||
console.log('Received WhatsApp code:', code);
|
||||
},
|
||||
|
||||
async launchWhatsAppSignup() {
|
||||
if (!window.fbSDKLoaded) {
|
||||
await this.initializeFacebookSDK();
|
||||
}
|
||||
|
||||
try {
|
||||
FB.login(this.fbLoginCallback, {
|
||||
config_id: window.chatwootConfig.fbAppId,
|
||||
response_type: 'code',
|
||||
override_default_response_type: true,
|
||||
extras: {
|
||||
setup: {},
|
||||
featureType: '',
|
||||
sessionInfoVersion: '3',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
useAlert(this.$t('INBOX_MGMT.DETAILS.ERROR_FB_AUTH'));
|
||||
}
|
||||
},
|
||||
|
||||
async createChannel() {
|
||||
this.v$.$touch();
|
||||
if (this.v$.$invalid) {
|
||||
@@ -146,14 +79,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NextButton
|
||||
type="submit"
|
||||
solid
|
||||
blue
|
||||
:label="$t('INBOX_MGMT.ADD.WHATSAPP.SUBMIT_BUTTON')"
|
||||
@click="launchWhatsAppSignup"
|
||||
/>
|
||||
<!-- <form class="flex flex-col flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||
<form class="flex flex-col flex-wrap mx-0" @submit.prevent="createChannel()">
|
||||
<div class="flex-grow-0 flex-shrink-0">
|
||||
<label :class="{ error: v$.inboxName.$error }">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.INBOX_NAME.LABEL') }}
|
||||
@@ -248,5 +174,5 @@ export default {
|
||||
:label="$t('INBOX_MGMT.ADD.WHATSAPP.SUBMIT_BUTTON')"
|
||||
/>
|
||||
</div>
|
||||
</form> -->
|
||||
</form>
|
||||
</template>
|
||||
|
||||
@@ -3,6 +3,7 @@ import PageHeader from '../../SettingsSubPageHeader.vue';
|
||||
import Twilio from './Twilio.vue';
|
||||
import ThreeSixtyDialogWhatsapp from './360DialogWhatsapp.vue';
|
||||
import CloudWhatsapp from './CloudWhatsapp.vue';
|
||||
import WhatsappEmbeddedSignup from './WhatsappEmbeddedSignup.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -10,10 +11,11 @@ export default {
|
||||
Twilio,
|
||||
ThreeSixtyDialogWhatsapp,
|
||||
CloudWhatsapp,
|
||||
WhatsappEmbeddedSignup,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
provider: 'whatsapp_cloud',
|
||||
provider: 'whatsapp_embedded',
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -31,6 +33,9 @@ export default {
|
||||
<label>
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.LABEL') }}
|
||||
<select v-model="provider">
|
||||
<option value="whatsapp_embedded">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.WHATSAPP_EMBEDDED') }}
|
||||
</option>
|
||||
<option value="whatsapp_cloud">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.WHATSAPP_CLOUD') }}
|
||||
</option>
|
||||
@@ -41,7 +46,8 @@ export default {
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<Twilio v-if="provider === 'twilio'" type="whatsapp" />
|
||||
<WhatsappEmbeddedSignup v-if="provider === 'whatsapp_embedded'" />
|
||||
<Twilio v-else-if="provider === 'twilio'" type="whatsapp" />
|
||||
<ThreeSixtyDialogWhatsapp v-else-if="provider === '360dialog'" />
|
||||
<CloudWhatsapp v-else />
|
||||
</div>
|
||||
|
||||
+396
@@ -0,0 +1,396 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import router from '../../../../index';
|
||||
import NextButton from 'dashboard/components-next/button/Button.vue';
|
||||
import Auth from 'dashboard/api/auth';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NextButton,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fbSdkLoaded: false,
|
||||
isProcessing: false,
|
||||
processingMessage: '',
|
||||
authCodeReceived: false,
|
||||
currentStep: 'initial', // 'initial', 'auth_received', 'processing', 'completed'
|
||||
authCode: null,
|
||||
businessData: null, // Store business data when received
|
||||
};
|
||||
},
|
||||
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 {};
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.loadFacebookSdk();
|
||||
window.addEventListener('message', this.handleSignupMessage);
|
||||
},
|
||||
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;
|
||||
}
|
||||
|
||||
this.currentStep = 'auth_processing';
|
||||
this.processingMessage = this.$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.AUTH_PROCESSING'
|
||||
);
|
||||
|
||||
// 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
|
||||
if (!event.origin.endsWith('facebook.com')) 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;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<!-- Processing State -->
|
||||
<div v-if="isProcessing" class="text-center py-8">
|
||||
<div class="mb-4">
|
||||
<div
|
||||
class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"
|
||||
/>
|
||||
</div>
|
||||
<h3 class="text-lg font-medium text-gray-900 mb-2">
|
||||
{{ processingMessage }}
|
||||
</h3>
|
||||
<p class="text-gray-600">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.PROCESSING_DESC') }}
|
||||
</p>
|
||||
|
||||
<!-- Show current step for better UX -->
|
||||
<div class="mt-4 text-sm text-gray-500">
|
||||
<span v-if="currentStep === 'auth_processing'">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.STEP_AUTH') }}
|
||||
</span>
|
||||
<span v-else-if="currentStep === 'auth_received'">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.STEP_BUSINESS') }}
|
||||
</span>
|
||||
<span v-else-if="currentStep === 'processing'">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.STEP_CREATING') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Initial Setup State -->
|
||||
<div v-else class="space-y-6">
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-6">
|
||||
<h3 class="text-lg font-medium text-blue-900 mb-3">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.TITLE') }}
|
||||
</h3>
|
||||
<p class="text-blue-800 mb-4">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.DESC') }}
|
||||
</p>
|
||||
|
||||
<div class="space-y-2 mb-6">
|
||||
<h4 class="font-medium text-blue-900">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.TITLE') }}
|
||||
</h4>
|
||||
<ul class="space-y-1 text-blue-800">
|
||||
<li class="flex items-center">
|
||||
<span class="w-2 h-2 bg-blue-600 rounded-full mr-3" />
|
||||
{{
|
||||
$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.EASY_SETUP'
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="w-2 h-2 bg-blue-600 rounded-full mr-3" />
|
||||
{{
|
||||
$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.SECURE_AUTH'
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="w-2 h-2 bg-blue-600 rounded-full mr-3" />
|
||||
{{
|
||||
$t(
|
||||
'INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.BENEFITS.AUTO_CONFIG'
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<NextButton
|
||||
:disabled="!fbSdkLoaded"
|
||||
solid
|
||||
blue
|
||||
:label="$t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.SUBMIT_BUTTON')"
|
||||
@click="launchEmbeddedSignup"
|
||||
/>
|
||||
|
||||
<p v-if="!fbSdkLoaded" class="text-sm text-gray-500 mt-2">
|
||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.EMBEDDED_SIGNUP.LOADING_SDK') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user