2025-10-09 22:09:24 +03:30
using Blazored.LocalStorage ;
2025-10-09 21:55:18 +03:30
using FrontOffice.BFF.Package.Protobuf.Protos.Package ;
2025-10-12 23:52:34 +03:30
using FrontOffice.Main.Shared ;
2025-10-09 21:55:18 +03:30
using FrontOffice.Main.Utilities ;
using Grpc.Core ;
using Microsoft.AspNetCore.Components ;
using MudBlazor ;
namespace FrontOffice.Main.Pages ;
public partial class PackageDetail : IDisposable
{
[Parameter] public long Id { get ; set ; }
[Inject] private PackageContract . PackageContractClient PackageClient { get ; set ; } = default ! ;
2025-10-09 22:09:24 +03:30
[Inject] private ILocalStorageService LocalStorage { get ; set ; } = default ! ;
2025-10-09 21:55:18 +03:30
private PackageDetailDto ? _package ;
private List < Review > _reviews = new ( ) ;
private List < RelatedPackage > _relatedPackages = new ( ) ;
private bool _isLoading = true ;
private bool _isPurchasing ;
2025-10-09 22:09:24 +03:30
private bool _isAuthenticated ;
2025-10-09 21:55:18 +03:30
private CancellationTokenSource ? _loadCts ;
2025-10-09 22:09:24 +03:30
// Comment form
private NewComment _newComment = new ( ) ;
private bool _isSubmittingComment ;
2025-10-09 21:55:18 +03:30
private List < BreadcrumbItem > _breadcrumbItems = new ( )
{
new BreadcrumbItem ( "صفحه اصلی" , RouteConstants . Main . MainPage ) ,
new BreadcrumbItem ( "پکیجها" , "#features" ) ,
new BreadcrumbItem ( "جزئیات پکیج" , null , disabled : true )
} ;
protected override async Task OnInitializedAsync ( )
{
2025-10-09 22:09:24 +03:30
await CheckAuthStatus ( ) ;
2025-10-09 21:55:18 +03:30
if ( Id < 1 )
{
_isLoading = false ;
return ;
}
await LoadPackageDetailsAsync ( ) ;
}
protected override async Task OnParametersSetAsync ( )
{
if ( Id > 0 )
{
await LoadPackageDetailsAsync ( ) ;
}
}
private async Task LoadPackageDetailsAsync ( )
{
_isLoading = true ;
_loadCts ? . Cancel ( ) ;
_loadCts ? . Dispose ( ) ;
_loadCts = new CancellationTokenSource ( ) ;
try
{
// Load package details
var packageResponse = await PackageClient . GetPackageAsync ( request : new ( ) { Id = Id } , cancellationToken : _loadCts . Token ) ;
if ( packageResponse ! = null )
{
_package = new PackageDetailDto
{
Id = packageResponse . Id ,
Title = packageResponse . Title ,
Body = packageResponse . Description ,
Image = UrlUtility . DownloadUrl + packageResponse . ImagePath ,
Specifications = new List < Specification >
{
new ( ) { Name = "ظرفیت" , Value = "تا ۲۰۰ عضو" , Icon = Icons . Material . Filled . Group } ,
new ( ) { Name = "شجرهنامه" , Value = "پیشرفته" , Icon = Icons . Material . Filled . AccountTree } ,
new ( ) { Name = "گزارشگیری" , Value = "جامع" , Icon = Icons . Material . Filled . Analytics } ,
new ( ) { Name = "پشتیبانی" , Value = "۲۴ ساعته" , Icon = Icons . Material . Filled . Support }
} ,
Features = new List < string >
{
"مدیریت تیم نامحدود" ,
"شجرهنامه بصری" ,
"محاسبه کارمزد خودکار" ,
"گزارشهای مالی" ,
"پشتیبانی اولویتدار"
} ,
Pricing = new PricingInfo
{
OriginalPrice = packageResponse . Price ,
FinalPrice = packageResponse . Price ,
HasDiscount = false ,
DiscountPercent = 0
}
} ;
// Load reviews (mock data for now)
await LoadReviewsAsync ( ) ;
// Load related packages
await LoadRelatedPackagesAsync ( ) ;
}
}
catch ( RpcException rpcEx )
{
Snackbar . Add ( $"خطا در بارگذاری پکیج: {rpcEx.Status.Detail}" , Severity . Error ) ;
}
catch ( Exception ex )
{
Snackbar . Add ( $"خطا در بارگذاری پکیج: {ex.Message}" , Severity . Error ) ;
}
finally
{
_isLoading = false ;
await InvokeAsync ( StateHasChanged ) ;
}
}
private async Task LoadReviewsAsync ( )
{
// TODO: Load reviews from API
_reviews = new List < Review >
{
new ( ) { UserName = "علی احمدی" , Rating = 5 , Comment = "عالی! کارمزد رو دقیق حساب میکنه و گزارشها کامل هستن." , Date = "۱۴۰۲/۱ ۰ /۰ ۵ " } ,
new ( ) { UserName = "مریم رضایی" , Rating = 4 , Comment = "رابط کاربری خوبی داره، فقط سرعت بارگذاری میتونه بهتر بشه." , Date = "۱۴۰۲/۰۹/۲۲" } ,
new ( ) { UserName = "حسن کریمی" , Rating = 5 , Comment = "پشتیبانی فوقالعاده سریع و حرفهای داشتن. پیشنهاد میکنم." , Date = "۱۴۰۲/۰۹/۱ ۵ " }
} ;
}
private async Task LoadRelatedPackagesAsync ( )
{
// TODO: Load related packages from API
_relatedPackages = new List < RelatedPackage >
{
2025-10-13 00:07:50 +03:30
new ( ) { Id = "2" , Title = "پکیج رشد" , ShortDescription = "مناسب برای تیمهای در حال توسعه" , Image = "images/package1.jpg" , Pricing = new PricingInfo { FinalPrice = 750000 } } ,
new ( ) { Id = "3" , Title = "پکیج حرفهای" , ShortDescription = "برای کسبوکارهای بزرگ" , Image = "images/package2.jpg" , Pricing = new PricingInfo { FinalPrice = 1200000 } }
2025-10-09 21:55:18 +03:30
} ;
}
private async Task PurchasePackage ( )
{
if ( _package = = null ) return ;
_isPurchasing = true ;
try
{
// TODO: Implement purchase logic
await Task . Delay ( 2000 ) ; // Simulate API call
Snackbar . Add ( "پکیج با موفقیت خریداری شد!" , Severity . Success ) ;
}
catch ( Exception ex )
{
Snackbar . Add ( $"خطا در خرید پکیج: {ex.Message}" , Severity . Error ) ;
}
finally
{
_isPurchasing = false ;
await InvokeAsync ( StateHasChanged ) ;
}
}
2025-10-09 22:09:24 +03:30
private async Task CheckAuthStatus ( )
{
var token = await LocalStorage . GetItemAsync < string > ( "auth:token" ) ;
_isAuthenticated = ! string . IsNullOrWhiteSpace ( token ) ;
}
private async Task SubmitComment ( )
{
if ( ! _isAuthenticated )
{
Snackbar . Add ( "برای ثبت نظر ابتدا وارد حساب کاربری شوید." , Severity . Warning ) ;
return ;
}
if ( string . IsNullOrWhiteSpace ( _newComment . Comment ) )
{
Snackbar . Add ( "لطفاً نظر خود را وارد کنید." , Severity . Warning ) ;
return ;
}
if ( _newComment . Rating < 1 | | _newComment . Rating > 5 )
{
Snackbar . Add ( "لطفاً امتیاز را انتخاب کنید." , Severity . Warning ) ;
return ;
}
_isSubmittingComment = true ;
try
{
// TODO: Submit comment to API
await Task . Delay ( 1000 ) ; // Simulate API call
// Add the new comment to the list
var newReview = new Review
{
UserName = "کاربر فعلی" , // TODO: Get from user profile
Rating = _newComment . Rating ,
Comment = _newComment . Comment ,
Date = DateTime . Now . ToString ( "yyyy/MM/dd" )
} ;
_reviews . Insert ( 0 , newReview ) ;
_newComment = new NewComment ( ) ;
Snackbar . Add ( "نظر شما با موفقیت ثبت شد." , Severity . Success ) ;
}
catch ( Exception ex )
{
Snackbar . Add ( $"خطا در ثبت نظر: {ex.Message}" , Severity . Error ) ;
}
finally
{
_isSubmittingComment = false ;
await InvokeAsync ( StateHasChanged ) ;
}
}
2025-10-09 21:55:18 +03:30
private void NavigateToPackage ( string packageId )
{
Navigation . NavigateTo ( $"{RouteConstants.Package.Detail}/{packageId}" ) ;
}
2025-10-12 23:52:34 +03:30
private async Task OpenAuthDialog ( )
{
var dialog = await DialogService . ShowAsync < AuthDialog > ( "ورود به حساب کاربری" ) ;
var result = await dialog . Result ;
if ( ! result . Canceled )
{
// User logged in successfully, refresh the page to show comment form
await CheckAuthStatus ( ) ;
await InvokeAsync ( StateHasChanged ) ;
}
}
2025-10-09 21:55:18 +03:30
public void Dispose ( )
{
_loadCts ? . Cancel ( ) ;
_loadCts ? . Dispose ( ) ;
_loadCts = null ;
}
public class PackageDetailDto
{
public long? Id { get ; set ; }
public string? Title { get ; set ; }
public string? Body { get ; set ; }
public string? Image { get ; set ; }
public List < Specification > Specifications { get ; set ; } = new ( ) ;
public List < string > Features { get ; set ; } = new ( ) ;
public PricingInfo Pricing { get ; set ; } = new ( ) ;
}
public class Specification
{
public string? Name { get ; set ; }
public string? Value { get ; set ; }
public string? Icon { get ; set ; }
}
public class PricingInfo
{
public long OriginalPrice { get ; set ; }
public long FinalPrice { get ; set ; }
public bool HasDiscount { get ; set ; }
public int DiscountPercent { get ; set ; }
}
public class Review
{
public string? UserName { get ; set ; }
public int Rating { get ; set ; }
public string? Comment { get ; set ; }
public string? Date { get ; set ; }
}
public class RelatedPackage
{
public string? Id { get ; set ; }
public string? Title { get ; set ; }
public string? ShortDescription { get ; set ; }
public string? Image { get ; set ; }
public PricingInfo Pricing { get ; set ; } = new ( ) ;
}
2025-10-09 22:09:24 +03:30
public class NewComment
{
public int Rating { get ; set ; } = 5 ;
public string? Comment { get ; set ; }
}
2025-10-09 21:55:18 +03:30
}