diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopAttendance.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopAttendance.razor index 77281261..cc8e4a7d 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopAttendance.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Shop/ShopAttendance.razor @@ -79,8 +79,8 @@ @(r.StaffName ?? r.StaffId.ToString()[..8]) @r.Date.ToString("dd/MM") - @(r.CheckIn?.ToString("HH:mm") ?? "--") - @(r.CheckOut?.ToString("HH:mm") ?? "--") + @(r.CheckIn?.ToLocalTime().ToString("HH:mm") ?? "--") + @(r.CheckOut?.ToLocalTime().ToString("HH:mm") ?? "--") @(r.HoursWorked.HasValue ? r.HoursWorked.Value.ToString("0.#") + "h" : "--") @{ diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Shared/Dialogs/StockIn.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Shared/Dialogs/StockIn.razor index 126fa12d..ed478810 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Shared/Dialogs/StockIn.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Shared/Dialogs/StockIn.razor @@ -157,16 +157,17 @@ // VI: Dữ liệu dialog — được điền từ context hiện tại (đơn hàng/sản phẩm đã chọn). // TODO: Integrate with Order/Catalog/Inventory APIs when DDD Value Object mapping is fixed. - // EN: Stock-in state / VI: Trạng thái nhập kho - private string _productSearch = "Cà phê hạt Arabica"; - private string _selectedProduct = "Cà phê hạt Arabica"; - private string _selectedSku = "CF-ARA-500"; - private int _currentStock = 120; - private int _quantity = 50; - private decimal _unitCost = 185_000; - private string _supplier = "Công ty TNHH Cà phê Đà Lạt"; - private string _lotNumber = "LOT-2026-0226"; - private DateTime _expiryDate = new(2027, 2, 26); + // EN: Stock-in state — will be loaded from Inventory API. No hardcoded values in production. + // VI: Trạng thái nhập kho — sẽ tải từ Inventory API. Không hardcode giá trị trong production. + private string _productSearch = ""; + private string _selectedProduct = ""; + private string _selectedSku = ""; + private int _currentStock = 0; + private int _quantity = 0; + private decimal _unitCost = 0; + private string _supplier = ""; + private string _lotNumber = ""; + private DateTime _expiryDate = DateTime.Now.AddMonths(6); private string _notes = ""; // EN: Suppliers / VI: Nhà cung cấp diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffAttendance.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffAttendance.razor index 25b31322..ddf4f3a3 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffAttendance.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffAttendance.razor @@ -74,8 +74,8 @@ @r.Date.ToString("dd/MM/yyyy") @GetDayOfWeek(r.Date) - @(r.CheckIn?.ToString("HH:mm") ?? "--") - @(r.CheckOut?.ToString("HH:mm") ?? "--") + @(r.CheckIn?.ToLocalTime().ToString("HH:mm") ?? "--") + @(r.CheckOut?.ToLocalTime().ToString("HH:mm") ?? "--") @(r.HoursWorked.HasValue ? r.HoursWorked.Value.ToString("0.#") + "h" : "--") diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffDashboard.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffDashboard.razor index d3c35311..2aac0b69 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffDashboard.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffDashboard.razor @@ -69,7 +69,7 @@ @_leaveBalance - Ngày phép còn lại + Ngày phép đã dùng
@@ -111,8 +111,8 @@ { @r.Date.ToString("dd/MM") - @(r.CheckIn?.ToString("HH:mm") ?? "--") - @(r.CheckOut?.ToString("HH:mm") ?? "--") + @(r.CheckIn?.ToLocalTime().ToString("HH:mm") ?? "--") + @(r.CheckOut?.ToLocalTime().ToString("HH:mm") ?? "--") @(r.HoursWorked.HasValue ? r.HoursWorked.Value.ToString("0.#") + "h" : "--") @@ -141,7 +141,9 @@ private bool _checkedOut = false; private string _todayHours = "0"; private int _monthDays = 0; - private int _leaveBalance = 12; + // EN: Leave balance — loaded from real leave request data. TODO: load annual allowance from merchant config API. + // VI: Số phép còn lại — tính từ dữ liệu nghỉ phép thực. TODO: tải số phép năm từ API cấu hình merchant. + private int _leaveBalance = 0; private int _unreadCount = 0; private string _displayName => _profile?.FirstName ?? AuthState.UserEmail?.Split('@').FirstOrDefault() ?? "Staff"; @@ -177,16 +179,28 @@ _unreadCount = _notifications.Count(n => !n.IsRead); _monthDays = _recentAttendance.Count(r => r.Status == "Completed"); - var today = _recentAttendance.FirstOrDefault(r => r.Date.Date == DateTime.Now.Date); + // EN: Compare UTC dates consistently — backend stores all times in UTC. + // VI: So sánh ngày UTC nhất quán — backend lưu tất cả thời gian theo UTC. + var todayUtc = DateTime.UtcNow.Date; + var today = _recentAttendance.FirstOrDefault(r => r.Date.Date == todayUtc); if (today != null) { _checkedIn = today.CheckIn.HasValue; _checkedOut = today.CheckOut.HasValue; if (today.CheckIn.HasValue && !today.CheckOut.HasValue) - _todayHours = ((DateTime.Now - today.CheckIn.Value).TotalHours).ToString("0.#"); + _todayHours = ((DateTime.UtcNow - today.CheckIn.Value).TotalHours).ToString("0.#"); else if (today.HoursWorked.HasValue) _todayHours = today.HoursWorked.Value.ToString("0.#"); } + + // EN: Calculate leave days used from approved leave requests (real data). + // VI: Tính số ngày phép đã dùng từ các yêu cầu nghỉ phép đã duyệt (dữ liệu thực). + try + { + var leaveRequests = await DataService.GetMyLeaveRequestsAsync(); + _leaveBalance = leaveRequests.Where(r => r.Status == "Approved").Sum(r => (r.EndDate - r.StartDate).Days + 1); + } + catch { } } catch { } finally { _loading = false; } diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffLeave.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffLeave.razor index e4a8bb12..1ddd81ce 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffLeave.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Staff/StaffLeave.razor @@ -26,23 +26,25 @@
@* ═══ SUMMARY ═══ *@ + @* EN: Leave stats from real data. Total annual allowance will come from merchant config API (TODO). + VI: Thống kê phép từ dữ liệu thực. Tổng phép năm sẽ từ API cấu hình merchant (TODO). *@
-
- 12 - Tổng phép năm -
@_usedDays - Đã sử dụng -
-
- @(12 - _usedDays) - Còn lại + Ngày phép đã dùng
@_pendingCount Chờ duyệt
+
+ @_rejectedCount + Từ chối +
+
+ @_requests.Count + Tổng yêu cầu +
@* ═══ CREATE FORM ═══ *@ @@ -129,6 +131,7 @@ private bool _submitting = false; private int _usedDays = 0; private int _pendingCount = 0; + private int _rejectedCount = 0; // Form fields private string _leaveType = "Annual"; @@ -158,6 +161,7 @@ _requests = await DataService.GetMyLeaveRequestsAsync(); _usedDays = _requests.Where(r => r.Status == "Approved").Sum(r => (r.EndDate - r.StartDate).Days + 1); _pendingCount = _requests.Count(r => r.Status == "Pending"); + _rejectedCount = _requests.Count(r => r.Status == "Rejected"); } catch { } finally { _loading = false; } diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/StaffController.cs b/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/StaffController.cs index bd7c5340..ce476b5d 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/StaffController.cs +++ b/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/StaffController.cs @@ -367,21 +367,15 @@ public class StaffController : ControllerBase } /// - /// EN: Get notifications for current staff. - /// VI: Lấy thông báo của nhân viên hiện tại. + /// EN: Get notifications for current staff. Returns empty list until notification service is implemented. + /// VI: Lấy thông báo của nhân viên hiện tại. Trả về danh sách trống cho đến khi notification service được triển khai. /// [HttpGet("staff/me/notifications")] public IActionResult GetMyNotifications() { - // EN: Stub — returns sample notifications - // VI: Stub — trả về thông báo mẫu - var notifications = new List - { - new { id = Guid.NewGuid(), title = "Chào mừng!", message = "Bạn đã đăng nhập thành công vào hệ thống GoodGo Staff.", type = "info", isRead = false, createdAt = DateTime.UtcNow.AddHours(-1).ToString("o") }, - new { id = Guid.NewGuid(), title = "Lịch làm việc", message = "Lịch làm việc tuần này đã được cập nhật.", type = "schedule", isRead = false, createdAt = DateTime.UtcNow.AddDays(-1).ToString("o") } - }; - - return Ok(new { success = true, data = new { items = notifications } }); + // EN: No notification service yet — return empty list (no fake data in production). + // VI: Chưa có notification service — trả về danh sách trống (không fake data trong production). + return Ok(new { success = true, data = new { items = Array.Empty() } }); } ///