From 1493c459bdd2ec87fb06a7bf1565c32c634ce9c8 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 Aug 2025 20:41:25 +0200 Subject: [PATCH] Implement responsive mobile/desktop UI layout for shift scheduler (#38) * Initial plan * Implement responsive mobile/desktop UI layout Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com> * Clean up demo files and finalize mobile UI implementation Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com> * Fix desktop calendar week grouping to properly start weeks on Monday and end on Sunday Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com> * Remove button for shift delete * Fix desktop week grouping to start weeks on Monday instead of grouping consecutive days Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com> * UI improvements --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com> Co-authored-by: Claudio Schaad --- Client/Pages/Index.razor | 137 ++++++++++++++++++++++++----------- Client/Pages/Index.razor.cs | 30 ++++++++ Client/Pages/Index.razor.css | 89 ++++++++++++++++++++++- Client/Pages/MonthAndYear.cs | 23 +++++- 4 files changed, 231 insertions(+), 48 deletions(-) diff --git a/Client/Pages/Index.razor b/Client/Pages/Index.razor index 4f98e59..d19b76e 100644 --- a/Client/Pages/Index.razor +++ b/Client/Pages/Index.razor @@ -3,11 +3,10 @@
- - + +
- @@ -44,54 +43,108 @@ else { -
- @foreach (var day in SelectedDate.DaysInMonth()) - { -
-
- @day.ToString("dd.MM.yyyy") (@day.ToString("dddd")) -
-
- @foreach (var shift in Shifts) - { -
- + @shift.Name +
+ } +
+ @if (SelectedSchedule.ContainsKey(day)) + { +
+ @GetShiftTimes(day) +
+
+ @GetTransportSummary(day) +
+ } +
+ } + } +
+ + +
+ @foreach (var day in SelectedDate.DaysInMonth()) + { +
+
+ @day.ToString("dd.MM.yyyy") (@day.ToString("dddd")) +
+
+ @foreach (var shift in Shifts) + { +
+ - @shift.Name + + @shift.Name +
+ } +
+ @if (SelectedSchedule.ContainsKey(day)) + { +
+ @GetShiftTimes(day) +
+
+ @GetTransportSummary(day)
}
- @if (SelectedSchedule.ContainsKey(day)) - { -
- @GetShiftTimes(day) -
-
- @GetTransportSummary(day) -
- } -
- } + } +
} + OnClose="HideConfiguration" + OnConfigurationChanged="OnConfigurationChanged" /> diff --git a/Client/Pages/Index.razor.cs b/Client/Pages/Index.razor.cs index df89fad..81bf0a7 100644 --- a/Client/Pages/Index.razor.cs +++ b/Client/Pages/Index.razor.cs @@ -320,5 +320,35 @@ namespace ShiftScheduler.Client.Pages Shifts = await HttpClient.GetFromJsonAsync>("api/shift/shifts") ?? new(); StateHasChanged(); } + + // Helper method to group days by week for desktop calendar view + // Each week starts with Monday and ends with Sunday + private List> GetWeeksInMonth() + { + var days = SelectedDate.DaysInMonth(); + var weeks = new List>(); + var currentWeek = new List(); + + foreach (var day in days) + { + // Start a new week if this is Monday and we have days in current week + if (day.DayOfWeek == DayOfWeek.Monday && currentWeek.Count > 0) + { + weeks.Add(currentWeek); + currentWeek = new List(); + } + + // Add the day to current week + currentWeek.Add(day); + } + + // Add any remaining days as the last week + if (currentWeek.Count > 0) + { + weeks.Add(currentWeek); + } + + return weeks; + } } } diff --git a/Client/Pages/Index.razor.css b/Client/Pages/Index.razor.css index 9a7d49d..09147ad 100644 --- a/Client/Pages/Index.razor.css +++ b/Client/Pages/Index.razor.css @@ -6,6 +6,26 @@ margin-bottom: 1rem; flex-wrap: wrap; gap: 1rem; + /* Make buttons scrollable instead of fixed */ + position: static; + overflow: visible; +} + +/* Mobile top navigation - stack vertically */ +@media (max-width: 768px) { + .top-nav-buttons { + flex-direction: column; + align-items: stretch; + gap: 0.5rem; + } + + .month-selection { + justify-content: center; + } + + .action-buttons { + justify-content: center; + } } /* Month selection buttons */ @@ -75,11 +95,43 @@ } /* Calendar container */ +.calendar-container { + margin-top: 1rem; +} + .calendar-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; - margin-top: 1rem; +} + +/* Desktop calendar grid - week-based layout with 7 columns max */ +.desktop-calendar { + grid-template-columns: repeat(7, 1fr); +} + +/* Mobile calendar grid - single column */ +.mobile-calendar { + grid-template-columns: 1fr; +} + +/* Show desktop calendar only on larger screens */ +@media (min-width: 769px) { + .desktop-calendar { + display: grid; + } + .mobile-calendar { + display: none; + } +} + +/* Show mobile calendar only on smaller screens */ +@media (max-width: 768px) { + .desktop-calendar { + display: none; + } + .mobile-calendar { + display: grid; + } } /* Each day cell */ @@ -91,6 +143,14 @@ box-shadow: 0 2px 4px rgba(0,0,0,0.1); } +/* Mobile day cell adjustments */ +@media (max-width: 768px) { + .day-cell { + padding: 0.75rem; + margin-bottom: 0.5rem; + } +} + /* Day number */ .day-header { font-weight: bold; @@ -102,11 +162,25 @@ /* Shift buttons container */ .shifts { display: grid; - grid-template-columns: repeat(3, 1fr); gap: 0.5rem; margin-bottom: 0.5rem; } +/* Desktop shift buttons - 3 columns */ +@media (min-width: 769px) { + .shifts { + grid-template-columns: repeat(3, 1fr); + } +} + +/* Mobile shift buttons - single row */ +@media (max-width: 768px) { + .shifts { + grid-template-columns: repeat(auto-fit, minmax(60px, 1fr)); + gap: 0.25rem; + } +} + /* Individual shift buttons */ .shift-button { border: 2px solid #ddd; @@ -123,6 +197,15 @@ justify-content: center; } +/* Mobile shift button adjustments */ +@media (max-width: 768px) { + .shift-button { + min-height: 2rem; + font-size: 1rem; + padding: 0.4rem; + } +} + .shift-button:hover { background-color: #f8f9fa; border-color: #007bff; diff --git a/Client/Pages/MonthAndYear.cs b/Client/Pages/MonthAndYear.cs index 0d76c99..6fe1996 100644 --- a/Client/Pages/MonthAndYear.cs +++ b/Client/Pages/MonthAndYear.cs @@ -1,8 +1,11 @@ -namespace ShiftScheduler.Client.Pages; +using System.Globalization; + +namespace ShiftScheduler.Client.Pages; public record MonthAndYear(int Month, int Year) { - public static MonthAndYear Current() => new MonthAndYear(DateTime.Now.Month, DateTime.Now.Year); + public static MonthAndYear Current() => new (DateTime.Now.Month, DateTime.Now.Year); + public static MonthAndYear Next() { var today = DateTime.Today; @@ -10,13 +13,27 @@ public record MonthAndYear(int Month, int Year) var year = today.Month == 12 ? today.Year + 1 : today.Year; return new MonthAndYear(nextMonth, year); } + + public static string CurrentMonthName => Current().ToDateTime.ToString("MMMM"); + public static string NextMonthName => Next().ToDateTime.ToString("MMMM"); - public string Title => new DateTime(Year, Month, 1).ToString("MMMM yyyy"); + public string Title => ToDateTime.ToString("MMMM yyyy"); + private DateTime ToDateTime => new DateTime(Year, Month, 1); + public IReadOnlyList DaysInMonth() { return Enumerable.Range(1, DateTime.DaysInMonth(Year, Month)) .Select(d => new DateTime(Year, Month, d)) .ToList(); } + + public IReadOnlyDictionary> GetWeeksInMonth() + { + var days = DaysInMonth(); + var weeks = days + .GroupBy(d => CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(d, CalendarWeekRule.FirstDay, DayOfWeek.Monday)) + .ToDictionary(d => d.Key, d => d.ToList()); + return weeks; + } } \ No newline at end of file