174 lines
7.1 KiB
TypeScript
174 lines
7.1 KiB
TypeScript
import { useCallback, useEffect, useState } from "preact/hooks";
|
|
import "./style.scss";
|
|
|
|
function divmod(a: number, b: number) {
|
|
return [Math.floor(a / b), a % b];
|
|
}
|
|
|
|
function secondsToHMS(seconds: number) {
|
|
let hours: number, minutes: number;
|
|
|
|
[minutes, seconds] = divmod(seconds, 60);
|
|
[hours, minutes] = divmod(minutes, 60);
|
|
|
|
return [hours, minutes, seconds];
|
|
}
|
|
|
|
export const IntervalSelector = ({
|
|
months: monthsProp,
|
|
days: daysProp,
|
|
seconds: secondsProp,
|
|
setInterval,
|
|
clearInterval,
|
|
}) => {
|
|
const [months, setMonths] = useState(monthsProp);
|
|
const [days, setDays] = useState(daysProp);
|
|
|
|
let [_hours, _minutes, _seconds] = [0, 0, 0];
|
|
if (secondsProp !== null) {
|
|
[_hours, _minutes, _seconds] = secondsToHMS(secondsProp);
|
|
}
|
|
|
|
const [seconds, setSeconds] = useState(_seconds);
|
|
const [minutes, setMinutes] = useState(_minutes);
|
|
const [hours, setHours] = useState(_hours);
|
|
|
|
useEffect(() => {
|
|
if (seconds || minutes || hours || days || months) {
|
|
setInterval({
|
|
seconds: (seconds || 0) + (minutes || 0) * 60 + (hours || 0) * 3600,
|
|
days: days || 0,
|
|
months: months || 0,
|
|
});
|
|
} else {
|
|
clearInterval();
|
|
}
|
|
}, [seconds, minutes, hours, days, months]);
|
|
|
|
const placeholder = useCallback(() => {
|
|
return seconds || minutes || hours || days || months ? "0" : "";
|
|
}, [seconds, minutes, hours, days, months]);
|
|
|
|
return (
|
|
<div class="control intervalSelector">
|
|
<div class="input interval-group">
|
|
<div class="interval-group-left">
|
|
<span class="no-break">
|
|
<label>
|
|
<span class="is-sr-only">Interval months</span>
|
|
<input
|
|
class="w2"
|
|
type="text"
|
|
pattern="\d*"
|
|
name="interval_months"
|
|
maxlength={2}
|
|
placeholder=""
|
|
value={months || placeholder()}
|
|
onInput={(ev) => {
|
|
const value = ev.currentTarget.value;
|
|
if (value && !isNaN(parseInt(value))) {
|
|
setMonths(parseInt(ev.currentTarget.value));
|
|
}
|
|
}}
|
|
></input>{" "}
|
|
<span class="half-rem"></span> months, <span class="half-rem"></span>
|
|
</label>
|
|
<label>
|
|
<span class="is-sr-only">Interval days</span>
|
|
<input
|
|
class="w3"
|
|
type="text"
|
|
pattern="\d*"
|
|
name="interval_days"
|
|
maxlength={4}
|
|
placeholder=""
|
|
value={days || placeholder()}
|
|
onInput={(ev) => {
|
|
const value = ev.currentTarget.value;
|
|
if (value && !isNaN(parseInt(value))) {
|
|
setDays(parseInt(ev.currentTarget.value));
|
|
}
|
|
}}
|
|
></input>{" "}
|
|
<span class="half-rem"></span> days, <span class="half-rem"></span>
|
|
</label>
|
|
</span>
|
|
<span class="no-break">
|
|
<label>
|
|
<span class="is-sr-only">Interval hours</span>
|
|
<input
|
|
class="w2"
|
|
type="text"
|
|
pattern="\d*"
|
|
name="interval_hours"
|
|
maxlength={2}
|
|
placeholder="HH"
|
|
value={hours || placeholder()}
|
|
onInput={(ev) => {
|
|
const value = ev.currentTarget.value;
|
|
if (value && !isNaN(parseInt(value))) {
|
|
setHours(parseInt(ev.currentTarget.value));
|
|
}
|
|
}}
|
|
></input>
|
|
:
|
|
</label>
|
|
<label>
|
|
<span class="is-sr-only">Interval minutes</span>
|
|
<input
|
|
class="w2"
|
|
type="text"
|
|
pattern="\d*"
|
|
name="interval_minutes"
|
|
maxlength={2}
|
|
placeholder="MM"
|
|
value={minutes || placeholder()}
|
|
onInput={(ev) => {
|
|
const value = ev.currentTarget.value;
|
|
if (value && !isNaN(parseInt(value))) {
|
|
setMinutes(parseInt(ev.currentTarget.value));
|
|
}
|
|
}}
|
|
></input>
|
|
:
|
|
</label>
|
|
<label>
|
|
<span class="is-sr-only">Interval seconds</span>
|
|
<input
|
|
class="w2"
|
|
type="text"
|
|
pattern="\d*"
|
|
name="interval_seconds"
|
|
maxlength={2}
|
|
placeholder="SS"
|
|
value={seconds || placeholder()}
|
|
onInput={(ev) => {
|
|
const value = ev.currentTarget.value;
|
|
if (value && !isNaN(parseInt(value))) {
|
|
setSeconds(parseInt(ev.currentTarget.value));
|
|
}
|
|
}}
|
|
></input>
|
|
</label>
|
|
</span>
|
|
</div>
|
|
<button
|
|
class="clear"
|
|
onClick={() => {
|
|
setMonths(0);
|
|
setDays(0);
|
|
setSeconds(0);
|
|
setMinutes(0);
|
|
setHours(0);
|
|
}}
|
|
>
|
|
<span class="is-sr-only">Clear interval</span>
|
|
<span class="icon">
|
|
<i class="fas fa-trash"></i>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|