BondsTable.tsx 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. 'use client';
  2. import Link from 'next/link';
  3. import DataTable, { DataTableColumn } from '@/components/table/DataTable';
  4. import { BondRow, BOND_MARKET_LABEL } from '@/types/market';
  5. import { formatNumber } from '@/lib/utils/stock';
  6. import { formatDecimal, formatRatePercent } from '@/lib/utils/market';
  7. // KRX 채권 Code 는 12자리 ISIN → 채권 상세 링크 대상
  8. function isIsin(code: string): boolean {
  9. return /^[A-Za-z0-9]{12}$/.test(code);
  10. }
  11. function buildColumns(): DataTableColumn<BondRow>[] {
  12. return [
  13. {
  14. key: 'name',
  15. header: '종목명',
  16. align: 'left',
  17. priority: 'high',
  18. cellClassName: 'data-table__cell--name',
  19. cell: (row) => (
  20. isIsin(row.code) ? (
  21. <Link href={`/market/bonds/${row.code}`} className='stock-cell'>
  22. <span className='stock-cell__name'>{row.name}</span>
  23. <span className='stock-cell__code'>{row.code}</span>
  24. </Link>
  25. ) : (
  26. <span className='stock-cell'>
  27. <span className='stock-cell__name'>{row.name}</span>
  28. <span className='stock-cell__code'>{row.code}</span>
  29. </span>
  30. )
  31. )
  32. },
  33. {
  34. key: 'market',
  35. header: '시장',
  36. align: 'center',
  37. priority: 'low',
  38. cell: (row) => <span className='market__cls-badge'>{BOND_MARKET_LABEL[row.market] ?? row.market}</span>
  39. },
  40. {
  41. key: 'close',
  42. header: '가격',
  43. align: 'right',
  44. priority: 'high',
  45. cell: (row) => formatDecimal(row.close)
  46. },
  47. {
  48. key: 'ytm',
  49. header: '수익률(YTM)',
  50. align: 'right',
  51. priority: 'high',
  52. cell: (row) => formatRatePercent(row.yieldToMaturity, 3)
  53. },
  54. {
  55. key: 'volume',
  56. header: '거래량',
  57. align: 'right',
  58. priority: 'medium',
  59. cell: (row) => formatNumber(row.volume)
  60. },
  61. {
  62. key: 'maturity',
  63. header: '만기',
  64. align: 'center',
  65. priority: 'low',
  66. cell: (row) => row.maturityYears || '—'
  67. }
  68. ];
  69. }
  70. export default function BondsTable({ rows }: { rows: BondRow[] })
  71. {
  72. return (
  73. <DataTable<BondRow>
  74. caption='채권 목록 — 종목명, 시장, 가격, 수익률, 거래량, 만기'
  75. columns={buildColumns()}
  76. rows={rows}
  77. rowKey={(row) => row.code}
  78. emptyMessage='표시할 채권이 없습니다.'
  79. />
  80. );
  81. }