Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Others/토너먼트 페이지 토너먼트 모달 style 작업#1128 #1137

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
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