You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
5.3 KiB
222 lines
5.3 KiB
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
|
|
|
import "./Bois.css";
|
|
import {StatusContext} from "./Contexts";
|
|
import {CalorieScore, CpmScore, LevelScore, PulseScore, RpmScore, Timer} from "./Score";
|
|
import calculateDiff from "../helpers/diff";
|
|
import useKey from "../hooks/useKey";
|
|
import {Milestones} from "./Milestones";
|
|
import {Info, InfoTable, StateFilter, Differ} from "./Misc";
|
|
|
|
const Boi = ({type, children}) => {
|
|
return (
|
|
<div className={`Boi Boi-${type}`}>
|
|
{children}
|
|
</div>
|
|
)
|
|
};
|
|
|
|
export const LeftBoi = () => {
|
|
const {prevDiff, prevLongDiff, workout, workoutStatus, program, hidden} = useContext(StatusContext);
|
|
if (workoutStatus === null || workout === null || program === null || hidden) {
|
|
return null;
|
|
}
|
|
|
|
const {cooldownMin} = workout;
|
|
const {minutes, seconds, calories, level, rpm, pulse} = workoutStatus;
|
|
const diff = calculateDiff({program, cooldownMin, minutes, seconds, calories});
|
|
const cpm = calories / (minutes + (seconds / 60));
|
|
|
|
return (
|
|
<Boi type="left">
|
|
<Timer minutes={minutes} seconds={seconds} cooldownMin={cooldownMin}/>
|
|
<CalorieScore calories={calories} diff={diff} prevDiff={prevLongDiff} stonks={prevDiff}/>
|
|
<RpmScore rpm={rpm}/>
|
|
<CpmScore cpm={cpm}/>
|
|
<LevelScore level={level}/>
|
|
<PulseScore pulse={pulse} />
|
|
</Boi>
|
|
);
|
|
};
|
|
|
|
export const CentreBoi = () => {
|
|
const {
|
|
state, program, setProgram, bike, setBike, bikes, programs,
|
|
start, pause, stop, create, workoutStatus,
|
|
hidden, setHidden,
|
|
workout,
|
|
prevLongDiff,
|
|
toggleCooldown,
|
|
} = useContext(StatusContext);
|
|
const [options, setOptions] = useState(null);
|
|
const [current, setCurrent] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (bikes === null && programs === null) {
|
|
return;
|
|
}
|
|
|
|
setOptions(state === "bike" ? bikes : programs);
|
|
}, [state, bike, program, bikes, programs]);
|
|
|
|
useKey("-", () => {
|
|
if (options === null) {
|
|
return false;
|
|
}
|
|
|
|
if (current > 0) {
|
|
setCurrent(current - 1);
|
|
} else {
|
|
setCurrent(options.length - 1);
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
useKey("+", () => {
|
|
if (options === null) {
|
|
return false;
|
|
}
|
|
|
|
if (current < options.length - 1) {
|
|
setCurrent(current + 1);
|
|
} else {
|
|
setCurrent(0);
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
useKey("Enter", () => {
|
|
if (state === "bike") {
|
|
setBike(options[current]);
|
|
|
|
return true;
|
|
} else if (state === "program") {
|
|
setProgram(options[current]);
|
|
create(options[current]);
|
|
|
|
return true;
|
|
} else if (state === "connected") {
|
|
start();
|
|
|
|
return true;
|
|
} else if (state === "started") {
|
|
pause();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
});
|
|
|
|
const showHide = useCallback(() => {
|
|
setHidden(!hidden);
|
|
}, [setHidden, hidden]);
|
|
|
|
const stopRun = useCallback(() => {
|
|
if (state === "connected") {
|
|
stop();
|
|
setHidden(true);
|
|
|
|
return true;
|
|
}
|
|
}, [state, stop, setHidden]);
|
|
|
|
useKey("Escape", stopRun);
|
|
|
|
useKey(["H", "h", "/"], showHide);
|
|
|
|
useKey("*", () => {
|
|
if (state === "started" || state === "connected") {
|
|
toggleCooldown();
|
|
}
|
|
});
|
|
|
|
if (hidden) {
|
|
return null;
|
|
}
|
|
|
|
if (state === "started" && workoutStatus !== null) {
|
|
const {cooldownMin} = workout;
|
|
const {minutes, seconds, calories} = workoutStatus;
|
|
const diff = calculateDiff({program, cooldownMin, minutes, seconds, calories});
|
|
|
|
if (diff < 0 || (minutes > 0 && seconds === 0)) {
|
|
return (
|
|
<Boi type="centre">
|
|
<Differ diff={diff} prevDiff={prevLongDiff} />
|
|
</Boi>
|
|
);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (bikes === null || programs === null) {
|
|
return <Boi type="centre"><Info>Laster inn...</Info></Boi>;
|
|
}
|
|
|
|
function currentOptionName() {
|
|
if (options === null) {
|
|
return "";
|
|
}
|
|
|
|
if (options[current] === void (0)) {
|
|
return "";
|
|
}
|
|
|
|
return options[current].name;
|
|
}
|
|
|
|
return (
|
|
<Boi type="centre">
|
|
<StateFilter current={state} required="stopped">
|
|
<Info>Inaktiv</Info>
|
|
</StateFilter>
|
|
<StateFilter current={state} required="bike">
|
|
<Info>
|
|
Velg sykkel (+/-):
|
|
<br/>
|
|
<b>{currentOptionName()}</b>
|
|
</Info>
|
|
</StateFilter>
|
|
<StateFilter current={state} required="program">
|
|
<Info>
|
|
Velg program (+/-):
|
|
<br/>
|
|
<b>{currentOptionName()}</b>
|
|
</Info>
|
|
</StateFilter>
|
|
<StateFilter current={state} required="connected">
|
|
<InfoTable keyValuePairs={[
|
|
{key: "Enter", value: "Start"},
|
|
{key: "Escape", value: "Avslutt"},
|
|
]}/>
|
|
</StateFilter>
|
|
<StateFilter current={state} required="disconnected">
|
|
<Info>Kobler til...</Info>
|
|
</StateFilter>
|
|
<StateFilter current={state} required="started">
|
|
<Info>Abonnerer på WS...</Info>
|
|
</StateFilter>
|
|
<StateFilter current={state} required="unknown">
|
|
<Info>Noe gikk galt!</Info>
|
|
</StateFilter>
|
|
</Boi>
|
|
);
|
|
};
|
|
|
|
export const RightBoi = () => {
|
|
const {milestones, hidden} = useContext(StatusContext);
|
|
|
|
if (hidden || (milestones || []).length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Boi type="right">
|
|
<Milestones milestones={milestones.sort((i, j) => j.minutes - i.minutes)}/>
|
|
</Boi>
|
|
);
|
|
};
|