using Blazored.LocalStorage; using FrontOffice.BFF.Package.Protobuf.Protos.Package; using FrontOffice.Main.Shared; 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!; [Inject] private ILocalStorageService LocalStorage { get; set; } = default!; private PackageDetailDto? _package; private List _reviews = new(); private List _relatedPackages = new(); private bool _isLoading = true; private bool _isPurchasing; private bool _isAuthenticated; private CancellationTokenSource? _loadCts; // Comment form private NewComment _newComment = new(); private bool _isSubmittingComment; private List _breadcrumbItems = new() { new BreadcrumbItem("صفحه اصلی", RouteConstants.Main.MainPage), new BreadcrumbItem("پکیج‌ها", "#features"), new BreadcrumbItem("جزئیات پکیج", null, disabled: true) }; protected override async Task OnInitializedAsync() { await CheckAuthStatus(); 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 { 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 { "مدیریت تیم نامحدود", "شجره‌نامه بصری", "محاسبه کارمزد خودکار", "گزارش‌های مالی", "پشتیبانی اولویت‌دار" }, 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 { 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 { 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 } } }; } private async Task PurchasePackage() { if (_package == null) return; _isPurchasing = true; try { // Navigate to checkout page with package ID Navigation.NavigateTo($"{RouteConstants.Checkout.Index}/{_package.Id}"); } catch (Exception ex) { Snackbar.Add($"خطا در انتقال به صفحه پرداخت: {ex.Message}", Severity.Error); } finally { _isPurchasing = false; await InvokeAsync(StateHasChanged); } } private async Task CheckAuthStatus() { var token = await LocalStorage.GetItemAsync("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); } } private void NavigateToPackage(string packageId) { Navigation.NavigateTo($"{RouteConstants.Package.Detail}/{packageId}"); } private async Task OpenAuthDialog() { var dialog = await DialogService.ShowAsync("ورود به حساب کاربری"); var result = await dialog.Result; if (!result.Canceled) { // User logged in successfully, refresh the page to show comment form await CheckAuthStatus(); await InvokeAsync(StateHasChanged); } } 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 Specifications { get; set; } = new(); public List 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(); } public class NewComment { public int Rating { get; set; } = 5; public string? Comment { get; set; } } }