diff --git a/packages/frontend/src/components/gamePage/leftSection/MainDisplay.tsx b/packages/frontend/src/components/gamePage/leftSection/MainDisplay.tsx
index fdb6ad09..a1818cad 100644
--- a/packages/frontend/src/components/gamePage/leftSection/MainDisplay.tsx
+++ b/packages/frontend/src/components/gamePage/leftSection/MainDisplay.tsx
@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
-import { useRoomStore } from '@/states/store/roomStore';
+import { useRoomStore } from '@/store/roomStore';
import StartButton from './GameButtons/StartButton';
import ReadyButton from './GameButtons/ReadyButton';
import { GAME_PHASE, GamePhase } from '@/constants';
@@ -9,15 +9,15 @@ import { useGameSocket } from '@/hooks/useGameSocket';
import useGuessing from '@/hooks/useGuessing';
import useEnding from '@/hooks/useEnding';
import useVoteResult from '@/hooks/useVoteResult';
-import { useAuthStore } from '@/states/store/authStore';
+import { useAuthStore } from '@/store/authStore';
import Countdown from './Countdown';
import WordDisplay from './WordDisplay';
import Voting from './GamePhases/Voting';
import VoteResult from './GamePhases/VoteResult';
import EndingResult from './GamePhases/EndingResult';
-import { usePeerConnectionStore } from '@/states/store/peerConnectionStore';
+import { usePeerConnectionStore } from '@/store/peerConnectionStore';
import VideoStream from '@/components/gamePage/stream/VideoStream';
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
import { useSpeakingControl } from '@/hooks/useSpeakingControl';
export default function MainDisplay() {
diff --git a/packages/frontend/src/components/gamePage/leftSection/VideoFeed.tsx b/packages/frontend/src/components/gamePage/leftSection/VideoFeed.tsx
index 31f042b2..9c9636c8 100644
--- a/packages/frontend/src/components/gamePage/leftSection/VideoFeed.tsx
+++ b/packages/frontend/src/components/gamePage/leftSection/VideoFeed.tsx
@@ -1,8 +1,8 @@
import { useRef, useEffect } from 'react';
import VideoStream from '@/components/gamePage/stream/VideoStream';
-import { useAuthStore } from '@/states/store/authStore';
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
-import { usePeerConnectionStore } from '@/states/store/peerConnectionStore';
+import { useAuthStore } from '@/store/authStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
+import { usePeerConnectionStore } from '@/store/peerConnectionStore';
import { useReadyStatus } from '@/hooks/useReadyStatus';
export default function VideoFeed() {
diff --git a/packages/frontend/src/components/gamePage/rightSection/ChatSection.tsx b/packages/frontend/src/components/gamePage/rightSection/ChatSection.tsx
index 4e3a5a9b..f1cb23a4 100644
--- a/packages/frontend/src/components/gamePage/rightSection/ChatSection.tsx
+++ b/packages/frontend/src/components/gamePage/rightSection/ChatSection.tsx
@@ -1,8 +1,8 @@
import React, { useState, useEffect, useRef } from 'react';
import { useParams } from 'react-router-dom';
import { useChatSocket } from '@/hooks/useChatSocket';
-import { useAuthStore } from '@/states/store/authStore';
-import { useChatStore } from '@/states/store/chatStore';
+import { useAuthStore } from '@/store/authStore';
+import { useChatStore } from '@/store/chatStore';
import { ChatType } from '@/constants/chatState';
import ArrowDownIcon from '@/assets/images/ArrowDownIcon.svg?react';
diff --git a/packages/frontend/src/components/gamePage/rightSection/LeaveButton.tsx b/packages/frontend/src/components/gamePage/rightSection/LeaveButton.tsx
index 7d0071b8..b19066b8 100644
--- a/packages/frontend/src/components/gamePage/rightSection/LeaveButton.tsx
+++ b/packages/frontend/src/components/gamePage/rightSection/LeaveButton.tsx
@@ -1,16 +1,20 @@
import Leave from '@/assets/images/Leave.svg?react';
import { useNavigate } from 'react-router-dom';
-import { useSocketStore } from '@/states/store/socketStore';
-import { useChatStore } from '@/states/store/chatStore';
-import { useRoomStore } from '@/states/store/roomStore';
-import { useSignalingSocketStore } from '@/states/store/signalingSocketStore';
+import { useSocketStore } from '@/store/socketStore';
+import { useChatStore } from '@/store/chatStore';
+import { useRoomStore } from '@/store/roomStore';
+import { useSignalingSocketStore } from '@/store/signalingSocketStore';
+import { useState } from 'react';
+import LeaveConfirmModal from './LeaveConfirmModal';
export default function LeaveButton() {
+ const [showModal, setShowModal] = useState(false);
const navigate = useNavigate();
const socket = useSocketStore((state) => state.socket);
const setChatHistory = useChatStore((state) => state.setChatHistory);
const setRoomData = useRoomStore((state) => state.setRoomData);
const signalingSocket = useSignalingSocketStore((state) => state.signalingSocket);
+
function handleLeave() {
if (!socket || !signalingSocket) return;
socket.emit('leave_room');
@@ -19,13 +23,20 @@ export default function LeaveButton() {
setRoomData(null, false, false);
navigate('/lobby');
}
+
return (
-
+ <>
+
+
+ {showModal && (
+ setShowModal(false)} />
+ )}
+ >
);
}
diff --git a/packages/frontend/src/components/gamePage/rightSection/LeaveConfirmModal.tsx b/packages/frontend/src/components/gamePage/rightSection/LeaveConfirmModal.tsx
new file mode 100644
index 00000000..fd92ba16
--- /dev/null
+++ b/packages/frontend/src/components/gamePage/rightSection/LeaveConfirmModal.tsx
@@ -0,0 +1,34 @@
+import ReactDOM from 'react-dom';
+
+interface ILeaveConfirmModalProps {
+ onConfirm: () => void;
+ onClose: () => void;
+}
+
+export default function LeaveConfirmModal({ onConfirm, onClose }: ILeaveConfirmModalProps) {
+ const modalContent = (
+
+
+
+ 게임을 나가시겠습니까?
+
+
+
+
+
+
+
+ );
+
+ return ReactDOM.createPortal(modalContent, document.getElementById('portal-root') as HTMLElement);
+}
diff --git a/packages/frontend/src/components/gamePage/stream/CameraSettingButton.tsx b/packages/frontend/src/components/gamePage/stream/CameraSettingButton.tsx
index 73b18a7b..7bf8fb72 100644
--- a/packages/frontend/src/components/gamePage/stream/CameraSettingButton.tsx
+++ b/packages/frontend/src/components/gamePage/stream/CameraSettingButton.tsx
@@ -1,7 +1,7 @@
import { useState, useEffect } from 'react';
import CameraOn from '@/assets/images/CameraOn.svg?react';
import CameraOff from '@/assets/images/CameraOff.svg?react';
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
export default function CameraSettingButton({ iconColor }: { iconColor: string }) {
const { localStream } = useLocalStreamStore();
diff --git a/packages/frontend/src/components/gamePage/stream/MikeSettingButton.tsx b/packages/frontend/src/components/gamePage/stream/MikeSettingButton.tsx
index dd08f183..430dffba 100644
--- a/packages/frontend/src/components/gamePage/stream/MikeSettingButton.tsx
+++ b/packages/frontend/src/components/gamePage/stream/MikeSettingButton.tsx
@@ -1,7 +1,7 @@
import { useState, useEffect } from 'react';
import MikeOn from '@/assets/images/MikeOn.svg?react';
import MikeOff from '@/assets/images/MikeOff.svg?react';
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
export default function MikeSettingButton({ iconColor }: { iconColor: string }) {
const { localStream } = useLocalStreamStore();
diff --git a/packages/frontend/src/components/landingPage/GuestLoginButton.tsx b/packages/frontend/src/components/landingPage/GuestLoginButton.tsx
index 268a1a8a..51b38b76 100644
--- a/packages/frontend/src/components/landingPage/GuestLoginButton.tsx
+++ b/packages/frontend/src/components/landingPage/GuestLoginButton.tsx
@@ -3,9 +3,9 @@ import Button from '@/components/common/Button';
import NicknameModal from './NicknameModal';
import { useNavigate } from 'react-router-dom';
import { getGuestLogin } from '@/apis/login';
-import { useAuthStore } from '@/states/store/authStore';
-import { useSocketStore } from '@/states/store/socketStore';
-import { useSignalingSocketStore } from '@/states/store/signalingSocketStore';
+import { useAuthStore } from '@/store/authStore';
+import { useSocketStore } from '@/store/socketStore';
+import { useSignalingSocketStore } from '@/store/signalingSocketStore';
export default function GuestLoginButton() {
const navigate = useNavigate();
diff --git a/packages/frontend/src/components/lobbyPage/VideoAudioTestModal.tsx b/packages/frontend/src/components/lobbyPage/VideoAudioTestModal.tsx
index 6a957d5c..5913699e 100644
--- a/packages/frontend/src/components/lobbyPage/VideoAudioTestModal.tsx
+++ b/packages/frontend/src/components/lobbyPage/VideoAudioTestModal.tsx
@@ -1,5 +1,5 @@
import VideoStream from '@/components/gamePage/stream/VideoStream';
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
import CameraSettingButton from '@/components/gamePage/stream/CameraSettingButton';
import MikeSettingButton from '@/components/gamePage/stream/MikeSettingButton';
diff --git a/packages/frontend/src/hooks/useChatSocket.ts b/packages/frontend/src/hooks/useChatSocket.ts
index 3aac9949..7f10a906 100644
--- a/packages/frontend/src/hooks/useChatSocket.ts
+++ b/packages/frontend/src/hooks/useChatSocket.ts
@@ -1,9 +1,9 @@
import { useEffect } from 'react';
-import { useChatStore } from '@/states/store/chatStore';
-import { useSocketStore } from '@/states/store/socketStore';
-import { useRoomStore } from '@/states/store/roomStore';
+import { useChatStore } from '@/store/chatStore';
+import { useSocketStore } from '@/store/socketStore';
+import { useRoomStore } from '@/store/roomStore';
import { ChatType } from '@/constants/chatState';
-import { useAuthStore } from '@/states/store/authStore';
+import { useAuthStore } from '@/store/authStore';
interface IChatEntry {
userId: string;
diff --git a/packages/frontend/src/hooks/useCreateRoom.ts b/packages/frontend/src/hooks/useCreateRoom.ts
index ccd4d920..bd551cf6 100644
--- a/packages/frontend/src/hooks/useCreateRoom.ts
+++ b/packages/frontend/src/hooks/useCreateRoom.ts
@@ -1,8 +1,8 @@
import { useNavigate } from 'react-router-dom';
-import { useAuthStore } from '@/states/store/authStore';
-import { useRoomStore } from '@/states/store/roomStore';
-import { useSocketStore } from '@/states/store/socketStore';
-import { useSignalingSocketStore } from '@/states/store/signalingSocketStore';
+import { useAuthStore } from '@/store/authStore';
+import { useRoomStore } from '@/store/roomStore';
+import { useSocketStore } from '@/store/socketStore';
+import { useSignalingSocketStore } from '@/store/signalingSocketStore';
export default function useCreateRoom() {
const navigate = useNavigate();
diff --git a/packages/frontend/src/hooks/useEnding.ts b/packages/frontend/src/hooks/useEnding.ts
index afb4f307..a9cd2f16 100644
--- a/packages/frontend/src/hooks/useEnding.ts
+++ b/packages/frontend/src/hooks/useEnding.ts
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
-import { useSocketStore } from '@/states/store/socketStore';
+import { useSocketStore } from '@/store/socketStore';
import { GAME_PHASE, GamePhase } from '@/constants';
interface IEndingResult {
diff --git a/packages/frontend/src/hooks/useGameSocket.ts b/packages/frontend/src/hooks/useGameSocket.ts
index be2e2cc8..637290b5 100644
--- a/packages/frontend/src/hooks/useGameSocket.ts
+++ b/packages/frontend/src/hooks/useGameSocket.ts
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
-import { useSocketStore } from '@/states/store/socketStore';
-import { useRoomStore } from '@/states/store/roomStore';
+import { useSocketStore } from '@/store/socketStore';
+import { useRoomStore } from '@/store/roomStore';
import { GAME_PHASE, GamePhase } from '@/constants';
interface IReadyUsers {
diff --git a/packages/frontend/src/hooks/useGuessing.ts b/packages/frontend/src/hooks/useGuessing.ts
index 3571b3b3..539656f1 100644
--- a/packages/frontend/src/hooks/useGuessing.ts
+++ b/packages/frontend/src/hooks/useGuessing.ts
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
-import { useSocketStore } from '@/states/store/socketStore';
+import { useSocketStore } from '@/store/socketStore';
import { GAME_PHASE, GamePhase } from '@/constants';
export default function useGuessing(isPinoco: boolean, setGamePhase: (phase: GamePhase) => void) {
diff --git a/packages/frontend/src/hooks/useJoinRoom.ts b/packages/frontend/src/hooks/useJoinRoom.ts
index ebea5b05..5f553960 100644
--- a/packages/frontend/src/hooks/useJoinRoom.ts
+++ b/packages/frontend/src/hooks/useJoinRoom.ts
@@ -1,8 +1,8 @@
import { useNavigate } from 'react-router-dom';
-import { useAuthStore } from '@/states/store/authStore';
-import { useRoomStore } from '@/states/store/roomStore';
-import { useSocketStore } from '@/states/store/socketStore';
-import { useSignalingSocketStore } from '@/states/store/signalingSocketStore';
+import { useAuthStore } from '@/store/authStore';
+import { useRoomStore } from '@/store/roomStore';
+import { useSocketStore } from '@/store/socketStore';
+import { useSignalingSocketStore } from '@/store/signalingSocketStore';
export default function useJoinRoom() {
const navigate = useNavigate();
diff --git a/packages/frontend/src/hooks/useSpeakingControl.ts b/packages/frontend/src/hooks/useSpeakingControl.ts
index e7252778..e7a2d8ec 100644
--- a/packages/frontend/src/hooks/useSpeakingControl.ts
+++ b/packages/frontend/src/hooks/useSpeakingControl.ts
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
-import { useSocketStore } from '@/states/store/socketStore';
+import { useSocketStore } from '@/store/socketStore';
export const useSpeakingControl = (currentSpeaker: string | null, userId: string | null) => {
const socket = useSocketStore((state) => state.socket);
diff --git a/packages/frontend/src/hooks/useVoteResult.ts b/packages/frontend/src/hooks/useVoteResult.ts
index 4c7637a0..86324f0d 100644
--- a/packages/frontend/src/hooks/useVoteResult.ts
+++ b/packages/frontend/src/hooks/useVoteResult.ts
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
-import { useSocketStore } from '@/states/store/socketStore';
+import { useSocketStore } from '@/store/socketStore';
import { GAME_PHASE, GamePhase } from '@/constants';
-import { useRoomStore } from '@/states/store/roomStore';
+import { useRoomStore } from '@/store/roomStore';
interface IVoteResult {
voteResult: Record;
diff --git a/packages/frontend/src/pages/gamePage/index.tsx b/packages/frontend/src/pages/gamePage/index.tsx
index bb3cd7e8..184e5c12 100644
--- a/packages/frontend/src/pages/gamePage/index.tsx
+++ b/packages/frontend/src/pages/gamePage/index.tsx
@@ -4,8 +4,8 @@ import LeftGameSection from '@/components/gamePage/leftSection/LeftGameSection';
import RightGameSection from '@/components/gamePage/rightSection/RightGameSection';
import Header from '@/components/layout/Header';
import GameManual from '@/components/gamePage/GameManual';
-import { useSocketStore } from '@/states/store/socketStore';
-import { useRoomStore } from '@/states/store/roomStore';
+import { useSocketStore } from '@/store/socketStore';
+import { useRoomStore } from '@/store/roomStore';
export default function GamePage() {
const { socket } = useSocketStore();
diff --git a/packages/frontend/src/pages/landingPage/index.tsx b/packages/frontend/src/pages/landingPage/index.tsx
index eff2af9f..b23a7e30 100644
--- a/packages/frontend/src/pages/landingPage/index.tsx
+++ b/packages/frontend/src/pages/landingPage/index.tsx
@@ -1,7 +1,7 @@
import GuestLoginButton from '@/components/landingPage/GuestLoginButton';
import BackgroundImage from '@/components/layout/BackgroundImage';
import MainLogo from '@/assets/images/MainLogo.svg?react';
-import { useSocketStore } from '@/states/store/socketStore';
+import { useSocketStore } from '@/store/socketStore';
export default function LandingPage() {
const { socket } = useSocketStore();
diff --git a/packages/frontend/src/pages/lobbyPage/index.tsx b/packages/frontend/src/pages/lobbyPage/index.tsx
index 6d33354b..83c0c0bf 100644
--- a/packages/frontend/src/pages/lobbyPage/index.tsx
+++ b/packages/frontend/src/pages/lobbyPage/index.tsx
@@ -1,14 +1,14 @@
import { useEffect } from 'react';
-import { useSocketStore } from '@/states/store/socketStore';
+import { useSocketStore } from '@/store/socketStore';
import BackgroundImage from '@/components/layout/BackgroundImage';
import MainLogo from '@/assets/images/MainLogo.svg?react';
import RoomCreationButton from '@/components/lobbyPage/RoomCreationButton';
import RoomJoinButton from '@/components/lobbyPage/RoomJoinButton';
import VideoAudioTestButton from '@/components/lobbyPage/VideoAudioTestButton';
import Header from '@/components/layout/Header';
-import { useRoomStore } from '@/states/store/roomStore';
-import { useChatStore } from '@/states/store/chatStore';
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
+import { useRoomStore } from '@/store/roomStore';
+import { useChatStore } from '@/store/chatStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
import { getVideoStream } from '@/utils/videoStreamUtils';
export default function LobbyPage() {
diff --git a/packages/frontend/src/states/mutations/index.tsx b/packages/frontend/src/states/mutations/index.tsx
deleted file mode 100644
index cb0ff5c3..00000000
--- a/packages/frontend/src/states/mutations/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export {};
diff --git a/packages/frontend/src/states/queries/index.tsx b/packages/frontend/src/states/queries/index.tsx
deleted file mode 100644
index cb0ff5c3..00000000
--- a/packages/frontend/src/states/queries/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export {};
diff --git a/packages/frontend/src/states/store/authStore.ts b/packages/frontend/src/store/authStore.ts
similarity index 100%
rename from packages/frontend/src/states/store/authStore.ts
rename to packages/frontend/src/store/authStore.ts
diff --git a/packages/frontend/src/states/store/chatStore.ts b/packages/frontend/src/store/chatStore.ts
similarity index 100%
rename from packages/frontend/src/states/store/chatStore.ts
rename to packages/frontend/src/store/chatStore.ts
diff --git a/packages/frontend/src/states/store/localStreamStore.ts b/packages/frontend/src/store/localStreamStore.ts
similarity index 100%
rename from packages/frontend/src/states/store/localStreamStore.ts
rename to packages/frontend/src/store/localStreamStore.ts
diff --git a/packages/frontend/src/states/store/peerConnectionStore.ts b/packages/frontend/src/store/peerConnectionStore.ts
similarity index 100%
rename from packages/frontend/src/states/store/peerConnectionStore.ts
rename to packages/frontend/src/store/peerConnectionStore.ts
diff --git a/packages/frontend/src/states/store/roomStore.ts b/packages/frontend/src/store/roomStore.ts
similarity index 100%
rename from packages/frontend/src/states/store/roomStore.ts
rename to packages/frontend/src/store/roomStore.ts
diff --git a/packages/frontend/src/states/store/signalingSocketStore.ts b/packages/frontend/src/store/signalingSocketStore.ts
similarity index 97%
rename from packages/frontend/src/states/store/signalingSocketStore.ts
rename to packages/frontend/src/store/signalingSocketStore.ts
index 7b1d4d4e..1b0e105c 100644
--- a/packages/frontend/src/states/store/signalingSocketStore.ts
+++ b/packages/frontend/src/store/signalingSocketStore.ts
@@ -1,7 +1,7 @@
import { create } from 'zustand';
import { Socket, io } from 'socket.io-client';
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
-import { usePeerConnectionStore } from '@/states/store/peerConnectionStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
+import { usePeerConnectionStore } from '@/store/peerConnectionStore';
import { getVideoStream } from '@/utils/videoStreamUtils';
interface ISignalingSocketStore {
diff --git a/packages/frontend/src/states/store/socketStore.ts b/packages/frontend/src/store/socketStore.ts
similarity index 100%
rename from packages/frontend/src/states/store/socketStore.ts
rename to packages/frontend/src/store/socketStore.ts
diff --git a/packages/frontend/src/utils/videoStreamUtils.ts b/packages/frontend/src/utils/videoStreamUtils.ts
index 6ac1d897..fefe750f 100644
--- a/packages/frontend/src/utils/videoStreamUtils.ts
+++ b/packages/frontend/src/utils/videoStreamUtils.ts
@@ -1,4 +1,4 @@
-import { useLocalStreamStore } from '@/states/store/localStreamStore';
+import { useLocalStreamStore } from '@/store/localStreamStore';
export async function getVideoStream() {
const videoConfig = {