diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor index db121a02..c351679f 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopPage.razor @@ -490,18 +490,23 @@ Đang hát: @_tables.Count(t => t.Status == "occupied") Đã đặt: @_tables.Count(t => t.Status == "reserved") +
@_tables.Count phòng
-
+
@foreach (var room in _tables) { var bgColor = room.Status switch { "available" => "rgba(139,92,246,0.08)", "occupied" => "rgba(239,68,68,0.08)", "reserved" => "rgba(245,158,11,0.08)", _ => "rgba(107,107,111,0.08)" }; var borderColor = room.Status switch { "available" => "rgba(139,92,246,0.3)", "occupied" => "rgba(239,68,68,0.3)", "reserved" => "rgba(245,158,11,0.3)", _ => "rgba(107,107,111,0.3)" }; var statusColor = room.Status switch { "available" => "#8B5CF6", "occupied" => "#EF4444", "reserved" => "#F59E0B", _ => "#6B6B6F" }; var statusText = room.Status switch { "available" => "Trống", "occupied" => "Đang hát", "reserved" => "Đã đặt", "cleaning" => "Dọn dẹp", _ => room.Status }; + var roomType = (room.Zone ?? "").ToLower() switch { var z when z.Contains("vip") => ("VIP", "#F59E0B"), var z when z.Contains("party") => ("Party", "#EC4899"), _ => ("Standard", "#8B5CF6") };
-
- - Phòng @room.TableNumber +
+
+ + Phòng @room.TableNumber +
+ @roomType.Item1
@(room.Zone ?? "Chung") • @room.Capacity chỗ
@@ -520,39 +525,57 @@ } break; - // ═══ APPOINTMENTS (Spa / Thẩm mỹ) ═══ + // ═══ APPOINTMENTS (Spa / Thẩm mỹ) — Calendar View ═══ case "appointments": - @if (!_appointments.Any()) - { - @RenderEmpty("calendar", "#EC4899", "Chưa có lịch hẹn", "Lịch hẹn sẽ hiển thị khi khách đặt dịch vụ", "plus-circle", "Tạo lịch hẹn", $"/admin/shop/{ShopId}/appointments") - } - else - { -
+ var calWeekStart = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + 1 + _calendarWeekOffset * 7); + var calWeekEnd = calWeekStart.AddDays(7); + var weekAppts = _appointments.Where(a => a.StartTime >= calWeekStart && a.StartTime < calWeekEnd).ToList(); +
+
@_appointments.CountTổng lịch hẹn
@_appointments.Count(a => a.Status == "Confirmed")Đã xác nhận
@_appointments.Count(a => a.Status == "Pending")Chờ xác nhận
+
@weekAppts.CountTuần này
-
-
- - - - - - @foreach (var a in _appointments.OrderBy(a => a.StartTime)) - { - var statusColor = a.Status switch { "Confirmed" => "#22C55E", "Pending" => "#F59E0B", "Completed" => "#3B82F6", "Cancelled" => "#EF4444", _ => "#6B6B6F" }; - - - - - - } -
Thời gianPhòng / Tài nguyênTrạng thái
@a.StartTime.ToString("dd/MM/yyyy")
@a.StartTime.ToString("HH:mm") — @a.EndTime.ToString("HH:mm")
@(a.ResourceName ?? "—")@a.Status
+
+
+
+

Lịch hẹn tuần @calWeekStart.ToString("dd/MM") — @calWeekEnd.AddDays(-1).ToString("dd/MM")

+
+ + +
- } +
+
+ @for (int d = 0; d < 7; d++) + { + var day = calWeekStart.AddDays(d); + var dayAppts = weekAppts.Where(a => a.StartTime.Date == day.Date).OrderBy(a => a.StartTime).ToList(); + var isToday = day.Date == DateTime.Today; +
+
+
@DayLabel((int)day.DayOfWeek)
+
@day.Day
+
+ @foreach (var appt in dayAppts) + { + var apptColor = appt.Status switch { "Confirmed" => "#22C55E", "Pending" => "#F59E0B", "Completed" => "#3B82F6", _ => "#6B6B6F" }; +
+
@appt.StartTime.ToString("HH:mm")-@appt.EndTime.ToString("HH:mm")
+
@(appt.ResourceName ?? "—")
+
+ } + @if (!dayAppts.Any()) + { +
+ } +
+ } +
+
+
break; // ═══ SERVICES (Spa — products with type=Service) ═══ @@ -664,16 +687,53 @@ } break; - // ═══ KITCHEN — Placeholder (needs KDS) ═══ + // ═══ KITCHEN — KDS Station View ═══ case "kitchen": -
-
-
- -
-

