diff --git a/Timely/Components/TimeRecord.razor b/Timely/Components/TimeRecord.razor index 95197de..a03419c 100644 --- a/Timely/Components/TimeRecord.razor +++ b/Timely/Components/TimeRecord.razor @@ -1,29 +1,41 @@ @using Timely.Models @using Humanizer +@using Microsoft.EntityFrameworkCore +@using Timely.Services.Data - @Shift.ShiftStart.ToString("dd") - @Shift.ShiftStart.ToString("MMMM") + @Shift.Date.ToString("dd") + @Shift.Date.ToString("MMMM") - @((Shift.ShiftEnd - Shift.ShiftStart).ToString("hh\\:mm\\:ss")) Shift + @((Shift.ShiftEnd.Value - Shift.ShiftStart.Value).ToString("hh\\:mm\\:ss")) Shift - @Shift.ShiftStart.ToString("t") + @((DateTime.Today + Shift.ShiftStart.Value).ToString("t")) - - @Shift.ShiftEnd.ToString("t") + @((DateTime.Today + Shift.ShiftEnd.Value).ToString("t")) + + @code { [Parameter] public Shift Shift { get; set; } + + private async Task Delete() + { + await using var db = new AppDbContext(); + await db.Shifts.Where(shift => shift.Id == Shift.Id).ExecuteDeleteAsync(); + await db.SaveToCacheAsync(); + } + } \ No newline at end of file diff --git a/Timely/Layout/AddRecordDialog.razor b/Timely/Layout/AddRecordDialog.razor new file mode 100644 index 0000000..9c21065 --- /dev/null +++ b/Timely/Layout/AddRecordDialog.razor @@ -0,0 +1,38 @@ +@using Timely.Models + + + + + Add Record + + + + + + + + + Cancel + Add + + + +@code { + + private DateTime? _date = DateTime.Today; + + [CascadingParameter] MudDialogInstance MudDialog { get; set; } + [Parameter] public Shift Shift { get; set; } = new(); + + private void Cancel() + { + MudDialog.Cancel(); + } + + private void AddRecord() + { + Shift.Date = _date is not null ? DateTime.Today : _date!.Value; + MudDialog.Close(DialogResult.Ok(Shift)); + } + +} \ No newline at end of file diff --git a/Timely/Models/Shift.cs b/Timely/Models/Shift.cs index cfd16ed..2bed8a4 100644 --- a/Timely/Models/Shift.cs +++ b/Timely/Models/Shift.cs @@ -2,6 +2,9 @@ public record Shift { - public DateTime ShiftStart { get; set; } - public DateTime ShiftEnd { get; set; } + public int Id { get; set; } + public DateTime Date { get; set; } + public TimeSpan? ShiftStart { get; set; } + public TimeSpan? ShiftEnd { get; set; } + public bool Active { get; set; } } \ No newline at end of file diff --git a/Timely/Pages/Home.razor b/Timely/Pages/Home.razor index 662b8d3..ef09899 100644 --- a/Timely/Pages/Home.razor +++ b/Timely/Pages/Home.razor @@ -12,7 +12,7 @@ @_currentTime.ToString("dddd, MMMM dd - hh\\:mm\\:ss tt") - @((DateTime.Now - _currentShift.ShiftStart).ToString(@"hh\:mm\:ss")) + @((DateTime.Now - _currentShift.ShiftStart.Value).ToString(@"hh\:mm\:ss")) Shift Ongoing @@ -64,8 +64,8 @@ @($"{_timeLogged.Value.TotalHours:0.00} Hours") - - Clear Records + + Add Record } @@ -77,11 +77,17 @@ { } + + Clear Records + } else { + + Add Record +
No data recorded.
@@ -107,7 +113,7 @@ private DateTime _currentTime = DateTime.Now; private TimeSpan? _timeLogged; - private LinkedList? _timeRecords = new(); + private IEnumerable? _timeRecords; protected override async Task OnInitializedAsync() { @@ -118,7 +124,7 @@ { _currentShift = new Shift { - ShiftStart = DateTime.Now + ShiftStart = DateTime.Now.TimeOfDay }; await ShiftManager.StartShift(); @@ -135,6 +141,21 @@ Snackbar.Add("Shift ended, record saved"); } + async Task AddRecord() + { + var dialog = await DialogService.ShowAsync("Add Record"); + var result = await dialog.Result; + + if (result.Canceled) + { + return; + } + + if (result.Data is not Shift shift) return; + + await ShiftManager.AddTimeRecord(shift); + } + async Task ClearRecords() { var result = await DialogService.ShowMessageBox("Clear Time Records", "This action cannot be undone, continue?"); @@ -145,7 +166,6 @@ } await ShiftManager.ClearTimeRecords(); - await ShiftManager.GetDataFromLocalStorage(); _timeRecords = await ShiftManager.GetTimeRecords(); Snackbar.Add("Time records cleared"); } @@ -154,8 +174,6 @@ { _currentTime = DateTime.Now; - await ShiftManager.GetDataFromLocalStorage(); - _timeRecords = await ShiftManager.GetTimeRecords(); _currentShift = await ShiftManager.GetCurrentShift(); @@ -167,8 +185,8 @@ if (_timeRecords is not null && _timeRecords.Any()) { var totalTimeRecordTicks = _timeRecords.Select( - timeRecord => new TimeSpan(timeRecord.ShiftEnd.Ticks - timeRecord.ShiftStart.Ticks)) - .Sum(timeSpans => timeSpans.Ticks); + timeRecord => timeRecord.ShiftEnd - timeRecord.ShiftStart) + .Sum(timerecord => timerecord.Value.Ticks); _timeLogged = new TimeSpan(totalTimeRecordTicks); } diff --git a/Timely/Program.cs b/Timely/Program.cs index 6f8e711..37476d6 100644 --- a/Timely/Program.cs +++ b/Timely/Program.cs @@ -1,3 +1,4 @@ +using BlazorDB; using Blazored.LocalStorage; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; @@ -19,4 +20,8 @@ // App Services builder.Services.AddScoped(); -await builder.Build().RunAsync(); +var app = builder.Build(); + +await app.Services.ConfigureBlazorDBAsync(); + +await app.RunAsync(); diff --git a/Timely/Services/Data/AppDbContext.cs b/Timely/Services/Data/AppDbContext.cs new file mode 100644 index 0000000..f9ee89e --- /dev/null +++ b/Timely/Services/Data/AppDbContext.cs @@ -0,0 +1,10 @@ +using BlazorDB; +using Microsoft.EntityFrameworkCore; +using Timely.Models; + +namespace Timely.Services.Data; + +public class AppDbContext : BlazorDBContext +{ + public DbSet Shifts { get; set; } +} \ No newline at end of file diff --git a/Timely/Services/Data/ShiftManager.cs b/Timely/Services/Data/ShiftManager.cs index 332b923..7ce8c71 100644 --- a/Timely/Services/Data/ShiftManager.cs +++ b/Timely/Services/Data/ShiftManager.cs @@ -1,75 +1,97 @@ using Blazored.LocalStorage; +using Microsoft.EntityFrameworkCore; using Timely.Models; namespace Timely.Services.Data; public class ShiftManager { - private Shift? _currentShift; - private LinkedList? _timeRecords; - private ILocalStorageService _localStorage; - - public ShiftManager(ILocalStorageService localStorage) - { - _localStorage = localStorage; - _timeRecords = new LinkedList(); - } - - public async Task GetDataFromLocalStorage() - { - _currentShift = await _localStorage.GetItemAsync("current-shift"); - - var timeRecords = await _localStorage.GetItemAsync?>("time-records"); - _timeRecords = timeRecords ?? new LinkedList(Enumerable.Empty()); - - await UpdateTimeRecords(); - } + private Shift? _activeShift; - public async Task UpdateTimeRecords() + public ShiftManager() { - await _localStorage.SetItemAsync("time-records", _timeRecords); + using var db = new AppDbContext(); + db.Database.EnsureCreated(); } public async Task AddTimeRecord(Shift shift) { - _timeRecords.AddFirst(shift); - await UpdateTimeRecords(); - await GetDataFromLocalStorage(); + await using var db = new AppDbContext(); + await db.Shifts.AddAsync(shift); + await db.SaveToCacheAsync(); } - public async Task?> GetTimeRecords() + public async Task?> GetTimeRecords() { - return await _localStorage.GetItemAsync?>("time-records"); + await using var db = new AppDbContext(); + return await db.Shifts.Where(shift => !shift.Active).ToListAsync(); } public async Task ClearTimeRecords() { - await _localStorage.RemoveItemAsync("time-records"); - await GetDataFromLocalStorage(); + await using var db = new AppDbContext(); + await db.Shifts.AsQueryable().ExecuteDeleteAsync(); + await db.SaveToCacheAsync(); } public async Task GetCurrentShift() { - return await _localStorage.GetItemAsync("current-shift"); + if (_activeShift is not null) return _activeShift; + + await using var db = new AppDbContext(); + _activeShift = await db.Shifts.FirstOrDefaultAsync(shift => shift.Active); + + return _activeShift; + } + + public async Task AddShift(TimeSpan start, TimeSpan end, DateTime? date = null) + { + + var shift = new Shift() + { + ShiftStart = start, + ShiftEnd = end, + Date = date ?? DateTime.Today + }; + + await using var db = new AppDbContext(); + await db.Shifts.AddAsync(shift); + await db.SaveToCacheAsync(); + } public async Task StartShift() { - _currentShift ??= new Shift() + if (_activeShift is not null) return; + + var shift = new Shift() { - ShiftStart = DateTime.Now + Date = DateTime.Today, + ShiftStart = DateTime.Now.TimeOfDay, + Active = true }; - await _localStorage.SetItemAsync("current-shift",_currentShift); + await using var db = new AppDbContext(); + var entry = await db.Shifts.AddAsync(shift); + await db.SaveToCacheAsync(); + + _activeShift = entry.Entity; + } public async Task EndShift() { - _currentShift.ShiftEnd = DateTime.Now; + await GetCurrentShift(); + + await using var db = new AppDbContext(); + if (_activeShift is null) return; + + _activeShift.Active = false; + _activeShift.ShiftEnd = DateTime.Now.TimeOfDay; - await AddTimeRecord(_currentShift); + db.Shifts.Update(_activeShift); + await db.SaveToCacheAsync(); - await _localStorage.RemoveItemAsync("current-shift"); - await GetDataFromLocalStorage(); + _activeShift = null; } } \ No newline at end of file diff --git a/Timely/Timely.csproj b/Timely/Timely.csproj index 1b544b9..08c0878 100644 --- a/Timely/Timely.csproj +++ b/Timely/Timely.csproj @@ -9,6 +9,7 @@ +