diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor
index b0c01f21..3ecd45bf 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor
@@ -252,7 +252,7 @@
break;
case "settings":
-
+
break;
case "schedule":
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs b/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs
index 3e0f0940..76800fd1 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Services/PosDataService.cs
@@ -212,8 +212,19 @@ public class PosDataService
public async Task GetShopByIdAsync(Guid shopId)
=> await GetObjectFromApiAsync($"api/bff/shops/{shopId}");
+ ///
+ /// EN: Get products for a shop. Deduplicates by product ID to prevent UI duplication
+ /// when the API response contains duplicate entries (e.g. from multi-format deserialization).
+ /// VI: Lấy sản phẩm của shop. Loại bỏ trùng lặp theo ID để tránh hiển thị đôi trên UI
+ /// khi API response chứa bản ghi trùng (ví dụ từ deserialization đa định dạng).
+ ///
public async Task> GetProductsAsync(Guid shopId)
- => await GetListFromApiAsync($"api/bff/shops/{shopId}/products");
+ {
+ var products = await GetListFromApiAsync($"api/bff/shops/{shopId}/products");
+ // EN: Deduplicate by Id — prevents double-display regardless of API response shape.
+ // VI: Loại trùng theo Id — ngăn hiển thị đôi bất kể định dạng API response.
+ return products.GroupBy(p => p.Id).Select(g => g.First()).ToList();
+ }
public async Task> GetCategoriesAsync(Guid shopId)
=> await GetListFromApiAsync($"api/bff/shops/{shopId}/categories");
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/CatalogController.cs b/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/CatalogController.cs
index ce230020..6d9dc667 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/CatalogController.cs
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/CatalogController.cs
@@ -34,12 +34,15 @@ public class CatalogController : ControllerBase
}
///
- /// EN: Get products for a specific shop.
- /// VI: Lấy sản phẩm của một cửa hàng cụ thể.
+ /// EN: Get products for a specific shop. POS-facing — only returns active products by default.
+ /// VI: Lấy sản phẩm của một cửa hàng cụ thể. Dành cho POS — chỉ trả về sản phẩm đang hoạt động.
///
[HttpGet("shops/{shopId}/products")]
- public Task GetShopProducts(Guid shopId) =>
- _catalog.GetAsync($"/api/v1/shops/{shopId}/products").ProxyAsync();
+ public Task GetShopProducts(Guid shopId, [FromQuery] bool? isActive = true)
+ {
+ var qs = isActive.HasValue ? $"?isActive={isActive.Value.ToString().ToLower()}" : "";
+ return _catalog.GetAsync($"/api/v1/shops/{shopId}/products{qs}").ProxyAsync();
+ }
///
/// EN: Create a product.