fix(admin): dashboard loads shops from BFF API, shows onboarding when empty
- Inject PosDataService and load shops in OnInitializedAsync - Show 'Welcome! Tạo cửa hàng đầu tiên' with onboarding link when no shops - Render dynamic shop cards from DB data when shops exist - Keep existing KPI cards and alerts/activity panels unchanged Co-authored-by: Velik <hongochai10@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
@page "/admin"
|
||||
@layout AdminLayout
|
||||
@inherits AdminBase
|
||||
@inject PosDataService DataService
|
||||
@using WebClientTpos.Client.Services
|
||||
|
||||
@*
|
||||
EN: Admin Dashboard — overview of business metrics, stores, alerts, and recent activity.
|
||||
@@ -107,123 +109,47 @@
|
||||
<i data-lucide="store" style="color:var(--admin-orange-primary);"></i>
|
||||
Cửa hàng của bạn
|
||||
</h3>
|
||||
<a href="/admin/stores" class="admin-panel__action">Quản lý tất cả →</a>
|
||||
@if (_shops.Count > 0)
|
||||
{
|
||||
<a href="/admin/stores" class="admin-panel__action">Quản lý tất cả →</a>
|
||||
}
|
||||
</div>
|
||||
<div class="admin-panel__body" style="display:flex;flex-direction:column;gap:12px;">
|
||||
@* Store 1: Coffee House Q1 *@
|
||||
<div class="admin-store-card">
|
||||
<div class="admin-store-card__top">
|
||||
<div class="admin-store-card__info">
|
||||
<div class="admin-store-card__avatar" style="background-color:rgba(255,92,0,0.125);">
|
||||
<i data-lucide="coffee" style="color:var(--admin-orange-primary);"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="admin-store-card__name">Coffee House Q1</div>
|
||||
<div class="admin-store-card__type">Café • 123 Nguyễn Huệ, Q1</div>
|
||||
@if (_shops.Count == 0)
|
||||
{
|
||||
<div style="text-align:center;padding:40px 20px;">
|
||||
<i data-lucide="store" style="width:48px;height:48px;color:var(--admin-orange-primary);margin-bottom:16px;"></i>
|
||||
<h3 style="font-size:18px;font-weight:700;color:var(--pos-text-primary, #FFFFFF);margin:0 0 8px;">Welcome! Tạo cửa hàng đầu tiên</h3>
|
||||
<p style="font-size:14px;color:var(--pos-text-tertiary, #ADADB0);margin:0 0 20px;">Bắt đầu bằng việc tạo cửa hàng để quản lý kinh doanh của bạn.</p>
|
||||
<a href="/admin/onboarding/store" class="admin-btn-primary" style="display:inline-flex;align-items:center;gap:8px;">
|
||||
<i data-lucide="plus" style="width:16px;height:16px;"></i>
|
||||
Tạo cửa hàng ngay
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var shop in _shops)
|
||||
{
|
||||
<div class="admin-store-card">
|
||||
<div class="admin-store-card__top">
|
||||
<div class="admin-store-card__info">
|
||||
<div class="admin-store-card__avatar" style="background-color:rgba(255,92,0,0.125);">
|
||||
<i data-lucide="@GetShopIcon(shop.Category)" style="color:var(--admin-orange-primary);"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="admin-store-card__name">@shop.Name</div>
|
||||
<div class="admin-store-card__type">@(shop.Category ?? "Shop") • @(shop.Description ?? shop.Slug)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-status-badge admin-status-badge--@(shop.Status == "active" ? "online" : "setup")">
|
||||
<span class="admin-status-badge__dot"></span>
|
||||
@(shop.Status == "active" ? "Đang mở" : "Thiết lập")
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-status-badge admin-status-badge--online">
|
||||
<span class="admin-status-badge__dot"></span>
|
||||
Đang mở
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-store-card__stats">
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">45.2M</div>
|
||||
<div class="admin-store-stat__label">Doanh thu</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">342</div>
|
||||
<div class="admin-store-stat__label">Đơn hàng</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">5</div>
|
||||
<div class="admin-store-stat__label">Nhân viên</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">48</div>
|
||||
<div class="admin-store-stat__label">Sản phẩm</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Store 2: Nhà hàng Q3 *@
|
||||
<div class="admin-store-card">
|
||||
<div class="admin-store-card__top">
|
||||
<div class="admin-store-card__info">
|
||||
<div class="admin-store-card__avatar" style="background-color:rgba(59,130,246,0.125);">
|
||||
<i data-lucide="utensils" style="color:#3B82F6;"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="admin-store-card__name">Nhà hàng Q3</div>
|
||||
<div class="admin-store-card__type">Restaurant • 456 Lê Văn Sỹ, Q3</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-status-badge admin-status-badge--online">
|
||||
<span class="admin-status-badge__dot"></span>
|
||||
Đang mở
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-store-card__stats">
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">62.8M</div>
|
||||
<div class="admin-store-stat__label">Doanh thu</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">185</div>
|
||||
<div class="admin-store-stat__label">Đơn hàng</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">8</div>
|
||||
<div class="admin-store-stat__label">Nhân viên</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">72</div>
|
||||
<div class="admin-store-stat__label">Sản phẩm</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Store 3: Karaoke Star Q7 *@
|
||||
<div class="admin-store-card">
|
||||
<div class="admin-store-card__top">
|
||||
<div class="admin-store-card__info">
|
||||
<div class="admin-store-card__avatar" style="background-color:rgba(139,92,246,0.125);">
|
||||
<i data-lucide="mic" style="color:#8B5CF6;"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="admin-store-card__name">Karaoke Star Q7</div>
|
||||
<div class="admin-store-card__type">Karaoke • 789 Nguyễn Thị Thập, Q7</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-status-badge admin-status-badge--setup">
|
||||
<span class="admin-status-badge__dot"></span>
|
||||
Thiết lập
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-store-card__stats">
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">--</div>
|
||||
<div class="admin-store-stat__label">Doanh thu</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">--</div>
|
||||
<div class="admin-store-stat__label">Đơn hàng</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">0</div>
|
||||
<div class="admin-store-stat__label">Nhân viên</div>
|
||||
</div>
|
||||
<div class="admin-store-stat">
|
||||
<div class="admin-store-stat__value">0</div>
|
||||
<div class="admin-store-stat__label">Sản phẩm</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="admin-store-card__cta admin-store-card__cta--warning">
|
||||
<i data-lucide="settings" style="width:14px;height:14px;"></i>
|
||||
Hoàn tất thiết lập
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -316,3 +242,34 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private List<PosDataService.ShopInfo> _shops = new();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
IsLoading = true;
|
||||
try
|
||||
{
|
||||
_shops = await DataService.GetShopsAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_shops = new();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetShopIcon(string? category) => category?.ToLowerInvariant() switch
|
||||
{
|
||||
"cafe" or "café" or "coffee" => "coffee",
|
||||
"restaurant" or "nhà hàng" => "utensils",
|
||||
"karaoke" => "mic",
|
||||
"spa" => "sparkles",
|
||||
"retail" => "shopping-bag",
|
||||
_ => "store"
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user