Loading frontend/src/components/ExerciseList/ExerciseButtons.tsx +33 −14 Original line number Diff line number Diff line import type { ExerciseLoadingPayload } from '@/events' import DeleteAlert from '@/exercisepanel/DeleteAlert' import StartAlert from '@/exercisepanel/StartAlert' import { convertMinutes } from '@/utils' import type { Intent } from '@blueprintjs/core' import { Button, ButtonGroup, Classes } from '@blueprintjs/core' import { css } from '@emotion/css' Loading Loading @@ -106,6 +108,7 @@ const ExerciseButtons: FC<ExerciseButtonsProps> = ({ runningAny, }) => { const [alertOpen, setAlertOpen] = useState(false) const [startAlertOpen, setStartAlertOpen] = useState(false) const intent: Intent | undefined = useMemo(() => { if (exercise.running) return 'success' Loading @@ -127,10 +130,11 @@ const ExerciseButtons: FC<ExerciseButtonsProps> = ({ ) : ( <> {!exercise.running && !exercise.finished && ( <> <Button intent={intent} icon='play' onClick={() => start(client, exercise.id, 'start')} onClick={() => setStartAlertOpen(true)} loading={loading} disabled={runningAny} title={ Loading @@ -141,6 +145,21 @@ const ExerciseButtons: FC<ExerciseButtonsProps> = ({ : 'Start' } /> {type === 'managing' && ( <StartAlert open={startAlertOpen} setOpen={setStartAlertOpen} onSubmit={() => start(client, exercise.id, 'start')} loading={loading} > <p>Are you sure you want to start this exercise? </p> <p> The exercise will take: <br /> <b>{convertMinutes(exercise.config.exerciseDuration)}</b> </p> </StartAlert> )} </> )} {exercise.running && ( <Button Loading frontend/src/exercisepanel/StartAlert.tsx 0 → 100644 +36 −0 Original line number Diff line number Diff line import { Alert } from '@blueprintjs/core' import type { PropsWithChildren } from 'react' import { type Dispatch, type FC, type SetStateAction } from 'react' interface StartAlertProps extends PropsWithChildren { open: boolean setOpen: Dispatch<SetStateAction<boolean>> onSubmit: () => void loading?: boolean } const StartAlert: FC<StartAlertProps> = ({ open, setOpen, children, onSubmit, loading, }) => ( <Alert isOpen={open} canEscapeKeyCancel canOutsideClickCancel cancelButtonText='Cancel' onCancel={() => setOpen(false)} confirmButtonText='Start' icon='warning-sign' intent='warning' onConfirm={onSubmit} onClose={() => setOpen(false)} loading={loading} > {children} </Alert> ) export default StartAlert frontend/src/utils.ts +25 −0 Original line number Diff line number Diff line Loading @@ -71,3 +71,28 @@ export const checkFileSize = (file: File) => { } return true } export const convertMinutes = (minutes: number) => { let hours = Math.floor(minutes / 60) const days = Math.floor(hours / 24) hours = hours % 24 minutes = minutes % 60 let result = '' if (days > 0) { const dText = days == 1 ? 'day' : 'days' const coma = hours > 0 ? ', ' : '' result = result.concat(days.toString(), ' ', dText, coma) } if (hours > 0) { const hText = hours == 1 ? 'hour' : 'hours' result = result.concat(hours.toString(), ' ', hText) } if (minutes > 0) { const mText = minutes == 1 ? 'minute' : 'minutes' const conjunction = hours > 0 ? ' and ' : days > 0 ? ' and ' : '' result = result.concat(conjunction, minutes.toString(), ' ', mText) } return result } Loading
frontend/src/components/ExerciseList/ExerciseButtons.tsx +33 −14 Original line number Diff line number Diff line import type { ExerciseLoadingPayload } from '@/events' import DeleteAlert from '@/exercisepanel/DeleteAlert' import StartAlert from '@/exercisepanel/StartAlert' import { convertMinutes } from '@/utils' import type { Intent } from '@blueprintjs/core' import { Button, ButtonGroup, Classes } from '@blueprintjs/core' import { css } from '@emotion/css' Loading Loading @@ -106,6 +108,7 @@ const ExerciseButtons: FC<ExerciseButtonsProps> = ({ runningAny, }) => { const [alertOpen, setAlertOpen] = useState(false) const [startAlertOpen, setStartAlertOpen] = useState(false) const intent: Intent | undefined = useMemo(() => { if (exercise.running) return 'success' Loading @@ -127,10 +130,11 @@ const ExerciseButtons: FC<ExerciseButtonsProps> = ({ ) : ( <> {!exercise.running && !exercise.finished && ( <> <Button intent={intent} icon='play' onClick={() => start(client, exercise.id, 'start')} onClick={() => setStartAlertOpen(true)} loading={loading} disabled={runningAny} title={ Loading @@ -141,6 +145,21 @@ const ExerciseButtons: FC<ExerciseButtonsProps> = ({ : 'Start' } /> {type === 'managing' && ( <StartAlert open={startAlertOpen} setOpen={setStartAlertOpen} onSubmit={() => start(client, exercise.id, 'start')} loading={loading} > <p>Are you sure you want to start this exercise? </p> <p> The exercise will take: <br /> <b>{convertMinutes(exercise.config.exerciseDuration)}</b> </p> </StartAlert> )} </> )} {exercise.running && ( <Button Loading
frontend/src/exercisepanel/StartAlert.tsx 0 → 100644 +36 −0 Original line number Diff line number Diff line import { Alert } from '@blueprintjs/core' import type { PropsWithChildren } from 'react' import { type Dispatch, type FC, type SetStateAction } from 'react' interface StartAlertProps extends PropsWithChildren { open: boolean setOpen: Dispatch<SetStateAction<boolean>> onSubmit: () => void loading?: boolean } const StartAlert: FC<StartAlertProps> = ({ open, setOpen, children, onSubmit, loading, }) => ( <Alert isOpen={open} canEscapeKeyCancel canOutsideClickCancel cancelButtonText='Cancel' onCancel={() => setOpen(false)} confirmButtonText='Start' icon='warning-sign' intent='warning' onConfirm={onSubmit} onClose={() => setOpen(false)} loading={loading} > {children} </Alert> ) export default StartAlert
frontend/src/utils.ts +25 −0 Original line number Diff line number Diff line Loading @@ -71,3 +71,28 @@ export const checkFileSize = (file: File) => { } return true } export const convertMinutes = (minutes: number) => { let hours = Math.floor(minutes / 60) const days = Math.floor(hours / 24) hours = hours % 24 minutes = minutes % 60 let result = '' if (days > 0) { const dText = days == 1 ? 'day' : 'days' const coma = hours > 0 ? ', ' : '' result = result.concat(days.toString(), ' ', dText, coma) } if (hours > 0) { const hText = hours == 1 ? 'hour' : 'hours' result = result.concat(hours.toString(), ' ', hText) } if (minutes > 0) { const mText = minutes == 1 ? 'minute' : 'minutes' const conjunction = hours > 0 ? ' and ' : days > 0 ? ' and ' : '' result = result.concat(conjunction, minutes.toString(), ' ', mText) } return result }