From f0b70572d052c672ea46b59a4bbe780c7484515b Mon Sep 17 00:00:00 2001 From: ys677 Date: Wed, 29 Oct 2025 07:05:34 +1300 Subject: [PATCH 1/3] import loadingButton, set button state, set minimum loading time --- .../WorkoutRoutines/widgets/forms/RoutineForm.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx b/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx index 4e43dcda..9e948cff 100644 --- a/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx +++ b/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx @@ -23,6 +23,7 @@ import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { makeLink, WgerLink } from "utils/url"; import * as yup from 'yup'; +import LoadingButton from "@mui/material/Button"; interface RoutineFormProps { existingRoutine?: Routine, @@ -42,6 +43,7 @@ export const RoutineForm = ({ const addRoutineQuery = useAddRoutineQuery(); const editRoutineQuery = useEditRoutineQuery(existingRoutine?.id ?? -1); const navigate = useNavigate(); + const [buttonState, setButtonState] = useState<'idle'|'loading'|'error'|'success'>('idle'); const routine = existingRoutine ? Routine.clone(existingRoutine) @@ -124,22 +126,28 @@ export const RoutineForm = ({ validationSchema={validationSchema} onSubmit={async (values) => { + setButtonState('loading'); + const minWait = new Promise(res => setTimeout(res, 1000)); // set minimum loading time to 1 second routine.name = values.name; routine.description = values.description; routine.fitInWeek = values.fitInWeek; routine.start = values.start!.toJSDate(); routine.end = values.end!.toJSDate(); - if (routine.id !== null) { + try{if (routine.id !== null) { editRoutineQuery.mutate(routine); } else { const result = await addRoutineQuery.mutateAsync(routine); navigate(makeLink(WgerLink.ROUTINE_EDIT, i18n.language, { id: result.id! })); - if (closeFn) { + if (closeFn) closeFn(); - } } + setButtonState('success'); + } catch(err){ + setButtonState('error'); + } + setTimeout(()=> setButtonState("idle"),1000); }} > {formik => ( @@ -234,6 +242,7 @@ export const RoutineForm = ({ color="primary" variant="contained" type="submit" + sx={{ mt: 2 }}> {t('save')} From eb4de5a660aba07956cb7b1f4b9468a86a2f806a Mon Sep 17 00:00:00 2001 From: ys677 Date: Wed, 29 Oct 2025 07:19:23 +1300 Subject: [PATCH 2/3] change the button text based on button state --- .../widgets/forms/RoutineForm.tsx | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx b/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx index 9e948cff..97732ccc 100644 --- a/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx +++ b/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx @@ -237,15 +237,30 @@ export const RoutineForm = ({ - + )} - sx={{ mt: 2 }}> - {t('save')} - From 70ad9e77cc0bd19612b05933671e38a6096b11c5 Mon Sep 17 00:00:00 2001 From: ys677 Date: Mon, 3 Nov 2025 17:52:13 +1300 Subject: [PATCH 3/3] formatting code --- .../widgets/forms/RoutineForm.tsx | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx b/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx index 97732ccc..06f0584a 100644 --- a/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx +++ b/src/components/WorkoutRoutines/widgets/forms/RoutineForm.tsx @@ -1,11 +1,11 @@ import HelpOutlineIcon from "@mui/icons-material/HelpOutline"; -import { Button, FormControlLabel, IconButton, Menu, MenuItem, Stack, Switch } from "@mui/material"; +import {Button, FormControlLabel, IconButton, Menu, MenuItem, Stack, Switch} from "@mui/material"; import Grid from '@mui/material/Grid'; import Tooltip from "@mui/material/Tooltip"; -import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers"; -import { AdapterLuxon } from "@mui/x-date-pickers/AdapterLuxon"; -import { WgerTextField } from "components/Common/forms/WgerTextField"; -import { useProfileQuery } from "components/User/queries/profile"; +import {DatePicker, LocalizationProvider} from "@mui/x-date-pickers"; +import {AdapterLuxon} from "@mui/x-date-pickers/AdapterLuxon"; +import {WgerTextField} from "components/Common/forms/WgerTextField"; +import {useProfileQuery} from "components/User/queries/profile"; import { DESCRIPTION_MAX_LENGTH, MAX_WORKOUT_DURATION, @@ -14,14 +14,14 @@ import { NAME_MIN_LENGTH, Routine } from "components/WorkoutRoutines/models/Routine"; -import { useAddRoutineQuery, useEditRoutineQuery } from "components/WorkoutRoutines/queries/routines"; -import { SlotEntryRoundingField } from "components/WorkoutRoutines/widgets/forms/SlotEntryForm"; -import { Form, Formik } from "formik"; -import { DateTime } from "luxon"; -import React, { useState } from 'react'; -import { useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; -import { makeLink, WgerLink } from "utils/url"; +import {useAddRoutineQuery, useEditRoutineQuery} from "components/WorkoutRoutines/queries/routines"; +import {SlotEntryRoundingField} from "components/WorkoutRoutines/widgets/forms/SlotEntryForm"; +import {Form, Formik} from "formik"; +import {DateTime} from "luxon"; +import React, {useState} from 'react'; +import {useTranslation} from "react-i18next"; +import {useNavigate} from "react-router-dom"; +import {makeLink, WgerLink} from "utils/url"; import * as yup from 'yup'; import LoadingButton from "@mui/material/Button"; @@ -43,7 +43,7 @@ export const RoutineForm = ({ const addRoutineQuery = useAddRoutineQuery(); const editRoutineQuery = useEditRoutineQuery(existingRoutine?.id ?? -1); const navigate = useNavigate(); - const [buttonState, setButtonState] = useState<'idle'|'loading'|'error'|'success'>('idle'); + const [buttonState, setButtonState] = useState<'idle' | 'loading' | 'error' | 'success'>('idle'); const routine = existingRoutine ? Routine.clone(existingRoutine) @@ -67,11 +67,11 @@ export const RoutineForm = ({ name: yup .string() .required() - .max(NAME_MAX_LENGTH, t('forms.maxLength', { chars: NAME_MAX_LENGTH })) - .min(NAME_MIN_LENGTH, t('forms.minLength', { chars: NAME_MIN_LENGTH })), + .max(NAME_MAX_LENGTH, t('forms.maxLength', {chars: NAME_MAX_LENGTH})) + .min(NAME_MIN_LENGTH, t('forms.minLength', {chars: NAME_MIN_LENGTH})), description: yup .string() - .max(DESCRIPTION_MAX_LENGTH, t('forms.maxLength', { chars: DESCRIPTION_MAX_LENGTH })), + .max(DESCRIPTION_MAX_LENGTH, t('forms.maxLength', {chars: DESCRIPTION_MAX_LENGTH})), start: yup .date() .required(), @@ -84,7 +84,7 @@ export const RoutineForm = ({ ) .test( 'hasMinimumDuration', - t('routines.minLengthRoutine', { number: MIN_WORKOUT_DURATION }), + t('routines.minLengthRoutine', {number: MIN_WORKOUT_DURATION}), function (value) { const startDate = this.parent.start; if (startDate && value) { @@ -98,7 +98,7 @@ export const RoutineForm = ({ ) .test( 'hasMaximumDuration', - t('routines.maxLengthRoutine', { number: MAX_WORKOUT_DURATION }), + t('routines.maxLengthRoutine', {number: MAX_WORKOUT_DURATION}), function (value) { const startDate = this.parent.start; if (startDate && value) { @@ -134,37 +134,38 @@ export const RoutineForm = ({ routine.start = values.start!.toJSDate(); routine.end = values.end!.toJSDate(); - try{if (routine.id !== null) { - editRoutineQuery.mutate(routine); - } else { - const result = await addRoutineQuery.mutateAsync(routine); - navigate(makeLink(WgerLink.ROUTINE_EDIT, i18n.language, { id: result.id! })); + try { + if (routine.id !== null) { + editRoutineQuery.mutate(routine); + } else { + const result = await addRoutineQuery.mutateAsync(routine); + navigate(makeLink(WgerLink.ROUTINE_EDIT, i18n.language, {id: result.id!})); - if (closeFn) - closeFn(); - } - setButtonState('success'); - } catch(err){ + if (closeFn) + closeFn(); + } + setButtonState('success'); + } catch (err) { setButtonState('error'); } - setTimeout(()=> setButtonState("idle"),1000); + setTimeout(() => setButtonState("idle"), 1000); }} > {formik => (
- - + + - + - + - {durationDays === 0 ? t('durationWeeks', { number: durationWeeks }) : t('durationWeeksDays', { + {durationDays === 0 ? t('durationWeeks', {number: durationWeeks}) : t('durationWeeksDays', { nrWeeks: durationWeeks, nrDays: durationDays })} @@ -229,10 +230,10 @@ export const RoutineForm = ({ control={ } - label={t('routines.fitDaysInWeek')} /> + label={t('routines.fitDaysInWeek')}/> - + @@ -243,7 +244,7 @@ export const RoutineForm = ({ loadingPosition="center" variant="contained" color="primary" - sx={{ mt: 2 }} + sx={{mt: 2}} > {t('save')} @@ -251,7 +252,7 @@ export const RoutineForm = ({