From 5d58d354d79f443cb77c2a8a57579bab37a08165 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Wed, 1 Jul 2026 21:21:57 +0330 Subject: [PATCH] feat: enhance product detail loading and initialization logic - Introduced an `_initialized` flag to manage product loading state more effectively. - Updated `OnParametersSetAsync` to conditionally load product details based on the initialization state and valid product ID. - Refactored product retrieval logic in `ProductService` to handle invalid IDs and improve fallback mechanisms for fetching product details. These changes improve the reliability and performance of the product detail component, ensuring that product information is loaded correctly and efficiently. --- .../Pages/Store/ProductDetail.razor.cs | 32 +++++----- .../Utilities/ProductService.cs | 62 +++++++++++++++---- 2 files changed, 67 insertions(+), 27 deletions(-) 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; } }