feat(pos): Display empty state messages for resource grids and implement shop-specific staff management in POS views.
This commit is contained in:
@@ -2861,7 +2861,7 @@
|
||||
case "overview":
|
||||
_ovOrders = await DataService.GetOrdersAsync(_shopGuid);
|
||||
_ovProducts = await DataService.GetAllProductsAsync(_shopGuid);
|
||||
_ovStaff = await DataService.GetStaffAsync();
|
||||
_ovStaff = await DataService.GetStaffForShopAsync(_shopGuid.Value);
|
||||
if (_shopGuid.HasValue && (_posVertical == "restaurant" || _posVertical == "karaoke"))
|
||||
_ovTables = await DataService.GetTablesAsync(_shopGuid.Value);
|
||||
if (_shopGuid.HasValue && (_posVertical == "spa" || _posVertical == "beauty"))
|
||||
@@ -2882,7 +2882,7 @@
|
||||
_walletTxns = await DataService.GetWalletTransactionsAsync();
|
||||
break;
|
||||
case "staff":
|
||||
_staff = await DataService.GetStaffAsync();
|
||||
_staff = await DataService.GetStaffForShopAsync(_shopGuid.Value);
|
||||
_staffSchedules = await DataService.GetStaffSchedulesAsync(_shopGuid);
|
||||
break;
|
||||
case "customers":
|
||||
@@ -2922,7 +2922,7 @@
|
||||
case "shifts":
|
||||
case "schedule":
|
||||
_staffSchedules = await DataService.GetStaffSchedulesAsync(_shopGuid);
|
||||
_staff = await DataService.GetStaffAsync();
|
||||
_staff = await DataService.GetStaffForShopAsync(_shopGuid.Value);
|
||||
break;
|
||||
case "kitchen":
|
||||
if (_shopGuid.HasValue)
|
||||
@@ -3008,7 +3008,7 @@
|
||||
case "inventory": _sectionTitle = "Tồn kho"; _sectionIcon = "warehouse"; _sectionDescription = "Theo dõi tồn kho, cảnh báo hết hàng."; break;
|
||||
case "finance": _sectionTitle = "Tài chính"; _sectionIcon = "trending-up"; _sectionDescription = "Doanh thu, đơn hàng, chi phí."; break;
|
||||
case "staff": _sectionTitle = "Nhân sự"; _sectionIcon = "users"; _sectionDescription = "Quản lý nhân viên cửa hàng."; break;
|
||||
case "customers": _sectionTitle = "Khách hàng"; _sectionIcon = "heart"; _sectionDescription = "Khách hàng, thành viên."; break;
|
||||
case "customers": _sectionTitle = "Khách hàng"; _sectionIcon = "heart"; _sectionDescription = "Khách hàng & thành viên — dữ liệu chung cho tất cả cửa hàng."; break;
|
||||
case "pos": _sectionTitle = "POS Bán hàng"; _sectionIcon = "monitor"; _sectionDescription = "Mở giao diện bán hàng tại điểm."; break;
|
||||
case "tables": _sectionTitle = "Quản lý Bàn"; _sectionIcon = "grid-3x3"; _sectionDescription = "Sơ đồ bàn, khu vực phục vụ."; break;
|
||||
case "kitchen": _sectionTitle = "Bếp (Kitchen)"; _sectionIcon = "flame"; _sectionDescription = "Màn hình hiển thị đơn cho bếp."; break;
|
||||
@@ -3017,7 +3017,7 @@
|
||||
case "services": _sectionTitle = "Dịch vụ"; _sectionIcon = "sparkles"; _sectionDescription = "Quản lý danh mục dịch vụ."; break;
|
||||
case "resources": _sectionTitle = "Tài nguyên"; _sectionIcon = "door-open"; _sectionDescription = "Quản lý phòng, giường, thiết bị."; break;
|
||||
case "treatments": _sectionTitle = "Liệu trình"; _sectionIcon = "clipboard-list"; _sectionDescription = "Theo dõi liệu trình điều trị."; break;
|
||||
case "promotions": _sectionTitle = "Khuyến mãi"; _sectionIcon = "tag"; _sectionDescription = "Quản lý chương trình khuyến mãi."; break;
|
||||
case "promotions": _sectionTitle = "Khuyến mãi"; _sectionIcon = "tag"; _sectionDescription = "Chương trình khuyến mãi — dữ liệu chung cho tất cả cửa hàng."; 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;
|
||||
@@ -3213,7 +3213,7 @@
|
||||
}
|
||||
_newStaffCode = ""; _newStaffPhone = ""; _newStaffEmail = ""; _newStaffFirstName = ""; _newStaffLastName = ""; _newStaffPassword = ""; _newStaffAddress = ""; _createStaffAccount = false;
|
||||
_staffDocFrontFile = null; _staffDocBackFile = null; _staffDocFrontPreview = null; _staffDocBackPreview = null;
|
||||
_staff = await DataService.GetStaffAsync();
|
||||
_staff = await DataService.GetStaffForShopAsync(_shopGuid.Value);
|
||||
}
|
||||
catch (Exception ex) { _staffFormMessage = $"Lỗi: {ex.Message}"; _staffFormSuccess = false; }
|
||||
}
|
||||
@@ -3252,7 +3252,7 @@
|
||||
_staffFormMessage = $"Đã cập nhật NV '{_newStaffCode}' thành công!"; _staffFormSuccess = true;
|
||||
_editingStaffId = null;
|
||||
_staffDocFrontFile = null; _staffDocBackFile = null; _staffDocFrontPreview = null; _staffDocBackPreview = null;
|
||||
_staff = await DataService.GetStaffAsync();
|
||||
_staff = await DataService.GetStaffForShopAsync(_shopGuid.Value);
|
||||
}
|
||||
catch (Exception ex) { _staffFormMessage = $"Lỗi: {ex.Message}"; _staffFormSuccess = false; }
|
||||
}
|
||||
@@ -3262,7 +3262,7 @@
|
||||
try
|
||||
{
|
||||
await DataService.DeleteStaffAsync(staffId);
|
||||
_staff = await DataService.GetStaffAsync();
|
||||
_staff = await DataService.GetStaffForShopAsync(_shopGuid.Value);
|
||||
}
|
||||
catch (Exception ex) { _errorMessage = $"Không thể xóa nhân viên: {ex.Message}"; }
|
||||
}
|
||||
|
||||
@@ -41,6 +41,16 @@
|
||||
</div>
|
||||
|
||||
@* ═══ ROOM GRID / LƯỚI PHÒNG ═══ *@
|
||||
@if (!_rooms.Any())
|
||||
{
|
||||
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 0;color:var(--pos-text-tertiary);">
|
||||
<i data-lucide="door-open" style="width:48px;height:48px;margin-bottom:12px;opacity:0.3;"></i>
|
||||
<div style="font-size:15px;font-weight:600;margin-bottom:4px;">Chưa có phòng nào</div>
|
||||
<div style="font-size:13px;">Vui lòng thêm phòng trong phần Quản lý cửa hàng</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px;padding:8px 0;">
|
||||
@foreach (var room in FilteredRooms)
|
||||
{
|
||||
@@ -70,6 +80,7 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@* ═══ SESSION PANEL (RIGHT) / PANEL PHIÊN HÁT (PHẢI) ═══ *@
|
||||
|
||||
@@ -34,6 +34,16 @@
|
||||
</div>
|
||||
|
||||
@* ═══ TABLE MAP GRID / LƯỚI SƠ ĐỒ BÀN ═══ *@
|
||||
@if (!_tables.Any())
|
||||
{
|
||||
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 0;color:var(--pos-text-tertiary);">
|
||||
<i data-lucide="grid-3x3" style="width:48px;height:48px;margin-bottom:12px;opacity:0.3;"></i>
|
||||
<div style="font-size:15px;font-weight:600;margin-bottom:4px;">Chưa có bàn nào</div>
|
||||
<div style="font-size:13px;">Vui lòng thêm bàn trong phần Quản lý cửa hàng</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:12px;padding:8px 0;">
|
||||
@foreach (var table in FilteredTables)
|
||||
{
|
||||
@@ -49,6 +59,7 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -35,6 +35,16 @@
|
||||
</div>
|
||||
|
||||
@* ═══ SERVICE GRID / LƯỚI DỊCH VỤ ═══ *@
|
||||
@if (!_services.Any())
|
||||
{
|
||||
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 0;color:var(--pos-text-tertiary);">
|
||||
<i data-lucide="sparkles" style="width:48px;height:48px;margin-bottom:12px;opacity:0.3;"></i>
|
||||
<div style="font-size:15px;font-weight:600;margin-bottom:4px;">Chưa có dịch vụ nào</div>
|
||||
<div style="font-size:13px;">Vui lòng thêm dịch vụ trong phần Quản lý cửa hàng</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="pos-product-grid">
|
||||
@foreach (var svc in FilteredServices)
|
||||
{
|
||||
@@ -50,6 +60,7 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -142,8 +142,18 @@ public class PosDataService
|
||||
public record CategoryInfo(Guid Id, string Name, string? Description, int DisplayOrder, string? ImageUrl = null);
|
||||
public record TableInfo(Guid Id, string TableNumber, int Capacity, string? Zone, string Status, Guid? SessionId, int? GuestCount, DateTime? StartedAt);
|
||||
public record AppointmentInfo(Guid Id, Guid? CustomerId, Guid? StaffId, Guid? ResourceId, Guid ServiceId, DateTime StartTime, DateTime EndTime, string Status, string? ResourceName);
|
||||
public record ShopAssignmentInfo(Guid ShopId, string? ShopRole, Guid? BranchId);
|
||||
public record StaffInfo(Guid Id, Guid? UserId, string? EmployeeCode, string? Phone, string? Email, DateTime? JoinedAt, DateTime? TerminatedAt, string? Role, string? Status, string? ShopName,
|
||||
string? FirstName = null, string? LastName = null, string? Address = null, string? ProfilePhotoUrl = null, string? DocumentFrontUrl = null, string? DocumentBackUrl = null);
|
||||
string? FirstName = null, string? LastName = null, string? Address = null, string? ProfilePhotoUrl = null, string? DocumentFrontUrl = null, string? DocumentBackUrl = null,
|
||||
List<ShopAssignmentInfo>? ShopAssignments = null);
|
||||
|
||||
public async Task<List<StaffInfo>> GetStaffForShopAsync(Guid shopId)
|
||||
{
|
||||
var all = await GetStaffAsync();
|
||||
return all.Where(s =>
|
||||
s.ShopAssignments == null || s.ShopAssignments.Count == 0 ||
|
||||
s.ShopAssignments.Any(a => a.ShopId == shopId)).ToList();
|
||||
}
|
||||
|
||||
public async Task<List<ShopInfo>> GetShopsAsync()
|
||||
=> await GetListFromApiAsync<ShopInfo>("api/bff/shops");
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using MediatR;
|
||||
using FnbEngine.Domain.AggregatesModel.TableAggregate;
|
||||
using FnbEngine.Domain.SeedWork;
|
||||
|
||||
namespace FnbEngine.API.Application.Queries;
|
||||
|
||||
@@ -23,13 +24,16 @@ public class GetTablesQueryHandler : IRequestHandler<GetTablesQuery, IEnumerable
|
||||
{
|
||||
var tables = await _tableRepository.GetByShopAsync(request.ShopId, cancellationToken);
|
||||
|
||||
var allStatuses = Enumeration.GetAll<TableStatus>()
|
||||
.ToDictionary(s => s.Id, s => s.Name.ToLowerInvariant());
|
||||
|
||||
return tables.Select(t => new TableDto(
|
||||
t.Id,
|
||||
t.ShopId,
|
||||
t.TableNumber,
|
||||
t.Capacity,
|
||||
t.Zone,
|
||||
t.Status.Name
|
||||
allStatuses.TryGetValue(t.StatusId, out var name) ? name : "available"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user