c243b59113
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 6m48s
- Updated the Checkout and CheckoutSummary components to allow users to add new addresses directly from the interface, improving accessibility and user experience. - Introduced dialog functionality for adding and editing addresses, streamlining the address management process. - Removed the calculation of order PV from the OrderDetail component, simplifying the order details view and improving performance. These changes enhance the usability of the checkout process by making address management more intuitive and efficient.
157 lines
5.5 KiB
C#
157 lines
5.5 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using CMSMicroservice.Protobuf.Protos.UserAddress;
|
|
using FrontOffice.Main.Pages.Profile.Components;
|
|
using FrontOffice.Main.Utilities;
|
|
using MudBlazor;
|
|
|
|
namespace FrontOffice.Main.Pages.DiscountStore;
|
|
|
|
public partial class Checkout
|
|
{
|
|
[Inject] private DiscountCartService DiscountCart { get; set; } = default!;
|
|
[Inject] private DiscountOrderService DiscountOrderService { get; set; } = default!;
|
|
[Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!;
|
|
[Inject] private VATService VAT { get; set; } = default!;
|
|
[Inject] private AuthDialogService AuthDialogService { get; set; } = default!;
|
|
[Inject] private AuthService AuthService { get; set; } = default!;
|
|
|
|
private List<CustomerAddressModel> _addresses = new();
|
|
private CustomerAddressModel? _selectedAddress;
|
|
private bool _loadingAddresses;
|
|
|
|
private string? _notes;
|
|
private bool _placing;
|
|
|
|
/// <summary>مبلغ درگاه قبل از مالیات (جمع کل - اعتبار)</summary>
|
|
private long NetGatewayAmount => DiscountCart.TotalPrice - DiscountCart.TotalDiscount;
|
|
|
|
/// <summary>مالیات بر ارزش افزوده</summary>
|
|
private long VatAmount => VAT.CalculateVAT(NetGatewayAmount);
|
|
|
|
/// <summary>مبلغ نهایی قابل پرداخت (شامل VAT)</summary>
|
|
private long FinalGatewayAmount => NetGatewayAmount + VatAmount;
|
|
|
|
private bool CanPlaceOrder => DiscountCart.Items.Count > 0 && _selectedAddress is not null;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
if (!await AuthService.IsAuthenticatedAsync())
|
|
{
|
|
await AuthDialogService.ShowAuthDialogAsync();
|
|
}
|
|
await VAT.LoadAsync();
|
|
await DiscountCart.EnsureInitializedAsync();
|
|
var userInfo = await AuthService.GetUserAuthInfo();
|
|
if (userInfo.HasAddress)
|
|
await LoadAddresses();
|
|
else
|
|
_addresses = new();
|
|
}
|
|
|
|
private async Task LoadAddresses()
|
|
{
|
|
_loadingAddresses = true;
|
|
try
|
|
{
|
|
var response = await UserAddressContract.GetCustomerAddressesAsync(new());
|
|
if (response?.Models?.Any() == true)
|
|
{
|
|
_addresses = response.Models.ToList();
|
|
_selectedAddress = _addresses.FirstOrDefault(a => a.IsDefault) ?? _addresses.First();
|
|
}
|
|
else
|
|
{
|
|
_addresses = new();
|
|
_selectedAddress = null;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"خطا در بارگذاری آدرسها: {ex.Message}", Severity.Error);
|
|
_addresses = new();
|
|
_selectedAddress = null;
|
|
}
|
|
finally
|
|
{
|
|
_loadingAddresses = false;
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
private async Task OpenAddAddressDialog()
|
|
{
|
|
var dialog = await DialogService.ShowAsync<AddAddressDialog>("افزودن آدرس جدید");
|
|
var result = await dialog.Result;
|
|
if (result is { Canceled: false })
|
|
{
|
|
await AuthService.RefreshTokenAsync();
|
|
await LoadAddresses();
|
|
}
|
|
}
|
|
|
|
private async Task OpenEditAddressDialog(CustomerAddressModel address)
|
|
{
|
|
var dialog = await DialogService.ShowAsync<EditAddressDialog>("ویرایش آدرس", new DialogParameters<EditAddressDialog>
|
|
{
|
|
{ x => x.Model, address }
|
|
});
|
|
var result = await dialog.Result;
|
|
if (result is { Canceled: false })
|
|
{
|
|
await LoadAddresses();
|
|
}
|
|
}
|
|
|
|
private async Task PlaceOrder()
|
|
{
|
|
if (!CanPlaceOrder || _selectedAddress is null)
|
|
{
|
|
Snackbar.Add("لطفاً آدرس را انتخاب کنید.", Severity.Warning);
|
|
return;
|
|
}
|
|
|
|
_placing = true;
|
|
try
|
|
{
|
|
// Always use 100% discount — send full price, server will apply max from wallet
|
|
var result = await DiscountOrderService.PlaceOrderAsync(
|
|
_selectedAddress.Id,
|
|
DiscountCart.TotalPrice,
|
|
_notes);
|
|
|
|
if (!result.Success)
|
|
{
|
|
Snackbar.Add(result.Message, Severity.Error);
|
|
return;
|
|
}
|
|
|
|
// If there's a gateway payment URL, redirect to it
|
|
if (!string.IsNullOrWhiteSpace(result.PaymentUrl) && result.GatewayAmount > 0)
|
|
{
|
|
Snackbar.Add("در حال انتقال به درگاه پرداخت...", Severity.Info);
|
|
await DiscountCart.ClearAsync();
|
|
Navigation.NavigateTo(result.PaymentUrl, forceLoad: true);
|
|
return;
|
|
}
|
|
|
|
// If fully paid via discount balance (no gateway needed)
|
|
await DiscountCart.ClearAsync();
|
|
Snackbar.Add("سفارش با موفقیت ثبت شد!", Severity.Success);
|
|
Navigation.NavigateTo($"{RouteConstants.DiscountStore.OrderDetail}{result.OrderId}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"خطا در ثبت سفارش: {ex.Message}", Severity.Error);
|
|
}
|
|
finally
|
|
{
|
|
_placing = false;
|
|
}
|
|
}
|
|
|
|
private static string FormatPrice(long price) => $"{price:N0}";
|
|
|
|
private static string GetImageUrl(string? imageUrl)
|
|
=> string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl.TrimStart('/');
|
|
}
|