66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { loadPaperLedger, type PaperLedgerEntryDto } from '../../utils/backendApi';
|
|
import { fmtKrw } from '../TradeOrderPanel';
|
|
|
|
const ENTRY_LABELS: Record<string, string> = {
|
|
INITIAL: '초기 예탁',
|
|
BUY_SETTLE: '매수 결제',
|
|
SELL_SETTLE: '매도 입금',
|
|
RESET: '계좌 초기화',
|
|
FEE: '수수료',
|
|
ADJUST: '조정',
|
|
};
|
|
|
|
interface Props {
|
|
refreshKey?: number;
|
|
}
|
|
|
|
const PaperLedgerTab: React.FC<Props> = ({ refreshKey = 0 }) => {
|
|
const [entries, setEntries] = useState<PaperLedgerEntryDto[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
if (entries.length === 0) setLoading(true);
|
|
void loadPaperLedger({ page: 0, size: 50 }).then(page => {
|
|
if (!cancelled) {
|
|
setEntries(page.content);
|
|
setLoading(false);
|
|
}
|
|
});
|
|
return () => { cancelled = true; };
|
|
// entries.length: 최초 로드만 스피너 — 갱신 시 목록 유지(깜빡임 방지)
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [refreshKey]);
|
|
|
|
if (loading) return <p className="ptd-muted">원장 로딩…</p>;
|
|
if (!entries.length) return <p className="ptd-muted">자금 변동 내역이 없습니다.</p>;
|
|
|
|
return (
|
|
<table className="ptd-table ptd-table--compact">
|
|
<thead>
|
|
<tr>
|
|
<th>시각</th>
|
|
<th>유형</th>
|
|
<th>금액</th>
|
|
<th>예수금</th>
|
|
<th>종목</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{entries.map(e => (
|
|
<tr key={e.id}>
|
|
<td className="ptd-time">{e.createdAt?.slice(5, 16).replace('T', ' ') ?? '—'}</td>
|
|
<td>{ENTRY_LABELS[e.entryType] ?? e.entryType}</td>
|
|
<td className={e.amount >= 0 ? 'up' : 'down'}>{e.amount >= 0 ? '+' : ''}{fmtKrw(e.amount)}</td>
|
|
<td>{fmtKrw(e.cashAfter)}</td>
|
|
<td>{e.symbol?.replace(/^KRW-/, '') ?? '—'}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
);
|
|
};
|
|
|
|
export default PaperLedgerTab;
|