import React, { useState, useEffect, useCallback } from 'react'; import { Building2, Wallet, Clock, RefreshCw, Inbox, CheckCircle2, Phone, CalendarDays, Stethoscope, Briefcase, User } from 'lucide-react'; import { HybridBackend } from '../services/backend.ts'; import { PageHeader } from '../components/PageHeader.tsx'; const fmtBRL = (v: number) => 'R$ ' + Number(v || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2 }); const dataBR = (d: string) => (d || '').slice(0, 10).split('-').reverse().join('/'); const mesBR = (m: string) => { const [y, mo] = (m || '').split('-'); return mo ? new Date(Number(y), Number(mo) - 1, 1).toLocaleDateString('pt-BR', { month: 'short', year: 'numeric' }) : m; }; const ORIGEM_META: Record = { 'Clínica': { icon: Building2, cls: 'bg-blue-100 text-blue-700' }, 'Consultório': { icon: Briefcase, cls: 'bg-teal-100 text-teal-700' }, 'Dentista': { icon: Stethoscope, cls: 'bg-violet-100 text-violet-700' }, 'Biomédico': { icon: User, cls: 'bg-pink-100 text-pink-700' }, 'Profissional': { icon: User, cls: 'bg-gray-100 text-gray-600' }, }; // CRM Financeiro do laboratório: Clientes (por origem, com contato/ticket/recebíveis) + Financeiro // (fechamento mensal + recebimentos). export const LabClientesView: React.FC<{ tab?: 'clientes' | 'financeiro' }> = ({ tab = 'clientes' }) => { const [aba, setAba] = useState<'clientes' | 'financeiro'>(tab); const [clientes, setClientes] = useState([]); const [pagamentos, setPagamentos] = useState([]); const [fechamento, setFechamento] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { setAba(tab); }, [tab]); const carregar = useCallback(async () => { setLoading(true); try { const [c, p, f] = await Promise.all([HybridBackend.getLabClientes(), HybridBackend.getLabPagamentos(), HybridBackend.getLabFechamento()]); setClientes(Array.isArray(c) ? c : []); setPagamentos(Array.isArray(p) ? p : []); setFechamento(Array.isArray(f) ? f : []); } catch { /* silent */ } finally { setLoading(false); } }, []); useEffect(() => { carregar(); }, [carregar]); const totFaturado = clientes.reduce((s, c) => s + Number(c.faturado || 0), 0); const totRecebido = clientes.reduce((s, c) => s + Number(c.recebido || 0), 0); const totReceber = clientes.reduce((s, c) => s + Number(c.a_receber || 0), 0); // resumo por origem const porOrigem: Record = {}; for (const c of clientes) porOrigem[c.origem] = (porOrigem[c.origem] || 0) + 1; const KPI: React.FC<{ titulo: string; valor: string; cor: string; Icon: any }> = ({ titulo, valor, cor, Icon }) => (

{titulo}

{valor}
); return (
{(['clientes', 'financeiro'] as const).map(t => ( ))}
{loading ?
: ( <> {aba === 'clientes' && ( clientes.length === 0 ?
Nenhuma clínica enviou OS ainda.
: ( <> {/* resumo por origem */}
{Object.entries(porOrigem).map(([o, n]) => { const m = ORIGEM_META[o] || ORIGEM_META['Profissional']; const I = m.icon; return {o}: {n}; })}
{['Cliente', 'Origem', 'Contato', 'OS', 'Ativas', 'Ticket méd.', 'Últ. pedido', 'A receber'].map(h => )} {clientes.map(c => { const m = ORIGEM_META[c.origem] || ORIGEM_META['Profissional']; return ( ); })}
{h}
{c.clinica_nome || '—'} {c.origem} {c.contato ? {c.contato} : '—'} {c.total} 0 ? 'text-red-500' : 'text-teal-600'}`}>{c.ativas}{c.atrasadas > 0 ? ` (${c.atrasadas}!)` : ''} {fmtBRL(c.ticket_medio)} {c.ultimo_pedido ? dataBR(c.ultimo_pedido) : '—'} 0 ? 'text-amber-600' : 'text-gray-300'}`}>{fmtBRL(c.a_receber)}
) )} {aba === 'financeiro' && ( <>
{/* Fechamento mensal */}

Fechamento mensal

{fechamento.length === 0 ?
Sem movimento ainda.
: (
{['Mês', 'Entregas', 'Faturado', 'Recebido', 'Saldo'].map(h => )} {fechamento.map(m => ( ))}
{h}
{mesBR(m.mes)} {m.entregues} {fmtBRL(m.faturado)} {fmtBRL(m.recebido)} 0 ? 'text-amber-600' : 'text-gray-300'}`}>{fmtBRL(Math.max(0, m.faturado - m.recebido))}
)}
{/* Extrato */}

Recebimentos

{pagamentos.length}
{pagamentos.length === 0 ?
Nenhum recebimento.
: (
{['Cliente', 'Trabalho', 'Forma', 'Data', 'Valor'].map(h => )} {pagamentos.map(p => ( ))}
{h}
{p.clinica_nome || '—'} {p.tipo || '—'} {p.forma || '—'} {dataBR(p.data)} {fmtBRL(p.valor)}
)}

Faturado = custo das OS entregues (≠ garantia). A receber = faturado − recebido.

)} )}
); };