Enhance MeetingSchedule component to support student exclusion management

This commit introduces functionality in the MeetingSchedule feature to manage student exclusions during scheduling. The Index.razor component has been updated to include methods for saving and loading excluded students, as well as UI elements for toggling exclusions. Additionally, the TeamScheduler logic has been modified to account for excluded students when calculating overlaps and scheduling teams. These changes improve the flexibility and accuracy of the scheduling process, enhancing the overall user experience.
This commit is contained in:
2026-01-13 11:54:06 -05:00
parent c505bf42dd
commit 52bf303537
4 changed files with 274 additions and 14 deletions
@@ -36,10 +36,14 @@
</MudTooltip>
</MudStack>
<MudStack Row="true" Spacing="1" Wrap="Wrap.Wrap" AlignItems="AlignItems.Center">
@{
var nonExcludedStudentCount = GetNonExcludedStudentCount(team);
}
@foreach (var student in team.Students)
{
var overlap = StudentHasOverlaps(student);
var chipColor = overlap ? Color.Warning : Color.Default;
var isExcluded = IsStudentExcluded(team.Id, TimeSlotIndex, student.Id);
var formattedName = TeamStudentNameFormatter.FormatStudentName(
student,
team,
@@ -51,9 +55,29 @@
AbsentStudents = AbsentStudents.ToList()
});
<MudChip T="string" Size="Size.Small" Color="@chipColor" Variant="Variant.Outlined">
@formattedName
</MudChip>
<MudStack Row="true" Spacing="0" AlignItems="AlignItems.Center"
Style="position: relative; display: inline-flex;"
@onmouseenter="@(() => _hoveredStudent = (team.Id, student.Id))"
@onmouseleave="@(() => _hoveredStudent = (null, null))">
<MudChip T="string"
Size="Size.Small"
Color="@chipColor"
Variant="Variant.Outlined"
Style="@(isExcluded ? "opacity: 0.5;" : "")">
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
<span>@formattedName</span>
@if (_hoveredStudent == (team.Id, student.Id) && nonExcludedStudentCount > 1)
{
<MudIconButton Icon="@Icons.Material.Filled.Close"
Size="Size.Small"
Color="Color.Error"
Variant="Variant.Text"
OnClick="@(() => OnToggleStudentExclusion.InvokeAsync((team.Id, TimeSlotIndex, student.Id)))"
Style="padding: 0; min-width: 16px; width: 16px; height: 16px; margin-left: 4px;" />
}
</MudStack>
</MudChip>
</MudStack>
}
</MudStack>
</MudStack>
@@ -64,6 +88,9 @@
[Parameter]
public string TimeSlotName { get; set; } = string.Empty;
[Parameter]
public int TimeSlotIndex { get; set; }
[Parameter]
public IEnumerable<Team> Teams { get; set; } = [];
@@ -76,6 +103,25 @@
[Parameter]
public Func<Student, bool> StudentHasOverlaps { get; set; } = null!;
[Parameter]
public Dictionary<(int teamId, int timeSlotIndex, int studentId), bool> ExcludedStudents { get; set; } = new();
[Parameter]
public EventCallback<Team> OnToggleTeam { get; set; }
[Parameter]
public EventCallback<(int teamId, int timeSlotIndex, int studentId)> OnToggleStudentExclusion { get; set; }
private (int? teamId, int? studentId) _hoveredStudent = (null, null);
private bool IsStudentExcluded(int teamId, int timeSlotIndex, int studentId)
{
var key = (teamId, timeSlotIndex, studentId);
return ExcludedStudents.ContainsKey(key) && ExcludedStudents[key];
}
private int GetNonExcludedStudentCount(Team team)
{
return team.Students.Count(s => !IsStudentExcluded(team.Id, TimeSlotIndex, s.Id));
}
}