-
-
-
{commentCount} comments
+
+
+
+
+ {commentCount} comments
+
+ {isPending && (
+
+ syncing…
+
+ )}
+
- {isPending && (
-
- syncing…
-
- )}
-
-
+
diff --git a/src/components/PostDetail.tsx b/src/components/PostDetail.tsx
index ed4de00..a6d78c0 100644
--- a/src/components/PostDetail.tsx
+++ b/src/components/PostDetail.tsx
@@ -6,6 +6,7 @@ import {
useForumActions,
usePermissions,
useUserVotes,
+ usePostBookmark,
} from '@/hooks';
import { Button } from '@/components/ui/button';
import { Textarea } from '@/components/ui/textarea';
@@ -17,33 +18,14 @@ import {
MessageCircle,
Send,
Loader2,
- Shield,
- UserX,
} from 'lucide-react';
import { formatDistanceToNow } from 'date-fns';
import { RelevanceIndicator } from './ui/relevance-indicator';
import { AuthorDisplay } from './ui/author-display';
+import { BookmarkButton } from './ui/bookmark-button';
+import CommentCard from './CommentCard';
import { usePending, usePendingVote } from '@/hooks/usePending';
-import {
- Tooltip,
- TooltipContent,
- TooltipTrigger,
-} from '@/components/ui/tooltip';
-
-// Extracted child component to respect Rules of Hooks
-const PendingBadge: React.FC<{ id: string }> = ({ id }) => {
- const { isPending } = usePending(id);
- if (!isPending) return null;
- return (
- <>
-
•
-
- syncing…
-
- >
- );
-};
const PostDetail = () => {
const { postId } = useParams<{ postId: string }>();
@@ -55,7 +37,6 @@ const PostDetail = () => {
const {
createComment,
votePost,
- voteComment,
moderateComment,
moderateUser,
isCreatingComment,
@@ -63,6 +44,11 @@ const PostDetail = () => {
} = useForumActions();
const { canVote, canComment, canModerate } = usePermissions();
const userVotes = useUserVotes();
+ const {
+ isBookmarked,
+ loading: bookmarkLoading,
+ toggleBookmark,
+ } = usePostBookmark(post!, post?.cellId);
// ✅ Move ALL hook calls to the top, before any conditional logic
const postPending = usePending(post?.id);
@@ -118,9 +104,12 @@ const PostDetail = () => {
await votePost(post.id, isUpvote);
};
- const handleVoteComment = async (commentId: string, isUpvote: boolean) => {
- // ✅ Permission checking handled in hook
- await voteComment(commentId, isUpvote);
+ const handleBookmark = async (e?: React.MouseEvent) => {
+ if (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ await toggleBookmark();
};
// ✅ Get vote status from hooks
@@ -128,10 +117,6 @@ const PostDetail = () => {
const isPostUpvoted = postVoteType === 'upvote';
const isPostDownvoted = postVoteType === 'downvote';
- const getCommentVoteType = (commentId: string) => {
- return userVotes.getCommentVoteType(commentId);
- };
-
const handleModerateComment = async (commentId: string) => {
const reason =
window.prompt('Enter a reason for moderation (optional):') || undefined;
@@ -239,7 +224,17 @@ const PostDetail = () => {
)}
-