feat: add friend invite modal to all game modes

- New InviteFriendsModal component: fetches friends list, sends game
  invite via notification socket with per-friend sent confirmation
- Multiplayer (GamePage): invite button below copy link, hidden after game ends
- Correspondence: invite button in waiting-for-opponent card
- Tournament: invite button for joined players while status is waiting
- Invite links use mode-prefixed codes (correspondence/XYZ, tournament/XYZ)
  so notification "Beitreten" button navigates to the correct page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Michess
2026-04-14 13:16:00 +02:00
parent 50ef567a1a
commit b29c467766
4 changed files with 103 additions and 1 deletions

View File

@@ -1,5 +1,6 @@
"use client";
import InviteFriendsModal from "@/components/InviteFriendsModal";
import { useSession } from "@/context/session";
import { fetchTournament, joinTournament, startTournament } from "@/lib/tournament";
import type { Tournament, TournamentRound } from "@michess/types";
@@ -109,7 +110,7 @@ export default function TournamentDetailPage() {
)}
</div>
</div>
<div className="flex gap-2">
<div className="flex gap-2 flex-wrap">
{tournament.status === "waiting" && user?.id && !isJoined && (
<button
className={"btn btn-secondary btn-sm" + (actionLoading ? " loading" : "")}
@@ -119,6 +120,9 @@ export default function TournamentDetailPage() {
Beitreten
</button>
)}
{tournament.status === "waiting" && isJoined && (
<InviteFriendsModal gameCode={`tournament/${code}`} label="Freunde einladen" />
)}
{canStart && (
<button
className={"btn btn-primary btn-sm" + (actionLoading ? " loading" : "")}