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

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>
);
}