Skip to content

Commit

Permalink
Merge pull request #48 from FRC2713/Timer-Input
Browse files Browse the repository at this point in the history
Timer input
  • Loading branch information
Owen-Morgan825 authored Nov 27, 2024
2 parents ad3fe3c + 1fbf97e commit 2fce45f
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 2 deletions.
8 changes: 8 additions & 0 deletions config/2024/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@
"required": false,
"code": "Mved"
},
{
"code": "timer",
"title": "Timer",
"type": "timer",
"defaultValue": 0,
"min": 0,
"required": false
},
{
"code": "ausc",
"title": "Speaker Scored",
Expand Down
3 changes: 2 additions & 1 deletion config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
"range",
"select",
"counter",
"image"
"image",
"timer"
]
}
}
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"clsx": "^2.1.0",
"immer": "^10.0.3",
"lodash": "^4.17.21",
"lucide-react": "^0.456.0",
"next-themes": "^0.2.1",
"preact": "^10.19.3",
"qrcode.react": "^3.1.0",
Expand Down
3 changes: 2 additions & 1 deletion src/components/inputs/BaseInputProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ export type InputTypes =
| 'range'
| 'select'
| 'counter'
| 'image';
| 'image'
| 'timer';
13 changes: 13 additions & 0 deletions src/components/inputs/ConfigurableInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import NumberInput from './NumberInput';
import RangeInput from './RangeInput';
import SelectInput from './SelectInput';
import StringInput from './StringInput';
import TimerInput from './TimerInput';

export interface ConfigurableInputProps {
section: string;
Expand Down Expand Up @@ -85,6 +86,18 @@ export default function ConfigurableInput(props: ConfigurableInputProps) {
section={props.section}
/>
);
case 'timer':
return (
<TimerInput
key={input.title}
{...input}
min={input.min}
max={input.max}
defaultValue={input.defaultValue as number}
onChange={handleChange}
section={props.section}
/>
)
default:
return (
<div className="py-2 px-1">
Expand Down
87 changes: 87 additions & 0 deletions src/components/inputs/TimerInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Pause, Play, TimerReset, Undo } from 'lucide-react';
import BaseInputProps from './BaseInputProps';
import { useState, useEffect, useMemo } from 'react';

Check failure on line 3 in src/components/inputs/TimerInput.tsx

View workflow job for this annotation

GitHub Actions / deploy

'useMemo' is declared but its value is never read.
export interface TimerInputProps extends BaseInputProps {
min?: number;
max?: number;
step?: number;
defaultValue?: number;
}
function getAvg(array: any[]) {
if (array.length === 0) {
return 0;
}
let avg = 0;
array.forEach((num) => {
avg += num;
});
return avg / array.length;
}
export default function TimerInput(data: TimerInputProps) {
const [time, setTime] = useState(0);
const [isRunning, toggleTimer] = useState(false);
const [times, setTimes] = useState<number[]>([]);

useEffect(() => {
if (data.value === data.defaultValue && times.length > 0) {
clearTimer();
setTimes([]);
}
}, [data.value, data.defaultValue, times]);

function startStop() {
toggleTimer(!isRunning);
}

function clearTimer(update: boolean = false) {
if (update) {
updateTimes(time / 100);
}
setTime(0);
toggleTimer(false);
}

function updateTimes(newValue: number) {
data.onChange(getAvg([...times, newValue]))
setTimes((old) => ([...old, newValue]));
}

useEffect(() => {
let intervalId: number;
if (isRunning) {
intervalId = setInterval(() => setTime(time + (data.step || 1)), 10);
}
return () => clearInterval(intervalId);
}, [isRunning, time]);


return (
<div className="my-2 flex flex-col items-center justify-center">
<p className='font-bold'>{`${data.value.toFixed(3)} (${times.length})`}</p>
<h2 className="px-4 text-2xl dark:text-white">{(time / 100).toFixed(2)}</h2>
<div className="my-2 flex flex-row items-center justify-center gap-4">
<button
className="focus:shadow-outline rounded bg-gray-500 text-white hover:bg-red-700 focus:outline-none dark:bg-gray-700 p-2"
type="button"
onClick={() => startStop()}
>
{isRunning ? <Pause className="size-4" /> : <Play className="size-4" />}
</button>
<button
className="focus:shadow-outline rounded bg-gray-500 text-white hover:bg-red-700 focus:outline-none dark:bg-gray-700 p-2"
type="button"
onClick={() => clearTimer(true)}
>
<TimerReset className="size-4" />
</button>
<button
className="focus:shadow-outline rounded bg-gray-500 text-white hover:bg-red-700 focus:outline-none dark:bg-gray-700 p-2"
type="button"
onClick={() => clearTimer(false)}
>
<Undo className="size-4" />
</button>
</div>
</div>
);
}

0 comments on commit 2fce45f

Please sign in to comment.