// Analytics di studio. È un'isola React perché tutto dipende da due controlli — l'intervallo // di date e la dimensione di confronto — e ogni numero della pagina si ricalcola con essi. import { useMemo, useState } from 'react'; import DataChart from './charts/DataChart'; import type { Alert, Client, Measurement } from '../../lib/stress-index/data'; import { DIMENSIONI, METRICHE, classificaRecupero, confrontoSegmenti, distribuzione, kpis, type Dimensione, } from '../../lib/stress-index/analytics'; interface Props { clients: Client[]; measurementsByClient: Record; alerts: Alert[]; /** Intervallo iniziale, deciso dalla pagina. */ from: string; to: string; } const dataItaliana = (iso: string) => new Date(`${iso}T00:00:00`).toLocaleDateString('it-IT', { day: '2-digit', month: 'short', year: 'numeric' }); export default function AnalyticsView({ clients, measurementsByClient, alerts, from, to }: Props) { const [periodo, setPeriodo] = useState({ from, to }); const [dimensione, setDimensione] = useState('sesso'); const indicatori = useMemo(() => kpis(clients, measurementsByClient, alerts, periodo), [clients, measurementsByClient, alerts, periodo]); const fasce = useMemo(() => distribuzione(measurementsByClient, periodo), [measurementsByClient, periodo]); const classifica = useMemo(() => classificaRecupero(clients, measurementsByClient, periodo), [clients, measurementsByClient, periodo]); const segmenti = useMemo(() => confrontoSegmenti(clients, measurementsByClient, periodo, dimensione), [clients, measurementsByClient, periodo, dimensione]); const migliori = classifica.slice(0, 4); const critici = [...classifica].reverse().slice(0, 4); return (

Analytics di studio

Confronta i tuoi clienti, individua gli andamenti, calibra il lavoro

{indicatori.map((k) => (

{k.label}

{k.value}

{k.note}

))}

Distribuzione score clienti

Quante misurazioni cadono in ogni fascia di valore

({ ...m }))} height={300} />

Andamento migliore

Recupero medio più alto nel periodo

    {migliori.map((r) => (
  • {r.name} {r.recovery} {r.count} {r.count === 1 ? 'misurazione' : 'misurazioni'}
  • ))}

Clienti critici

Recupero medio più basso nel periodo

    {critici.map((r) => (
  • {r.name} {r.recovery} {r.count} {r.count === 1 ? 'misurazione' : 'misurazioni'}
  • ))}

Confronto segmenti

Valori medi per {dataItaliana(periodo.from)} – {dataItaliana(periodo.to)}

); }