feat: Enrich DTOs and UI to display member names instead of UUIDs for task assignees, creators, and shift signups.
This commit is contained in:
@@ -76,26 +76,27 @@ public class ShiftService
|
||||
{
|
||||
var shift = await _context.Shifts.FindAsync(id);
|
||||
|
||||
if (shift == null)
|
||||
return null;
|
||||
if (shift == null)
|
||||
return null;
|
||||
|
||||
var signups = await (from ss in _context.ShiftSignups
|
||||
where ss.ShiftId == id
|
||||
join m in _context.Members on ss.MemberId equals m.Id
|
||||
orderby ss.SignedUpAt
|
||||
select new { ss.Id, ss.MemberId, m.ExternalUserId, ss.SignedUpAt })
|
||||
.ToListAsync();
|
||||
var signups = await (from ss in _context.ShiftSignups
|
||||
where ss.ShiftId == id
|
||||
join m in _context.Members on ss.MemberId equals m.Id
|
||||
orderby ss.SignedUpAt
|
||||
select new { ss.Id, ss.MemberId, m.DisplayName, m.ExternalUserId, ss.SignedUpAt })
|
||||
.ToListAsync();
|
||||
|
||||
var signupDtos = signups.Select(ss => new ShiftSignupDto(
|
||||
ss.Id,
|
||||
ss.MemberId,
|
||||
ss.ExternalUserId,
|
||||
ss.SignedUpAt
|
||||
)).ToList();
|
||||
var signupDtos = signups.Select(ss => new ShiftSignupDto(
|
||||
ss.Id,
|
||||
ss.MemberId,
|
||||
ss.DisplayName,
|
||||
ss.ExternalUserId,
|
||||
ss.SignedUpAt
|
||||
)).ToList();
|
||||
|
||||
var isSignedUp = currentExternalUserId != null && signupDtos.Any(s => s.ExternalUserId == currentExternalUserId);
|
||||
var isSignedUp = currentExternalUserId != null && signupDtos.Any(s => s.ExternalUserId == currentExternalUserId);
|
||||
|
||||
return new ShiftDetailDto(
|
||||
return new ShiftDetailDto(
|
||||
shift.Id,
|
||||
shift.Title,
|
||||
shift.Description,
|
||||
@@ -190,23 +191,24 @@ public class ShiftService
|
||||
return (null, "Shift was modified by another user. Please refresh and try again.", true);
|
||||
}
|
||||
|
||||
var signups = await (from ss in _context.ShiftSignups
|
||||
where ss.ShiftId == id
|
||||
join m in _context.Members on ss.MemberId equals m.Id
|
||||
orderby ss.SignedUpAt
|
||||
select new { ss.Id, ss.MemberId, m.ExternalUserId, ss.SignedUpAt })
|
||||
.ToListAsync();
|
||||
var signups = await (from ss in _context.ShiftSignups
|
||||
where ss.ShiftId == id
|
||||
join m in _context.Members on ss.MemberId equals m.Id
|
||||
orderby ss.SignedUpAt
|
||||
select new { ss.Id, ss.MemberId, m.DisplayName, m.ExternalUserId, ss.SignedUpAt })
|
||||
.ToListAsync();
|
||||
|
||||
var signupDtos = signups.Select(ss => new ShiftSignupDto(
|
||||
ss.Id,
|
||||
ss.MemberId,
|
||||
ss.ExternalUserId,
|
||||
ss.SignedUpAt
|
||||
)).ToList();
|
||||
var signupDtos = signups.Select(ss => new ShiftSignupDto(
|
||||
ss.Id,
|
||||
ss.MemberId,
|
||||
ss.DisplayName,
|
||||
ss.ExternalUserId,
|
||||
ss.SignedUpAt
|
||||
)).ToList();
|
||||
|
||||
var isSignedUp = currentExternalUserId != null && signupDtos.Any(s => s.ExternalUserId == currentExternalUserId);
|
||||
var isSignedUp = currentExternalUserId != null && signupDtos.Any(s => s.ExternalUserId == currentExternalUserId);
|
||||
|
||||
var dto = new ShiftDetailDto(
|
||||
var dto = new ShiftDetailDto(
|
||||
shift.Id,
|
||||
shift.Title,
|
||||
shift.Description,
|
||||
|
||||
@@ -30,67 +30,89 @@ public class TaskService
|
||||
}
|
||||
}
|
||||
|
||||
var total = await query.CountAsync();
|
||||
var total = await query.CountAsync();
|
||||
|
||||
var items = await query
|
||||
.OrderBy(w => w.CreatedAt)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
var items = await query
|
||||
.OrderBy(w => w.CreatedAt)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
Guid? memberId = null;
|
||||
if (currentExternalUserId != null)
|
||||
{
|
||||
var tenantId = _tenantProvider.GetTenantId();
|
||||
memberId = await _context.Members
|
||||
.Where(m => m.ExternalUserId == currentExternalUserId && m.TenantId == tenantId)
|
||||
.Select(m => m.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
// Get current member ID for IsAssignedToMe check
|
||||
Guid? currentMemberId = null;
|
||||
if (currentExternalUserId != null)
|
||||
{
|
||||
var tenantId = _tenantProvider.GetTenantId();
|
||||
currentMemberId = await _context.Members
|
||||
.Where(m => m.ExternalUserId == currentExternalUserId && m.TenantId == tenantId)
|
||||
.Select(m => m.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
var itemDtos = items.Select(w => new TaskListItemDto(
|
||||
w.Id,
|
||||
w.Title,
|
||||
w.Status.ToString(),
|
||||
w.AssigneeId,
|
||||
w.CreatedAt,
|
||||
memberId != null && w.AssigneeId == memberId
|
||||
)).ToList();
|
||||
// Get all assignee IDs to fetch their names in bulk
|
||||
var assigneeIds = items.Where(w => w.AssigneeId.HasValue).Select(w => w.AssigneeId!.Value).Distinct().ToList();
|
||||
var assigneeNames = await _context.Members
|
||||
.Where(m => assigneeIds.Contains(m.Id))
|
||||
.Select(m => new { m.Id, m.DisplayName })
|
||||
.ToDictionaryAsync(m => m.Id, m => m.DisplayName);
|
||||
|
||||
return new TaskListDto(itemDtos, total, page, pageSize);
|
||||
}
|
||||
var itemDtos = items.Select(w => new TaskListItemDto(
|
||||
w.Id,
|
||||
w.Title,
|
||||
w.Status.ToString(),
|
||||
w.AssigneeId,
|
||||
w.AssigneeId.HasValue && assigneeNames.TryGetValue(w.AssigneeId.Value, out var name) ? name : null,
|
||||
w.CreatedAt,
|
||||
currentMemberId != null && w.AssigneeId == currentMemberId
|
||||
)).ToList();
|
||||
|
||||
public async Task<TaskDetailDto?> GetTaskByIdAsync(Guid id, string? currentExternalUserId = null)
|
||||
{
|
||||
var workItem = await _context.WorkItems.FindAsync(id);
|
||||
return new TaskListDto(itemDtos, total, page, pageSize);
|
||||
}
|
||||
|
||||
if (workItem == null)
|
||||
return null;
|
||||
public async Task<TaskDetailDto?> GetTaskByIdAsync(Guid id, string? currentExternalUserId = null)
|
||||
{
|
||||
var workItem = await _context.WorkItems.FindAsync(id);
|
||||
|
||||
Guid? memberId = null;
|
||||
if (currentExternalUserId != null)
|
||||
{
|
||||
var tenantId = _tenantProvider.GetTenantId();
|
||||
memberId = await _context.Members
|
||||
.Where(m => m.ExternalUserId == currentExternalUserId && m.TenantId == tenantId)
|
||||
.Select(m => m.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
if (workItem == null)
|
||||
return null;
|
||||
|
||||
return new TaskDetailDto(
|
||||
workItem.Id,
|
||||
workItem.Title,
|
||||
workItem.Description,
|
||||
workItem.Status.ToString(),
|
||||
workItem.AssigneeId,
|
||||
workItem.CreatedById,
|
||||
workItem.ClubId,
|
||||
workItem.DueDate,
|
||||
workItem.CreatedAt,
|
||||
workItem.UpdatedAt,
|
||||
memberId != null && workItem.AssigneeId == memberId
|
||||
);
|
||||
}
|
||||
// Get current member ID for IsAssignedToMe check
|
||||
Guid? currentMemberId = null;
|
||||
if (currentExternalUserId != null)
|
||||
{
|
||||
var tenantId = _tenantProvider.GetTenantId();
|
||||
currentMemberId = await _context.Members
|
||||
.Where(m => m.ExternalUserId == currentExternalUserId && m.TenantId == tenantId)
|
||||
.Select(m => m.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
// Fetch assignee and creator names
|
||||
var memberIds = new List<Guid>();
|
||||
if (workItem.AssigneeId.HasValue) memberIds.Add(workItem.AssigneeId.Value);
|
||||
memberIds.Add(workItem.CreatedById);
|
||||
|
||||
var memberNames = await _context.Members
|
||||
.Where(m => memberIds.Contains(m.Id))
|
||||
.Select(m => new { m.Id, m.DisplayName })
|
||||
.ToDictionaryAsync(m => m.Id, m => m.DisplayName);
|
||||
|
||||
return new TaskDetailDto(
|
||||
workItem.Id,
|
||||
workItem.Title,
|
||||
workItem.Description,
|
||||
workItem.Status.ToString(),
|
||||
workItem.AssigneeId,
|
||||
workItem.AssigneeId.HasValue && memberNames.TryGetValue(workItem.AssigneeId.Value, out var assigneeName) ? assigneeName : null,
|
||||
workItem.CreatedById,
|
||||
memberNames.TryGetValue(workItem.CreatedById, out var createdByName) ? createdByName : null,
|
||||
workItem.ClubId,
|
||||
workItem.DueDate,
|
||||
workItem.CreatedAt,
|
||||
workItem.UpdatedAt,
|
||||
currentMemberId != null && workItem.AssigneeId == currentMemberId
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<(TaskDetailDto? task, string? error)> CreateTaskAsync(CreateTaskRequest request, Guid createdById)
|
||||
{
|
||||
@@ -111,24 +133,35 @@ public class TaskService
|
||||
UpdatedAt = DateTimeOffset.UtcNow
|
||||
};
|
||||
|
||||
_context.WorkItems.Add(workItem);
|
||||
await _context.SaveChangesAsync();
|
||||
_context.WorkItems.Add(workItem);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var dto = new TaskDetailDto(
|
||||
workItem.Id,
|
||||
workItem.Title,
|
||||
workItem.Description,
|
||||
workItem.Status.ToString(),
|
||||
workItem.AssigneeId,
|
||||
workItem.CreatedById,
|
||||
workItem.ClubId,
|
||||
workItem.DueDate,
|
||||
workItem.CreatedAt,
|
||||
workItem.UpdatedAt,
|
||||
false
|
||||
);
|
||||
// Fetch creator and assignee names
|
||||
var memberIds = new List<Guid> { createdById };
|
||||
if (workItem.AssigneeId.HasValue) memberIds.Add(workItem.AssigneeId.Value);
|
||||
|
||||
return (dto, null);
|
||||
var memberNames = await _context.Members
|
||||
.Where(m => memberIds.Contains(m.Id))
|
||||
.Select(m => new { m.Id, m.DisplayName })
|
||||
.ToDictionaryAsync(m => m.Id, m => m.DisplayName);
|
||||
|
||||
var dto = new TaskDetailDto(
|
||||
workItem.Id,
|
||||
workItem.Title,
|
||||
workItem.Description,
|
||||
workItem.Status.ToString(),
|
||||
workItem.AssigneeId,
|
||||
workItem.AssigneeId.HasValue && memberNames.TryGetValue(workItem.AssigneeId.Value, out var assigneeName) ? assigneeName : null,
|
||||
workItem.CreatedById,
|
||||
memberNames.TryGetValue(workItem.CreatedById, out var createdByName) ? createdByName : null,
|
||||
workItem.ClubId,
|
||||
workItem.DueDate,
|
||||
workItem.CreatedAt,
|
||||
workItem.UpdatedAt,
|
||||
false
|
||||
);
|
||||
|
||||
return (dto, null);
|
||||
}
|
||||
|
||||
public async Task<(TaskDetailDto? task, string? error, bool isConflict)> UpdateTaskAsync(Guid id, UpdateTaskRequest request, string? currentExternalUserId = null)
|
||||
@@ -176,32 +209,45 @@ public class TaskService
|
||||
return (null, "Task was modified by another user. Please refresh and try again.", true);
|
||||
}
|
||||
|
||||
Guid? memberId = null;
|
||||
if (currentExternalUserId != null)
|
||||
{
|
||||
var tenantId = _tenantProvider.GetTenantId();
|
||||
memberId = await _context.Members
|
||||
.Where(m => m.ExternalUserId == currentExternalUserId && m.TenantId == tenantId)
|
||||
.Select(m => m.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
// Get current member ID for IsAssignedToMe check
|
||||
Guid? currentMemberId = null;
|
||||
if (currentExternalUserId != null)
|
||||
{
|
||||
var tenantId = _tenantProvider.GetTenantId();
|
||||
currentMemberId = await _context.Members
|
||||
.Where(m => m.ExternalUserId == currentExternalUserId && m.TenantId == tenantId)
|
||||
.Select(m => m.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
var dto = new TaskDetailDto(
|
||||
workItem.Id,
|
||||
workItem.Title,
|
||||
workItem.Description,
|
||||
workItem.Status.ToString(),
|
||||
workItem.AssigneeId,
|
||||
workItem.CreatedById,
|
||||
workItem.ClubId,
|
||||
workItem.DueDate,
|
||||
workItem.CreatedAt,
|
||||
workItem.UpdatedAt,
|
||||
memberId != null && workItem.AssigneeId == memberId
|
||||
);
|
||||
// Fetch assignee and creator names
|
||||
var memberIds = new List<Guid>();
|
||||
if (workItem.AssigneeId.HasValue) memberIds.Add(workItem.AssigneeId.Value);
|
||||
memberIds.Add(workItem.CreatedById);
|
||||
|
||||
return (dto, null, false);
|
||||
}
|
||||
var memberNames = await _context.Members
|
||||
.Where(m => memberIds.Contains(m.Id))
|
||||
.Select(m => new { m.Id, m.DisplayName })
|
||||
.ToDictionaryAsync(m => m.Id, m => m.DisplayName);
|
||||
|
||||
var dto = new TaskDetailDto(
|
||||
workItem.Id,
|
||||
workItem.Title,
|
||||
workItem.Description,
|
||||
workItem.Status.ToString(),
|
||||
workItem.AssigneeId,
|
||||
workItem.AssigneeId.HasValue && memberNames.TryGetValue(workItem.AssigneeId.Value, out var assigneeName) ? assigneeName : null,
|
||||
workItem.CreatedById,
|
||||
memberNames.TryGetValue(workItem.CreatedById, out var createdByName) ? createdByName : null,
|
||||
workItem.ClubId,
|
||||
workItem.DueDate,
|
||||
workItem.CreatedAt,
|
||||
workItem.UpdatedAt,
|
||||
currentMemberId != null && workItem.AssigneeId == currentMemberId
|
||||
);
|
||||
|
||||
return (dto, null, false);
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteTaskAsync(Guid id)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,9 @@ public record ShiftDetailDto(
|
||||
);
|
||||
|
||||
public record ShiftSignupDto(
|
||||
Guid Id,
|
||||
Guid MemberId, string? ExternalUserId,
|
||||
DateTimeOffset SignedUpAt
|
||||
Guid Id,
|
||||
Guid MemberId,
|
||||
string? MemberName,
|
||||
string? ExternalUserId,
|
||||
DateTimeOffset SignedUpAt
|
||||
);
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
namespace WorkClub.Application.Tasks.DTOs;
|
||||
|
||||
public record TaskDetailDto(
|
||||
Guid Id,
|
||||
string Title,
|
||||
string? Description,
|
||||
string Status,
|
||||
Guid? AssigneeId,
|
||||
Guid CreatedById,
|
||||
Guid ClubId,
|
||||
DateTimeOffset? DueDate,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset UpdatedAt,
|
||||
bool IsAssignedToMe
|
||||
Guid Id,
|
||||
string Title,
|
||||
string? Description,
|
||||
string Status,
|
||||
Guid? AssigneeId,
|
||||
string? AssigneeName,
|
||||
Guid CreatedById,
|
||||
string? CreatedByName,
|
||||
Guid ClubId,
|
||||
DateTimeOffset? DueDate,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset UpdatedAt,
|
||||
bool IsAssignedToMe
|
||||
);
|
||||
|
||||
@@ -8,10 +8,11 @@ public record TaskListDto(
|
||||
);
|
||||
|
||||
public record TaskListItemDto(
|
||||
Guid Id,
|
||||
string Title,
|
||||
string Status,
|
||||
Guid? AssigneeId,
|
||||
DateTimeOffset CreatedAt,
|
||||
bool IsAssignedToMe
|
||||
Guid Id,
|
||||
string Title,
|
||||
string Status,
|
||||
Guid? AssigneeId,
|
||||
string? AssigneeName,
|
||||
DateTimeOffset CreatedAt,
|
||||
bool IsAssignedToMe
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user