TrendingStocks.tsx 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // D2 트렌딩 위젯 — "지금 뜨는 종목" (글수·언급량 랭킹). SSR 프레젠테이션.
  2. // 서버 컴포넌트: rows prop 을 상위(page)에서 fetchTrendingStocks 로 주입.
  3. import '@/app/styles/community.scss';
  4. import Link from 'next/link';
  5. import { TrendingUp } from 'lucide-react';
  6. import { changeDirection, changeSymbol, formatNumber } from '@/lib/utils/stock';
  7. import { TrendingStockRow } from '@/types/community';
  8. interface Props {
  9. rows: TrendingStockRow[];
  10. limit?: number;
  11. }
  12. export default function TrendingStocks({ rows, limit = 10 }: Props)
  13. {
  14. const list = rows.slice(0, limit);
  15. return (
  16. <div className='trending-widget'>
  17. <div className='trending-widget__title'>
  18. <TrendingUp size={16} strokeWidth={2} aria-hidden='true' />
  19. 지금 뜨는 종목
  20. </div>
  21. {list.length === 0 ? (
  22. <p className='trending-widget__empty'>집계된 종목이 없습니다.</p>
  23. ) : (
  24. <ul className='trending-widget__list'>
  25. {list.map(row => {
  26. const dir = changeDirection(row.changeRate);
  27. return (
  28. <li key={row.stockCode}>
  29. <Link href={`/stock/${row.stockCode}?tab=discussion`} className='trending-widget__item'>
  30. <span className='trending-widget__rank'>{row.rank}</span>
  31. <span className='trending-widget__name'>{row.stockName ?? row.stockCode}</span>
  32. {row.closePrice !== null && (
  33. <span className={`trending-widget__price stock-change stock-change--${dir}`}>
  34. <span aria-hidden='true'>{changeSymbol(dir)}</span> {formatNumber(row.closePrice)}
  35. </span>
  36. )}
  37. <span className='trending-widget__posts'>글 {row.posts.toLocaleString()}</span>
  38. </Link>
  39. </li>
  40. );
  41. })}
  42. </ul>
  43. )}
  44. </div>
  45. );
  46. }