import { SlotEntry, SlotEntryType } from "@/components/Routines/models/SlotEntry";
import {
useEditSlotEntryQuery,
useFetchRoutineRepUnitsQuery,
useFetchRoutineWeighUnitsQuery
} from "@/components/Routines/queries";
import { useEditProfileQuery, useProfileQuery } from "@/components/User";
import { DEBOUNCE_ROUTINE_FORMS } from "@/core/lib/consts";
import { LoadingProgressIcon } from "@/core/ui/LoadingWidget/LoadingWidget";
import { MenuItem, TextField } from "@mui/material";
import debounce from "lodash/debounce";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
export const SlotEntryTypeField = (props: { slotEntry: SlotEntry, routineId: number }) => {
const { t } = useTranslation();
const editQuery = useEditSlotEntryQuery(props.routineId);
const options = [
{
value: 'normal',
label: t('routines.set.normalSet'),
},
{
value: 'warmup',
label: t('routines.set.warmup'),
},
{
value: 'dropset',
label: t('routines.set.dropSet'),
},
{
value: 'myo',
label: t('routines.set.myo'),
},
{
value: 'partial',
label: t('routines.set.partial'),
},
{
value: 'forced',
label: t('routines.set.forced'),
},
{
value: 'tut',
label: t('routines.set.tut'),
},
{
value: 'iso',
label: t('routines.set.iso'),
},
{
value: 'jump',
label: t('routines.set.jump'),
}
] as const;
const handleOnChange = (newValue: string) => {
editQuery.mutate(SlotEntry.clone(props.slotEntry, { type: newValue as SlotEntryType }));
};
return <>
handleOnChange(e.target.value)}
>
{options!.map((option) => (
))}
>;
};
export const SlotEntryRepetitionUnitField = (props: { slotEntry: SlotEntry, routineId: number }) => {
const { t } = useTranslation();
const editSlotEntryQuery = useEditSlotEntryQuery(props.routineId);
const repUnitsQuery = useFetchRoutineRepUnitsQuery();
if (repUnitsQuery.isLoading) {
return ;
}
const options = repUnitsQuery.data?.map((unit) => ({
value: unit.id,
label: unit.name,
}));
const handleOnChange = (newValue: string) => {
editSlotEntryQuery.mutate(SlotEntry.clone(props.slotEntry, { repetitionUnitId: parseInt(newValue) }));
};
return <>
handleOnChange(e.target.value)}
>
{options!.map((option) => (
))}
>;
};
export const SlotEntryWeightUnitField = (props: { slotEntry: SlotEntry, routineId: number }) => {
const { t } = useTranslation();
const editSlotEntryQuery = useEditSlotEntryQuery(props.routineId);
const weightUnitsQuery = useFetchRoutineWeighUnitsQuery();
const userProfileQuery = useProfileQuery();
if (weightUnitsQuery.isLoading || userProfileQuery.isLoading) {
return ;
}
const options = weightUnitsQuery.data?.map((unit) => ({
value: unit.id,
label: unit.name,
}));
const handleOnChange = (newValue: string) => {
editSlotEntryQuery.mutate(SlotEntry.clone(props.slotEntry, { weightUnitId: parseInt(newValue) }));
};
return <>
handleOnChange(e.target.value)}
>
{options!.map((option) => (
))}
>;
};
type BaseSlotEntryRoundingFieldProps = {
initialValue: number | null;
rounding: 'weight' | 'reps';
routineId: number;
};
type SlotEntryRoundingFieldProps =
| (BaseSlotEntryRoundingFieldProps & { editProfile: true })
| (BaseSlotEntryRoundingFieldProps & { editProfile: false; slotEntry: SlotEntry });
export const SlotEntryRoundingField = (props: SlotEntryRoundingFieldProps) => {
const { t } = useTranslation();
const editSlotEntryQuery = useEditSlotEntryQuery(props.routineId);
const editProfileQuery = useEditProfileQuery();
const [value, setValue] = useState(props.initialValue === null ? '' : props.initialValue);
// Hold the latest save logic in a ref so the debounced wrapper always
// uses current props/queries instead of values captured on first render.
const saveRef = useRef<(newValue: string) => void>(() => {
});
saveRef.current = (newValue: string) => {
const parsedValue = isNaN(Number(newValue)) ? null : parseFloat(newValue);
const data = props.rounding === 'weight'
? { weightRounding: parsedValue }
: { repetitionRounding: parsedValue };
if (props.editProfile) {
editProfileQuery.mutate(data);
} else {
editSlotEntryQuery.mutate(SlotEntry.clone(props.slotEntry, data));
}
};
const debouncedSave = useMemo(
() => debounce((newValue: string) => saveRef.current(newValue), DEBOUNCE_ROUTINE_FORMS),
[]
);
useEffect(() => () => debouncedSave.cancel(), [debouncedSave]);
const handleOnChange = (newValue: string) => {
setValue(newValue);
debouncedSave(newValue);
};
return (
handleOnChange(e.target.value)}
slotProps={{ htmlInput: { inputMode: 'decimal' } }}
/>
);
};