From b29c467766ff2d0b6c00c081cdf06b004f7af43c Mon Sep 17 00:00:00 2001 From: Michess Date: Tue, 14 Apr 2026 13:16:00 +0200 Subject: [PATCH] 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 --- client/src/app/correspondence/[code]/page.tsx | 2 + client/src/app/tournament/[code]/page.tsx | 6 +- client/src/components/InviteFriendsModal.tsx | 90 +++++++++++++++++++ client/src/components/game/GamePage.tsx | 6 ++ 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 client/src/components/InviteFriendsModal.tsx diff --git a/client/src/app/correspondence/[code]/page.tsx b/client/src/app/correspondence/[code]/page.tsx index 2cf3389..e398990 100644 --- a/client/src/app/correspondence/[code]/page.tsx +++ b/client/src/app/correspondence/[code]/page.tsx @@ -14,6 +14,7 @@ import { useCallback, useEffect, useState } from "react"; import { Chessboard } from "react-chessboard"; import type { Square } from "chess.js"; import { APP_URL } from "@/config"; +import InviteFriendsModal from "@/components/InviteFriendsModal"; export default function CorrespondenceGamePage() { const { user } = useSession(); @@ -194,6 +195,7 @@ export default function CorrespondenceGamePage() { > {copied ? "Kopiert!" : `${APP_URL.replace(/^https?:\/\//, "")}/correspondence/${code}`} + {!isPlayer && user?.id && ( + + {open && ( + +
+ +

{label}

+ {loading ? ( +
+ +
+ ) : friends.length === 0 ? ( +

+ Keine Freunde gefunden. Füge zuerst Freunde hinzu. +

+ ) : ( +
+ {friends.map((f) => ( +
+ {f.friend_name} + +
+ ))} +
+ )} +
+
setOpen(false)} /> +
+ )} + + ); +} diff --git a/client/src/components/game/GamePage.tsx b/client/src/components/game/GamePage.tsx index f794a76..5439261 100644 --- a/client/src/components/game/GamePage.tsx +++ b/client/src/components/game/GamePage.tsx @@ -23,6 +23,7 @@ import type { ClearPremoves } from "react-chessboard"; import { Chessboard } from "react-chessboard"; import { API_URL, APP_URL } from "@/config"; +import InviteFriendsModal from "@/components/InviteFriendsModal"; import { io } from "socket.io-client"; import { lobbyReducer, squareReducer } from "./reducers"; @@ -654,6 +655,11 @@ export default function GamePage({ initialLobby }: { initialLobby: Game }) { + {!lobby.endReason && ( +
+ +
+ )}
{getMoveListHtml()}