'use client'; import { useState } from 'react'; import { Comment } from '@/lib/api'; import { Avatar } from '@/components/ui/avatar'; import { Button } from '@/components/ui/button'; interface Props { comments: Comment[]; currentUserId: string; currentUserRole?: string; isProjectAdmin: boolean; currentTime: number; pendingAnnotation: unknown; onAddComment: (data: { content: string; timestamp?: number; annotation?: unknown; parentId?: string }) => Promise; onResolve: (commentId: string, action: 'approve' | 'reject') => Promise; onRequestResolve: (commentId: string) => Promise; onDelete: (commentId: string) => Promise; onCommentClick: (comment: Comment) => void; } export function CommentPanel({ comments, currentUserId, currentUserRole, isProjectAdmin, currentTime, pendingAnnotation, onAddComment, onResolve, onRequestResolve, onDelete, onCommentClick, }: Props) { const [newComment, setNewComment] = useState(''); const [submitting, setSubmitting] = useState(false); const [replyTo, setReplyTo] = useState(null); const [replyText, setReplyText] = useState(''); const [showResolved, setShowResolved] = useState(false); const canComment: boolean | undefined = !!(currentUserRole && currentUserRole !== 'VIEWER'); const visibleComments = comments.filter(c => c.resolveStatus !== 'RESOLVED' || showResolved); const timestampedComments = visibleComments.filter(c => c.timestamp != null); const generalComments = visibleComments.filter(c => c.timestamp == null); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!newComment.trim()) return; setSubmitting(true); try { await onAddComment({ content: newComment.trim(), timestamp: currentTime > 0 ? currentTime : undefined, annotation: pendingAnnotation ?? undefined, }); setNewComment(''); } finally { setSubmitting(false); } }; const handleReply = async (e: React.FormEvent) => { e.preventDefault(); if (!replyText.trim() || !replyTo) return; setSubmitting(true); try { await onAddComment({ content: replyText.trim(), parentId: replyTo.id, }); setReplyText(''); setReplyTo(null); } finally { setSubmitting(false); } }; const openCount = comments.filter(c => c.resolveStatus !== 'RESOLVED').length; const pendingCount = comments.filter(c => c.resolveStatus === 'PENDING_APPROVAL').length; return (
{/* Header */}

Comments {openCount} open {pendingCount > 0 && ({pendingCount} pending)}

{/* Comment list */}
{visibleComments.length === 0 && (

No comments yet

Be the first to leave feedback

)} {/* Timestamped comments */} {timestampedComments.length > 0 && (
Timeline
{timestampedComments.map(comment => ( setReplyTo(comment)} onResolve={(action) => onResolve(comment.id, action)} onRequestResolve={() => onRequestResolve(comment.id)} onDelete={() => onDelete(comment.id)} onTimestampClick={() => onCommentClick(comment)} /> ))}
)} {/* General comments */} {generalComments.length > 0 && (
General
{generalComments.map(comment => ( setReplyTo(comment)} onResolve={(action) => onResolve(comment.id, action)} onRequestResolve={() => onRequestResolve(comment.id)} onDelete={() => onDelete(comment.id)} /> ))}
)}
{/* Reply form */} {replyTo && (

Replying to {replyTo.user?.name ?? 'Unknown'}