import React, { useState, useEffect, useMemo } from 'react'; import ReactDOM from 'react-dom/client'; import { LayoutDashboard, MessageSquare, Users, Kanban, CheckSquare, Settings, ShieldAlert, LogOut, Bell, Search, Plus, Filter, MoreVertical, Send, ArrowRight, CheckCircle2, XCircle, Clock, AlertCircle, TrendingUp, Building2, UserPlus, Trash2, Edit3, Save, X, ChevronRight, UserCheck } from 'lucide-react'; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area, PieChart, Pie, Cell } from 'recharts'; // --- TYPES --- type UserRole = 'DEVELOPER' | 'DIRECTOR' | 'MANAGER' | 'CONSULTANT'; interface User { id: string; companyId: string; name: string; email: string; role: UserRole; teamId?: string; active: boolean; } interface Contact { id: string; companyId: string; name: string; phone: string; email: string; type: string; allowAI: boolean; companyName?: string; assignedUserId?: string; status: string; extension?: string; stageId: string; } interface Stage { id: string; name: string; order: number; noReplyTimeout: number; routingMode: string; isMandatory?: boolean; } interface Company { id: string; name: string; active: boolean; userLimit: number; memoryLimitGb: number; } // --- CONSTANTS --- const COLORS = { primary: '#ff7a59', secondary: '#2d3e50', success: '#00a4bd', warning: '#f5c26b' }; // --- SHARED COMPONENTS --- const Badge = ({ children, color = 'gray' }: any) => { const colors: any = { orange: 'bg-orange-50 text-orange-600 border-orange-100', blue: 'bg-blue-50 text-blue-600 border-blue-100', green: 'bg-green-50 text-green-600 border-green-100', gray: 'bg-gray-50 text-gray-600 border-gray-100', red: 'bg-red-50 text-red-600 border-red-100' }; return {children}; }; const Modal = ({ title, isOpen, onClose, children }: any) => { if (!isOpen) return null; return (

{title}

{children}
); }; // --- PAGES --- // 1. DASHBOARD const DashboardPage = () => { const data = [ { name: 'Seg', v: 40 }, { name: 'Ter', v: 55 }, { name: 'Qua', v: 45 }, { name: 'Qui', v: 70 }, { name: 'Sex', v: 60 }, { name: 'Sab', v: 30 }, { name: 'Dom', v: 20 } ]; return (

Visão Geral

Performance e KPIs da operação.

{[ { label: 'Conversas Ativas', val: '154', icon: , color: 'text-orange-500' }, { label: 'Novos Leads', val: '24', icon: , color: 'text-blue-500' }, { label: 'Tempo Médio', val: '3m 12s', icon: , color: 'text-green-500' }, { label: 'Taxa Resposta', val: '94%', icon: , color: 'text-purple-500' }, ].map((s, i) => (
{s.icon} +12%

{s.label}

{s.val}

))}

Volume de Mensagens

Ranking Performance

{['Bruno Silva', 'Alice Souza', 'Daniel Bueno'].map((name, i) => (
{i+1}

{name}

Time Vendas SP

{95 - i * 5}%
))}
); }; // 2. KANBAN interface KanbanProps { stages: Stage[]; contacts: Contact[]; onMove: (contactId: string, newStageId: string) => void; onEdit: (contact: Contact) => void; } const KanbanPage = ({ stages, contacts, onMove, onEdit }: KanbanProps) => { const [draggedId, setDraggedId] = useState(null); const handleDragStart = (e: React.DragEvent, id: string) => { setDraggedId(id); e.dataTransfer.setData('contactId', id); e.dataTransfer.effectAllowed = 'move'; }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; }; const handleDrop = (e: React.DragEvent, stageId: string) => { e.preventDefault(); const contactId = e.dataTransfer.getData('contactId'); if (contactId) { onMove(contactId, stageId); } setDraggedId(null); }; return (

Pipeline de Atendimento

Arraste os cards para mudar o status.

