Skip to content

Commit

Permalink
�fix: 경기 참여 로직 수정 (#254)
Browse files Browse the repository at this point in the history
* feat: 경기 상태, 유저 상태에 따라 다르게 버튼 렌더링

* chore: 주석 삭제

* feat: leagueInfo 컴포넌트화

* feat: 경기 참여 버튼 컴포넌트화

* feat: 대진표 생성 버튼 컴포넌트화

* feat: 컴포넌트 적용

* fix: 경기 취소로 수정

* fix: 참여 버튼 로직 변경

* feat: 경기 취소 상태 추가

* feat: 경기 관련 fetch 함수 toast 적용
  • Loading branch information
Yejin0O0 authored Nov 26, 2024
1 parent 5c3b243 commit 4d47533
Show file tree
Hide file tree
Showing 12 changed files with 421 additions and 213 deletions.
22 changes: 22 additions & 0 deletions components/club/LeagueDetail/LeagueInfo.tsx
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;
59 changes: 59 additions & 0 deletions components/club/LeagueDetail/MatchButton.tsx
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;
160 changes: 160 additions & 0 deletions components/club/LeagueDetail/ParticipateButton.tsx
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;
4 changes: 2 additions & 2 deletions components/pages/LiveMatchList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
useGetMainLeaguesMatch,
} from "@/lib/api/hooks/mainLeagueHook";
import { useGetMembersSession } from "@/lib/api/hooks/memberHook";
import type { LeagueStatus, TierLimit } from "@/types/leagueTypes";
import type { LeagueStatus, Tier } from "@/types/commonTypes";
import type {
GetMainLeagues,
GetMainLeaguesMatchData,
Expand Down Expand Up @@ -61,7 +61,7 @@ const renderLeagueStatusButton = (
}
};

const renderLeagueTierBadge = (tier: TierLimit) => {
const renderLeagueTierBadge = (tier: Tier) => {
if (tier === "GOLD") {
return (
<Badge
Expand Down
Loading

0 comments on commit 4d47533

Please sign in to comment.