Stress Index: Analytics e Sport rifatti sulle viste reali

Le due sezioni erano ferme al prototipo locale, più povero della
piattaforma vera. Analytics ha ora l'intervallo di date, i KPI con la
nota sotto il valore, la distribuzione dello score a quattro serie per
fascia, le classifiche per recupero medio col numero di misurazioni e il
confronto segmenti con selettore di dimensione. Sport diventa Dashboard,
Sessioni con filtri atleta/periodo/sport e schede atleta con carico e
tendenza.

I numeri non sono più costanti scritte a mano: si calcolano dai dati nel
periodo scelto. La logica sta in lib/stress-index/analytics.ts e sport.ts,
coperta da test — che hanno subito trovato uno slittamento delle settimane
dovuto alle date costruite in ora locale invece che in UTC.

Le sessioni hanno ora ora di inizio, HR max, RPE e durata al secondo, che
il prototipo non prevedeva.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 16:20:40 +02:00
parent c4eb598a3a
commit 3cda76b4c4
17 changed files with 907 additions and 409 deletions
+31 -8
View File
@@ -45,14 +45,6 @@
padding: 1px 7px; font-size: .58rem; letter-spacing: .1em;
}
.si-foot {
display: flex; flex-direction: column; gap: 9px; margin-top: auto; padding-top: 20px;
border-top: 1px solid rgba(255,255,255,.12);
}
.si-foot__role { font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: var(--c-accent); }
.si-foot a { font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: #8d8379; text-decoration: none; }
.si-foot a:hover { color: #fff; }
/* --- shell contenuto --- */
.si-body { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }
.si-top {
@@ -285,3 +277,34 @@
.si-org p { margin: 0; }
.si-org .si-field { text-align: left; }
.si-org__cta:disabled { opacity: .45; cursor: not-allowed; }
/* --- analytics: intervallo e classifiche --- */
.si-range { display: flex; align-items: center; gap: 8px; }
.si-range__sep { color: var(--c-text-light); }
.si-range input { padding: 7px 10px; }
.si-card__head p { margin: 4px 0 0; }
.si-rank { list-style: none; margin: 0; padding: 0; }
.si-rank li { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-bottom: 1px solid var(--si-line); }
.si-rank li:last-child { border-bottom: 0; }
.si-rank a { text-decoration: none; color: var(--c-heading); font-weight: 600; font-size: .9rem; }
.si-rank a:hover { color: var(--c-accent-dark); }
.si-rank__value { display: block; text-align: right; font-family: var(--font-heading); font-size: 1.05rem; }
.si-rank__value--ok { color: var(--si-ok); }
.si-rank__value--bad { color: var(--si-bad); }
.si-rank__count { display: block; text-align: right; font-size: .72rem; color: var(--c-text-light); }
/* --- modulo sport --- */
.si-badge--pro { background: var(--c-accent); color: #fff; vertical-align: middle; margin-left: 8px; }
.si-filters { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.si-filters__count { margin: 0 0 8px auto; }
.si-athlete__name { font-size: 1.05rem; text-transform: none; letter-spacing: .02em; margin: 0 0 2px; }
.si-athlete__stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.si-athlete__stats > div { background: var(--c-bg-alt); padding: 14px 10px; text-align: center; }
.si-athlete__stats p { margin: 0; }
.si-athlete__num { font-family: var(--font-heading); font-size: 1.3rem; color: var(--c-heading); }
.si-athlete__foot {
display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 18px;
padding-top: 14px; border-top: 1px solid var(--si-line); text-decoration: none;
font-size: .82rem; color: var(--c-text-light);
}
.si-athlete__foot:hover { color: var(--c-accent-dark); }