Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87db67f979 | ||
|
|
2aaefb2491 |
@@ -19,7 +19,7 @@
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="12" md="6">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Paste Event Occurrence Data</MudText>
|
||||
<MudStack Spacing="3">
|
||||
<MudTextField
|
||||
@@ -53,7 +53,7 @@
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" md="6">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Parsed Results</MudText>
|
||||
|
||||
@if (_isParsing)
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
@using WebApp.Models
|
||||
@using WebApp.Services
|
||||
@using Heron.MudCalendar
|
||||
@using Microsoft.Extensions.Logging
|
||||
@inject IEventOccurrenceService EventOccurrenceService
|
||||
@inject ILogger<Index> Logger
|
||||
|
||||
<PageHeader Title="Event Calendar" Description="View competition schedules and event occurrences" Icon="@AppIcons.EventCalendar">
|
||||
<ActionButtons>
|
||||
@@ -12,7 +14,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
@if (_calendarItems == null)
|
||||
{
|
||||
<MudProgressLinear Indeterminate="true" />
|
||||
@@ -23,7 +25,7 @@
|
||||
<MudCalendar T="CalendarEventItem"
|
||||
Items="_calendarItems"
|
||||
View="CalendarView.Day"
|
||||
CurrentDay=_calendarDate
|
||||
CurrentDay="@_calendarDate"
|
||||
/>
|
||||
}
|
||||
</MudPaper>
|
||||
@@ -39,29 +41,115 @@
|
||||
|
||||
private async Task LoadCalendarEvents()
|
||||
{
|
||||
var occurrences = await EventOccurrenceService.GetEventOccurrencesAsync();
|
||||
_calendarItems = occurrences
|
||||
.Select(occ => new CalendarEventItem(occ))
|
||||
.ToList();
|
||||
try
|
||||
{
|
||||
Logger.LogInformation("Loading calendar events");
|
||||
var occurrences = await EventOccurrenceService.GetEventOccurrencesAsync();
|
||||
|
||||
// Find the next date with events
|
||||
_calendarDate = GetNextDateWithEvents();
|
||||
if (occurrences == null)
|
||||
{
|
||||
Logger.LogWarning("Service returned null occurrences");
|
||||
_calendarItems = new List<CalendarEventItem>();
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogDebug("Received {Count} occurrences from service", occurrences.Count());
|
||||
|
||||
var items = new List<CalendarEventItem>();
|
||||
foreach (var occ in occurrences)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (occ == null)
|
||||
{
|
||||
Logger.LogWarning("Null occurrence found, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(occ.Name))
|
||||
{
|
||||
Logger.LogWarning("Occurrence with Id={Id} has null or empty Name", occ.Id);
|
||||
}
|
||||
|
||||
var calendarItem = new CalendarEventItem(occ, occ.EventDefinition);
|
||||
items.Add(calendarItem);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error creating CalendarEventItem for occurrence Id={Id}, Name={Name}",
|
||||
occ?.Id, occ?.Name);
|
||||
// Continue processing other items
|
||||
}
|
||||
}
|
||||
|
||||
_calendarItems = items;
|
||||
Logger.LogInformation("Created {Count} calendar items from {OccurrenceCount} occurrences",
|
||||
_calendarItems.Count, occurrences.Count());
|
||||
|
||||
// Find the next date with events
|
||||
_calendarDate = GetNextDateWithEvents();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error loading calendar events");
|
||||
_calendarItems = new List<CalendarEventItem>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime GetNextDateWithEvents()
|
||||
{
|
||||
if (_calendarItems == null || !_calendarItems.Any())
|
||||
try
|
||||
{
|
||||
if (_calendarItems == null || !_calendarItems.Any())
|
||||
{
|
||||
Logger.LogDebug("No calendar items available, returning today's date");
|
||||
return DateTime.Today;
|
||||
}
|
||||
|
||||
var today = DateTime.Today;
|
||||
var nextEvent = _calendarItems
|
||||
.Where(item =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return item != null && item.Start.Date >= today;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Error checking item date, skipping item");
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.OrderBy(item => item.Start)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (nextEvent != null)
|
||||
{
|
||||
return nextEvent.Start.Date;
|
||||
}
|
||||
|
||||
// Fallback to first event if no future events
|
||||
var firstEvent = _calendarItems
|
||||
.Where(item => item != null)
|
||||
.OrderBy(item => item.Start)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (firstEvent != null)
|
||||
{
|
||||
return firstEvent.Start.Date;
|
||||
}
|
||||
|
||||
return DateTime.Today;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error in GetNextDateWithEvents");
|
||||
return DateTime.Today;
|
||||
}
|
||||
|
||||
var today = DateTime.Today;
|
||||
var nextEvent = _calendarItems
|
||||
.Where(item => item.Start.Date >= today)
|
||||
.OrderBy(item => item.Start)
|
||||
.FirstOrDefault();
|
||||
|
||||
return nextEvent?.Start.Date ?? _calendarItems.OrderBy(item => item.Start).First().Start.Date;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
|
||||
@if (_isLoading)
|
||||
{
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudProgressLinear Indeterminate="true" Color="Color.Primary"/>
|
||||
<MudText Typo="Typo.body1" Class="mt-4">Loading career mapping data...</MudText>
|
||||
</MudPaper>
|
||||
}
|
||||
else if (_networkData == null || !_networkData.Nodes.Any())
|
||||
{
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h6" Class="mb-4">No Career Field Mappings Found</MudText>
|
||||
<MudText Typo="Typo.body1" Class="mud-text-secondary">
|
||||
No events have related careers assigned that match any career fields. Edit events to add related careers.
|
||||
@@ -30,7 +30,7 @@ else if (_networkData == null || !_networkData.Nodes.Any())
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h6" Class="mb-4">Event-Career Field Relationships</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mb-4 mud-text-secondary">
|
||||
This diagram shows the connections between events and their related career fields.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<ValidationErrorDisplay Errors="_validationErrors" />
|
||||
|
||||
<MudStack Spacing="4">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" sm="6">
|
||||
@@ -49,7 +49,7 @@
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Event Details</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12">
|
||||
@@ -67,7 +67,7 @@
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Team Configuration</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12">
|
||||
@@ -88,7 +88,7 @@
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Competition Details</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12">
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" sm="6" md="4">
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<ValidationErrorDisplay Errors="_validationErrors" />
|
||||
|
||||
<MudStack Spacing="4">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" sm="6">
|
||||
@@ -56,7 +56,7 @@
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Event Details</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12">
|
||||
@@ -74,7 +74,7 @@
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Team Configuration</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12">
|
||||
@@ -95,7 +95,7 @@
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Competition Details</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12">
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudDataGrid T="EventDefinition"
|
||||
ServerData="ServerReload"
|
||||
@ref="_dataGrid"
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
<PageHeader Title="@($"{Configuration["ChapterSettings:Shortname"]} TSA Schedule {Configuration["ChapterSettings:CompetitionYear"]}")" />
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6 mt-4">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4">
|
||||
<MudGrid>
|
||||
<MudItem xs="7" sm="8" lg="9">
|
||||
<MudItem xs="12" sm="8" lg="9">
|
||||
<MudText Typo="Typo.h4">Time Slots</MudText>
|
||||
<MudPaper Class="pa-2 ma-2" Elevation="3">
|
||||
<MudGrid>
|
||||
@@ -81,7 +81,7 @@
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
</MudItem>
|
||||
<MudItem xs="5" sm="4" lg="3">
|
||||
<MudItem xs="12" sm="4" lg="3">
|
||||
<MudStack>
|
||||
<StudentTextBoxSelector Students="@_students"
|
||||
SelectedStudents="_absentStudents"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<ValidationErrorDisplay Errors="_validationErrors" />
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Student Information</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" sm="6">
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Student Information</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" sm="6" md="4">
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="12" sm="7">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudTextField T="string" Label="First Name" @bind-Value="Student.FirstName" For="@(() => Student.FirstName)"></MudTextField>
|
||||
<MudTextField T="string" Label="Last Name" @bind-Value="Student.LastName" For="@(() => Student.LastName)"></MudTextField>
|
||||
<MudTextField T="string" Label="Email Adress" @bind-Value="Student.Email" For="@(() => Student.Email)"></MudTextField>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
else
|
||||
{
|
||||
<MudStack Spacing="4">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<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>
|
||||
@@ -64,7 +64,7 @@ else
|
||||
</MudTable>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<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>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudDataGrid T="Student"
|
||||
ServerData="ServerReload"
|
||||
@ref="_dataGrid"
|
||||
@@ -30,7 +30,7 @@
|
||||
<PropertyColumn Property="@(e => e.LastName)" Title="Name" Sortable="true">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
||||
<div class="d-flex align-center flex-wrap" style="gap: 0.25rem;">
|
||||
<MudLink Href="@($"/students/details?id={context.Item.Id}&returnUrl=/students")"
|
||||
Underline="Underline.Hover"
|
||||
Color="Color.Primary">
|
||||
@@ -40,7 +40,7 @@
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Icon="@(AppIcons.OfficerRoleIcon(context.Item.OfficerRole.Value))">@context.Item.OfficerRole</MudChip>
|
||||
}
|
||||
</MudStack>
|
||||
</div>
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
||||
<IconButtonWithTooltip Icon="@Icons.Material.Filled.Edit"
|
||||
TooltipText="Edit"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.body2" Class="mb-2">
|
||||
<MudIcon Icon="@AppIcons.Captain" Size="Size.Small" /> = Team Captain
|
||||
</MudText>
|
||||
@@ -78,8 +78,9 @@
|
||||
var teamsToDisplay = _showRegionalOnly
|
||||
? context.Item.Teams.Where(t => t?.Event is { RegionalEvent: true }).OrderBy(t => t.Event.Name)
|
||||
: context.Item.Teams.Where(t => t?.Event != null).OrderBy(t => t.Event.Name);
|
||||
|
||||
foreach (var team in teamsToDisplay)
|
||||
}
|
||||
<div class="d-flex flex-wrap" style="gap: 0.25rem;">
|
||||
@foreach (var team in teamsToDisplay)
|
||||
{
|
||||
var isCaptain = team.Captain != null && team.Captain.Equals(context.Item.Student);
|
||||
var teamMembers = string.Join(", ", team.Students.Select(s => s.FirstName));
|
||||
@@ -97,7 +98,7 @@
|
||||
</MudChip>
|
||||
</MudTooltip>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6 mt-4">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4">
|
||||
<MudGrid>
|
||||
<MudItem Style="width:160px;">
|
||||
<MudNumericField @bind-Value="_parameters.TeamSizeLimit"
|
||||
@@ -117,7 +117,7 @@
|
||||
<MudButton Class="ma-3" OnClick="Solve" Variant="Variant.Filled" Color="Color.Primary" Disabled="@_isSolving">Solve</MudButton>
|
||||
</MudPaper>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6 mt-4">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4">
|
||||
<MudGrid>
|
||||
<MudItem xs="12" lg="8">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Students</MudText>
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
@using WebApp.Models
|
||||
@foreach (var student in
|
||||
Team.Students
|
||||
.OrderBy(e =>
|
||||
e.EventRankings
|
||||
.Find(er => er.EventDefinition == Team.Event)?.Rank ?? 10)
|
||||
.ThenBy(s => s.Grade + s.TsaYear))
|
||||
{
|
||||
var eventRank =
|
||||
student.EventRankings
|
||||
.Find(e => e.EventDefinition == Team.Event)?.Rank;
|
||||
var color = AppIcons.RankedEventColor(eventRank ?? 0);
|
||||
var captain = Team.Captain != null && Team.Captain.Equals(student);
|
||||
var rankLabel = eventRank.HasValue ? $"Rank {eventRank}" : "Unranked";
|
||||
<div class="d-flex flex-wrap" style="gap: 0.25rem;">
|
||||
@foreach (var student in
|
||||
Team.Students
|
||||
.OrderBy(e =>
|
||||
e.EventRankings
|
||||
.Find(er => er.EventDefinition == Team.Event)?.Rank ?? 10)
|
||||
.ThenBy(s => s.Grade + s.TsaYear))
|
||||
{
|
||||
var eventRank =
|
||||
student.EventRankings
|
||||
.Find(e => e.EventDefinition == Team.Event)?.Rank;
|
||||
var color = AppIcons.RankedEventColor(eventRank ?? 0);
|
||||
var captain = Team.Captain != null && Team.Captain.Equals(student);
|
||||
var rankLabel = eventRank.HasValue ? $"Rank {eventRank}" : "Unranked";
|
||||
|
||||
<MudTooltip Text="@rankLabel">
|
||||
<MudChip T="string"
|
||||
Size="Size.Medium"
|
||||
Variant="Variant.Outlined"
|
||||
Class="mx-1 my-1">
|
||||
@if (eventRank.HasValue)
|
||||
{
|
||||
<span style="@($"display: inline-block; width: 12px; height: 12px; border-radius: 50%; background-color: {color}; margin-right: 6px;")")></span>
|
||||
}
|
||||
@student.FirstName
|
||||
@if (captain && Team.Event.EventFormat != EventFormat.Individual)
|
||||
{
|
||||
<MudIcon Icon="@AppIcons.Captain" Size="Size.Small" Style="margin-left: 4px;" />
|
||||
}
|
||||
</MudChip>
|
||||
</MudTooltip>
|
||||
}
|
||||
<MudTooltip Text="@rankLabel">
|
||||
<MudChip T="string"
|
||||
Size="Size.Medium"
|
||||
Variant="Variant.Outlined"
|
||||
Class="mx-1 my-1">
|
||||
@if (eventRank.HasValue)
|
||||
{
|
||||
<span style="@($"display: inline-block; width: 12px; height: 12px; border-radius: 50%; background-color: {color}; margin-right: 6px;")")"></span>
|
||||
}
|
||||
@student.FirstName
|
||||
@if (captain && Team.Event.EventFormat != EventFormat.Individual)
|
||||
{
|
||||
<MudIcon Icon="@AppIcons.Captain" Size="Size.Small" Style="margin-left: 4px;" />
|
||||
}
|
||||
</MudChip>
|
||||
</MudTooltip>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="12" sm="7">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudSelect T="EventDefinition" Value="@Team.Event" ValueChanged="OnEventChanged" Label="Event">
|
||||
|
||||
@foreach (var evt in _events)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudText Typo="Typo.h5" Class="mb-4">Team Information</MudText>
|
||||
<MudGrid Spacing="3">
|
||||
<MudItem xs="12" sm="6">
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="12" sm="7">
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<StudentToggleSelector Students="@_students"
|
||||
@bind-SelectedStudents="_selectedStudents"
|
||||
Title="Students"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
@foreach (var student in _students)
|
||||
{
|
||||
<MudContainer Class="pagebreak">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</ActionButtons>
|
||||
</PageHeader>
|
||||
|
||||
<MudPaper Elevation="2" Class="pa-6">
|
||||
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||
<MudDataGrid T="Team"
|
||||
ServerData="ServerReload"
|
||||
@ref="_dataGrid"
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<MudLayout>
|
||||
<MudAppBar Class="no-print">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
|
||||
TSA Chapter Organizer - @Configuration["ChapterSettings:Name"]
|
||||
<MudText Typo="Typo.h6" Class="text-truncate appbar-title">
|
||||
TSA Chapter Organizer - @Configuration["ChapterSettings:Name"]
|
||||
</MudText>
|
||||
<MudSpacer />
|
||||
<AuthorizeView>
|
||||
<form action="Auth/CookieLogout" method="post">
|
||||
|
||||
@@ -24,6 +24,10 @@ public class CalendarEventItem : CalendarItem
|
||||
/// </summary>
|
||||
public CalendarEventItem()
|
||||
{
|
||||
// Initialize base class properties to avoid null reference issues
|
||||
Text = string.Empty;
|
||||
Start = DateTime.MinValue;
|
||||
End = DateTime.MinValue;
|
||||
}
|
||||
|
||||
public CalendarEventItem(Core.Entities.EventOccurrence occurrence, Core.Entities.EventDefinition? eventDefinition = null)
|
||||
|
||||
+26
-1
@@ -1,5 +1,6 @@
|
||||
using Data;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MudBlazor.Services;
|
||||
using Serilog;
|
||||
@@ -268,7 +269,31 @@ app.UseRouting();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseStaticFiles();
|
||||
// Configure static files with proper cache headers for Blazor assets
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
OnPrepareResponse = ctx =>
|
||||
{
|
||||
// Blazor framework files: Use ETags with short cache and revalidation
|
||||
// This allows caching for performance but ensures fresh files after deployments
|
||||
// Browser will check ETag on each request (304 Not Modified if unchanged)
|
||||
if (ctx.File.Name.Contains("_framework") ||
|
||||
ctx.File.Name.Contains("blazor") ||
|
||||
ctx.File.Name.EndsWith(".dll") ||
|
||||
ctx.File.Name.EndsWith(".wasm"))
|
||||
{
|
||||
// Cache for 12 hours, but must revalidate (check ETag) before using
|
||||
// If file hasn't changed, browser gets 304 Not Modified (no download)
|
||||
// If file changed, browser downloads new version
|
||||
ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=43200, must-revalidate");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Other static files (CSS, images, etc.) can be cached long-term
|
||||
ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=31536000");
|
||||
}
|
||||
}
|
||||
});
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapRazorComponents<App>()
|
||||
|
||||
@@ -56,6 +56,19 @@
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.page-header-actions {
|
||||
width: 100%;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.page-header > div > div:first-of-type {
|
||||
flex-direction: column;
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
@@ -66,6 +79,17 @@
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.form-actions {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-actions > * {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-button-hover-error:hover {
|
||||
color: var(--mud-palette-error) !important;
|
||||
}
|
||||
@@ -88,3 +112,20 @@
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Toolbar title responsive styling */
|
||||
.appbar-title {
|
||||
max-width: calc(100vw - 150px);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.appbar-title {
|
||||
font-size: 0.875rem;
|
||||
max-width: calc(100vw - 120px);
|
||||
}
|
||||
|
||||
/* Reduce base font size on mobile */
|
||||
body {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user