StockRow.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. 'use client';
  2. // D6 §5.1 — 종목행(StockRow) 열 구성 빌더 + StockDataTable 편의 래퍼.
  3. // 한 줄 완결: 종목명+코드 | 현재가 | 등락률(색+부호) | 시가총액 | 시장.
  4. // 거래량/시총 등 우선순위 낮은 열은 mobile drop (data-priority='low').
  5. import Link from 'next/link';
  6. import DataTable, { DataTableColumn } from '@/components/table/DataTable';
  7. import PriceChange from '@/components/table/PriceChange';
  8. import { StockListRow } from '@/types/stock';
  9. import { formatKrwCompact, formatNumber, tradingStatusLabel } from '@/lib/utils/stock';
  10. export function buildStockColumns(): DataTableColumn<StockListRow>[] {
  11. return [
  12. {
  13. key: 'name',
  14. header: '종목명',
  15. align: 'left',
  16. priority: 'high',
  17. cellClassName: 'data-table__cell--name',
  18. cell: (row) => {
  19. const status = tradingStatusLabel(row.tradingStatus);
  20. return (
  21. <Link href={`/stock/${row.code}`} className='stock-cell'>
  22. <span className='stock-cell__name'>{row.name}</span>
  23. <span className='stock-cell__code'>{row.code}</span>
  24. {status && (
  25. <span className={`stock-badge stock-badge--${row.tradingStatus.toLowerCase()}`}>{status}</span>
  26. )}
  27. </Link>
  28. );
  29. }
  30. },
  31. {
  32. key: 'price',
  33. header: <>현재가 <small>(전일종가)</small></>,
  34. align: 'right',
  35. priority: 'high',
  36. cell: (row) => formatNumber(row.closePrice)
  37. },
  38. {
  39. key: 'change',
  40. header: '등락률',
  41. align: 'right',
  42. priority: 'high',
  43. cell: (row) => <PriceChange rate={row.changeRate} />
  44. },
  45. {
  46. key: 'cap',
  47. header: '시가총액',
  48. align: 'right',
  49. priority: 'low',
  50. cell: (row) => formatKrwCompact(row.marketCap)
  51. },
  52. {
  53. key: 'market',
  54. header: '시장',
  55. align: 'center',
  56. priority: 'medium',
  57. cell: (row) => <span className={`stock-badge stock-badge--${row.market.toLowerCase()}`}>{row.market}</span>
  58. }
  59. ];
  60. }
  61. interface StockDataTableProps {
  62. rows: StockListRow[];
  63. caption?: string;
  64. emptyMessage?: string;
  65. }
  66. // 종목 목록 편의 래퍼 — 기본 열 구성으로 DataTable 렌더
  67. export default function StockDataTable({ rows, caption, emptyMessage }: StockDataTableProps)
  68. {
  69. return (
  70. <DataTable<StockListRow>
  71. caption={caption ?? '종목 목록 — 종목명, 현재가(전일 종가), 등락률, 시가총액, 시장'}
  72. columns={buildStockColumns()}
  73. rows={rows}
  74. rowKey={(row) => row.code}
  75. emptyMessage={emptyMessage}
  76. />
  77. );
  78. }