Added in Local Storage functionality to store products and cart items into the users local storage.

Cleaned up code and removed excess files.
This commit is contained in:
Kira 2022-09-16 16:06:57 -07:00
parent 4a358ede89
commit c4f54c70b6
15 changed files with 244 additions and 138 deletions

View File

@ -3,66 +3,60 @@
<h3>Checkout</h3>
@if (ShoppingCartItems.Count() == 0)
{
<h4 class="text-warning">You currently have no items in your shopping cart.</h4>
}
else
{
<div class="mb-5">
<div class="row">
<div class="col-md-6">
<h4 class="mb-2">Payment Method</h4>
<div id="smart-button-container">
<input type="hidden" name="descriptionInput" id="description" @bind="PaymentDescription" />
<input name="amountInput" type="hidden" id="amount" @bind="PaymentAmount" />
<div style="text-align: center; margin-top: 0.625rem;" id="paypal-button-container"></div>
</div>
<div class="mb-5">
<div class="row">
<div class="col-md-6">
<h4 class="mb-2">Payment Method</h4>
<div id="smart-button-container">
<input type="hidden" name="descriptionInput" id="description" @bind="PaymentDescription" />
<input name="amountInput" type="hidden" id="amount" @bind="PaymentAmount" />
<div style="text-align: center; margin-top: 0.625rem;" id="paypal-button-container"></div>
</div>
</div>
@if (ShoppingCartItems == null)
{
<div class="row d-flex justify-content-center">
<div class="col-md-1">
<DisplayCustomSpinner />
</div>
@if (ShoppingCartItems == null)
</div>
}
else
{
<div class="col-md-6">
<h4 class="mb-2">Payment Summary</h4>
@if (ShoppingCartItems.Count() > 0)
{
<div class="row d-flex justify-content-center">
<div class="col-md-1">
<DisplayCustomSpinner />
</div>
</div>
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
</thead>
<tbody>
@foreach (var item in ShoppingCartItems)
{
<tr>
<td>@item.Quantity x @item.ProductName</td>
<td>@item.TotalPrice.ToString("C")</td>
</tr>
}
<tr>
<td><b>Total</b></td>
<td><b>@PaymentAmount.ToString("C")</b></td>
</tr>
</tbody>
</table>
}
else
{
<div class="col-md-6">
<h4 class="mb-2">Payment Summary</h4>
@if (ShoppingCartItems.Count() > 0)
{
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
</thead>
<tbody>
@foreach (var item in ShoppingCartItems)
{
<tr>
<td>@item.Quantity x @item.ProductName</td>
<td>@item.TotalPrice.ToString("C")</td>
</tr>
}
<tr>
<td><b>Total</b></td>
<td><b>@PaymentAmount.ToString("C")</b></td>
</tr>
</tbody>
</table>
}
else
{
<p class="text-warning">You currently have no items in your shopping cart.</p>
}
</div>
<p class="text-warning">You currently have no items in your shopping cart.</p>
}
</div>
</div>
}
}
</div>
</div>

View File

