Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Has been cancelled

This commit is contained in:
masoodafar-web
2026-07-01 21:31:49 +03:30
2 changed files with 67 additions and 27 deletions
@@ -21,6 +21,7 @@ public partial class ProductDetail : ComponentBase, IDisposable
private Product? _product; private Product? _product;
private bool _loading; private bool _loading;
private bool _initialized;
private int _qty = 1; private int _qty = 1;
private const int MinQty = 1; private const int MinQty = 1;
@@ -48,29 +49,35 @@ public partial class ProductDetail : ComponentBase, IDisposable
private bool IsInCart => CurrentCartItem is not null; private bool IsInCart => CurrentCartItem is not null;
private int CurrentCartQuantity => CurrentCartItem?.Quantity ?? 0; private int CurrentCartQuantity => CurrentCartItem?.Quantity ?? 0;
protected override async Task OnParametersSetAsync()
{
}
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
_isAuthenticated = await AuthService.IsAuthenticatedAsync(); _isAuthenticated = await AuthService.IsAuthenticatedAsync();
await Cart.EnsureInitializedAsync(); await Cart.EnsureInitializedAsync();
Cart.OnChange += HandleCartChanged; Cart.OnChange += HandleCartChanged;
_initialized = true;
}
protected override async Task OnParametersSetAsync()
{
if (!_initialized || id <= 0)
return;
await LoadProductAsync();
}
private async Task LoadProductAsync()
{
_loading = true; _loading = true;
_product = await ProductService.GetByIdAsync(id); _product = await ProductService.GetByIdAsync(id);
_loading = false; _loading = false;
if (_product is not null) if (_product is not null)
{ {
_galleryItems = BuildGalleryItems(_product); _galleryItems = BuildGalleryItems(_product);
_selectedGalleryImage = _galleryItems.FirstOrDefault(); _selectedGalleryImage = _galleryItems.FirstOrDefault();
_categoryPaths = _product.Categories; _categoryPaths = _product.Categories;
UpdateBreadcrumb(); UpdateBreadcrumb();
_qty = Math.Clamp(CurrentCartItem?.Quantity ?? _qty, MinQty, MaxQty); _qty = Math.Clamp(CurrentCartItem?.Quantity ?? MinQty, MinQty, Math.Max(MinQty, MaxQty));
} }
else else
{ {
@@ -78,19 +85,16 @@ public partial class ProductDetail : ComponentBase, IDisposable
_categoryPaths = Array.Empty<ProductCategoryPathInfo>(); _categoryPaths = Array.Empty<ProductCategoryPathInfo>();
_breadcrumbItems.Clear(); _breadcrumbItems.Clear();
} }
StateHasChanged();
await base.OnInitializedAsync();
} }
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
{ {
await base.OnAfterRenderAsync(firstRender);
if (firstRender) if (firstRender)
{ {
// بارگذاری نرخ VAT
await VAT.LoadAsync(); await VAT.LoadAsync();
} }
await base.OnAfterRenderAsync(firstRender);
} }
private async Task AddToCart() private async Task AddToCart()
@@ -137,30 +137,66 @@ public class ProductService
public async Task<Product?> GetByIdAsync(long id) public async Task<Product?> GetByIdAsync(long id)
{ {
if (TryGetCachedProduct(id, out var cached) && HasDetailedData(cached)) if (id <= 0)
{ return null;
return cached;
}
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<Product?> TryFetchDetailAsync(long id)
{
try try
{ {
var resp = await _client.GetProductsAsync(new GetProductsRequest { Id = id }); var resp = await _client.GetProductsAsync(new GetProductsRequest { Id = id });
if (resp == null) if (resp is null || resp.Id <= 0)
{
return null; return null;
}
return MapAndCache(resp); return MapAndCache(resp);
} }
catch catch
{ {
if (cached is not null) return null;
{ }
return cached; }
}
TryGetCachedProduct(id, out var result); private async Task<Product?> TryFetchByFilterIdAsync(long id)
return result; {
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;
} }
} }