diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopSchedule.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopSchedule.razor index ed4e19df..f2cf577c 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopSchedule.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopSchedule.razor @@ -82,10 +82,10 @@ var schedStaffName = schedStaff != null && (!string.IsNullOrWhiteSpace(schedStaff.LastName) || !string.IsNullOrWhiteSpace(schedStaff.FirstName)) ? $"{schedStaff.LastName} {schedStaff.FirstName}".Trim() : (s.EmployeeCode ?? s.StaffId.ToString()[..8]); @schedStaffName - @(s.Role ?? "—") + @(schedStaff?.Role ?? s.Role ?? "—") @ShopHelpers.DayLabel(s.DayOfWeek) - @s.StartTime - @s.EndTime + @FormatTime(s.StartTime) + @FormatTime(s.EndTime) } @@ -278,4 +278,15 @@ else if (SubSection == "shifts") } catch (Exception ex) { Console.Error.WriteLine($"Không thể xóa lịch làm việc: {ex.Message}"); } } + + /// + /// EN: Format time string — remove seconds if present (08:00:00 → 08:00). + /// VI: Định dạng giờ — bỏ giây nếu có (08:00:00 → 08:00). + /// + private static string FormatTime(string? time) + { + if (string.IsNullOrEmpty(time)) return "—"; + var parts = time.Split(':'); + return parts.Length >= 2 ? $"{parts[0]}:{parts[1]}" : time; + } } 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 index c6358fc2..9875d174 100644 --- 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 @@ -1,11 +1,14 @@ @page "/staff/schedule" @layout StaffLayout -@inject WebClientTpos.Client.Services.PosDataService DataService +@using WebClientTpos.Client.Services +@inject PosDataService DataService +@inject AuthService AuthSvc +@inject AuthStateService AuthState @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. + EN: Staff schedule page — view weekly work schedule from real API data. + VI: Trang lịch làm việc — xem lịch làm việc hàng tuần từ dữ liệu API thật. *@ Lịch làm việc @@ -16,60 +19,124 @@

Lịch trình làm việc của bạ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
- } + @if (_loading) + { +
+
+

Đang tải lịch...

+
+ } + else if (!_mySchedules.Any()) + { +
+
+
- } -
+

Chưa có lịch làm việc

+

Quản lý chưa phân lịch cho bạn

+
+ } + else + { + @* ═══ WEEK VIEW ═══ *@ +
+ @for (int i = 0; i < 7; i++) + { + var day = _weekStart.AddDays(i); + var isToday = day.Date == DateTime.Now.Date; + var dow = (int)day.DayOfWeek; + var daySchedules = _mySchedules.Where(s => s.DayOfWeek == dow).OrderBy(s => s.StartTime).ToList(); + var hasSchedule = daySchedules.Any(); +
+
@GetDayName(day)
+
@day.Day
+ @if (hasSchedule) + { + @foreach (var sched in daySchedules) + { +
@FormatTime(sched.StartTime) - @FormatTime(sched.EndTime)
+ } + } + else + { + Nghỉ + } +
+ } +
- @* ═══ UPCOMING SHIFTS ═══ *@ -
-
- Thông tin ca làm việc -
-
-
-
- -
-
Ca sáng: 08:00 - 12:00
-
Thu 2 - Thu 6
-
-
-
- -
-
Ca chiều: 13:00 - 17:00
-
Thu 2 - Thu 6
-
+ @* ═══ SHIFT DETAILS ═══ *@ +
+
+ Thông tin ca làm việc +
+
+
+ @foreach (var group in _mySchedules.GroupBy(s => new { s.StartTime, s.EndTime }).OrderBy(g => g.Key.StartTime)) + { + var isMorning = group.Key.StartTime?.CompareTo("12:00") < 0; + var isEvening = group.Key.StartTime?.CompareTo("18:00") >= 0; + var color = isEvening ? "#F59E0B" : isMorning ? "#22C55E" : "#3B82F6"; + var label = isEvening ? "Ca tối" : isMorning ? "Ca sáng" : "Ca chiều"; + var days = string.Join(", ", group.OrderBy(s => s.DayOfWeek == 0 ? 7 : s.DayOfWeek).Select(s => DayLabel(s.DayOfWeek))); +
+ +
+
@label: @FormatTime(group.Key.StartTime) - @FormatTime(group.Key.EndTime)
+
@days
+
+
+ }
-
+ }
@code { + private bool _loading = true; + private List _mySchedules = new(); 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 { } + + if (firstRender) + { + // EN: Restore staff session and load schedule data + // VI: Khôi phục session nhân viên và tải dữ liệu lịch + if (!AuthState.IsAuthenticated) + { + try { await AuthSvc.TryRestoreSessionAsync("staff"); } catch { } + } + + try + { + var profile = await DataService.GetMyStaffProfileAsync(); + if (profile?.ShopId != null) + { + var allSchedules = await DataService.GetStaffSchedulesAsync(profile.ShopId.Value); + _mySchedules = allSchedules.Where(s => s.StaffId == profile.StaffId).ToList(); + } + } + catch { /* API unavailable */ } + + _loading = false; + StateHasChanged(); + } + } + + /// + /// EN: Format time string — remove seconds if present (08:00:00 → 08:00). + /// VI: Định dạng giờ — bỏ giây nếu có (08:00:00 → 08:00). + /// + private static string FormatTime(string? time) + { + if (string.IsNullOrEmpty(time)) return "—"; + // Handle "08:00:00" -> "08:00" + var parts = time.Split(':'); + return parts.Length >= 2 ? $"{parts[0]}:{parts[1]}" : time; } private static string GetDayName(DateTime d) => d.DayOfWeek switch @@ -83,4 +150,16 @@ DayOfWeek.Sunday => "CN", _ => "" }; + + private static string DayLabel(int dow) => dow switch + { + 1 => "Thứ 2", + 2 => "Thứ 3", + 3 => "Thứ 4", + 4 => "Thứ 5", + 5 => "Thứ 6", + 6 => "Thứ 7", + 0 => "CN", + _ => "" + }; }