feat: implement VAT management service and integrate VAT calculations across components
This commit is contained in:
@@ -141,11 +141,22 @@
|
||||
</MudHidden>
|
||||
@if (DeviceDetector.IsMobile())
|
||||
{
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center"
|
||||
Class="mobile-actions-stack px-5">
|
||||
<MudText Typo="Typo.subtitle2"> تخفیف کل: <b>@FormatPrice(CartData.TotalDiscount)</b></MudText>
|
||||
<MudText Typo="Typo.h5"> مبلغ کل: <b>@FormatPrice(CartData.Total)</b></MudText>
|
||||
|
||||
<MudStack Spacing="1" Class="mobile-actions-stack px-5">
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
||||
<MudText Typo="Typo.body2">جمع کالاها:</MudText>
|
||||
<MudText Typo="Typo.body2">@FormatPrice(CartData.Total) تومان</MudText>
|
||||
</MudStack>
|
||||
@if (VAT.IsEnabled)
|
||||
{
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
||||
<MudText Typo="Typo.caption" Class="mud-text-secondary">مالیات (@VAT.VatPercentage%):</MudText>
|
||||
<MudText Typo="Typo.caption" Class="mud-text-secondary">@FormatPrice(VATAmount) تومان</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
|
||||
<MudText Typo="Typo.h6" Style="font-weight:bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary" Style="font-weight:bold;">@FormatPrice(TotalWithVAT) تومان</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" Spacing="2" Class="mobile-actions-stack">
|
||||
@@ -159,12 +170,29 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center"
|
||||
Class="mobile-actions-stack px-5">
|
||||
<MudText Typo="Typo.subtitle2"> تخفیف کل: <b>@FormatPrice(CartData.TotalDiscount)</b></MudText>
|
||||
<MudText Typo="Typo.h5"> مبلغ کل: <b>@FormatPrice(CartData.Total)</b></MudText>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
||||
<MudPaper Class="pa-4 rounded-lg" Style="background-color: var(--mud-palette-background-grey);">
|
||||
<MudStack Spacing="1">
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.body2">جمع کالاها:</MudText>
|
||||
<MudText Typo="Typo.body2">@FormatPrice(CartData.Total) تومان</MudText>
|
||||
</MudStack>
|
||||
@if (VAT.IsEnabled)
|
||||
{
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">مالیات بر ارزش افزوده (@VAT.VatPercentage%):</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">@FormatPrice(VATAmount) تومان</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
<MudDivider Class="my-1" />
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight:bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight:bold;">@FormatPrice(TotalWithVAT) تومان</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
<MudStack Row="true" Justify="Justify.FlexEnd" Spacing="2" Class="mt-3">
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Primary"
|
||||
OnClick="() => Navigation.NavigateTo(RouteConstants.Store.Products)">افزودن محصول
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Success" OnClick="ProceedCheckout"
|
||||
|
||||
@@ -7,12 +7,16 @@ namespace FrontOffice.Main.Pages.Store;
|
||||
public partial class Cart : ComponentBase, IDisposable
|
||||
{
|
||||
[Inject] private CartService CartService { get; set; } = default!;
|
||||
[Inject] private VATService VAT { get; set; } = default!;
|
||||
// Navigation and Snackbar are available via _Imports.razor
|
||||
private CartService CartData => CartService;
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// لود سبد خرید (فقط اگر کاربر لاگین کرده باشد)
|
||||
await CartService.EnsureInitializedAsync();
|
||||
CartService.OnChange += StateHasChanged;
|
||||
await VAT.LoadAsync();
|
||||
}
|
||||
|
||||
private async Task IncrementQty(long productId)
|
||||
@@ -44,7 +48,13 @@ public partial class Cart : ComponentBase, IDisposable
|
||||
Navigation.NavigateTo(RouteConstants.Store.CheckoutSummary);
|
||||
}
|
||||
|
||||
private static string FormatPrice(long price) => string.Format("{0:N0} ", price);
|
||||
private string FormatPrice(long price) => $"{price:N0} ";
|
||||
|
||||
private string FormatPriceWithVAT(long price) => $"{VAT.AddVAT(price):N0} ";
|
||||
|
||||
private long TotalWithVAT => VAT.AddVAT(CartData.Total);
|
||||
|
||||
private long VATAmount => VAT.CalculateVAT(CartData.Total);
|
||||
|
||||
private static string GetProductImageUrl(string? imageUrl)
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl;
|
||||
|
||||
@@ -108,14 +108,17 @@
|
||||
<MudText Typo="Typo.body2">جمع کالاها:</MudText>
|
||||
<MudText Typo="Typo.body2">@FormatPrice(Cart.Total)</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">مالیات بر ارزش افزوده (۹%):</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">@FormatPrice(CalculateVAT())</MudText>
|
||||
</MudStack>
|
||||
@if (VAT.IsEnabled)
|
||||
{
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">مالیات بر ارزش افزوده (@VAT.VatPercentage%):</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">@FormatPrice(CalculateVAT())</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
<MudDivider Class="my-1" />
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight: bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(Cart.Total + CalculateVAT())</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(VAT.AddVAT(Cart.Total))</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ public partial class CheckoutSummary : ComponentBase
|
||||
{
|
||||
[Inject] private CartService Cart { get; set; } = default!;
|
||||
[Inject] private OrderService OrderService { get; set; } = default!;
|
||||
[Inject] private VATService VAT { get; set; } = default!;
|
||||
[Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!;
|
||||
[Inject] private UserOrderContract.UserOrderContractClient UserOrderContract { get; set; } = default!;
|
||||
// Snackbar and Navigation are injected via _Imports.razor
|
||||
@@ -25,8 +26,11 @@ public partial class CheckoutSummary : ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// لود سبد خرید (فقط اگر کاربر لاگین کرده باشد)
|
||||
await Cart.EnsureInitializedAsync();
|
||||
await LoadAddresses();
|
||||
await LoadWalletBalance();
|
||||
await VAT.LoadAsync();
|
||||
}
|
||||
|
||||
private async Task LoadWalletBalance()
|
||||
@@ -92,9 +96,9 @@ public partial class CheckoutSummary : ComponentBase
|
||||
private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price);
|
||||
|
||||
/// <summary>
|
||||
/// محاسبه مالیات بر ارزش افزوده (۹%)
|
||||
/// محاسبه مالیات بر ارزش افزوده
|
||||
/// </summary>
|
||||
private long CalculateVAT() => (long)(Cart.Total * 0.09);
|
||||
private long CalculateVAT() => VAT.CalculateVAT(Cart.Total);
|
||||
|
||||
private static string GetProductImageUrl(string? imageUrl)
|
||||
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl;
|
||||
|
||||
@@ -78,8 +78,6 @@ else
|
||||
@* نمایش جزئیات مالی *@
|
||||
@{
|
||||
var subtotal = _order.FactorDetails.Sum(s => s.UnitPrice.Value * s.Count.Value);
|
||||
var vatAmount = (long)(subtotal * 0.09);
|
||||
var totalWithVat = subtotal + vatAmount;
|
||||
}
|
||||
<MudStack Spacing="1" Class="pa-2" Style="background-color: var(--mud-palette-background-grey); border-radius: 8px;">
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
@@ -87,15 +85,26 @@ else
|
||||
<MudText Typo="Typo.body2">@FormatPrice(subtotal)</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">مالیات بر ارزش افزوده (۹%):</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">@FormatPrice(vatAmount)</MudText>
|
||||
</MudStack>
|
||||
<MudDivider Class="my-1" />
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight: bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(totalWithVat)</MudText>
|
||||
</MudStack>
|
||||
@if (_order.VatInfo is not null)
|
||||
{
|
||||
var vatPercent = (int)(_order.VatInfo.VatRate * 100);
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">مالیات بر ارزش افزوده (@vatPercent%):</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mud-text-secondary">@FormatPrice(_order.VatInfo.VatAmount)</MudText>
|
||||
</MudStack>
|
||||
<MudDivider Class="my-1" />
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight: bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(_order.VatInfo.TotalAmount)</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudStack Row="true" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle1" Style="font-weight: bold;">مبلغ قابل پرداخت:</MudText>
|
||||
<MudText Typo="Typo.subtitle1" Color="Color.Primary" Style="font-weight: bold;">@FormatPrice(subtotal)</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace FrontOffice.Main.Pages.Store;
|
||||
public partial class Orders : ComponentBase
|
||||
{
|
||||
[Inject] private OrderService OrderService { get; set; } = default!;
|
||||
[Inject] private VATService VAT { get; set; } = default!;
|
||||
|
||||
private List<GetUserOrderResponse> _orders = new();
|
||||
private bool _loading;
|
||||
@@ -18,6 +19,7 @@ public partial class Orders : ComponentBase
|
||||
_loading = true;
|
||||
try
|
||||
{
|
||||
await VAT.LoadAsync();
|
||||
_orders = await OrderService.GetOrdersAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -77,18 +77,51 @@ else
|
||||
@* </MudStack> *@
|
||||
@* } *@
|
||||
<MudDivider Class="my-2"/>
|
||||
<MudText Typo="Typo.h5" Color="Color.Primary">@FormatPrice(_product.Price)</MudText>
|
||||
<MudStack Spacing="1">
|
||||
<MudText Typo="Typo.h5" Color="Color.Primary">@FormatPrice(_product.Price)</MudText>
|
||||
@if (VAT.IsEnabled)
|
||||
{
|
||||
<MudText Typo="Typo.caption" Class="mud-text-secondary">
|
||||
(شامل @VAT.VatPercentage% مالیات بر ارزش افزوده)
|
||||
</MudText>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<!-- نمایش وضعیت موجودی -->
|
||||
@if (IsInStock)
|
||||
{
|
||||
<MudChip T="string" Color="Color.Success" Variant="Variant.Filled" Size="Size.Small">
|
||||
<MudIcon Icon="@Icons.Material.Filled.CheckCircle" Size="Size.Small" Class="me-1" />
|
||||
موجود در انبار (@_product.RemainingCount عدد)
|
||||
</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Color="Color.Error" Variant="Variant.Filled" Size="Size.Small">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Cancel" Size="Size.Small" Class="me-1" />
|
||||
ناموجود
|
||||
</MudChip>
|
||||
}
|
||||
|
||||
<!-- Desktop/tablet actions -->
|
||||
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert="true">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||
<MudNumericField T="int" @bind-Value="_qty" Min="@MinQty" Max="@MaxQty" Immediate="true"
|
||||
HideSpinButtons="true" Style="max-width:120px"/>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.AddShoppingCart" OnClick="AddToCart">افزودن به
|
||||
سبد
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
@if (IsInStock)
|
||||
{
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||
<MudNumericField T="int" @bind-Value="_qty" Min="@MinQty" Max="@MaxQty" Immediate="true"
|
||||
HideSpinButtons="true" Style="max-width:120px"/>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.AddShoppingCart" OnClick="AddToCart">افزودن به
|
||||
سبد
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Dense="true">
|
||||
این محصول در حال حاضر موجود نیست.
|
||||
</MudAlert>
|
||||
}
|
||||
</MudHidden>
|
||||
|
||||
<!-- Mobile actions use sticky bar rendered below -->
|
||||
@@ -103,51 +136,58 @@ else
|
||||
<MudPaper Class="mud-width-full mud-elevation-3 pa-3"
|
||||
Style="position:sticky;bottom:0;left:0;z-index:9;border-top-left-radius:1rem;border-top-right-radius:1rem;">
|
||||
|
||||
<MudGrid Class="align-center" Justify="Justify.SpaceBetween">
|
||||
<MudItem xs="6">
|
||||
<MudStack Spacing="1">
|
||||
@if (HasDiscount && OriginalPrice is not null)
|
||||
{
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="mud-text-secondary mud-line-through">@FormatPrice(OriginalPrice.Value)</MudText>
|
||||
<MudChip T="string" Color="Color.Error" Variant="Variant.Filled" Size="Size.Small"
|
||||
Label="true">@($"٪{_product!.Discount}")</MudChip>
|
||||
</MudStack>
|
||||
}
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary">@FormatPrice(TotalPrice)</MudText>
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
|
||||
@if (IsInCart)
|
||||
{
|
||||
<MudItem xs="5" Class="">
|
||||
<MudPaper Class="mud-width-full d-flex align-center justify-space-between px-2"
|
||||
Elevation="1" Style="border-radius:1rem;">
|
||||
<MudIconButton
|
||||
Icon="@(CurrentCartQuantity == 1 ? Icons.Material.Filled.Delete : Icons.Material.Filled.Remove)"
|
||||
Color="Color.Error" Variant="Variant.Text" OnClick="RemoveFromCart"/>
|
||||
<MudText Typo="Typo.subtitle2" Class="mud-font-weight-bold">@CurrentCartQuantity</MudText>
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Add" Color="Color.Primary"
|
||||
Variant="Variant.Text" Disabled="@(CurrentCartQuantity >= MaxQty)"
|
||||
OnClick="AddToCart"/>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudItem xs="6" >
|
||||
@if (IsInStock)
|
||||
{
|
||||
<MudGrid Class="align-center" Justify="Justify.SpaceBetween">
|
||||
<MudItem xs="6">
|
||||
<MudStack Spacing="1">
|
||||
|
||||
<MudButton Variant="Variant.Filled" Size="Size.Large" Color="Color.Error" Class="mud-width-full"
|
||||
StartIcon="@Icons.Material.Filled.AddShoppingCart" OnClick="AddToCart">
|
||||
افزودن به سبد
|
||||
</MudButton>
|
||||
@if (HasDiscount && OriginalPrice is not null)
|
||||
{
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="mud-text-secondary mud-line-through">@FormatPrice(OriginalPrice.Value)</MudText>
|
||||
<MudChip T="string" Color="Color.Error" Variant="Variant.Filled" Size="Size.Small"
|
||||
Label="true">@($"٪{_product!.Discount}")</MudChip>
|
||||
</MudStack>
|
||||
}
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary">@FormatPrice(TotalPrice)</MudText>
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
|
||||
@if (IsInCart)
|
||||
{
|
||||
<MudItem xs="5" Class="">
|
||||
<MudPaper Class="mud-width-full d-flex align-center justify-space-between px-2"
|
||||
Elevation="1" Style="border-radius:1rem;">
|
||||
<MudIconButton
|
||||
Icon="@(CurrentCartQuantity == 1 ? Icons.Material.Filled.Delete : Icons.Material.Filled.Remove)"
|
||||
Color="Color.Error" Variant="Variant.Text" OnClick="RemoveFromCart"/>
|
||||
<MudText Typo="Typo.subtitle2" Class="mud-font-weight-bold">@CurrentCartQuantity</MudText>
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Add" Color="Color.Primary"
|
||||
Variant="Variant.Text" Disabled="@(CurrentCartQuantity >= MaxQty)"
|
||||
OnClick="AddToCart"/>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudItem xs="6" >
|
||||
<MudStack Spacing="1">
|
||||
<MudButton Variant="Variant.Filled" Size="Size.Large" Color="Color.Error" Class="mud-width-full"
|
||||
StartIcon="@Icons.Material.Filled.AddShoppingCart" OnClick="AddToCart">
|
||||
افزودن به سبد
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Variant="Variant.Filled" Dense="true" Class="mb-0">
|
||||
این محصول ناموجود است
|
||||
</MudAlert>
|
||||
}
|
||||
|
||||
</MudPaper>
|
||||
</MudHidden>
|
||||
|
||||
@@ -11,6 +11,7 @@ public partial class ProductDetail : ComponentBase, IDisposable
|
||||
{
|
||||
[Inject] private ProductService ProductService { get; set; } = default!;
|
||||
[Inject] private CartService Cart { get; set; } = default!;
|
||||
[Inject] private VATService VAT { get; set; } = default!;
|
||||
|
||||
[Parameter] public long id { get; set; }
|
||||
|
||||
@@ -18,12 +19,18 @@ public partial class ProductDetail : ComponentBase, IDisposable
|
||||
private bool _loading;
|
||||
private int _qty = 1;
|
||||
private const int MinQty = 1;
|
||||
private const int MaxQty = 20;
|
||||
|
||||
// حداکثر تعداد قابل خرید بر اساس موجودی انبار
|
||||
private int MaxQty => _product?.RemainingCount > 0 ? _product.RemainingCount : 0;
|
||||
|
||||
// آیا محصول موجود است
|
||||
private bool IsInStock => _product is not null && _product.RemainingCount > 0;
|
||||
|
||||
private IReadOnlyList<ProductGalleryImage> _galleryItems = Array.Empty<ProductGalleryImage>();
|
||||
private IReadOnlyList<ProductCategoryPathInfo> _categoryPaths = Array.Empty<ProductCategoryPathInfo>();
|
||||
private ProductGalleryImage? _selectedGalleryImage;
|
||||
private readonly List<BreadcrumbItem> _breadcrumbItems = new();
|
||||
private long TotalPrice => (_product?.Price ?? 0) * _qty;
|
||||
private long TotalPrice => VAT.AddVAT((_product?.Price ?? 0) * _qty);
|
||||
private bool HasDiscount => _product is { Discount: > 0 and < 100 };
|
||||
|
||||
private long? OriginalPrice => HasDiscount && _product is not null
|
||||
@@ -44,8 +51,13 @@ public partial class ProductDetail : ComponentBase, IDisposable
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// لود سبد خرید (فقط اگر کاربر لاگین کرده باشد)
|
||||
await Cart.EnsureInitializedAsync();
|
||||
Cart.OnChange += HandleCartChanged;
|
||||
|
||||
// بارگذاری نرخ VAT
|
||||
await VAT.LoadAsync();
|
||||
|
||||
_loading = true;
|
||||
_product = await ProductService.GetByIdAsync(id);
|
||||
_loading = false;
|
||||
@@ -127,7 +139,9 @@ public partial class ProductDetail : ComponentBase, IDisposable
|
||||
Cart.OnChange -= HandleCartChanged;
|
||||
}
|
||||
|
||||
private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price);
|
||||
private string FormatPrice(long price) => $"{VAT.AddVAT(price):N0} تومان";
|
||||
|
||||
private string FormatPriceWithoutVAT(long price) => $"{price:N0} تومان";
|
||||
|
||||
private static IReadOnlyList<ProductGalleryImage> BuildGalleryItems(Product product)
|
||||
{
|
||||
|
||||
@@ -59,8 +59,20 @@
|
||||
|
||||
|
||||
<MudCardContent Class="d-flex flex-column pa-1 h-100">
|
||||
<div style="height: 60%;background-image: url('@p.ImageUrl');background-size: cover; background-position: center;border-radius: 0.5rem">
|
||||
|
||||
<div style="height: 60%;background-image: url('@p.ImageUrl');background-size: cover; background-position: center;border-radius: 0.5rem; position: relative;">
|
||||
@if (p.RemainingCount <= 0)
|
||||
{
|
||||
<div style="position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;border-radius:0.5rem;">
|
||||
<MudChip T="string" Color="Color.Error" Variant="Variant.Filled" Size="Size.Small">ناموجود</MudChip>
|
||||
</div>
|
||||
}
|
||||
else if (p.RemainingCount <= 5)
|
||||
{
|
||||
<MudChip T="string" Color="Color.Warning" Variant="Variant.Filled" Size="Size.Small"
|
||||
Style="position:absolute;top:8px;right:8px;">
|
||||
فقط @p.RemainingCount عدد
|
||||
</MudChip>
|
||||
}
|
||||
</div>
|
||||
<div class="pa-1 flex-grow-1 d-flex flex-column justify-space-between">
|
||||
<MudText Typo="Typo.subtitle1">@p.Title</MudText>
|
||||
@@ -73,7 +85,9 @@
|
||||
@* Href="@($"{RouteConstants.Store.ProductDetail}{p.Id}")">جزئیات *@
|
||||
@* </MudButton> *@
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="() => AddToCart(p)"
|
||||
StartIcon="@Icons.Material.Filled.AddShoppingCart">افزودن
|
||||
StartIcon="@Icons.Material.Filled.AddShoppingCart"
|
||||
Disabled="@(p.RemainingCount <= 0)">
|
||||
@(p.RemainingCount <= 0 ? "ناموجود" : "افزودن")
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
|
||||
@@ -12,6 +12,7 @@ public partial class Products : ComponentBase, IDisposable
|
||||
[Inject] private ProductService ProductService { get; set; } = default!;
|
||||
[Inject] private CategoryService CategoryService { get; set; } = default!;
|
||||
[Inject] private CartService Cart { get; set; } = default!;
|
||||
[Inject] private VATService VAT { get; set; } = default!;
|
||||
|
||||
private string _query = string.Empty;
|
||||
private bool _loading;
|
||||
@@ -21,8 +22,11 @@ public partial class Products : ComponentBase, IDisposable
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// لود سبد خرید (فقط اگر کاربر لاگین کرده باشد)
|
||||
await Cart.EnsureInitializedAsync();
|
||||
Cart.OnChange += StateHasChanged;
|
||||
Navigation.LocationChanged += HandleLocationChanged;
|
||||
await VAT.LoadAsync();
|
||||
await Load();
|
||||
}
|
||||
|
||||
@@ -47,7 +51,7 @@ public partial class Products : ComponentBase, IDisposable
|
||||
await Cart.Add(p, 1);
|
||||
}
|
||||
|
||||
private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price);
|
||||
private string FormatPrice(long price) => $"{VAT.AddVAT(price):N0} تومان";
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user