import React from 'react'; import { Link } from 'react-router-dom'; import { ArrowUp, ArrowDown, MessageSquare } from 'lucide-react'; import { formatDistanceToNow } from 'date-fns'; import { Post } from '@opchan/core'; // Removed unused imports import { RelevanceIndicator } from '@/components/ui/relevance-indicator'; import { AuthorDisplay } from '@/components/ui/author-display'; import { BookmarkButton } from '@/components/ui/bookmark-button'; import { LinkRenderer } from '@/components/ui/link-renderer'; import { useForum } from '@opchan/react'; import { ShareButton } from '@/components/ui/ShareButton'; interface PostCardProps { post: Post; commentCount?: number; } const PostCard: React.FC = ({ post, commentCount = 0 }) => { const forum = useForum(); const { content, permissions } = forum; // Get cell data from content const cell = content.cells.find(c => c.id === post.cellId); const cellName = cell?.name || 'unknown'; // Use pre-computed vote data const score = 'voteScore' in post ? (post.voteScore as number) : post.upvotes.length - post.downvotes.length; // Use library pending API const isPending = content.pending.isPending(post.id); const votePending = content.pending.isVotePending(post.id); // Get user vote status from post data const userUpvoted = (post as unknown as { userUpvoted?: boolean }).userUpvoted || false; const userDownvoted = (post as unknown as { userDownvoted?: boolean }).userDownvoted || false; // Check if bookmarked const isBookmarked = content.bookmarks.some( b => b.targetId === post.id && b.type === 'post' ); const [bookmarkLoading, setBookmarkLoading] = React.useState(false); // Remove duplicate vote status logic // ✅ Content truncation (simple presentation logic is OK) const contentPreview = post.content.length > 200 ? post.content.substring(0, 200) + '...' : post.content; const handleVote = async (e: React.MouseEvent, isUpvote: boolean) => { e.preventDefault(); await content.vote({ targetId: post.id, isUpvote }); }; const handleBookmark = async (e?: React.MouseEvent) => { if (e) { e.preventDefault(); e.stopPropagation(); } setBookmarkLoading(true); try { await content.togglePostBookmark(post, post.cellId); } finally { setBookmarkLoading(false); } }; return (
{/* Voting column */}
0 ? 'text-cyber-accent' : score < 0 ? 'text-blue-400' : 'text-cyber-neutral' }`} > {score} {votePending && ( syncing… )}
{/* Content column */}
{/* Post metadata */}
r/{cellName} Posted by u/ {formatDistanceToNow(new Date(post.timestamp), { addSuffix: true, })} {post.relevanceScore !== undefined && ( <> )}
{/* Post title and content - clickable to navigate to post */}

{post.title}

{/* Post content preview */}

{/* Post actions */}
{commentCount} comments
{isPending && ( syncing… )}
); }; export default PostCard;