83522ac52c
Updated the Teams Index and Printout components to prioritize sorting by EventFormat, enhancing the organization of team data. Introduced a regional filter toggle in the Teams Index to allow users to view only regional teams. Adjusted the ScheduledTeamsList to sort teams by EventFormat first, ensuring consistent ordering across components. Additionally, added necessary using directives for improved code clarity.
218 lines
8.3 KiB
Plaintext
218 lines
8.3 KiB
Plaintext
@using Microsoft.EntityFrameworkCore
|
|
@using WebApp.Components.Shared.Components
|
|
@using WebApp.Models
|
|
@page "/teams"
|
|
@attribute [Authorize]
|
|
@inject AppDbContext Context
|
|
@inject IDialogService DialogService
|
|
@inject ISnackbar Snackbar
|
|
|
|
<PageHeader Title="Teams">
|
|
<ActionButtons>
|
|
<MudButton StartIcon="@Icons.Material.Filled.Create" Href="teams/create" Variant="Variant.Filled" Color="Color.Primary">Create New</MudButton>
|
|
<MudButton StartIcon="@Icons.Material.Filled.Print" Href="teams/printout" Variant="Variant.Outlined">Printout</MudButton>
|
|
<MudButton StartIcon="@Icons.Material.Filled.Print" Href="teams/handout" Variant="Variant.Outlined">Handout</MudButton>
|
|
<MudButton StartIcon="@Icons.Material.Filled.FilterAlt"
|
|
Variant="@(_showRegionalOnly ? Variant.Filled : Variant.Outlined)"
|
|
Color="Color.Primary"
|
|
OnClick="ToggleRegionalFilter">
|
|
@(_showRegionalOnly ? "Showing Regional Only" : "Show Regional Only")
|
|
</MudButton>
|
|
</ActionButtons>
|
|
</PageHeader>
|
|
|
|
<MudPaper Elevation="2" Class="pa-6">
|
|
<MudDataGrid T="Team"
|
|
ServerData="ServerReload"
|
|
@ref="_dataGrid"
|
|
Filterable="true"
|
|
RowsPerPage="50"
|
|
Dense="true"
|
|
Striped="true"
|
|
Hover="true"
|
|
Loading="@_isLoading"
|
|
LoadingProgressColor="Color.Primary">
|
|
<Columns>
|
|
<TemplateColumn Title="Event" Sortable="true" SortBy="@(t => t.Event.Name)">
|
|
<CellTemplate>
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1">
|
|
<MudLink Href="@($"/teams/details?id={context.Item.Id}")"
|
|
Underline="Underline.Hover"
|
|
Color="Color.Primary">
|
|
@context.Item.ToString()
|
|
</MudLink>
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
|
<IconButtonWithTooltip Icon="@Icons.Material.Filled.Edit"
|
|
TooltipText="Edit"
|
|
Href="@($"/teams/edit?id={context.Item.Id}")" />
|
|
<IconButtonWithTooltip Icon="@Icons.Material.Outlined.Delete"
|
|
TooltipText="Delete"
|
|
HoverColor="Color.Error"
|
|
OnClick="() => DeleteTeam(context.Item!)" />
|
|
</MudStack>
|
|
</MudStack>
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
<TemplateColumn Title="Attributes">
|
|
<CellTemplate>
|
|
<EventAttributes EventDefinition="@context.Item.Event"></EventAttributes>
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
<TemplateColumn Title="Students">
|
|
<CellTemplate>
|
|
<TeamStudents Team="@context.Item"></TeamStudents>
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
</Columns>
|
|
<PagerContent>
|
|
<MudDataGridPager T="Team"></MudDataGridPager>
|
|
</PagerContent>
|
|
</MudDataGrid>
|
|
</MudPaper>
|
|
|
|
@code {
|
|
MudDataGrid<Team> _dataGrid = null!;
|
|
private bool _isLoading = true;
|
|
private bool _showRegionalOnly = false;
|
|
|
|
private async Task ToggleRegionalFilter()
|
|
{
|
|
try
|
|
{
|
|
_showRegionalOnly = !_showRegionalOnly;
|
|
if (_dataGrid != null)
|
|
{
|
|
await _dataGrid.ReloadServerData();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error applying filter: {ex.Message}", Severity.Error);
|
|
}
|
|
}
|
|
|
|
private async Task<GridData<Team>> ServerReload(GridState<Team> state)
|
|
{
|
|
_isLoading = true;
|
|
try
|
|
{
|
|
IQueryable<Team> query
|
|
= Context.Teams
|
|
.Include(e => e.Event)
|
|
.Include(e => e.Students)
|
|
.ThenInclude(e => e.EventRankings);
|
|
|
|
// Apply regional filter if enabled
|
|
// Note: RegionalEvent is a computed property, so we must use the underlying property
|
|
if (_showRegionalOnly)
|
|
{
|
|
query = query.Where(t => t.Event.ChapterEligibilityCountRegionals > 0);
|
|
}
|
|
|
|
// Apply grid filter definitions
|
|
query = query.Where(state.FilterDefinitions);
|
|
|
|
// Load all data first
|
|
var allTeams = await query.ToArrayAsync();
|
|
|
|
// Always sort by EventFormat FIRST to separate group/individual teams
|
|
// Sort in memory to ensure this ordering is maintained regardless of user sorts
|
|
var sortedTeams = allTeams.OrderByEventFormatFirst();
|
|
|
|
// Apply user sort definitions as secondary sorts (within each group)
|
|
bool appliedUserSort = false;
|
|
if (state.SortDefinitions != null && state.SortDefinitions.Any())
|
|
{
|
|
var sortDef = state.SortDefinitions.First();
|
|
var sortBy = sortDef.SortBy ?? "";
|
|
|
|
// Handle Event.Name sorting
|
|
if (sortBy == "Event.Name" || (sortBy.Contains("Event") && sortBy.Contains("Name")))
|
|
{
|
|
sortedTeams = sortDef.Descending
|
|
? sortedTeams.ThenByDescending(t => t.Event.Name)
|
|
: sortedTeams.ThenBy(t => t.Event.Name);
|
|
appliedUserSort = true;
|
|
}
|
|
// Handle Identifier sorting
|
|
else if (sortBy == "Identifier")
|
|
{
|
|
sortedTeams = sortDef.Descending
|
|
? sortedTeams.ThenByDescending(t => t.Identifier ?? "")
|
|
: sortedTeams.ThenBy(t => t.Identifier ?? "");
|
|
appliedUserSort = true;
|
|
}
|
|
}
|
|
|
|
// Apply default secondary sorting
|
|
if (!appliedUserSort)
|
|
{
|
|
sortedTeams = sortedTeams
|
|
.ThenBy(t => t.Event.Name)
|
|
.ThenBy(t => t.Identifier ?? "");
|
|
}
|
|
else
|
|
{
|
|
// Add default sorting as tie-breakers
|
|
if (state.SortDefinitions?.First().SortBy != "Event.Name")
|
|
{
|
|
sortedTeams = sortedTeams.ThenBy(t => t.Event.Name);
|
|
}
|
|
if (state.SortDefinitions?.First().SortBy != "Identifier")
|
|
{
|
|
sortedTeams = sortedTeams.ThenBy(t => t.Identifier ?? "");
|
|
}
|
|
}
|
|
|
|
var totalItems = sortedTeams.Count();
|
|
var pagedData = sortedTeams.Skip(state.Page * state.PageSize).Take(state.PageSize).ToArray();
|
|
|
|
return new GridData<Team>
|
|
{
|
|
TotalItems = totalItems,
|
|
Items = pagedData
|
|
};
|
|
}
|
|
finally
|
|
{
|
|
_isLoading = false;
|
|
}
|
|
}
|
|
|
|
private async Task DeleteTeam(Team team)
|
|
{
|
|
//_isRowBlocked = true;
|
|
|
|
var result = await DialogService
|
|
.ShowMessageBox("Delete team",
|
|
(MarkupString)$"Are you sure want to delete <b>{team}</b>? This cannot be undone.",
|
|
yesText: "Yes",
|
|
noText: "Cancel");
|
|
|
|
if (result == true)
|
|
{
|
|
// If deleting a numbered team (1 or 2), clear the identifier of the remaining team
|
|
if (team.Identifier == "1" || team.Identifier == "2")
|
|
{
|
|
var remainingTeam = await Context.Teams
|
|
.Include(t => t.Event)
|
|
.FirstOrDefaultAsync(t => t.Event.Id == team.Event.Id && t.Id != team.Id);
|
|
|
|
if (remainingTeam != null)
|
|
{
|
|
remainingTeam.Identifier = null;
|
|
Context.Teams.Update(remainingTeam);
|
|
}
|
|
}
|
|
|
|
Context.Teams.Remove(team!);
|
|
await Context.SaveChangesAsync();
|
|
Snackbar.Add($"Delete event: Delete of Team {team}", Severity.Info);
|
|
}
|
|
|
|
//_isRowBlocked = false;
|
|
StateHasChanged();
|
|
await _dataGrid.ReloadServerData();
|
|
}
|
|
}
|