Files
web-page/src/pages/lotto/hooks/useBriefing.js

69 lines
2.3 KiB
JavaScript

import { useState, useEffect, useCallback, useRef } from 'react';
import { getLatestBriefing, triggerLottoCurate } from '../../../api';
const normalizePicks = (picks) => {
if (Array.isArray(picks)) {
return { core: picks, bonus: [], extended: [], pool: [] };
}
return {
core: picks?.core || [],
bonus: picks?.bonus || [],
extended: picks?.extended || [],
pool: picks?.pool || [],
};
};
export default function useBriefing() {
const [briefing, setBriefing] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [regenerating, setRegenerating] = useState(false);
const pollingRef = useRef(null);
const load = useCallback(async () => {
setLoading(true); setError('');
try {
const data = await getLatestBriefing();
setBriefing(data ? { ...data, picks: normalizePicks(data.picks) } : data);
} catch (e) {
setError(e.message);
} finally {
setLoading(false);
}
}, []);
useEffect(() => { load(); }, [load]);
const regenerate = useCallback(async () => {
setRegenerating(true); setError('');
try {
const prevGen = briefing?.generated_at;
await triggerLottoCurate();
let attempts = 0;
pollingRef.current = setInterval(async () => {
attempts += 1;
try {
const data = await getLatestBriefing();
if (data && data.generated_at !== prevGen) {
setBriefing({ ...data, picks: normalizePicks(data.picks) });
setRegenerating(false);
clearInterval(pollingRef.current);
}
} catch {}
if (attempts >= 40) {
clearInterval(pollingRef.current);
setRegenerating(false);
setError('재생성 타임아웃 (2분)');
}
}, 3000);
} catch (e) {
setError(e.message);
setRegenerating(false);
}
}, [briefing?.generated_at]);
useEffect(() => () => { if (pollingRef.current) clearInterval(pollingRef.current); }, []);
return { briefing, loading, error, regenerating, reload: load, regenerate };
}