diff --git a/.gitignore b/.gitignore index fe8a569..1c55f34 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs -# Mono auto generated files +# Mono auto generated files mono_crash.* # Build results diff --git a/src/FrontOffice.Main/Pages/Checkout.razor b/src/FrontOffice.Main/Pages/Checkout.razor index 79173be..f138e5b 100644 --- a/src/FrontOffice.Main/Pages/Checkout.razor +++ b/src/FrontOffice.Main/Pages/Checkout.razor @@ -71,80 +71,6 @@ } - - - - انتخاب آدرس - - @if (_isLoadingAddresses) - { - - - بارگذاری آدرس‌ها... - - } - else if (_addresses.Any()) - { - - @foreach (var address in _addresses) - { - - - - - @(address.Title) - @if (address.IsDefault) - { - پیش‌فرض - } - @if (!address.IsDefault) - { - @if (_isSettingDefaultAddress && _settingDefaultAddressId == address.Id) - { - - } - else - { - - تنظیم به عنوان پیش‌فرض - - } - } - - - @(address.Address) - - کد پستی: @(address.PostalCode) - - - - } - - } - else - { - - - آدرسی ثبت نشده است. - - افزودن آدرس - - - } - @@ -241,7 +167,7 @@ @if (!CanProceedToPayment) { - لطفاً پکیج و آدرس را انتخاب کنید. + لطفاً پکیج را انتخاب کنید. } diff --git a/src/FrontOffice.Main/Pages/Checkout.razor.cs b/src/FrontOffice.Main/Pages/Checkout.razor.cs index 24e2a78..5e30af5 100644 --- a/src/FrontOffice.Main/Pages/Checkout.razor.cs +++ b/src/FrontOffice.Main/Pages/Checkout.razor.cs @@ -1,6 +1,4 @@ - using CMSMicroservice.Protobuf.Protos.Package; -using CMSMicroservice.Protobuf.Protos.UserAddress; using FrontOffice.Main.Utilities; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; @@ -13,14 +11,10 @@ public partial class Checkout { [Inject] private PackageService PackageService { get; set; } = default!; [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 CustomerAddressModel? _selectedAddress; - private bool _isLoadingAddresses; private bool _isProcessingPayment; // Discount code @@ -31,16 +25,11 @@ public partial class Checkout private long _discountAmount; private long _finalPrice; - // Address management - private bool _isSettingDefaultAddress; - private long? _settingDefaultAddressId; - - private bool CanProceedToPayment => _selectedPackage != null && _selectedAddress != null; + private bool CanProceedToPayment => _selectedPackage != null; protected override async Task OnInitializedAsync() { await LoadPackageDetails(); - await LoadAddresses(); } private async Task LoadPackageDetails() @@ -72,60 +61,6 @@ public partial class Checkout } } - private async Task LoadAddresses() - { - _isLoadingAddresses = true; - try - { - var response = await UserAddressContract.GetCustomerAddressesAsync(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 async Task SetAddressAsDefault(long addressId) - { - if (_isSettingDefaultAddress) return; - - _isSettingDefaultAddress = true; - _settingDefaultAddressId = addressId; - - try - { - await UserAddressContract.SetAddressAsDefaultAsync(new() { Id = addressId }); - await LoadAddresses(); // Reload addresses to reflect the change - Snackbar.Add("آدرس پیش‌فرض با موفقیت تغییر یافت.", Severity.Success); - } - catch (Exception ex) - { - Snackbar.Add($"خطا در تغییر آدرس پیش‌فرض: {ex.Message}", Severity.Error); - } - finally - { - _isSettingDefaultAddress = false; - _settingDefaultAddressId = null; - await InvokeAsync(StateHasChanged); - } - } - private async Task ApplyDiscountCode() { if (string.IsNullOrWhiteSpace(_discountCode)) @@ -157,7 +92,7 @@ public partial class Checkout _finalPrice = _selectedPackage!.Price; } } - catch (Exception ex) + catch (Exception) { _discountMessage = "خطا در اعمال کد تخفیف."; _discountApplied = false; @@ -175,9 +110,9 @@ public partial class Checkout { if (_isProcessingPayment) return; - if (!CanProceedToPayment || _selectedPackage == null || _selectedAddress == null) + if (!CanProceedToPayment || _selectedPackage == null) { - Snackbar.Add("لطفاً پکیج و آدرس را انتخاب کنید.", Severity.Warning); + Snackbar.Add("لطفاً پکیج را انتخاب کنید.", Severity.Warning); return; } @@ -219,9 +154,9 @@ public partial class Checkout private async Task DayaLoanPayment() { - if (_selectedAddress == null) + if (_selectedPackage == null) { - Snackbar.Add("لطفاً آدرس را انتخاب کنید.", Severity.Warning); + Snackbar.Add("لطفاً پکیج را انتخاب کنید.", Severity.Warning); return; } @@ -230,4 +165,4 @@ public partial class Checkout } private record Pack(long Id, string Title, string Body, string Image, long Price, bool SupportsDirectPurchase = true, bool SupportsDayaPurchase = false); -} \ No newline at end of file +} diff --git a/src/FrontOffice.Main/Pages/DiscountStore/Checkout.razor.cs b/src/FrontOffice.Main/Pages/DiscountStore/Checkout.razor.cs index 50cb81b..1185e0b 100644 --- a/src/FrontOffice.Main/Pages/DiscountStore/Checkout.razor.cs +++ b/src/FrontOffice.Main/Pages/DiscountStore/Checkout.razor.cs @@ -40,7 +40,11 @@ public partial class Checkout } await VAT.LoadAsync(); await DiscountCart.EnsureInitializedAsync(); - await LoadAddresses(); + var userInfo = await AuthService.GetUserAuthInfo(); + if (userInfo.HasAddress) + await LoadAddresses(); + else + _addresses = new(); } private async Task LoadAddresses() diff --git a/src/FrontOffice.Main/Pages/Profile/Addresses.razor.cs b/src/FrontOffice.Main/Pages/Profile/Addresses.razor.cs index be3d05d..2a496ef 100644 --- a/src/FrontOffice.Main/Pages/Profile/Addresses.razor.cs +++ b/src/FrontOffice.Main/Pages/Profile/Addresses.razor.cs @@ -1,4 +1,4 @@ -using CMSMicroservice.Protobuf.Protos.UserAddress; +using FrontOffice.Main.Utilities; using CMSMicroservice.Protobuf.Protos.UserAddress; using FrontOffice.Main.Pages.Profile.Components; using Microsoft.AspNetCore.Components; @@ -9,6 +9,7 @@ namespace FrontOffice.Main.Pages.Profile; public partial class Addresses : ComponentBase { [Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!; + [Inject] private AuthService AuthService { get; set; } = default!; private List _addresses = new(); private bool _isLoadingAddresses; @@ -42,7 +43,10 @@ public partial class Addresses : ComponentBase var dialog = await DialogService.ShowAsync("افزودن آدرس جدید"); var result = await dialog.Result; if (result is not null && !result.Canceled) + { await LoadAddresses(); + await AuthService.RefreshTokenAsync(); + } } private async Task OpenEditAddressDialog(CustomerAddressModel address) @@ -80,6 +84,7 @@ public partial class Addresses : ComponentBase await UserAddressContract.DeleteCustomerAddressAsync(new() { Id = id }); Snackbar.Add("آدرس حذف شد.", Severity.Success); await LoadAddresses(); + await AuthService.RefreshTokenAsync(); } catch (Exception ex) { diff --git a/src/FrontOffice.Main/Pages/Profile/Index.razor.cs b/src/FrontOffice.Main/Pages/Profile/Index.razor.cs index 10272ec..2f4a266 100644 --- a/src/FrontOffice.Main/Pages/Profile/Index.razor.cs +++ b/src/FrontOffice.Main/Pages/Profile/Index.razor.cs @@ -333,6 +333,7 @@ public partial class Index if (!result.Canceled) { await LoadAddresses(); + await AuthService.RefreshTokenAsync(); } } @@ -385,6 +386,7 @@ public partial class Index }); Snackbar.Add("آدرس با موفقیت حذف شد.", Severity.Success); await LoadAddresses(); + await AuthService.RefreshTokenAsync(); } catch (Exception ex) { @@ -491,11 +493,6 @@ public partial class Index Snackbar.Add("لطفا اطلاعات شخصی خود را تکمیل کنید. (تاریخ تولد وارد نشده)", Severity.Error); return; } - if (!_addresses.Any()) - { - Snackbar.Add("آدرس محل سکونت شما الزامی است!", Severity.Error); - return; - } var url = "https://dayadiamond.ir/profile/creditpurchase/?merchantcode=56146364"; await JSRuntime.InvokeVoidAsync("open", url, "_blank"); diff --git a/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs b/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs index 5866666..2370755 100644 --- a/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs +++ b/src/FrontOffice.Main/Pages/Profile/WithdrawalRequests.razor.cs @@ -58,8 +58,19 @@ public partial class WithdrawalRequests : ComponentBase try { _isSubmittingWithdrawal = true; - _withdrawIban=_withdrawIban!.Trim().ToUpper().Replace("IR", "").Replace(" ", ""); - await WalletService.RequestWithdrawalAsync(_selectedPayout.Id, _withdrawMethod, "IR"+_withdrawIban); + + string? normalizedIban = null; + if (_withdrawMethod == WithdrawalMethodClient.Cash) + { + normalizedIban = NormalizeIranianIban(_withdrawIban); + if (normalizedIban is null) + { + Snackbar.Add("فرمت شماره شبا معتبر نیست. باید IR و ۲۴ رقم باشد (خط تیره اختیاری است).", Severity.Warning); + return; + } + } + + await WalletService.RequestWithdrawalAsync(_selectedPayout.Id, _withdrawMethod, normalizedIban); Snackbar.Add("درخواست برداشت ثبت شد.", Severity.Success); // بروزرسانی لیست @@ -125,4 +136,26 @@ public partial class WithdrawalRequests : ComponentBase 1 => "الماس", _ => "-" }; + + /// + /// فاصله و خط تیره را حذف می‌کند و شبا را به شکل IR + ۲۴ رقم برمی‌گرداند. + /// + private static string? NormalizeIranianIban(string? iban) + { + if (string.IsNullOrWhiteSpace(iban)) + return null; + + var normalized = iban.Trim().ToUpperInvariant() + .Replace(" ", "", StringComparison.Ordinal) + .Replace("-", "", StringComparison.Ordinal); + + if (normalized.StartsWith("IR", StringComparison.Ordinal)) + normalized = normalized[2..]; + + normalized = "IR" + normalized; + + return System.Text.RegularExpressions.Regex.IsMatch(normalized, @"^IR\d{24}$") + ? normalized + : null; + } } diff --git a/src/FrontOffice.Main/Pages/Store/CheckoutSummary.razor.cs b/src/FrontOffice.Main/Pages/Store/CheckoutSummary.razor.cs index 8437093..0c8aedf 100644 --- a/src/FrontOffice.Main/Pages/Store/CheckoutSummary.razor.cs +++ b/src/FrontOffice.Main/Pages/Store/CheckoutSummary.razor.cs @@ -35,7 +35,11 @@ public partial class CheckoutSummary : ComponentBase await AuthDialogService.ShowAuthDialogAsync(); } await Cart.EnsureInitializedAsync(); - await LoadAddresses(); + var userInfo = await AuthService.GetUserAuthInfo(); + if (userInfo.HasAddress) + await LoadAddresses(); + else + _addresses = new(); await LoadWalletBalance(); } diff --git a/src/FrontOffice.Main/Utilities/AuthService.cs b/src/FrontOffice.Main/Utilities/AuthService.cs index 8fe509a..111d5d6 100644 --- a/src/FrontOffice.Main/Utilities/AuthService.cs +++ b/src/FrontOffice.Main/Utilities/AuthService.cs @@ -79,6 +79,7 @@ public class AuthService var isSignMainContractStr = claims.FirstOrDefault(c => c.key == "IsSignMainContract").value; var hasPurchasedPackageStr = claims.FirstOrDefault(c => c.key == "HasPurchasedPackage").value; var isClubMemberActiveStr = claims.FirstOrDefault(c => c.key == "IsClubMemberActive").value; + var hasAddressStr = claims.FirstOrDefault(c => c.key == "HasAddress").value; _userAuthInfo.UserId = long.TryParse(userIdStr, out var userId) ? userId : 0; _userAuthInfo.FirstName = firstName ?? string.Empty; @@ -88,6 +89,7 @@ public class AuthService _userAuthInfo.IsSignMainContract = bool.TryParse(isSignMainContractStr, out var isSignMainContract) && isSignMainContract; _userAuthInfo.HasPurchasedPackage = bool.TryParse(hasPurchasedPackageStr, out var hasPurchased) && hasPurchased; _userAuthInfo.IsClubMemberActive = bool.TryParse(isClubMemberActiveStr, out var isClubActive) && isClubActive; + _userAuthInfo.HasAddress = bool.TryParse(hasAddressStr, out var hasAddress) && hasAddress; } private async Task?> GetTokenClaimsAsync() diff --git a/src/FrontOffice.Main/Utilities/UserAuthInfo.cs b/src/FrontOffice.Main/Utilities/UserAuthInfo.cs index 32ae68e..043a25b 100644 --- a/src/FrontOffice.Main/Utilities/UserAuthInfo.cs +++ b/src/FrontOffice.Main/Utilities/UserAuthInfo.cs @@ -11,4 +11,5 @@ public class UserAuthInfo public bool IsSignMainContract { get; set; } public bool HasPurchasedPackage { get; set; } public bool IsClubMemberActive { get; set; } + public bool HasAddress { get; set; } } \ No newline at end of file