From cbd829ac74dd16fd4d6ff0c4eb971e4f261940bf Mon Sep 17 00:00:00 2001 From: Yonghun Date: Wed, 15 Nov 2023 22:11:00 +0900 Subject: [PATCH 1/4] Feat: main --- src/components/Main/GameCard/index.tsx | 56 +++++++- src/components/Main/GameLists/index.tsx | 166 +++++++++++++++++++++--- 2 files changed, 199 insertions(+), 23 deletions(-) diff --git a/src/components/Main/GameCard/index.tsx b/src/components/Main/GameCard/index.tsx index 217f35b9..273543dc 100644 --- a/src/components/Main/GameCard/index.tsx +++ b/src/components/Main/GameCard/index.tsx @@ -10,6 +10,11 @@ import { Text, } from "@chakra-ui/react"; import { DocumentData } from "firebase/firestore"; +import { useNavigate } from "react-router-dom"; +import { userState } from "../../../recoil/atoms/userState"; +import { useRecoilValue } from "recoil"; +import useFetch from "../../../hooks/useFetch"; +import useFireFetch from "../../../hooks/useFireFetch"; interface Game { name: string; @@ -21,12 +26,58 @@ interface Game { id: string; } +interface ChatRoom { + name: string; + users: string[]; + isPrivate?: boolean; + num?: number; + bg?: string; + status?: string; + id: string; +} + +interface Socket { + on(event: string, callback: any): void; + emit(event: string, data: any): void; +} + interface Props { game: Game | DocumentData; + socket: Socket; } -const GameCard = ({ game: { id, bg, name, num, status, users } }: Props) => { - console.log(id); +const GameCard = ({ + game: { id, bg, name, num, status, users }, + socket, +}: Props) => { + const fireFetch = useFireFetch(); + const navigate = useNavigate(); + const user = useRecoilValue(userState); + + // 입장 요청 선언 + const join = useFetch({ + url: "https://fastcampus-chat.net/chat/participate", + method: "PATCH", + data: { + chatId: id, + }, + start: false, + }); + + // // 게임 정보 조회 + // const gameInfo = useFetch({ + // url: `https://fastcampus-chat.net/chat/only?chatId=${id}`, + // method: "GET", + // start: true, + // }); + + // 게임 입장 함수 + const joinGame = () => { + socket.emit("message-to-server", `${user.id}:${id}:!#%&(`); + join.refresh(); + fireFetch.updateData("game", id, { users: [...users, user.id] }); + navigate(`/game?gameId=${id}`); + }; return ( { bg="blackAlpha.800" color="white" _hover={{ bg: "blackAlpha.900" }} + onClick={joinGame} > 입장하기 diff --git a/src/components/Main/GameLists/index.tsx b/src/components/Main/GameLists/index.tsx index 157970fd..41aa765e 100644 --- a/src/components/Main/GameLists/index.tsx +++ b/src/components/Main/GameLists/index.tsx @@ -7,21 +7,23 @@ import { Image, Text, } from "@chakra-ui/react"; -import { IoSettingsOutline } from "react-icons/io5"; -import { BiBell } from "react-icons/bi"; -import { useEffect, useState } from "react"; -import useFetch from "../../../hooks/useFetch"; -import useFireFetch from "../../../hooks/useFireFetch"; import { DocumentData } from "firebase/firestore"; -import GameCard from "../GameCard"; +import { useEffect, useState } from "react"; +import { BiBell } from "react-icons/bi"; +import { IoSettingsOutline } from "react-icons/io5"; import { useNavigate } from "react-router-dom"; import { useRecoilValue } from "recoil"; import UserConfigModal from "../../../components/Main/UserConfigModal"; import { useAuth } from "../../../hooks/useAuth"; +import useFetch from "../../../hooks/useFetch"; +import useFireFetch from "../../../hooks/useFireFetch"; import { authState } from "../../../recoil/atoms/authState"; -import { io } from "socket.io-client"; -import GameListChat from "../GameListsChat"; +import { userState } from "../../../recoil/atoms/userState"; +import connect from "../../../socket/socket"; +import ToastNotice from "../../common/ToastNotice"; import CreateGameModal from "../CreateGameModal"; +import GameCard from "../GameCard"; +import GameListChat from "../GameListsChat"; interface ResponseValue { accessToken: string; // 사용자 접근 토큰 @@ -69,34 +71,149 @@ interface GameRoom { id: string; } +interface MessageInfo { + id: string; + text: string; +} + type ChatResponseValue = { chats: Chat[] }; const GameLists = () => { + // 페이지 입장시 자동으로 해당 채팅방으로 입장 + useFetch({ + url: "https://fastcampus-chat.net/chat/participate", + method: "PATCH", + data: { + chatId: "9984747e-389a-4aef-9a8f-968dc86a44e4", + }, + start: true, + }); + + const fireFetch = useFireFetch(); + const navigate = useNavigate(); + const { isAuthenticated } = useRecoilValue(authState); + const user = useRecoilValue(userState); const { logout } = useAuth(); - const navigate = useNavigate(); + const [isUserConfigModalOpen, setIsUserConfigModalOpen] = useState(false); const [token, setToken] = useState(); const [gameLists, setGameLists] = useState<(GameRoom | DocumentData)[]>([]); + + // 메세지 데이터 + const [messages, setMessages] = useState([]); + + useEffect(() => { + console.log(messages); + }, [messages]); + + // 초대방 정보 데이터 + const [roomData, setRoomData] = useState({ + id: "", + name: "", + host: "", + bg: "", + users: [""], + }); + + // 팝업 데이터 + const [toastUser, setToastUser] = useState([""]); + + // 토스트 모달 + const [toast, setToast] = useState(false); const [modal, setModal] = useState(false); - const fireFetch = useFireFetch(); - const socket = io( - `https://fastcampus-chat.net/chat?chatId=9984747e-389a-4aef-9a8f-968dc86a44e4`, - { - extraHeaders: { - Authorization: `Bearer ${token?.accessToken}`, - serverId: "6603aca7", - }, - }, - ); + const socket = connect("9984747e-389a-4aef-9a8f-968dc86a44e4"); useEffect(() => { socket.on("message-to-client", (messageObject) => { - console.log(messageObject); + // 메시지 구분 + if (messageObject.text.slice(-5, -2) === "*&^") { + // 초대 상태 저장 + const usersArr = JSON.parse(messageObject.text); + const users = [...usersArr]; + users.pop(); + users.pop(); + const room = usersArr[usersArr.length - 2]; + + const copy = [...gameLists]; + copy.push(room); + + setGameLists(copy); + setToastUser(users); + setRoomData(room); + } else if (messageObject.text.endsWith("!#%&(")) { + // 유저 입장 구분 + const arr = messageObject.text.split(":"); + const gameId = arr[1]; + const userData = arr[0]; + + const copy = [...gameLists]; + const index = copy.findIndex((value) => value.id === gameId); + + copy[index].users = [...copy[index].users, userData]; + + setGameLists(copy); + } else if (messageObject.text.endsWith(")*^$@")) { + // 유저 퇴장 구분 + const arr = messageObject.text.split(":"); + const gameId = arr[1]; + const userData = arr[0]; + + const copy = [...gameLists]; + const index = copy.findIndex((value) => value.id === gameId); + + copy[index].users = copy[index].users.filter( + (value: any) => value !== userData, + ); + + setGameLists(copy); + } else if (messageObject.text.endsWith("@#$%")) { + } else { + // 메시지 데이터, 작성 유저 상태 저장 + const message = { + id: messageObject.userId, + text: messageObject.text, + }; + + console.log(message); + setMessages((prev) => [...prev, message]); + } + }); + + // 채팅 기록 확인 + socket.on("messages-to-client", (messagesObject) => { + console.log(messagesObject); + }); + + // 유저 join확인 + socket.on("join", (users) => { + console.log(users); }); + + // 유저 leave확인 + socket.on("leave", (users) => { + console.log(users); + }); + + return () => { + socket.off("message-to-client"); + socket.off("join"); + socket.off("leave"); + }; }, [socket]); + //팝업 변화 감지 + useEffect(() => { + if (toastUser[0] !== "" && user.id) { + if (toastUser.includes(user.id)) { + console.log(roomData); + setToast(true); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [toastUser]); + const { result: userInfo }: FetchResultUser = useFetch({ url: `https://fastcampus-chat.net/user?userId=${token?.id}`, method: "GET", @@ -188,7 +305,7 @@ const GameLists = () => { {gameLists.map((game) => ( - + ))} @@ -281,6 +398,13 @@ const GameLists = () => { {modal ? : null} + {toast && roomData ? ( + + ) : null} ); } From ed63b34508ccc46d4d72d0226cffc26b21752171 Mon Sep 17 00:00:00 2001 From: Yonghun Date: Wed, 15 Nov 2023 22:34:36 +0900 Subject: [PATCH 2/4] Fix: type error --- src/components/Main/GameCard/index.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/components/Main/GameCard/index.tsx b/src/components/Main/GameCard/index.tsx index 273543dc..2315b0a8 100644 --- a/src/components/Main/GameCard/index.tsx +++ b/src/components/Main/GameCard/index.tsx @@ -26,16 +26,6 @@ interface Game { id: string; } -interface ChatRoom { - name: string; - users: string[]; - isPrivate?: boolean; - num?: number; - bg?: string; - status?: string; - id: string; -} - interface Socket { on(event: string, callback: any): void; emit(event: string, data: any): void; From d18f24038922ed9a9278698f25e7459cbbad4a6b Mon Sep 17 00:00:00 2001 From: Yonghun Date: Wed, 15 Nov 2023 22:36:42 +0900 Subject: [PATCH 3/4] Fix: game status change --- src/components/Main/GameLists/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/Main/GameLists/index.tsx b/src/components/Main/GameLists/index.tsx index 5199fc4c..27f48dd0 100644 --- a/src/components/Main/GameLists/index.tsx +++ b/src/components/Main/GameLists/index.tsx @@ -181,6 +181,7 @@ const GameLists = () => { setGameLists(copy); } else if (messageObject.text.endsWith("@#$%")) { + console.log("대기중"); } else { // 메시지 데이터, 작성 유저 상태 저장 const message = { @@ -213,6 +214,7 @@ const GameLists = () => { socket.off("join"); socket.off("leave"); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [socket]); //팝업 변화 감지 From e7b7c27494eedd049dfc0c1a2de2a48ce9e249fd Mon Sep 17 00:00:00 2001 From: Yonghun Date: Wed, 15 Nov 2023 23:31:02 +0900 Subject: [PATCH 4/4] Feat: Change the number and status of game in real time --- src/components/Game/GameStart/index.tsx | 6 +++++- src/components/Main/GameLists/index.tsx | 20 ++++++++++++++++++-- src/pages/Game/index.tsx | 3 ++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/components/Game/GameStart/index.tsx b/src/components/Game/GameStart/index.tsx index 51676b9e..c02ea600 100644 --- a/src/components/Game/GameStart/index.tsx +++ b/src/components/Game/GameStart/index.tsx @@ -19,6 +19,7 @@ import useFireFetch from "../../../hooks/useFireFetch"; interface GameStartProps { gameId: string; socket: Socket; + socketMain: Socket; status: string; users: string[]; host: string; @@ -32,6 +33,7 @@ interface UserWithSort { const GameStart: React.FC = ({ gameId, socket, + socketMain, status, users, host, @@ -100,7 +102,7 @@ const GameStart: React.FC = ({ // 모든 클라이언트에게 게임 정보를 포함하는 이벤트 전송 socket.emit("message-to-server", gameInfo + "~!@##"); - + socketMain.emit("message-to-server", gameId + ":" + "~!@##"); // setShowStartModal(true); }; @@ -118,6 +120,8 @@ const GameStart: React.FC = ({ fireFetch.updateData("game", gameId as string, { votedFor: [] }); fireFetch.updateData("game", gameId as string, { status: "대기중" }); + socketMain.emit("message-to-server", gameId + ":" + "~!a%2@##"); + // setShowStartModal(false); }; diff --git a/src/components/Main/GameLists/index.tsx b/src/components/Main/GameLists/index.tsx index 27f48dd0..9166c95f 100644 --- a/src/components/Main/GameLists/index.tsx +++ b/src/components/Main/GameLists/index.tsx @@ -180,8 +180,24 @@ const GameLists = () => { ); setGameLists(copy); - } else if (messageObject.text.endsWith("@#$%")) { - console.log("대기중"); + } else if (messageObject.text.endsWith("~!@##")) { + const arr = messageObject.text.split(":"); + const gameId = arr[0]; + + const copy = [...gameLists]; + const index = copy.findIndex((value) => value.id === gameId); + + copy[index].status = "게임중"; + setGameLists(copy); + } else if (messageObject.text.endsWith("~!a%2@##")) { + const arr = messageObject.text.split(":"); + const gameId = arr[0]; + + const copy = [...gameLists]; + const index = copy.findIndex((value) => value.id === gameId); + + copy[index].status = "대기중"; + setGameLists(copy); } else { // 메시지 데이터, 작성 유저 상태 저장 const message = { diff --git a/src/pages/Game/index.tsx b/src/pages/Game/index.tsx index 6ac34e8a..3ac2fde9 100644 --- a/src/pages/Game/index.tsx +++ b/src/pages/Game/index.tsx @@ -80,7 +80,7 @@ const Game = () => { // 게임 소켓 서버 연결 const socket = connect(gameId as string); // 메인 소켓 서버 연결 (메인페이지 상태 변경 통신) - const socketMain = connect("b5275c5d-6561-413b-b828-5c66646a940f"); + const socketMain = connect("9984747e-389a-4aef-9a8f-968dc86a44e4"); const [category, setCategory] = useState(""); const [keyword, setKeyword] = useState(""); @@ -184,6 +184,7 @@ const Game = () => {