- @if (_isLoading)
+@* ═══════════════ MAIN CONTENT AREA ═══════════════ *@
+
+ @switch (_activeTab)
{
-
- Đang tải...
-
- }
- else if (_loadError)
- {
-
- Không thể tải dữ liệu
-
- }
- else
- {
- @* EN: Category tabs / VI: Tab danh mục *@
-
- @foreach (var cat in _categories)
- {
-
- }
-
-
- @* EN: Product grid / VI: Lưới sản phẩm *@
-
- @foreach (var product in FilteredProducts)
- {
-
AddToCart(product)">
-
-
+ case PosTab.Sale:
+ @* ═══ PRODUCT PANEL (LEFT) ═══ *@
+
+ @if (_isLoading)
+ {
+
+ Đang tải...
-
@product.Name
-
@FormatPrice(product.Price)
+ }
+ else if (_loadError)
+ {
+
+ Không thể tải dữ liệu
+
+ }
+ else
+ {
+
+ @foreach (var cat in _categories)
+ {
+
+ }
+
+
+
+ @foreach (var product in FilteredProducts)
+ {
+
AddToCart(product)">
+
+
+
+
@product.Name
+
@FormatPrice(product.Price)
+
+ }
+
+ }
+
+
+ @* ═══ CART / PAYMENT PANEL (RIGHT) ═══ *@
+
+ @if (_paymentStep == PayStep.None)
+ {
+ @* ─── NORMAL CART MODE ─── *@
+
+
+ @foreach (var item in _cartItems)
+ {
+
+
+ @item.Name
+ @FormatPrice(item.Price)
+
+
+
+ @item.Qty
+
+
+
+ }
+
+
+ }
+ else if (_paymentStep == PayStep.MethodSelect)
+ {
+ @* ─── PAYMENT: METHOD SELECT ─── *@
+
+
+
+
+
+
+
+
+
+ }
+ else if (_paymentStep == PayStep.AmountInput)
+ {
+ @* ─── PAYMENT: CASH AMOUNT INPUT ─── *@
+
+
+
+
Số tiền nhanh
+
+ @foreach (var qa in GetQuickAmounts())
+ {
+
+ }
+
+
Nhập số tiền
+
+ @if (!string.IsNullOrEmpty(_customAmountInput))
+ {
+
+ }
+
+
+ Khách đưa
+ @FormatPrice(_receivedAmount)
+
+
+ Tiền thối
+
+ @FormatPrice(ChangeAmount)
+
+
+
+
+
+
+
+
+ }
+ else if (_paymentStep == PayStep.Processing)
+ {
+ @* ─── PAYMENT: QR/CARD/TRANSFER — Confirm ─── *@
+
+
+
+
@FormatPrice(CartTotal)
+ @if (_selectedMethod == "qr")
+ {
+
+
Quét mã bằng app Ngân hàng / MoMo / ZaloPay
+ }
+ else if (_selectedMethod == "card")
+ {
+
💳
+
Chạm, quẹt hoặc cắm thẻ
+ }
+ else
+ {
+
🏦
+
Xác nhận đã nhận chuyển khoản
+ }
+
+
+
+
+
+ }
+ else if (_paymentStep == PayStep.Success)
+ {
+ @* ─── PAYMENT: SUCCESS ─── *@
+
+
+
Thanh toán thành công!
+
@FormatPrice(_lastOrderTotal)
+
Mã: @_lastTransactionId
+
+
+
+
+
+ }
+
+ break;
+
+ case PosTab.History:
+ @* ═══ ORDER HISTORY TAB ═══ *@
+
+
+
+ @foreach (var f in _historyFilters)
+ {
+
+ }
- }
-
+
+ @foreach (var order in FilteredOrders)
+ {
+
_selectedOrder = order">
+
+
+
@order.Items
+
+
@FormatPrice(order.Total)
+
@order.Time
+
@order.Method
+
+
+
+ }
+ @if (!FilteredOrders.Any())
+ {
+
+
+
Không tìm thấy đơn hàng
+
+ }
+
+
+ break;
+
+ case PosTab.Dashboard:
+ @* ═══ DASHBOARD TAB ═══ *@
+
+
+
+
+ @foreach (var stat in _dashStats)
+ {
+
+
@stat.Label
+
@stat.Value
+
@stat.Sub
+
+ }
+
+
+
+ @* Popular items *@
+
+
Món bán chạy
+ @foreach (var item in _dashPopular)
+ {
+
+
+
@item.Name
+
@item.Qty đã bán
+
+
@FormatPrice(item.Revenue)
+
+ }
+
+
+ @* Payment breakdown + Hourly chart *@
+
+
Hình thức thanh toán
+ @foreach (var p in _dashPayments)
+ {
+
+ }
+
+
Doanh thu theo giờ
+
+ @foreach (var h in _dashHourly)
+ {
+
+ }
+
+
+
+
+ break;
}
-@* ═══ CART PANEL ═══ *@
-
-
-
-
- @foreach (var item in _cartItems)
- {
-
-
- @item.Name
- @FormatPrice(item.Price)
-
-
-
- @item.Qty
-
-
-
- }
-
-
-
+@* ═══════════════ BOTTOM NAVIGATION ═══════════════ *@
+
+
+
+
@code {
+ // ═══════════════ TAB SYSTEM ═══════════════
+ private enum PosTab { Sale, History, Dashboard }
+ private PosTab _activeTab = PosTab.Sale;
- // EN: Loading state / VI: Trạng thái tải
+ private void SwitchTab(PosTab tab)
+ {
+ if (_paymentStep != PayStep.None && _paymentStep != PayStep.Success) return; // Block tab switch during payment
+ _activeTab = tab;
+ }
+
+ // ═══════════════ SALE TAB — Product & Cart ═══════════════
private bool _isLoading = true;
private bool _loadError;
-
- // EN: Categories / VI: Danh mục
private string[] _categories = { "Tất cả" };
private string _selectedCategory = "Tất cả";
-
- // EN: Product list / VI: Danh sách sản phẩm
private List
_products = new();
-
- // EN: Cart items / VI: Mục giỏ hàng
private readonly List _cartItems = new();
private IEnumerable FilteredProducts =>
_selectedCategory == "Tất cả" ? _products : _products.Where(p => p.Category == _selectedCategory);
@@ -116,11 +402,7 @@
var apiProducts = await productsTask;
var apiCategories = await categoriesTask;
- _products = apiProducts.Select(p => new Product(
- p.Name,
- p.Price,
- p.Category ?? "Khác"
- )).ToList();
+ _products = apiProducts.Select(p => new Product(p.Name, p.Price, p.Category ?? "Khác")).ToList();
var catNames = apiCategories.Select(c => c.Name).ToList();
if (catNames.Count > 0)
@@ -131,18 +413,13 @@
_categories = new[] { "Tất cả" }.Concat(productCats).ToArray();
}
}
- catch
- {
- _loadError = true;
- }
- finally
- {
- _isLoading = false;
- }
+ catch { _loadError = true; }
+ finally { _isLoading = false; }
}
private void AddToCart(Product product)
{
+ if (_paymentStep != PayStep.None) return;
var existing = _cartItems.FirstOrDefault(i => i.Name == product.Name);
if (existing != null) existing.Qty++;
else _cartItems.Add(new CartItem(product.Name, product.Price));
@@ -154,9 +431,166 @@
if (item.Qty <= 0) _cartItems.Remove(item);
}
- private void Checkout() => NavigateTo("cafe/order-customize");
+ // ═══════════════ INLINE PAYMENT ═══════════════
+ private enum PayStep { None, MethodSelect, AmountInput, Processing, Success }
+ private PayStep _paymentStep = PayStep.None;
+ private string _selectedMethod = "";
+ private decimal _receivedAmount;
+ private string _customAmountInput = "";
+ private decimal _lastOrderTotal;
+ private string _lastTransactionId = "";
+ private decimal ChangeAmount => _receivedAmount - CartTotal;
- // EN: Models / VI: Mô hình dữ liệu
+ private void StartPayment()
+ {
+ if (!_cartItems.Any()) return;
+ _paymentStep = PayStep.MethodSelect;
+ }
+
+ private void CancelPayment()
+ {
+ _paymentStep = PayStep.None;
+ _selectedMethod = "";
+ _receivedAmount = 0;
+ _customAmountInput = "";
+ }
+
+ private void SelectPaymentMethod(string method)
+ {
+ _selectedMethod = method;
+ _receivedAmount = 0;
+ _customAmountInput = "";
+
+ if (method == "cash")
+ _paymentStep = PayStep.AmountInput;
+ else
+ _paymentStep = PayStep.Processing;
+ }
+
+ private string GetMethodLabel() => _selectedMethod switch
+ {
+ "cash" => "💵 Tiền mặt",
+ "card" => "💳 Thẻ",
+ "qr" => "📱 Mã QR",
+ "transfer" => "🏦 Chuyển khoản",
+ _ => "Thanh toán"
+ };
+
+ private List<(string Label, decimal Value)> GetQuickAmounts()
+ {
+ var total = CartTotal;
+ var amounts = new List<(string, decimal)>();
+ var roundUp = Math.Ceiling(total / 50_000) * 50_000;
+ if (roundUp == total) roundUp += 50_000;
+ amounts.Add(("Đúng tiền", total));
+ amounts.Add((FormatPrice(roundUp), roundUp));
+ amounts.Add((FormatPrice(roundUp + 50_000), roundUp + 50_000));
+ amounts.Add((FormatPrice(500_000), 500_000));
+ amounts.Add((FormatPrice(200_000), 200_000));
+ amounts.Add((FormatPrice(1_000_000), 1_000_000));
+ return amounts;
+ }
+
+ private void ApplyCustomAmount()
+ {
+ if (decimal.TryParse(_customAmountInput, out var val))
+ _receivedAmount = val;
+ }
+
+ private void ConfirmPayment()
+ {
+ _lastOrderTotal = CartTotal;
+ _lastTransactionId = $"TXN-{DateTime.Now:yyyyMMdd}-{Random.Shared.Next(100, 999)}";
+
+ // EN: Save to history / VI: Lưu vào lịch sử
+ var methodLabel = _selectedMethod switch { "cash" => "Tiền mặt", "card" => "Thẻ", "qr" => "QR Code", _ => "Chuyển khoản" };
+ _orderHistory.Insert(0, new OrderRecord(
+ _lastTransactionId,
+ string.Join(", ", _cartItems.Select(i => $"{i.Name} x{i.Qty}")),
+ _lastOrderTotal,
+ DateTime.Now.ToString("HH:mm"),
+ methodLabel,
+ "Hoàn thành"
+ ));
+
+ _paymentStep = PayStep.Success;
+ }
+
+ private void ResetAfterPayment()
+ {
+ _cartItems.Clear();
+ _paymentStep = PayStep.None;
+ _selectedMethod = "";
+ _receivedAmount = 0;
+ _customAmountInput = "";
+ }
+
+ // ═══════════════ HISTORY TAB ═══════════════
+ private string _historySearch = "";
+ private string _historyFilter = "today";
+ private OrderRecord? _selectedOrder;
+
+ private readonly List _historyFilters = new()
+ {
+ new("today", "Hôm nay"),
+ new("week", "7 ngày"),
+ new("month", "30 ngày"),
+ };
+
+ // EN: Demo history data + real-time additions / VI: Dữ liệu lịch sử mẫu + thêm real-time
+ private readonly List _orderHistory = new()
+ {
+ new("TXN-20260303-001", "Cà phê sữa đá x2, Bạc xỉu x1", 103_000, "10:15", "Tiền mặt", "Hoàn thành"),
+ new("TXN-20260303-002", "Cappuccino x1, Croissant bơ x2", 125_000, "10:02", "QR Code", "Hoàn thành"),
+ new("TXN-20260303-003", "Trà đào cam sả x3, Sinh tố bơ x1", 190_000, "09:48", "Thẻ", "Hoàn thành"),
+ new("TXN-20260303-004", "Matcha Latte x1", 59_000, "09:30", "Tiền mặt", "Hoàn thành"),
+ new("TXN-20260303-005", "Espresso x2, Latte x1", 145_000, "09:15", "Chuyển khoản", "Hoàn thành"),
+ new("TXN-20260303-006", "Cà phê đen đá x4", 116_000, "08:55", "Tiền mặt", "Hoàn thành"),
+ new("TXN-20260303-007", "Trà sen vàng x2, Bánh mì bơ x1", 133_000, "08:40", "QR Code", "Hoàn thành"),
+ new("TXN-20260303-008", "Sinh tố bơ x1", 55_000, "08:25", "Tiền mặt", "Hoàn trả"),
+ };
+
+ private IEnumerable FilteredOrders =>
+ string.IsNullOrWhiteSpace(_historySearch)
+ ? _orderHistory
+ : _orderHistory.Where(o =>
+ o.Id.Contains(_historySearch, StringComparison.OrdinalIgnoreCase) ||
+ o.Items.Contains(_historySearch, StringComparison.OrdinalIgnoreCase));
+
+ // ═══════════════ DASHBOARD TAB ═══════════════
+ private readonly List _dashStats = new()
+ {
+ new("Doanh thu", "8,450,000₫", "var(--pos-orange-primary)", "+12% so với hôm qua"),
+ new("Đơn hàng", "156", "var(--pos-success)", "TB 54,167₫/đơn"),
+ new("Khách hàng", "132", "var(--pos-info)", "18% khách quay lại"),
+ new("Món bán ra", "347", "var(--pos-warning)", "2.2 món/đơn"),
+ };
+
+ private readonly List _dashPopular = new()
+ {
+ new("Cà phê sữa đá", 52, 1_820_000),
+ new("Bạc xỉu", 38, 1_482_000),
+ new("Trà đào cam sả", 29, 1_305_000),
+ new("Cappuccino", 24, 1_320_000),
+ new("Sinh tố bơ", 18, 990_000),
+ };
+
+ private readonly List _dashPayments = new()
+ {
+ new("Tiền mặt", 4_650_000, 55, "var(--pos-success)"),
+ new("Chuyển khoản", 2_535_000, 30, "var(--pos-info)"),
+ new("Thẻ", 845_000, 10, "var(--pos-warning)"),
+ new("Ví điện tử", 420_000, 5, "var(--pos-orange-primary)"),
+ };
+
+ private readonly List _dashHourly = new()
+ {
+ new("7h", 30), new("8h", 65), new("9h", 85), new("10h", 55),
+ new("11h", 90), new("12h", 100), new("13h", 70), new("14h", 45),
+ new("15h", 60), new("16h", 75), new("17h", 50), new("18h", 20),
+ };
+
+ // ═══════════════ RECORDS ═══════════════
private record Product(string Name, decimal Price, string Category);
private class CartItem(string name, decimal price)
{
@@ -164,4 +598,10 @@
public decimal Price { get; set; } = price;
public int Qty { get; set; } = 1;
}
+ private record OrderRecord(string Id, string Items, decimal Total, string Time, string Method, string Status);
+ private record HistoryFilter(string Key, string Label);
+ private record DashStat(string Label, string Value, string Color, string Sub);
+ private record DashPopular(string Name, int Qty, decimal Revenue);
+ private record DashPayment(string Method, decimal Amount, int Pct, string Color);
+ private record DashHour(string Hour, int Pct);
}