diff --git a/__mocks__/constants/matchRoundMock.ts b/__mocks__/constants/matchRoundMock.ts
index 9778862..f151511 100644
--- a/__mocks__/constants/matchRoundMock.ts
+++ b/__mocks__/constants/matchRoundMock.ts
@@ -1,11 +1,11 @@
import { BracketContents } from '@type/bracket';
interface mockRoundData {
- [key: string]: BracketContents;
+ [key: number]: BracketContents;
}
export const matchRoundMock: mockRoundData = {
- '1': {
+ 1: {
myGameId: 'NO_DATA',
matchInfoDtoList: [
{
@@ -439,7 +439,7 @@ export const matchRoundMock: mockRoundData = {
},
],
},
- '2': {
+ 2: {
myGameId: 'NO_DATA',
matchInfoDtoList: [
{
@@ -658,7 +658,7 @@ export const matchRoundMock: mockRoundData = {
},
],
},
- '3': {
+ 3: {
myGameId: 'NO_DATA',
matchInfoDtoList: [
{
@@ -773,7 +773,7 @@ export const matchRoundMock: mockRoundData = {
},
],
},
- '4': {
+ 4: {
myGameId: 'NO_DATA',
matchInfoDtoList: [
{
diff --git a/__mocks__/handlers/bracketHandlers.ts b/__mocks__/handlers/bracketHandlers.ts
index 167ca02..0d06ce8 100644
--- a/__mocks__/handlers/bracketHandlers.ts
+++ b/__mocks__/handlers/bracketHandlers.ts
@@ -1,7 +1,13 @@
import { SERVER_URL } from '@config/index';
import { matchRoundMock } from '@mocks/constants/matchRoundMock';
+import { MatchCountList } from '@type/channelConfig';
import { rest } from 'msw';
+const channelRoundList: MatchCountList[] = [
+ {
+ roundCountList: [2, 3, 4, 5],
+ },
+];
const bracketHandlers = [
rest.get(SERVER_URL + '/api/match/:channelLink', (req, res, ctx) => {
const { channelLink } = req.params;
@@ -9,12 +15,18 @@ const bracketHandlers = [
return res(ctx.json({ roundList: [1, 2, 3, 4], liveRound: 1 }));
}),
- rest.get(SERVER_URL + '/api/match/:channelLink/:matchRound', (req, res, ctx) => {
+ rest.get(SERVER_URL + '/api/match/:channelLink/:matchRound(\\d+)', (req, res, ctx) => {
const { channelLink, matchRound } = req.params;
- if (typeof matchRound === 'string') {
- return res(ctx.json(matchRoundMock[matchRound]));
- }
+ return res(ctx.json(matchRoundMock[Number(matchRound)]));
+ }),
+
+ rest.get(SERVER_URL + '/api/match/:channelLink/count', (req, res, ctx) => {
+ return res(ctx.json(channelRoundList[0]));
+ }),
+
+ rest.post(SERVER_URL + '/api/match/:channelLink/count', (req, res, ctx) => {
+ return res(ctx.json({ message: '채널 재설정 완료' }));
}),
];
diff --git a/src/@types/channelConfig.ts b/src/@types/channelConfig.ts
new file mode 100644
index 0000000..a9eb886
--- /dev/null
+++ b/src/@types/channelConfig.ts
@@ -0,0 +1,3 @@
+export interface MatchCountList {
+ roundCountList: number[];
+}
diff --git a/src/@types/icon.ts b/src/@types/icon.ts
index f072fee..4f8e383 100644
--- a/src/@types/icon.ts
+++ b/src/@types/icon.ts
@@ -10,4 +10,6 @@ export type IconKind =
| 'clock'
| 'refresh'
| 'sendEmail'
- | 'modify';
+ | 'modify'
+ | 'setting'
+ | 'cancel';
diff --git a/src/components/Bracket/BracketContents.tsx b/src/components/Bracket/BracketContents.tsx
index d8ec4f1..f25aac9 100644
--- a/src/components/Bracket/BracketContents.tsx
+++ b/src/components/Bracket/BracketContents.tsx
@@ -39,29 +39,33 @@ const BracketContents = (props: Props) => {
return (
- R{match.matchRoundCount}
+ M{match.matchRoundCount}
{match.matchName}
자세히
- {match.matchPlayerInfoList.map((user) => {
- return (
-
-
- {user.profileSrc ? (
-
- ) : (
-
- {user.gameId.substring(0, 2)}
-
- )}
-
-
- {user.gameId}
- {user.score}
-
- );
- })}
+ {match.matchPlayerInfoList.length === 0 ? (
+ 아직 대진표가 생성되지 않았어요 :(
+ ) : (
+ match.matchPlayerInfoList.map((user) => {
+ return (
+
+
+ {user.profileSrc ? (
+
+ ) : (
+
+ {user.gameId.substring(0, 2)}
+
+ )}
+
+
+ {user.gameId}
+ {user.score}
+
+ );
+ })
+ )}
);
@@ -78,6 +82,8 @@ const Container = styled.div``;
const Header = styled.div``;
const Content = styled.div`
+ position: relative;
+
display: grid;
max-width: 100rem;
@@ -170,6 +176,19 @@ const MatchContent = styled.div`
flex-direction: column;
`;
+const MatchNoGame = styled.div`
+ height: 35rem;
+ width: 21rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #b4b4b3;
+ opacity: 0.6;
+
+ font-size: 1.8 rem;
+ color: black;
+`;
+
const UserContainer = styled.div<{ myself: boolean }>`
width: 20rem;
display: grid;
diff --git a/src/components/Icon/index.tsx b/src/components/Icon/index.tsx
index f211ffa..7aabb28 100644
--- a/src/components/Icon/index.tsx
+++ b/src/components/Icon/index.tsx
@@ -13,6 +13,8 @@ import {
MdRefresh,
MdSend,
MdModeEdit,
+ MdSettings,
+ MdCancel,
} from 'react-icons/md';
import { MouseEventHandler } from 'react';
@@ -29,6 +31,8 @@ const ICON: { [key in IconKind]: IconType } = {
refresh: MdRefresh,
sendEmail: MdSend,
modify: MdModeEdit,
+ setting: MdSettings,
+ cancel: MdCancel,
};
interface IconProps {
diff --git a/src/components/Modal/ModifyChannel/ModifyChannel.tsx b/src/components/Modal/ModifyChannel/ModifyChannel.tsx
index 358dbf0..432faf7 100644
--- a/src/components/Modal/ModifyChannel/ModifyChannel.tsx
+++ b/src/components/Modal/ModifyChannel/ModifyChannel.tsx
@@ -1,8 +1,8 @@
-import authAPI from '@apis/authAPI';
-import { css } from '@emotion/react';
+import Icon from '@components/Icon';
+import BasicInfoChannel from '@components/ModifyChannel/BasicInfoChannel';
+import BracketInfoChannel from '@components/ModifyChannel/BracketInfoChannel';
import styled from '@emotion/styled';
-import { useRef } from 'react';
-
+import { useState } from 'react';
interface ModifyChannelProps {
channelLink: string;
leagueTitle: string;
@@ -10,68 +10,38 @@ interface ModifyChannelProps {
onClose: (leagueTitle?: string, maxPlayer?: number) => void;
}
+type MenuList = 'basicInfo' | 'bracketInfo';
+
const ModifyChannel = ({ channelLink, leagueTitle, maxPlayer, onClose }: ModifyChannelProps) => {
- const leagueTitleRef = useRef(null);
- const maxPlayerRef = useRef(null);
+ const [selectedMenu, setSelectedMenu] = useState('basicInfo');
- const onClickSubmit = async () => {
- console.log(leagueTitleRef.current?.value, maxPlayerRef.current?.value);
- if (!leagueTitleRef.current || !maxPlayerRef.current) return;
- const updatedLeagueTitle = leagueTitleRef.current.value;
- const updatedMaxPlayer = parseInt(maxPlayerRef.current.value, 10);
- if (isNaN(updatedMaxPlayer)) {
- alert('최대인원수를 숫자로 입력해주세요');
- return;
- }
- if (!confirm('리그를 수정하시겠습니까?')) return;
- const res = await authAPI({
- method: 'post',
- url: `/api/channel/${channelLink}`,
- data: {
- title: updatedLeagueTitle,
- maxPlayer: updatedMaxPlayer,
- },
- });
- if (res.status !== 200) return;
- alert('정보가 수정되었습니다');
- onClose(updatedLeagueTitle, updatedMaxPlayer);
+ const handleSelectedMenu = (menu: MenuList) => {
+ setSelectedMenu(menu);
};
return (
-
- 리그 수정하기
-
-
- 리그 제목
-
-
+ handleSelectedMenu('basicInfo')}>
+ 대회 기본 정보 수정
+
+ handleSelectedMenu('bracketInfo')}>
+ 대진표 수정
+
+
+
+ {selectedMenu === 'basicInfo' && (
+
-
-
-
- 최대 참여자 인원
-
-
-
-
-
- onClose()}>취소
- 수정하기
-
+ )}
+ {selectedMenu === 'bracketInfo' && }
+
+
+ onClose()} />
+
);
};
@@ -79,58 +49,42 @@ const ModifyChannel = ({ channelLink, leagueTitle, maxPlayer, onClose }: ModifyC
export default ModifyChannel;
const Container = styled.div`
- color: black;
- padding: 5%;
-`;
+ width: 100vw;
+ height: 100vh;
+ background-color: white;
-const Wrapper = styled.div`
display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
- padding: 1rem;
- font-size: 1.7rem;
- font-weight: bold;
- min-height: 7rem;
`;
-const FlexWrapper = styled.div`
- flex: 1;
- justify-content: flex-start;
+const Sidebar = styled.div`
+ width: 30rem;
+ background-color: #141c24;
`;
-const ButtonWrapper = styled.div`
+const SidebarContent = styled.div`
+ width: 80%;
+ height: 5rem;
+ margin: 0 auto;
+ color: white;
+
+ font-size: 2rem;
+ font-weight: 900;
+
display: flex;
- flex-direction: row;
- justify-content: center;
align-items: center;
- padding: 1rem;
- font-size: 1.7rem;
- font-weight: bold;
- min-height: 7rem;
+
+ cursor: pointer;
`;
-const Input = styled.input`
- width: 80%;
- height: 4rem;
- border: none;
- border-radius: 0.6rem;
- padding: 0.6rem;
+const MainContent = styled.div`
+ width: calc(100vw - 30rem);
+
+ background-color: #202b37;
`;
-const SubmitButton = styled.button`
- width: 10rem;
- height: 6rem;
- background-color: #344051;
- border: none;
- border-radius: 0.5rem;
- color: white;
- margin: 0 6rem 0 6rem;
- &:hover {
- cursor: pointer;
- }
- &:disabled {
- background-color: #d3d3d3;
- cursor: not-allowed;
- }
+const CloseButtonContainer = styled.div`
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
+ cursor: pointer;
`;
diff --git a/src/components/ModifyChannel/BasicInfoChannel.tsx b/src/components/ModifyChannel/BasicInfoChannel.tsx
new file mode 100644
index 0000000..b693f30
--- /dev/null
+++ b/src/components/ModifyChannel/BasicInfoChannel.tsx
@@ -0,0 +1,134 @@
+import styled from '@emotion/styled';
+import { css } from '@emotion/react';
+import { useRef } from 'react';
+import authAPI from '@apis/authAPI';
+
+interface BasicInfoChannelProps {
+ channelLink: string;
+ leagueTitle: string;
+ maxPlayer: number;
+}
+
+const BasicInfoChannel = ({ channelLink, leagueTitle, maxPlayer }: BasicInfoChannelProps) => {
+ const leagueTitleRef = useRef(null);
+ const maxPlayerRef = useRef(null);
+
+ const onClickSubmit = async () => {
+ console.log(leagueTitleRef.current?.value, maxPlayerRef.current?.value);
+ if (!leagueTitleRef.current || !maxPlayerRef.current) return;
+ const updatedLeagueTitle = leagueTitleRef.current.value;
+ const updatedMaxPlayer = parseInt(maxPlayerRef.current.value, 10);
+ if (isNaN(updatedMaxPlayer)) {
+ alert('최대인원수를 숫자로 입력해주세요');
+ return;
+ }
+ if (!confirm('리그를 수정하시겠습니까?')) return;
+ const res = await authAPI({
+ method: 'post',
+ url: `/api/channel/${channelLink}`,
+ data: {
+ title: updatedLeagueTitle,
+ maxPlayer: updatedMaxPlayer,
+ },
+ });
+ if (res.status !== 200) return;
+ alert('정보가 수정되었습니다');
+ };
+
+ return (
+
+
+
+
+ 리그 제목
+
+
+
+
+
+ 최대 인원
+
+
+
+
+
+
+
+ 수정하기
+
+
+ );
+};
+
+export default BasicInfoChannel;
+
+const Container = styled.div`
+ margin: 2rem 4rem;
+`;
+const Header = styled.div`
+ text-align: left;
+
+ font-size: 3rem;
+ font-weight: 900;
+ color: white;
+`;
+
+const Content = styled.div``;
+
+const Wrapper = styled.div`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ padding: 1rem;
+ font-size: 1.7rem;
+ font-weight: bold;
+ min-height: 7rem;
+`;
+
+const FlexWrapper = styled.div`
+ color: white;
+`;
+
+const ButtonWrapper = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+
+ font-weight: bold;
+ font-size: 1.8rem;
+`;
+
+const Input = styled.input`
+ width: 80%;
+ height: 4rem;
+ border: none;
+ border-radius: 0.6rem;
+ padding: 0.6rem;
+`;
+
+const SubmitButton = styled.button`
+ width: 10rem;
+ height: 6rem;
+ background-color: #344051;
+ border: none;
+ border-radius: 0.5rem;
+ color: white;
+ margin: 0 6rem 0 6rem;
+ &:hover {
+ cursor: pointer;
+ }
+ &:disabled {
+ background-color: #d3d3d3;
+ cursor: not-allowed;
+ }
+`;
diff --git a/src/components/ModifyChannel/BracketInfoChannel.tsx b/src/components/ModifyChannel/BracketInfoChannel.tsx
new file mode 100644
index 0000000..fb06db5
--- /dev/null
+++ b/src/components/ModifyChannel/BracketInfoChannel.tsx
@@ -0,0 +1,133 @@
+import authAPI from '@apis/authAPI';
+import styled from '@emotion/styled';
+import { useQuery } from '@tanstack/react-query';
+import { MatchCountList } from '@type/channelConfig';
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+
+const fetchInitialMatchCount = async (channelLink: string) => {
+ const res = await authAPI({
+ method: 'get',
+ url: `/api/match/${channelLink}/count`,
+ });
+ return res.data;
+};
+
+const BracketInfoChannel = () => {
+ const router = useRouter();
+
+ const [roundInfo, setRoundInfo] = useState();
+
+ const { data, isLoading, isError, isSuccess } = useQuery({
+ queryKey: ['matchCount', router.query.channelLink as string],
+ queryFn: () => fetchInitialMatchCount(router.query.channelLink as string),
+ });
+
+ const handleRoundInfo = (e: React.ChangeEvent, roundIndex: number) => {
+ const changeRoundInfoArr = roundInfo?.map((ele, index) =>
+ index === roundIndex ? Number(e.target.value) : ele,
+ );
+
+ setRoundInfo(changeRoundInfoArr);
+ };
+
+ const updateRoundMatchCount = async () => {
+ try {
+ const res = await authAPI({
+ method: 'post',
+ url: `/api/match/${router.query.channelLink as string}/count`,
+ data: {
+ roundCountList: roundInfo?.reverse(),
+ },
+ });
+
+ console.log(res);
+
+ alert('수정이 완료되었습니다!');
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ useEffect(() => {
+ if (isSuccess) {
+ setRoundInfo(data?.roundCountList.reverse());
+ }
+ }, [data]);
+
+ return (
+
+
+
+ {roundInfo?.map((currentMatchCount, index) => {
+ return (
+
+ Round {index + 1}
+
+
+ );
+ })}
+
+ 수정완료
+
+
+
+ );
+};
+
+export default BracketInfoChannel;
+
+const Container = styled.div`
+ margin: 2rem 4rem;
+`;
+
+const Header = styled.div`
+ text-align: left;
+
+ font-size: 3rem;
+ font-weight: 900;
+ color: white;
+`;
+
+const Content = styled.div``;
+
+const RoundInfo = styled.div`
+ height: 7rem;
+ display: flex;
+ align-items: center;
+ gap: 2rem;
+`;
+
+const RoundInfoHeader = styled.div`
+ font-size: 2rem;
+ color: white;
+`;
+
+const ButtonWrapper = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+`;
+
+const ModifyButton = styled.button`
+ width: 10rem;
+ height: 6rem;
+ background-color: #344051;
+ border: none;
+ border-radius: 0.5rem;
+ color: white;
+ margin: 0 6rem 0 6rem;
+
+ cursor: pointer;
+
+ font-size: 1.8rem;
+`;