@*
EN: Restaurant POS Desktop — Table map grid + order panel for dine-in service.
VI: POS Nhà hàng Desktop — Lưới sơ đồ bàn + panel đặt món cho phục vụ tại chỗ.
*@
@page "/pos/{ShopId:guid}/restaurant"
@layout PosLayout
@inherits PosBase
@inject WebClientTpos.Client.Services.PosDataService DataService
@if (_isLoading)
{
Đang tải...
}
else if (_loadError)
{
Không thể tải dữ liệu
}
else
{
@* ═══ SECTION TABS / TAB KHU VỰC ═══ *@
@foreach (var section in _sections)
{
}
@* ═══ TABLE MAP GRID / LƯỚI SƠ ĐỒ BÀN ═══ *@
@foreach (var table in FilteredTables)
{
SelectTable(table)"
style="background:@GetStatusColor(table.Status);border-radius:var(--pos-radius);
padding:16px;text-align:center;cursor:pointer;border:2px solid @(SelectedTable?.Id == table.Id ? "var(--pos-orange-primary)" : "transparent");
transition:all .2s ease;">
@table.Name
@table.Seats chỗ
@GetStatusLabel(table.Status)
}
}
@* ═══ ORDER PANEL (RIGHT) / PANEL ĐẶT MÓN (PHẢI) ═══ *@
@if (SelectedTable is not null)
{
@if (SelectedTable.Status == "occupied")
{
@foreach (var item in _demoOrderItems)
{
@item.Name
@FormatPrice(item.Price)
x@item.Qty
}
}
else
{
Bàn trống — Nhấn để mở đơn mới
}
}
else
{
Chọn bàn để bắt đầu
}
@code {
// EN: Loading state / VI: Trạng thái tải
private bool _isLoading = true;
private bool _loadError;
// EN: Active section filter / VI: Bộ lọc khu vực
private string _activeSection = "Tất cả";
private string[] _sections = { "Tất cả" };
// EN: Selected table reference / VI: Bàn đang chọn
private TableInfo? SelectedTable { get; set; }
// EN: Table data from API / VI: Dữ liệu bàn từ API
private List _tables = new();
private IEnumerable FilteredTables =>
_activeSection == "Tất cả" ? _tables : _tables.Where(t => t.Section == _activeSection);
// EN: Demo order items for occupied tables / VI: Món mẫu cho bàn đang phục vụ
private readonly List _demoOrderItems = new()
{
new("Phở bò tái", 75_000, 2), new("Gỏi cuốn", 45_000, 1),
new("Cơm tấm sườn", 65_000, 1), new("Trà đá", 10_000, 3),
};
protected override async Task OnInitializedAsync()
{
try
{
var apiTables = await DataService.GetTablesAsync(ShopId);
_tables = apiTables.Select(t => new TableInfo(
t.Id.ToString(),
$"Bàn {t.TableNumber}",
t.Capacity,
t.Status ?? "available",
t.Zone ?? "Trong nhà"
)).ToList();
var zones = _tables.Select(t => t.Section).Distinct().ToList();
_sections = new[] { "Tất cả" }.Concat(zones).ToArray();
}
catch
{
_loadError = true;
}
finally
{
_isLoading = false;
}
}
private void SelectTable(TableInfo table) => SelectedTable = table;
private static string GetStatusColor(string status) => status switch
{
"available" => "rgba(34,197,94,.15)", "occupied" => "rgba(255,92,0,.18)",
"reserved" => "rgba(59,130,246,.18)", _ => "var(--pos-bg-interactive)"
};
private static string GetStatusLabel(string status) => status switch
{
"available" => "Trống", "occupied" => "Đang phục vụ", "reserved" => "Đã đặt", _ => status
};
private record TableInfo(string Id, string Name, int Seats, string Status, string Section);
private record OrderItem(string Name, decimal Price, int Qty);
}