FEAT: Adicionado configuração para canal de atendimento Whatsapp
This commit is contained in:
parent
072cd1cb75
commit
c4b846a079
@ -1,4 +1,5 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { DataPanel } from '../components/DataPanel';
|
import { DataPanel } from '../components/DataPanel';
|
||||||
import { ManagementLayout } from '../components/ManagementLayout';
|
import { ManagementLayout } from '../components/ManagementLayout';
|
||||||
import { ManagementTable } from '../components/ManagementTable';
|
import { ManagementTable } from '../components/ManagementTable';
|
||||||
@ -65,6 +66,7 @@ const integrationCards = [
|
|||||||
name: 'WhatsApp',
|
name: 'WhatsApp',
|
||||||
icon: 'WA',
|
icon: 'WA',
|
||||||
color: '#20a45b',
|
color: '#20a45b',
|
||||||
|
configured: true,
|
||||||
description: 'Canal principal para atendimento, abertura ativa e continuidade das conversas no chat.',
|
description: 'Canal principal para atendimento, abertura ativa e continuidade das conversas no chat.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -73,6 +75,7 @@ const integrationCards = [
|
|||||||
name: 'SMS',
|
name: 'SMS',
|
||||||
icon: 'SM',
|
icon: 'SM',
|
||||||
color: '#00a4b7',
|
color: '#00a4b7',
|
||||||
|
configured: false,
|
||||||
description: 'Envio de comunicados curtos, confirmações e mensagens transacionais para contatos sem WhatsApp.',
|
description: 'Envio de comunicados curtos, confirmações e mensagens transacionais para contatos sem WhatsApp.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -81,6 +84,7 @@ const integrationCards = [
|
|||||||
name: 'Email',
|
name: 'Email',
|
||||||
icon: 'EM',
|
icon: 'EM',
|
||||||
color: '#d8891c',
|
color: '#d8891c',
|
||||||
|
configured: false,
|
||||||
description: 'Recebimento e resposta de demandas por email dentro da fila omnichannel.',
|
description: 'Recebimento e resposta de demandas por email dentro da fila omnichannel.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -89,6 +93,7 @@ const integrationCards = [
|
|||||||
name: 'SharePoint',
|
name: 'SharePoint',
|
||||||
icon: 'SP',
|
icon: 'SP',
|
||||||
color: '#036c70',
|
color: '#036c70',
|
||||||
|
configured: false,
|
||||||
description: 'Permite que a IA visualize documentos autorizados para alimentar e manter a base de conhecimento.',
|
description: 'Permite que a IA visualize documentos autorizados para alimentar e manter a base de conhecimento.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -97,6 +102,7 @@ const integrationCards = [
|
|||||||
name: 'Gupy',
|
name: 'Gupy',
|
||||||
icon: 'GP',
|
icon: 'GP',
|
||||||
color: '#7b4cc2',
|
color: '#7b4cc2',
|
||||||
|
configured: false,
|
||||||
description: 'Conecta vagas abertas e processos dos candidatos para enriquecer a base de conhecimento.',
|
description: 'Conecta vagas abertas e processos dos candidatos para enriquecer a base de conhecimento.',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -180,6 +186,7 @@ export function AdminAttendanceWorkspace({ isWideDesktop, isDesktop, isTablet, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function AdminPage() {
|
export function AdminPage() {
|
||||||
|
const navigate = useNavigate();
|
||||||
const { isWideDesktop, isDesktop, isTablet, isMobile } = useViewport();
|
const { isWideDesktop, isDesktop, isTablet, isMobile } = useViewport();
|
||||||
const userDisplay = getCurrentUserDisplay();
|
const userDisplay = getCurrentUserDisplay();
|
||||||
const [activeAdminSection, setActiveAdminSection] = useState('home');
|
const [activeAdminSection, setActiveAdminSection] = useState('home');
|
||||||
@ -213,6 +220,8 @@ export function AdminPage() {
|
|||||||
sharepoint: false,
|
sharepoint: false,
|
||||||
gupy: false,
|
gupy: false,
|
||||||
});
|
});
|
||||||
|
const [integrationNotice, setIntegrationNotice] = useState('');
|
||||||
|
const [configurationModal, setConfigurationModal] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
@ -1271,6 +1280,21 @@ export function AdminPage() {
|
|||||||
const channelCount = integrationCards.filter((item) => item.group === 'Canal' && integrationStates[item.id]).length;
|
const channelCount = integrationCards.filter((item) => item.group === 'Canal' && integrationStates[item.id]).length;
|
||||||
const integrationCount = integrationCards.filter((item) => item.group === 'Integração' && integrationStates[item.id]).length;
|
const integrationCount = integrationCards.filter((item) => item.group === 'Integração' && integrationStates[item.id]).length;
|
||||||
|
|
||||||
|
function toggleIntegration(item) {
|
||||||
|
const isEnabled = Boolean(integrationStates[item.id]);
|
||||||
|
|
||||||
|
if (!isEnabled && !item.configured) {
|
||||||
|
setIntegrationNotice(`${item.name} ainda não pode ser habilitado porque precisa ser configurado primeiro.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIntegrationNotice('');
|
||||||
|
setIntegrationStates((current) => ({
|
||||||
|
...current,
|
||||||
|
[item.id]: !current[item.id],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section style={{ display: 'grid', gap: '1rem' }}>
|
<section style={{ display: 'grid', gap: '1rem' }}>
|
||||||
<DataPanel
|
<DataPanel
|
||||||
@ -1305,6 +1329,22 @@ export function AdminPage() {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{integrationNotice ? (
|
||||||
|
<div
|
||||||
|
role="alert"
|
||||||
|
style={{
|
||||||
|
border: '1px solid rgba(216, 137, 28, 0.32)',
|
||||||
|
borderRadius: 16,
|
||||||
|
padding: '0.85rem 1rem',
|
||||||
|
background: 'rgba(216, 137, 28, 0.08)',
|
||||||
|
color: '#7a4a08',
|
||||||
|
fontWeight: 800,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{integrationNotice}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</DataPanel>
|
</DataPanel>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -1371,12 +1411,7 @@ export function AdminPage() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-pressed={isEnabled}
|
aria-pressed={isEnabled}
|
||||||
onClick={() => {
|
onClick={() => toggleIntegration(item)}
|
||||||
setIntegrationStates((current) => ({
|
|
||||||
...current,
|
|
||||||
[item.id]: !current[item.id],
|
|
||||||
}));
|
|
||||||
}}
|
|
||||||
style={{
|
style={{
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: 999,
|
borderRadius: 999,
|
||||||
@ -1422,10 +1457,18 @@ export function AdminPage() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span style={{ color: isEnabled ? item.color : 'var(--color-text-soft)', fontWeight: 800 }}>
|
<span style={{ color: isEnabled ? item.color : 'var(--color-text-soft)', fontWeight: 800 }}>
|
||||||
{isEnabled ? 'Habilitado' : 'Desabilitado'}
|
{isEnabled ? 'Habilitado' : item.configured ? 'Desabilitado' : 'Pendente de configuração'}
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
if (item.id === 'whatsapp') {
|
||||||
|
navigate('/admin/whatsapp');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfigurationModal(item);
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${item.color}44`,
|
border: `1px solid ${item.color}44`,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
@ -1442,6 +1485,85 @@ export function AdminPage() {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{configurationModal ? (
|
||||||
|
<div
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="integration-config-title"
|
||||||
|
style={{
|
||||||
|
position: 'fixed',
|
||||||
|
inset: 0,
|
||||||
|
background: 'rgba(0, 20, 32, 0.42)',
|
||||||
|
display: 'grid',
|
||||||
|
placeItems: 'center',
|
||||||
|
padding: '1rem',
|
||||||
|
zIndex: 50,
|
||||||
|
}}
|
||||||
|
onClick={() => setConfigurationModal(null)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
onClick={(event) => event.stopPropagation()}
|
||||||
|
style={{
|
||||||
|
width: 'min(460px, 100%)',
|
||||||
|
borderRadius: 22,
|
||||||
|
border: '1px solid var(--color-border)',
|
||||||
|
background: '#fff',
|
||||||
|
padding: '1.25rem',
|
||||||
|
display: 'grid',
|
||||||
|
gap: '0.9rem',
|
||||||
|
boxShadow: 'var(--shadow-lg)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '0.8rem' }}>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
borderRadius: 14,
|
||||||
|
display: 'grid',
|
||||||
|
placeItems: 'center',
|
||||||
|
background: configurationModal.color,
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 900,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{configurationModal.icon}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong id="integration-config-title" style={{ display: 'block', fontSize: '1.08rem' }}>
|
||||||
|
Configurar {configurationModal.name}
|
||||||
|
</strong>
|
||||||
|
<span style={{ color: 'var(--color-text-soft)', fontWeight: 700 }}>
|
||||||
|
{configurationModal.group}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style={{ margin: 0, color: 'var(--color-text-soft)', lineHeight: 1.5, fontWeight: 700 }}>
|
||||||
|
Esta configuração ainda está em construção. Assim que a integração estiver disponível, este espaço vai reunir credenciais, permissões e parâmetros de sincronização.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setConfigurationModal(null)}
|
||||||
|
style={{
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: 14,
|
||||||
|
padding: '0.75rem 0.95rem',
|
||||||
|
background: 'var(--color-primary)',
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 800,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Entendi
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user