@page "/calendar" @attribute [Authorize] @using WebApp.Models @using WebApp.Services @using Heron.MudCalendar @using Microsoft.Extensions.Logging @using WebApp.Authentication @using Core.Utility @inject IEventOccurrenceService EventOccurrenceService @inject ILogger Logger @inject IDialogService DialogService Import Admin @if (_calendarItems == null) { Loading calendar events... } else { Month Day @* *@
@context.Text
@*
*@
@* *@
@context.Text
@*
*@
@* *@
@context.Text
@*
*@
}
@code { private List? _calendarItems; private DateTime _calendarDate = DateTime.Today; private CalendarView _currentView = CalendarView.Month; protected override async Task OnInitializedAsync() { await LoadCalendarEvents(); } private async Task LoadCalendarEvents() { try { Logger.LogInformation("Loading calendar events"); var occurrences = await EventOccurrenceService.GetEventOccurrencesAsync(); var eventOccurrences = occurrences as EventOccurrence[] ?? occurrences.ToArray(); Logger.LogDebug("Received {Count} occurrences from service", eventOccurrences.Count()); // Get all unique event definition IDs that have occurrences var eventDefinitionIds = eventOccurrences .Where(occ => occ?.EventDefinition?.Id != null) .Select(occ => occ!.EventDefinition!.Id) .Distinct() .ToList(); // Load teams for all event definitions var teamsByEventId = await EventOccurrenceService.GetTeamsByEventDefinitionIdsAsync(eventDefinitionIds); List items = []; foreach (var occ in eventOccurrences) { try { if (string.IsNullOrEmpty(occ.Name)) { Logger.LogWarning("Occurrence with Id={Id} has null or empty Name", occ.Id); } // Get student first names for this event definition var studentFirstNames = occ.EventDefinition != null && teamsByEventId.TryGetValue(occ.EventDefinition.Id, out var teams) ? TeamStudentNameFormatter.FormatStudentListForEvent( occ.EventDefinition, teams, new TeamStudentNameFormatter.FormatOptions { CaptainIndicator = TeamStudentNameFormatter.CaptainIndicatorStyle.Star, Ordering = TeamStudentNameFormatter.OrderingStyle.Alphabetical }) : []; var calendarItem = new CalendarEventItem(occ, studentFirstNames); 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, eventOccurrences.Count()); // Find the next date with events _calendarDate = GetNextDateWithEvents(); } catch (Exception ex) { Logger.LogError(ex, "Error loading calendar events"); _calendarItems = []; } finally { StateHasChanged(); } } private DateTime GetNextDateWithEvents() { 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.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 .OrderBy(item => item.Start) .FirstOrDefault(); return firstEvent != null ? firstEvent.Start.Date : DateTime.Today; } catch (Exception ex) { Logger.LogError(ex, "Error in GetNextDateWithEvents"); return DateTime.Today; } } private string GetEventTooltip(CalendarEventItem item) { List 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 async Task OnItemClicked(CalendarEventItem calendarEventItem) { if (_calendarItems == null) return; await ShowEventDetails(calendarEventItem); } 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("Event Details", parameters, options); } }