feat: stronger visual scoring differentiation + streak fix
- Exakt cards: gold glow border, gold banner, trophy emoji, larger animated badge - Tendency: green accent (was blue), clearer differentiation from Exakt - Falsch: muted gray, reduced opacity — clearly "lost" - Profile tip history: solid gold/green/gray badges with distinct borders - Streak: remove utc_date <= NOW() filter so dev-finished matches count; handle PostgreSQL boolean serialization Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -53,13 +53,13 @@ router.get('/', async (req: Request, res: Response): Promise<void> => {
|
|||||||
`SELECT CASE WHEN t.id IS NOT NULL THEN true ELSE false END AS has_tip
|
`SELECT CASE WHEN t.id IS NOT NULL THEN true ELSE false END AS has_tip
|
||||||
FROM matches m
|
FROM matches m
|
||||||
LEFT JOIN tips t ON t.match_id = m.id AND t.user_id = $1
|
LEFT JOIN tips t ON t.match_id = m.id AND t.user_id = $1
|
||||||
WHERE m.utc_date <= NOW() AND m.status IN ('FINISHED', 'IN_PLAY')
|
WHERE m.status IN ('FINISHED', 'IN_PLAY')
|
||||||
ORDER BY m.utc_date DESC`,
|
ORDER BY m.utc_date DESC`,
|
||||||
[userId]
|
[userId]
|
||||||
);
|
);
|
||||||
let streak = 0;
|
let streak = 0;
|
||||||
for (const m of pastMatches) {
|
for (const m of pastMatches) {
|
||||||
if (m.has_tip) streak++;
|
if (m.has_tip === true || (m.has_tip as unknown) === 't' || (m.has_tip as unknown) === '1') streak++;
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -341,43 +341,46 @@
|
|||||||
|
|
||||||
/* Farb-Varianten Banner */
|
/* Farb-Varianten Banner */
|
||||||
.exact {
|
.exact {
|
||||||
background: linear-gradient(90deg, rgba(52,211,153,0.18) 0%, rgba(52,211,153,0.08) 100%);
|
background: linear-gradient(90deg, rgba(254,174,50,0.22) 0%, rgba(254,174,50,0.09) 100%);
|
||||||
color: #4ade80;
|
color: #FECC4C;
|
||||||
border-top: 1px solid rgba(52,211,153,0.20);
|
border-top: 1px solid rgba(254,174,50,0.30);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tendency {
|
.tendency {
|
||||||
background: linear-gradient(90deg, rgba(75,183,248,0.18) 0%, rgba(75,183,248,0.08) 100%);
|
background: linear-gradient(90deg, rgba(52,211,153,0.18) 0%, rgba(52,211,153,0.08) 100%);
|
||||||
color: var(--primary);
|
color: #4ade80;
|
||||||
border-top: 1px solid rgba(75,183,248,0.20);
|
border-top: 1px solid rgba(52,211,153,0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrong {
|
.wrong {
|
||||||
background: linear-gradient(90deg, rgba(248,113,113,0.15) 0%, rgba(248,113,113,0.06) 100%);
|
background: linear-gradient(90deg, rgba(148,163,184,0.12) 0%, rgba(148,163,184,0.05) 100%);
|
||||||
color: var(--error);
|
color: var(--text-muted);
|
||||||
border-top: 1px solid rgba(248,113,113,0.18);
|
border-top: 1px solid rgba(148,163,184,0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Card-Glow je Ergebnis */
|
/* Card-Glow je Ergebnis */
|
||||||
.glowExact {
|
.glowExact {
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 1px rgba(52,211,153,0.18),
|
0 0 0 1.5px rgba(254,174,50,0.40),
|
||||||
0 10px 30px rgba(52,211,153,0.07),
|
0 0 20px rgba(254,174,50,0.18),
|
||||||
inset 0 1px 0 rgba(255,255,255,0.07) !important;
|
0 10px 30px rgba(254,174,50,0.10),
|
||||||
|
inset 0 1px 0 rgba(255,255,255,0.09) !important;
|
||||||
|
border-color: rgba(254,174,50,0.35) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glowTendency {
|
.glowTendency {
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 1px rgba(75,183,248,0.18),
|
0 0 0 1px rgba(52,211,153,0.28),
|
||||||
0 10px 30px rgba(75,183,248,0.07),
|
0 10px 30px rgba(52,211,153,0.10),
|
||||||
inset 0 1px 0 rgba(255,255,255,0.07) !important;
|
inset 0 1px 0 rgba(255,255,255,0.07) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.glowWrong {
|
.glowWrong {
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 1px rgba(248,113,113,0.15),
|
0 0 0 1px rgba(148,163,184,0.15),
|
||||||
0 10px 30px rgba(248,113,113,0.05),
|
0 10px 20px rgba(0,0,0,0.08),
|
||||||
inset 0 1px 0 rgba(255,255,255,0.07) !important;
|
inset 0 1px 0 rgba(255,255,255,0.05) !important;
|
||||||
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editBtn {
|
.editBtn {
|
||||||
@@ -493,19 +496,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pointsBadge_exact {
|
.pointsBadge_exact {
|
||||||
background: linear-gradient(135deg, var(--gold), #FFD700);
|
background: linear-gradient(135deg, #FEAE32, #FFD700, #FECC4C);
|
||||||
color: #1a1a1a;
|
color: #1a1a1a;
|
||||||
animation: shimmer 2s ease-in-out;
|
font-size: 0.9rem;
|
||||||
|
padding: 5px 12px;
|
||||||
|
box-shadow: 0 0 12px rgba(254,174,50,0.45);
|
||||||
|
animation: shimmer 2.5s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pointsBadge_tendency {
|
.pointsBadge_tendency {
|
||||||
background: var(--success);
|
background: linear-gradient(135deg, var(--success), #22c55e);
|
||||||
color: #1a1a1a;
|
color: #0a2a1a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pointsBadge_wrong {
|
.pointsBadge_wrong {
|
||||||
background: var(--text-muted);
|
background: var(--surface-high);
|
||||||
color: var(--bg-deep);
|
color: var(--text-muted);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Missed label */
|
/* Missed label */
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ export default function MatchCard({ match, onTip }: Props) {
|
|||||||
<X size={14} strokeWidth={3} />}
|
<X size={14} strokeWidth={3} />}
|
||||||
</span>
|
</span>
|
||||||
<span className={styles.resultLabel}>
|
<span className={styles.resultLabel}>
|
||||||
{points === 3 ? 'Exakt' : points === 1 ? 'Tendenz' : 'Falsch'}
|
{points === 3 ? '🏆 Exakt' : points === 1 ? 'Tendenz' : 'Falsch'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -186,9 +186,21 @@
|
|||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badgeExact { background: rgba(255,196,0,0.15); color: var(--gold); }
|
.badgeExact {
|
||||||
.badgeTendency { background: rgba(34,197,94,0.15); color: var(--success); }
|
background: linear-gradient(135deg, #FEAE32, #FFD700);
|
||||||
.badgeWrong { background: rgba(239,68,68,0.12); color: var(--error); }
|
color: #1a1a1a;
|
||||||
|
box-shadow: 0 0 8px rgba(254,174,50,0.35);
|
||||||
|
}
|
||||||
|
.badgeTendency {
|
||||||
|
background: rgba(34,197,94,0.22);
|
||||||
|
color: #4ade80;
|
||||||
|
border: 1px solid rgba(34,197,94,0.30);
|
||||||
|
}
|
||||||
|
.badgeWrong {
|
||||||
|
background: var(--surface-high);
|
||||||
|
color: var(--text-muted);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Fun stats ── */
|
/* ── Fun stats ── */
|
||||||
.funStats { display: flex; flex-direction: column; gap: 12px; }
|
.funStats { display: flex; flex-direction: column; gap: 12px; }
|
||||||
|
|||||||
Reference in New Issue
Block a user