diff --git a/src/FrontOffice.Main/Pages/Store/ProductDetail.razor.cs b/src/FrontOffice.Main/Pages/Store/ProductDetail.razor.cs index 4a5fb07..fea4dde 100644 --- a/src/FrontOffice.Main/Pages/Store/ProductDetail.razor.cs +++ b/src/FrontOffice.Main/Pages/Store/ProductDetail.razor.cs @@ -21,6 +21,7 @@ public partial class ProductDetail : ComponentBase, IDisposable private Product? _product; private bool _loading; + private bool _initialized; private int _qty = 1; private const int MinQty = 1; @@ -48,29 +49,35 @@ public partial class ProductDetail : ComponentBase, IDisposable private bool IsInCart => CurrentCartItem is not null; private int CurrentCartQuantity => CurrentCartItem?.Quantity ?? 0; - protected override async Task OnParametersSetAsync() - { - - } - protected override async Task OnInitializedAsync() { _isAuthenticated = await AuthService.IsAuthenticatedAsync(); await Cart.EnsureInitializedAsync(); Cart.OnChange += HandleCartChanged; - - - + _initialized = true; + } + + protected override async Task OnParametersSetAsync() + { + if (!_initialized || id <= 0) + return; + + await LoadProductAsync(); + } + + private async Task LoadProductAsync() + { _loading = true; _product = await ProductService.GetByIdAsync(id); _loading = false; + if (_product is not null) { _galleryItems = BuildGalleryItems(_product); _selectedGalleryImage = _galleryItems.FirstOrDefault(); _categoryPaths = _product.Categories; UpdateBreadcrumb(); - _qty = Math.Clamp(CurrentCartItem?.Quantity ?? _qty, MinQty, MaxQty); + _qty = Math.Clamp(CurrentCartItem?.Quantity ?? MinQty, MinQty, Math.Max(MinQty, MaxQty)); } else { @@ -78,19 +85,16 @@ public partial class ProductDetail : ComponentBase, IDisposable _categoryPaths = Array.Empty(); _breadcrumbItems.Clear(); } - - StateHasChanged(); - await base.OnInitializedAsync(); } protected override async Task OnAfterRenderAsync(bool firstRender) { - await base.OnAfterRenderAsync(firstRender); if (firstRender) { - // بارگذاری نرخ VAT await VAT.LoadAsync(); } + + await base.OnAfterRenderAsync(firstRender); } private async Task AddToCart() diff --git a/src/FrontOffice.Main/Utilities/ProductService.cs b/src/FrontOffice.Main/Utilities/ProductService.cs index 39b7f9c..4bfaeed 100644 --- a/src/FrontOffice.Main/Utilities/ProductService.cs +++ b/src/FrontOffice.Main/Utilities/ProductService.cs @@ -137,30 +137,66 @@ public class ProductService public async Task GetByIdAsync(long id) { - if (TryGetCachedProduct(id, out var cached) && HasDetailedData(cached)) - { - return cached; - } + if (id <= 0) + return null; + TryGetCachedProduct(id, out var cached); + + if (cached is not null && HasDetailedData(cached)) + return cached; + + // جزئیات کامل (گالری + دسته‌بندی) + var detailed = await TryFetchDetailAsync(id); + if (detailed is not null) + return detailed; + + // fallback: همان API لیست محصولات — ناموجودها را هم برمی‌گرداند + var fromFilter = await TryFetchByFilterIdAsync(id); + if (fromFilter is not null) + return fromFilter; + + return cached; + } + + private async Task TryFetchDetailAsync(long id) + { try { var resp = await _client.GetProductsAsync(new GetProductsRequest { Id = id }); - if (resp == null) - { + if (resp is null || resp.Id <= 0) return null; - } return MapAndCache(resp); } catch { - if (cached is not null) - { - return cached; - } + return null; + } + } - TryGetCachedProduct(id, out var result); - return result; + private async Task TryFetchByFilterIdAsync(long id) + { + try + { + var resp = await _client.GetAllProductsByFilterAsync(new GetAllProductsByFilterRequest + { + PaginationState = new CMSMicroservice.Protobuf.Protos.PaginationState + { + PageNumber = 1, + PageSize = 1 + }, + Filter = new GetAllProductsByFilterFilter { Id = id } + }); + + var model = resp.Models.FirstOrDefault(m => m.Id == id); + if (model is null) + return null; + + return MapAndCache(resp.Models).FirstOrDefault(p => p.Id == id); + } + catch + { + return null; } }