Skip to content

Commit

Permalink
Store activities in local storage
Browse files Browse the repository at this point in the history
  • Loading branch information
Keller253 committed Feb 14, 2024
1 parent 12dfa73 commit b2d1caa
Show file tree
Hide file tree
Showing 11 changed files with 301 additions and 83 deletions.
1 change: 1 addition & 0 deletions src/CyclingApp/CyclingApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

<ItemGroup>
<PackageReference Include="Blazor.Geolocation" Version="8.0.0" />
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="Geolocation" Version="1.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.1" PrivateAssets="all" />
Expand Down
68 changes: 68 additions & 0 deletions src/CyclingApp/DTOs/ConvertExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using CyclingApp.Models;

namespace CyclingApp.DTOs;

/// <summary>
/// Contains convert extensions for DTOs.
/// </summary>
internal static class ConvertExtensions
{
/// <summary>
/// Create a <see cref="GeoLocation"/> model from the DTO.
/// </summary>
/// <param name="dto">The DTO.</param>
/// <returns>The created model.</returns>
public static GeoLocation ToModel(this StoreGeoLocationDto dto)
{
return new GeoLocation(dto.Timestamp, dto.Longitude, dto.Latitude, dto.Accuracy, dto.Altitude,
dto.AltitudeAccuracy, dto.Heading, dto.Speed);
}

/// <summary>
/// Create a <see cref="StoreGeoLocationDto"/> from the model.
/// </summary>
/// <param name="geoLocation">The model.</param>
/// <returns>THe created DTO.</returns>
public static StoreGeoLocationDto ToDto(this GeoLocation geoLocation)
{
return new StoreGeoLocationDto
{
Longitude = geoLocation.Longitude,
Latitude = geoLocation.Latitude,
Accuracy = geoLocation.Accuracy,
Altitude = geoLocation.Altitude,
AltitudeAccuracy = geoLocation.AltitudeAccuracy,
Heading = geoLocation.Heading,
Speed = geoLocation.Speed,
Timestamp = geoLocation.Timestamp,
};
}

/// <summary>
/// Create a <see cref="GeoLocation"/> model from the DTO.
/// </summary>
/// <param name="dto">The DTO.</param>
/// <param name="id">The id of the activity to create.</param>
/// <returns>The created model.</returns>
public static Activity ToModel(this StoreActivityDto dto, Guid id)
{
var waypoints = dto.Route.Select(x => x.ToModel()).ToList();
var route = new ReadOnlyRoute(waypoints);
return new Activity(id, dto.CreationTime, dto.Duration, route);
}

/// <summary>
/// Create a <see cref="StoreActivityDto"/> from the model.
/// </summary>
/// <param name="activity">The model.</param>
/// <returns>THe created DTO.</returns>
public static StoreActivityDto ToDto(this Activity activity)
{
return new StoreActivityDto
{
CreationTime = activity.CreationTime,
Duration = activity.Duration,
Route = activity.Route.Waypoints.Select(x => x.ToDto()).ToArray()
};
}
}
18 changes: 18 additions & 0 deletions src/CyclingApp/DTOs/StoreActivityDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using CyclingApp.Models;

namespace CyclingApp.DTOs;

/// <summary>
/// DTO to store an <see cref="Activity"/>.
/// </summary>
internal class StoreActivityDto
{
/// <inheritdoc cref="Activity.CreationTime"/>
public DateTime CreationTime { get; set; }

/// <inheritdoc cref="Activity.Duration"/>
public TimeSpan Duration { get; set; }

/// <inheritdoc cref="Activity.Route"/>
public StoreGeoLocationDto[] Route { get; set; } = [];
}
33 changes: 33 additions & 0 deletions src/CyclingApp/DTOs/StoreGeoLocationDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using CyclingApp.Models;

namespace CyclingApp.DTOs;

/// <summary>
/// DTO to store a <see cref="GeoLocation"/>.
/// </summary>
internal class StoreGeoLocationDto
{
/// <inheritdoc cref="GeoLocation.Longitude"/>
public double Longitude { get; set; }

/// <inheritdoc cref="GeoLocation.Latitude"/>
public double Latitude { get; set; }

/// <inheritdoc cref="GeoLocation.Accuracy"/>
public double Accuracy { get; set; }

/// <inheritdoc cref="GeoLocation.Altitude"/>
public double? Altitude { get; set; }

/// <inheritdoc cref="GeoLocation.AltitudeAccuracy"/>
public double? AltitudeAccuracy { get; set; }

/// <inheritdoc cref="GeoLocation.Heading"/>
public double? Heading { get; set; }

/// <inheritdoc cref="GeoLocation.Speed"/>
public double? Speed { get; set; }

/// <inheritdoc cref="GeoLocation.Timestamp"/>
public DateTime Timestamp { get; set; }
}
11 changes: 9 additions & 2 deletions src/CyclingApp/Pages/Activity.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ public partial class Activity
protected NavigationManager NavigationManager { get; set; } = default!;

