feat(lotto): 구매탭에 자동 채점 일치수 배지 + 4등↑ 플래그

This commit is contained in:
2026-05-11 09:05:22 +09:00
parent 0bf1233e96
commit 4ef76f6cce
3 changed files with 37 additions and 5 deletions

View File

@@ -1020,7 +1020,7 @@
.lotto-purchase-list__head {
display: grid;
grid-template-columns: 60px 100px 100px 100px minmax(0, 1fr) 120px;
grid-template-columns: 60px 100px 100px 100px minmax(0, 160px) minmax(0, 1fr) 120px;
gap: 8px;
padding: 10px 14px;
font-size: 11px;
@@ -1033,7 +1033,7 @@
.lotto-purchase-row {
display: grid;
grid-template-columns: 60px 100px 100px 100px minmax(0, 1fr) 120px;
grid-template-columns: 60px 100px 100px 100px minmax(0, 160px) minmax(0, 1fr) 120px;
gap: 8px;
align-items: center;
padding: 12px 14px;
@@ -1068,6 +1068,21 @@
justify-content: flex-end;
}
.lotto-purchase-row__hits {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 2px;
overflow: hidden;
}
.hit-badge { display: inline-block; min-width: 16px; padding: 1px 4px; margin-right: 2px;
font-size: 10px; border-radius: 4px; background: rgba(255,255,255,0.06); text-align: center; }
.hit-badge.hit-3 { background: rgba(80, 200, 120, 0.2); color: #76e09a; }
.hit-badge.hit-4 { background: rgba(255, 200, 80, 0.25); color: #ffce6e; font-weight: 700; }
.hit-badge.hit-5, .hit-badge.hit-6 { background: rgba(255, 100, 130, 0.3); color: #ff8aa0; font-weight: 700; }
.prize-flag { font-size: 10px; color: #ff8aa0; margin-left: 6px; }
.is-pos { color: #97c9aa; }
.is-neg { color: #f7a8a5; }
.is-prize { color: #fdd4b1; }
@@ -1098,8 +1113,8 @@
gap: 8px;
}
.lotto-purchase-list__head span:nth-child(n+3):nth-child(-n+5),
.lotto-purchase-row span:nth-child(n+3):nth-child(-n+5) {
.lotto-purchase-list__head span:nth-child(n+3):nth-child(-n+6),
.lotto-purchase-row span:nth-child(n+3):nth-child(-n+6) {
display: none;
}
@@ -1143,7 +1158,7 @@
.lotto-purchase-list__head,
.lotto-purchase-row {
grid-template-columns: 56px 90px 90px minmax(0, 1fr) 100px;
grid-template-columns: 56px 90px 90px minmax(0, 120px) minmax(0, 1fr) 100px;
}
.lotto-purchase-list__head span:nth-child(4),

View File

@@ -137,6 +137,7 @@ const PurchasePanel = ({
<span>투자금</span>
<span>당첨금</span>
<span>손익</span>
<span>채점</span>
<span>메모</span>
<span />
</div>
@@ -152,6 +153,14 @@ const PurchasePanel = ({
<span className={net >= 0 ? 'is-pos' : 'is-neg'}>
{net >= 0 ? '+' : ''}{fmtWon(net)}
</span>
<span className="lotto-purchase-row__hits">
{(rec.results || []).map((r, i) => (
<span key={i} className={`hit-badge hit-${r.correct}`}>{r.correct}</span>
))}
{(rec.results || []).some((r) => r.correct >= 4) && (
<span className="prize-flag">🚨 4 확인 필요</span>
)}
</span>
<span className="lotto-purchase-row__note">{rec.note || '-'}</span>
<div className="lotto-purchase-row__actions">
<button className="button ghost small" onClick={() => onEditStart(rec)}>

View File

@@ -1,6 +1,7 @@
import { useCallback, useEffect, useState } from 'react';
import {
getPurchases, getPurchaseStats, addPurchase, updatePurchase, deletePurchase,
bulkPurchase as apiBulkPurchase,
} from '../../../api';
import { emptyPurchaseForm } from '../lottoUtils';
@@ -94,6 +95,12 @@ export default function usePurchases() {
} catch { refreshPurchases(); }
}, [refreshPurchases]);
const handleBulkPurchase = useCallback(async (params) => {
const result = await apiBulkPurchase(params);
await refreshPurchases();
return result;
}, [refreshPurchases]);
useEffect(() => { refreshPurchases(); }, []); // eslint-disable-line react-hooks/exhaustive-deps
return {
@@ -101,5 +108,6 @@ export default function usePurchases() {
purchaseFormOpen, purchaseForm, purchaseFormSaving, purchaseFormError, purchaseEditId,
handlePurchaseFormOpen, handlePurchaseFormClose, handlePurchaseFormChange,
handlePurchaseFormSubmit, handlePurchaseEditStart, handlePurchaseDelete,
handleBulkPurchase,
};
}