Kitchen Display System

-

Màn hình hiển thị đơn cho bếp (KDS) — tự động nhận đơn từ POS, phân luồng theo trạm bếp.

-

Tính năng KDS sẽ hoạt động khi kết nối với F&B Engine

+
+
+ @foreach (var st in new[] { ("all", "Tất cả"), ("kitchen", "🔥 Bếp"), ("bar", "🍸 Bar"), ("grill", "🥩 Nướng") }) + { + + } +
+
+ Chờ: 0 + Đang làm: 0 + Xong: 0 +
+
+
+ @foreach (var ticket in new[] { + new { Id = "#KDS-001", Table = "Bàn 3", Items = "Phở bò tái (x2), Gỏi cuốn (x1)", Station = "kitchen", Status = "pending", Time = "2 phút" }, + new { Id = "#KDS-002", Table = "Bàn 7", Items = "Mojito (x3), Bia Tiger (x2)", Station = "bar", Status = "cooking", Time = "5 phút" }, + new { Id = "#KDS-003", Table = "Bàn 1", Items = "Bò nướng lá lốt (x1)", Station = "grill", Status = "done", Time = "12 phút" } + }) + { + if (_kdsStation == "all" || _kdsStation == ticket.Station) + { + var ticketColor = ticket.Status switch { "pending" => "#F59E0B", "cooking" => "#3B82F6", "done" => "#22C55E", _ => "#6B6B6F" }; + var ticketLabel = ticket.Status switch { "pending" => "Chờ", "cooking" => "Đang làm", "done" => "Hoàn thành", _ => ticket.Status }; +
+
+ @ticket.Id + @ticketLabel +
+
@ticket.Table
+
@ticket.Items
+
+ @ticket.Time + @ticket.Station.ToUpper() +
+
+ } + } +
+
+
+

Demo KDS — Dữ liệu sẽ real-time khi kết nối F&B Engine

break; @@ -717,23 +777,63 @@ // ═══ TREATMENTS (Beauty — Liệu trình) ═══ case "treatments": -
-
-

Liệu trình điều trị

-
-
-
- -
-

Quản lý liệu trình dài hạn

-

Theo dõi tiến trình điều trị nhiều buổi, ảnh before/after, lịch tái khám sau phẫu thuật.

-
- Ảnh Before/After - Lịch tái khám - Hồ sơ y tế -
-
+
+ @foreach (var tab in new[] { ("treatment", "📋 Liệu trình"), ("medical", "🏥 Hồ sơ y tế"), ("photos", "📷 Ảnh Before/After") }) + { + + }
+ @if (_treatmentTab == "treatment") + { +
+
+

Liệu trình điều trị

+
+
+
+ +
+

Quản lý liệu trình dài hạn

+

Theo dõi tiến trình điều trị nhiều buổi, lịch tái khám sau phẫu thuật.

+
+
+ } + else if (_treatmentTab == "medical") + { +
+

🏥 Hồ sơ y tế khách hàng

+
+
+
+
Chưa chọn khách
+
+
+
+
+
+
+
+
+ } + else + { +
+

📷 Ảnh Before / After

+
+
+ +
+

So sánh kết quả điều trị

+

Upload ảnh trước/sau điều trị để theo dõi tiến triển và tư vấn khách hàng.

+ +
+
+ } break; // ═══ STAFF SCHEDULE (Spa/Beauty — Lịch làm việc) ═══ @@ -844,6 +944,20 @@
+
+

🧾 Cài đặt hóa đơn / Bill

+
+
+
+
+
+
+
80mm
+
+
+
+
+
break; // ═══ UNKNOWN SECTIONS ═══ @@ -918,6 +1032,10 @@ private List _memberLevels = new(); private List _staffSchedules = new(); private List _invTxns = new(); + // P2 state: calendar, KDS, treatments + private int _calendarWeekOffset; + private string _kdsStation = "all"; + private string _treatmentTab = "treatment"; private List _resources = new(); // Customer filter state private string _customerSearch = "";