nerdware/apps/web/src/components/room-code.tsx
AyoubBenziza 1071a59b68 feat: pick pseudo inside the room + shareable invite link
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>
2026-06-10 15:32:24 +02:00

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>
)
}