diff --git a/Client/Pages/Index.razor.cs b/Client/Pages/Index.razor.cs index 1400c9b..7110f75 100644 --- a/Client/Pages/Index.razor.cs +++ b/Client/Pages/Index.razor.cs @@ -112,7 +112,7 @@ namespace ShiftScheduler.Client.Pages var response = await HttpClient.PostAsJsonAsync("api/shift/export_pdf", shiftsWithTransportList); var bytes = await response.Content.ReadAsByteArrayAsync(); var base64 = Convert.ToBase64String(bytes); - await JSRuntime.InvokeVoidAsync("downloadFile", $"Schedule {EditYear}-{EditMonth:00}.pdf", "application/pdf", base64); + await JSRuntime.InvokeVoidAsync("downloadFile", $"Schedule {EditYear}-{EditMonth:D2}.pdf", "application/pdf", base64); } private async Task SaveScheduleToStorage() diff --git a/Server/Controllers/ShiftController.cs b/Server/Controllers/ShiftController.cs index 29d2e12..6664d70 100644 --- a/Server/Controllers/ShiftController.cs +++ b/Server/Controllers/ShiftController.cs @@ -12,7 +12,6 @@ namespace ShiftScheduler.Server.Controllers private readonly IcsExportService _icsService; private readonly PdfExportService _pdfExportService; private readonly TransportService _transportService; - private readonly ShiftEnrichmentService _enrichmentService; private readonly TransportConfiguration _transportConfig; public ShiftController( @@ -20,14 +19,12 @@ namespace ShiftScheduler.Server.Controllers IcsExportService icsService, PdfExportService pdfExportService, TransportService transportService, - ShiftEnrichmentService enrichmentService, TransportConfiguration transportConfig) { _shiftService = shiftService; _icsService = icsService; _pdfExportService = pdfExportService; _transportService = transportService; - _enrichmentService = enrichmentService; _transportConfig = transportConfig; } @@ -37,13 +34,6 @@ namespace ShiftScheduler.Server.Controllers return Ok(_shiftService.GetShifts()); } - [HttpPost("transport_connection")] - public async Task GetTransportConnection([FromBody] TransportConnectionRequest request) - { - var connection = await _transportService.GetConnectionAsync(request.ArrivalTime, request.EndStation); - return Ok(connection); - } - [HttpPost("shift_transport")] public async Task GetShiftTransport([FromBody] ShiftTransportRequest request) { @@ -101,7 +91,6 @@ namespace ShiftScheduler.Server.Controllers Shift = shift, MorningTransport = morningTransport, AfternoonTransport = afternoonTransport, - DepartureStation = _transportConfig.StartStation }; return Ok(shiftWithTransport); @@ -156,12 +145,6 @@ namespace ShiftScheduler.Server.Controllers } } - public class TransportConnectionRequest - { - public DateTime ArrivalTime { get; set; } - public string? EndStation { get; set; } - } - public class ShiftTransportRequest { public string ShiftName { get; set; } = string.Empty; diff --git a/Server/Program.cs b/Server/Program.cs index 715efa4..80455b3 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -15,7 +15,6 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); diff --git a/Services/IcsExportService.cs b/Services/IcsExportService.cs index 689e7d1..98217f9 100644 --- a/Services/IcsExportService.cs +++ b/Services/IcsExportService.cs @@ -28,7 +28,7 @@ namespace ShiftScheduler.Services if (shiftWithTransport.MorningTransport != null && !string.IsNullOrEmpty(shiftWithTransport.MorningTransport.DepartureTime)) { - var transportSummary = FormatTransportInfo(shiftWithTransport.MorningTransport, shiftWithTransport.DepartureStation); + var transportSummary = FormatTransportInfo(shiftWithTransport.MorningTransport); description = $"Transport: {transportSummary}"; } @@ -49,7 +49,7 @@ namespace ShiftScheduler.Services if (shiftWithTransport.AfternoonTransport != null && !string.IsNullOrEmpty(shiftWithTransport.AfternoonTransport.DepartureTime)) { - var transportSummary = FormatTransportInfo(shiftWithTransport.AfternoonTransport, shiftWithTransport.DepartureStation); + var transportSummary = FormatTransportInfo(shiftWithTransport.AfternoonTransport); description = $"Transport: {transportSummary}"; } @@ -66,20 +66,18 @@ namespace ShiftScheduler.Services return new CalendarSerializer().SerializeToString(calendar); } - private string FormatTransportInfo(TransportConnection transport, string departureStation) + private string FormatTransportInfo(TransportConnection transport) { var departure = DateTime.TryParse(transport.DepartureTime, out var dep) ? dep.ToString("HH:mm") : transport.DepartureTime; var arrival = DateTime.TryParse(transport.ArrivalTime, out var arr) ? arr.ToString("HH:mm") : transport.ArrivalTime; - var departureStationInfo = !string.IsNullOrEmpty(departureStation) ? $"{departureStation} " : ""; - var mainJourney = transport.Sections?.FirstOrDefault()?.Journey; if (mainJourney != null) { - return $"{mainJourney.Category} {mainJourney.Number}: {departureStationInfo}{departure} → {arrival}"; + return $"{mainJourney.Category} {mainJourney.Number}: {departure} → {arrival}"; } - return $"{departureStationInfo}{departure} → {arrival}"; + return $"{departure} → {arrival}"; } } } diff --git a/Services/PdfExportService.cs b/Services/PdfExportService.cs index f949403..02f570f 100644 --- a/Services/PdfExportService.cs +++ b/Services/PdfExportService.cs @@ -155,30 +155,28 @@ namespace ShiftScheduler.Services if (shiftWithTransport.MorningTransport != null && !string.IsNullOrEmpty(shiftWithTransport.MorningTransport.DepartureTime)) { - var morningInfo = FormatTransportConnection(shiftWithTransport.MorningTransport, "Morning", shiftWithTransport.DepartureStation); + var morningInfo = FormatTransportConnection(shiftWithTransport.MorningTransport, "Morning"); transportLines.Add(morningInfo); } if (shiftWithTransport.AfternoonTransport != null && !string.IsNullOrEmpty(shiftWithTransport.AfternoonTransport.DepartureTime)) { - var afternoonInfo = FormatTransportConnection(shiftWithTransport.AfternoonTransport, "Afternoon", shiftWithTransport.DepartureStation); + var afternoonInfo = FormatTransportConnection(shiftWithTransport.AfternoonTransport, "Afternoon"); transportLines.Add(afternoonInfo); } return transportLines.Count > 0 ? string.Join("\n", transportLines) : "-"; } - private static string FormatTransportConnection(TransportConnection transport, string timeOfDay, string departureStation) + private static string FormatTransportConnection(TransportConnection transport, string timeOfDay) { var departure = DateTime.TryParse(transport.DepartureTime, out var dep) ? dep.ToString("HH:mm") : transport.DepartureTime; var arrival = DateTime.TryParse(transport.ArrivalTime, out var arr) ? arr.ToString("HH:mm") : transport.ArrivalTime; var mainJourney = transport.Sections?.FirstOrDefault()?.Journey; var trainInfo = mainJourney != null ? $"{mainJourney.Category} {mainJourney.Number}" : "Train"; - - var departureStationInfo = !string.IsNullOrEmpty(departureStation) ? $"{departureStation} " : ""; - - return $"{timeOfDay}: {trainInfo} {departureStationInfo}{departure}→{arrival}"; + + return $"{timeOfDay}: {trainInfo} {departure}→{arrival}"; } private static void RenderEmptyCell(TableDescriptor table) diff --git a/Services/ShiftEnrichmentService.cs b/Services/ShiftEnrichmentService.cs deleted file mode 100644 index 26ecb4e..0000000 --- a/Services/ShiftEnrichmentService.cs +++ /dev/null @@ -1,77 +0,0 @@ -using ShiftScheduler.Shared.Models; - -namespace ShiftScheduler.Services -{ - public class ShiftEnrichmentService - { - private readonly TransportService _transportService; - - public ShiftEnrichmentService(TransportService transportService) - { - _transportService = transportService; - } - - public async Task> EnrichShiftsWithTransportAsync(List shifts, Dictionary schedule) - { - var shiftTransports = new List(); - - foreach (var shift in shifts) - { - var shiftTransport = new ShiftTransport - { - ShiftName = shift.Name - }; - - // Find dates where this shift is scheduled - var scheduledDates = schedule.Where(kvp => kvp.Value == shift.Name).Select(kvp => kvp.Key).ToList(); - - if (scheduledDates.Count > 0) - { - // Use the first scheduled date to calculate transport times - var sampleDate = scheduledDates.First(); - - // Get transport for morning shift - if (!string.IsNullOrEmpty(shift.MorningTime)) - { - var morningStartTime = ParseShiftTime(sampleDate, shift.MorningTime); - if (morningStartTime.HasValue) - { - shiftTransport.MorningTransport = await _transportService.GetConnectionAsync(morningStartTime.Value); - } - } - - // Get transport for afternoon shift - if (!string.IsNullOrEmpty(shift.AfternoonTime)) - { - var afternoonStartTime = ParseShiftTime(sampleDate, shift.AfternoonTime); - if (afternoonStartTime.HasValue) - { - shiftTransport.AfternoonTransport = await _transportService.GetConnectionAsync(afternoonStartTime.Value); - } - } - } - - shiftTransports.Add(shiftTransport); - } - - return shiftTransports; - } - - private DateTime? ParseShiftTime(DateTime date, string timeRange) - { - try - { - var times = timeRange.Split('-'); - if (times.Length > 0 && TimeSpan.TryParse(times[0], out var startTime)) - { - return date.Add(startTime); - } - } - catch - { - // Ignore parsing errors - } - return null; - } - } -} \ No newline at end of file diff --git a/Services/TransportService.cs b/Services/TransportService.cs index 6213bbf..b388beb 100644 --- a/Services/TransportService.cs +++ b/Services/TransportService.cs @@ -23,13 +23,12 @@ namespace ShiftScheduler.Services // Calculate the latest acceptable arrival time (shift start time - safety buffer) var latestArrivalTime = shiftStartTime.AddMinutes(-_config.SafetyBufferMinutes); - // Search for connections starting from a reasonable time before the latest acceptable arrival - // Start searching from 90 minutes before the latest acceptable time - var searchTime = latestArrivalTime.AddMinutes(-90); + // Search for arrival time + var searchTime = shiftStartTime; var searchTimeStr = searchTime.ToString("yyyy-MM-dd"); var searchHourStr = searchTime.ToString("HH:mm"); - var url = $"{_config.ApiBaseUrl}/connections?from={Uri.EscapeDataString(_config.StartStation)}&to={Uri.EscapeDataString(endStation)}&date={searchTimeStr}&time={searchHourStr}&limit=15"; + var url = $"{_config.ApiBaseUrl}/connections?from={Uri.EscapeDataString(_config.StartStation)}&to={Uri.EscapeDataString(endStation)}&date={searchTimeStr}&time={searchHourStr}&isArrivalTime=1&limit=5"; var response = await _httpClient.GetStringAsync(url); var apiResponse = JsonSerializer.Deserialize(response, new JsonSerializerOptions @@ -121,25 +120,11 @@ namespace ShiftScheduler.Services if (validConnections.Count > 0) { - // Sort by arrival time (earliest first) and take the one that arrives - // with reasonable margin but not too early var sortedValid = validConnections .OrderBy(c => DateTime.Parse(c.To?.Arrival ?? "00:00")) .ToList(); - - // Prefer a connection that arrives with 10-45 minutes margin - var preferredMarginMin = 10; - var preferredMarginMax = 45; - - var idealConnection = sortedValid.LastOrDefault(c => - { - var arrivalTime = DateTime.Parse(c.To?.Arrival ?? "00:00"); - var marginMinutes = (latestArrivalTime - arrivalTime).TotalMinutes; - return marginMinutes >= preferredMarginMin && marginMinutes <= preferredMarginMax; - }); - - // If we found an ideal connection, use it; otherwise use the latest valid one - return idealConnection ?? sortedValid.Last(); + + return sortedValid.Last(); } // If no valid connections, return the earliest available diff --git a/Shared/ShiftWithTransport.cs b/Shared/ShiftWithTransport.cs index 9cc538b..5bfa2b7 100644 --- a/Shared/ShiftWithTransport.cs +++ b/Shared/ShiftWithTransport.cs @@ -7,7 +7,6 @@ namespace ShiftScheduler.Shared.Models public Shift Shift { get; init; } = new(); public TransportConnection? MorningTransport { get; init; } public TransportConnection? AfternoonTransport { get; init; } - public string DepartureStation { get; init; } = string.Empty; public string GetMorningTransportSummary() { @@ -29,9 +28,7 @@ namespace ShiftScheduler.Shared.Models var mainJourney = connection.Sections?.FirstOrDefault()?.Journey; var trainInfo = mainJourney != null ? $"{mainJourney.Category}{mainJourney.Number}" : "Train"; - var departureStationInfo = !string.IsNullOrEmpty(DepartureStation) ? $"{DepartureStation} " : ""; - - return $"{trainInfo} {departureStationInfo}{departure}→{arrival}"; + return $"{trainInfo} {departure}→{arrival}"; } } } \ No newline at end of file diff --git a/Shared/TransportModels.cs b/Shared/TransportModels.cs index 8eaa52c..c826316 100644 --- a/Shared/TransportModels.cs +++ b/Shared/TransportModels.cs @@ -1,12 +1,5 @@ namespace ShiftScheduler.Shared.Models { - public class ShiftTransport - { - public string ShiftName { get; set; } = string.Empty; - public TransportConnection? MorningTransport { get; set; } - public TransportConnection? AfternoonTransport { get; set; } - } - public class TransportConfiguration { public string StartStation { get; set; } = string.Empty; @@ -65,6 +58,11 @@ namespace ShiftScheduler.Shared.Models public TransportApiCheckpoint? To { get; set; } public string Duration { get; set; } = string.Empty; public List Sections { get; set; } = new(); + + public override string ToString() + { + return $"{From} - {To}"; + } } public class TransportApiCheckpoint @@ -73,6 +71,11 @@ namespace ShiftScheduler.Shared.Models public string Departure { get; set; } = string.Empty; public string Arrival { get; set; } = string.Empty; public string Platform { get; set; } = string.Empty; + + public override string ToString() + { + return $"{Station?.Name}: {Departure} - {Arrival}"; + } } public class TransportApiStation