Restructure onboarding (option B): - home is just Create / Join (code) — no name field - name is chosen in the room: room:create/join no longer require a name; new player:setName event. Nameless players are hidden from the snapshot (players/scores/submissions) and excluded from eligible voters and the 3-player blindtest gate until they pick a pseudo. - PseudoScreen with live DiceBear avatar preview gates RoomPage until set - /join/:code auto-joins then redirects to the room (seamless invite links) - RoomCode gains a "copier le lien" button (origin/join/CODE) Verified e2e: nameless players excluded from the room until setName. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import { useState } from "react"
|
|
import { Check, Copy, Link2 } from "lucide-react"
|
|
import { Button } from "@workspace/ui/components/button"
|
|
|
|
type Copied = "code" | "link" | null
|
|
|
|
/** Code de room copiable + bouton pour copier le lien d'invitation. */
|
|
export function RoomCode({ code }: { code: string }) {
|
|
const [copied, setCopied] = useState<Copied>(null)
|
|
|
|
async function copy(what: Copied, text: string) {
|
|
try {
|
|
await navigator.clipboard.writeText(text)
|
|
setCopied(what)
|
|
setTimeout(() => setCopied(null), 1500)
|
|
} catch {
|
|
// presse-papier indisponible (http non sécurisé) : on ignore silencieusement
|
|
}
|
|
}
|
|
|
|
const link = `${window.location.origin}/join/${code}`
|
|
|
|
return (
|
|
<div className="flex items-center gap-3">
|
|
<button
|
|
onClick={() => copy("code", code)}
|
|
title="Copier le code"
|
|
className="group flex items-center gap-2 text-left"
|
|
>
|
|
<span>
|
|
<span className="text-muted-foreground text-xs uppercase">
|
|
Code room
|
|
</span>
|
|
<span className="font-heading block text-2xl font-bold tracking-widest">
|
|
{code}
|
|
</span>
|
|
</span>
|
|
{copied === "code" ? (
|
|
<Check className="size-4 text-green-500" />
|
|
) : (
|
|
<Copy className="text-muted-foreground group-hover:text-foreground size-4 transition-colors" />
|
|
)}
|
|
</button>
|
|
|
|
<Button
|
|
size="sm"
|
|
variant="secondary"
|
|
onClick={() => copy("link", link)}
|
|
title="Copier le lien d'invitation"
|
|
>
|
|
{copied === "link" ? <Check className="text-green-500" /> : <Link2 />}
|
|
{copied === "link" ? "Copié" : "Lien"}
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|