Skip to content

Commit

Permalink
fix: 타임라인 및 선수 선택 개선 (#354)
Browse files Browse the repository at this point in the history
* feat: 선수 이름과 번호가 같이 나타나도록 추가

* fix: 경기 종료 타임라인 예외 처리 추가

* fix: 타임라인 삭제 시 가장 마지막 recordId를 선택하도록 변경

* chore: 불필요 파일 제거

* fix: 코드리뷰 반영
  • Loading branch information
ohprettyhak authored Nov 10, 2024
1 parent c6613fb commit a01888c
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
useToast,
} from '@hcc/ui';
import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect, useMemo } from 'react';
import { useMemo } from 'react';
import { useForm } from 'react-hook-form';

import TimeInput from '@/components/TimeInput';
Expand Down Expand Up @@ -87,23 +87,18 @@ const ReplacementForm = ({
const gameTeamId = methods.watch('gameTeamId');
const players = useMemo(() => {
return (
lineupPlayers?.find(lineup => lineup.gameTeamId.toString() === gameTeamId)
lineupPlayers?.find(lineup => lineup.gameTeamId === Number(gameTeamId))
?.candidatePlayers ?? []
);
}, [lineupPlayers, gameTeamId]);

const playingPlayers = useMemo(() => {
return (
lineupPlayers?.find(lineup => lineup.gameTeamId.toString() === gameTeamId)
lineupPlayers?.find(lineup => lineup.gameTeamId === Number(gameTeamId))
?.starterPlayers ?? []
);
}, [lineupPlayers, gameTeamId]);

useEffect(() => {
methods.setValue('originLineupPlayerId', '');
methods.setValue('replacementLineupPlayerId', '');
}, [gameTeamId, methods]);

if (!quarter)
return (
<p className={styles.emptyQuarterMessage}>
Expand Down Expand Up @@ -148,13 +143,20 @@ const ReplacementForm = ({
name="gameTeamId"
render={({ field }) => (
<FormItem>
<Select onValueChange={field.onChange} value={field.value}>
<Select
onValueChange={value => {
field.onChange(value);
methods.setValue('originLineupPlayerId', '');
methods.setValue('replacementLineupPlayerId', '');
}}
value={field.value}
>
<FormLabel>팀 명</FormLabel>
<FormControl>
<SelectTrigger type="button">
<SelectValue>
{teams.find(
team => team.gameTeamId.toString() === field.value,
team => team.gameTeamId === Number(field.value),
)?.gameTeamName ?? '팀 선택'}
</SelectValue>
</SelectTrigger>
Expand All @@ -181,59 +183,77 @@ const ReplacementForm = ({
<FormField
control={methods.control}
name="replacementLineupPlayerId"
render={({ field }) => (
<FormItem>
<Select onValueChange={field.onChange} value={field.value}>
<FormLabel>교체 투입 선수</FormLabel>
<FormControl>
<SelectTrigger type="button">
<SelectValue>
{players.find(
player => player.id.toString() === field.value,
)?.playerName ?? '선수 선택'}
</SelectValue>
</SelectTrigger>
</FormControl>
<SelectContent>
{players.map(player => (
<SelectItem key={player.id} value={player.id.toString()}>
{player.playerName}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
render={({ field }) => {
const selectedPlayer = players.find(
player => player.id === Number(field.value),
);

return (
<FormItem>
<Select onValueChange={field.onChange} value={field.value}>
<FormLabel>교체 투입 선수</FormLabel>
<FormControl>
<SelectTrigger type="button">
<SelectValue>
{selectedPlayer
? `${selectedPlayer.playerName}(${selectedPlayer.number})`
: '선수 선택'}
</SelectValue>
</SelectTrigger>
</FormControl>
<SelectContent>
{players.map(player => (
<SelectItem
key={player.id}
value={player.id.toString()}
>
{player.playerName}({player.number})
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
);
}}
/>

<FormField
control={methods.control}
name="originLineupPlayerId"
render={({ field }) => (
<FormItem>
<Select onValueChange={field.onChange} value={field.value}>
<FormLabel>교체 아웃 선수</FormLabel>
<FormControl>
<SelectTrigger type="button">
<SelectValue>
{playingPlayers.find(
player => player.id.toString() === field.value,
)?.playerName ?? '선수 선택'}
</SelectValue>
</SelectTrigger>
</FormControl>
<SelectContent>
{playingPlayers.map(player => (
<SelectItem key={player.id} value={player.id.toString()}>
{player.playerName}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
render={({ field }) => {
const selectedPlayer = playingPlayers.find(
player => player.id === Number(field.value),
);

return (
<FormItem>
<Select onValueChange={field.onChange} value={field.value}>
<FormLabel>교체 아웃 선수</FormLabel>
<FormControl>
<SelectTrigger type="button">
<SelectValue>
{selectedPlayer
? `${selectedPlayer.playerName}(${selectedPlayer.number})`
: '선수 선택'}
</SelectValue>
</SelectTrigger>
</FormControl>
<SelectContent>
{playingPlayers.map(player => (
<SelectItem
key={player.id}
value={player.id.toString()}
>
{player.playerName}({player.number})
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
);
}}
/>

<FormField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const ScoreForm = ({ gameId, onClose, quarter }: ScoreFormProps) => {
const players = useMemo(() => {
return (
lineupPlayingPlayers?.find(
lineup => lineup.gameTeamId.toString() === gameTeamId,
lineup => lineup.gameTeamId === Number(gameTeamId),
)?.gameTeamPlayers ?? []
);
}, [lineupPlayingPlayers, gameTeamId]);
Expand Down Expand Up @@ -145,7 +145,7 @@ const ScoreForm = ({ gameId, onClose, quarter }: ScoreFormProps) => {
<SelectTrigger type="button">
<SelectValue>
{teams.find(
team => team.gameTeamId.toString() === field.value,
team => team.gameTeamId === Number(field.value),
)?.gameTeamName ?? '팀 선택'}
</SelectValue>
</SelectTrigger>
Expand All @@ -166,36 +166,44 @@ const ScoreForm = ({ gameId, onClose, quarter }: ScoreFormProps) => {
)}
/>
</section>

<h4 className={styles.sectionTitle}>득점 상세 정보</h4>
<section className={styles.section}>
<FormField
control={methods.control}
name="scoreLineupPlayerId"
render={({ field }) => (
<FormItem>
<Select onValueChange={field.onChange} value={field.value}>
<FormLabel>선수</FormLabel>
<FormControl>
<SelectTrigger type="button">
<SelectValue>
{players.find(
player => player.id.toString() === field.value,
)?.playerName ?? '선수 선택'}
</SelectValue>
</SelectTrigger>
</FormControl>
<SelectContent>
{players.map(player => (
<SelectItem key={player.id} value={player.id.toString()}>
{player.playerName}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
render={({ field }) => {
const selectedPlayer = players.find(
player => player.id === Number(field.value),
);

return (
<FormItem>
<Select onValueChange={field.onChange} value={field.value}>
<FormLabel>선수</FormLabel>
<FormControl>
<SelectTrigger type="button">
<SelectValue>
{selectedPlayer
? `${selectedPlayer.playerName}(${selectedPlayer.number})`
: '선수 선택'}
</SelectValue>
</SelectTrigger>
</FormControl>
<SelectContent>
{players.map(player => (
<SelectItem
key={player.id}
value={player.id.toString()}
>
{player.playerName}({player.number})
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
);
}}
/>

<FormField
Expand All @@ -212,7 +220,6 @@ const ScoreForm = ({ gameId, onClose, quarter }: ScoreFormProps) => {
)}
/>
</section>

<Button
disabled={isPending}
type="submit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const EventRecord = ({ record, homeTeamId }: EventRecordProps) => {
const isAway = record.gameTeamId !== homeTeamId;

return (
<div
<li
className={clsx(styles.eventRecordContainer, {
[styles.eventRecordAwayContainer]: isAway,
})}
Expand All @@ -33,7 +33,7 @@ const EventRecord = ({ record, homeTeamId }: EventRecordProps) => {
{getRecordSubtitle(record)}
</p>
</div>
</div>
</li>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ComponentProps, ReactNode } from 'react';

import * as styles from './styles.css';

type TextRecordProps = ComponentProps<'div'> & {
type TextRecordProps = ComponentProps<'li'> & {
showDividerLine?: boolean;
className?: string;
children: ReactNode;
Expand All @@ -16,7 +16,7 @@ const TextRecord = ({
...props
}: TextRecordProps) => {
return (
<div
<li
className={clsx(styles.textRecordContainer, className, {
[styles.textRecordCenter]: !showDividerLine,
})}
Expand All @@ -25,7 +25,7 @@ const TextRecord = ({
{showDividerLine && <div className={styles.textRecordDivider} />}
<p className={styles.textRecordText}>{children}</p>
{showDividerLine && <div className={styles.textRecordDivider} />}
</div>
</li>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getRecordSubtitle, getRecordTitle } from '../../_utils/record';

type RecordDeleteMenuProps = {
gameId: string;
record: TimelineRecordType | undefined;
record?: TimelineRecordType;
};

const RecordDeleteMenu = ({ gameId, record }: RecordDeleteMenuProps) => {
Expand Down
25 changes: 9 additions & 16 deletions apps/manager/app/league/[leagueId]/[gameId]/timeline/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
'use client';
import {
TimelineRecordType,
TimelineType,
useGame,
useTimeline,
} from '@hcc/api';
import { TimelineRecordType, useGame, useTimeline } from '@hcc/api';
import { Fragment } from 'react';

import Layout from '@/components/Layout';
Expand All @@ -30,14 +25,11 @@ export default function Page({ params }: PageProps) {

const homeTeamId: number = game.gameTeams[0].gameTeamId;

const sortedTimelines: TimelineType[] = timelines.map(timeline => ({
...timeline,
records: timeline.records.sort((a, b) => b.recordId - a.recordId),
}));
const lastRecord: TimelineRecordType | undefined =
sortedTimelines?.[0]?.records?.[0] ?? undefined;
const lastRecord: TimelineRecordType | undefined = timelines
.flatMap(item => item.records)
.sort((a, b) => b.recordId - a.recordId)[0];

const currentQuarter = sortedTimelines[0]?.gameQuarter ?? undefined;
const currentQuarter: string | undefined = timelines[0]?.gameQuarter;

return (
<Layout
Expand All @@ -46,7 +38,7 @@ export default function Page({ params }: PageProps) {
>
<GameScoreBanner game={game} />

<div className={styles.timeline}>
<ul className={styles.timeline}>
{game.state === 'FINISHED' && (
<Fragment>
<TextRecord>경기가 종료되었습니다.</TextRecord>
Expand All @@ -57,11 +49,12 @@ export default function Page({ params }: PageProps) {
</TextRecord>
</Fragment>
)}
{sortedTimelines.map(timeline => {
{timelines.map(timeline => {
return (
<Fragment key={timeline.gameQuarter}>
{timeline.records.map(record => {
if (record.type === 'GAME_PROGRESS') {
if (timeline.gameQuarter === '경기 종료') return null;
return (
<TextRecord key={record.recordId} showDividerLine={true}>
{timeline.gameQuarter}이(가)&nbsp;
Expand All @@ -83,7 +76,7 @@ export default function Page({ params }: PageProps) {
</Fragment>
);
})}
</div>
</ul>

<BottomMenu gameId={gameId} quarter={currentQuarter} />
</Layout>
Expand Down
Loading

0 comments on commit a01888c

Please sign in to comment.