import React, { useState } from 'react';
import { Link, useParams, useNavigate } from 'react-router-dom';
import { useForum } from '@/contexts/useForum';
import { useAuth } from '@/contexts/useAuth';
import { Button } from '@/components/ui/button';
import { Textarea } from '@/components/ui/textarea';
import {
ArrowLeft,
ArrowUp,
ArrowDown,
Clock,
MessageCircle,
Send,
Eye,
Loader2,
} from 'lucide-react';
import { formatDistanceToNow } from 'date-fns';
import { Comment } from '@/types/forum';
import { CypherImage } from './ui/CypherImage';
import { RelevanceIndicator } from './ui/relevance-indicator';
import { AuthorDisplay } from './ui/author-display';
const PostDetail = () => {
const { postId } = useParams<{ postId: string }>();
const navigate = useNavigate();
const {
posts,
getCommentsByPost,
createComment,
votePost,
voteComment,
getCellById,
isInitialLoading,
isPostingComment,
isVoting,
moderateComment,
moderateUser,
} = useForum();
const { currentUser, verificationStatus } = useAuth();
const [newComment, setNewComment] = useState('');
if (!postId) return
Invalid post ID
;
if (isInitialLoading) {
return (
);
}
const post = posts.find(p => p.id === postId);
if (!post) {
return (
Post not found
The post you're looking for doesn't exist or has been removed.
);
}
const cell = getCellById(post.cellId);
const postComments = getCommentsByPost(post.id);
const isCellAdmin =
currentUser && cell && currentUser.address === cell.signature;
const visibleComments = isCellAdmin
? postComments
: postComments.filter(comment => !comment.moderated);
const handleCreateComment = async (e: React.FormEvent) => {
e.preventDefault();
if (!newComment.trim()) return;
try {
const result = await createComment(postId, newComment);
if (result) {
setNewComment('');
}
} catch (error) {
console.error('Error creating comment:', error);
}
};
const handleVotePost = async (isUpvote: boolean) => {
if (
verificationStatus !== 'verified-owner' &&
verificationStatus !== 'verified-basic' &&
!currentUser?.ensDetails &&
!currentUser?.ordinalDetails
)
return;
await votePost(post.id, isUpvote);
};
const handleVoteComment = async (commentId: string, isUpvote: boolean) => {
if (
verificationStatus !== 'verified-owner' &&
verificationStatus !== 'verified-basic' &&
!currentUser?.ensDetails &&
!currentUser?.ordinalDetails
)
return;
await voteComment(commentId, isUpvote);
};
const isPostUpvoted =
currentUser &&
post.upvotes.some(vote => vote.author === currentUser.address);
const isPostDownvoted =
currentUser &&
post.downvotes.some(vote => vote.author === currentUser.address);
const isCommentVoted = (comment: Comment, isUpvote: boolean) => {
if (!currentUser) return false;
const votes = isUpvote ? comment.upvotes : comment.downvotes;
return votes.some(vote => vote.author === currentUser.address);
};
const getIdentityImageUrl = (address: string) => {
return `https://api.dicebear.com/7.x/identicon/svg?seed=${address}`;
};
const handleModerateComment = async (commentId: string) => {
const reason =
window.prompt('Enter a reason for moderation (optional):') || undefined;
if (!cell) return;
await moderateComment(cell.id, commentId, reason, cell.signature);
};
const handleModerateUser = async (userAddress: string) => {
if (!cell) return;
const reason =
window.prompt('Reason for moderating this user? (optional)') || undefined;
await moderateUser(cell.id, userAddress, reason, cell.signature);
};
return (
{post.upvotes.length - post.downvotes.length}
{post.title}
{post.content}
{formatDistanceToNow(post.timestamp, { addSuffix: true })}
{postComments.length}{' '}
{postComments.length === 1 ? 'comment' : 'comments'}
{post.relevanceScore !== undefined && (
)}
{verificationStatus === 'verified-owner' ||
verificationStatus === 'verified-basic' ||
currentUser?.ensDetails ||
currentUser?.ordinalDetails ? (
) : verificationStatus === 'verified-none' ? (
Read-Only Mode
Your wallet has been verified but does not contain any Ordinal
Operators. You can browse threads but cannot comment or vote.
) : (
Connect wallet and verify ownership to comment
)}
{postComments.length === 0 ? (
) : (
visibleComments.map(comment => (
))
)}
);
};
export default PostDetail;