diff --git a/src/api/index.ts b/src/api/index.ts index c51c58e9..92de7f81 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -24,7 +24,7 @@ export const postJoin = async (joinData: JoinData) => { }; export const getAllUsers = async (accessToken: string) => { - const res = await client.get('/users', { + const res = await client.get('users', { headers: { Authorization: `Bearer ${accessToken}`, }, @@ -38,54 +38,39 @@ export const createGameRooms = async ( users: string[], isPrivate: boolean, ) => { - const authData = { - name, - users, - isPrivate, - }; - try { - const response = await axios.post(`${SERVER_URL}/chat`, authData, { + const res = await client.post( + `chat`, + { name: name, users: users, isPrivate: isPrivate }, + { headers: { - 'content-type': CONTENT_TYPE, - serverId: SERVER_ID, Authorization: `Bearer ${accessToken}`, }, - }); - return response.data; - } catch (error) { - console.log(error); - } + }, + ); + return res.data; }; export const getAllGameRooms = async (accessToken: string) => { - const response = await axios.get(`${SERVER_URL}/chat/all`, { + const res = await client.get(`chat/all`, { headers: { - 'content-type': CONTENT_TYPE, - serverId: SERVER_ID, Authorization: `Bearer ${accessToken}`, }, }); - return response.data; + return res.data; }; export const participateGameRoom = async ( chatId: string, accessToken: string, ) => { - const authData = { - chatId, - }; - const response = await axios.patch( - `${SERVER_URL}/chat/participate`, - authData, + const res = await client.patch( + `chat/participate`, + { chatId: chatId }, { headers: { - 'content-type': CONTENT_TYPE, - serverId: SERVER_ID, Authorization: `Bearer ${accessToken}`, }, }, ); - console.log(response.data); - return response.data; + return res.data; }; diff --git a/src/api/socket.ts b/src/api/socket.ts index de619507..fa1ac27a 100644 --- a/src/api/socket.ts +++ b/src/api/socket.ts @@ -1,11 +1,23 @@ -import { SERVER_ID, CONTENT_TYPE, SERVER_URL } from '../constant'; -import io from 'socket.io-client'; -export const socketLogin = (accessToken: string) => { +import { io } from 'socket.io-client'; +import { SERVER_URL, SERVER_ID } from '../constant'; + +export const loginSocket = (accessToken: string) => { const socket = io(`${SERVER_URL}/server`, { extraHeaders: { Authorization: `Bearer ${accessToken}`, serverId: SERVER_ID, }, }); + socket.on('connect', () => { + socket.emit('users-server'); + }); + socket.on('users-server-to-client', (data) => { + console.log('Received users from server:', data); + }); + + socket.on('message-to-client', (messageObject) => { + const usersArr = messageObject.users; + }); + return socket; }; diff --git a/src/components/layout/checkGameRoom.tsx b/src/components/layout/checkGameRoom.tsx index 55eda2e8..97b7902b 100644 --- a/src/components/layout/checkGameRoom.tsx +++ b/src/components/layout/checkGameRoom.tsx @@ -4,8 +4,10 @@ import { allRoomState } from '../../states/atom'; import { getAllGameRooms, participateGameRoom } from '../../api'; import { useNavigate } from 'react-router-dom'; +const POLLING_INTERVAL = 30000; + const CheckGameRoom = () => { - const token: any = localStorage.getItem('jwt'); + const token: any = localStorage.getItem('accessToken'); const navigate = useNavigate(); const [allRooms, setAllRooms] = useRecoilState(allRoomState); const fetchData = async () => { @@ -19,7 +21,13 @@ const CheckGameRoom = () => { useEffect(() => { fetchData(); - }, [allRooms.length]); + const pollingId = setInterval(() => { + fetchData(); + }, POLLING_INTERVAL); + return () => { + clearInterval(pollingId); + }; + }, [fetchData, setAllRooms]); if (allRooms.length === 0) { return
No rooms available or an error occurred.
; diff --git a/src/components/layout/offlineUserList.tsx b/src/components/layout/offlineUserList.tsx new file mode 100644 index 00000000..00d32ac8 --- /dev/null +++ b/src/components/layout/offlineUserList.tsx @@ -0,0 +1,30 @@ +import { useRecoilValue } from 'recoil'; +import { allUserState, onlineUserState } from '../../states/atom'; +import { useEffect, useState } from 'react'; + +const OfflineUserList = () => { + const onLine = useRecoilValue(onlineUserState); + const all = useRecoilValue(allUserState); + const onlineUsers = onLine.users || []; + const differentNames = all.filter((element) => { + return !onlineUsers.includes(element.name); + }); + + const [offlineUsers, setOfflineUsers] = useState([]); + + useEffect(() => { + const offlineUserNames = differentNames.map((element) => element.name); + if (JSON.stringify(offlineUserNames) !== JSON.stringify(offlineUsers)) { + setOfflineUsers(offlineUserNames); + } + }, [differentNames, offlineUsers]); + + return ( +
+
OfflineUserList
+
Users: {offlineUsers.join(', ')}
+
+ ); +}; + +export default OfflineUserList; diff --git a/src/components/layout/onineUserList.tsx b/src/components/layout/onineUserList.tsx deleted file mode 100644 index 1942262c..00000000 --- a/src/components/layout/onineUserList.tsx +++ /dev/null @@ -1,41 +0,0 @@ -// import { } from '../../pages/login/userLogin'; - -// const OnlineUserList = async () => { -// const socket = sendingClient; -// if (socket) { -// socket.on('message-to-client', (messageObject: any) => { -// console.log(messageObject.data); -// }); -// } else { -// console.error( -// 'Socket is null. Socket connection might not be established yet.', -// ); -// } -// // const [allOnlineUsers, setAllOnlineUsers] = useRecoilState(onlineUserState); -// // const token: any = localStorage.getItem('jwt'); - -// // useEffect(() => { -// // const socket = socketLogin(token); - -// // const handleUsersUpdate = (responseData: any) => { -// // const usersArray = Array.isArray(responseData) ? responseData : []; -// // setAllOnlineUsers(usersArray); -// // }; - -// // socket.on('users-server-to-client', handleUsersUpdate); - -// // return () => { -// // socket.off('users-server-to-client', handleUsersUpdate); -// // }; -// // }, [setAllOnlineUsers, token]); - -// // console.log(allOnlineUsers); - -// return ( -// <> -//
1
-// -// ); -// }; - -// export default OnlineUserList; diff --git a/src/components/layout/onlineUserList.tsx b/src/components/layout/onlineUserList.tsx new file mode 100644 index 00000000..d9885c4c --- /dev/null +++ b/src/components/layout/onlineUserList.tsx @@ -0,0 +1,17 @@ +import { useRecoilValue } from 'recoil'; +import { onlineUserState } from '../../states/atom'; + +const OnlineUserList = () => { + const socket = useRecoilValue(onlineUserState); + + const users = socket.users || []; + + return ( +
+
OnlineUserList
+
Users: {users.join(', ')}
+
+ ); +}; + +export default OnlineUserList; diff --git a/src/components/layout/userList.tsx b/src/components/layout/userList.tsx index e1916193..a7d2a37f 100644 --- a/src/components/layout/userList.tsx +++ b/src/components/layout/userList.tsx @@ -1,29 +1,40 @@ import { useEffect } from 'react'; +import { getAllUsers } from '../../api'; import { useRecoilState } from 'recoil'; import { allUserState } from '../../states/atom'; -import { getAllUsers } from '../../api'; + +const POLLING_INTERVAL = 30000; const UserList = () => { const [allUsers, setAllUsers] = useRecoilState(allUserState); - // const [allRooms, setAllRooms] = useRecoilState(allRoomState); - const token: any = localStorage.getItem('jwt'); - // const allUsers = useRecoilValue(allUserState); - console.log(allUsers); - useEffect(() => { - async function fetchData() { - try { - const allUsersData = await getAllUsers(token); - setAllUsers(allUsersData); - } catch (error) { - console.error('데이터 가져오기 오류:', error); + + const fetchData = async () => { + try { + const token: any = localStorage.getItem('accessToken'); + const allUsersData = await getAllUsers(token); + if (JSON.stringify(allUsersData.data) !== JSON.stringify(allUsers)) { + setAllUsers(allUsersData.data); } + } catch (error) { + console.error('Error retrieving data:', error); } + }; + useEffect(() => { fetchData(); - }, []); + + const pollingId = setInterval(() => { + fetchData(); + }, POLLING_INTERVAL); + + return () => { + clearInterval(pollingId); + }; + }, [setAllUsers, fetchData]); return ( <> +
AllUserList
{allUsers.map((element, index) => (
{element.name}
))} diff --git a/src/pages/lobby/gameLobby.tsx b/src/pages/lobby/gameLobby.tsx index 051bc348..08723b59 100644 --- a/src/pages/lobby/gameLobby.tsx +++ b/src/pages/lobby/gameLobby.tsx @@ -1,12 +1,15 @@ import CreateGameRoom from '../../components/layout/createGameRoom'; import CheckGameRoom from '../../components/layout/checkGameRoom'; -// import OnlineUserList from '../../components/layout/onineUserList'; -// import UserList from '../../components/layout/userList'; +import OnlineUserList from '../../components/layout/onlineUserList'; +import UserList from '../../components/layout/userList'; +import OfflineUserList from '../../components/layout/offlineUserList'; +import { getAllUsers } from '../../api'; + const GameLobby = () => { const handleGetAllUsers = async (e: React.FormEvent) => { e.preventDefault(); - const token = localStorage.getItem('jwt'); + const token = localStorage.getItem('accessToken'); if (!token) { alert('인증 토큰이 없습니다. 로그인이 필요합니다.'); return; @@ -39,15 +42,16 @@ const GameLobby = () => { // } // } - // fetchData(); // }, []); return ( <> - {/* */} +

- {/* */} +

+ +


diff --git a/src/pages/login/userJoin.tsx b/src/pages/login/userJoin.tsx index 4451eb5a..2555c72b 100644 --- a/src/pages/login/userJoin.tsx +++ b/src/pages/login/userJoin.tsx @@ -106,7 +106,7 @@ const UserJoin = () => { const res = await postJoin(formData); console.log(res); alert('회원가입에 성공했습니다.'); - navigate('/lobby'); + navigate('/'); } catch (e: any) { if (e.message === 'Request failed with status code 401') { alert('중복된 아이디가 있습니다.'); diff --git a/src/pages/login/userLogin.tsx b/src/pages/login/userLogin.tsx index 80d290ee..2a580c78 100644 --- a/src/pages/login/userLogin.tsx +++ b/src/pages/login/userLogin.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; - import { Link as ReactRouterLink, useNavigate } from 'react-router-dom'; import { Center, @@ -14,13 +13,17 @@ import { } from '@chakra-ui/react'; import { postLogin } from '../../api/index'; +import { io } from 'socket.io-client'; +import { SERVER_ID, SERVER_URL } from '../../constant'; +import { useRecoilState } from 'recoil'; +import { onlineUserState } from '../../states/atom'; -const UserLogin = () => { +function UserLogin() { const navigate = useNavigate(); const [id, setId] = useState(''); const [password, setPassword] = useState(''); - const token: any = localStorage.getItem('jwt'); + const [onlineUsers, setOnlineUsers] = useRecoilState(onlineUserState); const handleLoginSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -28,10 +31,26 @@ const UserLogin = () => { const res = await postLogin(id, password); const { accessToken, refreshToken } = res.data; localStorage.setItem('accessToken', accessToken); - alert('로그인에 성공했습니다.'); + const token: any = localStorage.getItem('accessToken'); + const socket = io(`${SERVER_URL}/server`, { + extraHeaders: { + Authorization: `Bearer ${token}`, + serverId: SERVER_ID, + }, + }); + socket.on('connect', () => { + socket.emit('users-server'); + }); + socket.on('users-server-to-client', (data) => { + setOnlineUsers(data); + }); + + socket.on('message-to-client', (messageObject) => { + console.log(messageObject); + }); navigate('/lobby'); - } catch { - console.log('에러'); + } catch (error) { + console.log(error); } }; @@ -45,12 +64,7 @@ const UserLogin = () => { }}>
- mainImg + mainImg
@@ -105,6 +119,6 @@ const UserLogin = () => {
); -}; +} export default UserLogin; diff --git a/src/states/atom.ts b/src/states/atom.ts index 7c1fa863..211d1426 100644 --- a/src/states/atom.ts +++ b/src/states/atom.ts @@ -10,7 +10,7 @@ export const allRoomState = atom({ default: [], }); -export const onlineUserState = atom({ +export const onlineUserState = atom({ key: 'onlineUserState', default: [], });