{(stages || []).sort((a, b) => a.order - b.order).map(stage => (
handleDrop(e, stage.id)} className="kanban-column flex flex-col bg-slate-100/50 rounded-[2.5rem] p-4 border border-slate-200/50" >
{stage.name} {contacts.filter(c => c.stageId === stage.id).length}
{contacts .filter(c => c.stageId === stage.id) .map((c) => (
handleDragStart(e, c.id)} onClick={() => onEdit(c)} className={`bg-white p-5 rounded-3xl border border-slate-200 shadow-sm hover:border-orange-500/40 cursor-grab active:cursor-grabbing transition-all hover:shadow-lg group relative ${draggedId === c.id ? 'opacity-40 grayscale' : ''}`} >
{c.type || 'Geral'}

{c.name}

{c.companyName || 'S/ Empresa'}

{c.name[0]}
Responsável
2h
))} {contacts.filter(c => c.stageId === stage.id).length === 0 && (
Vazio
)}
))}
); }; // 3. CONTACTS const ContactsPage = ({ contacts, onEdit }: { contacts: Contact[], onEdit: (c?: Contact) => void }) => { const [searchTerm, setSearchTerm] = useState(''); const filtered = contacts.filter(c => c.name.toLowerCase().includes(searchTerm.toLowerCase())); return (

Base de Contatos

Controle total dos seus leads.

setSearchTerm(e.target.value)} placeholder="Buscar por nome, e-mail ou empresa..." className="bg-transparent border-none outline-none text-xs w-full font-bold text-slate-700" />
{filtered.map(c => ( ))}
Contato Empresa Etapa IA
{c.name[0]}

{c.name}

{c.phone}

{c.companyName || '-'} {c.stageId.toUpperCase()}
); }; // 4. SETTINGS const SettingsPage = ({ stages }: { stages: Stage[] }) => { const [activeTab, setActiveTab] = useState<'pipeline' | 'teams' | 'fields' | 'webhooks'>('pipeline'); return (

Configurações

Ajustes e personalização da plataforma.

{['pipeline', 'teams', 'fields', 'webhooks'].map(tab => ( ))}
{activeTab === 'pipeline' && (

Etapas do Funil

{stages.map(stage => (
{stage.order}
{stage.name}
{stage.routingMode} {stage.isMandatory && Obrigatória}
))}
)}
); }; // 5. SUPER ADMIN const SuperAdminPage = ({ companies }: { companies: Company[] }) => { return (

Painel SaaS Adm

Controle central de empresas e usuários.

Empresas Ativas

{companies.map(co => ( ))}
Empresa Usuários Status

{co.name}

Plano Premium

{co.userLimit} {co.active ? 'Ativo' : 'Suspenso'}

Convidar Adm

