|
|
import Page, {PageFlexRow} from "../primitives/page/Page"; import {useCallback, useContext, useEffect, useMemo, useState} from "react"; import RuntimeContext from "../contexts/RuntimeContext"; import {useNavigate} from "react-router"; import LoadingPage from "./LoadingPage"; import DeviceContext from "../contexts/DeviceContext"; import ProgramContext from "../contexts/ProgramContext"; import {Device} from "../models/Devices"; import {Program, subTitleOfProgram} from "../models/Programs"; import {useKey, usePlusMinus} from "../hooks/keyboard"; import {FluffyValue, TitleLine, Value} from "../primitives/misc/Misc"; import Blob, {BlobText, BlobTextLine} from "../primitives/blob/Blob"; import {Icon} from "../primitives/Shared"; import {faClose, faPlay} from "@fortawesome/free-solid-svg-icons"; import {stateString, WorkoutStatus} from "../models/Workouts"; import {Boi} from "../primitives/boi/Boi"; import {useLastState} from "./runtime/hooks"; import {ControlsBoi} from "./runtime/ControlsBoi"; import MessageBoi from "./runtime/MessageBoi"; import ProgramBoi from "./runtime/ProgramBoi"; import MilestoneBoi from "./runtime/MilestoneBoi"; import {useKpm} from "../hooks/kpm";
function PlayPage(): JSX.Element { const {active, ready, ended, workout, reset, resume} = useContext(RuntimeContext); const navigate = useNavigate();
useEffect(() => { if (!active) { resume(); } }, [active, resume]);
useEffect(() => { if (active && ended && workout) { navigate(`/workouts/${workout.id}`, {replace: true}); reset(); } }, [active, ready, ended, workout]);
if (active && ready && workout === null) { return <CreatePlayPage/>; }
if (active && workout !== null) { return <RunPlayPage/>; }
return <LoadingPage minimal text="Starter økt"/>; }
const noProgram: Program = { id: "", name: "Uten program", steps: [{index: 0, values: {}, duration: undefined}], }
function CreatePlayPage(): JSX.Element { const {devices} = useContext(DeviceContext); const {programs} = useContext(ProgramContext); const {create} = useContext(RuntimeContext); const programWithFake = useMemo(() => programs ? [noProgram, ...programs] : null, [programs]); const navigate = useNavigate();
const [device, setDevice] = useState<Device | null>(null); const [program, setProgram] = useState<Program | null>(null);
const [sel, setSel] = usePlusMinus((device ? (program ? 2 : programWithFake?.length) : devices?.length) || 1);
const confirmSelection = useCallback((idx: number) => { if (program && device) { if (idx === 0) { create({deviceId: device.id, programId: program.id || undefined, test: false}) } else { navigate("/"); } } else if (device && programWithFake) { setProgram(programWithFake[idx] || null); setSel(0); } else if (devices !== null) { setDevice(devices[idx] || null); setSel(0); } }, [create, device, program, devices, programWithFake]);
useKey("Enter", () => { confirmSelection(sel); }, [confirmSelection, sel]);
useKey("Escape", () => { navigate("/"); }, []);
useEffect(() => { if (devices && devices.length === 0) { navigate("/"); } }, [devices]);
if (devices === null) { return <LoadingPage minimal text="Henter enheter"/> } else if (programWithFake === null) { return <LoadingPage minimal text="Henter programmer"/> }
return ( <Page background={"2046"}> {device === null && ( <Boi vertical="center" horizontal="center" style={{fontSize: undefined}}> <TitleLine>Velg enhet</TitleLine> {devices.map((d, i) => ( <Blob key={d.id} onClick={() => confirmSelection(i)} color={sel === i ? "indigo" : "gray"}> <BlobText> <BlobTextLine>{d.name}</BlobTextLine> <BlobTextLine secondary>{d.connectionString}</BlobTextLine> </BlobText> </Blob> ))} </Boi> )}
{device !== null && program === null && ( <Boi vertical="center" horizontal="center" style={{fontSize: undefined}}> <TitleLine>Velg program</TitleLine> {programWithFake.map((p, i) => ( <Blob key={p.id} onClick={() => confirmSelection(i)} color={sel === i ? "indigo" : "gray"}> <BlobText> <BlobTextLine>{p.name}</BlobTextLine> <BlobTextLine secondary>{subTitleOfProgram(p)}</BlobTextLine> </BlobText> </Blob> ))} </Boi> )}
{device && program && ( <Boi vertical="center" horizontal="center" style={{fontSize: undefined}}> <TitleLine>Oppsumering</TitleLine> {device && ( <Blob> <BlobText> <BlobTextLine>{device.name}</BlobTextLine> <BlobTextLine secondary>{device.connectionString}</BlobTextLine> </BlobText> </Blob> )} {program && ( <Blob> <BlobText> <BlobTextLine>{program.name}</BlobTextLine> <BlobTextLine secondary>{subTitleOfProgram(program)}</BlobTextLine> </BlobText> </Blob> )} <PageFlexRow> {device && program && ( <> <Blob onClick={() => confirmSelection(0)} color={sel === 0 ? "indigo" : "gray"}> <BlobText> <Icon value={faPlay}/> Start </BlobText> </Blob> <Blob onClick={() => confirmSelection(1)} color={sel === 1 ? "indigo" : "gray"}> <BlobText> <Icon value={faClose}/> Avbryt </BlobText> </Blob> </> )} </PageFlexRow> </Boi> )} </Page> ); }
function RunPlayPage(): JSX.Element { const {workout} = useContext(RuntimeContext); const lastState = useLastState(); const kpm = useKpm();
if (!workout || workout.status === WorkoutStatus.Created) { return <LoadingPage minimal/>; }
return ( <Page title="YKonsole" background={"2046"}> <ControlsBoi/> {lastState && ( <Boi vertical="center" horizontal="left" style={{padding: "0.5vmax", paddingBottom: "0"}}> <span style={{fontSize: "125%"}}> <FluffyValue raw={lastState} valueKey="time"/> </span> <FluffyValue raw={lastState} valueKey="calories"/> <FluffyValue raw={lastState} valueKey="distance"/> <FluffyValue raw={lastState} valueKey="level"/> <FluffyValue raw={lastState} valueKey="rpmSpeed"/> {kpm > 0 && <FluffyValue raw={kpm} valueKey="kpm"/>} <FluffyValue raw={lastState} valueKey="pulse"/> </Boi> )} {workout?.status === WorkoutStatus.Connected && <MessageBoi text="Trykk Enter for å begynne"/>} {workout?.status === WorkoutStatus.Stopped && <MessageBoi text="Pause"/>} {workout.program && workout.program.steps.length > 0 && <ProgramBoi/>} <MilestoneBoi/> </Page> ); }
export default PlayPage;
|