diff --git a/backend/app/routers/projects.py b/backend/app/routers/projects.py index b95b32b..2f85ce0 100644 --- a/backend/app/routers/projects.py +++ b/backend/app/routers/projects.py @@ -44,8 +44,8 @@ def _project_load_options(): selectinload(Project.tasks).selectinload(ProjectTask.comments).selectinload(TaskComment.user), selectinload(Project.tasks).selectinload(ProjectTask.subtasks).selectinload(ProjectTask.comments).selectinload(TaskComment.user), selectinload(Project.tasks).selectinload(ProjectTask.subtasks).selectinload(ProjectTask.subtasks), - selectinload(Project.tasks).selectinload(ProjectTask.assignments), - selectinload(Project.tasks).selectinload(ProjectTask.subtasks).selectinload(ProjectTask.assignments), + selectinload(Project.tasks).selectinload(ProjectTask.assignments).selectinload(ProjectTaskAssignment.user), + selectinload(Project.tasks).selectinload(ProjectTask.subtasks).selectinload(ProjectTask.assignments).selectinload(ProjectTaskAssignment.user), selectinload(Project.members), ] @@ -56,8 +56,8 @@ def _task_load_options(): selectinload(ProjectTask.comments).selectinload(TaskComment.user), selectinload(ProjectTask.subtasks).selectinload(ProjectTask.comments), selectinload(ProjectTask.subtasks).selectinload(ProjectTask.subtasks), - selectinload(ProjectTask.assignments), - selectinload(ProjectTask.subtasks).selectinload(ProjectTask.assignments), + selectinload(ProjectTask.assignments).selectinload(ProjectTaskAssignment.user), + selectinload(ProjectTask.subtasks).selectinload(ProjectTask.assignments).selectinload(ProjectTaskAssignment.user), ] diff --git a/backend/app/schemas/project_task_assignment.py b/backend/app/schemas/project_task_assignment.py index 4d21f1f..27bbaff 100644 --- a/backend/app/schemas/project_task_assignment.py +++ b/backend/app/schemas/project_task_assignment.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, model_validator from datetime import datetime @@ -17,3 +17,19 @@ class TaskAssignmentResponse(BaseModel): created_at: datetime model_config = ConfigDict(from_attributes=True) + + @model_validator(mode="before") + @classmethod + def resolve_user_name(cls, data): # type: ignore[override] + """Populate user_name from eagerly loaded user relationship.""" + if hasattr(data, "user") and data.user is not None: + if not getattr(data, "user_name", None): + data = dict( + id=data.id, + task_id=data.task_id, + user_id=data.user_id, + assigned_by=data.assigned_by, + user_name=data.user.username, + created_at=data.created_at, + ) + return data diff --git a/frontend/src/components/projects/TaskRow.tsx b/frontend/src/components/projects/TaskRow.tsx index 8a94f01..ebea04c 100644 --- a/frontend/src/components/projects/TaskRow.tsx +++ b/frontend/src/components/projects/TaskRow.tsx @@ -135,12 +135,21 @@ export default function TaskRow({ {hasSubtasks ? `${completedSubtasks}/${task.subtasks.length}` : '—'} - {/* Assignee avatars */} - {task.assignments && task.assignments.length > 0 && ( - - - - )} + {/* Assigned column */} + + {task.assignments && task.assignments.length > 0 ? ( + <> + + + {task.assignments.length === 1 + ? (task.assignments[0].user_name ?? 'Unknown') + : `${task.assignments.length} people`} + + + ) : ( + + )} + {/* Mobile-only: compact priority dot + overdue indicator */}