import { useState, useRef, useEffect } from "react"; import { Check, RotateCcw, Reply, Pencil } from "lucide-react"; import { Button } from "@/components/ui/button"; import { CommentForm } from "./CommentForm"; import type { ReviewComment } from "./types"; interface CommentThreadProps { comments: ReviewComment[]; onResolve: (commentId: string) => void; onUnresolve: (commentId: string) => void; onReply?: (parentCommentId: string, body: string) => void; onEdit?: (commentId: string, body: string) => void; } export function CommentThread({ comments, onResolve, onUnresolve, onReply, onEdit }: CommentThreadProps) { // Group: root comments (no parentCommentId) and their replies const rootComments = comments.filter((c) => !c.parentCommentId); const repliesByParent = new Map(); for (const c of comments) { if (c.parentCommentId) { const arr = repliesByParent.get(c.parentCommentId) ?? []; arr.push(c); repliesByParent.set(c.parentCommentId, arr); } } return (
{rootComments.map((comment) => ( ))}
); } function RootComment({ comment, replies, onResolve, onUnresolve, onReply, onEdit, }: { comment: ReviewComment; replies: ReviewComment[]; onResolve: (id: string) => void; onUnresolve: (id: string) => void; onReply?: (parentCommentId: string, body: string) => void; onEdit?: (commentId: string, body: string) => void; }) { const [isReplying, setIsReplying] = useState(false); const [editingId, setEditingId] = useState(null); const replyRef = useRef(null); const editRef = useRef(null); useEffect(() => { if (isReplying) replyRef.current?.focus(); }, [isReplying]); useEffect(() => { if (editingId) editRef.current?.focus(); }, [editingId]); const isEditingRoot = editingId === comment.id; return (
{/* Root comment */}
{comment.author} {formatTime(comment.createdAt)} {comment.resolved && ( Resolved )}
{onEdit && comment.author !== "agent" && !comment.resolved && ( )} {onReply && !comment.resolved && ( )} {comment.resolved ? ( ) : ( )}
{isEditingRoot ? ( { onEdit!(comment.id, body); setEditingId(null); }} onCancel={() => setEditingId(null)} placeholder="Edit comment..." submitLabel="Save" /> ) : (

{comment.body}

)}
{/* Replies */} {replies.length > 0 && (
{replies.map((reply) => (
{reply.author} {formatTime(reply.createdAt)}
{onEdit && reply.author !== "agent" && !comment.resolved && editingId !== reply.id && ( )}
{editingId === reply.id ? ( { onEdit!(reply.id, body); setEditingId(null); }} onCancel={() => setEditingId(null)} placeholder="Edit reply..." submitLabel="Save" /> ) : (

{reply.body}

)}
))}
)} {/* Reply form */} {isReplying && onReply && (
{ onReply(comment.id, body); setIsReplying(false); }} onCancel={() => setIsReplying(false)} placeholder="Write a reply..." submitLabel="Reply" />
)}
); } function formatTime(iso: string): string { const d = new Date(iso); return d.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit" }); }