PaperLeaderboardMini.tsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. 'use client';
  2. import { useEffect, useState } from 'react';
  3. import Link from 'next/link';
  4. import { cn, fetchApi } from '@/lib/utils/client';
  5. import { formatBpPercent, bpDirection } from '@/lib/utils/paper';
  6. import type { PaperLeaderboardResponse, PaperLeaderboardRow } from '@/types/paper';
  7. // 홈 리더보드 Top10 미니 — 수익률·전체 기준
  8. export default function PaperLeaderboardMini()
  9. {
  10. const [rows, setRows] = useState<PaperLeaderboardRow[]>([]);
  11. const [loading, setLoading] = useState(true);
  12. useEffect(() => {
  13. let cancelled = false;
  14. (async () => {
  15. const res = await fetchApi<PaperLeaderboardResponse>('/api/paper/leaderboard?sort=return&period=all&page=1', { silent: true });
  16. if (cancelled) {
  17. return;
  18. }
  19. setRows(res.success ? (res.data?.rows ?? []).slice(0, 10) : []);
  20. setLoading(false);
  21. })();
  22. return () => {
  23. cancelled = true;
  24. };
  25. }, []);
  26. return (
  27. <section className='paper__section'>
  28. <div className='paper__section-head'>
  29. <h2 className='paper__section-title'>리더보드 Top 10</h2>
  30. <Link href='/paper/leaderboard' className='paper__section-link'>전체 보기</Link>
  31. </div>
  32. {loading ? (
  33. <div className='paper__empty'>불러오는 중...</div>
  34. ) : rows.length === 0 ? (
  35. <div className='paper__empty'>아직 등재된 참여자가 없습니다.</div>
  36. ) : (
  37. <div className='paper__table-wrap'>
  38. <table className='paper__table'>
  39. <thead>
  40. <tr>
  41. <th className='paper__th--center'>순위</th>
  42. <th className='paper__th--left'>닉네임</th>
  43. <th>수익률</th>
  44. </tr>
  45. </thead>
  46. <tbody>
  47. {rows.map(row => {
  48. const dir = bpDirection(row.returnBp);
  49. return (
  50. <tr key={row.memberSID}>
  51. <td className='paper__td--center paper__rank'>{row.rank}</td>
  52. <td className='paper__td--left'>
  53. <Link href={`/user/${row.memberSID}/paper`} className='paper__nick-name'>
  54. {row.nickname || '익명'}
  55. </Link>
  56. </td>
  57. <td className={cn(`paper__value--${dir}`)}>{formatBpPercent(row.returnBp)}</td>
  58. </tr>
  59. );
  60. })}
  61. </tbody>
  62. </table>
  63. </div>
  64. )}
  65. </section>
  66. );
  67. }