231da2cbaa
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 3m10s
- Add two sections to landing page (Index.razor) below the hero: - Top 6 best-selling regular products (3-per-row grid) - Top 6 best-selling discount store products (3-per-row grid) - Each section has a 'More' button linking to /products and /discount-store - Add GuestActionGate utility service: wraps auth-required actions; shows login modal for guests and resumes the original action after successful login - Register GuestActionGate as scoped service in ConfigureServices - Add GetTopSellingAsync(count) to ProductService and DiscountProductService - Add optional sortBy parameter to DiscountProductService.GetProductsAsync - Hybridize all product pages for guest browsing: - Store/Products, Store/ProductDetail: wrap AddToCart with GuestActionGate - DiscountStore/Products, DiscountStore/ProductDetail: wrap AddToCart with GuestActionGate - Store/Cart, DiscountStore/Cart, Store/CheckoutSummary: soft auth gate on page init - Fix MembershipPage membership benefit text to be package-agnostic Co-authored-by: Cursor <cursoragent@cursor.com>
76 lines
2.3 KiB
C#
76 lines
2.3 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using FrontOffice.Main.Utilities;
|
|
|
|
namespace FrontOffice.Main.Pages.DiscountStore;
|
|
|
|
public partial class Cart : IDisposable
|
|
{
|
|
[Inject] private DiscountCartService DiscountCart { get; set; } = default!;
|
|
[Inject] private VATService VAT { get; set; } = default!;
|
|
[Inject] private AuthDialogService AuthDialogService { get; set; } = default!;
|
|
[Inject] private AuthService AuthService { get; set; } = default!;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
if (!await AuthService.IsAuthenticatedAsync())
|
|
{
|
|
await AuthDialogService.ShowAuthDialogAsync();
|
|
}
|
|
await DiscountCart.EnsureInitializedAsync();
|
|
DiscountCart.OnChange += StateHasChanged;
|
|
}
|
|
|
|
private async Task IncrementQty(long productId)
|
|
{
|
|
var item = DiscountCart.Items.FirstOrDefault(i => i.ProductId == productId);
|
|
if (item is null) return;
|
|
await DiscountCart.UpdateQuantityAsync(productId, item.Quantity + 1);
|
|
}
|
|
|
|
private async Task DecrementQty(long productId)
|
|
{
|
|
var item = DiscountCart.Items.FirstOrDefault(i => i.ProductId == productId);
|
|
if (item is null) return;
|
|
if (item.Quantity <= 1)
|
|
{
|
|
await DiscountCart.RemoveAsync(productId);
|
|
}
|
|
else
|
|
{
|
|
await DiscountCart.UpdateQuantityAsync(productId, item.Quantity - 1);
|
|
}
|
|
}
|
|
|
|
private async Task Remove(long productId)
|
|
{
|
|
await DiscountCart.RemoveAsync(productId);
|
|
}
|
|
|
|
private void ProceedCheckout()
|
|
{
|
|
Navigation.NavigateTo(RouteConstants.DiscountStore.Checkout);
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender)
|
|
{
|
|
await VAT.LoadAsync();
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
private long VatAmount => VAT.CalculateVAT(DiscountCart.FinalPrice);
|
|
private long TotalWithVat => DiscountCart.FinalPrice + VatAmount;
|
|
|
|
private static string FormatPrice(long price) => $"{price:N0} ";
|
|
|
|
private static string GetImageUrl(string? imageUrl)
|
|
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl.TrimStart('/');
|
|
|
|
public void Dispose()
|
|
{
|
|
DiscountCart.OnChange -= StateHasChanged;
|
|
}
|
|
}
|