@ -21,11 +21,14 @@ namespace ShopOnline.Web.Pages
[Inject]
public IShoppingCartService ShoppingCartService { get; set; }
[Inject]
public IManageCartItemsLocalStorageService ManageCartItemsLocalStorage { get; set; }
protected override async Task OnInitializedAsync()
{
try
{
ShoppingCartItems = await ShoppingCartService.GetItems(HardCoded.UserId);
ShoppingCartItems = await ManageCartItemsLocalStorage.GetCollection();
if(ShoppingCartItems != null)
{
@ -49,7 +52,6 @@ namespace ShopOnline.Web.Pages
{
if(firstRender)
{
Console.WriteLine("HIT");
await Js.InvokeVoidAsync("initPayPalButton");
}
}

View File

@ -2,7 +2,6 @@
@foreach (var item in Products)
{
Console.WriteLine(@item.Price);
<div class="col-md-3 mb-2">
<a href="/ProductDetails/@item.Id">
<div class="card">

View File

@ -1,57 +0,0 @@
@page "/fetchdata"
@inject HttpClient Http
<PageTitle>Weather forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}

View File

@ -13,16 +13,26 @@ namespace ShopOnline.Web.Pages
public IProductService ProductService { get; set; }
[Inject]
public IShoppingCartService ShoppingCartService { get; set; }
[Inject]
public IManageProductsLocalStorageService ManageProductsLocalStorageService { get; set; }
[Inject]
public IManageCartItemsLocalStorageService ManageCartItemsLocalStorageService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
public ProductDto Product { get; set; }
public string ErrorMessage { get; set; }
private List<CartItemDto> ShoppingCartItems { get; set; }
protected override async Task OnInitializedAsync()
{
try
{
Product = await ProductService.GetItem(Id);
ShoppingCartItems = await ManageCartItemsLocalStorageService.GetCollection();
Product = await GetProductById(Id);
}
catch(Exception ex)
{
@ -35,6 +45,13 @@ namespace ShopOnline.Web.Pages
try
{
var cartItemDto = await ShoppingCartService.AddItem(cartItemToAddDto);
if(cartItemDto != null)
{
ShoppingCartItems.Add(cartItemDto);
await ManageCartItemsLocalStorageService.SaveCollection(ShoppingCartItems);
}
NavigationManager.NavigateTo("/ShoppingCart");
}
catch (Exception)
@ -43,5 +60,15 @@ namespace ShopOnline.Web.Pages
}
}
private async Task<ProductDto> GetProductById(int id)
{
var productDtos = await ManageProductsLocalStorageService.GetCollection();
if(productDtos != null)
{
return productDtos.SingleOrDefault(p => p.Id == id);
}
return null;
}
}
}

View File

@ -13,6 +13,13 @@ namespace ShopOnline.Web.Pages
[Inject]
public IShoppingCartService ShoppingCartService { get; set; }
[Inject]
public IManageProductsLocalStorageService ManageProductsLocalStorageService { get; set; }
[Inject]
public IManageCartItemsLocalStorageService ManageCartItemsLocalStorageService { get; set; }
public IEnumerable<ProductDto> Products { get; set; }
[Inject]
@ -24,9 +31,11 @@ namespace ShopOnline.Web.Pages
{
try
{
Products = await ProductService.GetItems();
await ClearLocalStorage();
var shoppingCartItems = await ShoppingCartService.GetItems(HardCoded.UserId);
Products = await ManageProductsLocalStorageService.GetCollection();
var shoppingCartItems = await ManageCartItemsLocalStorageService.GetCollection();
var totalQuantity = shoppingCartItems.Sum(i => i.Quantity);
ShoppingCartService.RaiseEventOnShoppingCartChanged(totalQuantity);
@ -51,5 +60,11 @@ namespace ShopOnline.Web.Pages
return groupedProductDtos.FirstOrDefault(pg => pg.CategoryId == groupedProductDtos.Key).CategoryName;
}
private async Task ClearLocalStorage()
{
await ManageProductsLocalStorageService.RemoveCollection();
await ManageCartItemsLocalStorageService.RemoveCollection();
}
}
}

View File

@ -12,6 +12,12 @@ namespace ShopOnline.Web.Pages
[Inject]
public IProductService ProductService { get; set; }
[Inject]
public IManageProductsLocalStorageService ManageProductsLocalStorageService { get; set; }
[Inject]
public IEnumerable<ProductDto> Products { get; set; }
public string CategoryName { get; set; }
public string ErrorMessage { get; set; }
@ -20,7 +26,7 @@ namespace ShopOnline.Web.Pages
{
try
{
Products = await ProductService.GetItemsByCategory(CategoryId);
Products = await GetProductCollectionByCategoryId(CategoryId);
if(Products != null && Products.Count() > 0)
{
var productDto = Products.FirstOrDefault(p => p.CategoryId == CategoryId);
@ -35,5 +41,19 @@ namespace ShopOnline.Web.Pages
ErrorMessage = ex.Message;
}
}
private async Task<IEnumerable<ProductDto>> GetProductCollectionByCategoryId(int categoryId)
{
var productCollection = await ManageProductsLocalStorageService.GetCollection();
if(productCollection != null)
{
return productCollection.Where(p => p.CategoryId == categoryId);
}
else
{
return await ProductService.GetItemsByCategory(categoryId);
}
}
}
}

View File

@ -13,6 +13,9 @@ namespace ShopOnline.Web.Pages
[Inject]
public IShoppingCartService ShoppingCartService { get; set; }
[Inject]
public IManageCartItemsLocalStorageService ManageCartItemsLocalStorageService { get; set; }
public List<CartItemDto> ShoppingCartItems { get; set; }
public string ErrorMessage { get; set; }
@ -24,7 +27,7 @@ namespace ShopOnline.Web.Pages
{
try
{
ShoppingCartItems = await ShoppingCartService.GetItems(HardCoded.UserId);
ShoppingCartItems = await ManageCartItemsLocalStorageService.GetCollection();
CartChanged();
}
catch (Exception ex)
@ -56,7 +59,7 @@ namespace ShopOnline.Web.Pages
var returnedUpdateItemDto = await this.ShoppingCartService.UpdateQuantity(updateItemDto);
UpdateItemTotalPrice(returnedUpdateItemDto);
await UpdateItemTotalPrice(returnedUpdateItemDto);
CartChanged();
await MakeUpdateQuantityButtonVisible(id, false);
@ -90,7 +93,7 @@ namespace ShopOnline.Web.Pages
}
private void UpdateItemTotalPrice(CartItemDto cartItemDto)
private async Task UpdateItemTotalPrice(CartItemDto cartItemDto)
{
var item = GetCartItem(cartItemDto.Id);
@ -98,6 +101,8 @@ namespace ShopOnline.Web.Pages
{
item.TotalPrice = cartItemDto.Price * cartItemDto.Quantity;
}
await ManageCartItemsLocalStorageService.SaveCollection(ShoppingCartItems);
}
private void CalculateCartSummaryTotals()
@ -121,11 +126,13 @@ namespace ShopOnline.Web.Pages
return ShoppingCartItems.FirstOrDefault(i => i.Id == id);
}
private void RemoveCartItem(int id)
private async Task RemoveCartItem(int id)
{
var CartItemDto = GetCartItem(id);
ShoppingCartItems.Remove(CartItemDto);
await ManageCartItemsLocalStorageService.SaveCollection(ShoppingCartItems);
}
private void CartChanged()

