diff --git a/src/components/Calendar/Components/CalendarComponent.tsx b/src/components/Calendar/Components/CalendarComponent.tsx index 56f7bffe7..e1e477a8b 100644 --- a/src/components/Calendar/Components/CalendarComponent.tsx +++ b/src/components/Calendar/Components/CalendarComponent.tsx @@ -25,7 +25,7 @@ export interface DayProps { const CalendarComponent = (props: { isStandalone?: boolean }) => { const [t] = useTranslation(); - const currentDate = new Date(); + const currentDate = useMemo(() => new Date(), []); const [currentMonth, setCurrentMonth] = useState(currentDate.getMonth()); const [currentYear, setCurrentYear] = useState(currentDate.getFullYear()); @@ -133,7 +133,7 @@ const CalendarComponent = (props: { isStandalone?: boolean }) => { setSelectedDay(todayWithData); } } - }, [isSuccess]); + }, [currentDate, days, isSuccess]); useEffect(() => { @@ -246,4 +246,4 @@ const CalendarComponent = (props: { isStandalone?: boolean }) => { ); }; -export default CalendarComponent; \ No newline at end of file +export default CalendarComponent; diff --git a/src/components/Calendar/Components/CalendarDayGrid.tsx b/src/components/Calendar/Components/CalendarDayGrid.tsx index 8f085140a..32a565aad 100644 --- a/src/components/Calendar/Components/CalendarDayGrid.tsx +++ b/src/components/Calendar/Components/CalendarDayGrid.tsx @@ -27,16 +27,16 @@ const CalendarDayGrid: React.FC = ({ return ( - {weekDays.map((day, index) => ( - + {weekDays.map((day) => ( + {day} ))} - {days.map((day, index) => ( - + {days.map((day) => ( + = ({ ); }; -export default CalendarDayGrid; \ No newline at end of file +export default CalendarDayGrid; diff --git a/src/components/Calendar/Components/Entries.tsx b/src/components/Calendar/Components/Entries.tsx index 9b5b23497..9066376ec 100644 --- a/src/components/Calendar/Components/Entries.tsx +++ b/src/components/Calendar/Components/Entries.tsx @@ -93,8 +93,8 @@ const Entries: React.FC = ({ selectedDay, isStandalone }) => { - {selectedDay.measurements.map((measurement, key) => ( - + {selectedDay.measurements.map((measurement) => ( + = ({ selectedDay, isStandalone }) => { ); }; -export default Entries; \ No newline at end of file +export default Entries; diff --git a/src/components/Dashboard/RoutineCard.tsx b/src/components/Dashboard/RoutineCard.tsx index 2307af19a..f88f24c54 100644 --- a/src/components/Dashboard/RoutineCard.tsx +++ b/src/components/Dashboard/RoutineCard.tsx @@ -76,12 +76,12 @@ const DayListItem = (props: { dayData: RoutineDayData }) => { - {props.dayData.slots.map((slotData, index) => ( -
- {slotData.setConfigs.map((setConfigData, index) => ( + {props.dayData.slots.map((slotData) => ( +
slotEntryId).join("-")}`}> + {slotData.setConfigs.map((setConfigData) => ( diff --git a/src/components/Exercises/forms/ExerciseAliases.tsx b/src/components/Exercises/forms/ExerciseAliases.tsx index 45ee349be..4c1bf7774 100644 --- a/src/components/Exercises/forms/ExerciseAliases.tsx +++ b/src/components/Exercises/forms/ExerciseAliases.tsx @@ -68,7 +68,7 @@ export function ExerciseAliases(props: { fieldName: string }) { newVal.splice(index, 1); helpers.setValue(newVal); }} - key={option.id ?? `${option.alias}-${index}`} + key={option.id ?? option.alias} /> )); @@ -98,4 +98,4 @@ export function ExerciseAliases(props: { fieldName: string }) { ); }} />; -} \ No newline at end of file +} diff --git a/src/components/Exercises/forms/ExerciseNotes.tsx b/src/components/Exercises/forms/ExerciseNotes.tsx index 5b45efc6c..5729385a6 100644 --- a/src/components/Exercises/forms/ExerciseNotes.tsx +++ b/src/components/Exercises/forms/ExerciseNotes.tsx @@ -3,15 +3,17 @@ import DeleteIcon from '@mui/icons-material/Delete'; import { IconButton, InputAdornment, TextField } from "@mui/material"; import Grid from '@mui/material/Grid'; import { useField } from "formik"; -import React, { useState } from "react"; +import React, { useRef, useState } from "react"; import { useTranslation } from "react-i18next"; export function ExerciseNotes(props: { fieldName: string }) { const [t] = useTranslation(); const [field, meta, helpers] = useField(props.fieldName); const [newNoteValue, setNewNoteValue] = useState(''); + const noteKeys = useRef(field.value.map(() => crypto.randomUUID())); const deleteAtIndex = (index: number) => { + noteKeys.current.splice(index, 1); helpers.setValue(field.value.filter((_: string, b: number) => b !== index)); }; @@ -20,6 +22,7 @@ export function ExerciseNotes(props: { fieldName: string }) { helpers.setValue(field.value); }; const addEntry = () => { + noteKeys.current.push(crypto.randomUUID()); field.value.push(newNoteValue); helpers.setValue(field.value); setNewNoteValue(''); @@ -51,7 +54,7 @@ export function ExerciseNotes(props: { fieldName: string }) { {field.value.map((note: string, index: number) => setNoteValueIndex(index, event.target.value)} @@ -73,4 +76,4 @@ export function ExerciseNotes(props: { fieldName: string }) { /> )} ; -} \ No newline at end of file +} diff --git a/src/components/Exercises/screens/Detail/ExerciseDetailEdit.test.tsx b/src/components/Exercises/screens/Detail/ExerciseDetailEdit.test.tsx index 259a9396b..31d85f912 100644 --- a/src/components/Exercises/screens/Detail/ExerciseDetailEdit.test.tsx +++ b/src/components/Exercises/screens/Detail/ExerciseDetailEdit.test.tsx @@ -106,7 +106,6 @@ describe("Exercise translation edit tests", () => { mutateAsync: vi.fn(), })); - // @ts-ignore // addTranslation.mockImplementation(() => Promise.resolve( // new Translation( // 300, diff --git a/src/components/Exercises/screens/Detail/ExerciseDetailView.tsx b/src/components/Exercises/screens/Detail/ExerciseDetailView.tsx index dfe247e1a..bc1768b1b 100644 --- a/src/components/Exercises/screens/Detail/ExerciseDetailView.tsx +++ b/src/components/Exercises/screens/Detail/ExerciseDetailView.tsx @@ -102,7 +102,7 @@ export const ExerciseDetailView = ({ } {t("exercises.description")} -
+
{currentTranslation?.notes.length > 0 && {t("exercises.notes")}} diff --git a/src/components/Exercises/screens/Detail/Head/index.tsx b/src/components/Exercises/screens/Detail/Head/index.tsx index a157b417c..685aeec2f 100644 --- a/src/components/Exercises/screens/Detail/Head/index.tsx +++ b/src/components/Exercises/screens/Detail/Head/index.tsx @@ -28,7 +28,7 @@ export interface HeadProp { languages: Language[] changeLanguage: (lang: Language) => void, language: Language | undefined // language displayed in the head since it's not found in the translations - setEditMode: Function, + setEditMode: (editMode: boolean) => void, editMode: boolean } diff --git a/src/components/Exercises/widgets/Overview/ExerciseGridLoadingSkeleton.tsx b/src/components/Exercises/widgets/Overview/ExerciseGridLoadingSkeleton.tsx index 7ba38509b..86dab2c00 100644 --- a/src/components/Exercises/widgets/Overview/ExerciseGridLoadingSkeleton.tsx +++ b/src/components/Exercises/widgets/Overview/ExerciseGridLoadingSkeleton.tsx @@ -4,10 +4,12 @@ import React from "react"; export const ExerciseGridSkeleton = () => { + const skeletonIds = Array.from({ length: 21 }, (_, id) => `exercise-skeleton-${id + 1}`); + return ( ( - {[...Array(21)].map((skeletonBase, idx) => ( - + {skeletonIds.map((skeletonId) => ( + diff --git a/src/components/Nutrition/screens/BmiCalculator.tsx b/src/components/Nutrition/screens/BmiCalculator.tsx index 7dfab7182..b13b293a2 100644 --- a/src/components/Nutrition/screens/BmiCalculator.tsx +++ b/src/components/Nutrition/screens/BmiCalculator.tsx @@ -144,7 +144,7 @@ export const BmiCalculator = () => { /> [Math.round(value as number), t('bmi.' + (name as string))]} /> @@ -202,4 +202,4 @@ export const BmiCalculator = () => { } /> ); -}; \ No newline at end of file +}; diff --git a/src/components/Nutrition/widgets/DiaryOverview.tsx b/src/components/Nutrition/widgets/DiaryOverview.tsx index a1bacf260..3bf9d5d32 100644 --- a/src/components/Nutrition/widgets/DiaryOverview.tsx +++ b/src/components/Nutrition/widgets/DiaryOverview.tsx @@ -27,7 +27,7 @@ export const DiaryOverview = (props: { - {Array.from(props.logged).map(([key]) => + {Array.from(props.logged).map(([key, diaryEntries]) => {t('nutrition.valueEnergyKcal', - { value: numberLocale(props.logged.get(key)?.nutritionalValues.energy!, i18n.language) } + { value: numberLocale(diaryEntries.nutritionalValues.energy, i18n.language) } )} - {numberLocale(props.logged.get(key)?.nutritionalValues.energy! - props.planned.energy, i18n.language)} + {numberLocale(diaryEntries.nutritionalValues.energy - props.planned.energy, i18n.language)} ) } ; -}; \ No newline at end of file +}; diff --git a/src/components/Nutrition/widgets/charts/MacrosPieChart.tsx b/src/components/Nutrition/widgets/charts/MacrosPieChart.tsx index bde145d6f..de9cc3682 100644 --- a/src/components/Nutrition/widgets/charts/MacrosPieChart.tsx +++ b/src/components/Nutrition/widgets/charts/MacrosPieChart.tsx @@ -54,8 +54,8 @@ export const MacrosPieChart = (props: { data: NutritionalValues }) => { fill="#8884d8" dataKey="value" > - {data.map((entry, index) => ( - + {data.map((entry) => ( + ))} {/**/} diff --git a/src/components/Nutrition/widgets/charts/NutritionalValuesDashboardChart.tsx b/src/components/Nutrition/widgets/charts/NutritionalValuesDashboardChart.tsx index c84a4aa79..c9d6c14a9 100644 --- a/src/components/Nutrition/widgets/charts/NutritionalValuesDashboardChart.tsx +++ b/src/components/Nutrition/widgets/charts/NutritionalValuesDashboardChart.tsx @@ -20,10 +20,12 @@ export const NutritionalValuesDashboardChart = (props: { const [t, i18n] = useTranslation(); const data = [ { + id: 'logged', name: '', value: energyPercentage, }, { + id: 'remaining', name: '', value: energyPercentage < 100 ? 100 - energyPercentage : 0, }, @@ -46,7 +48,7 @@ export const NutritionalValuesDashboardChart = (props: { dataKey="value" > {data.map((entry, index) => ( - + ))} diff --git a/src/components/Routines/models/WorkoutLog.ts b/src/components/Routines/models/WorkoutLog.ts index 19a00beb6..99080a608 100644 --- a/src/components/Routines/models/WorkoutLog.ts +++ b/src/components/Routines/models/WorkoutLog.ts @@ -6,6 +6,7 @@ import { WeightUnit } from "@/components/Routines/models/WeightUnit"; import { Adapter } from "@/core/lib/Adapter"; export interface LogEntryForm { + clientKey: string; exercise: Exercise | null; repetitionsUnit: RepetitionUnit | null; weightUnit: WeightUnit | null; @@ -156,4 +157,4 @@ export class WorkoutLogAdapter implements Adapter { rest: item.restTime, rest_target: item.restTimeTarget }); -} \ No newline at end of file +} diff --git a/src/components/Routines/screens/Detail/WorkoutStats.tsx b/src/components/Routines/screens/Detail/WorkoutStats.tsx index 99130626a..11a687098 100644 --- a/src/components/Routines/screens/Detail/WorkoutStats.tsx +++ b/src/components/Routines/screens/Detail/WorkoutStats.tsx @@ -133,11 +133,11 @@ export const WorkoutStats = () => { {statsData.data.map((row) => ( {row.key} - {row.values.map((value, index) => ( + {statsData.headers.map((header, index) => ( {value?.toFixed(selectedValueType === StatType.Intensity ? 2 : 0) || ""} + >{row.values[index]?.toFixed(selectedValueType === StatType.Intensity ? 2 : 0) || ""} ))} diff --git a/src/components/Routines/widgets/RoutineDetailsCard.tsx b/src/components/Routines/widgets/RoutineDetailsCard.tsx index 8d115cda6..e589e35b8 100644 --- a/src/components/Routines/widgets/RoutineDetailsCard.tsx +++ b/src/components/Routines/widgets/RoutineDetailsCard.tsx @@ -144,7 +144,7 @@ function SlotDataList(props: { slotData: SlotData }) { return ; })} @@ -184,8 +184,8 @@ export const DayDetailsCard = (props: { dayData: RoutineDayData, routineId: numb /> {props.dayData.slots.length > 0 && - {props.dayData.slots.map((slotData, index) => ( -
+ {props.dayData.slots.map((slotData) => ( +
slotEntryId).join("-")}`}> diff --git a/src/components/Routines/widgets/forms/BaseConfigForm.tsx b/src/components/Routines/widgets/forms/BaseConfigForm.tsx index 587a41e80..be85cec98 100644 --- a/src/components/Routines/widgets/forms/BaseConfigForm.tsx +++ b/src/components/Routines/widgets/forms/BaseConfigForm.tsx @@ -275,8 +275,8 @@ export const ConfigDetailsRequirementsField = (props: { open={Boolean(anchorEl)} onClose={() => setAnchorEl(null)} > - {...REQUIREMENTS_VALUES.map((e, index) => handleSelection(e as unknown as RequirementsType)}> {selectedElements.includes(e as unknown as RequirementsType) @@ -504,4 +504,4 @@ export const EntryDetailsStepField = (props: { ); }; -*/ \ No newline at end of file +*/ diff --git a/src/components/Routines/widgets/forms/ProgressionForm.tsx b/src/components/Routines/widgets/forms/ProgressionForm.tsx index 45abeb29a..1c76d34b4 100644 --- a/src/components/Routines/widgets/forms/ProgressionForm.tsx +++ b/src/components/Routines/widgets/forms/ProgressionForm.tsx @@ -349,7 +349,7 @@ export const ProgressionForm = (props: { {({ insert, remove }) => (<> {formik.values.entries.map((log, index) => ( - + } {log.requirements.length >= 0 &&
} - {log.requirements.length >= 0 && log.requirements.map((requirement, index) => ( - + {log.requirements.length >= 0 && log.requirements.map((requirement) => ( + {requirement}   ))} diff --git a/src/components/Routines/widgets/forms/SessionLogsForm.tsx b/src/components/Routines/widgets/forms/SessionLogsForm.tsx index 4dc86bae8..30866e0e2 100644 --- a/src/components/Routines/widgets/forms/SessionLogsForm.tsx +++ b/src/components/Routines/widgets/forms/SessionLogsForm.tsx @@ -139,6 +139,7 @@ export const SessionLogsForm = ({ dayId, routineId, selectedDate }: SessionLogsF for (let i = 0; i < config.nrOfSets; i++) { initialValues.logs.push({ + clientKey: `${dayData.iteration}-${config.slotEntryId}-${config.exerciseId}-${i}`, exercise: config.exercise!, repetitionsUnit: config.repetitionsUnit!, weightUnit: config.weightUnit!, @@ -174,7 +175,7 @@ export const SessionLogsForm = ({ dayId, routineId, selectedDate }: SessionLogsF {({ 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)) && <> diff --git a/src/core/ui/Widgets/FormError.tsx b/src/core/ui/Widgets/FormError.tsx index 09e7b9b1c..371d98cad 100644 --- a/src/core/ui/Widgets/FormError.tsx +++ b/src/core/ui/Widgets/FormError.tsx @@ -16,8 +16,8 @@ export const FormQueryErrors = (props: { mutationQuery: any }) => { {props.mutationQuery.error?.message}
    - {collectValidationErrors(props.mutationQuery.error.response?.data).map((error, index) => -
  • {error}
  • + {[...new Set(collectValidationErrors(props.mutationQuery.error.response?.data))].map((error) => +
  • {error}
  • )}
@@ -36,11 +36,11 @@ export const FormQueryErrorsSnackbar = (props: { mutationQuery: any }) => { {props.mutationQuery.error?.message}
    - {collectValidationErrors(props.mutationQuery.error.response?.data).map((error, index) => -
  • {error}
  • + {[...new Set(collectValidationErrors(props.mutationQuery.error.response?.data))].map((error) => +
  • {error}
  • )}
); -}; \ No newline at end of file +}; diff --git a/src/core/ui/Widgets/RenderLoadingQuery.tsx b/src/core/ui/Widgets/RenderLoadingQuery.tsx index 9f29c58ec..e4fc86e00 100644 --- a/src/core/ui/Widgets/RenderLoadingQuery.tsx +++ b/src/core/ui/Widgets/RenderLoadingQuery.tsx @@ -16,12 +16,11 @@ export const RenderLoadingQuery = (props: { query: UseQueryResult, child: JSX.El sx={{ height: 200, alignItems: "center", mt: 2, justifyContent: "center" }} component={Stack} direction="column"> - {/*// @ts-ignore */} - Error while fetching data: {props.query.error!.message} + Error while fetching data: {props.query.error.message} ; } if (props.query.isSuccess) { return props.child; } -}; \ No newline at end of file +}; diff --git a/src/i18n.ts b/src/i18n.ts index b9a231667..0b625023a 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -2,12 +2,12 @@ import { IS_PROD } from "@/config"; import i18n from "i18next"; import LanguageDetector from 'i18next-browser-languagedetector'; import Backend from 'i18next-http-backend'; -import common from "@/locales/en/translation.json"; +import type common from "@/locales/en/translation.json"; import { initReactI18next } from "react-i18next"; export const resources = { en: { - common, + common: null as unknown as typeof common, }, } as const; @@ -71,4 +71,4 @@ i18n //resources }); -export default i18n; \ No newline at end of file +export default i18n;