Make the participation code copyable as a shareable invite link

The code was shown as plain text on the game card with no way to copy
it. It's now a button that copies a full invite link
(origin/games/{id}?code={code}) to the clipboard instead of just the
bare code, since the recipient still needs the game id to get there.

GameSession's join form reads that ?code= param on mount and
pre-fills the input, so following the link lands straight on "click
Beitreten" instead of needing the code typed in by hand.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thorsten
2026-09-01 18:15:47 +02:00
parent a8763e175f
commit ff4c6f07e3
2 changed files with 32 additions and 4 deletions
+29 -2
View File
@@ -1,9 +1,20 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import { Game } from "../api/games";
export default function GameCard({ game }: { game: Game }) {
const created = new Date(game.created_at).toLocaleString("de-DE");
const [copied, setCopied] = useState(false);
async function handleCopyLink(e: React.MouseEvent) {
e.preventDefault();
e.stopPropagation();
const link = `${window.location.origin}/games/${game.id}?code=${game.participation_code}`;
await navigator.clipboard.writeText(link);
setCopied(true);
setTimeout(() => setCopied(false), 1500);
}
return (
<Link
@@ -18,9 +29,25 @@ export default function GameCard({ game }: { game: Game }) {
</span>
)}
{game.participation_code && (
<span className="shrink-0 rounded bg-amber-500/20 px-2 py-1 font-mono text-xs text-amber-300">
<button
onClick={handleCopyLink}
title="Einladungslink kopieren"
className="flex shrink-0 items-center gap-1.5 rounded bg-amber-500/20 px-2 py-1 font-mono text-xs text-amber-300 hover:bg-amber-500/30"
>
Code: {game.participation_code}
</span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={2}
className="h-3.5 w-3.5"
>
<rect x="9" y="9" width="11" height="11" rx="1.5" />
<path d="M5 15V5a2 2 0 0 1 2-2h10" />
</svg>
{copied && <span className="text-emerald-400">Kopiert!</span>}
</button>
)}
</div>
<p className="mt-1 text-sm text-slate-400">{game.description}</p>