From a30ed1e3f7562021f85bac90434d9f1b3a3d7eaa Mon Sep 17 00:00:00 2001 From: Imanol Uriarte Date: Thu, 9 Apr 2026 20:00:01 +0200 Subject: [PATCH 1/2] Preserve filter state after shift signup redirect --- .../Controllers/ShiftsController.cs | 25 ++++++++++++++----- src/Humans.Web/Views/Shifts/Index.cshtml | 10 ++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Humans.Web/Controllers/ShiftsController.cs b/src/Humans.Web/Controllers/ShiftsController.cs index f46c3216d..28a500365 100644 --- a/src/Humans.Web/Controllers/ShiftsController.cs +++ b/src/Humans.Web/Controllers/ShiftsController.cs @@ -188,7 +188,7 @@ public async Task Index(Guid? departmentId, string? fromDate, str [HttpPost("SignUp")] [ValidateAntiForgeryToken] - public async Task SignUp(Guid shiftId) + public async Task SignUp(Guid shiftId, Guid? departmentId, string? fromDate, string? toDate, string? period, [FromForm(Name = "tags")] List? tagIds) { var (currentUserNotFound, user) = await ResolveCurrentUserOrChallengeAsync(); if (currentUserNotFound is not null) @@ -202,19 +202,19 @@ public async Task SignUp(Guid shiftId) if (!result.Success) { SetError(result.Error ?? "Shift signup failed."); - return RedirectToAction(nameof(Index)); + return RedirectToAction(nameof(Index), BuildFilterRouteValues(departmentId, fromDate, toDate, period, tagIds)); } SetSuccess(result.Warning is not null ? $"Signed up successfully. Note: {result.Warning}" : "Signed up successfully!"); - return RedirectToAction(nameof(Index)); + return RedirectToAction(nameof(Index), BuildFilterRouteValues(departmentId, fromDate, toDate, period, tagIds)); } [HttpPost("SignUpRange")] [ValidateAntiForgeryToken] - public async Task SignUpRange(Guid rotaId, int startDayOffset, int endDayOffset) + public async Task SignUpRange(Guid rotaId, int startDayOffset, int endDayOffset, Guid? departmentId, string? fromDate, string? toDate, string? period, [FromForm(Name = "tags")] List? tagIds) { var (currentUserNotFound, user) = await ResolveCurrentUserOrChallengeAsync(); if (currentUserNotFound is not null) @@ -228,14 +228,27 @@ public async Task SignUpRange(Guid rotaId, int startDayOffset, in if (!result.Success) { SetError(result.Error ?? "Shift range signup failed."); - return RedirectToAction(nameof(Index)); + return RedirectToAction(nameof(Index), BuildFilterRouteValues(departmentId, fromDate, toDate, period, tagIds)); } SetSuccess(result.Warning is not null ? $"Signed up for date range. Note: {result.Warning}" : "Signed up for date range!"); - return RedirectToAction(nameof(Index)); + return RedirectToAction(nameof(Index), BuildFilterRouteValues(departmentId, fromDate, toDate, period, tagIds)); + } + + private static RouteValueDictionary BuildFilterRouteValues(Guid? departmentId, string? fromDate, string? toDate, string? period, List? tagIds) + { + var rv = new RouteValueDictionary(); + if (departmentId.HasValue) rv["departmentId"] = departmentId.Value; + if (!string.IsNullOrEmpty(fromDate)) rv["fromDate"] = fromDate; + if (!string.IsNullOrEmpty(toDate)) rv["toDate"] = toDate; + if (!string.IsNullOrEmpty(period)) rv["period"] = period; + if (tagIds is { Count: > 0 }) + for (var i = 0; i < tagIds.Count; i++) + rv[$"tags[{i}]"] = tagIds[i]; + return rv; } [HttpPost("BailRange")] diff --git a/src/Humans.Web/Views/Shifts/Index.cshtml b/src/Humans.Web/Views/Shifts/Index.cshtml index 83755c5ed..6f14ca31d 100644 --- a/src/Humans.Web/Views/Shifts/Index.cshtml +++ b/src/Humans.Web/Views/Shifts/Index.cshtml @@ -280,6 +280,11 @@
@Html.AntiForgeryToken() + @if (Model.FilterDepartmentId.HasValue) { } + @if (!string.IsNullOrEmpty(Model.FilterFromDate)) { } + @if (!string.IsNullOrEmpty(Model.FilterToDate)) { } + @if (!string.IsNullOrEmpty(Model.FilterPeriod)) { } + @foreach (var tagId in Model.FilterTagIds) { }
+ @if (Model.FilterDepartmentId.HasValue) { } + @if (!string.IsNullOrEmpty(Model.FilterFromDate)) { } + @if (!string.IsNullOrEmpty(Model.FilterToDate)) { } + @if (!string.IsNullOrEmpty(Model.FilterPeriod)) { } + @foreach (var tagId in Model.FilterTagIds) { } } From 3862a68af52d072e15f74b7ba7905b70dd578f91 Mon Sep 17 00:00:00 2001 From: Imanol Uriarte Date: Fri, 10 Apr 2026 13:02:53 +0200 Subject: [PATCH 2/2] Preserve filter state after shift signup redirect; fix coordinator notification link --- src/Humans.Infrastructure/Services/ShiftSignupService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Humans.Infrastructure/Services/ShiftSignupService.cs b/src/Humans.Infrastructure/Services/ShiftSignupService.cs index 3cb19c93d..098386894 100644 --- a/src/Humans.Infrastructure/Services/ShiftSignupService.cs +++ b/src/Humans.Infrastructure/Services/ShiftSignupService.cs @@ -992,7 +992,7 @@ await _notificationService.SendAsync( $"Coverage gap: {shift.Rota.Name} day {shift.DayOffset}", coordinatorIds, body: $"Only {confirmedCount}/{shift.MinVolunteers} volunteers confirmed.", - actionUrl: $"/Shifts?departmentId={teamId}", + actionUrl: $"/Shifts/Dashboard?departmentId={teamId}", actionLabel: "Find cover \u2192"); } catch (Exception ex) @@ -1037,7 +1037,7 @@ await _notificationService.SendAsync( $"Shift signup change: {rotaName}", coordinatorIds, body: enrichedDescription, - actionUrl: $"/Shifts?departmentId={teamId}", + actionUrl: $"/Shifts/Dashboard?departmentId={teamId}", actionLabel: "View \u2192"); } catch (Exception ex)