Skip to content

Commit

Permalink
feat: 루미큐브 페이지 및 컴포넌트 추가'
Browse files Browse the repository at this point in the history
feat: 루미큐브 페이지 추가
  • Loading branch information
seongminn committed Nov 28, 2023
1 parent 086d62c commit cf4fbb4
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 27 deletions.
160 changes: 160 additions & 0 deletions src/app/rummikube/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
'use client';

import { useRef, useState } from 'react';

import AsyncBoundary from '@/components/common/AsyncBoundary';
import Loader from '@/components/common/Loader';
import CommentForm from '@/components/match/CommentForm';
import CommentList from '@/components/match/CommentList';
import Lineup from '@/components/match/LineupList';
import Panel from '@/components/match/Panel';
import RecordList from '@/components/match/RecordList';
import Video from '@/components/match/Video';
import Cheer from '@/components/rummikub/Cheer';
import RummiKubMatchBanner from '@/components/rummikub/MatchBanner';
import useSocket from '@/hooks/useSocket';
import MatchByIdFetcher from '@/queries/useMatchById/Fetcher';
import MatchCheerByIdFetcher from '@/queries/useMatchCheerById/Fetcher';
import MatchCommentFetcher from '@/queries/useMatchCommentById/Fetcher';
import MatchLineupFetcher from '@/queries/useMatchLineupById/Fetcher';
import MatchTimelineFetcher from '@/queries/useMatchTimelineById/Fetcher';
import MatchVideoFetcher from '@/queries/useMatchVideoById/Fetcher';
import useSaveCommentMutation from '@/queries/useSaveCommentMutation/query';
import { MatchCommentType } from '@/types/match';

export default function Rummikute({ params }: { params: { id: string } }) {
const [comments, setComments] = useState<MatchCommentType[]>([]);

const handleSocketMessage = (comment: MatchCommentType) => {
if (comment) {
setComments(prev => [...prev, comment]);
}
};

const { connect } = useSocket({
url: 'wss://api.hufstreaming.site/ws',
destination: `/topic/games/${params.id}`,
callback: handleSocketMessage,
});

connect();

const { mutate } = useSaveCommentMutation();
const options = [
{ label: '라인업' },
{ label: '응원댓글' },
{ label: '경기영상' },
{ label: '타임라인' },
];

const scrollRef = useRef(null);
const scrollToBottom = () => {
if (!scrollRef.current) return;

(scrollRef.current as HTMLDivElement).scrollIntoView();
};

return (
<section>
<AsyncBoundary
errorFallback={props => (
<RummiKubMatchBanner.ErrorFallback {...props} />
)}
loadingFallback={<RummiKubMatchBanner.Skeleton />}
>
<MatchByIdFetcher matchId={params.id}>
{data => <RummiKubMatchBanner {...data} />}
</MatchByIdFetcher>
</AsyncBoundary>

<AsyncBoundary
errorFallback={props => <Cheer.ErrorFallback {...props} />}
loadingFallback={<Loader />}
>
<MatchCheerByIdFetcher matchId={params.id}>
{data => <Cheer cheers={data} />}
</MatchCheerByIdFetcher>
</AsyncBoundary>
<Panel options={options} defaultValue="라인업">
{({ selected }) => (
<>
{selected === '라인업' && (
<AsyncBoundary
errorFallback={props => <Lineup.ErrorFallback {...props} />}
loadingFallback={<Loader />}
>
<MatchLineupFetcher matchId={params.id}>
{([firstTeam, secondTeam]) => (
<div className="grid grid-cols-2 py-5 [&>*:first-child>ul]:before:absolute [&>*:first-child>ul]:before:right-0 [&>*:first-child>ul]:before:h-full [&>*:first-child>ul]:before:border-l-2 [&>*:first-child>ul]:before:bg-gray-2">
<Lineup {...firstTeam} />
<Lineup {...secondTeam} />
</div>
)}
</MatchLineupFetcher>
</AsyncBoundary>
)}
{selected === '타임라인' && (
<AsyncBoundary
errorFallback={props => <RecordList.ErrorFallback {...props} />}
loadingFallback={<Loader />}
>
<MatchTimelineFetcher matchId={params.id}>
{([firstHalf, secondHalf]) => (
<div className="overflow-y-auto p-5">
<RecordList {...firstHalf} />
<RecordList {...secondHalf} />
</div>
)}
</MatchTimelineFetcher>
</AsyncBoundary>
)}
{selected === '응원댓글' && (
<AsyncBoundary
errorFallback={props => (
<CommentList.ErrorFallback {...props} />
)}
loadingFallback={<Loader />}
>
<MatchCommentFetcher matchId={params.id}>
{({ commentList, matchTeams, ...data }) => (
<div className="max-h-[450px] overflow-y-auto p-5">
<ul className="pb-8">
<CommentList
commentList={commentList.pages.flat()}
scrollToBottom={scrollToBottom}
{...data}
/>
<CommentList.SocketList commentList={comments} />
<li ref={scrollRef}></li>
</ul>
<CommentForm
matchTeams={matchTeams}
matchId={params.id}
mutate={mutate}
scrollToBottom={scrollToBottom}
/>
</div>
)}
</MatchCommentFetcher>
</AsyncBoundary>
)}
{selected === '경기영상' && (
<AsyncBoundary
errorFallback={props => <Video.ErrorFallback {...props} />}
loadingFallback={<Loader />}
>
<MatchVideoFetcher matchId={params.id}>
{data => (
<div className="overflow-y-auto p-5">
<Video {...data} />
</div>
)}
</MatchVideoFetcher>
</AsyncBoundary>
)}
</>
)}
</Panel>
</section>
);
}
69 changes: 42 additions & 27 deletions src/components/match/MatchList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useRouter } from 'next/navigation';

