"use client" import { useState, useCallback, useEffect } from "react" import Link from "next/link" import { MessageSquareIcon, Loader2 } from "lucide-react" import { useSession } from "@/lib/auth-client" import { TiptapEditor } from "@/components/tiptap-editor" import { CommentItem, CommentData } from "./comment-item" interface CommentSectionProps { gameId: string initialCount: number } interface CommentsApiResponse { data: CommentData[] total: number limit: number offset: number } export function CommentSection({ gameId, initialCount }: CommentSectionProps) { const { data: session } = useSession() const [comments, setComments] = useState([]) const [total, setTotal] = useState(initialCount) const [offset, setOffset] = useState(0) const [loading, setLoading] = useState(true) const [commentContent, setCommentContent] = useState | null>(null) const [submitting, setSubmitting] = useState(false) const limit = 20 // Initial load useEffect(() => { let cancelled = false async function fetchInitial() { setLoading(true) try { const res = await fetch( `/api/games/${gameId}/comments?limit=${limit}&offset=0`, ) if (!cancelled && res.ok) { const json = (await res.json()) as CommentsApiResponse setComments(json.data) setTotal(json.total) } } catch (err) { console.error("Failed to load comments:", err) } finally { if (!cancelled) setLoading(false) } } fetchInitial() return () => { cancelled = true } }, [gameId]) const refreshComments = useCallback(async () => { try { const res = await fetch( `/api/games/${gameId}/comments?limit=${limit}&offset=0`, ) if (res.ok) { const json = (await res.json()) as CommentsApiResponse setComments(json.data) setTotal(json.total) } } catch (err) { console.error("Failed to refresh comments:", err) } }, [gameId]) const handleSubmit = useCallback(async () => { if (!commentContent || !session) return setSubmitting(true) try { const res = await fetch(`/api/games/${gameId}/comments`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: commentContent }), }) if (res.ok) { setCommentContent(null) await refreshComments() } } catch (err) { console.error("Failed to post comment:", err) } finally { setSubmitting(false) } }, [commentContent, session, gameId, refreshComments]) const handleLoadMore = useCallback(async () => { const newOffset = offset + limit setLoading(true) try { const res = await fetch( `/api/games/${gameId}/comments?limit=${limit}&offset=${newOffset}`, ) if (res.ok) { const json = (await res.json()) as CommentsApiResponse setComments((prev) => [...prev, ...json.data]) setTotal(json.total) setOffset(newOffset) } } catch (err) { console.error("Failed to load more comments:", err) } finally { setLoading(false) } }, [offset, gameId]) const handleReplyPosted = useCallback(() => { refreshComments() }, [refreshComments]) const hasMore = comments.length < total return (
{/* Header */}

Comments

({total})
{/* Compose */} {session ? (
setCommentContent(json)} />
) : (

Sign in {" "} to leave a comment

)} {/* Comment list */}
{loading && comments.length === 0 ? (
Loading comments...
) : comments.length === 0 ? (
No comments yet. Be the first to share your thoughts!
) : ( comments.map((comment) => ( )) )}
{/* Load more */} {hasMore && !loading && (
)} {loading && comments.length > 0 && (
)}
) }