@wger-project/react-components 25.10.16 → 25.11.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/build/chunks/{browser-ponyfill-DL_vVusK.js → browser-ponyfill-CyEkMYuR.js} +3 -3
- package/build/chunks/{browser-ponyfill-DL_vVusK.js.map → browser-ponyfill-CyEkMYuR.js.map} +1 -1
- package/build/locales/de/translation.json +334 -334
- package/build/locales/en/translation.json +12 -2
- package/build/locales/fil/translation.json +3 -0
- package/build/locales/fr/translation.json +347 -337
- package/build/locales/hr/translation.json +344 -244
- package/build/locales/it/translation.json +333 -333
- package/build/locales/ko/translation.json +327 -327
- package/build/locales/pt_PT/translation.json +330 -330
- package/build/locales/sk/translation.json +26 -1
- package/build/locales/sl/translation.json +321 -321
- package/build/locales/ta/translation.json +325 -325
- package/build/locales/uk/translation.json +344 -334
- package/build/locales/zh_Hans/translation.json +332 -332
- package/build/main.js +137 -236
- package/build/main.js.map +1 -1
- package/package.json +13 -13
- package/src/components/BodyWeight/Form/WeightForm.tsx +3 -4
- package/src/components/BodyWeight/WeightChart/index.tsx +26 -29
- package/src/components/Exercises/Detail/Head/ExerciseDeleteDialog.tsx +3 -4
- package/src/components/Exercises/ExerciseOverview.tsx +4 -4
- package/src/components/Exercises/Filter/NameAutcompleter.tsx +41 -39
- package/src/components/Exercises/Filter/NameAutocompleter.test.tsx +2 -1
- package/src/components/Measurements/Screens/MeasurementCategoryDetail.test.tsx +4 -2
- package/src/components/Measurements/widgets/MeasurementChart.tsx +27 -30
- package/src/components/Nutrition/components/BmiCalculator.tsx +40 -42
- package/src/components/Nutrition/widgets/IngredientAutcompleter.tsx +1 -1
- package/src/components/Nutrition/widgets/charts/MacrosPieChart.tsx +17 -19
- package/src/components/Nutrition/widgets/charts/NutritionDiaryChart.tsx +39 -38
- package/src/components/Nutrition/widgets/charts/NutritionalValuesDashboardChart.tsx +27 -29
- package/src/components/Nutrition/widgets/charts/NutritionalValuesPlannedLoggedChart.tsx +20 -19
- package/src/components/Nutrition/widgets/forms/NutritionDiaryEntryForm.tsx +15 -4
- package/src/components/WorkoutRoutines/Detail/RoutineDetailsTable.tsx +3 -3
- package/src/components/WorkoutRoutines/Detail/WorkoutStats.tsx +17 -19
- package/src/components/WorkoutRoutines/models/Day.ts +16 -6
- package/src/components/WorkoutRoutines/models/SlotEntry.ts +7 -2
- package/src/components/WorkoutRoutines/widgets/DayDetails.tsx +4 -4
- package/src/components/WorkoutRoutines/widgets/LogWidgets.tsx +35 -38
- package/src/components/WorkoutRoutines/widgets/RoutineDetailsCard.tsx +8 -11
- package/src/components/WorkoutRoutines/widgets/SlotDetails.tsx +4 -4
- package/src/components/WorkoutRoutines/widgets/forms/DayForm.tsx +21 -9
- package/src/components/WorkoutRoutines/widgets/forms/DayTypeSelect.tsx +66 -0
- package/src/components/WorkoutRoutines/widgets/forms/SessionForm.test.tsx +0 -2
- package/src/components/WorkoutRoutines/widgets/forms/SessionLogsForm.tsx +4 -4
- package/src/components/WorkoutRoutines/widgets/forms/SlotEntryForm.test.tsx +12 -10
- package/src/components/WorkoutRoutines/widgets/forms/SlotEntryForm.tsx +2 -1
- package/src/components/WorkoutRoutines/widgets/forms/SlotForm.tsx +1 -1
- package/src/services/exerciseTranslation.ts +24 -9
- package/src/services/responseType.ts +3 -29
- package/src/tests/exercises/searchResponse.ts +47 -22
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": "./build/index.js"
|
|
13
13
|
},
|
|
14
|
-
"version": "25.
|
|
14
|
+
"version": "25.11.17",
|
|
15
15
|
"repository": "https://github.com/wger-project/react",
|
|
16
16
|
"type": "module",
|
|
17
17
|
"publishConfig": {
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"@emotion/react": "^11.14.0",
|
|
23
23
|
"@emotion/styled": "^11.14.1",
|
|
24
24
|
"@hello-pangea/dnd": "^18.0.1",
|
|
25
|
-
"@mui/icons-material": "^7.3.
|
|
25
|
+
"@mui/icons-material": "^7.3.5",
|
|
26
26
|
"@mui/lab": "^7.0.1-beta.18",
|
|
27
27
|
"@mui/material": "^7.3.4",
|
|
28
28
|
"@mui/system": "^7.3.3",
|
|
29
|
-
"@mui/x-data-grid": "^8.
|
|
30
|
-
"@mui/x-date-pickers": "^8.
|
|
29
|
+
"@mui/x-data-grid": "^8.18.0",
|
|
30
|
+
"@mui/x-date-pickers": "^8.18.0",
|
|
31
31
|
"@tanstack/react-query": "^5.90.2",
|
|
32
|
-
"@vitejs/plugin-react": "^5.
|
|
32
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
33
33
|
"axios": "^1.12.2",
|
|
34
34
|
"formik": "^2.4.6",
|
|
35
35
|
"history": "^5.3.0",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"react-responsive": "^10.0.1",
|
|
45
45
|
"react-router-dom": "^7.9.4",
|
|
46
46
|
"react-simple-wysiwyg": "^3.4.1",
|
|
47
|
-
"recharts": "^3.
|
|
47
|
+
"recharts": "^3.4.1",
|
|
48
48
|
"slug": "^9.1.0",
|
|
49
49
|
"typescript": "^5.9.3",
|
|
50
50
|
"vite-tsconfig-paths": "^5.1.4",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"yup": "^1.7.1"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@eslint/js": "^9.
|
|
55
|
+
"@eslint/js": "^9.39.1",
|
|
56
56
|
"@tanstack/react-query-devtools": "^5.90.2",
|
|
57
57
|
"@testing-library/dom": "^10.4.1",
|
|
58
58
|
"@testing-library/jest-dom": "^6.9.1",
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
"@types/lodash": "^4.17.20",
|
|
63
63
|
"@types/luxon": "^3.7.1",
|
|
64
64
|
"@types/node": "^22.18.9",
|
|
65
|
-
"@types/react": "^19.2.
|
|
66
|
-
"@types/react-dom": "^19.2.
|
|
65
|
+
"@types/react": "^19.2.5",
|
|
66
|
+
"@types/react-dom": "^19.2.3",
|
|
67
67
|
"@types/react-is": "^19.2.0",
|
|
68
68
|
"@types/slug": "^5.0.9",
|
|
69
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
70
|
-
"@typescript-eslint/parser": "^8.
|
|
69
|
+
"@typescript-eslint/eslint-plugin": "^8.47.0",
|
|
70
|
+
"@typescript-eslint/parser": "^8.47.0",
|
|
71
71
|
"eslint": "^9.37.0",
|
|
72
72
|
"eslint-plugin-import": "^2.32.0",
|
|
73
73
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
@@ -76,10 +76,10 @@
|
|
|
76
76
|
"i18next-parser": "^9.3.0",
|
|
77
77
|
"jest": "^30.2.0",
|
|
78
78
|
"jest-environment-jsdom": "^30.2.0",
|
|
79
|
-
"jsdom": "^27.
|
|
79
|
+
"jsdom": "^27.2.0",
|
|
80
80
|
"ts-jest": "^29.4.5",
|
|
81
81
|
"typescript-eslint": "^8.46.0",
|
|
82
|
-
"vite": "^7.
|
|
82
|
+
"vite": "^7.2.2",
|
|
83
83
|
"vite-plugin-eslint": "^1.8.1",
|
|
84
84
|
"vitest": "^3.2.4"
|
|
85
85
|
},
|
|
@@ -8,7 +8,6 @@ import { Form, Formik } from "formik";
|
|
|
8
8
|
import { DateTime } from "luxon";
|
|
9
9
|
import { useState } from 'react';
|
|
10
10
|
import { useTranslation } from "react-i18next";
|
|
11
|
-
import { dateToYYYYMMDD } from "utils/date";
|
|
12
11
|
import * as yup from 'yup';
|
|
13
12
|
|
|
14
13
|
interface WeightFormProps {
|
|
@@ -41,7 +40,7 @@ export const WeightForm = ({ weightEntry, closeFn }: WeightFormProps) => {
|
|
|
41
40
|
(<Formik
|
|
42
41
|
initialValues={{
|
|
43
42
|
weight: weightEntry ? weightEntry.weight : 0,
|
|
44
|
-
date: weightEntry ?
|
|
43
|
+
date: weightEntry ? weightEntry.date : new Date(),
|
|
45
44
|
}}
|
|
46
45
|
validationSchema={validationSchema}
|
|
47
46
|
onSubmit={async (values) => {
|
|
@@ -49,12 +48,12 @@ export const WeightForm = ({ weightEntry, closeFn }: WeightFormProps) => {
|
|
|
49
48
|
// Edit existing weight entry
|
|
50
49
|
if (weightEntry) {
|
|
51
50
|
weightEntry.weight = values.weight;
|
|
52
|
-
weightEntry.date =
|
|
51
|
+
weightEntry.date = values.date;
|
|
53
52
|
editWeightQuery.mutate(weightEntry);
|
|
54
53
|
|
|
55
54
|
// Create a new weight entry
|
|
56
55
|
} else {
|
|
57
|
-
weightEntry = new WeightEntry(
|
|
56
|
+
weightEntry = new WeightEntry(values.date, values.weight);
|
|
58
57
|
addWeightQuery.mutate(weightEntry);
|
|
59
58
|
}
|
|
60
59
|
|
|
@@ -4,7 +4,7 @@ import { WeightEntry } from "components/BodyWeight/model";
|
|
|
4
4
|
import { WgerModal } from "components/Core/Modals/WgerModal";
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { useTranslation } from "react-i18next";
|
|
7
|
-
import { CartesianGrid, DotProps, Line, LineChart,
|
|
7
|
+
import { CartesianGrid, DotProps, Line, LineChart, Tooltip, XAxis, YAxis } from 'recharts';
|
|
8
8
|
import { dateToLocale } from "utils/date";
|
|
9
9
|
|
|
10
10
|
export interface WeightChartProps {
|
|
@@ -72,34 +72,31 @@ export const WeightChart = ({ weights, height }: WeightChartProps) => {
|
|
|
72
72
|
<WeightForm weightEntry={currentEntry} />
|
|
73
73
|
</WgerModal>
|
|
74
74
|
}
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<Tooltip content={<CustomTooltip />} />
|
|
101
|
-
</LineChart>
|
|
102
|
-
</ResponsiveContainer>
|
|
75
|
+
<LineChart data={weightData} responsive height={height}>
|
|
76
|
+
<Line
|
|
77
|
+
type="monotone"
|
|
78
|
+
dataKey="weight"
|
|
79
|
+
stroke={theme.palette.secondary.main}
|
|
80
|
+
strokeWidth={2}
|
|
81
|
+
dot={weightData.length > NR_OF_WEIGHTS_CHART_DOT ? false : { strokeWidth: 1, r: 4 }}
|
|
82
|
+
activeDot={{
|
|
83
|
+
stroke: 'black',
|
|
84
|
+
strokeWidth: 1,
|
|
85
|
+
r: 6,
|
|
86
|
+
onClick: handleClick
|
|
87
|
+
}} />
|
|
88
|
+
<CartesianGrid
|
|
89
|
+
stroke="#ccc"
|
|
90
|
+
strokeDasharray="5 5" />
|
|
91
|
+
<XAxis
|
|
92
|
+
dataKey="date"
|
|
93
|
+
type={'number'}
|
|
94
|
+
domain={['dataMin', 'dataMax']}
|
|
95
|
+
tickFormatter={timeStr => dateToLocale(new Date(timeStr))}
|
|
96
|
+
/>
|
|
97
|
+
<YAxis domain={['auto', 'auto']} />
|
|
98
|
+
<Tooltip content={<CustomTooltip />} />
|
|
99
|
+
</LineChart>
|
|
103
100
|
</div>
|
|
104
101
|
);
|
|
105
102
|
};
|
|
@@ -24,7 +24,6 @@ import React from "react";
|
|
|
24
24
|
import { useTranslation } from "react-i18next";
|
|
25
25
|
import { useNavigate } from "react-router-dom";
|
|
26
26
|
import { deleteExercise, deleteExerciseTranslation, getExercise } from "services";
|
|
27
|
-
import { ExerciseSearchResponse } from "services/responseType";
|
|
28
27
|
|
|
29
28
|
export function ExerciseDeleteDialog(props: {
|
|
30
29
|
onClose: () => void,
|
|
@@ -91,10 +90,10 @@ export function ExerciseDeleteDialog(props: {
|
|
|
91
90
|
<p>{t('exercises.replacementsSearch')}</p>
|
|
92
91
|
|
|
93
92
|
<NameAutocompleter
|
|
94
|
-
callback={(exercise:
|
|
93
|
+
callback={(exercise: Exercise | null) => {
|
|
95
94
|
if (exercise !== null) {
|
|
96
|
-
setReplacementId(exercise.
|
|
97
|
-
loadCurrentReplacement(exercise.
|
|
95
|
+
setReplacementId(exercise.id!);
|
|
96
|
+
loadCurrentReplacement(exercise.id!);
|
|
98
97
|
}
|
|
99
98
|
}}
|
|
100
99
|
/>
|
|
@@ -15,7 +15,7 @@ import { useExercisesQuery } from "components/Exercises/queries";
|
|
|
15
15
|
import React, { useContext, useMemo, useState } from "react";
|
|
16
16
|
import { useTranslation } from "react-i18next";
|
|
17
17
|
import { Link, useNavigate } from "react-router-dom";
|
|
18
|
-
import {
|
|
18
|
+
import { Exercise } from "components/Exercises/models/exercise";
|
|
19
19
|
import { makeLink, WgerLink } from "utils/url";
|
|
20
20
|
import { ExerciseFiltersContext } from './Filter/ExerciseFiltersContext';
|
|
21
21
|
import { FilterDrawer } from './Filter/FilterDrawer';
|
|
@@ -135,12 +135,12 @@ export const ExerciseOverviewList = () => {
|
|
|
135
135
|
page * ITEMS_PER_PAGE
|
|
136
136
|
);
|
|
137
137
|
|
|
138
|
-
const exerciseAdded = (
|
|
139
|
-
if (!
|
|
138
|
+
const exerciseAdded = (exercise: Exercise | null) => {
|
|
139
|
+
if (!exercise) {
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
navigate(makeLink(WgerLink.EXERCISE_DETAIL, i18n.language, { id:
|
|
143
|
+
navigate(makeLink(WgerLink.EXERCISE_DETAIL, i18n.language, { id: exercise.id }));
|
|
144
144
|
};
|
|
145
145
|
|
|
146
146
|
return (
|
|
@@ -12,25 +12,25 @@ import {
|
|
|
12
12
|
Switch,
|
|
13
13
|
TextField,
|
|
14
14
|
} from "@mui/material";
|
|
15
|
+
import { Exercise } from "components/Exercises/models/exercise";
|
|
15
16
|
import { SERVER_URL } from "config";
|
|
16
17
|
import debounce from "lodash/debounce";
|
|
17
18
|
import * as React from "react";
|
|
18
19
|
import { useState } from "react";
|
|
19
20
|
import { useTranslation } from "react-i18next";
|
|
20
|
-
import {
|
|
21
|
-
import { ExerciseSearchResponse } from "services/responseType";
|
|
21
|
+
import { searchExerciseTranslations } from "services";
|
|
22
22
|
import { LANGUAGE_SHORT_ENGLISH } from "utils/consts";
|
|
23
23
|
|
|
24
24
|
type NameAutocompleterProps = {
|
|
25
|
-
callback: (
|
|
25
|
+
callback: (exercise: Exercise | null) => void;
|
|
26
26
|
loadExercise?: boolean;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
export function NameAutocompleter({ callback, loadExercise }: NameAutocompleterProps) {
|
|
30
|
-
const [value, setValue] = React.useState<
|
|
30
|
+
const [value, setValue] = React.useState<Exercise | null>(null);
|
|
31
31
|
const [inputValue, setInputValue] = React.useState("");
|
|
32
32
|
const [searchEnglish, setSearchEnglish] = useState<boolean>(true);
|
|
33
|
-
const [options, setOptions] = React.useState<readonly
|
|
33
|
+
const [options, setOptions] = React.useState<readonly Exercise[]>([]);
|
|
34
34
|
const [t, i18n] = useTranslation();
|
|
35
35
|
|
|
36
36
|
loadExercise = loadExercise === undefined ? false : loadExercise;
|
|
@@ -61,7 +61,7 @@ export function NameAutocompleter({ callback, loadExercise }: NameAutocompleterP
|
|
|
61
61
|
<>
|
|
62
62
|
<Autocomplete
|
|
63
63
|
id="exercise-name-autocomplete"
|
|
64
|
-
getOptionLabel={(option) => option.
|
|
64
|
+
getOptionLabel={(option) => option.getTranslation().name}
|
|
65
65
|
data-testid="autocomplete"
|
|
66
66
|
filterOptions={(x) => x}
|
|
67
67
|
options={options}
|
|
@@ -70,13 +70,10 @@ export function NameAutocompleter({ callback, loadExercise }: NameAutocompleterP
|
|
|
70
70
|
filterSelectedOptions
|
|
71
71
|
value={value}
|
|
72
72
|
noOptionsText={t("noResults")}
|
|
73
|
-
isOptionEqualToValue={(option, value) => option.
|
|
74
|
-
onChange={async (event: React.SyntheticEvent, newValue:
|
|
73
|
+
isOptionEqualToValue={(option, value) => option.id === value.id}
|
|
74
|
+
onChange={async (event: React.SyntheticEvent, newValue: Exercise | null) => {
|
|
75
75
|
setOptions(newValue ? [newValue, ...options] : options);
|
|
76
76
|
setValue(newValue);
|
|
77
|
-
if (loadExercise && newValue !== null) {
|
|
78
|
-
newValue.exercise = await getExercise(newValue.data.base_id);
|
|
79
|
-
}
|
|
80
77
|
callback(newValue);
|
|
81
78
|
}}
|
|
82
79
|
onInputChange={(event, newInputValue) => {
|
|
@@ -102,34 +99,39 @@ export function NameAutocompleter({ callback, loadExercise }: NameAutocompleterP
|
|
|
102
99
|
}}
|
|
103
100
|
/>
|
|
104
101
|
)}
|
|
105
|
-
renderOption={(props, option, state) =>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
102
|
+
renderOption={(props, option, state) => {
|
|
103
|
+
const translation = option.getTranslation();
|
|
104
|
+
const mainImage = option.mainImage;
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<li
|
|
108
|
+
{...props}
|
|
109
|
+
key={`exercise-${state.index}-${option.id}`}
|
|
110
|
+
data-testid={`autocompleter-result-${option.id}`}
|
|
111
|
+
>
|
|
112
|
+
<ListItem disablePadding component="div">
|
|
113
|
+
<ListItemIcon>
|
|
114
|
+
{mainImage ? (
|
|
115
|
+
<Avatar alt="" src={`${SERVER_URL}${mainImage.url}`} variant="rounded" />
|
|
116
|
+
) : (
|
|
117
|
+
<PhotoIcon fontSize="large" />
|
|
118
|
+
)}
|
|
119
|
+
</ListItemIcon>
|
|
120
|
+
<ListItemText
|
|
121
|
+
primary={translation.name}
|
|
122
|
+
slotProps={{
|
|
123
|
+
primary: {
|
|
124
|
+
whiteSpace: "nowrap",
|
|
125
|
+
overflow: "hidden",
|
|
126
|
+
textOverflow: "ellipsis",
|
|
127
|
+
},
|
|
128
|
+
}}
|
|
129
|
+
secondary={option.category.name}
|
|
130
|
+
/>
|
|
131
|
+
</ListItem>
|
|
132
|
+
</li>
|
|
133
|
+
);
|
|
134
|
+
}}
|
|
133
135
|
/>
|
|
134
136
|
{i18n.language !== LANGUAGE_SHORT_ENGLISH && (
|
|
135
137
|
<FormGroup>
|
|
@@ -3,6 +3,7 @@ import { NameAutocompleter } from "components/Exercises/Filter/NameAutcompleter"
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { searchExerciseTranslations } from "services";
|
|
5
5
|
import { searchResponse } from "tests/exercises/searchResponse";
|
|
6
|
+
import { Exercise } from "components/Exercises/models/exercise";
|
|
6
7
|
|
|
7
8
|
jest.mock("services");
|
|
8
9
|
const mockCallback = jest.fn();
|
|
@@ -71,6 +72,6 @@ describe("Test the NameAutocompleter component", () => {
|
|
|
71
72
|
});
|
|
72
73
|
|
|
73
74
|
// Assert
|
|
74
|
-
expect(mockCallback).
|
|
75
|
+
expect(mockCallback).toHaveBeenCalledWith(expect.any(Exercise));
|
|
75
76
|
});
|
|
76
77
|
});
|
|
@@ -52,15 +52,17 @@ describe("Test the MeasurementCategoryDetail component", () => {
|
|
|
52
52
|
</QueryClientProvider>
|
|
53
53
|
);
|
|
54
54
|
|
|
55
|
+
screen.logTestingPlaygroundURL();
|
|
56
|
+
|
|
55
57
|
// Assert
|
|
56
58
|
expect(useMeasurementsQuery).toHaveBeenCalled();
|
|
57
59
|
expect(screen.getByText('Biceps')).toBeInTheDocument();
|
|
58
60
|
|
|
59
|
-
expect(screen.
|
|
61
|
+
expect(screen.getByRole('gridcell', { name: /10cm/i })).toBeInTheDocument();
|
|
60
62
|
expect(screen.getByText(/Feb 1, 2023/i)).toBeInTheDocument();
|
|
61
63
|
expect(screen.getByText('test note')).toBeInTheDocument();
|
|
62
64
|
|
|
63
|
-
expect(screen.
|
|
65
|
+
expect(screen.getByRole('gridcell', { name: /20cm/i })).toBeInTheDocument();
|
|
64
66
|
expect(screen.getByText(/Feb 2, 2023/i)).toBeInTheDocument();
|
|
65
67
|
expect(screen.getByText('important note')).toBeInTheDocument();
|
|
66
68
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box } from "@mui/material";
|
|
2
2
|
import { MeasurementCategory } from "components/Measurements/models/Category";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import { CartesianGrid, Line, LineChart,
|
|
4
|
+
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
|
|
5
5
|
import { theme } from "theme";
|
|
6
6
|
import { dateToLocale } from "utils/date";
|
|
7
7
|
|
|
@@ -19,34 +19,31 @@ export const MeasurementChart = (props: { category: MeasurementCategory }) => {
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
return <Box alignItems={'center'} display={'flex'} flexDirection={'column'}>
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{/*<Tooltip content={<CustomTooltip />} />*/}
|
|
49
|
-
</LineChart>
|
|
50
|
-
</ResponsiveContainer>
|
|
22
|
+
<LineChart data={entryData} responsive width="90%" height={200}>
|
|
23
|
+
<Line
|
|
24
|
+
type="monotone"
|
|
25
|
+
dataKey="value"
|
|
26
|
+
stroke={theme.palette.secondary.main}
|
|
27
|
+
strokeWidth={2}
|
|
28
|
+
dot={entryData.length > NR_OF_ENTRIES_CHART_DOT ? false : { strokeWidth: 1, r: 4 }}
|
|
29
|
+
activeDot={{
|
|
30
|
+
stroke: 'black',
|
|
31
|
+
strokeWidth: 1,
|
|
32
|
+
r: 6,
|
|
33
|
+
//onClick: handleClick
|
|
34
|
+
}} />
|
|
35
|
+
<CartesianGrid
|
|
36
|
+
stroke="#ccc"
|
|
37
|
+
strokeDasharray="5 5" />
|
|
38
|
+
<XAxis
|
|
39
|
+
dataKey="date"
|
|
40
|
+
type={'number'}
|
|
41
|
+
domain={['dataMin', 'dataMax']}
|
|
42
|
+
tickFormatter={timeStr => dateToLocale(new Date(timeStr))!}
|
|
43
|
+
tickCount={10}
|
|
44
|
+
/>
|
|
45
|
+
<YAxis domain={['auto', 'auto']} unit={props.category.unit} />
|
|
46
|
+
{/*<Tooltip content={<CustomTooltip />} />*/}
|
|
47
|
+
</LineChart>
|
|
51
48
|
</Box>;
|
|
52
49
|
};
|
|
@@ -6,7 +6,7 @@ import { WgerContainerRightSidebar } from "components/Core/Widgets/Container";
|
|
|
6
6
|
import { useProfileQuery } from "components/User/queries/profile";
|
|
7
7
|
import React, { useEffect, useState } from "react";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
|
-
import { Area, AreaChart, CartesianGrid, ReferenceDot,
|
|
9
|
+
import { Area, AreaChart, CartesianGrid, ReferenceDot, Tooltip, XAxis, YAxis, } from "recharts";
|
|
10
10
|
|
|
11
11
|
const bmiRanges = [
|
|
12
12
|
{ range: "obese", color: "#FF5733", min: 30, max: 100 },
|
|
@@ -128,48 +128,46 @@ export const BmiCalculator = () => {
|
|
|
128
128
|
{t('bmi.result', { value: bmi.toFixed(1) })}
|
|
129
129
|
</Typography>
|
|
130
130
|
}
|
|
131
|
-
<
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
131
|
+
<AreaChart data={chartData} responsive width="100%" height={400}>
|
|
132
|
+
<XAxis
|
|
133
|
+
dataKey="height"
|
|
134
|
+
type="number"
|
|
135
|
+
domain={[140, 220]}
|
|
136
|
+
unit="cm"
|
|
137
|
+
/>
|
|
138
|
+
<YAxis
|
|
139
|
+
domain={[40, 150]}
|
|
140
|
+
tickFormatter={(value) => Math.round(value).toString()} // Format as integers
|
|
141
|
+
unit="kg"
|
|
142
|
+
/>
|
|
143
|
+
<CartesianGrid strokeDasharray="3 3" />
|
|
144
|
+
<Tooltip
|
|
145
|
+
// @ts-ignore
|
|
146
|
+
formatter={(value, name) => [Math.round(value as number), t('bmi.' + (name as string))]}
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
{bmiRanges.map((range) => (
|
|
150
|
+
<Area
|
|
151
|
+
key={range.range}
|
|
152
|
+
type="monotone"
|
|
153
|
+
dataKey={range.range}
|
|
154
|
+
stroke={"black"}
|
|
155
|
+
// stroke={range.color}
|
|
156
|
+
fill={range.color}
|
|
157
|
+
fillOpacity={0.8}
|
|
143
158
|
/>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// stroke={range.color}
|
|
157
|
-
fill={range.color}
|
|
158
|
-
fillOpacity={0.8}
|
|
159
|
-
/>
|
|
160
|
-
))}
|
|
161
|
-
|
|
162
|
-
{bmi !== null &&
|
|
163
|
-
<ReferenceDot
|
|
164
|
-
x={height!}
|
|
165
|
-
y={weight!}
|
|
166
|
-
r={8}
|
|
167
|
-
fill="black"
|
|
168
|
-
stroke="none"
|
|
169
|
-
/>}
|
|
170
|
-
|
|
171
|
-
</AreaChart>
|
|
172
|
-
</ResponsiveContainer>
|
|
159
|
+
))}
|
|
160
|
+
|
|
161
|
+
{bmi !== null &&
|
|
162
|
+
<ReferenceDot
|
|
163
|
+
x={height!}
|
|
164
|
+
y={weight!}
|
|
165
|
+
r={8}
|
|
166
|
+
fill="black"
|
|
167
|
+
stroke="none"
|
|
168
|
+
/>}
|
|
169
|
+
|
|
170
|
+
</AreaChart>
|
|
173
171
|
<Stack direction={"row"} justifyContent="center">
|
|
174
172
|
<Box
|
|
175
173
|
height={20}
|
|
@@ -22,7 +22,7 @@ import { searchIngredient } from "services";
|
|
|
22
22
|
import { LANGUAGE_SHORT_ENGLISH } from "utils/consts";
|
|
23
23
|
|
|
24
24
|
type IngredientAutocompleterProps = {
|
|
25
|
-
callback: () => void;
|
|
25
|
+
callback: (ingredient: Ingredient | null) => void;
|
|
26
26
|
initialIngredient?: Ingredient | null;
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NutritionalValues } from "components/Nutrition/helpers/nutritionalValues";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
|
-
import { Cell, Legend, Pie, PieChart
|
|
4
|
+
import { Cell, Legend, Pie, PieChart } from 'recharts';
|
|
5
5
|
import { generateChartColors } from "utils/colors";
|
|
6
6
|
import { numberGramLocale } from "utils/numbers";
|
|
7
7
|
|
|
@@ -45,22 +45,20 @@ export const MacrosPieChart = (props: { data: NutritionalValues }) => {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
return <
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
</PieChart>
|
|
65
|
-
</ResponsiveContainer>;
|
|
48
|
+
return <PieChart responsive width={"100%"} height={300}>
|
|
49
|
+
<Pie
|
|
50
|
+
data={data}
|
|
51
|
+
labelLine={false}
|
|
52
|
+
// outerRadius={80}
|
|
53
|
+
label={renderCustomizedLabel}
|
|
54
|
+
fill="#8884d8"
|
|
55
|
+
dataKey="value"
|
|
56
|
+
>
|
|
57
|
+
{data.map((entry, index) => (
|
|
58
|
+
<Cell key={`cell-${index}`} fill={colorGenerator.next().value!} />
|
|
59
|
+
))}
|
|
60
|
+
</Pie>
|
|
61
|
+
{/*<Tooltip />*/}
|
|
62
|
+
<Legend />
|
|
63
|
+
</PieChart>;
|
|
66
64
|
};
|