Skip to content

Commit

Permalink
Others/토너먼트 페이지 토너먼트 모달 style 작업#1128 (#1137)
Browse files Browse the repository at this point in the history
* [FIX] Mcoock API 수정

* [Style] 토너먼트 신청 버튼#1128

* [Style] 버튼 패딩 크기 수정#1128

* [Style] 그카드 그림자 추가 #1128

* [FIX] 토너먼트 페이지 인피니티 스크롤 제거 #1128

* [FIX] 토너먼트 페이지 에러메세지 수정 #1128

* [FIX] ㅌ토너먼트 신청 완료시 모달 종료 #1128

* [FStyle] 아이콘 추가 및 CSS 변경 #1128

* [Style] 스크롤 생성, 중앙 정렬 등등#1128

* [Feat] insert bracket view #1128

* [Style] 토너먼트 카드 마진 수정 #1128

* [Style] 토너먼트 컨테이너, 카드 수정#1128

* [Fix] 컨테이너의 크기를 받아서 브라켓뷰 사이즈에 입력 #1128

* [FIX] API 주소수정 #1128

* [Fix] react-icon 버젼이 다른 문제 해결#1128

---------

Co-authored-by: Junho Jeon <[email protected]>
  • Loading branch information
joonho0410 and Junho Jeon authored Dec 6, 2023
1 parent 116a340 commit c7808d7
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 70 deletions.
2 changes: 1 addition & 1 deletion components/modal/tournament/TournamentRegistryModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export default function TournamentRegistryModal({
message: `토너먼트 신청이 완료됐습니다`,
clicked: true,
});
if (player_cnt < 8) setPlayerCount(playerCount + 1);
}
if (res.data.status == false) {
setSnackbar({
Expand All @@ -65,6 +64,7 @@ export default function TournamentRegistryModal({

setRegistState(res.data.status);
setLoading(false);
setModal({ modalName: null });
return res.data.status;
})
.catch((error) => {
Expand Down
6 changes: 4 additions & 2 deletions components/tournament/TournamentBraket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@ const SVGViewer = dynamic<React.ComponentProps<typeof StaticSVGViewer>>(

interface TournamentBraketProps {
singleEliminationBracketMatchs: Match[];
containerSize?: { width: number; height: number };
}

export default function TournamentBraket({
singleEliminationBracketMatchs,
containerSize,
}: TournamentBraketProps) {
if (singleEliminationBracketMatchs.length === 0)
return <h1 style={{ color: 'white' }}>Loading...</h1>;
// const [width, height] = useWindowSize();
const finalWidth = 500; //Math.max(width - 50, 500);
const finalHeight = 500; //Math.max(height - 100, 500);
const finalWidth = containerSize?.width; //Math.max(width - 50, 500);
const finalHeight = containerSize?.height; //Math.max(height - 100, 500);

return (
<SingleEliminationBracket
Expand Down
15 changes: 14 additions & 1 deletion components/tournament/TournamentCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useSetRecoilState } from 'recoil';
import { BiCalendar } from 'react-icons/bi';
import { Modal } from 'types/modalTypes';
import { TournamentInfo } from 'types/tournamentTypes';
import { dateToString } from 'utils/handleTime';
import { modalState } from 'utils/recoil/modal';
import styles from 'styles/tournament/TournamentCard.module.scss';

Expand Down Expand Up @@ -36,12 +38,23 @@ export default function TournamentCard({
});
};

const date = new Date(startTime);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const il = date.getDate();
const start = `${year}.${month}.${il}`;

return (
<div
className={styles.tournamentCardContainer}
onClick={openTournamentInfoModal}
>
<div className={styles.text}>{title}</div>
<div className={styles.text}>
<div className={styles.left}>{title}</div>
<div className={styles.right}>
<BiCalendar /> {start}
</div>
</div>
</div>
);
}
5 changes: 3 additions & 2 deletions components/tournament/TournamentMegaphone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useState, useEffect, useRef } from 'react';
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
import { TournamentInfo } from 'types/tournamentTypes';
import { instance } from 'utils/axios';
import { dateToString } from 'utils/handleTime';
import { mockInstance } from 'utils/mockAxios';
import useInterval from 'hooks/useInterval';
import styles from 'styles/Layout/MegaPhone.module.scss';
Expand Down Expand Up @@ -39,7 +40,7 @@ const TournamentMegaphone = () => {

function getTournamentListHandler() {
return mockInstance
.get(`tournament?page=1&status=예정&size=5`)
.get(`tournament?size=20&page=1&status=BEFORE`)
.then((res) => {
setTournamentList(res.data.tournaments);
});
Expand All @@ -61,7 +62,7 @@ const TournamentMegaphone = () => {
(item): IMegaphoneContent => ({
megaphoneId: item.tournamentId,
content: item.title,
intraId: item.startTime.toString().split(':').slice(0, 2).join(':'),
intraId: dateToString(new Date(item.startTime)),
onClick: goTournamentPage,
})
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json({
status: false,
});
return;
} else if (method === 'POST') {
for (let i = 0; i < DummyData.length; i++) {
if (DummyData[i].tournamentId === idAsNumber) {
Expand All @@ -56,10 +57,12 @@ export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(404).json({
error: 'Touranment Id not Found',
});
return;
} else {
// 다른 요청 메소드에 대한 처리
res.setHeader('Allow', ['GET']);
res.status(405).end(`Method ${method} Not Allowed`);
return;
}
}
}
2 changes: 2 additions & 0 deletions pages/api/pingpong/tournament/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default function handler(req: NextApiRequest, res: NextApiResponse) {
tournaments: [],
totalPage: 0,
});
return;
}

const totalPage = Math.ceil(filteredTournaments.length / sizeInt);
Expand All @@ -56,4 +57,5 @@ export default function handler(req: NextApiRequest, res: NextApiResponse) {
tournaments: filteredTournaments,
totalPage: totalPage,
});
return;
}
109 changes: 68 additions & 41 deletions pages/tournament.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,102 @@
import React, { useState } from 'react';
import { Match } from '@g-loot/react-tournament-brackets/dist/src/types';
import React, { useState, useEffect, useCallback, useRef } from 'react';
import { useQuery } from 'react-query';
import { useSetRecoilState } from 'recoil';
import { TournamentInfo , TournamentData } from 'types/tournamentTypes';
import { TournamentData, TournamentGame } from 'types/tournamentTypes';
import { instance } from 'utils/axios';
import { InfiniteScroll } from 'utils/infinityScroll';
import { convertTournamentGamesToBracketMatchs } from 'utils/handleTournamentGame';
import { mockInstance } from 'utils/mockAxios';
import { errorState } from 'utils/recoil/error';
import { InfiniteScrollComponent } from 'components/store/InfiniteScrollComponent';
import TournamentBraket from 'components/tournament/TournamentBraket';
import TournamentCard from 'components/tournament/TournamentCard';
import styles from 'styles/tournament/TournamentContainer.module.scss';

export default function Tournament() {
const setError = useSetRecoilState(errorState);
const [waitTournament, setWaitTournament] = useState<TournamentData | null>(
null
);
const [openTournamentId, setOpenTournamentId] = useState<number>(0);
const [openTournament, setOpenTournament] = useState<Match[]>([]);
const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });
const containerRef = useRef<HTMLDivElement | null>(null); // useRef를 사용하여 Ref 생성

const openInfo = useQuery<TournamentData>(
'openTorunamentInfo',
() =>
mockInstance
.get('tournament?page=1&status=진행중')
.then((res) => res.data),
mockInstance.get('tournament?page=1&status=BEFORE').then((res) => {
setOpenTournamentId(res.data.tournamentId);
return res.data.tournamentId;
}),
{ retry: 1, staleTime: 60000 /* 60초 */ }
);

async function fetchWaitTournamentData(page: number) {
return await mockInstance
.get(`tournament?page=${page}&status=예정&size=4`)
const fetchWaitTournamentData = (page: number) => {
return mockInstance
.get(`tournament?page=${page}&status=BEFORE&size=4`)
.then((res) => {
return res.data;
});
}
};

const { data, error, isLoading, hasNextPage, fetchNextPage } = InfiniteScroll(
'waitTournament',
fetchWaitTournamentData,
'JJH1'
);
const fetchTournamentGames = useCallback(async () => {
console.log('Fetching more data...');
try {
const res = await mockInstance.get(
`/tournament/${openTournamentId}/games`
);
const data: TournamentGame[] = res.data.games;
const bracketMatchs = convertTournamentGamesToBracketMatchs(data);
setOpenTournament(bracketMatchs);
return data;
} catch (error) {
console.error('Error fetching data:', error);
}
}, [openTournament]);

useEffect(() => {
fetchWaitTournamentData(1)
.then((data) => {
setWaitTournament(data);
})
.catch(() => {
setError('JHH02');
});
fetchTournamentGames();
}, []);

useEffect(() => {
if (containerRef.current) {
const width = containerRef.current.clientWidth;
const height = containerRef.current.clientHeight;
setContainerSize({ width, height });
}
}, []);

return (
<div className={styles.pageWrap}>
<h1 className={styles.title}>Tournament</h1>
<div className={styles.tournamentContainer}>
<div className={styles.tournamentTextWait}> 대기중인 토너먼트 </div>
<div className={styles.tournamentText}> 예정된 토너먼트 </div>
<div className={styles.waitTournamentBox}>
{data?.pages.map((page, pageIndex) => (
<div key={pageIndex}>
{page.tournaments.map(
(tournament: TournamentInfo, tournamentIndex: number) => (
<TournamentCard key={tournamentIndex} {...tournament} />
)
)}
{/* 실제로는 tournamnetId 를 key값으로 사용하는게 좋음, 현재는 mockdata에서 id 값들이 겹치기 때문에 Index로 사용
{page.tournaments.map((tournament: TournamentInfo, tournamentIndex: number) => (
< key={tournament.tournamentId} {...tournament} />
))}
*/}
{waitTournament?.tournaments.map((tournament) => (
<div className={styles.cardContainer} key={tournament.tournamentId}>
<TournamentCard key={tournament.tournamentId} {...tournament} />
</div>
))}
<InfiniteScrollComponent
fetchNextPage={fetchNextPage}
hasNextPage={hasNextPage}
/>
</div>
<div className={styles.tournamentTextOpen}> 진행중인 토너먼트 </div>
<div className={styles.openTournamentBox}>
<div className={styles.tournamentText}>
{openInfo.data && openInfo.data.tournaments.length === 0 ? (
<>진행중인 토너먼트가 없습니다</>
) : (
<>진행중인 토너먼트 사진</>
)}
</div>
<div className={styles.openTournamentBox} ref={containerRef}>
{openInfo.data && openInfo.data.tournaments.length === 0 ? (
<div className={styles.tournamentText}>
진행중인 토너먼트가 없습니다
</div>
) : (
<TournamentBraket
singleEliminationBracketMatchs={openTournament}
containerSize={containerSize}
/>
)}
</div>
</div>
</div>
Expand Down
27 changes: 23 additions & 4 deletions styles/modal/event/TournamentRegistryModal.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,29 @@
@include modalContainer('SKYPINK');
width: 80vw;
max-width: 22rem;
overflow: wrap;
}

.title {
@include modalTitle;
padding-bottom: 1rem;
width: 100%;
max-height: 11rem;
margin-bottom: 1rem;
overflow-y: scroll;
color: rgba(18, 23, 37, 1);
text-align: center;
word-wrap: break-word;
}

.title::-webkit-scrollbar {
display: inherit;
width: 0.5rem;
height: 1rem;
}

.title::-webkit-scrollbar-thumb {
background: white;
border-radius: 2rem;
}

.startTime {
Expand All @@ -30,13 +47,13 @@

.quillViewer::-webkit-scrollbar {
display: inherit;
width: 5px;
width: 0.5rem;
height: 1rem;
}

.quillViewer::-webkit-scrollbar-thumb {
background: white;
border-radius: 10px;
background: rgba(240, 210, 210, 1);
border-radius: 2rem;
}

.checkBox {
Expand All @@ -59,12 +76,14 @@

.closeButtonContainer {
display: flex;
margin-bottom: 1rem;
margin-left: auto;
}

.tournamentInfo {
justify-content: center;
align-items: center;
word-wrap: break-word;
}

.participants {
Expand Down
34 changes: 25 additions & 9 deletions styles/tournament/TournamentCard.module.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
.tournamentCardContainer {
display: flex;
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
background-color: black;
border: 2px solid black;
border-radius: 0.3rem;
height: 3.5rem;
padding: 0 1rem;
margin: 0.5rem;
overflow-y: scroll;
cursor: pointer;
background: linear-gradient(to bottom, #7816e1, #9e35db);
border-radius: 0.5rem;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.6);
align-items: center;

.text {
overflow: hidden;
display: flex;
width: 100%;
color: white;
text-overflow: ellipsis;
white-space: nowrap;
justify-content: space-between;

.left {
flex: 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// text-align: left;
}

.right {
flex: 1;
// text-align: right;
}
}
}
Loading

0 comments on commit c7808d7

Please sign in to comment.