Refactor ScheduledTeamsList component to enhance student exclusion UI

This commit updates the ScheduledTeamsList.razor component by replacing the existing MudChip implementation with InteractiveChip for better user interaction when managing student exclusions. The logic for displaying excluded students has been simplified, improving the overall readability and maintainability of the code. Additionally, the hover functionality has been removed to streamline the user experience. These changes contribute to a more intuitive and responsive scheduling interface.
This commit is contained in:
2026-01-14 09:50:16 -05:00
parent 27f08b3718
commit 68311f4012
3 changed files with 121 additions and 64 deletions
@@ -55,29 +55,35 @@
AbsentStudents = AbsentStudents.ToList() AbsentStudents = AbsentStudents.ToList()
}); });
<MudStack Row="true" Spacing="0" AlignItems="AlignItems.Center" @if (nonExcludedStudentCount > 1)
Style="position: relative; display: inline-flex;" {
@onmouseenter="@(() => _hoveredStudent = (team.Id, student.Id))" <InteractiveChip Size="Size.Small"
@onmouseleave="@(() => _hoveredStudent = (null, null))"> Color="@chipColor"
Variant="Variant.Outlined"
Style="@(isExcluded ? "opacity: 0.5;" : "")">
<ChildContent>
<span>@formattedName</span>
</ChildContent>
<ControlContent>
<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;" />
</ControlContent>
</InteractiveChip>
}
else
{
<MudChip T="string" <MudChip T="string"
Size="Size.Small" Size="Size.Small"
Color="@chipColor" Color="@chipColor"
Variant="Variant.Outlined" Variant="Variant.Outlined"
Style="@(isExcluded ? "opacity: 0.5;" : "")"> Style="@(isExcluded ? "opacity: 0.5;" : "")">
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center"> <span>@formattedName</span>
<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> </MudChip>
</MudStack> }
} }
</MudStack> </MudStack>
</MudStack> </MudStack>
@@ -112,8 +118,6 @@
[Parameter] [Parameter]
public EventCallback<(int teamId, int timeSlotIndex, int studentId)> OnToggleStudentExclusion { get; set; } 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) private bool IsStudentExcluded(int teamId, int timeSlotIndex, int studentId)
{ {
var key = (teamId, timeSlotIndex, studentId); var key = (teamId, timeSlotIndex, studentId);
@@ -163,7 +163,7 @@
var isAssigned = context.Events.Contains(e); var isAssigned = context.Events.Contains(e);
var color = AppIcons.RankedEventColor(eventRank ?? 0); var color = AppIcons.RankedEventColor(eventRank ?? 0);
var style = string.Empty; var style = "border-style: solid;";
if (isAssigned) if (isAssigned)
{ {
@@ -183,51 +183,54 @@
style += $"border-color:{color}; border-width:medium; color:{Colors.Gray.Lighten1};"; style += $"border-color:{color}; border-width:medium; color:{Colors.Gray.Lighten1};";
} }
<MudPaper Class="d-inline-flex align-center pa-2 mx-3 my-1 border-solid" Style="@(style)"> var isIncluded = _assignmentRequirements
@e.ShortName&nbsp; .Find(ar =>
@AppIcons.EventAttributes(e) ar.EventDefinition == e
@{ && ar.Student == context.Student
var isIncluded = _assignmentRequirements && ar.Requirement == Requirement.Include) == null;
.Find(ar => var isExcluded = _assignmentRequirements
ar.EventDefinition == e .Find(ar =>
&& ar.Student == context.Student ar.EventDefinition == e
&& ar.Requirement == Requirement.Include) == null; && ar.Student == context.Student
var isExcluded = _assignmentRequirements && ar.Requirement == Requirement.Exclude) == null;
.Find(ar =>
ar.EventDefinition == e
&& ar.Student == context.Student
&& ar.Requirement == Requirement.Exclude) == null;
}
@if (isIncluded)
{
<MudTooltip Text="@($"Add requirement for {context.Student.FirstName} in {e.ShortName}")">
<MudIconButton Icon="@Icons.Material.Outlined.ThumbUpAlt" Class="ml-3" Size="Size.Small" Color="Color.Default"
OnClick="() => RequireEvent(e, context.Student, Requirement.Include)"></MudIconButton>
</MudTooltip>
}
else
{
<MudTooltip Text="@($"Remove requirement for {context.Student.FirstName} in {e.ShortName}")">
<MudIconButton Icon="@Icons.Material.Filled.ThumbUpAlt" Class="ml-3" Size="Size.Small" Color="Color.Dark"
OnClick="() => RemoveRequireEvent(e, context.Student, Requirement.Include)"></MudIconButton>
</MudTooltip>
}
@if (isExcluded) <InteractiveChip WrapperClass="mx-3 my-1" Style="@style" Variant="Variant.Text">
{ <ChildContent>
<MudTooltip Text="@($"Add restriction against {context.Student.FirstName} in {e.ShortName}")"> @e.ShortName&nbsp;
<MudIconButton Icon="@Icons.Material.Outlined.ThumbDownAlt" Size="Size.Small" Color="Color.Default" @AppIcons.EventAttributes(e)
OnClick="() => RequireEvent(e, context.Student, Requirement.Exclude)"></MudIconButton> </ChildContent>
</MudTooltip> <ControlContent>
} @if (isIncluded)
else {
{ <MudTooltip Text="@($"Add requirement for {context.Student.FirstName} in {e.ShortName}")">
<MudTooltip Text="@($"Remove restriction against {context.Student.FirstName} in {e.ShortName}")"> <MudIconButton Icon="@Icons.Material.Outlined.ThumbUpAlt" Class="ml-3" Size="Size.Small" Color="Color.Default"
<MudIconButton Icon="@Icons.Material.Filled.ThumbDownAlt" Size="Size.Small" Color="Color.Dark" OnClick="() => RequireEvent(e, context.Student, Requirement.Include)"></MudIconButton>
OnClick="() => RemoveRequireEvent(e, context.Student, Requirement.Exclude)"></MudIconButton> </MudTooltip>
</MudTooltip> }
} else
</MudPaper> {
<MudTooltip Text="@($"Remove requirement for {context.Student.FirstName} in {e.ShortName}")">
<MudIconButton Icon="@Icons.Material.Filled.ThumbUpAlt" Class="ml-3" Size="Size.Small" Color="Color.Dark"
OnClick="() => RemoveRequireEvent(e, context.Student, Requirement.Include)"></MudIconButton>
</MudTooltip>
}
@if (isExcluded)
{
<MudTooltip Text="@($"Add restriction against {context.Student.FirstName} in {e.ShortName}")">
<MudIconButton Icon="@Icons.Material.Outlined.ThumbDownAlt" Size="Size.Small" Color="Color.Default"
OnClick="() => RequireEvent(e, context.Student, Requirement.Exclude)"></MudIconButton>
</MudTooltip>
}
else
{
<MudTooltip Text="@($"Remove restriction against {context.Student.FirstName} in {e.ShortName}")">
<MudIconButton Icon="@Icons.Material.Filled.ThumbDownAlt" Size="Size.Small" Color="Color.Dark"
OnClick="() => RemoveRequireEvent(e, context.Student, Requirement.Exclude)"></MudIconButton>
</MudTooltip>
}
</ControlContent>
</InteractiveChip>
} }
<MudDivider Style="border-width:3px" /> <MudDivider Style="border-width:3px" />
</td></MudTr> </td></MudTr>
@@ -0,0 +1,50 @@
@namespace WebApp.Components.Shared.Components
<MudStack Row="true" Spacing="0" AlignItems="AlignItems.Center"
Style="position: relative; display: inline-flex;"
Class="@WrapperClass"
@onmouseenter="@(() => _isHovered = true)"
@onmouseleave="@(() => _isHovered = false)">
<MudChip T="string"
Size="@Size"
Color="@Color"
Variant="@Variant"
Style="@Style"
Class="@Class">
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
@ChildContent
@if (_isHovered && ControlContent != null)
{
@ControlContent
}
</MudStack>
</MudChip>
</MudStack>
@code {
[Parameter]
public required RenderFragment ChildContent { get; set; }
[Parameter]
public RenderFragment? ControlContent { get; set; }
[Parameter]
public Size Size { get; set; } = Size.Small;
[Parameter]
public Color Color { get; set; } = Color.Default;
[Parameter]
public Variant Variant { get; set; } = Variant.Text;
[Parameter]
public string? Style { get; set; }
[Parameter]
public string? Class { get; set; }
[Parameter]
public string? WrapperClass { get; set; }
private bool _isHovered = false;
}