From d19326781a0b8c1ac1969cbfd53d9064428071ba Mon Sep 17 00:00:00 2001 From: James Kolpack Date: Sat, 27 Dec 2025 10:39:16 -0500 Subject: [PATCH] Add loading states to MudDataGrid components Implemented loading indicators and progress colors for all MudDataGrid instances across Events, Students, Teams, and Registration components to enhance user experience during data loading operations. --- WebApp/Components/Features/Events/Index.razor | 32 ++++++--- .../Components/Features/Students/Index.razor | 36 ++++++---- .../Features/Students/Registration.razor | 67 +++++++++++-------- WebApp/Components/Features/Teams/Index.razor | 47 ++++++++----- docs/plans/style-improvements.md | 4 +- 5 files changed, 113 insertions(+), 73 deletions(-) diff --git a/WebApp/Components/Features/Events/Index.razor b/WebApp/Components/Features/Events/Index.razor index c651e3f..3d5df60 100644 --- a/WebApp/Components/Features/Events/Index.razor +++ b/WebApp/Components/Features/Events/Index.razor @@ -22,7 +22,9 @@ RowsPerPage="50" Dense="true" Striped="true" - Hover="true"> + Hover="true" + Loading="@_isLoading" + LoadingProgressColor="Color.Primary"> @@ -71,20 +73,28 @@ @code { MudDataGrid _dataGrid = null!; + private bool _isLoading = true; private async Task> ServerReload(GridState state) { - - var query = Context.Events.OrderBy(e => e.Name).Where(state.FilterDefinitions).OrderBy(state.SortDefinitions); - - var totalItems = await query.CountAsync(); - var pagedData = await query.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArrayAsync(); - - return new GridData + _isLoading = true; + try { - TotalItems = totalItems, - Items = pagedData - }; + var query = Context.Events.OrderBy(e => e.Name).Where(state.FilterDefinitions).OrderBy(state.SortDefinitions); + + var totalItems = await query.CountAsync(); + var pagedData = await query.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArrayAsync(); + + return new GridData + { + TotalItems = totalItems, + Items = pagedData + }; + } + finally + { + _isLoading = false; + } } private async Task DeleteEventDefinition(EventDefinition evt) diff --git a/WebApp/Components/Features/Students/Index.razor b/WebApp/Components/Features/Students/Index.razor index b0ef2a8..9ccce83 100644 --- a/WebApp/Components/Features/Students/Index.razor +++ b/WebApp/Components/Features/Students/Index.razor @@ -23,7 +23,9 @@ RowsPerPage="25" Dense="true" Striped="true" - Hover="true"> + Hover="true" + Loading="@_isLoading" + LoadingProgressColor="Color.Primary"> @@ -65,22 +67,30 @@ @code { MudDataGrid _dataGrid = null!; + private bool _isLoading = true; private async Task> ServerReload(GridState state) { - - var query = - Context.Students.OrderBy(e => e.LastName) - .Where(state.FilterDefinitions).OrderBy(state.SortDefinitions); - - var totalItems = await query.CountAsync(); - var pagedData = await query.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArrayAsync(); - - return new GridData + _isLoading = true; + try { - TotalItems = totalItems, - Items = pagedData - }; + var query = + Context.Students.OrderBy(e => e.LastName) + .Where(state.FilterDefinitions).OrderBy(state.SortDefinitions); + + var totalItems = await query.CountAsync(); + var pagedData = await query.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArrayAsync(); + + return new GridData + { + TotalItems = totalItems, + Items = pagedData + }; + } + finally + { + _isLoading = false; + } } private async Task DeleteStudent(Student student) diff --git a/WebApp/Components/Features/Students/Registration.razor b/WebApp/Components/Features/Students/Registration.razor index a974742..ccd2945 100644 --- a/WebApp/Components/Features/Students/Registration.razor +++ b/WebApp/Components/Features/Students/Registration.razor @@ -34,7 +34,7 @@ - + @@ -109,6 +109,7 @@ @code { MudDataGrid _dataGrid = null!; + private bool _isLoading = true; private bool _showRegionalOnly; private bool _showGrade; private bool _showRegionalId; @@ -167,35 +168,43 @@ private async Task> ServerReload(GridState state) { - // Load all students with their teams - var students = await Context.Students - .Include(s => s.Teams) - .ThenInclude(t => t.Event) - .Include(s => s.Teams) - .ThenInclude(t => t.Captain) - .ToListAsync(); - - // Filter to only students with teams - var studentTeams = students - .Where(s => s.Teams.Any(t => t?.Event != null && (!_showRegionalOnly || t.Event.RegionalEvent))) - .Select(s => new StudentTeamInfo - { - Student = s, - Teams = s.Teams?.Where(t => t?.Event != null).ToList() ?? [] - }) - .ToList(); - - // Apply sorting - var sortedData = ApplySorting(studentTeams, state.SortDefinitions); - - var totalItems = sortedData.Count(); - var pagedData = sortedData.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArray(); - - return new GridData + _isLoading = true; + try { - TotalItems = totalItems, - Items = pagedData - }; + // Load all students with their teams + var students = await Context.Students + .Include(s => s.Teams) + .ThenInclude(t => t.Event) + .Include(s => s.Teams) + .ThenInclude(t => t.Captain) + .ToListAsync(); + + // Filter to only students with teams + var studentTeams = students + .Where(s => s.Teams.Any(t => t?.Event != null && (!_showRegionalOnly || t.Event.RegionalEvent))) + .Select(s => new StudentTeamInfo + { + Student = s, + Teams = s.Teams?.Where(t => t?.Event != null).ToList() ?? [] + }) + .ToList(); + + // Apply sorting + var sortedData = ApplySorting(studentTeams, state.SortDefinitions); + + var totalItems = sortedData.Count(); + var pagedData = sortedData.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArray(); + + return new GridData + { + TotalItems = totalItems, + Items = pagedData + }; + } + finally + { + _isLoading = false; + } } /// diff --git a/WebApp/Components/Features/Teams/Index.razor b/WebApp/Components/Features/Teams/Index.razor index 7758d74..57deeb3 100644 --- a/WebApp/Components/Features/Teams/Index.razor +++ b/WebApp/Components/Features/Teams/Index.razor @@ -22,7 +22,9 @@ RowsPerPage="35" Dense="true" Striped="true" - Hover="true"> + Hover="true" + Loading="@_isLoading" + LoadingProgressColor="Color.Primary"> @@ -63,27 +65,36 @@ @code { MudDataGrid _dataGrid = null!; + private bool _isLoading = true; private async Task> ServerReload(GridState state) { - var query - = Context.Teams - .Include(e => e.Event) - .Include(e => e.Students) - .ThenInclude(e => e.EventRankings) - .OrderBy(e => e.Event.Name) - .ThenBy(e => e.Identifier) - .Where(state.FilterDefinitions) - .OrderBy(state.SortDefinitions); - - var totalItems = await query.CountAsync(); - var pagedData = await query.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArrayAsync(); - - return new GridData + _isLoading = true; + try { - TotalItems = totalItems, - Items = pagedData - }; + var query + = Context.Teams + .Include(e => e.Event) + .Include(e => e.Students) + .ThenInclude(e => e.EventRankings) + .OrderBy(e => e.Event.Name) + .ThenBy(e => e.Identifier) + .Where(state.FilterDefinitions) + .OrderBy(state.SortDefinitions); + + var totalItems = await query.CountAsync(); + var pagedData = await query.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArrayAsync(); + + return new GridData + { + TotalItems = totalItems, + Items = pagedData + }; + } + finally + { + _isLoading = false; + } } private async Task DeleteTeam(Team team) diff --git a/docs/plans/style-improvements.md b/docs/plans/style-improvements.md index 4610fcf..4fac40a 100644 --- a/docs/plans/style-improvements.md +++ b/docs/plans/style-improvements.md @@ -127,7 +127,7 @@ This document outlines recommended style improvements to enhance the visual desi --- -### 5. Add Loading States +### 5. Add Loading States ✅ COMPLETED **Locations**: All MudDataGrid and async components **Issue**: No visual feedback during data loading operations. @@ -331,7 +331,7 @@ Consider using MudChip components with rank colors for better visual distinction ### Phase 2: Visual Polish (Medium Impact, Medium Effort) 4. ✅ Refine typography hierarchy usage -5. Add loading states to all grids +5. ✅ Add loading states to all grids 6. ✅ Wrap pages in consistent container styling ### Phase 3: Enhancements (Nice to Have)