Add CalendarService and integrate calendar functionality into components

This commit introduces the CalendarService, which provides methods for retrieving all calendar items and upcoming events. The service is integrated into various components, including the Calendar and Home pages, enhancing the calendar functionality by allowing users to view upcoming events and meeting histories. Additionally, the Index.razor component is updated to parse query parameters for date selection, improving user experience. The layout of the MeetingHistoryDetailDialog and SaveMeetingHistoryDialog components is also refined for better organization and responsiveness. These changes collectively enhance the calendar feature and improve the overall user interface in managing events and meetings.
This commit is contained in:
2026-01-27 22:38:52 -05:00
parent 84eaf338a9
commit 675f04afec
8 changed files with 452 additions and 213 deletions
+144
View File
@@ -0,0 +1,144 @@
using Core.Entities;
using Core.Utility;
using WebApp.Models;
namespace WebApp.Services;
/// <summary>
/// Service for calendar-related operations.
/// </summary>
public class CalendarService : ICalendarService
{
private readonly IEventOccurrenceService _eventOccurrenceService;
private readonly ITeamMeetingHistoryService _teamMeetingHistoryService;
public CalendarService(
IEventOccurrenceService eventOccurrenceService,
ITeamMeetingHistoryService teamMeetingHistoryService)
{
_eventOccurrenceService = eventOccurrenceService;
_teamMeetingHistoryService = teamMeetingHistoryService;
}
public async Task<List<CalendarItemWrapper>> GetAllCalendarItemsAsync()
{
var items = new List<CalendarItemWrapper>();
await AddEventItemsAsync(items, includeStudentNames: true);
await AddMeetingItemsAsync(items);
return items;
}
public async Task<List<CalendarItemWrapper>> GetUpcomingCalendarItemsAsync(int count = 3)
{
var today = DateTime.Today;
var items = new List<CalendarItemWrapper>();
await AddEventItemsAsync(items, startDate: today, includeStudentNames: false);
await AddMeetingItemsAsync(items, startDate: today);
// Sort by date and take top N
return items
.OrderBy(item => item.Start)
.Take(count)
.ToList();
}
private async Task AddEventItemsAsync(
List<CalendarItemWrapper> items,
DateTime? startDate = null,
bool includeStudentNames = false)
{
try
{
var occurrences = await _eventOccurrenceService.GetEventOccurrencesAsync();
var eventOccurrences = occurrences as EventOccurrence[] ?? occurrences.ToArray();
// Filter by start date if provided
if (startDate.HasValue)
{
eventOccurrences = eventOccurrences
.Where(occ => occ.StartTime.Date >= startDate.Value)
.ToArray();
}
Dictionary<int, List<Team>>? teamsByEventId = null;
if (includeStudentNames)
{
// 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
teamsByEventId = await _eventOccurrenceService.GetTeamsByEventDefinitionIdsAsync(eventDefinitionIds);
}
// Add event occurrences
foreach (var occ in eventOccurrences)
{
try
{
List<string>? studentFirstNames = null;
if (includeStudentNames && occ.EventDefinition != null && teamsByEventId != null)
{
studentFirstNames = 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 calendarEventItem = new CalendarEventItem(occ, studentFirstNames);
items.Add(new CalendarItemWrapper(calendarEventItem));
}
catch (Exception)
{
// Continue processing other items
}
}
}
catch (Exception)
{
// Continue - don't fail the entire calendar load if events fail
}
}
private async Task AddMeetingItemsAsync(
List<CalendarItemWrapper> items,
DateTime? startDate = null)
{
try
{
var meetingHistories = await _teamMeetingHistoryService.GetMeetingHistoriesAsync();
IEnumerable<TeamMeetingHistory> meetings = meetingHistories;
if (startDate.HasValue)
{
meetings = meetings.Where(m => m.MeetingDate.Date >= startDate.Value);
}
foreach (var meetingHistory in meetings)
{
try
{
var calendarMeetingItem = new CalendarMeetingItem(meetingHistory);
items.Add(new CalendarItemWrapper(calendarMeetingItem));
}
catch (Exception)
{
// Continue processing other items
}
}
}
catch (Exception)
{
// Continue - don't fail the entire calendar load if meetings fail
}
}
}