File size: 4,249 Bytes
42fcd29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import React, { useState } from 'react'
import { OHLCVPoint } from '../api/stockApi'

interface Props {
  data: OHLCVPoint[]
  rows?: number
}

function fmt(v: number | undefined): string {
  if (v == null) return '—'
  const abs = Math.abs(v)
  const sign = v < 0 ? '-' : '+'
  if (abs >= 1_000_000) return `${sign}${(abs / 1_000_000).toFixed(2)}M`
  if (abs >= 1_000) return `${sign}${(abs / 1_000).toFixed(0)}K`
  return `${sign}${Math.round(abs)}`
}

function cls(v: number | undefined): string {
  if (v == null || v === 0) return 'text-slate-400'
  return v > 0 ? 'text-green-400' : 'text-red-400'
}

export const InstitutionalFlowTable: React.FC<Props> = ({ data, rows = 20 }) => {
  const [expanded, setExpanded] = useState(false)
  const visible = expanded ? rows : 10
  const filtered = data
    .filter((d) => d.institutional_available)
    .slice(-rows)
    .reverse()
    .slice(0, visible)

  if (!filtered.length) return (
    <p className="text-slate-500 text-xs px-2 py-3">尚無三大法人資料(僅台股 TWSE/TPEx)</p>
  )

  return (
    <div className="overflow-x-auto">
      <table className="w-full text-xs border-collapse min-w-[640px]">
        <thead>
          <tr className="text-slate-400 border-b border-slate-700">
            <th className="text-left py-1.5 px-2 font-medium">日期</th>
            <th className="text-right py-1.5 px-2 font-medium text-blue-400">外資買</th>
            <th className="text-right py-1.5 px-2 font-medium text-blue-400">外資賣</th>
            <th className="text-right py-1.5 px-2 font-medium text-blue-300">外資淨</th>
            <th className="text-right py-1.5 px-2 font-medium text-yellow-400">投信買</th>
            <th className="text-right py-1.5 px-2 font-medium text-yellow-400">投信賣</th>
            <th className="text-right py-1.5 px-2 font-medium text-yellow-300">投信淨</th>
            <th className="text-right py-1.5 px-2 font-medium text-pink-400">自營買</th>
            <th className="text-right py-1.5 px-2 font-medium text-pink-400">自營賣</th>
            <th className="text-right py-1.5 px-2 font-medium text-pink-300">自營淨</th>
            <th className="text-right py-1.5 px-2 font-medium text-white">合計淨</th>
          </tr>
        </thead>
        <tbody>
          {filtered.map((d, i) => (
            <tr key={d.date} className={i % 2 === 0 ? 'bg-slate-900/40' : ''}>
              <td className="py-1 px-2 text-slate-300 whitespace-nowrap">
                {d.date}
                {d.institutional_carry_forward && (
                  <span className="ml-1 text-slate-600 text-[10px]"></span>
                )}
              </td>
              <td className={`py-1 px-2 text-right ${cls(d.foreign_buy)}`}>{fmt(d.foreign_buy)}</td>
              <td className={`py-1 px-2 text-right ${cls(-(d.foreign_sell ?? 0))}`}>{d.foreign_sell != null ? fmt(-d.foreign_sell) : '—'}</td>
              <td className={`py-1 px-2 text-right font-medium ${cls(d.foreign_net)}`}>{fmt(d.foreign_net)}</td>
              <td className={`py-1 px-2 text-right ${cls(d.trust_buy)}`}>{fmt(d.trust_buy)}</td>
              <td className={`py-1 px-2 text-right ${cls(-(d.trust_sell ?? 0))}`}>{d.trust_sell != null ? fmt(-d.trust_sell) : '—'}</td>
              <td className={`py-1 px-2 text-right font-medium ${cls(d.trust_net)}`}>{fmt(d.trust_net)}</td>
              <td className={`py-1 px-2 text-right ${cls(d.dealer_buy)}`}>{fmt(d.dealer_buy)}</td>
              <td className={`py-1 px-2 text-right ${cls(-(d.dealer_sell ?? 0))}`}>{d.dealer_sell != null ? fmt(-d.dealer_sell) : '—'}</td>
              <td className={`py-1 px-2 text-right font-medium ${cls(d.dealer_net)}`}>{fmt(d.dealer_net)}</td>
              <td className={`py-1 px-2 text-right font-bold ${cls(d.institutional_net)}`}>{fmt(d.institutional_net)}</td>
            </tr>
          ))}
        </tbody>
      </table>
      {filtered.length >= 10 && rows > 10 && (
        <button
          onClick={() => setExpanded(e => !e)}
          className="mt-2 text-xs text-slate-500 hover:text-slate-300 px-2"
        >
          {expanded ? '▲ 收合' : `▼ 顯示更多(最近 ${rows} 日)`}
        </button>
      )}
    </div>
  )
}