mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-20 22:49:18 +00:00
Feat/132 (#198)
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link, useSearchParams } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||
import Empty from '../../../common/components/state/Empty';
|
||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||
import { formatDisplay, millisToSeconds } from '../../../common/utils/dateConfig';
|
||||
import getDelayTo from '../../../common/utils/getDelayTo';
|
||||
import { formatTime } from '../../../common/utils/time';
|
||||
|
||||
import { fetchTimerData, sanitiseTitle, timerMessages } from './countdown.helpers';
|
||||
|
||||
import style from './Countdown.module.scss';
|
||||
import './Countdown.scss';
|
||||
|
||||
const formatOptions = {
|
||||
showSeconds: true,
|
||||
@@ -18,14 +20,15 @@ const formatOptions = {
|
||||
};
|
||||
|
||||
export default function Countdown(props) {
|
||||
const { backstageEvents, time, selectedId } = props;
|
||||
const { backstageEvents, time, selectedId, viewSettings } = props;
|
||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const [follow, setFollow] = useState(null);
|
||||
const [runningTimer, setRunningTimer] = useState(0);
|
||||
const [runningMessage, setRunningMessage] = useState('');
|
||||
const [delay, setDelay] = useState(0);
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
// Set window title
|
||||
useEffect(() => {
|
||||
document.title = 'ontime - Countdown';
|
||||
}, []);
|
||||
@@ -66,17 +69,15 @@ export default function Countdown(props) {
|
||||
setRunningTimer(timer);
|
||||
}, [follow, selectedId, time]);
|
||||
|
||||
const standby = useMemo(
|
||||
() => time.playstate !== 'start' && selectedId === follow?.id,
|
||||
[follow?.id, selectedId, time.playstate]
|
||||
);
|
||||
// defer rendering until we load stylesheets
|
||||
if (!shouldRender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isRunningFinished = useMemo(
|
||||
() => time.finished && runningMessage === timerMessages.running,
|
||||
[time.finished, runningMessage]
|
||||
);
|
||||
|
||||
const isSelected = useMemo(() => runningMessage === timerMessages.running, [runningMessage]);
|
||||
const standby = time.playstate !== 'start' && selectedId === follow?.id;
|
||||
const isRunningFinished = time.finished && runningMessage === timerMessages.running;
|
||||
const isSelected = runningMessage === timerMessages.running;
|
||||
const delayedTimerStyles = delay > 0 ? 'aux-timers__value--delayed' : '';
|
||||
|
||||
const clock = formatTime(time.clock, formatOptions);
|
||||
const startTime =
|
||||
@@ -89,12 +90,12 @@ export default function Countdown(props) {
|
||||
: formatTime(follow.timeEnd + delay, formatOptions);
|
||||
|
||||
return (
|
||||
<div className={style.container}>
|
||||
<div className='countdown'>
|
||||
<NavLogo />
|
||||
{follow === null ? (
|
||||
<div className={style.eventSelect}>
|
||||
<span className={style.actionTitle}>Select an event to follow</span>
|
||||
<ul className={style.events}>
|
||||
<div className='event-select'>
|
||||
<span className='event-select__title'>Select an event to follow</span>
|
||||
<ul className='event-select__events'>
|
||||
{backstageEvents.length === 0 ? (
|
||||
<Empty dark text='No events in database' />
|
||||
) : (
|
||||
@@ -111,27 +112,29 @@ export default function Countdown(props) {
|
||||
</ul>
|
||||
</div>
|
||||
) : (
|
||||
<div className={style.countdownContainer}>
|
||||
<div className={style.timers}>
|
||||
<div className={style.timer}>
|
||||
<div className={style.label}>Time Now</div>
|
||||
<span className={style.value}>{clock}</span>
|
||||
<div className='countdown-container'>
|
||||
<div className='timer-group'>
|
||||
<div className='aux-timers'>
|
||||
<div className='aux-timers__label'>Time Now</div>
|
||||
<span className='aux-timers__value'>{clock}</span>
|
||||
</div>
|
||||
<div className={style.timer}>
|
||||
<div className={style.label}>Start Time</div>
|
||||
<span className={`${style.value} ${delay > 0 ? style.delayed : ''}`}>
|
||||
<div className='aux-timers'>
|
||||
<div className='aux-timers__label'>Start Time</div>
|
||||
<span className={`aux-timers__value ${delayedTimerStyles}`}>
|
||||
{startTime}
|
||||
</span>
|
||||
</div>
|
||||
<div className={style.timer}>
|
||||
<div className={style.label}>End Time</div>
|
||||
<span className={`${style.value} ${delay > 0 ? style.delayed : ''}`}>{endTime}</span>
|
||||
<div className='aux-timers'>
|
||||
<div className='aux-timers__label'>End Time</div>
|
||||
<span className={`aux-timers__value ${delayedTimerStyles}`}>
|
||||
{endTime}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.status}>{runningMessage}</div>
|
||||
<div className='status'>{runningMessage}</div>
|
||||
<span
|
||||
className={`${style.countdownClock} ${standby ? style.standby : ''} ${
|
||||
isRunningFinished ? style.finished : ''
|
||||
className={`timer ${standby ? 'timer--paused' : ''} ${
|
||||
isRunningFinished ? 'timer--finished' : ''
|
||||
}`}
|
||||
>
|
||||
{formatDisplay(
|
||||
@@ -139,7 +142,7 @@ export default function Countdown(props) {
|
||||
isSelected || time.waiting
|
||||
)}
|
||||
</span>
|
||||
<div className={style.title}>{follow?.title || 'Untitled Event'}</div>
|
||||
<div className='title'>{follow?.title || 'Untitled Event'}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -150,5 +153,5 @@ Countdown.propTypes = {
|
||||
backstageEvents: PropTypes.array,
|
||||
time: PropTypes.object,
|
||||
selectedId: PropTypes.string,
|
||||
settings: PropTypes.object,
|
||||
viewSettings: PropTypes.object,
|
||||
};
|
||||
|
||||
+22
-22
@@ -1,17 +1,17 @@
|
||||
@use '../../../theme/main' as *;
|
||||
@use '../../../theme/viewerDefs' as *;
|
||||
|
||||
.container {
|
||||
.countdown {
|
||||
margin: 0;
|
||||
box-sizing: border-box; /* reset */
|
||||
overflow: hidden;
|
||||
width: 100%; /* restrict the page width to viewport */
|
||||
|
||||
background: $bg-black;
|
||||
background: var(--background-color-override, $viewer-background-color);
|
||||
height: 100vh;
|
||||
color: $title-white;
|
||||
color: var(--color-override, $viewer-color);
|
||||
padding: 1vw;
|
||||
|
||||
.eventSelect {
|
||||
.event-select {
|
||||
display: flex;
|
||||
margin-top: 8vh;
|
||||
align-items: center;
|
||||
@@ -19,11 +19,11 @@
|
||||
font-size: max(1.3vw, 12px);
|
||||
flex-direction: column;
|
||||
|
||||
.actionTitle {
|
||||
&__title {
|
||||
font-size: max(2vw, 14px);
|
||||
}
|
||||
|
||||
.events {
|
||||
&__events {
|
||||
margin-top: 1em;
|
||||
overflow-y: auto;
|
||||
height: 70vh;
|
||||
@@ -31,7 +31,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.countdownContainer {
|
||||
.countdown-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
@@ -47,28 +47,27 @@
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
.timers {
|
||||
.timer-group {
|
||||
grid-area: timers;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: flex-end;
|
||||
|
||||
.timer {
|
||||
.aux-timers {
|
||||
text-align: center;
|
||||
|
||||
.label {
|
||||
&__label {
|
||||
font-size: max(1.3vw, 12px);
|
||||
color: $ontime-pink;
|
||||
color: var(--accent-color-override, $accent-color);
|
||||
}
|
||||
|
||||
.value {
|
||||
&__value {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: max(2vw, 14px);
|
||||
letter-spacing: 0.3px;
|
||||
color: #ddd;
|
||||
|
||||
&.delayed {
|
||||
color: $block-delay-color;
|
||||
&--delayed {
|
||||
color: $delay-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,8 +77,8 @@
|
||||
grid-area: title;
|
||||
font-size: max(4vw, 18px);
|
||||
align-self: center;
|
||||
color: $ontime-pink;
|
||||
background-color: $bg-gray-1000;
|
||||
color: var(--accent-color-override, $accent-color);
|
||||
background-color: var(--outdent-background-color-override, $viewer-outdent-bg-color);
|
||||
padding: 1vh 2vw;
|
||||
border-radius: 1vw;
|
||||
}
|
||||
@@ -92,7 +91,7 @@
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.countdownClock {
|
||||
.timer {
|
||||
grid-area: clock;
|
||||
line-height: 20vw;
|
||||
font-size: 21vw;
|
||||
@@ -101,12 +100,13 @@
|
||||
align-self: flex-start;
|
||||
opacity: 1.0;
|
||||
transition: opacity 0.5s;
|
||||
color: var(--timer-color-override, $viewer-color);
|
||||
|
||||
&.standby {
|
||||
&--paused {
|
||||
opacity: 0.6;
|
||||
}
|
||||
&.finished {
|
||||
color: $ontime-pink-variant;
|
||||
&--finished {
|
||||
color: $timer-finished-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user