feat(FN-970): add mission badge to TaskCard with navigation to MissionManager

- Add mission badge UI to TaskCard showing linked mission name with colored indicator
- Wire up onOpenMission prop through App → Board → Column → WorktreeGroup → TaskCard
- Add CSS styles for mission badge with hover and click states
- Update MissionManager with openMission callback support for navigation from cards
- Add comprehensive tests for mission badge rendering, click behavior, and edge cases
This commit is contained in:
gsxdsm
2026-04-05 12:03:50 -07:00
parent f78845c2cd
commit 64dbbdd5ba
9 changed files with 165 additions and 6 deletions

View File

@@ -19,6 +19,8 @@ interface WorktreeGroupProps {
onOpenDetailWithTab?: (task: TaskDetail, initialTab: "changes") => void;
/** Project-level stuck task timeout in milliseconds (undefined = disabled) */
taskStuckTimeoutMs?: number;
/** Called when user clicks a mission badge on a task card */
onOpenMission?: (missionId: string) => void;
}
function WorktreeGroupComponent({
@@ -32,6 +34,7 @@ function WorktreeGroupComponent({
onUpdateTask,
onOpenDetailWithTab,
taskStuckTimeoutMs,
onOpenMission,
}: WorktreeGroupProps) {
return (
<div className="worktree-group">
@@ -42,7 +45,7 @@ function WorktreeGroupComponent({
<span className="worktree-label">{label}</span>
</div>
{activeTasks.map((task) => (
<TaskCard key={task.id} task={task} projectId={projectId} onOpenDetail={onOpenDetail} addToast={addToast} globalPaused={globalPaused} onUpdateTask={onUpdateTask} onOpenDetailWithTab={onOpenDetailWithTab} taskStuckTimeoutMs={taskStuckTimeoutMs} />
<TaskCard key={task.id} task={task} projectId={projectId} onOpenDetail={onOpenDetail} addToast={addToast} globalPaused={globalPaused} onUpdateTask={onUpdateTask} onOpenDetailWithTab={onOpenDetailWithTab} taskStuckTimeoutMs={taskStuckTimeoutMs} onOpenMission={onOpenMission} />
))}
{queuedTasks.map((task) => (
<TaskCard
@@ -56,6 +59,7 @@ function WorktreeGroupComponent({
onUpdateTask={onUpdateTask}
onOpenDetailWithTab={onOpenDetailWithTab}
taskStuckTimeoutMs={taskStuckTimeoutMs}
onOpenMission={onOpenMission}
/>
))}
</div>