kreativortex/components/CommentComponent.tsx
Jessica Rekcah 3a14660c6d update
2025-12-06 10:05:58 +07:00

206 lines
6.1 KiB
TypeScript

/**
* File: CommentComponent.tsx
* Created by: AI Assistant
* Date: 2025-12-05
* Purpose: Comment component with privacy controls for kreatiVortex platform
* Part of: kreatiVortex - Platform Pembelajaran Tari Online
*/
'use client';
import React, { useState } from 'react';
import { Button } from '@/components/ui/button';
import CommentForm from './CommentForm';
import AttachmentDisplay from './AttachmentDisplay';
import { authClient } from '@/lib/auth-client';
interface Comment {
id: string;
content: string;
isPrivate: boolean;
createdAt: string;
author: {
id: string;
user: {
name: string;
image?: string;
};
};
attachments: any[];
replies?: Comment[];
}
interface CommentComponentProps {
comment: Comment;
onReply: (content: string, attachments: any[], isPrivate?: boolean) => void;
onTogglePrivacy?: (commentId: string) => void;
postAuthorId?: string;
classEducatorId?: string;
level?: number;
}
export default function CommentComponent({
comment,
onReply,
onTogglePrivacy,
postAuthorId,
classEducatorId,
level = 0
}: CommentComponentProps) {
const [showReplyForm, setShowReplyForm] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [user, setUser] = useState<any>(null);
// Get current user
React.useEffect(() => {
const getCurrentUser = async () => {
try {
const session = await authClient.getSession();
setUser(session?.data?.user || null);
} catch (error) {
console.error('Error getting user session:', error);
}
};
getCurrentUser();
}, []);
const handleReply = async (content: string, attachments: any[]) => {
setIsSubmitting(true);
try {
onReply(content, attachments, comment.isPrivate); // Reply inherits privacy
setShowReplyForm(false);
} finally {
setIsSubmitting(false);
}
};
const handleTogglePrivacy = () => {
if (onTogglePrivacy) {
onTogglePrivacy(comment.id);
}
};
const canTogglePrivacy = user?.role === 'PENDIDIK' && user.id === classEducatorId;
const isPrivateComment = comment.isPrivate;
return (
<div className={`${level > 0 ? 'ml-8' : ''} mb-4`}>
{/* Comment Content */}
<div className={`
relative p-4 rounded-lg border transition-all
${isPrivateComment
? 'border-amber-300 bg-amber-50'
: 'border-gray-200 bg-white'
}
`}>
{/* Private Indicator */}
{isPrivateComment && (
<div className="absolute top-2 right-2 flex items-center space-x-1">
<svg className="w-4 h-4 text-amber-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
<span className="text-xs font-medium text-amber-600">Private</span>
</div>
)}
{/* Author Info */}
<div className="flex items-center space-x-3 mb-3">
<div className="w-8 h-8 bg-gold-500 rounded-full flex items-center justify-center">
{comment.author.user.image ? (
<img
src={comment.author.user.image}
alt={comment.author.user.name}
className="w-8 h-8 rounded-full object-cover"
/>
) : (
<span className="text-xs font-bold text-navy-900">
{comment.author.user.name.charAt(0).toUpperCase()}
</span>
)}
</div>
<div>
<p className="font-medium text-gray-900">{comment.author.user.name}</p>
<p className="text-xs text-gray-500">
{new Date(comment.createdAt).toLocaleString('id-ID')}
</p>
</div>
</div>
{/* Comment Text */}
<div className="mb-3">
<p className={`text-sm ${isPrivateComment ? 'text-amber-900' : 'text-gray-800'}`}>
{comment.content}
</p>
</div>
{/* Attachments */}
{comment.attachments && comment.attachments.length > 0 && (
<div className="mb-3">
<AttachmentDisplay attachments={comment.attachments} />
</div>
)}
{/* Actions */}
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<Button
variant="ghost"
size="sm"
onClick={() => setShowReplyForm(!showReplyForm)}
className="text-xs text-gray-500 hover:text-gray-700"
>
Balas
</Button>
</div>
{/* Privacy Toggle for Educators */}
{canTogglePrivacy && (
<Button
variant="ghost"
size="sm"
onClick={handleTogglePrivacy}
className={`
text-xs transition-colors
${isPrivateComment
? 'text-amber-600 hover:text-amber-700'
: 'text-gray-500 hover:text-gray-700'
}
`}
>
{isPrivateComment ? 'Jadikan Publik' : 'Jadikan Private'}
</Button>
)}
</div>
</div>
{/* Reply Form */}
{showReplyForm && (
<div className="mt-3 ml-4">
<CommentForm
onSubmit={handleReply}
placeholder="Tulis balasan..."
buttonText="Balas Komentar"
loading={isSubmitting}
/>
</div>
)}
{/* Replies */}
{comment.replies && comment.replies.length > 0 && (
<div className="mt-4 space-y-3">
{comment.replies.map((reply) => (
<CommentComponent
key={reply.id}
comment={reply}
onReply={onReply}
onTogglePrivacy={onTogglePrivacy}
postAuthorId={postAuthorId}
classEducatorId={classEducatorId}
level={level + 1}
/>
))}
</div>
)}
</div>
);
}