MacroTable.tsx 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. 'use client';
  2. import DataTable, { DataTableColumn, ColumnPriority } from '@/components/table/DataTable';
  3. import { MacroIndicator, MACRO_CODE_LABEL } from '@/types/macro';
  4. import { macroPeriodLabel, formatMacroValue } from '@/lib/utils/market';
  5. interface MacroTableRow {
  6. period: string;
  7. // 지표 코드 → 해당 시점 값 (미수록 시점은 null)
  8. values: Record<string, number|null>;
  9. }
  10. // 지표 열 우선순위 — 앞쪽 지표만 mobile 유지 (지표 6열 전부는 협소)
  11. function columnPriority(index: number): ColumnPriority {
  12. if (index < 2) {
  13. return 'high';
  14. }
  15. return index < 4 ? 'medium' : 'low';
  16. }
  17. function buildColumns(indicators: MacroIndicator[]): DataTableColumn<MacroTableRow>[] {
  18. const columns: DataTableColumn<MacroTableRow>[] = [
  19. {
  20. key: 'period',
  21. header: '시점',
  22. align: 'left',
  23. priority: 'high',
  24. cell: (row) => macroPeriodLabel(row.period)
  25. }
  26. ];
  27. indicators.forEach((indicator, index) => {
  28. const label = MACRO_CODE_LABEL[indicator.code] ?? indicator.name;
  29. columns.push({
  30. key: indicator.code,
  31. header: indicator.unit ? `${label} (${indicator.unit})` : label,
  32. align: 'right',
  33. priority: columnPriority(index),
  34. cell: (row) => formatMacroValue(row.values[indicator.code])
  35. });
  36. });
  37. return columns;
  38. }
  39. // 최근 N기간 매트릭스 — 행 = 시점(내림차순 = 최신 먼저), 열 = 지표
  40. export default function MacroTable({ indicators, maxRows = 12 }: { indicators: MacroIndicator[]; maxRows?: number })
  41. {
  42. const valueMaps = new Map<string, Map<string, number>>();
  43. const periods = new Set<string>();
  44. for (const indicator of indicators) {
  45. const map = new Map<string, number>();
  46. for (const point of indicator.points) {
  47. map.set(point.period, point.value);
  48. periods.add(point.period);
  49. }
  50. valueMaps.set(indicator.code, map);
  51. }
  52. const rows: MacroTableRow[] = [...periods]
  53. .sort((a, b) => b.localeCompare(a))
  54. .slice(0, maxRows)
  55. .map(period => ({
  56. period,
  57. values: Object.fromEntries(indicators.map(indicator => [indicator.code, valueMaps.get(indicator.code)?.get(period) ?? null]))
  58. }));
  59. return (
  60. <DataTable<MacroTableRow>
  61. caption='거시경제지표 최근 추이 — 시점별 고용률, 실업률, 취업자수, 소비자물가지수, 수출액, 수입액'
  62. columns={buildColumns(indicators)}
  63. rows={rows}
  64. rowKey={(row) => row.period}
  65. emptyMessage='표시할 거시지표 데이터가 없습니다.'
  66. />
  67. );
  68. }