// Pipeline Kanban View const Pipeline = ({ leads, setLeads, onOpenLead, onNewLead }) => { const [dragging, setDragging] = React.useState(null); const [dragOver, setDragOver] = React.useState(null); const handleDragStart = (lead) => setDragging(lead); const handleDragOver = (e, stage) => { e.preventDefault(); setDragOver(stage); }; const handleDrop = (stage) => { if (dragging && dragging.stage !== stage) { setLeads(prev => prev.map(l => l.id === dragging.id ? { ...l, stage } : l)); } setDragging(null); setDragOver(null); }; return (
Pipeline
Arraste os cards para mover entre etapas
{STAGES.map(stage => { const stageLeads = leads.filter(l => l.stage === stage); const stageVal = stageLeads.reduce((s, l) => s + l.valor, 0); const isOver = dragOver === stage; return (
handleDragOver(e, stage)} onDrop={() => handleDrop(stage)} onDragLeave={() => setDragOver(null)}>
{stage}
{stageLeads.length}
{formatCurrency(stageVal)}
{stageLeads.map(lead => (
handleDragStart(lead)} onDragEnd={() => { setDragging(null); setDragOver(null); }} onClick={() => onOpenLead(lead)} style={{ ...ps.card, ...(dragging?.id === lead.id ? ps.cardDragging : {}) }}>
{lead.empresa} {formatCurrency(lead.valor)}
{lead.contato}
{lead.responsavel.split(' ')[0]} {lead.followup && ( ⏰ {formatDate(lead.followup)} )}
{/* Checklist mini progress */}
{(() => { const done = lead.checklist.filter(c => c.done).length; const total = lead.checklist.length; const pct = Math.round((done / total) * 100); return ( <>
{done}/{total} ); })()}
))} {stageLeads.length === 0 && (
Sem leads
)}
); })}
); }; const ps = { page: { flex: 1, display: 'flex', flexDirection: 'column', background: '#0d1020', overflow: 'hidden' }, header: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '20px 24px 14px', flexShrink: 0 }, pageTitle: { fontSize: 22, fontWeight: 700, color: '#e8eaf0' }, pageSubtitle: { fontSize: 12, color: '#4a4f6a', marginTop: 2 }, addBtn: { background: '#4f7cff', color: '#fff', border: 'none', borderRadius: 8, padding: '9px 18px', fontSize: 13, fontWeight: 600, cursor: 'pointer', }, board: { display: 'flex', gap: 12, flex: 1, overflowX: 'auto', overflowY: 'hidden', padding: '0 24px 24px', alignItems: 'flex-start', }, column: { minWidth: 230, width: 230, background: '#151828', borderRadius: 12, border: '1px solid #1e2235', display: 'flex', flexDirection: 'column', maxHeight: 'calc(100vh - 130px)', transition: 'border-color 0.15s', flexShrink: 0, }, columnOver: { borderColor: '#4f7cff', background: '#151e38' }, colHeader: { padding: '14px 14px 4px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, colTitle: { fontSize: 12, fontWeight: 700, letterSpacing: 0.3 }, colCount: { fontSize: 11, background: '#1e2235', color: '#6b7194', borderRadius: 20, padding: '1px 7px', fontWeight: 700 }, colVal: { fontSize: 11, color: '#4a4f6a', padding: '2px 14px 10px', fontWeight: 600 }, colDivider: { height: 1, background: '#1e2235', marginBottom: 10 }, cards: { flex: 1, overflowY: 'auto', padding: '0 10px 10px', display: 'flex', flexDirection: 'column', gap: 8 }, card: { background: '#1a1d2e', border: '1px solid #1e2235', borderRadius: 9, padding: '10px 12px', cursor: 'grab', transition: 'all 0.15s', userSelect: 'none', }, cardDragging: { opacity: 0.5, transform: 'scale(0.97)' }, cardTop: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 6, marginBottom: 3 }, cardEmpresa: { fontSize: 12, fontWeight: 700, color: '#c7d2ff', lineHeight: 1.3, flex: 1 }, cardValor: { fontSize: 10, color: '#4ade80', fontWeight: 700, whiteSpace: 'nowrap' }, cardContato: { fontSize: 11, color: '#6b7194', marginBottom: 8 }, cardFooter: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }, cardResp: { fontSize: 10, color: '#4a4f6a', background: '#1e2235', borderRadius: 20, padding: '2px 7px' }, cardDate: { fontSize: 10 }, checkRow: { display: 'flex', alignItems: 'center', gap: 6 }, checkBg: { flex: 1, height: 3, background: '#1e2235', borderRadius: 2, overflow: 'hidden' }, checkFill: { height: '100%', borderRadius: 2, transition: 'width 0.3s' }, checkLabel: { fontSize: 9, color: '#4a4f6a', whiteSpace: 'nowrap' }, emptyCol: { textAlign: 'center', color: '#2a2d3e', fontSize: 12, padding: '20px 0', fontStyle: 'italic' }, }; Object.assign(window, { Pipeline });