Componenti UI — dominio edu
🎯 Cosa fa
Sotto TrainingHub.BackOffice/Components/CRUD/edu/ vivono i
componenti Blazor CRUD auto-generati per le ~38 entità del dominio
formazione. Il pattern di generazione è lo stesso di inv e reg
(triade razor + razor.tt.cs + razor.cs + Forms/ + FormPopups/). Vedi
componenti UI inv per i dettagli.
Questa pagina documenta le particolarità edu-specifiche.
🗺️ Entità core in scope
| Entità | File | Note |
|---|---|---|
Category | Category.razor | Anagrafica semplice |
Course | Course.razor | Form ricco con cascade variante normativa |
TrainingSession | TrainingSession.razor | Sessione formativa (ciclo vita stati) |
TrainingSessionsCourse | TrainingSessionsCourse.razor | M:N session ↔ corso (co-erogazione) |
Appointment | Appointment.razor (grid CRUD) + Pages/AppointmentsCalendar/ (vista calendario page-level) | Doppia vista griglia + calendario |
AppointmentsCourse | AppointmentsCourse.razor | Cella della matrice "programma" (appointment × corso) |
AppointmentsCoursesArgument | AppointmentsCoursesArgument.razor | Argomenti trattati per slot × corso |
Location | Location.razor | Aule con indirizzo inline + FK opzionale a reg.companies (gestore aula) |
Teacher | Teacher.razor | Anagrafica docente |
AppointmentsTeacher | AppointmentsTeacher.razor | M:N con hourlyAmount |
TeacherCost | TeacherCost.razor | Costi per organizer |
TeacherSkill | TeacherSkill.razor | Competenze docente (skill matrix ↔ variant) |
🧩 Pattern chiave edu-specifici
Vista calendario appuntamenti
Pages/AppointmentsCalendar/AppointmentsCalendar.razor (route
/appointments-calendar) è la vista calendario principale degli
appuntamenti, complementare alla griglia standard Appointment.razor.
Scritta a mano (non CRUD-generata). Sub-componenti:
CalendarGrid.razor— rendering mese/settimana/giorno.AppointmentDetailPanel.razor— pannello laterale con dettagli appuntamento + contesto sessione + azioni Edit/Duplica/Modifica sessione.
Caratteristiche principali (per dettaglio vedi panoramica edu — Vista calendario custom):
- Filtri Corso/Sede/Docente/Sessione con cascade Corso → Sessione.
- Colore appuntamento derivato da
trainingTopics.color(primo topic alfabetico della session). - Click slot apre
AppointmentFormPopup; pulsante "Nuova Sessione" apreSessionPlannerPopup. - Conflict detection via
ISessionPlannerService.DetectConflictsAsynccon toast warning post-save. - Query param
?teacherId=<guid>per landing dal teacher-calendar.
Wizard pianificazione sessione
Components/edu/SessionPlanner/SessionPlannerPopup.razor è un
wizard 7-step per pianificare una sessione formativa
end-to-end. Le partial class
SessionPlannerPopup.razor.Step1Session.cs …
SessionPlannerPopup.razor.Step6Review.cs (più
SessionPlannerPopup.razor.Step4Program.cs) contengono la logica
per-step.
Il backend è ISessionPlannerService (in Shared/Services/SessionPlanner/)
con stato persistito su SessionPlannerState + SessionCoursePlan[].
Step:
- Sessione — data inizio + argomento opzionale (filtra corsi).
- Corsi — aggiunge uno o più corsi in co-erogazione con finestre orarie per-corso.
- Date e sedi — appuntamenti fisici e sede.
- Programma — matrice appuntamento × corso
(
TrainingSessionProgramMatrix): dichiara quali corsi sono erogati in ogni slot e popola gli argomenti per cella (slot × corso). Logica inSessionPlannerPopup.razor.Step4Program.cs. - Docenti — assegnazione con "Suggerisci docenti per skill"
(filtro su
teacherSkillsdel corso). Logica inSessionPlannerPopup.razor.Step4Teachers.cs. - Iscritti — aggiunta workers con scelta del corso di destinazione; integrazione con coda richieste e scadenziario.
- Riepilogo costi — stima Iscrizioni + Docenze + Aule prima del confirm finale.
Punti d'ingresso: lista corsi, lista sessioni, coda richieste, scadenziario, scheda lavoratore, calendario (pulsante "Nuova Sessione").
Vista dati aggregati
AppointmentsData.razor fornisce una vista di dati aggregati per
analisi (totale ore per docente, saturazione aule, ecc.), distinta
dal CRUD. Non è un CRUD: è una pagina di reportistica.
Cascade variante normativa in Course
Il form CourseForm.razor ha un combobox Variante normativa che,
al cambio, pre-popola campi come durata minima e obblighi (logica nel
.razor.cs). Pattern simile al cascade ATECO → riskLevel del form
aziende.
Location con indirizzo inline e FK a reg.companies
Il form LocationForm.razor espone i campi indirizzo direttamente
sull'aula (formattedAddress + geocoded country/province/city/zipCode/address/streetNumber/latitude/longitude)
e un combobox opzionale companyId per il gestore aula (azienda
proprietaria, NULL = aula 3SD). Cross-dominio: edu consuma reg per le
aziende gestrici.
Suggerimento docenti per skill
Il filtro per competenza non vive più sul form
AppointmentForm.razor (l'appuntamento non ha più una lezione
associata): lo step "Docenti" del wizard
SessionPlannerPopup.Step4Teachers usa il pulsante
"Suggerisci docenti per skill" che incrocia
edu.teacherSkills.trainingVariantId con le varianti dei corsi
erogati nella sessione (trainingSessionsCourses → courses → trainingVariantId).
📁 File chiave
Components/CRUD/edu/Course.razor.cs— code-behind principaleComponents/CRUD/edu/Forms/CourseForm.razor— form con cascade varianteComponents/Pages/AppointmentsCalendar/— vista calendario page-level (AppointmentsCalendar.razor,CalendarGrid.razor,AppointmentDetailPanel.razor)Components/edu/SessionPlanner/— wizard 7-step pianificazione sessione (SessionPlannerPopup.razor+ Step1..Step6 + Step4Program partial;TrainingSessionProgramMatrix.razorper lo step Programma)Components/CRUD/edu/AppointmentsData.razor— vista dati aggregatiComponents/CRUD/edu/_conf/*.dxgrid.conf.json— configurazione
🔌 Estensione tipica
Segue il pattern generale (vedi
componenti UI inv). Specificità edu:
- Aggiungere un campo a
Course. Rigenera + valuta se il cascade variante va aggiornato per precompilare anche il nuovo campo. - Nuova vista analitica cross-dominio. Aggiungi una nuova pagina
Razor non-CRUD in
CRUD/edu/(es.MyAnalytics.razor), inject i service necessari. Non serveconf.json. Routing dichiarato con@pagedirettiva. - Estendere vista calendario. I file in
Pages/AppointmentsCalendar/sono scritti a mano — non CRUD generato. Modifiche dirette senza rigenerazione. Per aggiungere un filtro nuovo: aggiungi il combobox inAppointmentsCalendar.razor, il backing field nel code-behind, e passa il valore aIAppointmentsCalendarService.GetAppointmentsAsync.
⚠️ Debito tecnico
-
AppointmentsCalendarsenza test UI. Componente complesso custom, non coperto da test automatici. -
Filtro docenti per competenza. Coperto dallo step 4 delSessionPlannerPopup("Suggerisci docenti per skill") che usa la skill matrixedu.teacherSkills.
🔗 Vedi anche
- Panoramica dominio
- Schema DB
- Logica applicativa
- Dominio
inv: componenti UI — pattern CRUD base