Skip to content

Commit

Permalink
merge: [FEAT] 유저 정보 관리 cookie로 변경 #348
Browse files Browse the repository at this point in the history
[FEAT] 유저 정보 관리 cookie로 변경
  • Loading branch information
novice0840 authored Oct 24, 2024
2 parents e5d9179 + d86a41c commit 8855ab8
Show file tree
Hide file tree
Showing 39 changed files with 241 additions and 164 deletions.
2 changes: 1 addition & 1 deletion frontend/src/apis/balanceContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const checkMyGameStatus = async ({

// 다음 라운드로 이동하기
export const moveNextRound = async (roomId: number) => {
const res = await fetcher.patch({
await fetcher.patch({
url: API_URL.moveNextRound(roomId),
headers: {
'Content-Type': `application/json`,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/apis/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const fetcher = {
method,
body: body && JSON.stringify(body),
headers: headers && headers,
credentials: 'include',
});

if (!response.ok) {
Expand Down
17 changes: 16 additions & 1 deletion frontend/src/apis/room.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import fetcher from './fetcher';

import { API_URL } from '@/constants/url';
import { RoomInfo, CreateOrEnterRoomResponse, Category, RoomSettingApply } from '@/types/room';
import {
RoomInfo,
CreateOrEnterRoomResponse,
Category,
RoomSettingApply,
RoomAndMember,
} from '@/types/room';

interface CategoryResponse {
categories: Category[];
Expand Down Expand Up @@ -136,3 +142,12 @@ export const isJoinableRoom = async (roomUuid: string): Promise<{ isJoinable: bo

return data;
};

// 사용자 정보 조회
export const getUserInfo = async (): Promise<RoomAndMember> => {
const res = await fetcher.get({
url: API_URL.getUserInfo,
});
const data = await res.json();
return data;
};
13 changes: 7 additions & 6 deletions frontend/src/components/GameResult/GameResult.hook.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useMutation, useQuery, UseQueryResult } from '@tanstack/react-query';
import { useParams } from 'react-router-dom';
import { useRecoilValue } from 'recoil';

import { fetchMatchingResult } from '@/apis/balanceContent';
import { resetRoom } from '@/apis/room';
import { QUERY_KEYS } from '@/constants/queryKeys';
import { memberInfoState } from '@/recoil/atom';
import useGetUserInfo from '@/hooks/useGetUserInfo';
import { MatchingResult, MemberMatchingInfo } from '@/types/balanceContent';

type MatchingResultQueryResponse = UseQueryResult<MatchingResult, Error> & {
Expand All @@ -15,15 +14,17 @@ type MatchingResultQueryResponse = UseQueryResult<MatchingResult, Error> & {

export const useMatchingResultQuery = (): MatchingResultQueryResponse => {
const { roomId } = useParams();
const memberInfo = useRecoilValue(memberInfoState);
const {
member: { memberId },
} = useGetUserInfo();

const matchingResultQuery = useQuery({
queryKey: [QUERY_KEYS.matchingResult, roomId, memberInfo.memberId],
queryKey: [QUERY_KEYS.matchingResult, roomId, memberId],
queryFn: async () => {
if (!memberInfo.memberId) {
if (!memberId) {
throw new Error('Member ID is required');
}
return await fetchMatchingResult({ roomId: Number(roomId), memberId: memberInfo.memberId });
return await fetchMatchingResult({ roomId: Number(roomId), memberId: memberId });
},
});

Expand Down
8 changes: 3 additions & 5 deletions frontend/src/components/NicknameItem/NicknameItem.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { useRecoilValue } from 'recoil';

import { nicknameItemLayout, nicknameText, profileImage } from './NicknameItem.styled';

import SillyDdangkongMedium from '@/assets/images/sillyDdangkongMedium.webp';
import { memberInfoState } from '@/recoil/atom';
import useGetUserInfo from '@/hooks/useGetUserInfo';

interface NicknameItemProp {
nickName: string;
}

const NicknameItem = ({ nickName }: NicknameItemProp) => {
const memberInfo = useRecoilValue(memberInfoState);
const isMyNickname = memberInfo.nickname === nickName;
const { member } = useGetUserInfo();
const isMyNickname = member.nickname === nickName;

return (
<li css={nicknameItemLayout}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useQueryClient } from '@tanstack/react-query';
import { useEffect, useRef } from 'react';
import { useRecoilState } from 'recoil';

import {
readyMembersContainerLayout,
Expand All @@ -17,27 +17,24 @@ import A11yOnly from '../common/a11yOnly/A11yOnly';
import crownIcon from '@/assets/images/crownIcon.webp';
import SillyDdangkongMedium from '@/assets/images/sillyDdangkongMedium.webp';
import InviteModal from '@/components/common/InviteModal/InviteModal';
import { QUERY_KEYS } from '@/constants/queryKeys';
import { useGetRoomInfo } from '@/hooks/useGetRoomInfo';
import useModal from '@/hooks/useModal';
import { memberInfoState } from '@/recoil/atom';

const ReadyMembersContainer = () => {
const { members, master } = useGetRoomInfo();
const { show } = useModal();
const [memberInfo, setMemberInfo] = useRecoilState(memberInfoState);
const queryClient = useQueryClient();
const returnFocusRef = useRef<HTMLButtonElement>(null);
const memberCountMessage = `총 인원 ${members.length}명`;

const handleClickInvite = () => {
show(InviteModal, { returnFocusRef });
};

// 원래 방장이 아니다 + 방장의 memberId와 내 memberId가 같다 -> 방장으로 변경
useEffect(() => {
if (!memberInfo.isMaster && master.memberId === memberInfo.memberId) {
setMemberInfo({ ...memberInfo, isMaster: true });
}
}, [master.memberId, memberInfo, setMemberInfo]);
queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.getUserInfo] });
}, [master.memberId]);

return (
<section css={readyMembersContainerLayout}>
Expand Down
28 changes: 21 additions & 7 deletions frontend/src/components/RoomSetting/RoomSetting.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import getBorderRadius from '@/styles/utils/getBorderRadius';

export const roomSettingLayout = css`
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
width: 100%;
Expand All @@ -16,22 +17,35 @@ export const roomSettingLayout = css`
cursor: pointer;
`;

export const roomSettingBox = css`
display: flex;
flex-direction: column;
gap: 1rem;
`;

export const bigTitle = css`
width: 10rem;
font-weight: 800;
font-size: 2.8rem;
`;

export const smallTitle = css`
width: 10rem;
font-weight: 800;
font-size: 2rem;
`;

export const roomSettingLabel = css`
export const roomSettingKey = css`
width: 10rem;
`;

export const roomSettingKeyBox = css`
display: flex;
justify-content: space-between;
width: 50rem;
font-weight: 600;
`;

export const roomSettingValueBox = css`
display: flex;
justify-content: space-between;
align-items: center;
width: 50rem;
`;
27 changes: 17 additions & 10 deletions frontend/src/components/RoomSetting/RoomSetting.test.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { screen, waitFor } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import type { MutableSnapshot } from 'recoil';
import { http, HttpResponse } from 'msw';

import RoomSetting from './RoomSetting';

import { memberInfoState } from '@/recoil/atom';
import { MOCK_API_URL } from '@/constants/url';
import { server } from '@/mocks/server';
import { customRender } from '@/utils/test-utils';

describe('RoomSetting 컴포넌트 테스트', () => {
it('방장이 RoomSetting를 누르면 설정 modal이 뜬다', async () => {
// Given
const initializeState = (snap: MutableSnapshot) => {
snap.set(memberInfoState, { memberId: 1, nickname: 'Test User', isMaster: true });
};
const user = userEvent.setup();
customRender(<RoomSetting />, { initializeState });
customRender(<RoomSetting />);
const settingButton = await screen.findByRole('button', { name: '방 설정' });

// When
Expand All @@ -29,11 +27,20 @@ describe('RoomSetting 컴포넌트 테스트', () => {

it('방장이 아닌 사람이 RoomSetting를 누르면 설정 modal이 뜨지 않는다', async () => {
// Given
const initializeState = (snap: MutableSnapshot) => {
snap.set(memberInfoState, { memberId: 1, nickname: 'Test User', isMaster: false });
};
server.use(
http.get(MOCK_API_URL.getUserInfo, async () => {
return HttpResponse.json(
{
member: {
isMaster: false,
},
},
{ status: 400 },
);
}),
);
const user = userEvent.setup();
customRender(<RoomSetting />, { initializeState });
customRender(<RoomSetting />);
const optionButton = await screen.findByRole('button', { name: '방 설정' });

// When
Expand Down
26 changes: 13 additions & 13 deletions frontend/src/components/RoomSetting/RoomSetting.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { useRef } from 'react';
import { useRecoilValue } from 'recoil';

import {
roomSettingLayout,
bigTitle,
smallTitle,
roomSettingLabel,
roomSettingBox,
roomSettingKeyBox,
roomSettingValueBox,
roomSettingKey,
} from './RoomSetting.styled';

import A11yOnly from '@/components/common/a11yOnly/A11yOnly';
import RoomSettingModal from '@/components/common/RoomSettingModal/RoomSettingModal';
import { useGetRoomInfo } from '@/hooks/useGetRoomInfo';
import useGetUserInfo from '@/hooks/useGetUserInfo';
import useModal from '@/hooks/useModal';
import { memberInfoState } from '@/recoil/atom';

const RoomSetting = () => {
const returnFocusRef = useRef<HTMLButtonElement>(null);
const { roomSetting } = useGetRoomInfo();
const { isMaster } = useRecoilValue(memberInfoState);
const {
member: { isMaster },
} = useGetUserInfo();
const { show } = useModal();
const screenReaderRoomSetting = `
방 정보.
Expand All @@ -39,16 +41,14 @@ const RoomSetting = () => {
onClick={isMaster ? handleClickCategory : () => {}}
ref={returnFocusRef}
>
<div css={roomSettingBox}>
<span css={roomSettingLabel}>라운드</span>
<h2 css={smallTitle}>{roomSetting.totalRound}</h2>
<div css={roomSettingKeyBox}>
<span css={roomSettingKey}>라운드</span>
<span css={roomSettingKey}>카테고리</span>
<span css={roomSettingKey}>제한 시간</span>
</div>
<div css={roomSettingBox}>
<span css={roomSettingLabel}>카테고리</span>
<div css={roomSettingValueBox}>
<h2 css={smallTitle}>{roomSetting.totalRound}</h2>
<h2 css={bigTitle}>{roomSetting.category.label}</h2>
</div>
<div css={roomSettingBox}>
<span css={roomSettingLabel}>제한 시간</span>
<h2 css={smallTitle}>{roomSetting.timeLimit / 1000}</h2>
</div>
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import StartButton from './StartButton';
import { ERROR_MESSAGE } from '@/constants/message';
import { MOCK_API_URL } from '@/constants/url';
import { server } from '@/mocks/server';
import { customRenderWithIsMaster } from '@/utils/test-utils';
import { customRenderWithMaster } from '@/utils/test-utils';

describe('StartButton 테스트', () => {
it('시작 버튼을 클릭했을 때, 게임 시작 API에서 에러가 발생하면 알림 모달이 뜬다.', async () => {
Expand All @@ -24,7 +24,7 @@ describe('StartButton 테스트', () => {
}),
);

customRenderWithIsMaster(<StartButton />, true);
customRenderWithMaster(<StartButton />);

const startButton = await screen.findByRole('button', { name: '시작' });
await user.click(startButton);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import getStartButtonText from './StartButton.utils';
import Button from '@/components/common/Button/Button';

const StartButton = () => {
const { memberInfo, handleGameStart, isPending, isSuccess } = useGameStart();
const { isMaster, handleGameStart, isPending, isSuccess } = useGameStart();

return (
<Button
text={getStartButtonText(memberInfo.isMaster, isPending || isSuccess)}
disabled={!memberInfo.isMaster || isPending || isSuccess}
text={getStartButtonText(isMaster, isPending || isSuccess)}
disabled={!isMaster || isPending || isSuccess}
onClick={handleGameStart}
bottom
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { useMutation } from '@tanstack/react-query';
import { useParams } from 'react-router-dom';
import { useRecoilState } from 'recoil';

import { startGame } from '@/apis/room';
import { memberInfoState } from '@/recoil/atom';
import useGetUserInfo from '@/hooks/useGetUserInfo';

export const useGameStart = () => {
const [memberInfo, setMemberInfo] = useRecoilState(memberInfoState);
const {
member: { isMaster },
} = useGetUserInfo();
const { roomId } = useParams();

const startGameMutation = useMutation({
mutationFn: () => startGame(Number(roomId)),
});

const handleGameStart = () => {
if (memberInfo.isMaster) {
if (isMaster) {
startGameMutation.mutate();
}
};

return { memberInfo, handleGameStart, setMemberInfo, ...startGameMutation };
return { isMaster, handleGameStart, ...startGameMutation };
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { userEvent } from '@testing-library/user-event';

import StartButtonContainer from './StartButtonContainer';

import { customRenderWithIsMaster } from '@/utils/test-utils';
import { customRender } from '@/utils/test-utils';

describe('StartButtonContainer 테스트', () => {
it('게임 시작 버튼을 클릭하면 카운트 다운을 시작한다.', async () => {
const user = userEvent.setup();
customRenderWithIsMaster(<StartButtonContainer />, true);
customRender(<StartButtonContainer />);
const COUNTDOWN_LABEL_TEXT = '게임 시작 3초 전';

const button = await screen.findByRole('button', { name: '시작' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import FinalButton from './FinalButton';
import { ERROR_MESSAGE } from '@/constants/message';
import { MOCK_API_URL } from '@/constants/url';
import { server } from '@/mocks/server';
import { customRenderWithIsMaster } from '@/utils/test-utils';
import { customRenderWithMaster } from '@/utils/test-utils';

describe('FinalButton 테스트', () => {
it('확인 버튼을 클릭했을 때, 방 초기화 API에서 에러가 발생하면 알림 모달이 뜬다.', async () => {
Expand All @@ -24,7 +24,7 @@ describe('FinalButton 테스트', () => {
}),
);

customRenderWithIsMaster(<FinalButton />, true);
customRenderWithMaster(<FinalButton />);

const finalButton = await screen.findByRole('button', { name: '대기실로 이동' });
await user.click(finalButton);
Expand Down
Loading

0 comments on commit 8855ab8

Please sign in to comment.