This repository has been archived on 2026-05-06. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tippspiel/frontend/src/pages/DashboardPage.js
T
Ronny b273c6aa7e ci: switch to Gitea Container Registry for reliable deploys
Previous pipeline built images locally via Portainer Docker API,
but Docker layer caching produced identical images. Now:
- Build with nocache=1
- Push to Gitea registry (git.home.rm-warpstation.de)
- Compose uses image: from registry instead of build:
- Redeploy with pullImage: true forces fresh container

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:18:34 +02:00

48 lines
4.2 KiB
JavaScript

import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { api } from '../api/client';
import styles from './DashboardPage.module.css';
function formatStreak(streak) {
if (streak >= 20)
return `${streak}`;
if (streak >= 10)
return `🔥🔥${streak}`;
if (streak >= 3)
return `🔥${streak}`;
if (streak > 0)
return String(streak);
return '0';
}
function formatCountdown(minutes) {
if (minutes < 60)
return `in ${minutes} Min`;
if (minutes < 60 * 24)
return `in ${Math.floor(minutes / 60)}h`;
return `in ${Math.floor(minutes / (60 * 24))} Tagen`;
}
export default function DashboardPage(_props) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const navigate = useNavigate();
useEffect(() => {
setLoading(true);
setError(false);
api.getDashboard()
.then(d => { setData(d); setLoading(false); })
.catch(() => { setError(true); setLoading(false); });
}, []);
if (loading)
return _jsx("div", { className: styles.loading, children: "Laden..." });
if (error || !data)
return _jsx("div", { className: styles.error, children: "Dashboard konnte nicht geladen werden." });
const { hero, stats, nudges } = data;
return (_jsxs("div", { className: styles.dashboard, children: [_jsxs("div", { className: `card ${styles.hero}`, onClick: () => navigate('/spiele'), children: [_jsxs("div", { className: styles.heroLabel, children: [_jsx("span", { children: "N\u00E4chstes Spiel" }), hero && (_jsx("span", { className: styles.heroCountdown, children: formatCountdown(hero.match.minutesUntilKickoff) }))] }), hero ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.heroTeams, children: [_jsxs("div", { className: styles.heroTeam, children: [hero.match.homeTeam.crest ? (_jsx("img", { src: hero.match.homeTeam.crest, alt: hero.match.homeTeam.name, className: styles.heroCrest })) : (_jsx("div", { className: styles.heroCrest })), _jsx("span", { children: hero.match.homeTeam.shortName })] }), _jsx("span", { className: styles.heroVs, children: "vs" }), _jsxs("div", { className: styles.heroTeam, children: [hero.match.awayTeam.crest ? (_jsx("img", { src: hero.match.awayTeam.crest, alt: hero.match.awayTeam.name, className: styles.heroCrest })) : (_jsx("div", { className: styles.heroCrest })), _jsx("span", { children: hero.match.awayTeam.shortName })] })] }), hero.userTip ? (_jsxs("div", { className: styles.heroTip, children: ["Dein Tipp: ", hero.userTip.home, ":", hero.userTip.away, " \u2713"] })) : hero.tippable ? (_jsx("button", { className: styles.heroTipBtn, onClick: e => { e.stopPropagation(); navigate('/spiele'); }, children: "Jetzt tippen" })) : null] })) : (_jsx("p", { style: { textAlign: 'center', color: 'var(--text-muted)', margin: '16px 0' }, children: "Keine anstehenden Spiele" }))] }), _jsxs("div", { className: styles.statsRow, children: [_jsxs("div", { className: `card ${styles.statTile}`, children: [_jsx("span", { className: styles.statValue, children: stats.rank !== null ? stats.rank : '—' }), _jsx("span", { className: styles.statLabel, children: "Dein Rang" })] }), _jsxs("div", { className: `card ${styles.statTile}`, children: [_jsx("span", { className: styles.statValue, children: stats.totalPoints }), _jsx("span", { className: styles.statLabel, children: "Punkte" })] }), _jsxs("div", { className: `card ${styles.statTile}`, children: [_jsx("span", { className: styles.statValue, children: formatStreak(stats.streak) }), _jsx("span", { className: styles.statLabel, children: "Streak" })] })] }), nudges.length > 0 && (_jsx("div", { className: styles.nudges, children: nudges.map((nudge, i) => (_jsx("div", { className: `card ${styles.nudge}`, onClick: () => {
if (nudge.type === 'untipped')
navigate('/spiele');
else if (nudge.type === 'leader')
navigate('/rangliste');
}, children: nudge.text }, i))) }))] }));
}