Timer integration

This commit is contained in:
Marc Wieland 2026-01-23 10:55:27 +01:00
parent 5bcc4c570f
commit d43866615b
2 changed files with 102 additions and 0 deletions

View File

@ -0,0 +1,99 @@
import { useState, useEffect } from 'react';
import { Timer, Play, Pause, RotateCcw } from 'lucide-react';
import { Button } from '@/components/ui/button';
interface RoundTimerProps {
roundNumber: number;
}
export const RoundTimer = ({ roundNumber }: RoundTimerProps) => {
const [seconds, setSeconds] = useState(0);
const [isRunning, setIsRunning] = useState(true); // Auto-start beim Laden
const [isPaused, setIsPaused] = useState(false);
useEffect(() => {
// Reset timer wenn neue Runde startet
setSeconds(0);
setIsRunning(true);
setIsPaused(false);
}, [roundNumber]);
useEffect(() => {
let interval: NodeJS.Timeout | null = null;
if (isRunning && !isPaused) {
interval = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
}
return () => {
if (interval) clearInterval(interval);
};
}, [isRunning, isPaused]);
const togglePause = () => {
setIsPaused((prev) => !prev);
};
const reset = () => {
setSeconds(0);
setIsPaused(false);
};
const formatTime = (totalSeconds: number): string => {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const secs = totalSeconds % 60;
if (hours > 0) {
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
return `${minutes}:${secs.toString().padStart(2, '0')}`;
};
return (
<div className="card-apple p-4 flex items-center justify-between gap-4">
<div className="flex items-center gap-3">
<div className={`p-2 rounded-xl transition-colors ${
isPaused
? 'bg-muted text-muted-foreground'
: 'bg-primary/10 text-primary animate-pulse'
}`}>
<Timer className="w-5 h-5" />
</div>
<div>
<p className="text-sm font-medium text-muted-foreground">Rundenzeit</p>
<p className="text-2xl font-bold text-foreground tabular-nums">
{formatTime(seconds)}
</p>
</div>
</div>
<div className="flex gap-2">
<Button
variant="outline"
size="icon"
onClick={togglePause}
className="rounded-xl h-9 w-9"
title={isPaused ? 'Fortsetzen' : 'Pausieren'}
>
{isPaused ? (
<Play className="w-4 h-4" />
) : (
<Pause className="w-4 h-4" />
)}
</Button>
<Button
variant="outline"
size="icon"
onClick={reset}
className="rounded-xl h-9 w-9"
title="Zurücksetzen"
>
<RotateCcw className="w-4 h-4" />
</Button>
</div>
</div>
);
};

View File

@ -4,6 +4,7 @@ import { Trophy, Star, Clock, Play, CheckCircle, AlertCircle } from 'lucide-reac
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { MatchScoreInput } from '@/components/MatchScoreInput'; import { MatchScoreInput } from '@/components/MatchScoreInput';
import { ScoreboardModal } from '@/components/ScoreboardModal'; import { ScoreboardModal } from '@/components/ScoreboardModal';
import { RoundTimer } from '@/components/RoundTimer';
const WaitingTeam = ({ team }: { team: Team }) => ( const WaitingTeam = ({ team }: { team: Team }) => (
<div className="flex items-center gap-3 p-3 bg-waiting/10 rounded-xl border border-waiting/20"> <div className="flex items-center gap-3 p-3 bg-waiting/10 rounded-xl border border-waiting/20">
@ -160,6 +161,8 @@ export const TournamentView = () => {
{currentRound && ( {currentRound && (
<> <>
<RoundTimer roundNumber={currentRound.roundNumber} />
<div className="card-apple p-4 bg-primary/5 border-primary/20"> <div className="card-apple p-4 bg-primary/5 border-primary/20">
<p className="text-sm text-center text-muted-foreground"> <p className="text-sm text-center text-muted-foreground">
<span className="font-semibold text-primary">Runde {currentRound.roundNumber}</span> <span className="font-semibold text-primary">Runde {currentRound.roundNumber}</span>