/* ============================================================
CRM — conexão do WhatsApp e componentes compartilhados
============================================================ */
let crmMetaSdkPromise = null;
function loadCrmMetaSdk(appId, graphVersion) {
if (window.FB) return Promise.resolve(window.FB);
if (crmMetaSdkPromise) return crmMetaSdkPromise;
crmMetaSdkPromise = new Promise((resolve, reject) => {
const previousInit = window.fbAsyncInit;
window.fbAsyncInit = function () {
if (typeof previousInit === 'function') previousInit();
window.FB.init({
appId: String(appId),
cookie: true,
xfbml: false,
version: String(graphVersion),
});
resolve(window.FB);
};
const existing = document.getElementById('facebook-jssdk');
if (existing) {
const timer = window.setInterval(() => {
if (window.FB) {
window.clearInterval(timer);
resolve(window.FB);
}
}, 100);
window.setTimeout(() => {
window.clearInterval(timer);
if (!window.FB) reject(new Error('Não foi possível abrir a conexão.'));
}, 15000);
return;
}
const script = document.createElement('script');
script.id = 'facebook-jssdk';
script.async = true;
script.defer = true;
script.crossOrigin = 'anonymous';
script.src = 'https://connect.facebook.net/pt_BR/sdk.js';
script.onerror = () => reject(new Error('Não foi possível abrir a conexão.'));
document.head.appendChild(script);
});
return crmMetaSdkPromise;
}
function createEmbeddedSignupWaiter() {
let cancel = () => {};
const promise = new Promise((resolve, reject) => {
let finished = false;
const done = (fn, value) => {
if (finished) return;
finished = true;
window.clearTimeout(timer);
window.removeEventListener('message', handler);
fn(value);
};
const handler = (event) => {
let eventUrl;
try { eventUrl = new URL(event.origin); } catch { return; }
if (
eventUrl.protocol !== 'https:'
|| (eventUrl.hostname !== 'facebook.com' && !eventUrl.hostname.endsWith('.facebook.com'))
) return;
let message = event.data;
if (typeof message === 'string') {
try { message = JSON.parse(message); } catch { return; }
}
if (!message || message.type !== 'WA_EMBEDDED_SIGNUP') return;
const finishEvents = [
'FINISH',
'FINISH_ONLY_WABA',
'FINISH_WHATSAPP_BUSINESS_APP_ONBOARDING',
];
if (finishEvents.includes(message.event)) {
const data = message.data || {};
done(resolve, {
wabaId: String(data.waba_id || ''),
phoneNumberId: String(data.phone_number_id || ''),
businessId: String(data.business_id || ''),
});
} else if (message.event === 'CANCEL' || message.event === 'ERROR') {
done(reject, new Error(message.event === 'CANCEL'
? 'A conexão foi cancelada.'
: 'Não foi possível concluir a conexão.'));
}
};
const timer = window.setTimeout(
() => done(reject, new Error('A conexão expirou. Tente novamente.')),
3 * 60 * 1000
);
cancel = () => done(resolve, null);
window.addEventListener('message', handler);
});
return { promise, cancel: () => cancel() };
}
function crmMessageWhen(value) {
if (!value) return '';
const date = new Date(String(value).replace(' ', 'T'));
if (Number.isNaN(date.getTime())) return String(value);
return date.toLocaleString('pt-BR', {
day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit',
});
}
const crmMessageStatusLabels = {
pending: 'Pendente',
sent: 'Enviada',
delivered: 'Entregue',
read: 'Lida',
failed: 'Falhou',
received: 'Recebida',
};
function CrmRequestDate(value) {
if (!value) return '';
const date = new Date(String(value).replace(' ', 'T'));
if (Number.isNaN(date.getTime())) return '';
return date.toLocaleString('pt-BR', {
day: '2-digit', month: '2-digit', year: 'numeric',
hour: '2-digit', minute: '2-digit',
});
}
function CrmInactiveScreen({ user }) {
const [requestedAt, setRequestedAt] = React.useState(user.crmActivationRequestedAt || '');
const [requesting, setRequesting] = React.useState(false);
const [error, setError] = React.useState('');
const canRequest = user.role === 'admin' && user.isPrimaryAdmin;
const isReactivation = ['suspended', 'cancelled'].includes(String(user.crmModuleStatus || ''));
const formattedRequestDate = CrmRequestDate(requestedAt);
React.useEffect(() => {
if (user.crmActivationRequestedAt) setRequestedAt(user.crmActivationRequestedAt);
}, [user.crmActivationRequestedAt]);
const requestActivation = async () => {
if (!canRequest || requesting || requestedAt) return;
setRequesting(true);
setError('');
try {
const result = await window.API.crm.requestActivation();
setRequestedAt(result.requestedAt || new Date().toISOString());
} catch (err) {
setError(err && err.message
? err.message
: 'Não foi possível enviar a solicitação. Tente novamente.');
} finally {
setRequesting(false);
}
};
return (
CRM integrado à Agenda
Transforme conversas em atendimento organizado
Reúna o WhatsApp da empresa em uma caixa de entrada compartilhada,
distribua os atendimentos para sua equipe e mantenha cada conversa
conectada ao histórico do cliente.
{requestedAt ? (
Solicitação enviada
{formattedRequestDate
? `Recebida em ${formattedRequestDate}. Nossa equipe entrará em contato.`
: 'Nossa equipe entrará em contato para concluir a ativação.'}