Skip to content

Commit b51aefd

Browse files
committed
make remote bar a horizontal player
1 parent 32f4e2d commit b51aefd

1 file changed

Lines changed: 89 additions & 31 deletions

File tree

src/components/NotifyCompRemoteBar/NotifyCompRemoteBar.tsx

Lines changed: 89 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import classNames from 'classnames';
22
import { Link } from 'react-router-dom';
3-
import { Button } from '@/components/Button';
43
import { Container } from '@/components/Container';
54
import { useCompetitionRemoteControl } from '@/hooks/useCompetitionRemoteControl';
65

@@ -9,6 +8,10 @@ interface NotifyCompRemoteBarProps {
98
}
109

1110
const groupLabel = (count: number) => `${count} active activit${count === 1 ? 'y' : 'ies'}`;
11+
const iconButtonClassName =
12+
'flex h-8 w-8 items-center justify-center rounded-full text-base leading-none text-gray-200 hover-transition hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-40 md:h-9 md:w-9 md:text-lg';
13+
const primaryButtonClassName =
14+
'flex h-9 w-9 items-center justify-center rounded-full bg-white text-base leading-none text-gray-950 hover-transition hover:scale-105 disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:scale-100 md:h-10 md:w-10 md:text-lg';
1215

1316
export function NotifyCompRemoteBar({ competitionId }: NotifyCompRemoteBarProps) {
1417
const remote = useCompetitionRemoteControl({ competitionId });
@@ -25,50 +28,105 @@ export function NotifyCompRemoteBar({ competitionId }: NotifyCompRemoteBarProps)
2528
: remote.nextGroup
2629
? `Next: ${remote.nextGroup.name}`
2730
: 'Remote overview';
31+
const completedGroups = remote.activityGroups.filter((group) => group.status === 'done').length;
32+
const progress =
33+
remote.activityGroups.length > 0 ? (completedGroups / remote.activityGroups.length) * 100 : 0;
2834

2935
const runSwitch = (direction: 'previous' | 'next') => {
3036
const group = direction === 'previous' ? remote.previousGroup : remote.nextGroup;
3137
void remote.switchToGroup(group);
3238
};
39+
const togglePlayback = () => {
40+
if (remote.activeGroups.length > 0) {
41+
void Promise.all(remote.activeGroups.map((group) => remote.stopGroup(group)));
42+
return;
43+
}
44+
45+
void remote.switchToGroup(remote.nextGroup);
46+
};
3347

3448
return (
3549
<nav
3650
aria-label="Remote control"
37-
className="z-20 w-full border-t border-tertiary-weak bg-panel shadow-md shadow-tertiary-dark print:hidden">
38-
<Container className="flex-row items-center gap-2 px-2 py-2">
39-
<Button
40-
type="button"
41-
variant="light"
42-
className="min-w-[76px] justify-center"
43-
disabled={remote.isSaving || !remote.previousGroup}
44-
onClick={() => runSwitch('previous')}>
45-
Back
46-
</Button>
47-
51+
className="z-20 w-full border-t border-gray-800 bg-black text-white shadow-md print:hidden">
52+
<Container className="grid grid-cols-[minmax(0,1fr)_minmax(176px,1.2fr)_auto] items-center gap-2 px-2 py-2 md:grid-cols-[minmax(0,1fr)_minmax(220px,1.4fr)_minmax(0,1fr)] md:gap-4">
4853
<Link
4954
to={`/competitions/${competitionId}/remote`}
50-
className={classNames(
51-
'min-w-0 flex-1 rounded border border-tertiary-weak px-3 py-2 hover-transition hover:bg-gray-100 dark:hover:bg-gray-700',
52-
{
53-
'opacity-60': remote.isLoading,
54-
},
55-
)}>
56-
<div className="flex min-w-0 flex-col">
57-
<span className="truncate type-label">{title}</span>
58-
<span className="truncate type-meta">
59-
{remote.error ? `Remote error: ${remote.error}` : detail}
60-
</span>
55+
className="flex min-w-0 items-center gap-2 rounded px-1 py-1 hover-transition hover:bg-gray-900">
56+
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded bg-green-600 text-sm font-bold text-white">
57+
RC
58+
</div>
59+
<div className="min-w-0 space-y-1">
60+
<div className="truncate text-sm font-medium text-white">{title}</div>
61+
<div className="truncate text-xs text-gray-400">{detail}</div>
6162
</div>
6263
</Link>
6364

64-
<Button
65-
type="button"
66-
variant="green"
67-
className="min-w-[76px] justify-center"
68-
disabled={remote.isSaving || !remote.nextGroup}
69-
onClick={() => runSwitch('next')}>
70-
Next
71-
</Button>
65+
<div className="min-w-0 space-y-1">
66+
<div className="flex items-center justify-center gap-2">
67+
<button
68+
type="button"
69+
className={iconButtonClassName}
70+
disabled={remote.isSaving || !remote.previousGroup}
71+
aria-label="Go back to previous remote activity"
72+
onClick={() => runSwitch('previous')}>
73+
&#9198;
74+
</button>
75+
76+
<button
77+
type="button"
78+
className={primaryButtonClassName}
79+
disabled={remote.isSaving || (remote.activeGroups.length === 0 && !remote.nextGroup)}
80+
aria-label={
81+
remote.activeGroups.length > 0
82+
? 'Stop current remote activities'
83+
: 'Start next remote activity'
84+
}
85+
onClick={togglePlayback}>
86+
{remote.activeGroups.length > 0 ? <>&#9632;</> : <>&#9654;</>}
87+
</button>
88+
89+
<button
90+
type="button"
91+
className={iconButtonClassName}
92+
disabled={remote.isSaving || !remote.nextGroup}
93+
aria-label="Go to next remote activity"
94+
onClick={() => runSwitch('next')}>
95+
&#9197;
96+
</button>
97+
</div>
98+
99+
<Link
100+
to={`/competitions/${competitionId}/remote`}
101+
className={classNames('grid grid-cols-[44px_minmax(0,1fr)_44px] items-center gap-2', {
102+
'opacity-60': remote.isLoading,
103+
})}>
104+
<span className="text-right text-xs tabular-nums text-gray-400">{completedGroups}</span>
105+
<span className="h-1 overflow-hidden rounded-full bg-gray-700">
106+
<span
107+
className="block h-full rounded-full bg-white"
108+
style={{ width: `${progress}%` }}
109+
/>
110+
</span>
111+
<span className="text-xs tabular-nums text-gray-400">
112+
{remote.activityGroups.length}
113+
</span>
114+
</Link>
115+
</div>
116+
117+
<div className="flex min-w-0 items-center justify-end gap-3">
118+
<div className="hidden min-w-0 text-right sm:block">
119+
<div className="truncate text-sm font-medium text-white">Remote</div>
120+
<div className="truncate text-xs text-gray-400">
121+
{remote.error ? remote.error : remote.isSaving ? 'Syncing' : 'Ready'}
122+
</div>
123+
</div>
124+
<Link
125+
to={`/competitions/${competitionId}/remote`}
126+
className="rounded border border-green-500 px-3 py-1 text-sm font-medium text-green-400 hover-transition hover:bg-green-950">
127+
Open
128+
</Link>
129+
</div>
72130
</Container>
73131
</nav>
74132
);

0 commit comments

Comments
 (0)