87db67f979
Updated the MudPaper component styling in multiple files to use a consistent padding class of "pa-3 pa-md-6" instead of "pa-6". This change enhances the visual consistency of the UI across the Calendar, Events, Students, and Teams components, improving the overall user experience.
161 lines
6.4 KiB
Plaintext
161 lines
6.4 KiB
Plaintext
@page "/students/event-ranking"
|
|
@attribute [Authorize]
|
|
@using Microsoft.EntityFrameworkCore
|
|
@using WebApp.Models
|
|
@using Core.Validation
|
|
@inject AppDbContext Context
|
|
@inject ValidationService ValidationService
|
|
@rendermode InteractiveServer
|
|
|
|
<PageHeader
|
|
Title="Student Event Ranks"
|
|
Icon="@AppIcons.EventRank" />
|
|
|
|
@if (_students == null)
|
|
{
|
|
<p><em>Loading...</em></p>
|
|
}
|
|
else
|
|
{
|
|
<MudStack Spacing="4">
|
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
|
<MudText Typo="Typo.h5" Class="mb-4">Students by Rank</MudText>
|
|
<MudTable Items="_students" Hover="true" Striped="true" Breakpoint="Breakpoint.Sm" LoadingProgressColor="Color.Info">
|
|
<HeaderContent>
|
|
|
|
<MudTh>Name</MudTh>
|
|
<MudTh>Grade</MudTh>
|
|
<MudTh>TSA Year</MudTh>
|
|
<MudTh></MudTh>
|
|
<MudTh>Warnings</MudTh>
|
|
@for (var i = 1; i <= 10; i++)
|
|
{
|
|
var ii = i;
|
|
<MudTh>@AppIcons.GetOrdinal(ii)</MudTh>
|
|
}
|
|
</HeaderContent>
|
|
<RowTemplate>
|
|
|
|
<MudTd>@context.FirstName</MudTd>
|
|
<MudTh>@context.Grade</MudTh>
|
|
<MudTh>@context.TsaYear</MudTh>
|
|
<MudTd><MudButton StartIcon="@Icons.Material.Filled.TableChart" Href="@($"students/event-ranking-edit/{context.Id}")">Edit</MudButton></MudTd>
|
|
<MudTd>
|
|
<ValidationWarnings Warnings="@GetStudentWarnings(context)" />
|
|
</MudTd>
|
|
@for (var i = 1; i <= 10; i++)
|
|
{
|
|
var ii = i;
|
|
var st = context.EventRankings.FirstOrDefault(e => e.Rank == i);
|
|
<MudTd Class="@($"event-rank-{ii})")">
|
|
@if (st != null)
|
|
{
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
|
<span style="@($"display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: {AppIcons.RankedEventColor(ii)}; flex-shrink: 0;")")></span>
|
|
<span>@st.EventDefinition.ShortName
|
|
<EventAttributes EventDefinition="@st.EventDefinition"></EventAttributes>
|
|
</span>
|
|
</MudStack>
|
|
}
|
|
</MudTd>
|
|
}
|
|
|
|
</RowTemplate>
|
|
</MudTable>
|
|
</MudPaper>
|
|
|
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
|
<MudText Typo="Typo.h5" Class="mb-4">Events by Student</MudText>
|
|
<MudTable Items="_eventStudentRankings" Hover="true" Striped="true" Breakpoint="Breakpoint.Sm" LoadingProgressColor="Color.Info">
|
|
<HeaderContent>
|
|
<MudTh>Event</MudTh>
|
|
<MudTh>Level of Effort</MudTh>
|
|
<MudTh>Individual</MudTh>
|
|
<MudTh>Regional</MudTh>
|
|
<MudTh>On-site Activity</MudTh>
|
|
<MudTh>Team Size</MudTh>
|
|
@for (var i = 0; i < _maxEventStudentRankings; i++)
|
|
{
|
|
var i1 = i + 1;
|
|
<MudTh>@i1</MudTh>
|
|
}
|
|
</HeaderContent>
|
|
<RowTemplate>
|
|
<MudTd>@context.Event.Name</MudTd>
|
|
<MudTd>@context.Event.LevelOfEffort</MudTd>
|
|
<MudTd>@if (context.Event.EventFormat == EventFormat.Individual) { <span>ⓘ</span> }</MudTd >
|
|
<MudTd>@if (context.Event.RegionalEvent) { <span>ⓡ</span> }</MudTd >
|
|
<MudTd>@if (context.Event.OnSiteActivity) { <span>ⓐ</span> }</MudTd >
|
|
<MudTd>[@context.Event.MinTeamSize-@context.Event.MaxTeamSize]</MudTd >
|
|
@for (var j = 0; j < _maxEventStudentRankings; j++)
|
|
{
|
|
var student = j < context.StudentRanking.Length ? context.StudentRanking[j] : null;
|
|
var eventClass = student != null ? $"event-rank-{student.Item2}" : "";
|
|
<MudTd Class="@eventClass">
|
|
@if (student != null)
|
|
{
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
|
<span style="@($"display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: {AppIcons.RankedEventColor(student.Item2)}; flex-shrink: 0;")")></span>
|
|
@student.Item1.FirstName
|
|
</MudStack>
|
|
}
|
|
</MudTd>
|
|
}
|
|
</RowTemplate>
|
|
</MudTable>
|
|
</MudPaper>
|
|
</MudStack>
|
|
}
|
|
@code {
|
|
private Student[]? _students;
|
|
|
|
private class EventStudentRankings {
|
|
public required EventDefinition Event {get; set; }
|
|
public required Tuple<Student,int>[] StudentRanking { get; set; }
|
|
}
|
|
|
|
private EventStudentRankings[] _eventStudentRankings = null!;
|
|
private int _maxEventStudentRankings;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
_students =
|
|
await Context.Students
|
|
.Include(e => e.EventRankings)
|
|
.ThenInclude(e => e.EventDefinition)
|
|
.OrderBy(e => e.FirstName).ToArrayAsync();
|
|
|
|
_eventStudentRankings =
|
|
_students.SelectMany(s =>
|
|
s.EventRankings,
|
|
(student, ranking) => new { e = ranking.EventDefinition, a = Tuple.Create(student, ranking.Rank) }
|
|
)
|
|
.GroupBy(e => e.e)
|
|
.Select(e =>
|
|
new EventStudentRankings
|
|
{
|
|
Event = e.Key,
|
|
StudentRanking = e.Select(er => er.a).OrderBy(ser => ser.Item2).ThenByDescending(ser => ser.Item1.Grade + ser.Item1.TsaYear).ToArray()
|
|
})
|
|
.OrderBy(e => e.Event.Name)
|
|
.ToArray();
|
|
|
|
var events = await Context.Events.ToArrayAsync();
|
|
var remainingEvents =
|
|
events
|
|
.Where(e => _eventStudentRankings.All(est => est.Event.Id != e.Id))
|
|
.Select(e => new EventStudentRankings { Event = e, StudentRanking = Array.Empty<Tuple<Student, int>>() })
|
|
.OrderBy(e => e.Event.Name)
|
|
.ToArray();
|
|
|
|
_eventStudentRankings = _eventStudentRankings.Concat(remainingEvents).ToArray();
|
|
|
|
_maxEventStudentRankings = _eventStudentRankings.Max(esr => esr.StudentRanking.Length);
|
|
}
|
|
|
|
private List<ValidationWarning> GetStudentWarnings(Student student)
|
|
{
|
|
return ValidationService.ValidateStudentRankings(student, ValidationContext.StudentRanking);
|
|
}
|
|
}
|