feat(lotto): useBriefing·useCuratorUsage 훅
This commit is contained in:
56
src/pages/lotto/hooks/useBriefing.js
Normal file
56
src/pages/lotto/hooks/useBriefing.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||||
|
import { getLatestBriefing, triggerLottoCurate } from '../../../api';
|
||||||
|
|
||||||
|
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);
|
||||||
|
} 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);
|
||||||
|
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 };
|
||||||
|
}
|
||||||
17
src/pages/lotto/hooks/useCuratorUsage.js
Normal file
17
src/pages/lotto/hooks/useCuratorUsage.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { getCuratorUsage } from '../../../api';
|
||||||
|
|
||||||
|
export default function useCuratorUsage(days = 30) {
|
||||||
|
const [usage, setUsage] = useState(null);
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let alive = true;
|
||||||
|
getCuratorUsage(days)
|
||||||
|
.then(d => { if (alive) setUsage(d); })
|
||||||
|
.catch(e => { if (alive) setError(e.message); });
|
||||||
|
return () => { alive = false; };
|
||||||
|
}, [days]);
|
||||||
|
|
||||||
|
return { usage, error };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user