- lottoUtils.jsx: 공통 유틸·상수 추출 (Ball, NumberRow, 통계 헬퍼 등) - hooks/useLottoData.js: 핵심 데이터 로드 (최신회차, 통계, 시뮬레이션, 리포트) - hooks/usePurchases.js: 구매 기록 CRUD - hooks/useManualRecommend.js: 수동 추천 + 히스토리 - components/: MetricBlock, FrequencyChart, PerformanceBanner, ConfidenceRing, CombinedRecommendPanel, ReportPanel, PersonalAnalysisPanel, PurchasePanel 분리 - getReport import 누락 버그 수정 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
163 lines
6.1 KiB
JavaScript
163 lines
6.1 KiB
JavaScript
import { useCallback, useEffect, useState } from 'react';
|
|
import {
|
|
getLatest, getStats, getBestPicks, getAnalysis,
|
|
getPerformanceStats, getLatestReport, getReportHistory, getReport,
|
|
getPersonalAnalysis, getCombinedRecommend, getCombinedHistory,
|
|
} from '../../../api';
|
|
import { readStatsCache, writeStatsCache } from '../lottoUtils';
|
|
|
|
export default function useLottoData() {
|
|
const [latest, setLatest] = useState(null);
|
|
const [stats, setStats] = useState(() => readStatsCache());
|
|
const [statsLoading, setStatsLoading] = useState(false);
|
|
const [statsError, setStatsError] = useState('');
|
|
const [loading, setLoading] = useState({
|
|
latest: false, bestPicks: false, analysis: false,
|
|
});
|
|
const [error, setError] = useState('');
|
|
const [bestPicks, setBestPicks] = useState([]);
|
|
const [bestPicksExpanded, setBestPicksExpanded] = useState(false);
|
|
const [analysis, setAnalysis] = useState(null);
|
|
const [simulating, setSimulating] = useState(false);
|
|
const [simResult, setSimResult] = useState(null);
|
|
|
|
// 종합 추론
|
|
const [combined, setCombined] = useState(null);
|
|
const [combinedLoading, setCombinedLoading] = useState(false);
|
|
const [combinedHistory, setCombinedHistory] = useState([]);
|
|
const [combinedHistLoading, setCombinedHistLoading] = useState(false);
|
|
|
|
// 신뢰도·리포트·개인분석
|
|
const [perfStats, setPerfStats] = useState(null);
|
|
const [report, setReport] = useState(null);
|
|
const [reportHistory, setReportHistory] = useState([]);
|
|
const [reportLoading, setReportLoading] = useState(false);
|
|
const [personalAnalysis, setPersonalAnalysis] = useState(null);
|
|
const [personalLoading, setPersonalLoading] = useState(false);
|
|
|
|
const refreshLatest = useCallback(async () => {
|
|
setLoading((s) => ({ ...s, latest: true }));
|
|
setError('');
|
|
try { setLatest(await getLatest()); }
|
|
catch (e) { setError(e?.message ?? String(e)); }
|
|
finally { setLoading((s) => ({ ...s, latest: false })); }
|
|
}, []);
|
|
|
|
const refreshStats = useCallback(async () => {
|
|
setStatsLoading(true); setStatsError('');
|
|
try {
|
|
const cached = readStatsCache();
|
|
if (cached && !stats) setStats(cached);
|
|
const data = await getStats();
|
|
if (!cached || cached.total_draws !== data?.total_draws) {
|
|
setStats(data); writeStatsCache(data);
|
|
}
|
|
} catch (e) { setStatsError(e?.message ?? String(e)); }
|
|
finally { setStatsLoading(false); }
|
|
}, [stats]);
|
|
|
|
const refreshBestPicks = useCallback(async () => {
|
|
setLoading((s) => ({ ...s, bestPicks: true }));
|
|
try { setBestPicks((await getBestPicks(20)).items ?? []); }
|
|
catch {}
|
|
finally { setLoading((s) => ({ ...s, bestPicks: false })); }
|
|
}, []);
|
|
|
|
const refreshAnalysis = useCallback(async () => {
|
|
setLoading((s) => ({ ...s, analysis: true }));
|
|
try { setAnalysis(await getAnalysis()); }
|
|
catch {}
|
|
finally { setLoading((s) => ({ ...s, analysis: false })); }
|
|
}, []);
|
|
|
|
const refreshPerfStats = useCallback(async () => {
|
|
try { setPerfStats(await getPerformanceStats()); } catch {}
|
|
}, []);
|
|
|
|
const refreshReport = useCallback(async () => {
|
|
setReportLoading(true);
|
|
try {
|
|
const [rep, hist] = await Promise.all([
|
|
getLatestReport(),
|
|
getReportHistory(10),
|
|
]);
|
|
setReport(rep);
|
|
setReportHistory(hist?.reports ?? []);
|
|
} catch {}
|
|
finally { setReportLoading(false); }
|
|
}, []);
|
|
|
|
const loadSpecificReport = useCallback(async (drwNo) => {
|
|
setReportLoading(true);
|
|
try { setReport(await getReport(drwNo)); }
|
|
catch {}
|
|
finally { setReportLoading(false); }
|
|
}, []);
|
|
|
|
const runCombinedRecommend = useCallback(async () => {
|
|
setCombinedLoading(true);
|
|
try {
|
|
const data = await getCombinedRecommend();
|
|
setCombined(data);
|
|
const hist = await getCombinedHistory(30);
|
|
setCombinedHistory(hist?.items ?? []);
|
|
} catch (e) { setError(e?.message ?? String(e)); }
|
|
finally { setCombinedLoading(false); }
|
|
}, []);
|
|
|
|
const loadCombinedHistory = useCallback(async () => {
|
|
setCombinedHistLoading(true);
|
|
try {
|
|
const hist = await getCombinedHistory(30);
|
|
setCombinedHistory(hist?.items ?? []);
|
|
} catch {}
|
|
finally { setCombinedHistLoading(false); }
|
|
}, []);
|
|
|
|
const refreshPersonalAnalysis = useCallback(async () => {
|
|
setPersonalLoading(true);
|
|
try { setPersonalAnalysis(await getPersonalAnalysis()); }
|
|
catch {}
|
|
finally { setPersonalLoading(false); }
|
|
}, []);
|
|
|
|
const onSimulate = useCallback(async () => {
|
|
const ok = confirm('시뮬레이션을 즉시 실행할까요?\n20,000개 후보를 분석합니다. (약 1~3분 소요)');
|
|
if (!ok) return;
|
|
setSimulating(true); setSimResult(null); setError('');
|
|
try {
|
|
const { triggerSimulate } = await import('../../../api');
|
|
const data = await triggerSimulate();
|
|
setSimResult(data);
|
|
await refreshBestPicks();
|
|
} catch (e) { setError(e?.message ?? String(e)); }
|
|
finally { setSimulating(false); }
|
|
}, [refreshBestPicks]);
|
|
|
|
// 초기 로드
|
|
useEffect(() => {
|
|
refreshLatest();
|
|
refreshStats();
|
|
refreshBestPicks();
|
|
refreshAnalysis();
|
|
refreshPerfStats();
|
|
refreshReport();
|
|
refreshPersonalAnalysis();
|
|
loadCombinedHistory();
|
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
return {
|
|
latest, loading, error, setError,
|
|
stats, statsLoading, statsError, refreshStats,
|
|
refreshLatest,
|
|
bestPicks, bestPicksExpanded, setBestPicksExpanded, refreshBestPicks,
|
|
analysis, refreshAnalysis,
|
|
simulating, simResult, onSimulate,
|
|
combined, combinedLoading, combinedHistory, combinedHistLoading,
|
|
runCombinedRecommend,
|
|
perfStats,
|
|
report, reportHistory, reportLoading, refreshReport, loadSpecificReport,
|
|
personalAnalysis, personalLoading,
|
|
};
|
|
}
|