import React, { useState, useEffect, useCallback, useRef } from 'react';
import {
Users,
Settings,
LayoutDashboard,
LogOut,
Mail,
MessageSquare,
Search,
Plus,
Calendar,
FileUp,
ShieldCheck,
AlertCircle,
Clock,
ArrowRightLeft,
CheckCircle2,
XCircle,
Database,
History,
Phone,
Filter,
MoreVertical,
Save,
Trash2,
Bell,
Code,
UserPlus
} from 'lucide-react';
// --- CONFIGURAÇÕES ---
const APP_NAME = "Via Line Vendas";
const LOGO_URL = "https://vialine.net.br/wp-content/uploads/2025/01/via-line-logo-branca-e1736367873609-123x50.png.webp";
// --- COMPONENTES DE UI ---
const Card = ({ children, className = "" }) => (
{children}
);
const Button = ({ children, onClick, variant = 'primary', className = "", type = "button", disabled = false }) => {
const variants = {
primary: `bg-red-600 text-white hover:bg-red-700`,
secondary: `bg-white text-gray-700 border border-gray-300 hover:bg-gray-50`,
danger: `bg-red-100 text-red-600 hover:bg-red-200`,
success: `bg-green-600 text-white hover:bg-green-700`,
ghost: `bg-transparent text-gray-500 hover:bg-gray-100`
};
return (
);
};
const Input = ({ label, ...props }) => (
{label && }
);
const Badge = ({ children, variant = "neutral" }) => {
const styles = {
neutral: "bg-gray-100 text-gray-600",
success: "bg-green-100 text-green-700",
warning: "bg-orange-100 text-orange-700",
danger: "bg-red-100 text-red-700",
info: "bg-blue-100 text-blue-700"
};
return {children};
};
// --- APP PRINCIPAL ---
export default function App() {
const [user, setUser] = useState(null);
const [currentPage, setCurrentPage] = useState('login');
const [isSidebarOpen, setSidebarOpen] = useState(true);
const [logs, setLogs] = useState([]);
const [leads, setLeads] = useState([]);
const [selectedLead, setSelectedLead] = useState(null);
const [searchQuery, setSearchQuery] = useState('');
const [notifications, setNotifications] = useState([]);
const [mustChangePassword, setMustChangePassword] = useState(false);
const fileInputRef = useRef(null);
// Estados Gerenciáveis (Usuários e Templates)
const [systemUsers, setSystemUsers] = useState([
{ id: 1, name: 'Administrador Master', login: 'admin', role: 'master', created: '01/01/2024' }
]);
const [messageTemplate, setMessageTemplate] = useState(
"Olá {{nome}}, somos da Via Line! Notamos que seu Ponto de Atendimento {{ponto_de_acesso}} está qualificado para uma migração gratuita. Vamos agendar?"
);
// Estados de Configuração de Banco
const [config, setConfig] = useState({
dbHost: 'localhost',
dbName: 'vialine_vendas',
dbUser: '',
dbPass: '',
});
// --- LOGICA DE NOTIFICAÇÕES ---
useEffect(() => {
const interval = setInterval(() => {
const now = new Date();
const due = leads.filter(l => l.retorno && new Intl.DateTimeFormat('pt-BR', { dateStyle: 'short', timeStyle: 'short' }).format(new Date(l.retorno)) === new Intl.DateTimeFormat('pt-BR', { dateStyle: 'short', timeStyle: 'short' }).format(now));
if (due.length > 0) setNotifications(prev => [...due, ...prev]);
}, 60000);
return () => clearInterval(interval);
}, [leads]);
// --- LÓGICA DE LOGIN ---
const handleLogin = (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const login = formData.get('login');
const pass = formData.get('password');
const foundUser = systemUsers.find(u => u.login === login);
if ((login === 'admin' && pass === 'admin') || (foundUser && pass === '123456')) {
setUser(foundUser || { id: 1, name: 'Administrador Master', role: 'master' });
if (login === 'admin') setMustChangePassword(true);
setCurrentPage('dashboard');
addLog(`Login realizado por ${login}`);
} else {
alert('Credenciais inválidas! (Dica: Novos usuários usam 123456 como padrão)');
}
};
const addLog = (action) => {
const newLog = {
id: Date.now(),
user: user?.name || 'Sistema',
action,
time: new Date().toLocaleString()
};
setLogs([newLog, ...logs]);
};
// --- LÓGICA DE IMPORTAÇÃO CSV ---
const handleFileUpload = (e) => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
const text = event.target.result;
const rows = text.split('\n').filter(row => row.trim() !== '');
const headers = rows[0].split(',').map(h => h.trim().replace(/"/g, ''));
const newLeads = rows.slice(1).map((row, idx) => {
const values = row.split(',').map(v => v.trim().replace(/"/g, ''));
const lead = {};
headers.forEach((h, i) => {
let key = h;
if (h === 'SSID') key = 'ponto_de_acesso';
if (h === 'Called ID') key = 'vlan';
if (h === 'Nome Razão Social') key = 'nome';
if (h === 'Fone 01') key = 'telefone';
if (h === 'E-mail') key = 'email';
lead[key] = values[i];
});
return {
...lead,
id: Date.now() + idx,
status: 'Pendente',
tentativas: 0,
historico: [],
criado_em: new Date().toISOString()
};
});
setLeads(prev => [...newLeads, ...prev]);
addLog(`Importação: ${newLeads.length} novos clientes.`);
alert(`${newLeads.length} clientes importados!`);
};
reader.readAsText(file);
};
// --- GESTÃO DE LEAD ---
const updateLeadStatus = (leadId, newStatus, observation = "", scheduleReturn = null) => {
setLeads(prev => prev.map(l => {
if (l.id === leadId) {
const historyItem = {
data: new Date().toLocaleString(),
status: newStatus,
obs: observation,
usuario: user.name
};
return {
...l,
status: newStatus,
tentativas: l.tentativas + 1,
retorno: scheduleReturn || l.retorno,
historico: [historyItem, ...l.historico]
};
}
return l;
}));
addLog(`Lead #${leadId} -> ${newStatus}`);
setSelectedLead(null);
};
// --- COMPONENTES DE PÁGINA ---
const UsersPage = () => {
const [newUser, setNewUser] = useState({ name: '', login: '', role: 'vendedor' });
const handleAddUser = () => {
if (!newUser.name || !newUser.login) return alert('Preencha nome e login');
const userObj = {
...newUser,
id: Date.now(),
created: new Date().toLocaleDateString('pt-BR')
};
setSystemUsers([...systemUsers, userObj]);
setNewUser({ name: '', login: '', role: 'vendedor' });
addLog(`Usuário ${userObj.login} adicionado.`);
};
const removeUser = (id) => {
if (id === 1) return alert('O usuário Master principal não pode ser removido.');
setSystemUsers(systemUsers.filter(u => u.id !== id));
addLog(`Usuário ID ${id} removido.`);
};
return (
Cadastrar Novo Usuário
Lista de Usuários Ativos
| Nome |
Login |
Nível |
Data Cadastro |
Ações |
{systemUsers.map(u => (
| {u.name} |
{u.login} |
{u.role}
|
{u.created} |
|
))}
);
};
const ConfigPage = () => {
return (
);
};
const SalesFunnel = () => {
const columns = ['Pendente', 'Em Contato', 'Agendado', 'Migrado', 'Não Deseja'];
const filteredLeads = leads.filter(l =>
l.nome?.toLowerCase().includes(searchQuery.toLowerCase()) ||
l.CPF?.includes(searchQuery)
);
return (
{columns.map(status => (
{status}
{filteredLeads.filter(l => l.status === status).length}
{filteredLeads.filter(l => l.status === status).map(lead => (
setSelectedLead(lead)}
className="bg-white p-3 rounded-lg shadow-sm border border-gray-200 hover:border-red-400 cursor-pointer transition-all group"
>
{lead.nome}
{lead.telefone}
Tentativas: {lead.tentativas}
{lead.vlan}
))}
))}
);
};
const LeadModal = () => {
if (!selectedLead) return null;
const [obs, setObs] = useState('');
const [retornoDate, setRetornoDate] = useState('');
const copyGeneratedMessage = () => {
let msg = messageTemplate
.replace('{{nome}}', selectedLead.nome || '')
.replace('{{ponto_de_acesso}}', selectedLead.ponto_de_acesso || '')
.replace('{{vlan}}', selectedLead.vlan || '')
.replace('{{telefone}}', selectedLead.telefone || '')
.replace('{{bairro}}', selectedLead.Bairro || '')
.replace('{{plano}}', selectedLead.Plano || '');
const el = document.createElement('textarea');
el.value = msg;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
alert('Mensagem personalizada copiada para a área de transferência!');
};
return (
{selectedLead.nome}
Status: {selectedLead.status}
Ponto de Acesso:
{selectedLead.ponto_de_acesso}
VLAN:
{selectedLead.vlan}
Contato:
{selectedLead.telefone}
Bairro:
{selectedLead.Bairro}
Linha do Tempo
{selectedLead.historico.map((h, i) => (
{h.status}
"{h.obs}"
{h.data}
))}
);
};
const Dashboard = () => (
Base Importada
{leads.length}
Agendamentos
{leads.filter(l => l.status === 'Agendado').length}
Vendas Concluídas
{leads.filter(l => l.status === 'Migrado').length}
Conversão
{leads.length > 0 ? ((leads.filter(l => l.status === 'Migrado').length / leads.length) * 100).toFixed(1) : 0}%
Próximos Contatos (Alertas)
{notifications.length === 0 ?
Sem alertas para agora.
: notifications.map((n, i) => (
))}
Eventos Recentes
{logs.slice(0, 10).map(log => (
{log.action}
{log.time} - {log.user}
))}
);
// --- RENDERIZADOR ---
if (currentPage === 'login') {
return (
);
}
return (
{user?.name}
{user?.role}
{user?.name?.[0]}
{currentPage === 'dashboard' && }
{currentPage === 'funil' && }
{currentPage === 'usuarios' && }
{currentPage === 'configuracoes' && }
);
}