Implement localStorage persistence for shift selections (#6)

* Initial plan

* Fix .NET framework version compatibility from 9.0 to 8.0

Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com>

* Implement localStorage persistence for shift selections

Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com>

* Restore .NET 9.0 version and update Index.razor.cs per feedback

Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com>

* Fix compilation error by making EditMonth and EditYear instance variables

Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com>

* Minor changes

---------

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 <c.schaad@pog.ch>
This commit is contained in:
Copilot 2025-08-18 19:40:52 +02:00 committed by GitHub
parent 0aebab3d38
commit 76a1531729
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 57 additions and 7 deletions

View file

@ -1,26 +1,34 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using ShiftScheduler.Shared.Models; using ShiftScheduler.Shared.Models;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text.Json;
namespace ShiftScheduler.Client.Pages namespace ShiftScheduler.Client.Pages
{ {
public partial class Index : ComponentBase public partial class Index : ComponentBase
{ {
[Inject] private HttpClient HttpClient { get; set; } = default!; [Inject] private HttpClient HttpClient { get; set; } = default!;
[Inject] private IJSRuntime JSRuntime { get; set; } = default!;
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
private List<DateTime> DaysInMonth { get; set; } = new(); private List<DateTime> DaysInMonth { get; set; } = new();
private List<Shift> Shifts { get; set; } = new(); private List<Shift> Shifts { get; set; } = new();
private Dictionary<DateTime, string> SelectedSchedule { get; set; } = new(); private Dictionary<DateTime, string> SelectedSchedule { get; set; } = new();
private int EditMonth { get; set; }
private int EditYear { get; set; }
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
var (nextMonth, year) = GetNextMonthAndYear(); (EditMonth, EditYear) = GetNextMonthAndYear();
DaysInMonth = Enumerable.Range(1, DateTime.DaysInMonth(year, nextMonth)) DaysInMonth = Enumerable.Range(1, DateTime.DaysInMonth(EditYear, EditMonth))
.Select(d => new DateTime(year, nextMonth, d)) .Select(d => new DateTime(EditYear, EditMonth, d))
.ToList(); .ToList();
Shifts = await HttpClient.GetFromJsonAsync<List<Shift>>("api/shift/shifts") ?? new(); Shifts = await HttpClient.GetFromJsonAsync<List<Shift>>("api/shift/shifts") ?? new();
await LoadScheduleFromStorage();
} }
private (int nextMonth, int year) GetNextMonthAndYear() private (int nextMonth, int year) GetNextMonthAndYear()
@ -31,9 +39,10 @@ namespace ShiftScheduler.Client.Pages
return (nextMonth, year); return (nextMonth, year);
} }
private void SelectShift(DateTime day, string shiftName) private async Task SelectShift(DateTime day, string shiftName)
{ {
SelectedSchedule[day] = shiftName; SelectedSchedule[day] = shiftName;
await SaveScheduleToStorage();
} }
private async Task ExportToIcs() private async Task ExportToIcs()
@ -54,6 +63,49 @@ namespace ShiftScheduler.Client.Pages
NavigationManager.NavigateTo(fileUrl, true); NavigationManager.NavigateTo(fileUrl, true);
} }
[Inject] private NavigationManager NavigationManager { get; set; } = default!; private async Task SaveScheduleToStorage()
{
try
{
var storageKey = $"ShiftSchedule_{EditYear}_{EditMonth:D2}";
var serializableSchedule = SelectedSchedule.ToDictionary(
kvp => kvp.Key.ToString("yyyy-MM-dd"),
kvp => kvp.Value
);
var json = JsonSerializer.Serialize(serializableSchedule);
await JSRuntime.InvokeVoidAsync("localStorage.setItem", storageKey, json);
}
catch (Exception)
{
// ignored
}
}
private async Task LoadScheduleFromStorage()
{
try
{
var storageKey = $"ShiftSchedule_{EditYear}_{EditMonth:D2}";
var json = await JSRuntime.InvokeAsync<string>("localStorage.getItem", storageKey);
if (!string.IsNullOrEmpty(json))
{
var serializableSchedule = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
if (serializableSchedule != null)
{
SelectedSchedule = serializableSchedule.ToDictionary(
kvp => DateTime.Parse(kvp.Key),
kvp => kvp.Value
);
}
}
}
catch (Exception)
{
SelectedSchedule = new Dictionary<DateTime, string>();
}
}
} }
} }

View file

@ -27,8 +27,6 @@
<a class="dismiss">🗙</a> <a class="dismiss">🗙</a>
</div> </div>
<script src="_framework/blazor.webassembly.js"></script> <script src="_framework/blazor.webassembly.js"></script>
<script src="download.js"></script>
</body> </body>
</html> </html>