194 lines
7.4 KiB
Plaintext
194 lines
7.4 KiB
Plaintext
@page "/students/event-ranking-edit/{StudentId:int}"
|
|
@attribute [Authorize]
|
|
@using Microsoft.EntityFrameworkCore
|
|
@using BlazorSortableList
|
|
@using WebApp.Models
|
|
@inject AppDbContext Context
|
|
@inject NavigationManager NavigationManager
|
|
@inject ISnackbar Snackbar
|
|
@inject ILogger<EventRankingEdit> Logger
|
|
|
|
<PageTitle>Student Event Ranks - TSA Chapter Organizer</PageTitle>
|
|
|
|
<MudText Typo="Typo.h3"><MudIcon Icon="@AppIcons.EventRank"></MudIcon> Student Event Ranks</MudText>
|
|
|
|
<div>
|
|
@if (_student == null)
|
|
{
|
|
<p><em>Loading...</em></p>
|
|
}
|
|
else
|
|
{
|
|
<MudText Typo="Typo.h4" Class="mb-2">@_student.Name</MudText>
|
|
|
|
<div class="mb-4">
|
|
<MudButton StartIcon="@Icons.Material.Filled.ArrowBack" Href="students/event-ranking" Variant="Variant.Outlined" Class="mr-2">Back</MudButton>
|
|
<MudButton StartIcon="@Icons.Material.Filled.Save" OnClick="Save" Color="Color.Primary" Variant="Variant.Filled">Save Rankings</MudButton>
|
|
</div>
|
|
|
|
@* https://github.com/AlexNek/BlazorSortableList *@
|
|
<MudGrid Class="mt-2">
|
|
<MudItem xs="12" md="6" xl="4">
|
|
<MudPaper Class="pa-3 mb-3" Elevation="0">
|
|
<div class="d-flex align-center mb-1">
|
|
<MudIcon Icon="@Icons.Material.Filled.FormatListNumbered" Class="mr-2" Color="Color.Primary" />
|
|
<MudText Typo="Typo.h6" Color="Color.Primary">Ranked Events</MudText>
|
|
</div>
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary">Drag events here in order of preference</MudText>
|
|
</MudPaper>
|
|
<SortableList
|
|
Group="GroupId" Id="ListId1" Context="item"
|
|
Items="_rankedEvents" OnRemove="RankedEventsRemove" OnUpdate="Update">
|
|
<SortableItemTemplate>
|
|
<MudCard Outlined="true" Class="mb-2">
|
|
<MudCardContent Class="pa-2">
|
|
<div class="d-flex align-center">
|
|
<MudBadge Content="@(_rankedEvents.IndexOf(item) + 1)" Color="Color.Primary" Overlap="true" Class="mr-3">
|
|
<MudIcon Icon="@Icons.Material.Filled.DragIndicator" />
|
|
</MudBadge>
|
|
<div class="flex-grow-1">
|
|
<MudText Typo="Typo.body2"><strong>@item.Name</strong></MudText>
|
|
<MudText Typo="Typo.caption">
|
|
@AppIcons.EventAttributes(item) @AppIcons.EventEffort(item)
|
|
</MudText>
|
|
</div>
|
|
</div>
|
|
</MudCardContent>
|
|
</MudCard>
|
|
</SortableItemTemplate>
|
|
</SortableList>
|
|
</MudItem>
|
|
<MudItem xs="12" md="6" xl="4">
|
|
<MudPaper Class="pa-3 mb-3" Elevation="0">
|
|
<div class="d-flex align-center mb-1">
|
|
<MudIcon Icon="@AppIcons.Events" Class="mr-2" />
|
|
<MudText Typo="Typo.h6">Available Events</MudText>
|
|
</div>
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary">Drag events to rank them</MudText>
|
|
</MudPaper>
|
|
<SortableList
|
|
Group="GroupId" Id="ListId2" Context="item"
|
|
Items="_availableEvents" OnRemove="AvailableEventsRemove" Sort="false">
|
|
<SortableItemTemplate>
|
|
<MudCard Outlined="true" Class="mb-2">
|
|
<MudCardContent Class="pa-2">
|
|
<MudText Typo="Typo.body2"><strong>@item.Name</strong></MudText>
|
|
<MudText Typo="Typo.caption">
|
|
@AppIcons.EventAttributes(item) @AppIcons.EventEffort(item)
|
|
</MudText>
|
|
</MudCardContent>
|
|
</MudCard>
|
|
</SortableItemTemplate>
|
|
</SortableList>
|
|
</MudItem>
|
|
</MudGrid>
|
|
}
|
|
</div>
|
|
|
|
@code {
|
|
|
|
private const string ListId1 = "SharedListId1";
|
|
private const string ListId2 = "SharedListId2";
|
|
private const string GroupId = "CommonGroup";
|
|
|
|
[Parameter] public int? StudentId { get; set; }
|
|
|
|
private Student? _student;
|
|
private List<EventDefinition>? _events;
|
|
|
|
public List<EventDefinition> _rankedEvents = [];
|
|
public List<EventDefinition> _availableEvents = [];
|
|
|
|
private void RankedEventsRemove((int oldIndex, int newIndex) indices)
|
|
{
|
|
// get the item at the old index in list 1
|
|
var item = _rankedEvents[indices.oldIndex];
|
|
|
|
// add it to the new index in list 2
|
|
_availableEvents.Insert(indices.newIndex, item);
|
|
|
|
// remove the item from the old index in list 1
|
|
_rankedEvents.Remove(_rankedEvents[indices.oldIndex]);
|
|
}
|
|
|
|
private void AvailableEventsRemove((int oldIndex, int newIndex) indices)
|
|
{
|
|
// get the item at the old index in list 2
|
|
var item = _availableEvents[indices.oldIndex];
|
|
|
|
// add it to the new index in list 1
|
|
_rankedEvents.Insert(indices.newIndex, item);
|
|
|
|
// remove the item from the old index in list 2
|
|
_availableEvents.Remove(_availableEvents[indices.oldIndex]);
|
|
}
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
_student =
|
|
await Context.Students
|
|
.Include(e => e.EventRankings)
|
|
.Where(e => e.Id == StudentId).FirstAsync();
|
|
_events =
|
|
await Context.Events
|
|
.OrderBy(e => e.Name)
|
|
.ToListAsync();
|
|
|
|
_rankedEvents = _student.EventRankings.OrderBy(e => e.Rank).Select(e => e.EventDefinition).ToList();
|
|
_availableEvents = _events.Where(e => !_rankedEvents.Contains(e)).ToList();
|
|
}
|
|
|
|
private void Update((int oldIndex, int newIndex) indices)
|
|
{
|
|
var (oldIndex, newIndex) = indices;
|
|
|
|
var items = _rankedEvents;
|
|
var itemToMove = items[oldIndex];
|
|
items.RemoveAt(oldIndex);
|
|
|
|
if (newIndex < items.Count)
|
|
{
|
|
items.Insert(newIndex, itemToMove);
|
|
}
|
|
else
|
|
{
|
|
items.Add(itemToMove);
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
|
|
|
|
async Task Save()
|
|
{
|
|
if (_student == null)
|
|
return;
|
|
|
|
try
|
|
{
|
|
_student.EventRankings.Clear();
|
|
for (var index = 0; index < _rankedEvents.Count; index++)
|
|
{
|
|
var evt = _rankedEvents[index];
|
|
_student.EventRankings.Add(new StudentEventRanking
|
|
{
|
|
EventDefinition = evt,
|
|
Student = _student,
|
|
Rank = index + 1
|
|
});
|
|
}
|
|
|
|
Context.Students.Update(_student);
|
|
await Context.SaveChangesAsync();
|
|
|
|
Snackbar.Add($"Event rankings saved for {_student.Name}", Severity.Success);
|
|
NavigationManager.NavigateTo("/students/event-ranking");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Snackbar.Add("Error saving rankings. Please try again.", Severity.Error);
|
|
Logger.LogError(e, "Error saving event rankings for student {StudentId}", StudentId);
|
|
}
|
|
}
|
|
}
|