View File

@ -1,3 +1,4 @@
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using ShopOnline.Web;
@ -12,4 +13,8 @@ builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("https:/
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddScoped<IShoppingCartService, ShoppingCartService>();
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddScoped<IManageProductsLocalStorageService, ManageProductsLocalStorageService>();
builder.Services.AddScoped<IManageCartItemsLocalStorageService, ManageCartItemsLocalStorageService>();
await builder.Build().RunAsync();

View File

@ -0,0 +1,11 @@
using ShopOnline.Models.Dtos;
namespace ShopOnline.Web.Services.Contracts
{
public interface IManageCartItemsLocalStorageService
{
Task<List<CartItemDto>> GetCollection();
Task SaveCollection(List<CartItemDto> cartItemDtos);
Task RemoveCollection();
}
}

View File

@ -0,0 +1,10 @@
using ShopOnline.Models.Dtos;
namespace ShopOnline.Web.Services.Contracts
{
public interface IManageProductsLocalStorageService
{
Task<IEnumerable<ProductDto>> GetCollection();
Task RemoveCollection();
}
}

View File

@ -0,0 +1,47 @@
using Blazored.LocalStorage;
using ShopOnline.Models.Dtos;
using ShopOnline.Web.Services.Contracts;
namespace ShopOnline.Web.Services
{
public class ManageCartItemsLocalStorageService : IManageCartItemsLocalStorageService
{
private readonly ILocalStorageService localStorageService;
private readonly IShoppingCartService shoppingCartService;
const string key = "CartItemCollection";
public ManageCartItemsLocalStorageService(ILocalStorageService localStorageService, IShoppingCartService shoppingCartService)
{
this.localStorageService = localStorageService;
this.shoppingCartService = shoppingCartService;
}
public async Task<List<CartItemDto>> GetCollection()
{
return await this.localStorageService.GetItemAsync<List<CartItemDto>>(key) ?? await AddCollection();
}
public async Task RemoveCollection()
{
await this.localStorageService.RemoveItemAsync(key);
}
public async Task SaveCollection(List<CartItemDto> cartItemDtos)
{
await this.localStorageService.SetItemAsync(key, cartItemDtos);
}
private async Task<List<CartItemDto>> AddCollection()
{
var shoppingCartCollection = await this.shoppingCartService.GetItems(HardCoded.UserId);
if(shoppingCartCollection != null)
{
await this.localStorageService.SetItemAsync(key, shoppingCartCollection);
}
return shoppingCartCollection;
}
}
}

View File

@ -0,0 +1,41 @@
using Blazored.LocalStorage;
using ShopOnline.Models.Dtos;
using ShopOnline.Web.Services.Contracts;
namespace ShopOnline.Web.Services
{
public class ManageProductsLocalStorageService : IManageProductsLocalStorageService
{
private readonly ILocalStorageService localStorageService;
private readonly IProductService productService;
private const string key = "ProductCollection";
public ManageProductsLocalStorageService(ILocalStorageService localStorageService, IProductService productService)
{
this.localStorageService = localStorageService;
this.productService = productService;
}
public async Task<IEnumerable<ProductDto>> GetCollection()
{
return await this.localStorageService.GetItemAsync<IEnumerable<ProductDto>>(key) ?? await AddCollection();
}
public async Task RemoveCollection()
{
await this.localStorageService.RemoveItemAsync(key);
}
private async Task<IEnumerable<ProductDto>> AddCollection()
{
var productCollection = await this.productService.GetItems();
if(productCollection != null)
{
await this.localStorageService.SetItemAsync(key, productCollection);
}
return productCollection;
}
}
}

View File

@ -1,16 +0,0 @@
<div class="alert alert-secondary mt-4">
<span class="oi oi-pencil me-2" aria-hidden="true"></span>
<strong>@Title</strong>
<span class="text-nowrap">
Please take our
<a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2148851">brief survey</a>
</span>
and tell us what you think.
</div>
@code {
// Demonstrates how a parent component can supply parameters
[Parameter]
public string? Title { get; set; }
}

View File

@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.8" PrivateAssets="all" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />