/** * CommentList Component * Feature: personal-user-enhancements * * Displays a list of comments with virtualization for long lists */ import React, { useMemo } from 'react'; import { Empty, Divider, Spin } from 'antd'; import { FixedSizeList as List } from 'react-window'; import CommentItem from './CommentItem'; export interface CommentListProps { /** Array of comments to display */ comments: API.Comment[]; /** Loading state */ loading?: boolean; /** Callback when comment is edited */ onEdit?: (id: string, text: string) => void | Promise; /** Callback when comment is deleted */ onDelete?: (id: string) => void | Promise; /** Loading state for edit operation */ editLoading?: boolean; /** Loading state for delete operation */ deleteLoading?: boolean; /** Enable virtualization (default: true for >20 comments) */ enableVirtualization?: boolean; /** Height of the list container (for virtualization) */ height?: number; /** Item height estimate (for virtualization) */ itemHeight?: number; } const VIRTUALIZATION_THRESHOLD = 20; const DEFAULT_ITEM_HEIGHT = 100; const DEFAULT_LIST_HEIGHT = 600; const CommentList: React.FC = ({ comments, loading = false, onEdit, onDelete, editLoading = false, deleteLoading = false, enableVirtualization, height = DEFAULT_LIST_HEIGHT, itemHeight = DEFAULT_ITEM_HEIGHT, }) => { // Sort comments chronologically (oldest first) const sortedComments = useMemo(() => { if (!comments || !Array.isArray(comments)) { return []; } return [...comments].sort((a, b) => { return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(); }); }, [comments]); // Determine if virtualization should be used const shouldVirtualize = useMemo(() => { if (enableVirtualization !== undefined) { return enableVirtualization; } return sortedComments.length > VIRTUALIZATION_THRESHOLD; }, [enableVirtualization, sortedComments.length]); // Show loading state if (loading) { return (
); } // Show empty state if (sortedComments.length === 0) { return ( ); } // Render a single comment item const renderCommentItem = (comment: API.Comment, index: number) => (
{index < sortedComments.length - 1 && }
); // Render with virtualization for long lists if (shouldVirtualize) { const Row = ({ index, style }: { index: number; style: React.CSSProperties }) => { const comment = sortedComments[index]; return (
{renderCommentItem(comment, index)}
); }; return ( {Row} ); } // Render without virtualization for short lists return (
{sortedComments.map((comment, index) => renderCommentItem(comment, index))}
); }; export default CommentList;