import { useState } from 'react' import { FeatureCallout } from '../components/FeatureState.jsx' import { analyticsRepository } from '../repositories/analyticsRepository.js' const periods = [ ['1m', '1 Mes'], ['3m', '3 Meses'], ['6m', '6 Meses'], ['1a', '1 Ano'], ] const cardClass = 'rounded-2xl border border-[#404040] bg-[#262626] shadow-sm' export function AnalyticsPage() { const { absenteeismData, consultationsData, doctorPerformance, insuranceData, kpis, revenueData, topPatients, } = analyticsRepository.getDashboardData() const [period, setPeriod] = useState('6m') return (

Analytics

Dashboard executivo com métricas de desempenho

{periods.map(([key, label]) => ( ))}
{kpis.map((kpi) => ( ))}
{topPatients.map((patient, index) => (
{index + 1}.

{patient.name}

{patient.visits} visitas • R$ {patient.revenue.toLocaleString('pt-BR')}

))}

Performance por Médico

{doctorPerformance.map((doctor) => { const noShowRate = (doctor.noShow / doctor.consultas) * 100 return ( ) })}
Profissional Consultas No-Show Taxa No-Show Satisfação
{doctor.name} {doctor.consultas} {doctor.noShow} {noShowRate.toFixed(1)}% {doctor.satisfacao}
) } function KpiCard({ kpi }) { return (

{kpi.label}

{kpi.value}

{kpi.change} vs período anterior
) } function ChartCard({ children, description, title }) { return (

{title}

{description}

{children}
) } function AreaMetricChart({ data }) { const points = getLinePoints(data.map((item) => item.taxa), 0, 24) const metaPoints = getLinePoints(data.map((item) => item.meta), 0, 24) const area = `${points} 600,260 42,260` return ( {data.map((item, index) => ( {item.month} ))} ) } function GroupedBarChart({ data }) { return ( {data.map((item, index) => { const x = 58 + index * 94 const totalHeight = (item.total / 600) * 220 const doneHeight = (item.realizadas / 600) * 220 return ( {item.month} ) })} ) } function RevenueChart({ data }) { const points = getLinePoints( data.map((item) => item.valor), 30000, 60000, { left: 32, top: 18, width: 270, height: 160 }, ) return ( {[0, 1, 2, 3].map((line) => ( ))} {points.split(' ').map((point, index) => { const [x, y] = point.split(',').map(Number) return })} {data.map((item, index) => ( {item.month} ))} ) } function InsuranceBreakdown({ insuranceData }) { const radius = 42 const circumference = 2 * Math.PI * radius const segments = insuranceData.reduce((items, item) => { const dash = (item.value / 100) * circumference const previous = items.at(-1) const offset = previous ? previous.offset + previous.dash + 4 : 0 return [...items, { ...item, dash, offset }] }, []) return (
{segments.map((item) => ( ))}
{insuranceData.map((item) => (
{item.name} {item.value}%
))}
) } function ChartGrid({ labels }) { return ( <> {labels.map((label, index) => { const y = 20 + index * 60 return ( {label} ) })} ) } function getLinePoints(values, min, max, box = { left: 42, top: 20, width: 558, height: 240 }) { return values .map((value, index) => { const x = box.left + (index / Math.max(values.length - 1, 1)) * box.width const y = box.top + ((max - value) / (max - min)) * box.height return `${x.toFixed(1)},${y.toFixed(1)}` }) .join(' ') } function rateClass(rate) { if (rate > 15) { return 'text-red-400' } if (rate > 10) { return 'text-amber-400' } return 'text-emerald-400' } function AnalyticsIcon({ className = 'size-4', name }) { const common = { className, fill: 'none', stroke: 'currentColor', strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 1.9, viewBox: '0 0 24 24', } if (name === 'calendar') { return ( ) } if (name === 'activity') { return ( ) } if (name === 'dollar') { return ( ) } if (name === 'users') { return ( ) } if (name === 'arrow-up') { return ( ) } if (name === 'arrow-down') { return ( ) } return ( ) }