feat: rank change arrow (↑/↓) in dashboard stats tile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -308,6 +308,20 @@
|
|||||||
color: var(--gold);
|
color: var(--gold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rankUp {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
color: var(--success);
|
||||||
|
margin-left: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rankDown {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
color: var(--error);
|
||||||
|
margin-left: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.statLabel {
|
.statLabel {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
@@ -360,6 +374,10 @@
|
|||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nudgeStreak {
|
||||||
|
border-left: 3px solid var(--error) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* ═══════════════════════════════════════
|
/* ═══════════════════════════════════════
|
||||||
STATES
|
STATES
|
||||||
═══════════════════════════════════════ */
|
═══════════════════════════════════════ */
|
||||||
|
|||||||
@@ -49,6 +49,21 @@ export default function DashboardPage(_props: Props) {
|
|||||||
|
|
||||||
const { hero, stats, nudges } = data;
|
const { hero, stats, nudges } = data;
|
||||||
|
|
||||||
|
const lastRank = parseInt(localStorage.getItem('tippspiel_last_rank') || '0');
|
||||||
|
const rankDiff = lastRank > 0 && stats.rank !== null ? lastRank - stats.rank : 0;
|
||||||
|
|
||||||
|
// Streak break detection via localStorage
|
||||||
|
const STREAK_KEY = 'tippspiel_last_streak';
|
||||||
|
const lastStreak = parseInt(localStorage.getItem(STREAK_KEY) || '0');
|
||||||
|
const streakBroken = lastStreak >= 3 && stats.streak === 0;
|
||||||
|
|
||||||
|
// Keep stored streak up to date when active
|
||||||
|
useEffect(() => {
|
||||||
|
if (stats.streak > 0) {
|
||||||
|
localStorage.setItem(STREAK_KEY, String(stats.streak));
|
||||||
|
}
|
||||||
|
}, [stats.streak]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.dashboard}>
|
<div className={styles.dashboard}>
|
||||||
{/* Hero Card */}
|
{/* Hero Card */}
|
||||||
@@ -140,7 +155,11 @@ export default function DashboardPage(_props: Props) {
|
|||||||
{/* Stats Row */}
|
{/* Stats Row */}
|
||||||
<div className={styles.statsRow}>
|
<div className={styles.statsRow}>
|
||||||
<div className={`card ${styles.statTile}`}>
|
<div className={`card ${styles.statTile}`}>
|
||||||
<span className={styles.statValue}>{stats.rank !== null ? stats.rank : '—'}</span>
|
<span className={styles.statValue}>
|
||||||
|
{stats.rank !== null ? stats.rank : '—'}
|
||||||
|
{rankDiff > 0 && <span className={styles.rankUp}>↑{rankDiff}</span>}
|
||||||
|
{rankDiff < 0 && <span className={styles.rankDown}>↓{Math.abs(rankDiff)}</span>}
|
||||||
|
</span>
|
||||||
<span className={styles.statLabel}>Dein Rang</span>
|
<span className={styles.statLabel}>Dein Rang</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={`card ${styles.statTile}`}>
|
<div className={`card ${styles.statTile}`}>
|
||||||
|
|||||||
Reference in New Issue
Block a user