import React, { useState } from 'react'; import { TrendingUp, Users, Calendar, DollarSign, ArrowUpRight, ArrowDownRight, Printer, Filter, Loader2, Download, BarChart3, PieChart, Activity } from 'lucide-react'; import { HybridBackend } from '../services/backend.ts'; import { useHybridBackend } from '../hooks/useHybridBackend.ts'; import { PageHeader } from '../components/PageHeader.tsx'; interface ReportData { financeiro: { receita: number; despesa: number; totalTransacoes: number; }; producao: { dentista: string; totalAgendamentos: number; concluidos: number; faltas: number; }[]; } export const ReportsView: React.FC = () => { const activeWorkspace = HybridBackend.getActiveWorkspace(); const [startDate, setStartDate] = useState(new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString().split('T')[0]); const [endDate, setEndDate] = useState(new Date().toISOString().split('T')[0]); const { data, isLoading, error, refresh } = useHybridBackend(() => activeWorkspace ? HybridBackend.getProductivityReport(activeWorkspace.id, startDate, endDate) : Promise.resolve(null), [activeWorkspace?.id, startDate, endDate] ); const receita = data?.financeiro?.receita || 0; const despesa = data?.financeiro?.despesa || 0; const saldo = receita - despesa; const exportToCSV = () => { if (!data) return; let csv = "Dentista,Total,Concluidos,Faltas,Taxa Ocupacao\n"; data.producao.forEach(p => { const taxa = p.totalAgendamentos > 0 ? ((p.concluidos / p.totalAgendamentos) * 100).toFixed(1) : 0; csv += `${p.dentista},${p.totalAgendamentos},${p.concluidos},${p.faltas},${taxa}%\n`; }); const blob = new Blob([csv], { type: 'text/csv' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `relatorio_producao_${startDate}_${endDate}.csv`; a.click(); }; return (
{/* Filters */}
setStartDate(e.target.value)} className="bg-gray-50 border border-gray-200 rounded-xl px-4 py-2.5 text-sm font-bold text-gray-700 focus:ring-2 focus:ring-blue-100 outline-none transition-all" />
setEndDate(e.target.value)} className="bg-gray-50 border border-gray-200 rounded-xl px-4 py-2.5 text-sm font-bold text-gray-700 focus:ring-2 focus:ring-blue-100 outline-none transition-all" />
{isLoading ? (

Processando dados clínicos...

) : (
{/* Financial Summary */}

RECEITA NO PERÍODO

R$ {receita.toLocaleString('pt-BR', { minimumFractionDigits: 2 })} +2.4%

DESPESA NO PERÍODO

R$ {despesa.toLocaleString('pt-BR', { minimumFractionDigits: 2 })} -1.2%

SALDO OPERACIONAL

= 0 ? 'text-blue-600' : 'text-red-600'}`}> R$ {saldo.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}

LIQUIDEZ ATUAL DA UNIDADE

TRANSAÇÕES

{data?.financeiro?.totalTransacoes || 0}

MOVIMENTAÇÕES FINANCEIRAS

{/* Productivity Table */}

PRODUTIVIDADE POR DENTISTA

DESEMPENHO CLÍNICO NO PERÍODO

Visão por Especialista
{(data?.producao || []).map((p, idx) => { const occupancy = p.totalAgendamentos > 0 ? (p.concluidos / p.totalAgendamentos) * 100 : 0; return ( ); })}
ESPECIALISTA TOTAL APPTS EFETIVADOS FALTAS TAXA OCUPAÇÃO STATUS
{p.dentista.substring(0, 2).toUpperCase()}
{p.dentista}
{p.totalAgendamentos} {p.concluidos} {p.faltas}
70 ? 'bg-green-500' : occupancy > 40 ? 'bg-blue-500' : 'bg-orange-400'}`} style={{ width: `${occupancy}%` }} >
{occupancy.toFixed(0)}%
{occupancy > 75 ? ( Alta Performance ) : occupancy > 30 ? ( Estável ) : ( Baixa Ocupação )}
)}
); };