Files
chapter-organizer/WebApp/Components/Features/Calendar/Index.razor
T
poprhythm a9036d5d04 Add state schedule handout feature and configuration options
This commit introduces a new StateScheduleHandout component for generating printable schedules for students, including a combined master list of events. It adds configuration options in appsettings.json for state abbreviations and special event filters, enhancing the scheduling functionality. The Program.cs file is updated to register the new StateScheduleHandoutOptions, and the Calendar and Teams components are modified to include links to the new handout feature. Additionally, utility methods for filtering event occurrences are implemented to support the new functionality, improving the overall user experience in managing state schedules.
2026-04-06 23:33:57 -04:00

222 lines
7.0 KiB
Plaintext

@page "/calendar"
@attribute [Authorize]
@using WebApp.Models
@using WebApp.Services
@using Heron.MudCalendar
@using Microsoft.Extensions.Logging
@using WebApp.Authentication
@inject ICalendarService CalendarService
@inject ILogger<Index> Logger
@inject IDialogService DialogService
<PageHeader Title="Event Calendar" Description="View competition schedules and event occurrences" Icon="@AppIcons.EventCalendar">
<ActionButtons>
<MudTooltip Text="Import">
<MudButton StartIcon="@Icons.Material.Filled.ImportExport" Href="calendar/event-occurrences/import" Variant="Variant.Filled" Color="Color.Primary">Import</MudButton>
</MudTooltip>
<MudTooltip Text="Schedule handout (print)">
<MudButton StartIcon="@Icons.Material.Filled.Print" Href="calendar/state-schedule-handout" Variant="Variant.Outlined">Schedule handout</MudButton>
</MudTooltip>
<AuthorizeView Roles="@AuthRoles.Administrator">
<MudTooltip Text="Admin">
<MudButton StartIcon="@Icons.Material.Filled.AdminPanelSettings" Href="calendar/admin" Variant="Variant.Outlined" Color="Color.Default">Admin</MudButton>
</MudTooltip>
</AuthorizeView>
<PageNoteButton PageIdentifier="Event Calendar" />
</ActionButtons>
</PageHeader>
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
@if (_calendarItems == null)
{
<MudProgressLinear Indeterminate="true" />
<MudText>Loading calendar events...</MudText>
}
else
{
<MudStack Spacing="2">
<MudCalendar T="CalendarItemWrapper"
Items="_calendarItems"
@bind-View="_currentView"
@bind-CurrentDay="_calendarDate"
Class="event-calendar"
ItemClicked="OnItemClicked">
<MonthTemplate>
<MudTooltip Text="@GetEventTooltip(context)">
<div class="calendar-event-item">
@context.Text
</div>
</MudTooltip>
</MonthTemplate>
<WeekTemplate>
<MudTooltip Text="@GetEventTooltip(context)">
<div class="calendar-event-item">
@context.Text
</div>
</MudTooltip>
</WeekTemplate>
<DayTemplate>
<MudTooltip Text="@GetEventTooltip(context)">
<div class="calendar-event-item">
@context.Text
</div>
</MudTooltip>
</DayTemplate>
</MudCalendar>
</MudStack>
}
</MudPaper>
@code {
private List<CalendarItemWrapper>? _calendarItems;
private DateTime _calendarDate = DateTime.Today;
private CalendarView _currentView = CalendarView.Month;
[SupplyParameterFromQuery]
private string? Date { get; set; }
protected override async Task OnInitializedAsync()
{
// Parse date from query parameter if provided
if (!string.IsNullOrEmpty(Date) && DateTime.TryParse(Date, out var parsedDate))
{
_calendarDate = parsedDate.Date;
}
await LoadCalendarEvents();
}
private async Task LoadCalendarEvents()
{
try
{
Logger.LogInformation("Loading calendar events");
_calendarItems = await CalendarService.GetAllCalendarItemsAsync();
Logger.LogInformation("Loaded {Count} calendar items", _calendarItems.Count);
}
catch (Exception ex)
{
Logger.LogError(ex, "Error loading calendar events");
_calendarItems = [];
}
finally
{
StateHasChanged();
}
}
private string GetEventTooltip(CalendarItemWrapper wrapper)
{
if (wrapper.ItemType == CalendarItemType.Event && wrapper.EventItem != null)
{
return GetEventTooltip(wrapper.EventItem);
}
else if (wrapper.ItemType == CalendarItemType.Meeting && wrapper.MeetingItem != null)
{
return GetMeetingTooltip(wrapper.MeetingItem);
}
return wrapper.Text;
}
private string GetEventTooltip(CalendarEventItem item)
{
List<string> parts = [];
if (!string.IsNullOrEmpty(item.EventDefinition?.Name))
{
parts.Add($"Event: {item.EventDefinition.Name}");
}
if (!string.IsNullOrEmpty(item.EventOccurrenceData?.Name))
{
parts.Add($"Occurrence: {item.EventOccurrenceData.Name}");
}
if (!string.IsNullOrEmpty(item.EventOccurrenceData?.Location))
{
parts.Add($"Location: {item.EventOccurrenceData.Location}");
}
if (item.EventOccurrenceData?.StartTime != null)
{
parts.Add($"Time: {item.EventOccurrenceData.StartTime:g}");
}
if (item.StudentFirstNames.Any())
{
parts.Add($"Students: {string.Join(", ", item.StudentFirstNames)}");
}
return string.Join("\n", parts);
}
private string GetMeetingTooltip(CalendarMeetingItem item)
{
if (item.MeetingHistoryData == null)
return "Team Meeting";
return $"Team Meeting\nDate: {item.MeetingHistoryData.MeetingDate:g}";
}
private async Task OnItemClicked(CalendarItemWrapper wrapper)
{
if (_calendarItems == null)
return;
if (wrapper.ItemType == CalendarItemType.Event && wrapper.EventItem != null)
{
await ShowEventDetails(wrapper.EventItem);
}
else if (wrapper.ItemType == CalendarItemType.Meeting && wrapper.MeetingItem != null)
{
await ShowMeetingDetails(wrapper.MeetingItem);
}
}
private async Task ShowEventDetails(CalendarEventItem item)
{
if (item.EventOccurrenceData == null) return;
var parameters = new DialogParameters
{
["EventOccurrence"] = item.EventOccurrenceData,
["EventDefinition"] = item.EventDefinition,
["StudentFirstNames"] = item.StudentFirstNames
};
var options = new DialogOptions
{
CloseOnEscapeKey = true,
CloseButton = true,
MaxWidth = MaxWidth.Medium,
FullWidth = true
};
await DialogService.ShowAsync<EventOccurrenceDetailsDialog>("Event Details", parameters, options);
}
private async Task ShowMeetingDetails(CalendarMeetingItem item)
{
if (item.MeetingHistoryData == null) return;
var parameters = new DialogParameters
{
["MeetingHistoryId"] = item.MeetingHistoryData.Id
};
var options = new DialogOptions
{
CloseOnEscapeKey = true,
CloseButton = true,
MaxWidth = MaxWidth.Large,
FullWidth = true
};
await DialogService.ShowAsync<MeetingHistoryDetailDialog>("Meeting Details", parameters, options);
}
}