diff --git a/components/main/Section.tsx b/components/main/Section.tsx index e4d0e1c83..e00303f4a 100644 --- a/components/main/Section.tsx +++ b/components/main/Section.tsx @@ -17,6 +17,7 @@ export default function Section({ sectionTitle, path }: SectionProps) { const pathCheck: pathType = { game: , rank: , + tournament: <>, }; return ( diff --git a/components/modal/ModalProvider.tsx b/components/modal/ModalProvider.tsx index 1b6f6d4d6..abbf1aa7f 100644 --- a/components/modal/ModalProvider.tsx +++ b/components/modal/ModalProvider.tsx @@ -6,6 +6,7 @@ import AdminModal from 'components/modal/modalType/AdminModal'; import NormalModal from 'components/modal/modalType/NormalModal'; import StoreModal from 'components/modal/modalType/StoreModal'; import styles from 'styles/modal/Modal.module.scss'; +import TournamentModal from './modalType/TournamentModal'; export default function ModalProvider() { const [{ modalName }, setModal] = useRecoilState(modalState); @@ -43,6 +44,8 @@ export default function ModalProvider() { ) : modalType === 'ADMIN' ? ( + ) : modalType === 'TOURNAMENT' ? ( + ) : null} ) diff --git a/components/modal/modalType/TournamentModal.tsx b/components/modal/modalType/TournamentModal.tsx new file mode 100644 index 000000000..aea7d3053 --- /dev/null +++ b/components/modal/modalType/TournamentModal.tsx @@ -0,0 +1,16 @@ +import { useRecoilValue } from 'recoil'; +import { modalState } from 'utils/recoil/modal'; +import TournamentRegistryModal from '../tournament/TournamentRegistryModal'; + +export default function TournamentModal() { + const { modalName, tournamentInfo } = useRecoilValue(modalState); + + const content: { [key: string]: JSX.Element | null } = { + 'TOURNAMENT-REGISTRY': tournamentInfo ? ( + + ) : null, + }; + + if (!modalName) return null; + return content[modalName]; +} diff --git a/components/modal/tournament/TournamentRegistryModal.tsx b/components/modal/tournament/TournamentRegistryModal.tsx new file mode 100644 index 000000000..b6bf5b652 --- /dev/null +++ b/components/modal/tournament/TournamentRegistryModal.tsx @@ -0,0 +1,67 @@ +import dynamic from 'next/dynamic'; +import { useSetRecoilState } from 'recoil'; +import { TournamentInfo } from 'types/modalTypes'; +import { QUILL_FORMATS } from 'types/quillTypes'; +import { modalState } from 'utils/recoil/modal'; +import { + ModalButtonContainer, + ModalButton, +} from 'components/modal/ModalButton'; +import styles from 'styles/modal/event/AnnouncementModal.module.scss'; +import 'react-quill/dist/quill.bubble.css'; + +const Quill = dynamic(() => import('react-quill'), { + ssr: false, + loading: () =>

Loading ...

, +}); + +export default function TournamentRegistryModal({ + title, + contents, + startDate, + status, + type, + winnerId, + winnerImage, + endDate, +}: TournamentInfo) { + const setModal = useSetRecoilState(modalState); + + const registTournament = () => { + console.log('토너먼트에 등록하시겠습니까.'); + }; + + const closeModalButtonHandler = () => { + setModal({ modalName: null }); + }; + + return ( +
+
{title}
+
{startDate}
+ +
+ + + + + + +
+
+ ); +} diff --git a/components/rank/topRank/RankListMain.tsx b/components/rank/topRank/RankListMain.tsx index cecf97d2a..4b3160d7d 100644 --- a/components/rank/topRank/RankListMain.tsx +++ b/components/rank/topRank/RankListMain.tsx @@ -53,8 +53,10 @@ export default function RankListMain({ isMain, season }: RankListMainProps) { )); return ( -
-
{bangElements}
+ <> + {!isMain && ( +
{bangElements}
+ )}
{rank !== undefined && rank.map((item: userImages, index: number) => ( @@ -65,7 +67,7 @@ export default function RankListMain({ isMain, season }: RankListMainProps) { /> ))}
-
+ ); } diff --git a/components/tournament/TournamentCard.tsx b/components/tournament/TournamentCard.tsx new file mode 100644 index 000000000..5af6c76e3 --- /dev/null +++ b/components/tournament/TournamentCard.tsx @@ -0,0 +1,20 @@ +import { TournamentInfo } from 'types/modalTypes'; +import styles from 'styles/tournament/TournamentCard.module.scss'; + +export default function TournamentCard({ + tournametId, + title, + contents, + startDate, + status, + type, + winnerId, + winnerImage, + endDate, +}: TournamentInfo) { + return ( +
+
{title}
+
+ ); +} diff --git a/pages/index.tsx b/pages/index.tsx index 14a26465b..9ceb0d2c3 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -9,6 +9,9 @@ const Home: NextPage = () => {
+
+
+
diff --git a/pages/tournament-record.tsx b/pages/tournament-record.tsx new file mode 100644 index 000000000..d4df96761 --- /dev/null +++ b/pages/tournament-record.tsx @@ -0,0 +1,24 @@ +import styles from 'styles/tournament-record/TournamentRecord.module.scss'; + +export default function TournamentRecord() { + return ( +
+

명예의 전당

+
+ + + +
+
우승자 이미지들
+
+

cadet2147

+

+ 제 5회 정기 토너먼트 루키리그{' '} + 우승자 +

+

2023.11.11

+
+
+
+ ); +} diff --git a/pages/tournament.tsx b/pages/tournament.tsx new file mode 100644 index 000000000..5626b6070 --- /dev/null +++ b/pages/tournament.tsx @@ -0,0 +1,73 @@ +import { useSetRecoilState } from 'recoil'; +import { Modal } from 'types/modalTypes'; +import { modalState } from 'utils/recoil/modal'; +import TournamentCard from 'components/tournament/TournamentCard'; +import styles from 'styles/tournament/TournamentContainer.module.scss'; + +// 내부의 토너먼트 보여주는 부분만 Component화 하면될까? 다른곳에서도 쓰일까? +// 진행중인 토너먼트의 Bracket을 보여주는 부분도 다른곳에서도 쓸수있지않나? +const tempData = { + tournaments: [ + { + tournametId: 5, + title: '5회 루키 토너먼트', + contents: '블라블라', + startDate: '2023-11-11', + status: '종료', + type: 'rookie', + winnerId: 'hannkim', + winnerImage: '', + endDate: '2023-11-11', + }, + { + tournametId: 6, + title: '6회 마스터 토너먼트', + contents: '블라블라 하이하이', + startDate: '2023-11-12', + status: '진행중', + type: 'master', + winnerId: 'hannkim', + winnerImage: '', + endDate: '2023-11-12', + }, + ], + totalPage: 100, +}; + +export default function Tournament() { + const setModal = useSetRecoilState(modalState); + + const handleTournament = () => { + setModal({ + modalName: 'TOURNAMENT-REGISTRY', + tournamentInfo: { + tournametId: 5, + title: '5회 루키 토너먼트', + contents: '블라블라', + startDate: '2023-11-11', + status: '종료', + type: 'rookie', + winnerId: 'hannkim', + winnerImage: '', + endDate: '2023-11-11', + }, + }); + }; + return ( +
+

Tournament

+
+
대기중인 토너먼트
+
+ {tempData.tournaments.map((tournament, index) => ( + + ))} +
+
진행중인 토너먼트
+
+
무언가 토너먼트의 사진
+
+
+
+ ); +} diff --git a/styles/main/Section.module.scss b/styles/main/Section.module.scss index a220211e3..eecec2c95 100644 --- a/styles/main/Section.module.scss +++ b/styles/main/Section.module.scss @@ -2,7 +2,6 @@ .sectionWrap { position: relative; - z-index: 1; margin-top: 2.5rem; &.mainRank { margin-top: 1rem; @@ -23,6 +22,7 @@ align-items: center; } > button { + z-index: 10; width: 1.563rem; height: 1.563rem; color: #ffffff; diff --git a/styles/rank/RankListMain.module.scss b/styles/rank/RankListMain.module.scss index a0b1f3b78..161f037ed 100644 --- a/styles/rank/RankListMain.module.scss +++ b/styles/rank/RankListMain.module.scss @@ -1,5 +1,9 @@ @import 'styles/common.scss'; +.RankContainer { + z-index: 0; +} + .mainContainer { position: relative; top: 1.5rem; @@ -11,7 +15,6 @@ align-items: end; &.isMain { height: 15.5rem; - margin-top: 7.5rem; } } @@ -82,8 +85,9 @@ .bangContainer { display: flex; - justify-content: space-around; margin-top: -7.5rem; + pointer-events: none; + justify-content: space-around; } .bang { diff --git a/styles/tournament-record/TournamentRecord.module.scss b/styles/tournament-record/TournamentRecord.module.scss new file mode 100644 index 000000000..f344867df --- /dev/null +++ b/styles/tournament-record/TournamentRecord.module.scss @@ -0,0 +1,69 @@ +@import 'styles/common.scss'; + +.pageWrap { + @include pageWrap; +} + +.title { + @include pageTitle; + display: flex; + justify-content: center; +} + +.leagueButtonWrapper { + display: flex; + padding-right: 1.5rem; + padding-left: 1.5rem; + margin-top: 1.4rem; + justify-content: space-between; + + button { + font-size: 1rem; + font-weight: 400; + color: #cbcbcb; + background-color: transparent; + border-color: transparent; + } +} + +.winnerImageContainer { + height: 10rem; + margin-top: 1.8rem; + background-color: rgb(88, 88, 88); +} + +.winnerInfoContainer { + font-weight: 500; + color: #d591ff; + text-align: center; + + p { + margin: 0.4rem 0 0; + } + + .userId { + font-weight: 700; + color: white; + } + + .gameInfo { + font-size: 1rem; + + .highlighted { + color: #ffc700; + } + } + + .date { + font-size: 0.8rem; + } +} + +.bracketContainer { + width: 100%; + height: 21.5rem; + margin-top: 1rem; + background-color: rgba(112, 0, 255, 0.17); + border: 1px solid #c67dff; + border-radius: 26px; +} diff --git a/styles/tournament/TournamentCard.module.scss b/styles/tournament/TournamentCard.module.scss new file mode 100644 index 000000000..c175a9325 --- /dev/null +++ b/styles/tournament/TournamentCard.module.scss @@ -0,0 +1,16 @@ +.tournamentCardContainer { + display: flex; + width: 100%; + padding: 1rem; + margin-bottom: 1rem; + background-color: black; + border: 2px solid black; + border-radius: 0.3rem; + + .text { + overflow: hidden; + color: white; + text-overflow: ellipsis; + white-space: nowrap; + } +} diff --git a/styles/tournament/TournamentContainer.module.scss b/styles/tournament/TournamentContainer.module.scss new file mode 100644 index 000000000..6adb9e781 --- /dev/null +++ b/styles/tournament/TournamentContainer.module.scss @@ -0,0 +1,67 @@ +@import 'styles/common.scss'; + +.pageWrap { + @include pageWrap; +} + +.title { + @include pageTitle; + width: fit-content; + cursor: pointer; +} + +.tournamentContainer { + display: flex; + height: 60vh; + flex-direction: column; + padding: 1rem 1rem 0rem; + overflow-y: scroll; + background: #d4b8f2; + border-radius: $small-radius; +} + +.waitTournamentBox { + display: flex; + width: 100%; + flex: 5; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 3rem 1rem 0; + overflow-x: hidden; + overflow-y: scroll; + background: rgba(112, 0, 255, 0.17); + border: 2px solid #c67dff; + border-radius: 0.3rem; +} + +.openTournamentBox { + display: flex; + width: 100%; + flex: 15; + flex-direction: column; + padding: 0.2rem 0 0.2rem 0.2rem; + margin-bottom: 1rem; + overflow-x: scroll; + overflow-y: scroll; + background: rgba(112, 0, 255, 0.17); + border: 2px solid #c67dff; + border-radius: 0.3rem; +} + +.tournamentTextWait { + display: flex; + flex: 1; + font-weight: 700; + color: black; + text-align: center; /* 텍스트를 가로로 중앙에 정렬 */ +} + +.tournamentTextOpen { + display: flex; + flex: 1; + padding-top: 1rem; + font-weight: 700; + color: black; + text-align: center; /* 텍스트를 가로로 중앙에 정렬 */ +} diff --git a/types/modalTypes.ts b/types/modalTypes.ts index 27906a532..b03d0fcdd 100644 --- a/types/modalTypes.ts +++ b/types/modalTypes.ts @@ -27,8 +27,11 @@ type PurchaseModal = 'BUY' | 'GIFT' | 'NO_COIN'; type UseItemModal = ItemType | 'GACHA'; type EditItemModal = 'MEGAPHONE'; + type StoreModal = 'MANUAL' | 'COIN_HISTORY'; +type TournamentModal = 'REGISTRY'; + type AdminModal = | 'PROFILE' | 'USER-COIN' @@ -59,7 +62,8 @@ type ModalName = | `USE-ITEM-${UseItemModal}` | `EDIT-ITEM-${EditItemModal}` | `STORE-${StoreModal}` - | `PURCHASE-${PurchaseModal}`; + | `PURCHASE-${PurchaseModal}` + | `TOURNAMENT-${TournamentModal}`; export interface Cancel { startTime: string; @@ -88,6 +92,18 @@ export interface Manual { radioMode: MatchMode; } +export interface TournamentInfo { + tournametId: number; + title: string; + contents: string; + startDate: string; + status: string; + type: string; + winnerId: string; + winnerImage?: string | null; + endDate: string; +} + export interface PriceTag { itemId: number; product: string; @@ -129,4 +145,5 @@ export interface Modal { isAttended?: boolean; totalCoin?: ICoin; randomItem?: IRandomItem; + tournamentInfo?: TournamentInfo; } diff --git a/utils/recoil/modal.ts b/utils/recoil/modal.ts index 5821a6ba7..f0f1911c8 100644 --- a/utils/recoil/modal.ts +++ b/utils/recoil/modal.ts @@ -13,12 +13,15 @@ export const modalTypeState = selector({ let modalType = ''; const normalPrefixes = ['EVENT', 'MENU', 'MATCH', 'USER', 'FIXED']; const storePrefixes = ['COIN', 'STORE', 'PURCHASE', 'USE', 'EDIT']; + const tournamentPrefixes = ['TOURNAMENT']; const prefix = get(modalState).modalName?.split('-')[0] || ''; if (normalPrefixes.includes(prefix)) { modalType = 'NORMAL'; } else if (storePrefixes.includes(prefix)) { modalType = 'STORE'; + } else if (tournamentPrefixes.includes(prefix)) { + modalType = 'TOURNAMENT'; } else if (prefix === 'ADMIN') { modalType = 'ADMIN'; }