@*
EN: Spa POS Desktop — 2-panel layout: service categories + grid (left), current appointment/bill (right).
VI: POS Spa Desktop — Bố cục 2 panel: danh mục dịch vụ + lưới (trái), lịch hẹn/hóa đơn hiện tại (phải).
*@
@page "/pos/{ShopId:guid}/spa"
@layout PosLayout
@inherits PosBase
@inject WebClientTpos.Client.Services.PosDataService DataService
@* ═══ SERVICE PANEL (LEFT) / PANEL DỊCH VỤ (TRÁI) ═══ *@
@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)
{
}
@* ═══ SERVICE GRID / LƯỚI DỊCH VỤ ═══ *@
@foreach (var svc in FilteredServices)
{
AddToAppointment(svc)">
@svc.Name
@FormatPrice(svc.Price)
@svc.Duration phút
}
}
@* ═══ APPOINTMENT PANEL (RIGHT) / PANEL LỊCH HẸN (PHẢI) ═══ *@
@* EN: Customer info / VI: Thông tin khách *@
@if (_customerName is not null)
{
@_customerName[..1]
@_customerName
@_customerPhone • @_customerTier
}
else
{
}
@foreach (var item in _appointmentItems)
{
@item.Name
@FormatPrice(item.Price)
@item.Duration phút
}
@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ả";
// EN: Demo customer / VI: Khách hàng mẫu
private string? _customerName = "Nguyễn Thị Mai";
private string _customerPhone = "0901234567";
private string _customerTier = "Gold";
// EN: Service list from API / VI: Danh sách dịch vụ từ API
private List _services = new();
// EN: Appointment items / VI: Mục lịch hẹn
private readonly List _appointmentItems = new();
private IEnumerable FilteredServices =>
_selectedCategory == "Tất cả" ? _services : _services.Where(s => s.Category == _selectedCategory);
private decimal AppointmentTotal => _appointmentItems.Sum(i => i.Price);
protected override async Task OnInitializedAsync()
{
try
{
var apiProducts = await DataService.GetProductsAsync(ShopId);
_services = apiProducts.Select(p => new SpaService(
p.Name,
p.Price,
p.DurationMinutes ?? 60,
p.Category ?? "Khác"
)).ToList();
var cats = _services.Select(s => s.Category).Distinct().ToList();
_categories = new[] { "Tất cả" }.Concat(cats).ToArray();
}
catch
{
_loadError = true;
}
finally
{
_isLoading = false;
}
}
private void AddToAppointment(SpaService svc)
{
_appointmentItems.Add(new AppointmentItem(svc.Name, svc.Price, svc.Duration));
}
private void RemoveItem(AppointmentItem item) => _appointmentItems.Remove(item);
private void Checkout() => NavigateTo("spa/spa-journey");
private static string GetCategoryIcon(string category) => category switch
{
"Massage" => "hand", "Facial" => "sparkles", "Body" => "bath",
"Nail" => "paintbrush", "Hair" => "scissors", _ => "heart"
};
// EN: Models / VI: Mô hình dữ liệu
private record SpaService(string Name, decimal Price, int Duration, string Category);
private record AppointmentItem(string Name, decimal Price, int Duration);
}