# Calendario delle lezioni e dashboard con metriche

Status: validated (15/09/2026)

## Context

La dashboard mostra solo contatori grezzi (crediti, aule, lezioni in corso) e le prossime 8 lezioni. Non esiste una
vista d'insieme della pianificazione né metriche su lezioni completate, ore erogate e consumi. L'utente (responsabile
formazione) deve poter vedere in un colpo d'occhio cosa è stato fatto, cosa resta da fare e quanto ha consumato.

## Requirements

- Pagina `/calendario` (nav "Calendario") con viste mese, settimana e agenda; tutte le lezioni dell'ente, colore per
  aula, stato (pianificata / in corso / terminata), filtro per aula, navigazione periodo, "Oggi", click → pagina lezione;
  caricamento del solo intervallo visibile (Inertia partial reload).
- Servizio `App\Services\Reporting\DashboardMetrics` (scoped per company) che calcola: lezioni terminate, pianificate,
  in corso, di oggi e della settimana; ore erogate (effettive) vs ore pianificate; lezioni per settimana nelle ultime
  8 settimane; aule per stato; per ogni aula attiva ore usate / ore massime e partecipanti / massimo; crediti
  disponibili, consumati, in scadenza entro 30 giorni; presenza media % sulle ultime 20 lezioni terminate;
  sync Forma.Temp riuscite/fallite negli ultimi 30 giorni.
- Dashboard ridisegnata: riga di indicatori, grafico a barre settimanale (SVG, nessuna libreria), lista aule con
  barre di avanzamento ore, blocco consumi, blocco Forma.Temp, prossime lezioni, link al calendario.
- Nessuna nuova dipendenza npm; date gestite con helper in `resources/js/lib/date.ts`.

## Acceptance criteria

1. GET /calendario restituisce 200 con il componente Inertia `calendar/index` e props `range {from,to}`,
   `meetings[]` (solo quelle nell'intervallo: `id, uuid, title, scheduled_at, duration_minutes, status,
classroom {id, uuid, name, code, color}`) e `classrooms[]`; con `?from=2026-10-01&to=2026-10-31` non compaiono
   lezioni di settembre; una lezione di un'altra company non compare mai.
2. GET /calendario?view=week&date=2026-10-06 restituisce `range.from = 2026-10-05` (lunedì) e `range.to = 2026-10-11`.
3. Test unitario di `DashboardMetrics`: con 3 lezioni terminate (durate effettive 60, 90, 120 min), 2 pianificate
   future da 60 min e 1 in corso, restituisce `meetings.ended = 3`, `meetings.scheduled = 2`, `meetings.running = 1`,
   `hours.delivered = 4.5`, `hours.planned = 2` (solo le future), e `weekly` con 8 elementi la cui somma di `ended`
   è 3.
4. Con un'aula `max_hours = 10` e lezioni terminate per 6 ore, `classrooms.usage[0].hours_used = 6` e
   `hours_percent = 60`; con 5 crediti di cui 2 consumati e 1 in scadenza tra 10 giorni, `credits = {available: 3,
consumed: 2, expiring_soon: 1}`.
5. GET /dashboard espone `metrics` con le chiavi sopra e la pagina mostra il grafico settimanale (elemento `svg`
   con `data-testid="weekly-chart"`), la sezione consumi e il link "Apri il calendario"; `npm run types:check`,
   `npm run check`, `npm run build` e `composer test` passano.

## Out of scope

Drag & drop per riprogrammare, esportazione iCal, report PDF, metriche per docente, confronto tra periodi.
