Pipeline view groups phases by dependency depth with DAG visualization. Phase detail panel with Tiptap rich content editor and auto-save. Code review tab with diff viewer and comment threads (dummy data). Centralized live updates hook replaces scattered subscription boilerplate. Extract agent output parsing into shared utility. Inbox detail panel, account cards, and agent action components.
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
import { Check, RotateCcw } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import type { ReviewComment } from "./types";
|
|
|
|
interface CommentThreadProps {
|
|
comments: ReviewComment[];
|
|
onResolve: (commentId: string) => void;
|
|
onUnresolve: (commentId: string) => void;
|
|
}
|
|
|
|
export function CommentThread({ comments, onResolve, onUnresolve }: CommentThreadProps) {
|
|
return (
|
|
<div className="space-y-2">
|
|
{comments.map((comment) => (
|
|
<div
|
|
key={comment.id}
|
|
className={`rounded border p-2.5 text-xs space-y-1.5 ${
|
|
comment.resolved
|
|
? "border-green-200 dark:border-green-900 bg-green-50/50 dark:bg-green-950/10"
|
|
: "border-border bg-card"
|
|
}`}
|
|
>
|
|
<div className="flex items-center justify-between gap-2">
|
|
<div className="flex items-center gap-1.5">
|
|
<span className="font-semibold text-foreground">{comment.author}</span>
|
|
<span className="text-muted-foreground">
|
|
{formatTime(comment.createdAt)}
|
|
</span>
|
|
{comment.resolved && (
|
|
<span className="flex items-center gap-0.5 text-green-600 text-[10px] font-medium">
|
|
<Check className="h-3 w-3" />
|
|
Resolved
|
|
</span>
|
|
)}
|
|
</div>
|
|
<div>
|
|
{comment.resolved ? (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="h-6 px-1.5 text-[10px]"
|
|
onClick={() => onUnresolve(comment.id)}
|
|
>
|
|
<RotateCcw className="h-3 w-3 mr-0.5" />
|
|
Reopen
|
|
</Button>
|
|
) : (
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="h-6 px-1.5 text-[10px]"
|
|
onClick={() => onResolve(comment.id)}
|
|
>
|
|
<Check className="h-3 w-3 mr-0.5" />
|
|
Resolve
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<p className="text-foreground/90 leading-relaxed whitespace-pre-wrap">
|
|
{comment.body}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function formatTime(iso: string): string {
|
|
const d = new Date(iso);
|
|
return d.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit" });
|
|
}
|