lotto lab UI 수정
- 히스토리, 과거 이력 더 보기 좋게 변경
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { deleteHistory, getHistory, getLatest, getStats, recommend } from '../../api';
|
||||
|
||||
const fmtKST = (value) => value?.replace('T', ' ') ?? '';
|
||||
@@ -166,7 +166,9 @@ const FrequencyChart = ({ stats }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="lotto-chart__plot" role="list">
|
||||
{series.map((item) => (
|
||||
{series.map((item) => {
|
||||
const showLabel = item.number === 1 || item.number % 5 === 0;
|
||||
return (
|
||||
<div
|
||||
key={item.number}
|
||||
className="lotto-chart__col"
|
||||
@@ -178,9 +180,12 @@ const FrequencyChart = ({ stats }) => {
|
||||
title={`${item.number}번: ${item.count}회`}
|
||||
aria-label={`${item.number}번 ${item.count}회`}
|
||||
/>
|
||||
<span className="lotto-chart__x">{item.number}</span>
|
||||
<span className="lotto-chart__x" aria-hidden={!showLabel}>
|
||||
{showLabel ? item.number : ''}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -205,6 +210,9 @@ export default function Functions() {
|
||||
|
||||
const [result, setResult] = useState(null);
|
||||
const [history, setHistory] = useState([]);
|
||||
const [historyExpanded, setHistoryExpanded] = useState(false);
|
||||
const historyEndRef = useRef(null);
|
||||
const prevHistoryExpandedRef = useRef(false);
|
||||
const [stats, setStats] = useState(() => readStatsCache());
|
||||
const [statsLoading, setStatsLoading] = useState(false);
|
||||
const [statsError, setStatsError] = useState('');
|
||||
@@ -306,6 +314,20 @@ export default function Functions() {
|
||||
refreshStats();
|
||||
}, []);
|
||||
|
||||
const visibleHistory = historyExpanded ? history : history.slice(0, 5);
|
||||
|
||||
useEffect(() => {
|
||||
if (historyExpanded && !prevHistoryExpandedRef.current) {
|
||||
requestAnimationFrame(() => {
|
||||
historyEndRef.current?.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'end',
|
||||
});
|
||||
});
|
||||
}
|
||||
prevHistoryExpandedRef.current = historyExpanded;
|
||||
}, [historyExpanded, visibleHistory.length]);
|
||||
|
||||
return (
|
||||
<div className="lotto-functions">
|
||||
{error ? (
|
||||
@@ -542,7 +564,9 @@ export default function Functions() {
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section className="lotto-panel">
|
||||
</div>
|
||||
|
||||
<section className="lotto-panel lotto-panel--wide">
|
||||
<div className="lotto-panel__head">
|
||||
<div>
|
||||
<p className="lotto-panel__eyebrow">Distribution</p>
|
||||
@@ -570,9 +594,7 @@ export default function Functions() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{statsError ? (
|
||||
<p className="lotto-empty">{statsError}</p>
|
||||
) : null}
|
||||
{statsError ? <p className="lotto-empty">{statsError}</p> : null}
|
||||
{stats ? (
|
||||
<FrequencyChart stats={stats} />
|
||||
) : (
|
||||
@@ -581,7 +603,6 @@ export default function Functions() {
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section className="lotto-panel">
|
||||
<div className="lotto-panel__head">
|
||||
@@ -594,6 +615,30 @@ export default function Functions() {
|
||||
</div>
|
||||
<div className="lotto-panel__actions">
|
||||
<span className="lotto-chip">{history.length}건</span>
|
||||
{history.length > 5 ? (
|
||||
<button
|
||||
className="button ghost small lotto-history-toggle"
|
||||
onClick={() =>
|
||||
setHistoryExpanded((prev) => !prev)
|
||||
}
|
||||
aria-expanded={historyExpanded}
|
||||
aria-label={
|
||||
historyExpanded
|
||||
? '히스토리 접기'
|
||||
: '히스토리 더보기'
|
||||
}
|
||||
>
|
||||
{historyExpanded ? '접기' : '더보기'}
|
||||
<span
|
||||
className={`lotto-history-toggle__icon ${
|
||||
historyExpanded ? 'is-open' : ''
|
||||
}`}
|
||||
aria-hidden
|
||||
>
|
||||
▼
|
||||
</span>
|
||||
</button>
|
||||
) : null}
|
||||
<button
|
||||
className="button ghost small"
|
||||
onClick={refreshHistory}
|
||||
@@ -610,7 +655,7 @@ export default function Functions() {
|
||||
<p className="lotto-empty">저장된 히스토리가 없습니다.</p>
|
||||
) : (
|
||||
<div className="lotto-history">
|
||||
{history.map((item) => (
|
||||
{visibleHistory.map((item) => (
|
||||
<div key={item.id} className="lotto-history__item">
|
||||
<div className="lotto-history__meta">
|
||||
<p>#{item.id}</p>
|
||||
@@ -641,6 +686,7 @@ export default function Functions() {
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<span ref={historyEndRef} />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
@@ -69,6 +69,18 @@
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.lotto-panel--wide .lotto-chart {
|
||||
grid-template-columns: 60px minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.lotto-panel--wide .lotto-chart__plot {
|
||||
height: 220px;
|
||||
}
|
||||
|
||||
.lotto-panel--wide .lotto-chart__ticks {
|
||||
min-height: 220px;
|
||||
}
|
||||
|
||||
.lotto-panel__head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -505,6 +517,22 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.lotto-history-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.lotto-history-toggle__icon {
|
||||
display: inline-block;
|
||||
transition: transform 0.2s ease;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.lotto-history-toggle__icon.is-open {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.lotto-history__item {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 18px;
|
||||
|
||||
Reference in New Issue
Block a user