Functions.jsx 컴포넌트 분할: 1,583→460줄 (3훅+8컴포넌트+유틸)
- 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>
This commit is contained in:
105
src/pages/lotto/hooks/usePurchases.js
Normal file
105
src/pages/lotto/hooks/usePurchases.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
getPurchases, getPurchaseStats, addPurchase, updatePurchase, deletePurchase,
|
||||
} from '../../../api';
|
||||
import { emptyPurchaseForm } from '../lottoUtils';
|
||||
|
||||
export default function usePurchases() {
|
||||
const [purchases, setPurchases] = useState([]);
|
||||
const [purchaseStats, setPurchaseStats] = useState(null);
|
||||
const [purchaseLoading, setPurchaseLoading] = useState(false);
|
||||
|
||||
// 폼 상태
|
||||
const [purchaseFormOpen, setPurchaseFormOpen] = useState(false);
|
||||
const [purchaseForm, setPurchaseForm] = useState(emptyPurchaseForm);
|
||||
const [purchaseFormSaving, setPurchaseFormSaving] = useState(false);
|
||||
const [purchaseFormError, setPurchaseFormError] = useState('');
|
||||
const [purchaseEditId, setPurchaseEditId] = useState(null);
|
||||
|
||||
const refreshPurchases = useCallback(async () => {
|
||||
setPurchaseLoading(true);
|
||||
try {
|
||||
const [recs, st] = await Promise.all([getPurchases(), getPurchaseStats()]);
|
||||
setPurchases(recs?.records ?? []);
|
||||
setPurchaseStats(st);
|
||||
} catch {}
|
||||
finally { setPurchaseLoading(false); }
|
||||
}, []);
|
||||
|
||||
const handlePurchaseFormOpen = useCallback(() => {
|
||||
setPurchaseEditId(null);
|
||||
setPurchaseForm(emptyPurchaseForm());
|
||||
setPurchaseFormError('');
|
||||
setPurchaseFormOpen(true);
|
||||
}, []);
|
||||
|
||||
const handlePurchaseFormClose = useCallback(() => {
|
||||
setPurchaseFormOpen(false);
|
||||
setPurchaseEditId(null);
|
||||
setPurchaseFormError('');
|
||||
}, []);
|
||||
|
||||
const handlePurchaseFormChange = useCallback((field, value) => {
|
||||
setPurchaseForm((prev) => ({ ...prev, [field]: value }));
|
||||
}, []);
|
||||
|
||||
const handlePurchaseEditStart = useCallback((rec) => {
|
||||
setPurchaseEditId(rec.id);
|
||||
setPurchaseForm({
|
||||
draw_no: String(rec.draw_no ?? ''),
|
||||
amount: rec.amount ?? 5000,
|
||||
sets: rec.sets ?? 5,
|
||||
prize: rec.prize ?? 0,
|
||||
note: rec.note ?? '',
|
||||
});
|
||||
setPurchaseFormError('');
|
||||
setPurchaseFormOpen(true);
|
||||
}, []);
|
||||
|
||||
const handlePurchaseFormSubmit = useCallback(async (e) => {
|
||||
e.preventDefault();
|
||||
setPurchaseFormSaving(true); setPurchaseFormError('');
|
||||
const payload = {
|
||||
draw_no: Number(purchaseForm.draw_no),
|
||||
amount: Number(purchaseForm.amount),
|
||||
sets: Number(purchaseForm.sets),
|
||||
prize: Number(purchaseForm.prize),
|
||||
note: purchaseForm.note.trim(),
|
||||
};
|
||||
try {
|
||||
if (purchaseEditId != null) {
|
||||
const updated = await updatePurchase(purchaseEditId, payload);
|
||||
setPurchases((prev) =>
|
||||
prev.map((r) => r.id === purchaseEditId ? (updated ?? { ...payload, id: purchaseEditId }) : r)
|
||||
);
|
||||
} else {
|
||||
const saved = await addPurchase(payload);
|
||||
setPurchases((prev) => [saved ?? { ...payload, id: Date.now() }, ...prev]);
|
||||
}
|
||||
try { setPurchaseStats(await getPurchaseStats()); } catch {}
|
||||
handlePurchaseFormClose();
|
||||
} catch (err) {
|
||||
setPurchaseFormError(err?.message ?? String(err));
|
||||
} finally {
|
||||
setPurchaseFormSaving(false);
|
||||
}
|
||||
}, [purchaseForm, purchaseEditId, handlePurchaseFormClose]);
|
||||
|
||||
const handlePurchaseDelete = useCallback(async (id) => {
|
||||
if (!confirm('이 구매 기록을 삭제할까요?')) return;
|
||||
setPurchases((prev) => prev.filter((r) => r.id !== id));
|
||||
try {
|
||||
await deletePurchase(id);
|
||||
try { setPurchaseStats(await getPurchaseStats()); } catch {}
|
||||
} catch { refreshPurchases(); }
|
||||
}, [refreshPurchases]);
|
||||
|
||||
useEffect(() => { refreshPurchases(); }, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return {
|
||||
purchases, purchaseStats, purchaseLoading,
|
||||
purchaseFormOpen, purchaseForm, purchaseFormSaving, purchaseFormError, purchaseEditId,
|
||||
handlePurchaseFormOpen, handlePurchaseFormClose, handlePurchaseFormChange,
|
||||
handlePurchaseFormSubmit, handlePurchaseEditStart, handlePurchaseDelete,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user