Files
Wollmilchsau/Wollmilchsau/Components/Pages/Teachers/QuestionaireResults.razor
T
2026-08-23 18:48:39 +02:00

137 lines
6.6 KiB
Plaintext

@page "/teachers/questionaire-results"
@using Marten
@using Microsoft.AspNetCore.Authorization
@using Wollmilchsau.Models
@using Wollmilchsau.Services.Ldap
@attribute [Authorize(Roles = "ROLE_TEACHER,ROLE_ADMIN")]
@inject ILdapService LdapService
@inject IDocumentSession DocumentSession
<PageTitle>Questionnaire results</PageTitle>
<MudContainer MaxWidth="MaxWidth.Large" Class="mt-6 mb-6">
<MudText Typo="Typo.h3" GutterBottom="true">Questionnaire results</MudText>
<MudText Typo="Typo.body1" Class="mb-6">Eligible students and their submitted semester preferences.</MudText>
@if (isLoading)
{
<MudStack AlignItems="AlignItems.Center" Class="py-8">
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
<MudText>Loading questionnaire results...</MudText>
</MudStack>
}
else if (results.Count == 0)
{
<MudAlert Severity="Severity.Info">No eligible students were found.</MudAlert>
}
else
{
<MudAlert Severity="Severity.Info" Variant="Variant.Outlined" Class="mb-4">
@CompletedCount of @results.Count eligible students have submitted their choices.
</MudAlert>
<MudStack Spacing="4">
@foreach (var classroom in results.GroupBy(result => result.Classroom).OrderBy(group => group.Key, StringComparer.OrdinalIgnoreCase))
{
<MudPaper Outlined="true" Class="pa-4">
<MudText Typo="Typo.h5" GutterBottom="true">@classroom.Key</MudText>
<MudStack Spacing="3">
@foreach (var result in classroom)
{
<MudPaper Elevation="0" Outlined="true" Class="pa-3">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center" Class="mb-3">
<div>
<MudText Typo="Typo.h6">@result.DisplayName</MudText>
<MudText Typo="Typo.caption" Color="Color.Secondary">@result.Username</MudText>
</div>
<MudChip T="string" Color="@(result.Submission is null ? Color.Warning : Color.Success)" Variant="Variant.Filled" Size="Size.Small">
@(result.Submission is null ? "Not submitted" : "Submitted")
</MudChip>
</MudStack>
@if (result.Submission is null)
{
<MudText Color="Color.Secondary">This student has not made a choice yet.</MudText>
}
else
{
<MudText Typo="Typo.caption" Color="Color.Secondary" Class="mb-2">Last updated: @result.Submission.SubmittedAt.LocalDateTime.ToString("g")</MudText>
<MudGrid Spacing="2">
@for (var alternativeIndex = 0; alternativeIndex < result.Submission.Alternatives.Count; alternativeIndex++)
{
var currentAlternativeIndex = alternativeIndex;
var alternative = result.Submission.Alternatives[currentAlternativeIndex];
<MudItem xs="12" md="4">
<MudPaper Outlined="true" Class="pa-3 h-100">
<MudText Typo="Typo.subtitle2" GutterBottom="true">Alternative @(currentAlternativeIndex + 1)</MudText>
@for (var semesterIndex = 0; semesterIndex < alternative.Count; semesterIndex++)
{
<MudText Typo="Typo.body2">Semester @(semesterIndex + 1): @alternative[semesterIndex]</MudText>
}
</MudPaper>
</MudItem>
}
</MudGrid>
}
</MudPaper>
}
</MudStack>
</MudPaper>
}
</MudStack>
}
</MudContainer>
@code {
private IReadOnlyList<StudentQuestionnaireResult> results = [];
private bool isLoading = true;
private int CompletedCount => results.Count(result => result.Submission is not null);
protected override async Task OnInitializedAsync()
{
var submissions = await DocumentSession.Query<QuestionnaireSubmission>().ToListAsync();
var submissionsByStudent = submissions
.GroupBy(submission => submission.StudentId, StringComparer.OrdinalIgnoreCase)
.ToDictionary(
group => group.Key,
group => group.OrderByDescending(submission => submission.SubmittedAt).First(),
StringComparer.OrdinalIgnoreCase);
var students = new List<LdapUser>();
await foreach (var user in LdapService.GetAllUsers())
{
if (user.Role == LdapUserRole.Student &&
Wollmilchsau.Store.QuestionnaireStore.QuestionnaireSubmissionPolicy.IsClassroomAllowed(user.Classroom))
{
students.Add(user);
}
}
results = students
.OrderBy(student => student.Classroom, StringComparer.OrdinalIgnoreCase)
.ThenBy(student => student.Surname, StringComparer.OrdinalIgnoreCase)
.ThenBy(student => student.GivenName, StringComparer.OrdinalIgnoreCase)
.Select(student => new StudentQuestionnaireResult(
student.Username,
student.Classroom!,
GetDisplayName(student),
submissionsByStudent.GetValueOrDefault(student.Username)))
.ToList();
isLoading = false;
}
private static string GetDisplayName(LdapUser student)
{
var displayName = string.Join(" ", new[] { student.GivenName, student.Surname }.Where(value => !string.IsNullOrWhiteSpace(value)));
return string.IsNullOrWhiteSpace(displayName) ? student.Username : displayName;
}
private sealed record StudentQuestionnaireResult(
string Username,
string Classroom,
string DisplayName,
QuestionnaireSubmission? Submission);
}