diff --git a/src/FrontOffice.Main/Pages/Profile/AddressDialog.razor b/src/FrontOffice.Main/Pages/Profile/AddressDialog.razor new file mode 100644 index 0000000..322077f --- /dev/null +++ b/src/FrontOffice.Main/Pages/Profile/AddressDialog.razor @@ -0,0 +1,52 @@ + + + + @(IsEdit ? "ویرایش آدرس" : "افزودن آدرس جدید") + + + + + + + + + + + + + + + + لغو + + @(IsEdit ? "ویرایش آدرس" : "افزودن آدرس") + + + \ No newline at end of file diff --git a/src/FrontOffice.Main/Pages/Profile/AddressDialog.razor.cs b/src/FrontOffice.Main/Pages/Profile/AddressDialog.razor.cs new file mode 100644 index 0000000..414acff --- /dev/null +++ b/src/FrontOffice.Main/Pages/Profile/AddressDialog.razor.cs @@ -0,0 +1,64 @@ +using FrontOffice.BFF.UserAddress.Protobuf.Protos.UserAddress; +using FrontOffice.BFF.UserAddress.Protobuf.Validator; +using Mapster; +using Microsoft.AspNetCore.Components; +using MudBlazor; +using Severity = MudBlazor.Severity; + +namespace FrontOffice.Main.Pages.Profile; + +public partial class AddressDialog : ComponentBase +{ + [CascadingParameter] private MudDialogInstance MudDialog { get; set; } = default!; + [Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!; + + [Parameter] public GetAllUserAddressByFilterResponseModel? Model { get; set; } + [Parameter] public bool IsEdit { get; set; } + + private MudForm? _form; + private readonly UpdateUserAddressRequestValidator _validator = new(); + private bool _isSaving; + private UpdateUserAddressRequest _request = new(); + protected override void OnInitialized() + { + base.OnInitialized(); + if (Model != null) + _request = Model.Adapt(); + } + private async Task SaveAddress() + { + if (_form == null) return; + + await _form.Validate(); + if (!_form.IsValid) return; + + _isSaving = true; + try + { + if (IsEdit) + { + await UserAddressContract.UpdateUserAddressAsync(_request); + Snackbar.Add("آدرس با موفقیت ویرایش شد.", Severity.Success); + MudDialog.Close(DialogResult.Ok(true)); + } + else + { + var createRequest = _request.Adapt(); + var response = await UserAddressContract.CreateNewUserAddressAsync(createRequest); + Snackbar.Add("آدرس با موفقیت اضافه شد.", Severity.Success); + MudDialog.Close(DialogResult.Ok(true)); + } + } + catch (Exception ex) + { + Snackbar.Add($"خطا: {ex.Message}", Severity.Error); + } + finally + { + _isSaving = false; + await InvokeAsync(StateHasChanged); + } + } + + private void Cancel() => MudDialog.Cancel(); +} \ No newline at end of file diff --git a/src/FrontOffice.Main/Pages/Profile/Index.razor b/src/FrontOffice.Main/Pages/Profile/Index.razor index c661f56..080126e 100644 --- a/src/FrontOffice.Main/Pages/Profile/Index.razor +++ b/src/FrontOffice.Main/Pages/Profile/Index.razor @@ -64,7 +64,7 @@
- + + + +
+ + + + آدرس‌های شما + + افزودن آدرس جدید + + + + + @if (_isLoadingAddresses) + { + + + در حال بارگذاری آدرس‌ها... + + } + else if (_addresses.Any()) + { + + @foreach (var address in _addresses) + { + + + + + + @address.Title + @if (address.IsDefault) + { + پیش‌فرض + } + + @address.Address + کد پستی: @address.PostalCode + + + + ویرایش + @if (!address.IsDefault) + { + تنظیم به عنوان پیش‌فرض + } + + حذف + + + + + } + + } + else + { + + + هنوز آدرسی ثبت نکرده‌اید. + + افزودن اولین آدرس + + + } + +
+
+
diff --git a/src/FrontOffice.Main/Pages/Profile/Index.razor.cs b/src/FrontOffice.Main/Pages/Profile/Index.razor.cs index f3fc1aa..e0c05a9 100644 --- a/src/FrontOffice.Main/Pages/Profile/Index.razor.cs +++ b/src/FrontOffice.Main/Pages/Profile/Index.razor.cs @@ -1,5 +1,8 @@ using FluentValidation; using FrontOffice.BFF.User.Protobuf.Protos.User; +using FrontOffice.BFF.User.Protobuf.Validator; +using FrontOffice.BFF.UserAddress.Protobuf.Protos.UserAddress; +using FrontOffice.BFF.UserAddress.Protobuf.Validator; using FrontOffice.Main.Utilities; using Mapster; using Microsoft.AspNetCore.Components; @@ -13,9 +16,11 @@ namespace FrontOffice.Main.Pages.Profile; public partial class Index { [Inject] private UserContract.UserContractClient UserContract { get; set; } = default!; + [Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!; private GetUserResponse _userProfile = new(); private UpdateUserRequest _updateUserRequest = new(); + private readonly UpdateUserRequestValidator _personalValidator = new(); private MudForm? _personalForm; @@ -24,14 +29,22 @@ public partial class Index private string _copyMessage = string.Empty; - private readonly UserProfileValidator _personalValidator = new(); private DateTime? _date; + + // Address management + private List _addresses = new(); + private bool _isLoadingAddresses; + private CreateNewUserAddressRequest _newAddressRequest = new(); + private UpdateUserAddressRequest _editAddressRequest = new(); + private MudForm? _addressForm; + private readonly CreateNewUserAddressRequestValidator _addressValidator = new(); protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); if (firstRender) { await LoadUserProfile(); + await LoadAddresses(); } } @@ -52,7 +65,6 @@ public partial class Index StateHasChanged(); } - private async Task SavePersonalInfo() { if (_personalForm is null) return; @@ -82,12 +94,6 @@ public partial class Index } } - private void CancelPersonalChanges() - { - // TODO: Reset form to original values - Snackbar.Add("تغییرات لغو شد.", Severity.Info); - } - private async Task SaveSettings() { @@ -95,10 +101,7 @@ public partial class Index try { - await SavePersonalInfo(); - - Snackbar.Add("تنظیمات با موفقیت ذخیره شد.", Severity.Success); } catch (Exception ex) { @@ -153,50 +156,104 @@ public partial class Index } } - public class UserProfile + // Address management methods + private async Task LoadAddresses() { - [Required(ErrorMessage = "نام الزامی است")] - public string? FirstName { get; set; } - - [Required(ErrorMessage = "نام خانوادگی الزامی است")] - public string? LastName { get; set; } - - [Required(ErrorMessage = "ایمیل الزامی است")] - [EmailAddress(ErrorMessage = "فرمت ایمیل صحیح نیست")] - public string? Email { get; set; } - - [Required(ErrorMessage = "شماره موبایل الزامی است")] - public string? PhoneNumber { get; set; } - - public string? NationalCode { get; set; } - public string? BirthDate { get; set; } - public string? Address { get; set; } - - // Read-only fields - public string? JoinDate { get; set; } - public string? LastLogin { get; set; } - public int TotalReferrals { get; set; } - public string? Level { get; set; } - } - public class AccountSettings - { - public bool EmailNotifications { get; set; } - public bool SmsNotifications { get; set; } - public bool PushNotifications { get; set; } - public bool ProfileVisibility { get; set; } - public bool ShowOnlineStatus { get; set; } - public string? Language { get; set; } - public string? Theme { get; set; } - } - - public class UserProfileValidator : AbstractValidator - { - public UserProfileValidator() + _isLoadingAddresses = true; + try { - RuleFor(x => x.FirstName).NotEmpty().WithMessage("نام الزامی است"); - RuleFor(x => x.LastName).NotEmpty().WithMessage("نام خانوادگی الزامی است"); - RuleFor(x => x.Email).NotEmpty().EmailAddress().WithMessage("ایمیل معتبر نیست"); - RuleFor(x => x.PhoneNumber).NotEmpty().WithMessage("شماره موبایل الزامی است"); + var response = await UserAddressContract.GetAllUserAddressByFilterAsync(request: new()); + if (response?.Models?.Any() == true) + { + _addresses = response.Models.ToList(); + } + 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 OpenAddAddressDialog() + { + _newAddressRequest = new CreateNewUserAddressRequest(); + var dialog = await DialogService.ShowAsync("افزودن آدرس جدید", new DialogParameters + { + { x => x.IsEdit, false } + }); + var result = await dialog.Result; + + if (!result.Canceled) + { + await LoadAddresses(); + } + } + + private async Task OpenEditAddressDialog(GetAllUserAddressByFilterResponseModel address) + { + var dialog = await DialogService.ShowAsync("ویرایش آدرس", new DialogParameters + { + { x => x.Model, address }, + { x => x.IsEdit, true } + }); + var result = await dialog.Result; + + if (!result.Canceled) + { + await LoadAddresses(); + } + } + + private async Task SetAsDefaultAddress(long addressId) + { + try + { + await UserAddressContract.SetAddressAsDefaultAsync(request: new() + { + Id = addressId + }); + Snackbar.Add("آدرس پیش‌فرض با موفقیت تغییر کرد.", Severity.Success); + await LoadAddresses(); + } + catch (Exception ex) + { + Snackbar.Add($"خطا در تغییر آدرس پیش‌فرض: {ex.Message}", Severity.Error); + } + } + + private async Task DeleteAddress(long addressId) + { + var result = await DialogService.ShowMessageBox( + "تأیید حذف", + "آیا از حذف این آدرس اطمینان دارید؟", + yesText: "حذف", + cancelText: "لغو"); + + if (result == true) + { + try + { + await UserAddressContract.DeleteUserAddressAsync(request: new() + { + Id = addressId + }); + Snackbar.Add("آدرس با موفقیت حذف شد.", Severity.Success); + await LoadAddresses(); + } + catch (Exception ex) + { + Snackbar.Add($"خطا در حذف آدرس: {ex.Message}", Severity.Error); + } } } } \ No newline at end of file