/// <inheritdoc/>
protected override void OnParametersSet()
protected override async Task OnParametersSetAsync()
{
_activity = ActivityService.Activities.FirstOrDefault(x => x.Id == Id);
try
{
_activity = await ActivityService.GetActivityAsync(Id);
}
catch (Exception)
{
NavigateToHome();
}
}

private void NavigateToHome()
Expand Down
36 changes: 19 additions & 17 deletions src/CyclingApp/Pages/Home.razor
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,27 @@
<MudText Typo="Typo.h3">Enjoy Your Biking</MudText>
</div>
<div Style="height: 100%;" />
@if (ActivityService.Activities.Any())
@if (_activities.Any())
{
<MudText Typo="Typo.h4">Recent</MudText>
<MudStack Spacing="4" Class="overflow-auto">
@foreach (var activity in ActivityService.Activities)
{
<div @onclick="() => NavigateToActivity(activity.Id)" style="cursor: pointer;">
<MudPaper Class="pa-4">
<MudStack Spacing="2">
<MudText Typo="Typo.h4">@activity.CreationTime.ToString("ddd, dd.MM.yy")</MudText>
<MudStack Row="true" Class="d-flex justify-space-between flex-grow-1">
<MudText>@($"{(activity.Route.Distance / 1000):N2} km")</MudText>
<MudText>@activity.Duration.ToString("hh\\:mm\\:ss")</MudText>
<MudStack Style="height: 100%;" Class="pa-4" Spacing="4">
<MudText Typo="Typo.h4">Recent</MudText>
<MudStack Spacing="4" Class="overflow-auto">
@foreach (var activity in _activities)
{
<div @onclick="() => NavigateToActivity(activity.Id)" style="cursor: pointer;">
<MudPaper Class="pa-4">
<MudStack Spacing="2">
<MudText Typo="Typo.h4">@activity.CreationTime.ToString("ddd, dd.MM.yy")</MudText>
<MudStack Row="true" Class="d-flex justify-space-between flex-grow-1">
<MudText>@($"{(activity.Route.Distance / 1000):N2} km")</MudText>
<MudText>@activity.Duration.ToString("hh\\:mm\\:ss")</MudText>
</MudStack>
</MudStack>
</MudStack>
</MudPaper>
</div>
}
</MudStack>
</MudPaper>
</div>
}
</MudStack>
</MudStack>
}
<MudButton Variant="Variant.Filled" FullWidth="true" Class="pa-8" Size="@Size.Large" Color="Color.Primary" OnClick="@NavigateToTracker">
<MudStack Row="true" Spacing="4">
Expand Down
11 changes: 11 additions & 0 deletions src/CyclingApp/Pages/Home.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public partial class Home
/// </summary>
public const string Route = "/";

private readonly List<Models.Activity> _activities = [];

/// <summary>
/// Service to get an activity.
/// </summary>
Expand All @@ -25,6 +27,15 @@ public partial class Home
[Inject]
protected NavigationManager NavigationManager { get; set; } = default!;

/// <inheritdoc/>
protected override async Task OnInitializedAsync()
{
await foreach (var activity in ActivityService.GetActivitiesAsync())
{
_activities.Add(activity);
}
}

private void NavigateToTracker()
{
NavigationManager.NavigateTo(Tracker.Route);
Expand Down
9 changes: 6 additions & 3 deletions src/CyclingApp/Pages/Tracker.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,12 @@ private void Stop()

//_ = ScreenWakeLockService.RequestWakeLockAsync();

var route = new ReadOnlyRoute(_route.Waypoints);
var activity = ActivityService.CreateActivity(_creationTime, _stopWatch.Elapsed, route);
NavigationManager.NavigateTo($"{Activity.Route}/{activity.Id}");
_ = Task.Run(async () =>
{
var route = new ReadOnlyRoute(_route.Waypoints);
var activity = await ActivityService.CreateActivityAsync(_creationTime, _stopWatch.Elapsed, route);
NavigationManager.NavigateTo($"{Activity.Route}/{activity.Id}");
});
}

private void WatchStopWatch(object? state)
Expand Down
10 changes: 7 additions & 3 deletions src/CyclingApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Blazored.LocalStorage;
using CyclingApp.Services;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
Expand All @@ -16,14 +17,17 @@ public static async Task Main(string[] args)
// MudBlazor
_ = builder.Services.AddMudServices();

// Blazor.Geolocation
// Geolocation Api
_ = builder.Services.AddGeolocationServices();

// Blazor.ScreenWakeLock
// Screen Wake Lock Api
_ = builder.Services.AddScreenWakeLockServices();

// Local Storage Api
_ = builder.Services.AddBlazoredLocalStorage();

// Services
_ = builder.Services.AddSingleton<IActivityService, ActivityService>();
_ = builder.Services.AddTransient<IActivityService, ActivityService>();

// HttpClient
_ = builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
Expand Down
Loading

0 comments on commit b2d1caa

Please sign in to comment.