import { FallbackProps } from '@/components/common/ErrorBoundary';
import { MatchCard } from '@/components/common/MatchCard';
import RummiKubMatchItem from '@/components/rummikub/MatchItem';
import {
COMMON_ERROR_MESSAGE,
MATCH_LIST_API_ERROR_MESSAGE,
Expand Down Expand Up @@ -37,34 +38,48 @@ export default function MatchList({
return (
<>
<ul>
{matchList.map(({ id, ...match }) => (
<li key={id} className="mb-14">
<Link href={`match/${id}`}>
<MatchCard {...match} className="flex flex-col">
<MatchCard.Label className="mb-2 border-b-2 border-b-gray-5 px-1 pb-1" />
<div className="flex h-full min-h-[180px] items-center justify-around rounded-xl bg-gray-1 shadow-lg">
<MatchCard.Background
viewBox="-13 117 120 50"
width={150}
height={170}
className="h-[180px] fill-primary"
/>
{matchList.map(({ id, sportsName, ...match }) => (
<>
{sportsName === '루미큐브' ? (
<li key={id} className="mb-14">
<Link href={`rummikube/${id}`}>
<RummiKubMatchItem {...match} sportsName={sportsName} />
</Link>
</li>
) : (
<li key={id} className="mb-14">
<Link href={`match/${id}`}>
<MatchCard
{...match}
sportsName={sportsName}
className="flex flex-col"
>
<MatchCard.Label className="mb-2 border-b-2 border-b-gray-5 px-1 pb-1" />
<div className="flex h-full min-h-[180px] items-center justify-around rounded-xl bg-gray-1 shadow-lg">
<MatchCard.Background
viewBox="-13 117 120 50"
width={150}
height={170}
className="h-[180px] fill-primary"
/>

<MatchCard.Team
teamIndex={1}
className="flex flex-col items-center"
/>
<MatchCard.Score teamIndex={1} />
<MatchCard.Status />
<MatchCard.Score teamIndex={2} />
<MatchCard.Team
teamIndex={2}
className="flex flex-col items-center"
/>
</div>
</MatchCard>
</Link>
</li>
<MatchCard.Team
teamIndex={1}
className="flex flex-col items-center"
/>
<MatchCard.Score teamIndex={1} />
<MatchCard.Status />
<MatchCard.Score teamIndex={2} />
<MatchCard.Team
teamIndex={2}
className="flex flex-col items-center"
/>
</div>
</MatchCard>
</Link>
</li>
)}
</>
))}
</ul>
<div ref={ref}></div>
Expand Down

0 comments on commit cf4fbb4

Please sign in to comment.