Skip to content

Commit

Permalink
add manual matches
Browse files Browse the repository at this point in the history
  • Loading branch information
tytremblay committed Nov 30, 2023
1 parent 9d03533 commit cd115ec
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 70 deletions.
15 changes: 15 additions & 0 deletions src/components/matches/AddMatchButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PlusIcon } from '@heroicons/react/20/solid';
import { addBlankMatch } from '../../state/useMatches';

export function AddMatchButton() {
return (
<button
type="button"
className="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
onClick={() => addBlankMatch()}
>
<PlusIcon className="-ml-0.5 mr-1.5 h-5 w-5" aria-hidden="true" />
Add Match
</button>
);
}
13 changes: 6 additions & 7 deletions src/components/matches/MatchDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type MatchTitleProps = {

export function MatchDescription(props: MatchTitleProps) {
const [editing, setEditing] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null);

const handleClickOutside = useCallback(() => {
setEditing(false);
Expand All @@ -18,21 +18,20 @@ export function MatchDescription(props: MatchTitleProps) {
useOnClickOutside(inputRef, handleClickOutside);

return editing ? (
<input
className="min-w-0 text-sm font-semibold leading-6 text-white truncate cursor-text bg-white/5 border-none w-full"
type="text"
<textarea
className="text-sm leading-6 text-gray-400 cursor-text bg-white/5 border-none resize w-full"
value={props.match.description}
ref={inputRef}
onChange={(event) =>
updateMatch(props.index, { description: event.target.value })
}
/>
) : (
<span
className="min-w-0 text-sm leading-6 whitespace-nowrap font-light text-gray-400 truncate cursor-text"
<p
className="text-sm leading-6 font-light text-gray-400 whitespace-break-spaces cursor-text"
onClick={() => setEditing(true)}
>
{props.match.description || 'Add description'}
</span>
</p>
);
}
86 changes: 51 additions & 35 deletions src/components/matches/MatchItem.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Popover, Transition } from '@headlessui/react';
import { EllipsisVerticalIcon } from '@heroicons/react/20/solid';
import { clsx } from 'clsx';
import { useMemo } from 'react';
import { Fragment, useMemo } from 'react';
import {
SplitterMatch,
autoFillTimeStamps,
removeMatch,
updateMatch,
useMatches,
} from '../../state/useMatches';
import { seekSeconds, useVideo } from '../../state/useVideo';
import { Badge } from '../badges/Badge';
import { Button } from '../buttons';
import { MatchDescription } from './MatchDescription';
import { MatchTitle } from './MatchTitle';
Expand Down Expand Up @@ -54,31 +56,19 @@ export function MatchItem(props: MatchItemProps) {
<li
key={props.match.id}
className={clsx(
'relative flex items-center space-x-4 p-2',
'flex items-center space-x-4 p-2',
selectedMatches.includes(props.match.id)
? 'bg-gray-600/50 hover:bg-gray-600/70'
: 'hover:bg-gray-600/20'
)}
>
<div className="min-w-0 flex-auto">
<div className="flex items-center gap-x-3">
<div
className={clsx(statuses[status], 'flex-none rounded-full p-1')}
onClick={() => console.log('clicked match ', props.match.name)}
>
<div className="h-2 w-2 rounded-full bg-current" />
</div>
<h2 className="min-w-0 text-sm font-semibold leading-6 text-white flex-grow">
<div className="flex gap-x-2">
<MatchTitle match={props.match} index={props.index} />
<span className="text-gray-400">/</span>
<MatchDescription match={props.match} index={props.index} />
</div>
</h2>
<div className="min-w-0 flex-auto flex flex-row gap-2 justify-between items-center">
<div className="flex flex-col items-start gap-2 w-full">
<MatchTitle match={props.match} index={props.index} />
<MatchDescription match={props.match} index={props.index} />
</div>
<div className="mt-3 ml-6 flex items-center gap-x-2.5 text-xs leading-5 text-gray-400">
<div className="flex items-center gap-x-2.5 text-xs leading-5 text-gray-400">
<div className="flex flex-row gap-4 align-middle items-center">
<span className="text-gray-400">from</span>
<TimestampButton
timestampSeconds={props.match.fromSeconds}
onSet={() => {
Expand All @@ -105,7 +95,6 @@ export function MatchItem(props: MatchItemProps) {
</div>
</div>
</div>
<Badge type={status === 'new' ? 'info' : 'success'} text={badgeText} />
{props.match.startTime && props.match.resultsTime && (
<Button
secondary
Expand All @@ -123,21 +112,48 @@ export function MatchItem(props: MatchItemProps) {
Autofill
</Button>
)}
{(props.match.fromSeconds !== undefined ||
props.match.toSeconds !== undefined) && (
<Button
secondary
size="sm"
onClick={() =>
updateMatch(props.index, {
fromSeconds: undefined,
toSeconds: undefined,
})
}
<Popover className="relative">
<Popover.Button className="inline-flex items-center gap-x-1 text-sm font-semibold leading-6 text-gray-900">
<EllipsisVerticalIcon
className="h-5 w-5 text-gray-500"
aria-hidden="true"
/>
</Popover.Button>

<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
Reset
</Button>
)}
<Popover.Panel className="absolute z-10 flex w-screen max-w-min -translate-x-full">
<div className="w-24 shrink rounded-md bg-gray-400 text-sm font-semibold leading-6 text-gray-900 overflow-clip">
<button
key={'reset_match'}
className="block p-2 hover:text-indigo-600 hover:bg-gray-500 w-full"
onClick={() =>
updateMatch(props.index, {
fromSeconds: undefined,
toSeconds: undefined,
})
}
>
Reset
</button>
<button
key={'delete_match'}
className="block p-2 hover:text-indigo-600 hover:bg-gray-500 w-full"
onClick={() => removeMatch(props.match.id)}
>
Delete
</button>
</div>
</Popover.Panel>
</Transition>
</Popover>
</li>
);
}
4 changes: 2 additions & 2 deletions src/components/matches/MatchTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ export function MatchTitle(props: MatchTitleProps) {
}
/>
) : (
<span
<h2
className="min-w-0 text-sm font-semibold leading-6 text-white truncate cursor-text"
onClick={() => setEditing(true)}
>
{props.match.name || 'Add name'}
</span>
</h2>
);
}
8 changes: 7 additions & 1 deletion src/components/matches/MatchesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
useMatches,
} from '../../state/useMatches';
import { useTbaMatches } from '../../tba';
import { AddMatchButton } from './AddMatchButton';
import { MatchItem } from './MatchItem';
import { NoMatches } from './NoMatches';

Expand Down Expand Up @@ -41,11 +42,16 @@ export function MatchesList() {
return matches.length === 0 ? (
<NoMatches />
) : (
<div className="flex overflow-y-auto w-full scrollbar-thin scrollbar-thumb-white/20">
<div className="flex flex-col overflow-y-auto w-full scrollbar-thin scrollbar-thumb-white/20">
<ul className="divide-y divide-white/10 w-full">
{matches.map((match, i) => (
<MatchItem key={match.id} match={match} index={i} />
))}
<li className="h-4">
<div className="flex items-center justify-center w-full mt-4">
<AddMatchButton />
</div>
</li>
</ul>
</div>
);
Expand Down
12 changes: 2 additions & 10 deletions src/components/matches/NoMatches.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { PlusIcon } from '@heroicons/react/20/solid';
import { addBlankMatch } from '../../state/useMatches';
import { AddMatchButton } from './AddMatchButton';

export function NoMatches() {
return (
Expand All @@ -24,14 +23,7 @@ export function NoMatches() {
Get started by adding a manual match, or selecting an event from TBA.
</p>
<div className="mt-6">
<button
type="button"
className="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
onClick={() => addBlankMatch(0)}
>
<PlusIcon className="-ml-0.5 mr-1.5 h-5 w-5" aria-hidden="true" />
New Match
</button>
<AddMatchButton />
</div>
</div>
);
Expand Down
8 changes: 5 additions & 3 deletions src/components/video/VideoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ export function VideoPlayer() {
)
}
/>
<Button secondary size="md" onClick={() => setVideoPath('')}>
Remove Video
</Button>
{video.path && (
<Button secondary size="md" onClick={() => setVideoPath('')}>
Remove Video
</Button>
)}
</div>
);
}
24 changes: 12 additions & 12 deletions src/state/useMatches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,11 @@ export function setMatchesFromTBA(tbaEvent: TBAEvent, tbaMatches: TBAMatch[]) {
useMatches.setState({ matches });
}

export function addMatch(match: SplitterMatch, index: number) {
export function addMatch(match: SplitterMatch, index?: number) {
const oldMatches = [...useMatches.getState().matches];
if (index === undefined) {
index = oldMatches.length;
}
const newMatches = oldMatches
.slice(undefined, index)
.concat(match)
Expand All @@ -89,17 +92,14 @@ export function addMatch(match: SplitterMatch, index: number) {
});
}

export function addBlankMatch(index: number) {
addMatch(
{
id: uuid(),
name: `Match ${index + 1}`,
description: '',
sourceVideoPath: '',
splitPercentage: 0,
},
index
);
export function addBlankMatch() {
addMatch({
id: uuid(),
name: ``,
description: '',
sourceVideoPath: '',
splitPercentage: 0,
});
}

export function updateMatch(index: number, data: Partial<SplitterMatch>) {
Expand Down

0 comments on commit cd115ec

Please sign in to comment.