StockTrade 컴포넌트 훅 분리 (Phase 4): 2,788→1,932줄
8개 커스텀 훅으로 state/handler 로직 추출: - usePortfolio: 포트폴리오 CRUD, 예수금, 브로커 그룹 - useSellHistory: 매도 내역 CRUD, 드로어/폼 상태 - useAiCoach: AI 코치 분석 + 캐시 - useAssetHistory: 자산 추이 차트 데이터 - useMarketContext: VIX/F&G/국채/WTI 시장 데이터 - useAiBalance: AI 모의투자 잔고, 수동 주문 - useReportData: 리포트 정렬, 차트, 집중도 분석 - useAdvisor: 어드바이저 프롬프트 빌더 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
66
src/pages/stock/hooks/useAssetHistory.js
Normal file
66
src/pages/stock/hooks/useAssetHistory.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { getAssetHistory, saveAssetSnapshot } from '../../../api';
|
||||
|
||||
export default function useAssetHistory() {
|
||||
const [assetHistory, setAssetHistory] = useState(null);
|
||||
const [assetHistoryLoading, setAssetHistoryLoading] = useState(false);
|
||||
const [assetHistoryDays, setAssetHistoryDays] = useState(30);
|
||||
const [snapshotSaving, setSnapshotSaving] = useState(false);
|
||||
|
||||
const loadAssetHistory = useCallback(async (days) => {
|
||||
setAssetHistoryLoading(true);
|
||||
try {
|
||||
const data = await getAssetHistory(days);
|
||||
const raw = data?.snapshots ?? data?.history ?? (Array.isArray(data) ? data : []);
|
||||
const byDate = {};
|
||||
for (const item of raw) byDate[item.date] = item.total_assets ?? 0;
|
||||
|
||||
const toLocalDate = (d) => {
|
||||
const y = d.getFullYear();
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${y}-${m}-${day}`;
|
||||
};
|
||||
|
||||
let filled;
|
||||
if (days > 0) {
|
||||
const today = new Date();
|
||||
filled = Array.from({ length: days }, (_, i) => {
|
||||
const d = new Date(today);
|
||||
d.setDate(today.getDate() - (days - 1 - i));
|
||||
const dateStr = toLocalDate(d);
|
||||
const val = byDate[dateStr];
|
||||
return val > 0 ? { date: dateStr, total_assets: val } : null;
|
||||
}).filter(Boolean);
|
||||
} else {
|
||||
filled = Object.entries(byDate)
|
||||
.filter(([, v]) => v > 0)
|
||||
.map(([date, total_assets]) => ({ date, total_assets }))
|
||||
.sort((a, b) => a.date.localeCompare(b.date));
|
||||
}
|
||||
setAssetHistory(filled);
|
||||
} catch {
|
||||
setAssetHistory([]);
|
||||
} finally {
|
||||
setAssetHistoryLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleSaveSnapshot = async (totalAssets, days) => {
|
||||
setSnapshotSaving(true);
|
||||
try {
|
||||
await saveAssetSnapshot(totalAssets != null ? Number(totalAssets) : undefined);
|
||||
await loadAssetHistory(days);
|
||||
} catch (err) {
|
||||
alert('스냅샷 저장 실패: ' + (err?.message ?? String(err)));
|
||||
} finally {
|
||||
setSnapshotSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
assetHistory, assetHistoryLoading,
|
||||
assetHistoryDays, setAssetHistoryDays,
|
||||
snapshotSaving, loadAssetHistory, handleSaveSnapshot,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user