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

@@ -70,6 +70,8 @@ interface MissionManagerProps {
onSelectTask?: (taskId: string) => void;
availableTasks?: Array<{ id: string; title?: string }>;
resumeSessionId?: string;
/** Pre-select and load this mission when the modal opens */
targetMissionId?: string;
}
// Status badge colors — use CSS custom-property-compatible tokens
@@ -156,7 +158,7 @@ const EMPTY_FEATURE_FORM: FeatureFormData = {
status: "defined",
};
export function MissionManager({ isOpen, onClose, addToast, projectId, onSelectTask, availableTasks = [], resumeSessionId }: MissionManagerProps) {
export function MissionManager({ isOpen, onClose, addToast, projectId, onSelectTask, availableTasks = [], resumeSessionId, targetMissionId }: MissionManagerProps) {
const [missions, setMissions] = useState<Mission[]>([]);
const [selectedMission, setSelectedMission] = useState<MissionWithHierarchy | null>(null);
const [loading, setLoading] = useState(true);
@@ -241,6 +243,22 @@ export function MissionManager({ isOpen, onClose, addToast, projectId, onSelectT
}
}, [isOpen, loadMissions]);
// Auto-load target mission when specified
const targetLoadedRef = useRef<string | null>(null);
useEffect(() => {
if (isOpen && targetMissionId && targetLoadedRef.current !== targetMissionId && missions.length > 0) {
targetLoadedRef.current = targetMissionId;
loadMissionDetail(targetMissionId);
}
}, [isOpen, targetMissionId, missions, loadMissionDetail]);
// Reset target tracking when modal closes
useEffect(() => {
if (!isOpen) {
targetLoadedRef.current = null;
}
}, [isOpen]);
// Mission handlers
const handleCreateMission = useCallback(() => {
setIsCreatingMission(true);