'use client'; // D3 응원(Cheer) 섹션 — 글 상세 하단. 누적 응원 배지 + 최근 목록 + 응원 버튼(+모달). // 목록 조회는 익명 허용(GET). 발신은 로그인 필요 + 본인 글에는 버튼 숨김. import { useCallback, useEffect, useState } from 'react'; import { Heart } from 'lucide-react'; import { fetchApi, getDateTime } from '@/lib/utils/client'; import useAuth from '@/hooks/useAuth'; import type { CheerListResponse } from '@/types/reward'; import CheerModal from './CheerModal'; type Props = { postID: number; authorMemberID: number|null; }; export default function Cheer({ postID, authorMemberID }: Props) { const { member, loginCheck } = useAuth(); const [data, setData] = useState(null); const [open, setOpen] = useState(false); const [expanded, setExpanded] = useState(false); const isOwner = member?.id != null && member.id === authorMemberID; const load = useCallback(async () => { const res = await fetchApi(`/api/posts/${postID}/cheers?take=20`, { silent: true }); if (res.success && res.data) { setData(res.data); } }, [postID]); useEffect(() => { load(); }, [load]); const handleOpen = useCallback(() => { if (!loginCheck()) { return; } setOpen(true); }, [loginCheck]); const handleDone = useCallback(() => { setOpen(false); load(); }, [load]); const total = data?.totalAmount ?? 0; const count = data?.count ?? 0; const recent = data?.recent ?? []; const shown = expanded ? recent : recent.slice(0, 5); return (
응원 {count > 0 && ( {total.toLocaleString()} ({count.toLocaleString()}건) )}
{!isOwner && ( )}
{isOwner && count === 0 && (

내 글에는 응원할 수 없습니다.

)} {recent.length > 0 && (
    {shown.map((c) => (
  • {c.amount.toLocaleString()}
    {c.fromNickname ?? '익명'} {c.message && {c.message}}
    {getDateTime(c.createdAt)}
  • ))}
)} {recent.length > 5 && ( )} {open && ( setOpen(false)} onDone={handleDone} /> )}
); }