From 361f9268a396c69c9130275715f884bf6f057b11 Mon Sep 17 00:00:00 2001 From: MeysamMoghaddam <65253484+MeysamMoghaddam@users.noreply.github.com> Date: Mon, 13 Oct 2025 13:04:59 +0330 Subject: [PATCH] u --- src/FrontOffice.Main/ConfigureServices.cs | 2 + src/FrontOffice.Main/FrontOffice.Main.csproj | 1 + src/FrontOffice.Main/Pages/Checkout.razor | 190 ++++++++++++++++++ src/FrontOffice.Main/Pages/Checkout.razor.cs | 178 ++++++++++++++++ src/FrontOffice.Main/Pages/Index.razor.cs | 2 +- .../Utilities/RouteConstants.cs | 5 + 6 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 src/FrontOffice.Main/Pages/Checkout.razor create mode 100644 src/FrontOffice.Main/Pages/Checkout.razor.cs diff --git a/src/FrontOffice.Main/ConfigureServices.cs b/src/FrontOffice.Main/ConfigureServices.cs index 042ebd1..d04c3c7 100644 --- a/src/FrontOffice.Main/ConfigureServices.cs +++ b/src/FrontOffice.Main/ConfigureServices.cs @@ -9,6 +9,7 @@ using FrontOffice.BFF.Package.Protobuf.Protos.Package; using FrontOffice.BFF.User.Protobuf.Protos.User; using FrontOffice.BFF.UserAddress.Protobuf.Protos.UserAddress; using FrontOffice.BFF.UserOrder.Protobuf.Protos.UserOrder; +using FrontOffice.BFF.Transaction.Protobuf.Protos.Transaction; namespace Microsoft.Extensions.DependencyInjection; @@ -55,6 +56,7 @@ public static class ConfigureServices services.AddScoped(CreateAuthenticatedClient); services.AddScoped(CreateAuthenticatedClient); services.AddScoped(CreateAuthenticatedClient); + services.AddScoped(CreateAuthenticatedClient); return services; } diff --git a/src/FrontOffice.Main/FrontOffice.Main.csproj b/src/FrontOffice.Main/FrontOffice.Main.csproj index 096fae9..7242af3 100644 --- a/src/FrontOffice.Main/FrontOffice.Main.csproj +++ b/src/FrontOffice.Main/FrontOffice.Main.csproj @@ -9,6 +9,7 @@ + diff --git a/src/FrontOffice.Main/Pages/Checkout.razor b/src/FrontOffice.Main/Pages/Checkout.razor new file mode 100644 index 0000000..b8f9aeb --- /dev/null +++ b/src/FrontOffice.Main/Pages/Checkout.razor @@ -0,0 +1,190 @@ +@attribute [Route(RouteConstants.Checkout.Index + "/{PackageId:long}")] +@inject NavigationManager Navigation +@inject ISnackbar Snackbar + +تکمیل خرید + + + + + + + + + +
+ تکمیل خرید + مرحله نهایی خرید پکیج +
+
+
+
+
+ + + + + جزئیات پکیج + + @if (_selectedPackage != null) + { + + + + + @_selectedPackage.Title + @((MarkupString)_selectedPackage.Body) + + + + + + کد تخفیف + + + + اعمال + + + @if (!string.IsNullOrWhiteSpace(_discountMessage)) + { + + @_discountMessage + + } + + + } + else + { + + + پکیجی انتخاب نشده است. + + بازگشت به صفحه اصلی + + + } + + + + + + + + + انتخاب آدرس + + @if (_isLoadingAddresses) + { + + + بارگذاری آدرس‌ها... + + } + else if (_addresses.Any()) + { + + @foreach (var address in _addresses) + { + + + + + @address.Title + @if (address.IsDefault) + { + پیش‌فرض + } + + @address.Address + کد پستی: @address.PostalCode + + + } + + } + else + { + + + آدرسی ثبت نشده است. + + افزودن آدرس + + + } + + + + @if (_selectedPackage != null) + { + + خلاصه سفارش + + + + پکیج @(_selectedPackage.Title) + @_selectedPackage.Price.ToThousands().ToCurrencyUnitIRT() + + + @if (_discountApplied && _discountAmount > 0) + { + + تخفیف (@_discountCode) + -@_discountAmount.ToThousands().ToCurrencyUnitIRT() + + } + + + + + مجموع + @_finalPrice.ToThousands().ToCurrencyUnitIRT() + + + + @(_isProcessingPayment ? "در حال پردازش..." : "پرداخت آنلاین") + + + @if (!CanProceedToPayment) + { + + لطفاً پکیج و آدرس را انتخاب کنید. + + } + + + } + + +
+
\ No newline at end of file diff --git a/src/FrontOffice.Main/Pages/Checkout.razor.cs b/src/FrontOffice.Main/Pages/Checkout.razor.cs new file mode 100644 index 0000000..aba6eb3 --- /dev/null +++ b/src/FrontOffice.Main/Pages/Checkout.razor.cs @@ -0,0 +1,178 @@ +using FrontOffice.BFF.Package.Protobuf.Protos.Package; +using FrontOffice.BFF.UserAddress.Protobuf.Protos.UserAddress; +using FrontOffice.Main.Utilities; +using Microsoft.AspNetCore.Components; +using MudBlazor; +using Severity = MudBlazor.Severity; + +namespace FrontOffice.Main.Pages; + +public partial class Checkout +{ + [Inject] private PackageContract.PackageContractClient PackageClient { get; set; } = default!; + [Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!; + + [Parameter] public long? PackageId { get; set; } + + private Pack? _selectedPackage; + private List _addresses = new(); + private GetAllUserAddressByFilterResponseModel? _selectedAddress; + private bool _isLoadingAddresses; + private bool _isProcessingPayment; + + // Discount code + private string _discountCode = string.Empty; + private bool _isApplyingDiscount; + private string _discountMessage = string.Empty; + private bool _discountApplied; + private long _discountAmount; + private long _finalPrice; + + private bool CanProceedToPayment => _selectedPackage != null && _selectedAddress != null; + + protected override async Task OnInitializedAsync() + { + await LoadPackageDetails(); + await LoadAddresses(); + } + + private async Task LoadPackageDetails() + { + if (PackageId.HasValue) + { + try + { + var response = await PackageClient.GetPackageAsync(new() { Id = PackageId.Value }); + if (response != null) + { + _selectedPackage = new Pack( + Id: response.Id, + Title: response.Title, + Body: response.Description, + Image: UrlUtility.DownloadUrl + response.ImagePath, + Price: response.Price + ); + _finalPrice = _selectedPackage.Price; + } + } + catch (Exception ex) + { + Snackbar.Add($"خطا در بارگذاری پکیج: {ex.Message}", Severity.Error); + } + } + } + + private async Task LoadAddresses() + { + _isLoadingAddresses = true; + try + { + var response = await UserAddressContract.GetAllUserAddressByFilterAsync(request: new()); + if (response?.Models?.Any() == true) + { + _addresses = response.Models.ToList(); + // Select default address if available + _selectedAddress = _addresses.FirstOrDefault(a => a.IsDefault) ?? _addresses.First(); + } + else + { + _addresses = new List(); + } + } + catch (Exception ex) + { + Snackbar.Add($"خطا در بارگذاری آدرس‌ها: {ex.Message}", Severity.Error); + _addresses = new List(); + } + finally + { + _isLoadingAddresses = false; + await InvokeAsync(StateHasChanged); + } + } + + private void SelectAddress(GetAllUserAddressByFilterResponseModel address) + { + _selectedAddress = address; + StateHasChanged(); + } + + private async Task ApplyDiscountCode() + { + if (string.IsNullOrWhiteSpace(_discountCode)) + { + _discountMessage = "لطفاً کد تخفیف را وارد کنید."; + _discountApplied = false; + return; + } + + _isApplyingDiscount = true; + _discountMessage = string.Empty; + + try + { + // TODO: Implement discount code validation with backend + // For now, simulate a discount + if (_discountCode.ToUpper() == "TEST10") + { + _discountAmount = (long)(_selectedPackage!.Price * 0.1); // 10% discount + _finalPrice = _selectedPackage!.Price - _discountAmount; + _discountMessage = "کد تخفیف با موفقیت اعمال شد."; + _discountApplied = true; + } + else + { + _discountMessage = "کد تخفیف نامعتبر است."; + _discountApplied = false; + _discountAmount = 0; + _finalPrice = _selectedPackage!.Price; + } + } + catch (Exception ex) + { + _discountMessage = "خطا در اعمال کد تخفیف."; + _discountApplied = false; + _discountAmount = 0; + _finalPrice = _selectedPackage!.Price; + } + finally + { + _isApplyingDiscount = false; + await InvokeAsync(StateHasChanged); + } + } + + private async Task ProcessPayment() + { + if (!CanProceedToPayment || _selectedPackage == null || _selectedAddress == null) + { + Snackbar.Add("لطفاً پکیج و آدرس را انتخاب کنید.", Severity.Warning); + return; + } + + _isProcessingPayment = true; + + try + { + // TODO: Implement payment processing with backend + // This is a placeholder for payment integration + await Task.Delay(2000); // Simulate payment processing + + Snackbar.Add("پرداخت با موفقیت انجام شد!", Severity.Success); + + // Navigate to success page or order details + Navigation.NavigateTo("/order/success"); + } + catch (Exception ex) + { + Snackbar.Add($"خطا در پردازش پرداخت: {ex.Message}", Severity.Error); + } + finally + { + _isProcessingPayment = false; + await InvokeAsync(StateHasChanged); + } + } + + private record Pack(long Id, string Title, string Body, string Image, long Price); +} \ No newline at end of file diff --git a/src/FrontOffice.Main/Pages/Index.razor.cs b/src/FrontOffice.Main/Pages/Index.razor.cs index 3aa4324..d64bb3f 100644 --- a/src/FrontOffice.Main/Pages/Index.razor.cs +++ b/src/FrontOffice.Main/Pages/Index.razor.cs @@ -62,7 +62,7 @@ public partial class Index private void NavigateToPackage(long packageId) { - Navigation.NavigateTo($"{RouteConstants.Package.Detail}/{packageId}"); + Navigation.NavigateTo($"{RouteConstants.Package.Detail}{packageId}"); } private record Pack(long Id, string Title, string Body, string Image, long Price); diff --git a/src/FrontOffice.Main/Utilities/RouteConstants.cs b/src/FrontOffice.Main/Utilities/RouteConstants.cs index 7709548..96f17c4 100644 --- a/src/FrontOffice.Main/Utilities/RouteConstants.cs +++ b/src/FrontOffice.Main/Utilities/RouteConstants.cs @@ -31,4 +31,9 @@ public static class RouteConstants { public const string Index = "/contact"; } + + public static class Checkout + { + public const string Index = "/checkout"; + } }