@* EN: Retail POS Mobile — Single column, floating cart button, bottom sheet cart. VI: POS Bán lẻ Mobile — Một cột, nút giỏ hàng nổi, giỏ hàng dạng sheet dưới. *@ @page "/pos/{ShopId:guid}/retail/mobile" @layout PosLayout @inherits PosBase @inject WebClientTpos.Client.Services.PosDataService DataService
@* EN: Barcode input / VI: Ô nhập mã vạch *@
@if (_isLoading) {
Đ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) {
@product.Name @FormatPrice(product.Price)
}
} @* EN: Floating cart button / VI: Nút giỏ hàng nổi *@ @if (_cartItems.Any()) { } @* EN: Bottom sheet cart / VI: Giỏ hàng dạng sheet dưới *@ @if (_showCart) {
@* EN: Handle bar / VI: Thanh kéo *@
Giỏ hàng
@foreach (var item in _cartItems) {
@item.Name @FormatPrice(item.Price)
@item.Qty
}
}
@code { // EN: Loading state / VI: Trạng thái tải 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ả"; private string _barcodeInput = ""; private bool _showCart; // EN: Product list from API / VI: Danh sách sản phẩm từ API private List _products = new(); private readonly List _cartItems = new(); private IEnumerable FilteredProducts => _selectedCategory == "Tất cả" ? _products : _products.Where(p => p.Category == _selectedCategory); private decimal CartTotal => _cartItems.Sum(i => i.Price * i.Qty); protected override async Task OnInitializedAsync() { try { var apiProducts = await DataService.GetProductsAsync(ShopId); _products = apiProducts.Select(p => new Product( p.Name, p.Sku ?? "", p.Price, p.Category ?? "Khác", GetCategoryIcon(p.Category ?? "Khác") )).ToList(); var cats = _products.Select(p => p.Category).Distinct().ToList(); _categories = new[] { "Tất cả" }.Concat(cats).ToArray(); } catch { _loadError = true; } finally { _isLoading = false; } } private void AddToCart(Product product) { var existing = _cartItems.FirstOrDefault(i => i.Sku == product.Sku); if (existing != null) existing.Qty++; else _cartItems.Add(new CartItem(product.Name, product.Sku, product.Price)); } private void ChangeQty(CartItem item, int delta) { item.Qty += delta; if (item.Qty <= 0) _cartItems.Remove(item); } private void Checkout() { } private static string GetCategoryIcon(string category) => category switch { "Thời trang" => "shirt", "Phụ kiện" => "shopping-bag", "Điện tử" => "headphones", "Gia dụng" => "cooking-pot", "Mỹ phẩm" => "sparkles", _ => "package" }; // EN: Models / VI: Mô hình dữ liệu private record Product(string Name, string Sku, decimal Price, string Category, string Icon); private class CartItem(string name, string sku, decimal price) { public string Name { get; set; } = name; public string Sku { get; set; } = sku; public decimal Price { get; set; } = price; public int Qty { get; set; } = 1; } }