-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #149 from boostcampwm2023/138-대회-세부정보-페이지-생성
[#138] 대회 세부정보 페이지 생성
- Loading branch information
Showing
10 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
38 changes: 38 additions & 0 deletions
38
frontend/src/components/CompetitionDetail/AfterCompetition.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { css } from '@style/css'; | ||
|
||
import { CompetitionInfo } from '@/apis/competitions'; | ||
|
||
import CompetitionDetailInfo from './CompetitionDetailInfo'; | ||
import ProblemList from './ProblemList'; | ||
|
||
interface Props { | ||
competitionId: number; | ||
competition: CompetitionInfo; | ||
competitionSchedule: string; | ||
} | ||
|
||
const AFTER_COMPETITION_TEXT = ' 종료'; | ||
|
||
export default function AfterCompetition({ | ||
competitionId, | ||
competition, | ||
competitionSchedule, | ||
}: Props) { | ||
return ( | ||
<div className={containerStyle}> | ||
<CompetitionDetailInfo | ||
competition={competition} | ||
text={AFTER_COMPETITION_TEXT} | ||
competitionSchedule={competitionSchedule} | ||
/> | ||
<ProblemList competitionId={competitionId} /> | ||
</div> | ||
); | ||
} | ||
|
||
const containerStyle = css({ | ||
justifyContent: 'space-between', | ||
alignItems: 'center', | ||
padding: '16px', | ||
border: '1px solid #ccc', | ||
}); |
51 changes: 51 additions & 0 deletions
51
frontend/src/components/CompetitionDetail/BeforeCompetition.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { css } from '@style/css'; | ||
|
||
import { CompetitionInfo } from '@/apis/competitions'; | ||
|
||
import JoinCompetitionButton from '../Main/Buttons/JoinCompetitionButton'; | ||
import EnterCompetitionButton from './Buttons/EnterCompetitionButton'; | ||
import CompetitionDetailInfo from './CompetitionDetailInfo'; | ||
|
||
interface Props { | ||
competitionId: number; | ||
competition: CompetitionInfo; | ||
startsAt: Date; | ||
endsAt: Date; | ||
competitionSchedule: string; | ||
} | ||
|
||
export default function BeforeCompetition({ | ||
competitionId, | ||
competition, | ||
startsAt, | ||
endsAt, | ||
competitionSchedule, | ||
}: Props) { | ||
const BEFORE_COMPETITION_TEXT = ` 시작 전`; | ||
|
||
return ( | ||
<div className={containerStyle}> | ||
<CompetitionDetailInfo | ||
competition={competition} | ||
text={BEFORE_COMPETITION_TEXT} | ||
competitionSchedule={competitionSchedule} | ||
/> | ||
<div className={buttonContainerStyle}> | ||
<JoinCompetitionButton id={competitionId} /> | ||
<EnterCompetitionButton id={competitionId} startsAt={startsAt} endsAt={endsAt} /> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
const containerStyle = css({ | ||
justifyContent: 'space-between', | ||
alignItems: 'center', | ||
padding: '16px', | ||
border: '1px solid #ccc', | ||
}); | ||
|
||
const buttonContainerStyle = css({ | ||
display: 'flex', | ||
gap: '16px', | ||
}); |
34 changes: 34 additions & 0 deletions
34
frontend/src/components/CompetitionDetail/Buttons/EnterCompetitionButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import useAuth from '@/hooks/login/useAuth'; | ||
|
||
interface Props { | ||
id: number; | ||
startsAt: Date; | ||
endsAt: Date; | ||
} | ||
|
||
export default function EnterCompetitionButton({ id, startsAt, endsAt }: Props) { | ||
const competitionLink = `/contest/${id}`; | ||
const { isLoggedin } = useAuth(); | ||
const navigate = useNavigate(); | ||
|
||
const handleNavigate = () => { | ||
const currentTime = new Date(); | ||
|
||
if (!isLoggedin) { | ||
alert('로그인이 필요합니다.'); | ||
navigate('/login'); | ||
} else if (currentTime < startsAt) { | ||
alert('아직 대회가 시작되지 않았습니다. 다시 시도해주세요'); | ||
window.location.reload(); | ||
} else if (currentTime >= endsAt) { | ||
alert('해당 대회는 종료되었습니다.'); | ||
window.location.reload(); | ||
} else { | ||
navigate(competitionLink); | ||
} | ||
}; | ||
|
||
return <button onClick={handleNavigate}>대회 입장</button>; | ||
} |
39 changes: 39 additions & 0 deletions
39
frontend/src/components/CompetitionDetail/CompetitionDetailContent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// CompetitionDetailContent.js | ||
import { CompetitionInfo } from '@/apis/competitions'; | ||
import AfterCompetition from '@/components/CompetitionDetail/AfterCompetition'; | ||
import BeforeCompetition from '@/components/CompetitionDetail/BeforeCompetition'; | ||
import DuringCompetition from '@/components/CompetitionDetail/DuringCompetition'; | ||
|
||
interface Props { | ||
competitionId: number; | ||
competition: CompetitionInfo; | ||
startsAt: Date; | ||
endsAt: Date; | ||
competitionSchedule: string; | ||
} | ||
|
||
export function CompetitionDetailContent({ | ||
competitionId, | ||
competition, | ||
startsAt, | ||
endsAt, | ||
competitionSchedule, | ||
}: Props) { | ||
const currentDate = new Date(); | ||
|
||
if (currentDate < startsAt) { | ||
return ( | ||
<BeforeCompetition | ||
{...{ competitionId, competition, startsAt, endsAt, competitionSchedule }} | ||
/> | ||
); | ||
} else if (currentDate < endsAt) { | ||
return ( | ||
<DuringCompetition | ||
{...{ competitionId, competition, startsAt, endsAt, competitionSchedule }} | ||
/> | ||
); | ||
} else { | ||
return <AfterCompetition {...{ competitionId, competition, competitionSchedule }} />; | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
frontend/src/components/CompetitionDetail/CompetitionDetailInfo.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { css } from '@style/css'; | ||
|
||
import { CompetitionInfo } from '@/apis/competitions'; | ||
|
||
interface Props { | ||
competition: CompetitionInfo; | ||
text: string; | ||
competitionSchedule: string; | ||
} | ||
|
||
export default function CompetitionDetailInfo({ competition, text, competitionSchedule }: Props) { | ||
return ( | ||
<div className={infoContainerStyle}> | ||
<div> | ||
<span className={competitionNameStyle}>{competition.name}</span> | ||
<span className={statusTextStyle}>{text}</span> | ||
</div> | ||
<span className={statusTextStyle}>{competitionSchedule}</span> | ||
<div className={additionalTextStyle}>{competition.detail}</div> | ||
</div> | ||
); | ||
} | ||
|
||
const infoContainerStyle = css({ | ||
display: 'flex', | ||
flexDirection: 'column', | ||
}); | ||
|
||
const competitionNameStyle = css({ | ||
fontSize: '18px', | ||
fontWeight: 'bold', | ||
color: 'black', | ||
marginBottom: '8px', | ||
}); | ||
|
||
const statusTextStyle = css({ | ||
fontSize: '12px', | ||
color: 'gray', | ||
marginBottom: '8px', | ||
}); | ||
|
||
const additionalTextStyle = css({ | ||
fontSize: '14px', | ||
color: 'black', | ||
marginBottom: '8px', | ||
}); |
42 changes: 42 additions & 0 deletions
42
frontend/src/components/CompetitionDetail/DuringCompetition.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { css } from '@style/css'; | ||
|
||
import { CompetitionInfo } from '@/apis/competitions'; | ||
|
||
import EnterCompetitionButton from './Buttons/EnterCompetitionButton'; | ||
import CompetitionDetailInfo from './CompetitionDetailInfo'; | ||
|
||
interface Props { | ||
competitionId: number; | ||
competition: CompetitionInfo; | ||
startsAt: Date; | ||
endsAt: Date; | ||
competitionSchedule: string; | ||
} | ||
|
||
const DURING_COMPETITION_TEXT = ' 진행중'; | ||
|
||
export default function DuringCompetition({ | ||
competitionId, | ||
competition, | ||
startsAt, | ||
endsAt, | ||
competitionSchedule, | ||
}: Props) { | ||
return ( | ||
<div className={containerStyle}> | ||
<CompetitionDetailInfo | ||
competition={competition} | ||
text={DURING_COMPETITION_TEXT} | ||
competitionSchedule={competitionSchedule} | ||
/> | ||
<EnterCompetitionButton id={competitionId} startsAt={startsAt} endsAt={endsAt} /> | ||
</div> | ||
); | ||
} | ||
|
||
const containerStyle = css({ | ||
justifyContent: 'space-between', | ||
alignItems: 'center', | ||
padding: '16px', | ||
border: '1px solid #ccc', | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Link } from 'react-router-dom'; | ||
|
||
import { useCompetitionProblemList } from '@/hooks/problem'; | ||
|
||
interface Props { | ||
competitionId: number; | ||
} | ||
|
||
export default function ProblemList({ competitionId }: Props) { | ||
const { problemList } = useCompetitionProblemList(competitionId); | ||
|
||
return ( | ||
<div> | ||
<table> | ||
<thead> | ||
<tr> | ||
<th>번호</th> | ||
<th>문제 제목</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{problemList.map((problem) => ( | ||
<tr key={problem.id}> | ||
<td>{problem.id}</td> | ||
<td> | ||
<Link to={`/problem/${problem.id}`}>{problem.title}</Link> | ||
</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { useParams } from 'react-router-dom'; | ||
|
||
import { CompetitionDetailContent } from '@/components/CompetitionDetail/CompetitionDetailContent'; | ||
import Header from '@/components/Header'; | ||
import { useCompetition } from '@/hooks/competition'; | ||
import { formatDate } from '@/utils/date'; | ||
|
||
export default function CompetitionDetailPage() { | ||
const { id } = useParams<{ id: string }>(); | ||
const competitionId: number = id ? parseInt(id, 10) : -1; | ||
const { competition } = useCompetition(competitionId); | ||
// 대회 상태에 따른 페이지를 구성하기 위해 현재 날짜, 시작 시간, 종료 시간을 가져옴 | ||
const startsAt = new Date(competition?.startsAt || ''); | ||
const endsAt = new Date(competition?.endsAt || ''); | ||
const formattedStartsAt = formatDate(startsAt, 'YYYY. MM. DD. hh:mm'); | ||
const formattedEndsAt = formatDate(endsAt, 'YYYY. MM. DD. hh:mm'); | ||
|
||
const competitionSchedule = `시작: ${formattedStartsAt} 종료: ${formattedEndsAt}`; | ||
|
||
return ( | ||
<div> | ||
<Header /> | ||
<CompetitionDetailContent | ||
competitionId={competitionId} | ||
competition={competition} | ||
startsAt={startsAt} | ||
endsAt={endsAt} | ||
competitionSchedule={competitionSchedule} | ||
/> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters