Improve issue and approvals UI: parent chain, project names, approval details

shared:
- Add IssueAncestor type and ancestors?: IssueAncestor[] to Issue interface

IssueDetail:
- Show clickable parent chain breadcrumb above issue title when issue has parents
- Ancestors rendered root-first (reversed from API order) with chevron separators

IssueProperties:
- Project field now shows project name with a link instead of raw UUID
- Assignee field now links to agent detail page
- Parent field shows immediate parent title (from ancestors[0]) with link
- Show request depth when > 0

Approvals:
- Pending/All filter tabs with pending count badge
- HireAgentPayload renders name, role, title, capabilities, adapter type
- CeoStrategyPayload renders plan/description text in a monospace block
- Decision note shown when present
- Requester agent name shown in header
- Approve button uses green styling; empty state with icon

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-17 20:16:57 -06:00
parent fb8a77a53b
commit 0b9bea667c
5 changed files with 331 additions and 54 deletions

View File

@@ -1,5 +1,5 @@
import { useEffect } from "react";
import { useParams } from "react-router-dom";
import { useParams, Link } from "react-router-dom";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { issuesApi } from "../api/issues";
import { useCompany } from "../context/CompanyContext";
@@ -12,6 +12,7 @@ import { IssueProperties } from "../components/IssueProperties";
import { StatusIcon } from "../components/StatusIcon";
import { PriorityIcon } from "../components/PriorityIcon";
import { Separator } from "@/components/ui/separator";
import { ChevronRight } from "lucide-react";
export function IssueDetail() {
const { issueId } = useParams<{ issueId: string }>();
@@ -69,8 +70,31 @@ export function IssueDetail() {
if (error) return <p className="text-sm text-destructive">{error.message}</p>;
if (!issue) return null;
// Ancestors are returned oldest-first from the server (root at end, immediate parent at start)
const ancestors = issue.ancestors ?? [];
return (
<div className="max-w-2xl space-y-6">
{/* Parent chain breadcrumb */}
{ancestors.length > 0 && (
<nav className="flex items-center gap-1 text-xs text-muted-foreground flex-wrap">
{[...ancestors].reverse().map((ancestor, i) => (
<span key={ancestor.id} className="flex items-center gap-1">
{i > 0 && <ChevronRight className="h-3 w-3 shrink-0" />}
<Link
to={`/issues/${ancestor.id}`}
className="hover:text-foreground transition-colors truncate max-w-[200px]"
title={ancestor.title}
>
{ancestor.title}
</Link>
</span>
))}
<ChevronRight className="h-3 w-3 shrink-0" />
<span className="text-foreground/60 truncate max-w-[200px]">{issue.title}</span>
</nav>
)}
<div className="space-y-3">
<div className="flex items-center gap-2">
<StatusIcon