From 6a9aa0d46f1fa551e8dd7e6a18b98615f1752bc3 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Wed, 25 Mar 2026 15:27:46 +0700 Subject: [PATCH] fix(overview): load all orders and add date range selector to shop overview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change orders fetch from "today" filter to "all" so KPIs show actual data - Add date range presets (Hôm nay / 7 ngày / 30 ngày / Tất cả) - Add weekly period tab to revenue chart - Display filtered recent orders based on selected period Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Pages/Admin/Shop/ShopOverview.razor | 84 ++++++++++++++----- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopOverview.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopOverview.razor index a6e8e76a..2dbf6968 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopOverview.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopOverview.razor @@ -89,6 +89,22 @@ + @* ── Date Range Selector ── *@ +
+
+ @foreach (var (label, days) in new[] { ("Hôm nay", 0), ("7 ngày", 7), ("30 ngày", 30), ("Tất cả", -1) }) + { + + } +
+ @GetPeriodLabel() +
+ @* ── KPI ROW ── *@
@@ -97,8 +113,8 @@
-
@FormatVND(_orders.Sum(o => o.TotalAmount))
-
Doanh thu tháng
+
@FormatVND(GetFilteredOrders().Sum(o => o.TotalAmount))
+
Doanh thu
@@ -106,8 +122,8 @@
-
@_orders.Count
-
Đơn hàng tháng
+
@GetFilteredOrders().Count
+
Đơn hàng
@@ -115,7 +131,7 @@
-
@FormatVND(_orders.Any() ? _orders.Average(o => o.TotalAmount) : 0)
+
@FormatVND(GetFilteredOrders().Any() ? GetFilteredOrders().Average(o => o.TotalAmount) : 0)
Giá trị TB / đơn
@@ -136,26 +152,36 @@

- Doanh thu 7 ngày gần nhất + Biểu đồ doanh thu

- - + + +
@if (_dailyRevenue.Any()) { - var recent = _revenuePeriod == "monthly" ? _dailyRevenue.TakeLast(30).ToList() : _dailyRevenue.TakeLast(7).ToList(); + var recent = _revenuePeriod switch { + "monthly" => _dailyRevenue.TakeLast(12).ToList(), + "weekly" => _dailyRevenue.TakeLast(8).ToList(), + _ => _dailyRevenue.TakeLast(7).ToList() + }; var maxVal = recent.Max(r => r.Revenue);
@foreach (var r in recent) { var pct = maxVal > 0 ? (int)(r.Revenue / maxVal * 100) : 0; + var barLabel = _revenuePeriod switch { + "monthly" => r.PeriodStart.ToString("MM/yy"), + "weekly" => $"T{r.PeriodStart:dd/MM}", + _ => r.PeriodStart.ToString("dd/MM") + };
@FormatVND(r.Revenue)
- @r.PeriodStart.ToString("dd/MM") + @barLabel
}
@@ -183,10 +209,10 @@
- @if (_orders.Any()) + @if (GetFilteredOrders().Any()) {
- @foreach (var o in _orders.Take(5)) + @foreach (var o in GetFilteredOrders().Take(5)) {
@@ -244,13 +270,12 @@ private PosDataService.ShopInfo? _shop; private string _posVertical = "cafe"; - private List _orders = new(); + private List _allOrders = new(); private List _products = new(); private List _dailyRevenue = new(); private string _revenuePeriod = "daily"; + private int _activePeriod = 30; // default 30 days - // EN: Cascade layout reference to set shop context for sidebar switching. - // VI: Cascade layout để set shop context cho sidebar chuyển đổi. [CascadingParameter] public AdminLayout? Layout { get; set; } protected override async Task OnInitializedAsync() @@ -267,11 +292,12 @@ _posVertical = MapCategoryToVertical(_shop.Category); Layout?.SetShopContext(ShopId, _shop.Name ?? "Cửa hàng", _shop.Category); } - // EN: Load KPI data in parallel / VI: Tải dữ liệu KPI song song - var ordersTask = DataService.GetOrdersAsync(id); + // EN: Load all orders + products + revenue in parallel + // VI: Tải tất cả đơn hàng + sản phẩm + doanh thu song song + var ordersTask = DataService.GetOrdersAsync(id, "all"); var productsTask = DataService.GetAllProductsAsync(id); var revenueTask = DataService.GetRevenueReportAsync("daily", id); - _orders = await ordersTask; + _allOrders = await ordersTask; _products = await productsTask; try { _dailyRevenue = await revenueTask; } catch { _dailyRevenue = new(); } } @@ -284,6 +310,26 @@ finally { IsLoading = false; } } + private List GetFilteredOrders() + { + if (_activePeriod == -1) return _allOrders; // all + if (_activePeriod == 0) return _allOrders.Where(o => o.CreatedAt.Date == DateTime.UtcNow.Date).ToList(); // today + return _allOrders.Where(o => o.CreatedAt >= DateTime.UtcNow.AddDays(-_activePeriod)).ToList(); + } + + private void SetPeriod(int days) + { + _activePeriod = days; + StateHasChanged(); + } + + private string GetPeriodLabel() => _activePeriod switch + { + 0 => DateTime.UtcNow.ToString("dd/MM/yyyy"), + -1 => "Toàn bộ thời gian", + _ => $"{DateTime.UtcNow.AddDays(-_activePeriod):dd/MM} — {DateTime.UtcNow:dd/MM/yyyy}" + }; + private async Task SwitchRevenuePeriod(string period) { _revenuePeriod = period; @@ -295,9 +341,7 @@ } private static string FormatVND(decimal val) => val.ToString("N0") + " ₫"; - private static string GetStatusBadgeClass(string? status) => ShopVerticalHelper.GetStatusBadgeClass(status); - private static string GetStatusLabel(string? status) => ShopVerticalHelper.GetStatusLabel(status); private static string MapCategoryToVertical(string? category) => (category?.ToLowerInvariant()) switch