Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 40 additions & 22 deletions src/api/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,52 @@ export const authInstance = axios.create({

authInstance.interceptors.request.use(
(config) => {
const token = localStorage.getItem("accessToken") || "";
const token = localStorage.getItem("accessToken");
if (token) {
config.headers["authorization"] = `${token}`;
config.headers.Authorization = token; // "Bearer ..." 형태로 저장돼 있다면 그대로 사용
}
return config;
},
(error) => {
console.error(error);
return Promise.reject(error);
},
);

// authInstance.interceptors.response.use(
// (response) => response,
// async (error) => {
// const originalRequest = error.config;
// if (error.response.status === 401 && !originalRequest._retry) {
// originalRequest._retry = true;
// try {
// const newAccessToken = await refreshToken();
// originalRequest.headers["Authorization"] = `${newAccessToken}`;
// return authInstance(originalRequest);
// } catch (refreshError) {
// localStorage.removeItem("accessToken");
// alert("로그인을 다시 해주세요");
// throw Promise.reject(refreshError);
// }
// }
// throw error;
// },
// );
authInstance.interceptors.response.use(
(response) => {
// 성공 응답은 그대로 반환
return response;
},
async (error) => {
const originalRequest = error.config;

// 401 && 아직 재시도 안했을 경우
if (
error.response &&
error.response.status === 401 &&
!originalRequest._retry
) {
originalRequest._retry = true;
try {
// Refresh Token으로 새 Access Token 발급
const refreshResponse = await authInstance.post("/auth/refresh");
const { accessToken } = refreshResponse.data;

// 로컬스토리지에 다시 저장
localStorage.setItem("accessToken", accessToken);

// 원래 요청 헤더에 갱신된 토큰 반영
originalRequest.headers.Authorization = accessToken;

// 원래 요청 재시도
return authInstance(originalRequest);
} catch (refreshError) {
// 재발급 실패: 로그인 페이지로 이동 등 처리
// localStorage.clear() 또는 특정 에러 처리
return Promise.reject(refreshError);
}
}

return Promise.reject(error);
},
);
19 changes: 12 additions & 7 deletions src/components/layout/gameRoomHeader/GameRoomHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import iconExit from "@assets/images/icon_close.svg";
import { NavLink, useParams } from "react-router-dom";
import { NavLink, useNavigate, useParams } from "react-router-dom";
import { Flex, StyledHeader, TextButton } from "./GameRoomHeaderStyle";
import { useOutRoomMutaion } from "../../../hooks/useMutation";

import { useSocketStore } from "../../../store/useSocketStore";

export default function GameRoomHeader() {
const params = useParams();
const roomId = Number(params.id);
const mutation = useOutRoomMutaion();

const onClickOut = (roomId: number) => {
mutation.mutate(roomId);
console.log("방나가기 성공asdfasdf");
const navigate = useNavigate();
const { socket } = useSocketStore();
const onClickOut = async (roomId: number) => {
if (!socket) {
return;
}
socket.emit("leaveRoom", { roomId });
navigate("/game");
};

return (
<>
<StyledHeader>
Expand Down
4 changes: 1 addition & 3 deletions src/components/ui/badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { IBadgeProps } from "./badge_props";
import * as S from "./badgeStyle";

export default function Badge({ playerNumber }: IBadgeProps) {
const status = playerNumber === 2 ? "playing" : "waiting...";

export default function Badge({ playerNumber, status }: IBadgeProps) {
return (
<S.Badge playerNumber={playerNumber} status={status}>
{status}
Expand Down
4 changes: 4 additions & 0 deletions src/components/ui/badge/badgeStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export const Badge = styled.div<IBadgeProps>`
return `
background: radial-gradient(120% 120% at 50% 100%, #FF5E5E 0%, #FFFFFF 100%);
`;
case "ready":
return `
background: radial-gradient(120% 120% at 50% 100%, #2571FF 0%, #FFFFFF 100%);
`;
}
}};
`;
2 changes: 1 addition & 1 deletion src/components/ui/badge/badge_props.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReactNode } from "react";

export interface IBadgeProps {
status?: "waiting..." | "playing" | "not Ready";
status?: "waiting..." | "playing" | "not Ready" | "ready";
children?: ReactNode;
playerNumber?: number;
}
34 changes: 34 additions & 0 deletions src/components/ui/card/profileCard/OtherProfileCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ReactNode } from "react";
import * as S from "./ProfileCardStyle";
import { IUser } from "../../../../pages/game/GameRoom";
import WaitingCard from "../waitingCard/WaitingCard";
import OtherPlayerCard from "./playerCard/OtherPlayerCard";

interface IOtherProfileCard {
nickname?: string;
children: ReactNode;
roomId: number;
otherInfo?: IUser[];
otherReady: boolean;
}

export default function OtherProfileCard({
nickname,
children,
otherInfo = [],
otherReady,
}: IOtherProfileCard) {
console.log(otherReady, "아더레디 확인");
return (
<div>
<S.CardIndex>{children}</S.CardIndex>
<S.PlayerCardContainer>
{otherInfo?.length > 0 ? (
<OtherPlayerCard nickname={nickname} otherReady={otherReady} />
) : (
<WaitingCard />
)}
</S.PlayerCardContainer>
</div>
);
}
22 changes: 18 additions & 4 deletions src/components/ui/card/profileCard/ProfileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,31 @@ import { ReactNode } from "react";
import PlayerCard from "./playerCard/playerCard";
import * as S from "./ProfileCardStyle";

interface IProfileCard {
nickname: string | undefined;
interface IMyProfileCard {
nickname?: string;
children: ReactNode;
roomId: number;
myReady: boolean;
handleMyReady: () => void;
}

export default function ProfileCard({ nickname, children }: IProfileCard) {
export default function MyProfileCard({
nickname,
children,
roomId,
myReady,
handleMyReady,
}: IMyProfileCard) {
return (
<div>
<S.CardIndex>{children}</S.CardIndex>
<S.PlayerCardContainer>
<PlayerCard nickname={nickname} />
<PlayerCard
myReady={myReady}
handleMyReady={handleMyReady}
roomId={roomId}
nickname={nickname}
/>
</S.PlayerCardContainer>
</div>
);
Expand Down
18 changes: 18 additions & 0 deletions src/components/ui/card/profileCard/playerCard/OtherPlayerCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Fragment } from "react/jsx-runtime";

import Profile from "../../../profile/Profile";
import Badge from "../../../badge/Badge";

interface IPlayerCard {
nickname?: string;
otherReady: boolean;
}

export default function OtherPlayerCard({ nickname, otherReady }: IPlayerCard) {
return (
<Fragment>
<Profile nickname={nickname} />
<Badge status={otherReady ? "ready" : "not Ready"} />
</Fragment>
);
}
47 changes: 42 additions & 5 deletions src/components/ui/card/profileCard/playerCard/playerCard.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,54 @@
import { Fragment } from "react/jsx-runtime";
import Button from "../../../button/Button";
import Profile from "../../../profile/Profile";
import { useSocketStore } from "../../../../../store/useSocketStore";
import { useEffect } from "react";

interface IPlayerCard {
nickname?: string;
roomId: number;
handleMyReady: () => void;
myReady: boolean;
}

export default function PlayerCard({
nickname,
}: {
nickname: string | undefined;
}) {
roomId,
myReady,
handleMyReady,
}: IPlayerCard) {
const { socket } = useSocketStore();

const onClickReady = () => {
if (!socket) {
return;
}
handleMyReady();
};

useEffect(() => {
if (!socket) {
return;
}
if (myReady) {
console.log(myReady, "마이래디");
socket?.emit("setReady", { roomId });
} else {
socket?.emit("unReady", { roomId });
}
}, [myReady]);

return (
<Fragment>
<Profile nickname={nickname} />
<Button type="button" bgcolor="blue" textcolor="black" size="sm">
Ready
<Button
type="button"
bgcolor={!myReady ? "blue" : "red"}
textcolor="black"
size="sm"
onClick={onClickReady}
>
{myReady ? "UnReady" : "Ready"}
</Button>
</Fragment>
);
Expand Down
11 changes: 11 additions & 0 deletions src/components/ui/card/waitingCard/WaitingCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Badge from "../../badge/Badge";
import * as S from "./waitingCardStyle";

export default function WaitingCard() {
return (
<S.container>
<Badge status="waiting..." />
<S.text>상대를 기다리는 중입니다.</S.text>
</S.container>
);
}
17 changes: 17 additions & 0 deletions src/components/ui/card/waitingCard/waitingCardStyle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styled from "styled-components";

export const container = styled.div`
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 20px;
`;

export const text = styled.div`
font-weight: 600;
font-size: 14px;
color: var(--color-gray-600);
`;
Loading