Linka Na kavu v hlavicke lobby vedie na /donate. QR sa generuje dynamicky (balicek bysquare) pre presety 1/2/5 EUR alebo vlastnu sumu; IBAN sa da skopirovat do schranky. Navstevy loguje existujuci pageview beacon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
109 lines
4.1 KiB
TypeScript
109 lines
4.1 KiB
TypeScript
import { useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useGameStore } from '../store/gameStore';
|
|
import { emit, socket, setAuthToken } from '../lib/socket';
|
|
import { trackEvent } from '../lib/track';
|
|
import NameModal from '../components/NameModal';
|
|
import RulesModal from '../components/RulesModal';
|
|
|
|
export default function GameList() {
|
|
const navigate = useNavigate();
|
|
const games = useGameStore((s) => s.games);
|
|
const account = useGameStore((s) => s.account);
|
|
const [showCreate, setShowCreate] = useState(false);
|
|
const [showRules, setShowRules] = useState(false);
|
|
|
|
const handleShowRules = () => {
|
|
setShowRules(true);
|
|
trackEvent('rules_view');
|
|
};
|
|
|
|
const handleLogout = () => {
|
|
localStorage.removeItem('bridzik_token');
|
|
localStorage.removeItem('bridzik_player');
|
|
setAuthToken(null);
|
|
useGameStore.getState().logout();
|
|
// Drop the authenticated server-side session for this connection.
|
|
socket.disconnect();
|
|
socket.connect();
|
|
navigate('/auth', { replace: true });
|
|
};
|
|
|
|
return (
|
|
<div className="max-w-md mx-auto p-4 pt-8 min-h-screen">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<h1 className="font-serif text-2xl text-gold tracking-wide">Bridžik</h1>
|
|
<div className="flex items-center gap-3 text-sm">
|
|
<span className="text-green-dim">{account?.username}</span>
|
|
<button onClick={() => navigate('/history')} className="text-gold hover:text-gold-bright">
|
|
História
|
|
</button>
|
|
<button onClick={() => navigate('/donate')} className="text-gold hover:text-gold-bright">
|
|
Na kávu
|
|
</button>
|
|
<button onClick={handleLogout} className="text-green-dim hover:text-gold">
|
|
Odhlásiť
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-3 mb-6">
|
|
{games.length === 0 && (
|
|
<p className="text-center text-green-dim py-4">Žiadne hry. Vytvor prvú!</p>
|
|
)}
|
|
{games.map((g) => {
|
|
const full = g.players.length >= 4;
|
|
const isMember =
|
|
!!account && g.players.some((p) => p.player_id === account.player_id);
|
|
const canResume = g.started && isMember;
|
|
const unavailable = !canResume && (full || g.started);
|
|
const label = canResume ? 'Pokračovať' : full ? 'Plná' : g.started ? 'Začatá' : 'Vstúp';
|
|
return (
|
|
<div
|
|
key={g.gid}
|
|
className="flex items-center justify-between bg-header border border-[#142018] rounded-xl px-4 py-3"
|
|
>
|
|
<div>
|
|
<p className="font-serif text-green-score">{g.name}</p>
|
|
<p className="text-xs text-green-dim">
|
|
{g.players.length}/4 hráčov
|
|
{g.started ? ' · začatá' : ''}
|
|
</p>
|
|
</div>
|
|
<button
|
|
disabled={unavailable}
|
|
onClick={() => (canResume ? emit.rejoinGame(g.gid) : emit.registerPlayer(g.gid))}
|
|
className={`px-4 py-1.5 rounded-lg text-sm font-serif font-semibold disabled:opacity-40 disabled:cursor-default transition-colors ${
|
|
canResume
|
|
? 'bg-gold text-table hover:bg-gold-bright'
|
|
: 'border border-gold/40 text-gold hover:bg-gold hover:text-table'
|
|
}`}
|
|
>
|
|
{label}
|
|
</button>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<button
|
|
onClick={() => setShowCreate(true)}
|
|
className="w-full py-2 rounded-xl bg-gold text-table font-serif font-semibold text-base mb-3 hover:bg-gold-bright transition-colors"
|
|
>
|
|
Vytvoriť novú hru
|
|
</button>
|
|
|
|
<button
|
|
onClick={handleShowRules}
|
|
className="w-full py-2 rounded-xl border border-gold/20 text-sm text-green-score hover:border-gold/50 transition-colors"
|
|
>
|
|
Pravidlá hry
|
|
</button>
|
|
|
|
{showRules && <RulesModal onClose={() => setShowRules(false)} />}
|
|
|
|
{showCreate && <NameModal onClose={() => setShowCreate(false)} />}
|
|
</div>
|
|
);
|
|
}
|