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]) => (
))}
{topPatients.map((patient, index) => (
{index + 1}.
{patient.name}
{patient.visits} visitas • R$ {patient.revenue.toLocaleString('pt-BR')}
))}
Performance por Médico
| Profissional |
Consultas |
No-Show |
Taxa No-Show |
Satisfação |
{doctorPerformance.map((doctor) => {
const noShowRate = (doctor.noShow / doctor.consultas) * 100
return (
| {doctor.name} |
{doctor.consultas} |
{doctor.noShow} |
{noShowRate.toFixed(1)}%
|
★
{doctor.satisfacao}
|
)
})}
)
}
function KpiCard({ kpi }) {
return (
{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 (
)
}
function GroupedBarChart({ data }) {
return (
)
}
function RevenueChart({ data }) {
const points = getLinePoints(
data.map((item) => item.valor),
30000,
60000,
{ left: 32, top: 18, width: 270, height: 160 },
)
return (
)
}
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 (
{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 (
)
}