import { useCallback, useEffect, useState } from "react"; import { Link, useParams } from "react-router-dom"; import { requests as requestsApi, ApiError } from "../api/client"; import type { ChangeRequest } from "../api/types"; import { useNotifications } from "../context/NotificationsContext"; import { Button, Card, Spinner } from "../components/ui"; import { StateBadge } from "../components/StateBadge"; import { ChangeList } from "../components/ChangeRenderer"; import { AgentAvatar } from "../components/AgentAvatar"; import { DecisionModal } from "../components/DecisionModal"; import { expiresIn, formatDateTime, relativeTime } from "../utils"; type Decision = "APPROVE" | "REJECT" | "REQUEST_CHANGES"; export function RequestDetailPage() { const { id } = useParams<{ id: string }>(); const { requestEventTick } = useNotifications(); const [request, setRequest] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [decision, setDecision] = useState(null); const load = useCallback(async () => { if (!id) return; try { setRequest(await requestsApi.get(id)); setError(null); } catch (err) { setError(err instanceof ApiError ? err.message : "Failed to load"); } finally { setLoading(false); } }, [id]); useEffect(() => { load(); }, [load, requestEventTick]); if (loading) { return (
); } if (error || !request) { return (

{error ?? "Not found"}

← Back to requests
); } const exp = expiresIn(request.expires_at); const canDecide = request.state === "PENDING"; return (
← Back to requests {request.resubmitted && request.state === "PENDING" && (
UPDATED

This request was revised by the agent after you requested changes (update #{request.update_count}). Please re-review the changes below.

)}

{request.title}

{request.description &&

{request.description}

}
{request.comment && (

{request.state === "CHANGES_REQUESTED" ? "Changes requested" : "Reviewer note"}

{request.comment}

)}

Proposed changes ({request.changes.length})

{canDecide && (

Your decision

{exp.text}

)}

Agent

{request.agent ? (

{request.agent.name}

{request.agent.website && ( {request.agent.website} )}
) : (

Unknown

)} {request.agent?.description && (

{request.agent.description}

)}
{request.request_id}} /> {request.content_hash}} /> {request.decided_at && } {request.consumed_at && } {request.update_count > 0 && } {request.metadata && Object.keys(request.metadata).length > 0 && (

Metadata

{Object.entries(request.metadata).map(([k, v]) => ( {String(v)}} /> ))}
)} {request.receipt && (

🔏 Signed receipt

{request.receipt.signature}} />
)}
setDecision(null)} onDone={setRequest} />
); } function Row({ label, value }: { label: string; value: React.ReactNode }) { return (
{label} {value}
); }