-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 경기 상태, 유저 상태에 따라 다르게 버튼 렌더링 * chore: 주석 삭제 * feat: leagueInfo 컴포넌트화 * feat: 경기 참여 버튼 컴포넌트화 * feat: 대진표 생성 버튼 컴포넌트화 * feat: 컴포넌트 적용 * fix: 경기 취소로 수정 * fix: 참여 버튼 로직 변경 * feat: 경기 취소 상태 추가 * feat: 경기 관련 fetch 함수 toast 적용
- Loading branch information
Showing
12 changed files
with
421 additions
and
213 deletions.
There are no files selected for viewing
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,22 @@ | ||
interface LeagueInfoProps { | ||
icon: React.ElementType; | ||
label: string; // 제목 또는 레이블 | ||
value: string | number | null | undefined; // 값 (텍스트 또는 숫자) | ||
} | ||
|
||
function LeagueInfo(props: LeagueInfoProps) { | ||
const { icon: Icon, label, value } = props; | ||
return ( | ||
<div> | ||
<div className="p-4 bg-gray-100 rounded-lg flex items-center gap-3"> | ||
<Icon className="text-gray-500" size={24} /> | ||
<div> | ||
<p className="text-xs text-gray-500">{label}</p> | ||
<p className="text-sm font-semibold text-gray-800">{value}</p> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default LeagueInfo; |
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,59 @@ | ||
import { Button } from "@/components/ui/Button"; | ||
import type { GetLeagueDetailData } from "@/types/leagueTypes"; | ||
import { BookUser } from "lucide-react"; | ||
import Link from "next/link"; | ||
|
||
interface MatchButtonProps { | ||
clubId: string; | ||
leagueId: string; | ||
league: GetLeagueDetailData; | ||
createMatch: () => void; // 대진표 생성 함수 타입 정의; | ||
} | ||
|
||
const MatchButton = ({ | ||
leagueId, | ||
clubId, | ||
league, | ||
createMatch, | ||
}: MatchButtonProps) => { | ||
const matchCreateCondition = | ||
(league.league_status === "RECRUITING_COMPLETED" || | ||
league.league_status === "PLAYING") && | ||
!league?.is_match_created; | ||
|
||
if (matchCreateCondition) { | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="items-center justify-center gap-2 border-primary w-1/3 hover:bg-white hover:text-primary" | ||
onClick={createMatch} | ||
> | ||
<BookUser size={20} /> | ||
대진표 생성 | ||
</Button> | ||
); | ||
} | ||
|
||
if (league.is_match_created) { | ||
return ( | ||
<Link | ||
href={`/club/${clubId}/league/${leagueId}/match`} | ||
className="flex justify-center items-center gap-4 w-1/3" | ||
> | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="items-center justify-center gap-2 border-primary w-full" | ||
> | ||
<BookUser size={20} /> | ||
대진표 보기 | ||
</Button> | ||
</Link> | ||
); | ||
} | ||
|
||
return null; | ||
}; | ||
|
||
export default MatchButton; |
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,160 @@ | ||
import { Button } from "@/components/ui/Button"; | ||
import type { Tier } from "@/types/commonTypes"; | ||
import type { GetLeagueDetailData } from "@/types/leagueTypes"; | ||
import type { GetMemberSessionResponse } from "@/types/memberTypes"; | ||
import { User } from "lucide-react"; | ||
import { useRouter } from "next/navigation"; | ||
import type React from "react"; | ||
|
||
interface ParticipateButtonProps { | ||
league: GetLeagueDetailData; | ||
loginedUser: GetMemberSessionResponse; | ||
handleParticipate: (status: boolean) => void; | ||
isParticipating: boolean; | ||
} | ||
|
||
const canParticipate = (userTier: Tier, requiredTier: Tier): boolean => { | ||
if (userTier === "GOLD") { | ||
return true; // GOLD 티어는 모든 경기에 참가 가능 | ||
} | ||
|
||
if (userTier === "SILVER") { | ||
return requiredTier === "SILVER" || requiredTier === "BRONZE"; | ||
// SILVER 티어는 SILVER, BRONZE 경기에 참가 가능 | ||
} | ||
|
||
if (userTier === "BRONZE") { | ||
return requiredTier === "BRONZE"; | ||
// BRONZE 티어는 BRONZE 경기에만 참가 가능 | ||
} | ||
|
||
// 위 조건에 해당하지 않는 경우 참가 불가 | ||
return false; | ||
}; | ||
|
||
function ParticipateButton({ | ||
league, | ||
loginedUser, | ||
handleParticipate, | ||
isParticipating, | ||
}: ParticipateButtonProps) { | ||
const router = useRouter(); | ||
|
||
// 리그 생성자 여부 확인 | ||
const isLeagueOwner = | ||
loginedUser?.data?.member_token === league.league_owner_token; | ||
|
||
// 모집 상태 확인 (RECRUITING 또는 RECRUITING_COMPLETED 상태 포함) | ||
const isRecruitingOrCompleted = | ||
league.league_status === "RECRUITING" || | ||
league.league_status === "RECRUITING_COMPLETED"; | ||
|
||
// 모집 인원 초과 여부 확인 | ||
const isFull = league.recruited_member_count === league.player_limit_count; | ||
|
||
// 사용자 티어와 리그 티어 비교 | ||
const canUserParticipate = | ||
loginedUser && | ||
canParticipate(loginedUser?.data?.member_tier, league.required_tier); | ||
|
||
if (league.league_status === "CANCELED") { | ||
return null; | ||
} | ||
|
||
// 로그인 하지 않은 사용자 처리 | ||
if (loginedUser.result === "FAIL") { | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="items-center justify-center gap-2 border-primary w-1/3 hover:bg-white hover:text-primary" | ||
onClick={() => router.push("/login")} | ||
> | ||
<User size={20} /> | ||
경기 참가 | ||
</Button> | ||
); | ||
} | ||
|
||
// 경기 생성자 처리 | ||
if (isLeagueOwner) { | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="cursor-not-allowed items-center justify-center gap-2 border-primary w-1/3 border-zinc-300 text-zinc-500 hover:bg-white hover:text-zinc-500" | ||
> | ||
경기 생성자는 참가 취소를 할 수 없습니다 | ||
</Button> | ||
); | ||
} | ||
|
||
// 모집중 또는 모집 완료 상태가 아닌 경우 처리 | ||
if (!isRecruitingOrCompleted) { | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="cursor-not-allowed items-center justify-center gap-2 border-primary w-1/3 border-zinc-300 text-zinc-500 hover:bg-white hover:text-zinc-500" | ||
> | ||
모집중인 경기가 아닙니다 | ||
</Button> | ||
); | ||
} | ||
|
||
// 참여 신청 한 사람 처리 | ||
if (isParticipating) { | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="destructive" | ||
className="items-center justify-center gap-2 border-primary w-1/3" | ||
onClick={() => handleParticipate(true)} | ||
> | ||
<User size={20} /> | ||
참가 취소 | ||
</Button> | ||
); | ||
} | ||
|
||
// 지원할 수 있는 티어가 아닐 때 처리 | ||
if (!canUserParticipate) { | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="cursor-not-allowed items-center justify-center gap-2 border-primary w-1/3 border-zinc-300 text-zinc-500 hover:bg-white hover:text-zinc-500" | ||
> | ||
지원할 수 있는 티어가 아닙니다 | ||
</Button> | ||
); | ||
} | ||
|
||
// 모집 인원이 가득 찼을 때 처리 | ||
if (isFull) { | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="cursor-not-allowed items-center justify-center gap-2 border-primary w-1/3 border-zinc-300 text-zinc-500 hover:bg-white hover:text-zinc-500" | ||
> | ||
모집 인원이 가득 찼습니다 | ||
</Button> | ||
); | ||
} | ||
|
||
// 참가 신청 가능 버튼 | ||
return ( | ||
<Button | ||
size="lg" | ||
variant="outline" | ||
className="items-center justify-center gap-2 border-primary w-1/3 hover:bg-white hover:text-primary" | ||
onClick={() => handleParticipate(false)} | ||
> | ||
<User size={20} /> | ||
경기 참가 | ||
</Button> | ||
); | ||
} | ||
|
||
export default ParticipateButton; |
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
Oops, something went wrong.