import React, { useMemo } from 'react';
import {
Users,
DollarSign,
TrendingUp,
Megaphone,
Calendar,
ChevronRight,
ArrowUpRight,
ArrowDownRight,
Plus,
Clock,
ArrowRight
} from 'lucide-react';
import { PageHeader } from '../components/PageHeader.tsx';
import { useHybridBackend } from '../hooks/useHybridBackend.ts';
import { HybridBackend } from '../services/backend.ts';
import { NotificationCenter } from '../components/NotificationCenter.tsx';
const StatCard: React.FC<{
title: string;
value: string | number;
icon: React.ReactNode;
trend?: string;
isPositive?: boolean;
color: 'blue' | 'green' | 'purple' | 'amber';
onClick?: () => void;
}> = ({ title, value, icon, trend, isPositive, color, onClick }) => {
const bgLight = {
blue: 'bg-teal-50 text-teal-600',
green: 'bg-emerald-50 text-emerald-600',
purple: 'bg-emerald-50 text-emerald-600',
amber: 'bg-amber-50 text-amber-600'
};
return (
);
};
export const Dashboard: React.FC = () => {
const { data, isLoading } = useHybridBackend(HybridBackend.getDashboardStats);
const growthData = useMemo(() => {
if (!data?.growth || data.growth.length === 0) {
return Array(6).fill(null).map((_, i) => ({
label: `MÊS ${i + 1}`,
receita: 0,
despesa: 0,
heightP: '0%',
heightR: '0%'
}));
}
const maxVal = Math.max(...data.growth.map((g: any) => Math.max(parseFloat(g.receita), parseFloat(g.despesa))), 1000);
return data.growth.map((g: any) => {
const [year, month] = g.mes.split('-');
const date = new Date(parseInt(year), parseInt(month) - 1);
const label = date.toLocaleString('pt-BR', { month: 'short' }).toUpperCase();
return {
label,
receita: parseFloat(g.receita),
despesa: parseFloat(g.despesa),
// Proporção para o gráfico
heightR: `${(parseFloat(g.receita) / maxVal) * 100}%`,
heightD: `${(parseFloat(g.despesa) / maxVal) * 100}%`
};
}).slice(-6); // Garantir últimos 6
}, [data]);
const currentRole = HybridBackend.getCurrentRole();
const showFinancials = ['admin', 'donoclinica', 'funcionario'].includes(currentRole);
if (isLoading) {
return (
);
}
const stats = data?.stats || {
totalPacientes: 0,
totalAgendamentos: 0,
totalLeads: 0,
faturamentoTotal: 0,
despesasTotal: 0
};
const recent = data?.recentAgendamentos || [];
return (
{/* Stats Grid */}
}
trend="+12% este mês"
isPositive={true}
color="blue"
onClick={() => history.pushState({}, '', '/pacientes')}
/>
{showFinancials && (
}
trend="+5.4% vs mês ant."
isPositive={true}
color="green"
onClick={() => history.pushState({}, '', '/financeiro')}
/>
)}
}
trend="82% de ocupação"
isPositive={true}
color="purple"
onClick={() => history.pushState({}, '', '/agenda')}
/>
{showFinancials && (
}
trend="-2% vs ontem"
isPositive={false}
color="amber"
onClick={() => history.pushState({}, '', '/leads')}
/>
)}
{/* Growth Chart Area */}
{showFinancials && (
Crescimento Mensal
Receitas vs Despesas Reais
{growthData.map((d: any, i: number) => (
{/* Barra Despesa */}
{/* Barra Receita */}
{d.label}
))}
)}
{/* Recent Activity */}
Últimos Agendamentos
{recent.length > 0 ? recent.map((app: any) => (
history.pushState({}, '', '/agenda')}
className="flex items-center gap-4 group cursor-pointer"
>
{app.pacientenome || 'Paciente'}
{app.dentistaNome || 'Profissional'} • {new Date(app.start_time).toLocaleDateString('pt-BR')} {new Date(app.start_time).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })}
)) : (
Nenhum agendamento recente.
)}
);
};