import { WgerTextField } from "@/core/forms/WgerTextField"; import { LoadingPlaceholder } from "@/core/ui/LoadingWidget/LoadingWidget"; import { Exercise, getLanguageByShortName, NameAutocompleter, useLanguageQuery } from "@/components/Exercises"; import { RIR_VALUES_SELECT } from "@/components/Routines/models/BaseConfig"; import { LogEntryForm } from "@/components/Routines/models/WorkoutLog"; import { useAddRoutineLogsQuery, useRoutineDetailQuery } from "@/components/Routines/queries"; import { REP_UNIT_REPETITIONS, SNACKBAR_AUTO_HIDE_DURATION } from "@/core/lib/consts"; import { SwapHoriz } from "@mui/icons-material"; import AddIcon from "@mui/icons-material/Add"; import DeleteIcon from "@mui/icons-material/DeleteOutlined"; import { Alert, Button, IconButton, InputAdornment, MenuItem, Snackbar, TextField, Typography } from "@mui/material"; import Grid from '@mui/material/Grid'; import { FieldArray, Form, Formik, FormikProps } from "formik"; import { DateTime } from "luxon"; import React, { useState } from 'react'; import { useTranslation } from "react-i18next"; import * as yup from "yup"; interface SessionLogsFormProps { dayId: number, routineId: number, selectedDate: DateTime, } export const SessionLogsForm = ({ dayId, routineId, selectedDate }: SessionLogsFormProps) => { const { t, i18n } = useTranslation(); const [snackbarOpen, setSnackbarOpen] = useState(false); const routineQuery = useRoutineDetailQuery(routineId); const addLogsQuery = useAddRoutineLogsQuery(routineId); const languageQuery = useLanguageQuery(); const handleSnackbarClose = () => setSnackbarOpen(false); const [exerciseIdToSwap, setExerciseIdToSwap] = useState(null); let language = undefined; if (languageQuery.isSuccess) { language = getLanguageByShortName( i18n.language, languageQuery.data! ); } if (routineQuery.isLoading) { return ; } const routine = routineQuery.data!; const iterationDayData = routine?.getDayData(dayId, selectedDate.toJSDate()) ?? []; const hasNoIterationData = iterationDayData.length === 0; const validationSchema = yup.object({ logs: yup.array().of( yup.object().shape({ rir: yup.number().nullable(), repetitions: yup.number().typeError(t('forms.enterNumber')).nullable(), weight: yup.number().typeError(t('forms.enterNumber')).nullable() }) ), }); const handleSubmit = async (values: { logs: LogEntryForm[] }) => { const iteration = hasNoIterationData ? null : iterationDayData[0].iteration; const data = values.logs .filter(l => l.rir !== '' || l.repetitions !== '' || l.weight !== '') .map(l => ({ date: selectedDate.toISO(), iteration: iteration, exercise: l.exercise?.id, day: dayId, routine: routineId, // eslint-disable-next-line camelcase slot_entry: l.slotEntry, rir: l.rir !== '' ? l.rir : null, // eslint-disable-next-line camelcase rir_target: l.rirTarget !== '' ? l.rirTarget : null, // eslint-disable-next-line camelcase repetitions_unit: l.repetitionsUnit?.id, repetitions: l.repetitions !== '' ? l.repetitions : null, // eslint-disable-next-line camelcase repetitions_target: l.repetitionsTarget !== '' ? l.repetitionsTarget : null, // eslint-disable-next-line camelcase weight_unit: l.weightUnit?.id, weight: l.weight !== '' ? l.weight : null, // eslint-disable-next-line camelcase weight_target: l.weightTarget !== '' ? l.weightTarget : null, } )); await addLogsQuery.mutateAsync(data); setSnackbarOpen(true); }; const handleCallback = async (exercise: Exercise | null, formik: FormikProps<{ logs: LogEntryForm[] }>) => { if (exercise === null) { return; } const updatedLogs = formik.values.logs.map((log) => { if (exerciseIdToSwap === log.exercise!.id) { // Empty the rest of the values, this is a new exercise not in the routine return { ...log, weight: '', weightTarget: '', repetitions: '', repetitionsTarget: '', rir: '', rirTarget: '', exercise: exercise, }; } return log; }); await formik.setValues({ ...formik.values, logs: updatedLogs }); setExerciseIdToSwap(null); }; // Compute initial values const initialValues = { logs: [] as LogEntryForm[] }; const dayDataList = hasNoIterationData ? routine.dayDataCurrentIteration.filter(dayData => dayData.day?.id === dayId) : iterationDayData; for (const dayData of dayDataList) { for (const slot of dayData.slots) { for (const config of slot.setConfigs) { for (let i = 0; i < config.nrOfSets; i++) { initialValues.logs.push({ exercise: config.exercise!, repetitionsUnit: config.repetitionsUnit!, weightUnit: config.weightUnit!, slotEntry: config.slotEntryId, rir: !hasNoIterationData && config.rir !== null ? config.rir : '', rirTarget: !hasNoIterationData && config.rir !== null ? config.rir : '', repetitions: !hasNoIterationData && config.repetitions !== null ? config.repetitions : '', repetitionsTarget: !hasNoIterationData && config.repetitions !== null ? config.repetitions : '', weight: !hasNoIterationData && config.weight !== null ? config.weight : '', weightTarget: !hasNoIterationData && config.weight !== null ? config.weight : '' }); } } } } return (<> {hasNoIterationData && {t('routines.weightLogNotPlanned')} } {formik => (
{({ insert, remove }) => (<> {formik.values.logs.map((log, index) => ( {/* Only show the exercise name the first time it appears */} {(index === 0 || (index > 0 && formik.values.logs[index - 1].exercise!.id !== formik.values.logs[index].exercise!.id)) && <> {exerciseIdToSwap !== formik.values.logs[index].exercise!.id && {formik.values.logs[index].exercise?.getTranslation(language).name} } {exerciseIdToSwap === formik.values.logs[index].exercise!.id && handleCallback(searchResponse, formik)} />} } {/* Only show reps that are not "repetitions" */} {formik.values.logs[index].repetitionsUnit?.id !== REP_UNIT_REPETITIONS ? {formik.values.logs[index].repetitionsUnit?.name} : null} }, htmlInput: { inputMode: 'decimal' } } }} /> {formik.values.logs[index].weightUnit?.name} }, htmlInput: { inputMode: 'decimal' } } }} /> {RIR_VALUES_SELECT.map((option) => ( {option.label} ))} remove(index)}> ))} )}
)}
{t('success')} ); };