feat(admin): add Staff Schedule UI for Spa/Beauty (S3)
- Add "Lịch làm việc" menu item to Spa & Beauty sidebars - Add case "schedule": section with stat cards + weekly table - Display employee code, role, day (T2-CN), start/end time - Add DayLabel helper for Vietnamese day names - Add LoadData case + section title config
This commit is contained in:
@@ -706,6 +706,44 @@
|
||||
</div>
|
||||
break;
|
||||
|
||||
// ═══ STAFF SCHEDULE (Spa/Beauty — Lịch làm việc) ═══
|
||||
case "schedule":
|
||||
@if (!_staffSchedules.Any())
|
||||
{
|
||||
@RenderEmpty("calendar-clock", "#8B5CF6", "Chưa có lịch làm việc", "Thiết lập lịch ca cho nhân viên")
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px;margin-bottom:16px;">
|
||||
<div class="admin-stat-card"><div class="admin-stat-card__icon" style="background:rgba(139,92,246,0.1);"><i data-lucide="users" style="color:#8B5CF6;"></i></div><div class="admin-stat-card__content"><span class="admin-stat-card__value">@_staffSchedules.Select(s => s.StaffId).Distinct().Count()</span><span class="admin-stat-card__label">Nhân viên có lịch</span></div></div>
|
||||
<div class="admin-stat-card"><div class="admin-stat-card__icon" style="background:rgba(59,130,246,0.1);"><i data-lucide="calendar" style="color:#3B82F6;"></i></div><div class="admin-stat-card__content"><span class="admin-stat-card__value">@_staffSchedules.Count</span><span class="admin-stat-card__label">Ca làm việc</span></div></div>
|
||||
</div>
|
||||
<div class="admin-panel">
|
||||
<div class="admin-panel__header"><h3 class="admin-panel__title">Lịch làm việc theo tuần</h3></div>
|
||||
<div class="admin-panel__body" style="padding:0;">
|
||||
<table class="admin-table" style="width:100%;"><thead><tr>
|
||||
<th style="padding:12px 16px;text-align:left;font-size:12px;text-transform:uppercase;color:var(--admin-text-tertiary);">Nhân viên</th>
|
||||
<th style="padding:12px 16px;text-align:left;font-size:12px;text-transform:uppercase;color:var(--admin-text-tertiary);">Vai trò</th>
|
||||
<th style="padding:12px 16px;text-align:center;font-size:12px;text-transform:uppercase;color:var(--admin-text-tertiary);">Thứ</th>
|
||||
<th style="padding:12px 16px;text-align:center;font-size:12px;text-transform:uppercase;color:var(--admin-text-tertiary);">Bắt đầu</th>
|
||||
<th style="padding:12px 16px;text-align:center;font-size:12px;text-transform:uppercase;color:var(--admin-text-tertiary);">Kết thúc</th>
|
||||
</tr></thead><tbody>
|
||||
@foreach (var s in _staffSchedules.OrderBy(x => x.DayOfWeek).ThenBy(x => x.StartTime))
|
||||
{
|
||||
<tr style="border-top:1px solid var(--admin-border-subtle);">
|
||||
<td style="padding:12px 16px;font-weight:600;">@(s.EmployeeCode ?? s.StaffId.ToString()[..8])</td>
|
||||
<td style="padding:12px 16px;font-size:13px;color:var(--admin-text-tertiary);">@(s.Role ?? "—")</td>
|
||||
<td style="padding:12px 16px;text-align:center;font-weight:600;color:var(--admin-orange-primary);">@DayLabel(s.DayOfWeek)</td>
|
||||
<td style="padding:12px 16px;text-align:center;">@s.StartTime</td>
|
||||
<td style="padding:12px 16px;text-align:center;">@s.EndTime</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody></table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
break;
|
||||
|
||||
// ═══ PROMOTIONS (real data) ═══
|
||||
case "promotions":
|
||||
@if (!_promotions.Any())
|
||||
@@ -940,6 +978,9 @@
|
||||
case "promotions":
|
||||
_promotions = await DataService.GetPromotionsAsync();
|
||||
break;
|
||||
case "schedule":
|
||||
_staffSchedules = await DataService.GetStaffSchedulesAsync(_shopGuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -972,6 +1013,7 @@
|
||||
case "promotions": _sectionTitle = "Khuyến mãi"; _sectionIcon = "tag"; _sectionDescription = "Quản lý chương trình khuyến mãi."; break;
|
||||
case "settings": _sectionTitle = "Thiết lập"; _sectionIcon = "settings"; _sectionDescription = "Cài đặt cửa hàng."; break;
|
||||
case "reports": _sectionTitle = "Báo cáo"; _sectionIcon = "bar-chart-2"; _sectionDescription = "Doanh thu, sản phẩm bán chạy."; break;
|
||||
case "schedule": _sectionTitle = "Lịch làm việc"; _sectionIcon = "calendar-clock"; _sectionDescription = "Lịch ca làm việc nhân viên."; break;
|
||||
default: _sectionTitle = Section ?? "Trang"; _sectionIcon = "layout-dashboard"; _sectionDescription = "Trang đang phát triển."; break;
|
||||
}
|
||||
}
|
||||
@@ -1065,4 +1107,11 @@
|
||||
}
|
||||
catch (Exception ex) { _staffFormMessage = $"Lỗi: {ex.Message}"; _staffFormSuccess = false; }
|
||||
}
|
||||
|
||||
// EN: Day-of-week label / VI: Nhãn ngày trong tuần
|
||||
private static string DayLabel(int dow) => dow switch
|
||||
{
|
||||
0 => "CN", 1 => "T2", 2 => "T3", 3 => "T4",
|
||||
4 => "T5", 5 => "T6", 6 => "T7", _ => $"#{dow}"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ public static class ShopSidebarConfig
|
||||
new("Sản phẩm", "package", "products"),
|
||||
new("Tài chính", "trending-up", "finance"),
|
||||
new("Nhân sự", "users", "staff"),
|
||||
new("Lịch làm việc", "calendar-clock", "schedule"),
|
||||
new("Khách hàng", "heart", "customers"),
|
||||
new("Khuyến mãi", "tag", "promotions"),
|
||||
new("Báo cáo", "bar-chart-2", "reports"),
|
||||
@@ -96,6 +97,7 @@ public static class ShopSidebarConfig
|
||||
new("Sản phẩm", "package", "products"),
|
||||
new("Tài chính", "trending-up", "finance"),
|
||||
new("Nhân sự", "users", "staff"),
|
||||
new("Lịch làm việc", "calendar-clock", "schedule"),
|
||||
new("Khách hàng", "heart", "customers"),
|
||||
new("Khuyến mãi", "tag", "promotions"),
|
||||
new("Báo cáo", "bar-chart-2", "reports"),
|
||||
|
||||
Reference in New Issue
Block a user