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.
147 lines
5.1 KiB
147 lines
5.1 KiB
import Page, {PageBody, PageFlexColumn, PageFlexRow} from "../primitives/page/Page";
|
|
import {useNavigate, useParams} from "react-router";
|
|
import React, {useCallback, useContext, useEffect, useMemo, useState} from "react";
|
|
import ProgramContext from "../contexts/ProgramContext";
|
|
import LoadingPage from "./LoadingPage";
|
|
import Header, {HeaderButton, HeaderTitle} from "../primitives/header/Header";
|
|
import {Icon} from "../primitives/Shared";
|
|
import {
|
|
faArrowUpRightDots, faCheck,
|
|
faChevronLeft,
|
|
faClose,
|
|
faLevelUpAlt,
|
|
faPlus,
|
|
faStopwatch
|
|
} from "@fortawesome/free-solid-svg-icons";
|
|
import {Size, stringToValues, valuesToString} from "../models/Shared";
|
|
import {TitleLine} from "../primitives/misc/Misc";
|
|
import Blob, {BlobInput, BlobText} from "../primitives/blob/Blob";
|
|
import {ProgramStep} from "../models/Programs";
|
|
import programRepo from "../actions/programs";
|
|
|
|
interface StepOption {
|
|
level: number
|
|
duration: string
|
|
}
|
|
|
|
export default function EditProgramPage() {
|
|
const {programs, refreshPrograms} = useContext(ProgramContext);
|
|
const navigate = useNavigate();
|
|
const {id} = useParams();
|
|
const program = useMemo(() => programs?.find(p => p.id === id), [programs, id]);
|
|
|
|
const [name, setName] = useState(program?.name || "");
|
|
const [steps, setSteps] = useState<StepOption[]>([]);
|
|
|
|
const [wait, setWait] = useState<boolean>(false);
|
|
|
|
useEffect(() => {
|
|
if (program) {
|
|
setName(program.name)
|
|
setSteps(program.steps.map(s => ({
|
|
level: s.values.level || 0,
|
|
duration: valuesToString(s.duration || {}),
|
|
})));
|
|
}
|
|
}, [program]);
|
|
|
|
const onSave = useCallback(() => {
|
|
const id = program?.id || undefined;
|
|
const newSteps: ProgramStep[] = steps.map(s => ({
|
|
values: {level: s.level},
|
|
duration: stringToValues(s.duration),
|
|
}));
|
|
|
|
setWait(true);
|
|
programRepo().save({id, name, steps: newSteps})
|
|
.then(res => {
|
|
if (res) {
|
|
navigate(program ? `/programs/${program.id}` : "/");
|
|
refreshPrograms();
|
|
} else {
|
|
setWait(false);
|
|
}
|
|
});
|
|
}, [program, name, steps, navigate, refreshPrograms]);
|
|
|
|
if (programs === null) {
|
|
return <LoadingPage text="Henter programmer"/>;
|
|
} else if (wait) {
|
|
return <LoadingPage text="Lagrer programm"/>;
|
|
}
|
|
|
|
const title = program ? `Endre "${program.name}"` : "Nytt programm";
|
|
const canSave = name.trim() !== "" && steps.length > 0 && !steps.find(p => p.level === 0);
|
|
|
|
return (
|
|
<Page title={title}>
|
|
<Header>
|
|
<HeaderButton onClick={() => navigate(program ? `/programs/${program.id}` : "/")}>
|
|
<Icon value={faChevronLeft}/>
|
|
</HeaderButton>
|
|
<HeaderTitle>{title}</HeaderTitle>
|
|
</Header>
|
|
<PageBody>
|
|
<PageFlexRow collapseOn={Size.Tablet}>
|
|
<PageFlexColumn flex={1}>
|
|
<TitleLine>Programm</TitleLine>
|
|
<Blob fillOn={Size.Any}>
|
|
<BlobText>Navn</BlobText>
|
|
<BlobInput type="text" value={name} onChange={setName} flex={1}/>
|
|
</Blob>
|
|
<Blob color={canSave ? "indigo" : "gray"} onClick={onSave} disabled={!canSave}>
|
|
<BlobText>
|
|
<Icon value={faCheck}/> Lagre
|
|
</BlobText>
|
|
</Blob>
|
|
</PageFlexColumn>
|
|
<PageFlexColumn flex={1}>
|
|
<TitleLine>Steg</TitleLine>
|
|
{steps.map((s, i) => {
|
|
const onChange = (arg: Partial<StepOption>) => setSteps(prev => {
|
|
return prev.map((ps, pi) => (pi === i ? {...ps, ...arg} : ps));
|
|
});
|
|
|
|
const onRemove = () => setSteps(prev => {
|
|
return prev.filter((ignored, pi) => pi !== i);
|
|
})
|
|
|
|
return (
|
|
<PageFlexRow key={i}>
|
|
<Blob>
|
|
<BlobText>
|
|
<Icon value={faArrowUpRightDots}/>
|
|
</BlobText>
|
|
<BlobInput
|
|
type="number" value={s.level}
|
|
onChange={level => onChange({level})}
|
|
/>
|
|
</Blob>
|
|
<Blob flex={2}>
|
|
<BlobText>
|
|
<Icon value={faStopwatch}/>
|
|
</BlobText>
|
|
<BlobInput
|
|
flex={1} type="text" value={s.duration} placeholder="Manuell"
|
|
onChange={duration => onChange({duration})}
|
|
/>
|
|
</Blob>
|
|
<Blob color="red" onClick={onRemove}>
|
|
<BlobText>
|
|
<Icon value={faClose}/>
|
|
</BlobText>
|
|
</Blob>
|
|
</PageFlexRow>
|
|
);
|
|
})}
|
|
<Blob color="green" onClick={() => setSteps(prev => [...prev, {duration: "", level: 1}])}>
|
|
<BlobText>
|
|
<Icon value={faPlus}/> Legg til
|
|
</BlobText>
|
|
</Blob>
|
|
</PageFlexColumn>
|
|
</PageFlexRow>
|
|
</PageBody>
|
|
</Page>
|
|
);
|
|
}
|