diff --git a/src/app/match/[id]/page.tsx b/src/app/match/[id]/page.tsx index f7fe3da..5ef4ff4 100644 --- a/src/app/match/[id]/page.tsx +++ b/src/app/match/[id]/page.tsx @@ -66,7 +66,7 @@ export default function Match({ params }: { params: { id: string } }) { } - loadingFallback={
응원 로딩중...
} + loadingFallback={} > {data => } @@ -113,7 +113,7 @@ export default function Match({ params }: { params: { id: string } }) { loadingFallback={} > - {({ commentList, ...data }) => ( + {({ commentList, matchTeams, ...data }) => (
+
diff --git a/src/components/common/MatchCard/pieces/Score.tsx b/src/components/common/MatchCard/pieces/Score.tsx index 58cebf2..becefff 100644 --- a/src/components/common/MatchCard/pieces/Score.tsx +++ b/src/components/common/MatchCard/pieces/Score.tsx @@ -8,6 +8,11 @@ type ScoreProps = { export default function Score({ teamIndex, className }: ScoreProps) { const { gameTeams } = useMatchCardContext(); + + if (gameTeams.length === 0) { + return -; + } + const targetTeam = gameTeams[teamIndex - 1]; return {targetTeam.score}; diff --git a/src/components/common/MatchCard/pieces/Team.tsx b/src/components/common/MatchCard/pieces/Team.tsx index 4379a14..bf745fa 100644 --- a/src/components/common/MatchCard/pieces/Team.tsx +++ b/src/components/common/MatchCard/pieces/Team.tsx @@ -11,6 +11,22 @@ type TeamProps = { export default function Team({ teamIndex, className }: TeamProps) { const { gameTeams } = useMatchCardContext(); + if (gameTeams.length === 0) { + return ( +
+ +
+ ); + } + const targetTeamInfo = gameTeams[teamIndex - 1]; return ( diff --git a/src/components/match/Banner/index.tsx b/src/components/match/Banner/index.tsx index e144156..5bd9034 100644 --- a/src/components/match/Banner/index.tsx +++ b/src/components/match/Banner/index.tsx @@ -3,6 +3,8 @@ import { MatchCard } from '@/components/common/MatchCard'; import { MatchType } from '@/types/match'; export default function MatchBanner(props: MatchType) { + const [firstTeam, secondTeam] = props.gameTeams; + return ( @@ -13,11 +15,17 @@ export default function MatchBanner(props: MatchType) { height={200} className="h-[200px]" /> - - + + - - + +
); diff --git a/src/components/match/CheerTeam/index.tsx b/src/components/match/CheerTeam/index.tsx index e23c300..f3e3e8d 100644 --- a/src/components/match/CheerTeam/index.tsx +++ b/src/components/match/CheerTeam/index.tsx @@ -15,9 +15,9 @@ export default function CheerTeam({ )} {...props} > -
+
+
); } diff --git a/src/components/match/CommentForm/index.tsx b/src/components/match/CommentForm/index.tsx index 0f075fb..0e3100e 100644 --- a/src/components/match/CommentForm/index.tsx +++ b/src/components/match/CommentForm/index.tsx @@ -1,54 +1,83 @@ import { UseMutateFunction } from '@tanstack/react-query'; -import { FormEvent, useState } from 'react'; +import { ChangeEvent, FormEvent, useState } from 'react'; -import { MatchCommentPayload } from '@/types/match'; +import { MatchCommentPayload, MatchTeamType } from '@/types/match'; type CommentFormProps = { matchId: string; + matchTeams: MatchTeamType[]; mutate: UseMutateFunction; scrollToBottom: () => void; }; export default function CommentForm({ matchId, + matchTeams, mutate, scrollToBottom, }: CommentFormProps) { const [inputValue, setInputValue] = useState(''); + const [selectedTeamId, setSelectedTeamId] = useState(1); + const [isOpen, toggleOpen] = useState(false); + const handleCommentSubmit = ( e: FormEvent, payload: MatchCommentPayload, ) => { e.preventDefault(); - mutate(payload); + mutate({ ...payload, gameTeamId: selectedTeamId }); setInputValue(''); scrollToBottom(); }; + const handleRadioClick = (e: ChangeEvent) => { + setSelectedTeamId(Number(e.target.value)); + }; + return ( -
- handleCommentSubmit(e, { - gameTeamId: Number(matchId), - content: inputValue, - }) - } - > -
+ + handleCommentSubmit(e, { + gameTeamId: Number(matchId), + content: inputValue, + }) + } > - setInputValue(e.target.value)} - placeholder="응원하는 팀에 댓글을 남겨보세요!" - /> - -
-
+ {isOpen && ( +
+ {matchTeams.map(team => ( + + ))} +
+ )} + +
+ setInputValue(e.target.value)} + placeholder="응원하는 팀에 댓글을 남겨보세요!" + onFocus={() => toggleOpen(true)} + /> + +
+ + ); } diff --git a/src/queries/useMatchCommentById/Fetcher.tsx b/src/queries/useMatchCommentById/Fetcher.tsx index 1ac5e28..4571778 100644 --- a/src/queries/useMatchCommentById/Fetcher.tsx +++ b/src/queries/useMatchCommentById/Fetcher.tsx @@ -1,7 +1,7 @@ import { InfiniteData } from '@tanstack/react-query'; import { ReactNode } from 'react'; -import { MatchCommentType } from '@/types/match'; +import { MatchCommentType, MatchTeamType } from '@/types/match'; import useMatchCommentById from './query'; @@ -9,11 +9,13 @@ type MatchCommentFetcherProps = { matchId: string; children: ({ commentList, + matchTeams, fetchNextPage, hasNextPage, isFetching, }: { commentList: InfiniteData; + matchTeams: MatchTeamType[]; fetchNextPage: () => void; hasNextPage: boolean; isFetching: boolean; @@ -24,10 +26,22 @@ export default function MatchCommentFetcher({ matchId, children, }: MatchCommentFetcherProps) { - const { commentList, error, fetchNextPage, hasNextPage, isFetching } = - useMatchCommentById(matchId); + const { + commentList, + matchTeams, + error, + fetchNextPage, + hasNextPage, + isFetching, + } = useMatchCommentById(matchId); if (error) throw error; - return children({ commentList, fetchNextPage, hasNextPage, isFetching }); + return children({ + commentList, + matchTeams, + fetchNextPage, + hasNextPage, + isFetching, + }); } diff --git a/src/queries/useMatchCommentById/query.ts b/src/queries/useMatchCommentById/query.ts index ae4d537..a4fbcdc 100644 --- a/src/queries/useMatchCommentById/query.ts +++ b/src/queries/useMatchCommentById/query.ts @@ -1,6 +1,10 @@ -import { useSuspenseInfiniteQuery } from '@tanstack/react-query'; +import { + useSuspenseInfiniteQuery, + useSuspenseQuery, +} from '@tanstack/react-query'; + +import { getMatchById, getMatchCommentById } from '@/api/match'; -import { getMatchCommentById } from '@/api/match'; export default function useMatchCommentById(matchId: string) { const { data, error, fetchNextPage, hasNextPage, isFetching } = useSuspenseInfiniteQuery({ @@ -14,11 +18,19 @@ export default function useMatchCommentById(matchId: string) { }), }); + const { data: matchTeams, error: matchError } = useSuspenseQuery({ + queryKey: ['match-detail', 'for-comment', matchId], + queryFn: () => getMatchById(matchId), + select: data => data.gameTeams, + }); + return { commentList: data, + matchTeams, fetchNextPage, hasNextPage, isFetching, error, + matchError, }; } diff --git a/src/queries/useMatchList/query.ts b/src/queries/useMatchList/query.ts index f406d60..267e0a7 100644 --- a/src/queries/useMatchList/query.ts +++ b/src/queries/useMatchList/query.ts @@ -18,7 +18,7 @@ export const useMatchList = ({ cursor: pageParam, }), initialPageParam: 0, - getNextPageParam: lastPage => lastPage[0]?.id || null, + getNextPageParam: lastPage => lastPage.at(-1)?.id || null, }); return { diff --git a/src/types/match.ts b/src/types/match.ts index 50f6222..9b2d8b6 100644 --- a/src/types/match.ts +++ b/src/types/match.ts @@ -15,6 +15,7 @@ export type MatchTeamType = { gameTeamName: string; logoImageUrl: string; score: number; + order: number; }; export type MatchCheerType = { @@ -52,6 +53,7 @@ export type MatchCommentType = { gameTeamId: number; createdAt: string; isBlocked: boolean; + order: number; }; export type MatchCommentPayload = Pick<