2025-10-07 01:03:58 +03:30
using FluentValidation ;
2025-10-12 18:16:59 +03:30
using FrontOffice.BFF.User.Protobuf.Protos.User ;
2025-10-13 08:42:31 +03:30
using FrontOffice.Main.Utilities ;
2025-10-12 23:00:59 +03:30
using Mapster ;
2025-10-07 01:03:58 +03:30
using Microsoft.AspNetCore.Components ;
2025-10-12 23:21:30 +03:30
using Microsoft.JSInterop ;
2025-10-07 01:03:58 +03:30
using MudBlazor ;
using System.ComponentModel.DataAnnotations ;
using Severity = MudBlazor . Severity ;
namespace FrontOffice.Main.Pages.Profile ;
public partial class Index
{
2025-10-12 18:16:59 +03:30
[Inject] private UserContract . UserContractClient UserContract { get ; set ; } = default ! ;
private GetUserResponse _userProfile = new ( ) ;
2025-10-12 23:00:59 +03:30
private UpdateUserRequest _updateUserRequest = new ( ) ;
2025-10-07 01:03:58 +03:30
private MudForm ? _personalForm ;
private bool _isPersonalSaving ;
private bool _isSettingsSaving ;
2025-10-12 23:21:30 +03:30
private string _copyMessage = string . Empty ;
2025-10-07 01:03:58 +03:30
private readonly UserProfileValidator _personalValidator = new ( ) ;
2025-10-13 08:42:31 +03:30
private DateTime ? _date ;
2025-10-12 18:16:59 +03:30
protected override async Task OnAfterRenderAsync ( bool firstRender )
2025-10-07 01:03:58 +03:30
{
2025-10-12 18:16:59 +03:30
await base . OnAfterRenderAsync ( firstRender ) ;
2025-10-13 08:42:31 +03:30
if ( firstRender )
2025-10-12 18:16:59 +03:30
{
await LoadUserProfile ( ) ;
}
2025-10-07 01:03:58 +03:30
}
private async Task LoadUserProfile ( )
{
2025-10-12 23:21:30 +03:30
try
{
_userProfile = await UserContract . GetUserAsync ( request : new ( ) ) ;
_updateUserRequest = _userProfile . Adapt < UpdateUserRequest > ( ) ;
2025-10-13 08:42:31 +03:30
if ( _userProfile . BirthDate ! = null )
_date = _userProfile . BirthDate . ToDateTime ( ) ;
2025-10-12 23:21:30 +03:30
}
catch ( Exception ex )
{
// Handle the case when user is not authenticated or API fails
_userProfile = new GetUserResponse ( ) ;
}
2025-10-12 18:16:59 +03:30
StateHasChanged ( ) ;
2025-10-07 01:03:58 +03:30
}
2025-10-12 23:21:30 +03:30
2025-10-07 01:03:58 +03:30
private async Task SavePersonalInfo ( )
{
if ( _personalForm is null ) return ;
await _personalForm . Validate ( ) ;
if ( ! _personalForm . IsValid ) return ;
_isPersonalSaving = true ;
try
{
2025-10-13 08:42:31 +03:30
if ( _date ! = null )
_updateUserRequest . BirthDate = _date . Value . DateTimeToTimestamp ( ) ;
2025-10-12 23:00:59 +03:30
await UserContract . UpdateUserAsync ( request : _updateUserRequest ) ;
await LoadUserProfile ( ) ;
2025-10-07 01:03:58 +03:30
Snackbar . Add ( "اطلاعات شخصی با موفقیت ذخیره شد." , Severity . Success ) ;
}
catch ( Exception ex )
{
Snackbar . Add ( $"خطا در ذخیره اطلاعات: {ex.Message}" , Severity . Error ) ;
}
finally
{
_isPersonalSaving = false ;
await InvokeAsync ( StateHasChanged ) ;
}
}
private void CancelPersonalChanges ( )
{
// TODO: Reset form to original values
Snackbar . Add ( "تغییرات لغو شد." , Severity . Info ) ;
}
private async Task SaveSettings ( )
{
_isSettingsSaving = true ;
try
{
2025-10-13 08:42:31 +03:30
await SavePersonalInfo ( ) ;
2025-10-07 01:03:58 +03:30
Snackbar . Add ( "تنظیمات با موفقیت ذخیره شد." , Severity . Success ) ;
}
catch ( Exception ex )
{
Snackbar . Add ( $"خطا در ذخیره تنظیمات: {ex.Message}" , Severity . Error ) ;
}
finally
{
_isSettingsSaving = false ;
await InvokeAsync ( StateHasChanged ) ;
}
}
2025-10-12 23:21:30 +03:30
private async Task CopyReferralCode ( )
{
try
{
await JSRuntime . InvokeVoidAsync ( "navigator.clipboard.writeText" , $"{Navigation.BaseUri}?ref={_userProfile.ReferralCode}" ) ;
_copyMessage = "کد دعوت کپی شد!" ;
Snackbar . Add ( "کد دعوت در کلیپبورد کپی شد." , Severity . Success ) ;
// Clear message after 3 seconds
await Task . Delay ( 3000 ) ;
_copyMessage = string . Empty ;
await InvokeAsync ( StateHasChanged ) ;
}
catch ( Exception ex )
{
Snackbar . Add ( "خطا در کپی کردن کد دعوت." , Severity . Error ) ;
}
}
private async Task ShareReferralCode ( )
{
var shareText = $"کد دعوت من در فرصت: {_userProfile.ReferralCode}\nبرا ی عضویت از این لینک استفاده کنید: {Navigation.BaseUri}?ref={_userProfile.ReferralCode}" ;
try
{
// Try to use Web Share API if available
await JSRuntime . InvokeVoidAsync ( "navigator.share" ,
new
{
title = "کد دعوت فرصت" ,
text = shareText ,
url = $"{Navigation.BaseUri}?ref={_userProfile.ReferralCode}"
} ) ;
}
catch
{
// Fallback: copy to clipboard
await JSRuntime . InvokeVoidAsync ( "navigator.clipboard.writeText" , $"{Navigation.BaseUri}?ref={_userProfile.ReferralCode}" ) ;
Snackbar . Add ( "لینک دعوت در کلیپبورد کپی شد." , Severity . Success ) ;
}
}
2025-10-07 01:03:58 +03:30
public class UserProfile
{
[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 < UserProfile >
{
public UserProfileValidator ( )
{
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 ( "شماره موبایل الزامی است" ) ;
}
}
}