refactor(community): extract comment store and post/comment API adapters
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
"use client"
|
||||
|
||||
import { MessageCircle } from "lucide-react"
|
||||
import { useCommentStore } from "@/store/comments"
|
||||
|
||||
interface PostCommentCountProps {
|
||||
postId: string
|
||||
}
|
||||
|
||||
export function PostCommentCount({ postId }: PostCommentCountProps) {
|
||||
const count = useCommentStore(
|
||||
(state) => state.comments.filter((comment) => comment.postId === postId).length,
|
||||
)
|
||||
|
||||
return (
|
||||
<span className="flex items-center gap-1">
|
||||
<MessageCircle className="h-4 w-4" />
|
||||
{count}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -1,25 +1,26 @@
|
||||
"use client"
|
||||
|
||||
import { Heart } from "lucide-react"
|
||||
import { useState } from "react"
|
||||
import { generateId } from "@/lib/id"
|
||||
import type { Comment } from "@/lib/types"
|
||||
import { useMemo, useState } from "react"
|
||||
import { addComment, toggleCommentLike } from "@/lib/api/comments"
|
||||
import { useRequireAuth } from "@/lib/use-require-auth"
|
||||
import { useAuthStore } from "@/store/auth"
|
||||
import { useCommentStore } from "@/store/comments"
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar"
|
||||
import { Button } from "./ui/button"
|
||||
import { Textarea } from "./ui/textarea"
|
||||
|
||||
interface PostCommentsProps {
|
||||
initialComments: Comment[]
|
||||
postId: string
|
||||
}
|
||||
|
||||
export function PostComments({ initialComments, postId }: PostCommentsProps) {
|
||||
const [comments, setComments] = useState(initialComments)
|
||||
export function PostComments({ postId }: PostCommentsProps) {
|
||||
const allComments = useCommentStore((state) => state.comments)
|
||||
const comments = useMemo(
|
||||
() => allComments.filter((comment) => comment.postId === postId),
|
||||
[allComments, postId],
|
||||
)
|
||||
const [content, setContent] = useState("")
|
||||
const { requireAuth } = useRequireAuth()
|
||||
const user = useAuthStore((s) => s.user)
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
@@ -32,20 +33,8 @@ export function PostComments({ initialComments, postId }: PostCommentsProps) {
|
||||
requireAuth(() => {
|
||||
const nextContent = content.trim()
|
||||
if (!nextContent) return
|
||||
if (!user) return
|
||||
const createdAt = new Date().toISOString()
|
||||
setComments((prev) => [
|
||||
...prev,
|
||||
{
|
||||
id: generateId(`comment-${postId}`),
|
||||
postId,
|
||||
author: user,
|
||||
content: nextContent,
|
||||
likeCount: 0,
|
||||
liked: false,
|
||||
createdAt,
|
||||
},
|
||||
])
|
||||
const decision = addComment(postId, nextContent)
|
||||
if (!decision.ok) return
|
||||
setContent("")
|
||||
})
|
||||
}}
|
||||
@@ -85,19 +74,7 @@ export function PostComments({ initialComments, postId }: PostCommentsProps) {
|
||||
className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground mt-1 transition-colors"
|
||||
onClick={() =>
|
||||
requireAuth(() => {
|
||||
setComments((prev) =>
|
||||
prev.map((item) => {
|
||||
if (item.id !== comment.id) return item
|
||||
const nextLiked = !item.liked
|
||||
return {
|
||||
...item,
|
||||
liked: nextLiked,
|
||||
likeCount: nextLiked
|
||||
? item.likeCount + 1
|
||||
: Math.max(0, item.likeCount - 1),
|
||||
}
|
||||
}),
|
||||
)
|
||||
toggleCommentLike(comment.id)
|
||||
})
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
"use client"
|
||||
|
||||
import { Heart } from "lucide-react"
|
||||
import { useState } from "react"
|
||||
import { togglePostLike } from "@/lib/api/posts"
|
||||
import { useRequireAuth } from "@/lib/use-require-auth"
|
||||
import { usePostStore } from "@/store/posts"
|
||||
|
||||
interface PostLikeButtonProps {
|
||||
initialLiked: boolean
|
||||
initialCount: number
|
||||
postId: string
|
||||
}
|
||||
|
||||
export function PostLikeButton({ initialLiked, initialCount }: PostLikeButtonProps) {
|
||||
export function PostLikeButton({ postId }: PostLikeButtonProps) {
|
||||
const { requireAuth } = useRequireAuth()
|
||||
const [liked, setLiked] = useState(initialLiked)
|
||||
const [count, setCount] = useState(initialCount)
|
||||
const post = usePostStore((state) => state.posts.find((item) => item.id === postId))
|
||||
|
||||
if (!post) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
@@ -20,16 +23,12 @@ export function PostLikeButton({ initialLiked, initialCount }: PostLikeButtonPro
|
||||
className="flex items-center gap-1 hover:text-foreground transition-colors"
|
||||
onClick={() =>
|
||||
requireAuth(() => {
|
||||
setLiked((prevLiked) => {
|
||||
const nextLiked = !prevLiked
|
||||
setCount((prevCount) => (nextLiked ? prevCount + 1 : Math.max(0, prevCount - 1)))
|
||||
return nextLiked
|
||||
})
|
||||
togglePostLike(postId)
|
||||
})
|
||||
}
|
||||
>
|
||||
<Heart className={`h-4 w-4 ${liked ? "fill-red-500 text-red-500" : ""}`} />
|
||||
{count}
|
||||
<Heart className={`h-4 w-4 ${post.liked ? "fill-red-500 text-red-500" : ""}`} />
|
||||
{post.likeCount}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user