+
+
+ @* ═══ CURRENT MONTH ═══ *@
+
+
+
+
+
+
--
+
Lương cơ bản
+
+
+
+
+
+
+ @* ═══ NOTE ═══ *@
+
+
+
+
+
Tính năng đang phát triển
+
Thông tin lương sẽ được cập nhật bởi quản lý cửa hàng. Vui lòng liên hệ quản lý để biết chi tiết.
+
+
+
+@code {
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ try { await JS.InvokeVoidAsync("lucide.createIcons"); } catch { }
+ }
+}
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffPos.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffPos.razor
new file mode 100644
index 00000000..4ff43a54
--- /dev/null
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffPos.razor
@@ -0,0 +1,60 @@
+@page "/staff/pos"
+@layout StaffLayout
+@using WebClientTpos.Client.Services
+@inject NavigationManager Nav
+@inject IJSRuntime JS
+
+@*
+ EN: Cashier POS redirect — redirects cashier to the actual POS screen.
+ VI: Chuyển hướng POS thu ngân — chuyển thu ngân đến màn hình POS.
+*@
+
+
+
+
+
+
+
+
+
Mở POS
+
Nhấn nút bên dưới để mở màn hình thu ngân toàn màn hình
+
+ @if (_shopId.HasValue)
+ {
+
+ }
+ else
+ {
+
Chưa được phân công cửa hàng. Vui lòng liên hệ quản lý.
+ }
+
+
+
+@code {
+ private Guid? _shopId;
+ [CascadingParameter] private StaffLayout? Layout { get; set; }
+
+ protected override void OnInitialized()
+ {
+ _shopId = Layout?.ShopId;
+ }
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ try { await JS.InvokeVoidAsync("lucide.createIcons"); } catch { }
+ }
+
+ private void OpenPos()
+ {
+ if (_shopId.HasValue)
+ Nav.NavigateTo($"/pos/{_shopId}/cafe", forceLoad: true);
+ }
+}
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffSchedule.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffSchedule.razor
new file mode 100644
index 00000000..c6358fc2
--- /dev/null
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffSchedule.razor
@@ -0,0 +1,86 @@
+@page "/staff/schedule"
+@layout StaffLayout
+@inject WebClientTpos.Client.Services.PosDataService DataService
+@inject IJSRuntime JS
+
+@*
+ EN: Staff schedule page — view weekly work schedule.
+ VI: Trang lịch làm việc — xem lịch làm việc hàng tuần.
+*@
+
+
+
+
+ @* ═══ WEEK VIEW ═══ *@
+
+ @for (int i = 0; i < 7; i++)
+ {
+ var day = _weekStart.AddDays(i);
+ var isToday = day.Date == DateTime.Now.Date;
+ var isWeekend = day.DayOfWeek == DayOfWeek.Sunday;
+
+
@GetDayName(day)
+
@day.Day
+ @if (isWeekend)
+ {
+
Nghỉ
+ }
+ else
+ {
+
08:00 - 17:00
+ }
+
+ }
+
+
+ @* ═══ UPCOMING SHIFTS ═══ *@
+
+
+
+
+
+
+
+
Ca sáng: 08:00 - 12:00
+
Thu 2 - Thu 6
+
+
+
+
+
+
Ca chiều: 13:00 - 17:00
+
Thu 2 - Thu 6
+
+
+
+
+
+
+
+@code {
+ private DateTime _weekStart = DateTime.Now.Date.AddDays(-(int)DateTime.Now.DayOfWeek + (int)DayOfWeek.Monday);
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ try { await JS.InvokeVoidAsync("lucide.createIcons"); } catch { }
+ }
+
+ private static string GetDayName(DateTime d) => d.DayOfWeek switch
+ {
+ DayOfWeek.Monday => "T2",
+ DayOfWeek.Tuesday => "T3",
+ DayOfWeek.Wednesday => "T4",
+ DayOfWeek.Thursday => "T5",
+ DayOfWeek.Friday => "T6",
+ DayOfWeek.Saturday => "T7",
+ DayOfWeek.Sunday => "CN",
+ _ => ""
+ };
+}
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffTables.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffTables.razor
new file mode 100644
index 00000000..97df56ac
--- /dev/null
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffTables.razor
@@ -0,0 +1,142 @@
+@page "/staff/tables"
+@layout StaffLayout
+@using WebClientTpos.Client.Services
+@inject PosDataService DataService
+@inject IJSRuntime JS
+
+@*
+ EN: Waiter table view — shows tables, their status, and allows order management.
+ VI: Màn hình phục vụ — hiển thị bàn, trạng thái, và quản lý order.
+*@
+
+
+
+
+ @if (_loading)
+ {
+
+
+
+ }
+ else
+ {
+ @* ═══ TABLE GRID ═══ *@
+
+ @foreach (var table in _tables)
+ {
+ var bgColor = table.Status switch
+ {
+ "Available" => "var(--admin-bg-elevated)",
+ "Occupied" => "rgba(255,92,0,0.08)",
+ "Reserved" => "rgba(59,130,246,0.08)",
+ _ => "var(--admin-bg-elevated)"
+ };
+ var borderColor = table.Status switch
+ {
+ "Available" => "var(--admin-border-default)",
+ "Occupied" => "#FF5C00",
+ "Reserved" => "#3B82F6",
+ _ => "var(--admin-border-default)"
+ };
+
SelectTable(table))">
+
BÀN
+
@table.TableNumber
+
+ @GetTableStatusLabel(table.Status)
+
+ @if (table.GuestCount > 0)
+ {
+
+ @table.GuestCount khách
+
+ }
+
+ }
+
+
+ @* ═══ SELECTED TABLE DETAIL ═══ *@
+ @if (_selectedTable != null)
+ {
+
+
+
+
+ @if (_selectedTable.Status == "Available")
+ {
+
+ }
+ else if (_selectedTable.Status == "Occupied")
+ {
+
+
+ }
+
+
+
+ }
+ }
+
+
+@code {
+ private List