298 lines
10 KiB
C#
298 lines
10 KiB
C#
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<Review> _reviews = new();
|
||
private List<RelatedPackage> _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<BreadcrumbItem> _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<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>
|
||
{
|
||
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<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);
|
||
}
|
||
}
|
||
|
||
private void NavigateToPackage(string packageId)
|
||
{
|
||
Navigation.NavigateTo($"{RouteConstants.Package.Detail}/{packageId}");
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
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();
|
||
}
|
||
|
||
public class NewComment
|
||
{
|
||
public int Rating { get; set; } = 5;
|
||
public string? Comment { get; set; }
|
||
}
|
||
} |