Acesso exclusivo para desenvolvedores de sistema.

); }; // --- APP ROOT --- const App = () => { const [user, setUser] = useState(null); const [tab, setTab] = useState('dashboard'); const [isModalOpen, setIsModalOpen] = useState(false); const [editingContact, setEditingContact] = useState(null); const [data, setData] = useState({ users: [], contacts: [ { id: 'c1', name: 'João Silva', phone: '11 99999-0001', companyName: 'Logística S.A', allowAI: true, status: 'IN_PROGRESS', type: 'Venda', stageId: 's1', email: 'joao@log.com' }, { id: 'c2', name: 'Maria Souza', phone: '11 98888-0002', companyName: 'Tech Inovação', allowAI: false, status: 'NO_REPLY', type: 'Suporte', stageId: 's2', email: 'maria@tech.com' }, { id: 'c3', name: 'Daniel Bueno', phone: '11 97777-0003', companyName: 'Studio DB', allowAI: true, status: 'IN_PROGRESS', type: 'Venda', stageId: 's1', email: 'daniel@studio.com' } ], stages: [ { id: 's1', name: 'Novo Contato', order: 1, routingMode: 'CAROUSEL' }, { id: 's2', name: 'Em Atendimento', order: 2, routingMode: 'DEMAND' }, { id: 's3', name: 'Aguardando Cliente', order: 3, routingMode: 'PORTFOLIO' }, { id: 's4', name: 'Finalizado', order: 4, routingMode: 'MANAGER' } ], companies: [ { id: 'co-1', name: 'LOX Tech Solutions', active: true, userLimit: 50, memoryLimitGb: 10 }, { id: 'co-2', name: 'Braun Energia', active: true, userLimit: 5, memoryLimitGb: 2 } ] }); const handleLogin = (email: string, pass: string) => { if (email === 'daniel.bueno.studio@gmail.com' && pass === '123456') { setUser({ id: 'u-1', companyId: 'co-1', name: 'Daniel Bueno', email, role: 'DEVELOPER', active: true }); } else { alert("Credenciais de teste: daniel.bueno.studio@gmail.com / 123456"); } }; const moveContact = (contactId: string, newStageId: string) => { setData(prev => ({ ...prev, contacts: prev.contacts.map(c => c.id === contactId ? { ...c, stageId: newStageId } : c) })); }; const openEdit = (contact?: Contact) => { setEditingContact(contact || { id: '', companyId: '', name: '', phone: '', email: '', type: 'Venda', allowAI: false, status: 'IN_PROGRESS', stageId: 's1' }); setIsModalOpen(true); }; const saveContact = (e: React.FormEvent) => { e.preventDefault(); if (!editingContact) return; if (editingContact.id) { setData(prev => ({ ...prev, contacts: prev.contacts.map(c => c.id === editingContact.id ? editingContact : c) })); } else { const newId = 'c' + (data.contacts.length + 1); setData(prev => ({ ...prev, contacts: [...prev.contacts, { ...editingContact, id: newId }] })); } setIsModalOpen(false); }; if (!user) { // Reusing the inline login style for simplicity since we're in one file return (
L

LOX Atendimentos

CRM & Gestão de Atendimento

{ e.preventDefault(); handleLogin('daniel.bueno.studio@gmail.com', '123456'); }}>

Acesso de Desenvolvedor • Versão 1.2

); } const menu = [ { id: 'dashboard', label: 'Início', icon: , roles: ['DEVELOPER', 'DIRECTOR', 'MANAGER', 'CONSULTANT'] }, { id: 'kanban', label: 'CRM Kanban', icon: , roles: ['DEVELOPER', 'DIRECTOR', 'MANAGER', 'CONSULTANT'] }, { id: 'contacts', label: 'Contatos', icon: , roles: ['DEVELOPER', 'DIRECTOR', 'MANAGER', 'CONSULTANT'] }, { id: 'settings', label: 'Ajustes', icon: , roles: ['DEVELOPER', 'DIRECTOR'] }, { id: 'admin', label: 'SaaS Adm', icon: , roles: ['DEVELOPER'] }, ]; const visibleMenu = menu.filter(m => m.roles.includes(user.role)); return (

{user.name}

{user.role}

{user.name[0]}
{tab === 'dashboard' && } {tab === 'kanban' && } {tab === 'contacts' && } {tab === 'settings' && } {tab === 'admin' && }
setIsModalOpen(false)}>
setEditingContact({...editingContact!, name: e.target.value})} className="w-full bg-slate-50 border border-slate-200 p-4 rounded-2xl text-sm font-bold outline-none focus:ring-4 focus:ring-orange-500/10"/>
setEditingContact({...editingContact!, phone: e.target.value})} className="w-full bg-slate-50 border border-slate-200 p-4 rounded-2xl text-sm font-bold outline-none focus:ring-4 focus:ring-orange-500/10"/>
setEditingContact({...editingContact!, email: e.target.value})} className="w-full bg-slate-50 border border-slate-200 p-4 rounded-2xl text-sm font-bold outline-none focus:ring-4 focus:ring-orange-500/10" placeholder="exemplo@empresa.com"/>
setEditingContact({...editingContact!, companyName: e.target.value})} className="w-full bg-slate-50 border border-slate-200 p-4 rounded-2xl text-sm font-bold outline-none focus:ring-4 focus:ring-orange-500/10" placeholder="Nome da Empresa"/>

Ativar Inteligência Artificial

A IA responderá automaticamente as mensagens

); }; // --- INITIALIZE --- const root = ReactDOM.createRoot(document.getElementById('root')!); root.render();