@wger-project/react-components 25.10.24 → 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/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/fil/translation.json +3 -0
- package/build/locales/sk/translation.json +26 -1
- package/build/main.js +131 -229
- 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/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/WorkoutRoutines/Detail/WorkoutStats.tsx +17 -19
- package/src/components/WorkoutRoutines/widgets/DayDetails.tsx +3 -3
- package/src/components/WorkoutRoutines/widgets/LogWidgets.tsx +35 -38
- package/src/components/WorkoutRoutines/widgets/SlotDetails.tsx +4 -4
- package/src/components/WorkoutRoutines/widgets/forms/SessionLogsForm.tsx +4 -4
- package/src/services/exerciseTranslation.ts +24 -9
- package/src/services/responseType.ts +3 -29
- package/src/tests/exercises/searchResponse.ts +47 -22
|
@@ -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 { Bar, BarChart, CartesianGrid, Legend,
|
|
4
|
+
import { Bar, BarChart, CartesianGrid, Legend, Tooltip, XAxis, YAxis } from 'recharts';
|
|
5
5
|
import { generateChartColors } from "utils/colors";
|
|
6
6
|
import { numberLocale } from "utils/numbers";
|
|
7
7
|
|
|
@@ -50,46 +50,47 @@ export const NutritionDiaryChart = ({ showPlanned, planned, today, avg7Days }: N
|
|
|
50
50
|
];
|
|
51
51
|
|
|
52
52
|
return (
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
unit={t('nutrition.gramShort')}
|
|
76
|
-
name={t('nutrition.planned')}
|
|
77
|
-
fill={colorGenerator.next().value!}
|
|
78
|
-
/>
|
|
79
|
-
}
|
|
80
|
-
<Bar
|
|
81
|
-
dataKey="today"
|
|
82
|
-
unit={t('nutrition.gramShort')}
|
|
83
|
-
name={t('nutrition.today')}
|
|
84
|
-
fill={colorGenerator.next().value!}
|
|
85
|
-
/>
|
|
53
|
+
<BarChart
|
|
54
|
+
data={data}
|
|
55
|
+
margin={{
|
|
56
|
+
top: 20,
|
|
57
|
+
right: 30,
|
|
58
|
+
left: 20,
|
|
59
|
+
bottom: 5,
|
|
60
|
+
}}
|
|
61
|
+
responsive
|
|
62
|
+
width={"100%"}
|
|
63
|
+
height={300}
|
|
64
|
+
>
|
|
65
|
+
<CartesianGrid strokeDasharray="3 4" />
|
|
66
|
+
<XAxis dataKey="name" />
|
|
67
|
+
<YAxis
|
|
68
|
+
type="number"
|
|
69
|
+
orientation="left"
|
|
70
|
+
unit={t('nutrition.gramShort')}
|
|
71
|
+
/>
|
|
72
|
+
<Tooltip formatter={(value: number) => numberLocale(value, i18n.language)} />
|
|
73
|
+
<Legend />
|
|
74
|
+
{showPlanned &&
|
|
86
75
|
<Bar
|
|
87
|
-
dataKey="
|
|
76
|
+
dataKey="planned"
|
|
88
77
|
unit={t('nutrition.gramShort')}
|
|
89
|
-
name={t('nutrition.
|
|
78
|
+
name={t('nutrition.planned')}
|
|
90
79
|
fill={colorGenerator.next().value!}
|
|
91
80
|
/>
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
}
|
|
82
|
+
<Bar
|
|
83
|
+
dataKey="today"
|
|
84
|
+
unit={t('nutrition.gramShort')}
|
|
85
|
+
name={t('nutrition.today')}
|
|
86
|
+
fill={colorGenerator.next().value!}
|
|
87
|
+
/>
|
|
88
|
+
<Bar
|
|
89
|
+
dataKey="avg7Days"
|
|
90
|
+
unit={t('nutrition.gramShort')}
|
|
91
|
+
name={t('nutrition.7dayAvg')}
|
|
92
|
+
fill={colorGenerator.next().value!}
|
|
93
|
+
/>
|
|
94
|
+
</BarChart>
|
|
94
95
|
);
|
|
95
96
|
};
|
|
@@ -3,7 +3,7 @@ import { NutritionalValues } from "components/Nutrition/helpers/nutritionalValue
|
|
|
3
3
|
import { LinearPlannedLoggedChart } from "components/Nutrition/widgets/charts/LinearPlannedLoggedChart";
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
|
-
import { Cell, Pie, PieChart
|
|
6
|
+
import { Cell, Pie, PieChart } from 'recharts';
|
|
7
7
|
import { numberLocale } from "utils/numbers";
|
|
8
8
|
|
|
9
9
|
|
|
@@ -32,34 +32,32 @@ export const NutritionalValuesDashboardChart = (props: {
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
return <Stack direction={'row'}>
|
|
35
|
-
<
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</PieChart>
|
|
62
|
-
</ResponsiveContainer>
|
|
35
|
+
<PieChart responsive width={'50%'} height={140}>
|
|
36
|
+
<Pie
|
|
37
|
+
// cx={0}
|
|
38
|
+
// cy={'10'}
|
|
39
|
+
height={100}
|
|
40
|
+
data={data}
|
|
41
|
+
startAngle={200}
|
|
42
|
+
endAngle={-20}
|
|
43
|
+
innerRadius={60}
|
|
44
|
+
outerRadius={70}
|
|
45
|
+
paddingAngle={2}
|
|
46
|
+
dataKey="value"
|
|
47
|
+
>
|
|
48
|
+
{data.map((entry, index) => (
|
|
49
|
+
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
|
|
50
|
+
))}
|
|
51
|
+
</Pie>
|
|
52
|
+
<g>
|
|
53
|
+
<text x={'50%'} y={'45%'} fontSize="1.25em" textAnchor="middle">{/*fill="#333"*/}
|
|
54
|
+
{t('nutrition.valueEnergyKcal', { value: numberLocale(energyDiff, i18n.language) })}
|
|
55
|
+
</text>
|
|
56
|
+
<text x={'50%'} y={'60%'} fontSize="1em" textAnchor="middle">
|
|
57
|
+
{props.planned.energy > 0 && t(energyPercentage < 100 ? 'nutrition.valueRemaining' : 'nutrition.valueTooMany')}
|
|
58
|
+
</text>
|
|
59
|
+
</g>
|
|
60
|
+
</PieChart>
|
|
63
61
|
<Stack width={'50%'} spacing={1}>
|
|
64
62
|
<LinearPlannedLoggedChart
|
|
65
63
|
title={t('nutrition.protein')}
|
|
@@ -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 { Bar, BarChart, CartesianGrid,
|
|
4
|
+
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
|
5
5
|
import { generateChartColors } from "utils/colors";
|
|
6
6
|
|
|
7
7
|
|
|
@@ -32,23 +32,24 @@ export const NutritionalValuesPlannedLoggedChart = (props: {
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
<BarChart
|
|
36
|
+
data={data}
|
|
37
|
+
layout="vertical"
|
|
38
|
+
margin={{
|
|
39
|
+
left: 60,
|
|
40
|
+
}}
|
|
41
|
+
responsive
|
|
42
|
+
width={"100%"}
|
|
43
|
+
height={150}
|
|
44
|
+
>
|
|
45
|
+
<CartesianGrid strokeDasharray="3 4" />
|
|
46
|
+
<XAxis type={'number'} unit={'%'} />
|
|
47
|
+
<YAxis type={'category'} dataKey={'name'} />
|
|
48
|
+
<Bar
|
|
49
|
+
dataKey="value"
|
|
50
|
+
unit={'%'}
|
|
51
|
+
fill={colorGenerator.next().value!}
|
|
52
|
+
/>
|
|
53
|
+
</BarChart>
|
|
53
54
|
);
|
|
54
55
|
};
|
|
@@ -209,25 +209,23 @@ export const WorkoutStats = () => {
|
|
|
209
209
|
|
|
210
210
|
<Grid size={12}>
|
|
211
211
|
<Box width="100%" height={400}>
|
|
212
|
-
<
|
|
213
|
-
<
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
{
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
</LineChart>
|
|
230
|
-
</ResponsiveContainer>
|
|
212
|
+
<LineChart width="100%" height="100%" responsive>
|
|
213
|
+
<CartesianGrid strokeDasharray="3 3" />
|
|
214
|
+
<XAxis dataKey="category" type="category" allowDuplicatedCategory={false} />
|
|
215
|
+
<YAxis dataKey="value" />
|
|
216
|
+
<Tooltip
|
|
217
|
+
formatter={(value: number) => Number.isInteger(value) ? value.toFixed(0) : value.toFixed(2)} />
|
|
218
|
+
<Legend
|
|
219
|
+
layout={"vertical"}
|
|
220
|
+
verticalAlign="middle"
|
|
221
|
+
align="right"
|
|
222
|
+
wrapperStyle={{ paddingLeft: "20px" }}
|
|
223
|
+
/>
|
|
224
|
+
{chartData.map((s) => (
|
|
225
|
+
<Line dataKey="value" data={s.data} name={s.name} key={s.name}
|
|
226
|
+
stroke={colorGenerator.next()!.value!} />
|
|
227
|
+
))}
|
|
228
|
+
</LineChart>
|
|
231
229
|
</Box>
|
|
232
230
|
</Grid>
|
|
233
231
|
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
import Grid from '@mui/material/Grid';
|
|
25
25
|
import { LoadingPlaceholder, LoadingProgressIcon } from "components/Core/LoadingWidget/LoadingWidget";
|
|
26
26
|
import { NameAutocompleter } from "components/Exercises/Filter/NameAutcompleter";
|
|
27
|
+
import { Exercise } from "components/Exercises/models/exercise";
|
|
27
28
|
import { useProfileQuery } from "components/User/queries/profile";
|
|
28
29
|
import { Day } from "components/WorkoutRoutines/models/Day";
|
|
29
30
|
import { Slot } from "components/WorkoutRoutines/models/Slot";
|
|
@@ -43,7 +44,6 @@ import { SlotDetails } from "components/WorkoutRoutines/widgets/SlotDetails";
|
|
|
43
44
|
import React, { useState } from "react";
|
|
44
45
|
import { useTranslation } from "react-i18next";
|
|
45
46
|
import { Link } from "react-router-dom";
|
|
46
|
-
import { ExerciseSearchResponse } from "services/responseType";
|
|
47
47
|
import { SNACKBAR_AUTO_HIDE_DURATION, WEIGHT_UNIT_KG, WEIGHT_UNIT_LB } from "utils/consts";
|
|
48
48
|
import { makeLink, WgerLink } from "utils/url";
|
|
49
49
|
|
|
@@ -381,13 +381,13 @@ export const DayDetails = (props: {
|
|
|
381
381
|
&& <Grid size={12}>
|
|
382
382
|
<Box height={20} />
|
|
383
383
|
<NameAutocompleter
|
|
384
|
-
callback={(exercise:
|
|
384
|
+
callback={(exercise: Exercise | null) => {
|
|
385
385
|
if (exercise === null) {
|
|
386
386
|
return;
|
|
387
387
|
}
|
|
388
388
|
addSlotEntryQuery.mutate(new SlotEntry({
|
|
389
389
|
slotId: slot.id!,
|
|
390
|
-
exerciseId: exercise.
|
|
390
|
+
exerciseId: exercise.id!,
|
|
391
391
|
type: 'normal',
|
|
392
392
|
order: slot.entries.length + 1,
|
|
393
393
|
weightUnitId: userProfileQuery.data!.useMetric ? WEIGHT_UNIT_KG : WEIGHT_UNIT_LB,
|
|
@@ -27,7 +27,6 @@ import { useTranslation } from "react-i18next";
|
|
|
27
27
|
import {
|
|
28
28
|
CartesianGrid,
|
|
29
29
|
Legend,
|
|
30
|
-
ResponsiveContainer,
|
|
31
30
|
Scatter,
|
|
32
31
|
ScatterChart,
|
|
33
32
|
Tooltip,
|
|
@@ -292,43 +291,41 @@ export const TimeSeriesChart = (props: { data: WorkoutLog[] }) => {
|
|
|
292
291
|
|
|
293
292
|
return (
|
|
294
293
|
<Box>
|
|
295
|
-
<
|
|
296
|
-
<
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
</ScatterChart>
|
|
331
|
-
</ResponsiveContainer>
|
|
294
|
+
<ScatterChart responsive width={"100%"} height={250}>
|
|
295
|
+
<XAxis
|
|
296
|
+
dataKey="time"
|
|
297
|
+
domain={["auto", "auto"]}
|
|
298
|
+
name="Time"
|
|
299
|
+
tickFormatter={unixTime => luxonDateTimeToLocale(DateTime.fromMillis(unixTime))}
|
|
300
|
+
type="number"
|
|
301
|
+
/>
|
|
302
|
+
<YAxis
|
|
303
|
+
domain={["auto", "auto"]}
|
|
304
|
+
dataKey="value"
|
|
305
|
+
name="Value"
|
|
306
|
+
unit="kg"
|
|
307
|
+
/>
|
|
308
|
+
|
|
309
|
+
{Array.from(result).map(([key, value]) => {
|
|
310
|
+
const color = colorGenerator.next().value!;
|
|
311
|
+
const formattedData = formatData(value);
|
|
312
|
+
|
|
313
|
+
return <Scatter
|
|
314
|
+
key={key}
|
|
315
|
+
data={formattedData}
|
|
316
|
+
fill={color}
|
|
317
|
+
line={{ stroke: color }}
|
|
318
|
+
lineType="joint"
|
|
319
|
+
lineJointType="monotoneX"
|
|
320
|
+
name={key?.toString()}
|
|
321
|
+
/>;
|
|
322
|
+
}
|
|
323
|
+
)}
|
|
324
|
+
|
|
325
|
+
<Tooltip content={<ExerciseLogTooltip />} />
|
|
326
|
+
<CartesianGrid strokeDasharray="3 3" />
|
|
327
|
+
<Legend />
|
|
328
|
+
</ScatterChart>
|
|
332
329
|
</Box>
|
|
333
330
|
);
|
|
334
331
|
};
|
|
@@ -4,6 +4,7 @@ import EditOffIcon from '@mui/icons-material/EditOff';
|
|
|
4
4
|
import { Alert, AlertTitle, IconButton, Typography } from "@mui/material";
|
|
5
5
|
import Grid from '@mui/material/Grid';
|
|
6
6
|
import { NameAutocompleter } from "components/Exercises/Filter/NameAutcompleter";
|
|
7
|
+
import { Exercise } from "components/Exercises/models/exercise";
|
|
7
8
|
import { useLanguageQuery } from "components/Exercises/queries";
|
|
8
9
|
import { BaseConfig } from "components/WorkoutRoutines/models/BaseConfig";
|
|
9
10
|
import { Slot } from "components/WorkoutRoutines/models/Slot";
|
|
@@ -21,7 +22,6 @@ import {
|
|
|
21
22
|
import React, { useState } from "react";
|
|
22
23
|
import { useTranslation } from "react-i18next";
|
|
23
24
|
import { getLanguageByShortName } from "services";
|
|
24
|
-
import { ExerciseSearchResponse } from "services/responseType";
|
|
25
25
|
|
|
26
26
|
/*
|
|
27
27
|
* Converts a number to an alphabetic string, useful for counting
|
|
@@ -95,12 +95,12 @@ export const SlotEntryDetails = (props: {
|
|
|
95
95
|
|
|
96
96
|
const isPending = editSlotEntryQuery.isPending || deleteSlotEntryQuery.isPending;
|
|
97
97
|
|
|
98
|
-
const handleExerciseChange = (
|
|
99
|
-
if (
|
|
98
|
+
const handleExerciseChange = (exercise: Exercise | null) => {
|
|
99
|
+
if (exercise === null) {
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
editSlotEntryQuery.mutate(SlotEntry.clone(props.slotEntry, { exerciseId:
|
|
103
|
+
editSlotEntryQuery.mutate(SlotEntry.clone(props.slotEntry, { exerciseId: exercise.id! }));
|
|
104
104
|
setEditExercise(false);
|
|
105
105
|
};
|
|
106
106
|
|
|
@@ -6,6 +6,7 @@ import Grid from '@mui/material/Grid';
|
|
|
6
6
|
import { WgerTextField } from "components/Common/forms/WgerTextField";
|
|
7
7
|
import { LoadingPlaceholder } from "components/Core/LoadingWidget/LoadingWidget";
|
|
8
8
|
import { NameAutocompleter } from "components/Exercises/Filter/NameAutcompleter";
|
|
9
|
+
import { Exercise } from "components/Exercises/models/exercise";
|
|
9
10
|
import { useLanguageQuery } from "components/Exercises/queries";
|
|
10
11
|
import { RIR_VALUES_SELECT } from "components/WorkoutRoutines/models/BaseConfig";
|
|
11
12
|
import { LogEntryForm } from "components/WorkoutRoutines/models/WorkoutLog";
|
|
@@ -15,7 +16,6 @@ import { DateTime } from "luxon";
|
|
|
15
16
|
import React, { useState } from 'react';
|
|
16
17
|
import { useTranslation } from "react-i18next";
|
|
17
18
|
import { getLanguageByShortName } from "services";
|
|
18
|
-
import { ExerciseSearchResponse } from "services/responseType";
|
|
19
19
|
import { REP_UNIT_REPETITIONS, SNACKBAR_AUTO_HIDE_DURATION } from "utils/consts";
|
|
20
20
|
import * as yup from "yup";
|
|
21
21
|
|
|
@@ -96,11 +96,11 @@ export const SessionLogsForm = ({ dayId, routineId, selectedDate }: SessionLogsF
|
|
|
96
96
|
setSnackbarOpen(true);
|
|
97
97
|
};
|
|
98
98
|
|
|
99
|
-
const handleCallback = async (
|
|
99
|
+
const handleCallback = async (exercise: Exercise | null, formik: FormikProps<{
|
|
100
100
|
logs: LogEntryForm[]
|
|
101
101
|
}>) => {
|
|
102
102
|
|
|
103
|
-
if (
|
|
103
|
+
if (exercise === null) {
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -115,7 +115,7 @@ export const SessionLogsForm = ({ dayId, routineId, selectedDate }: SessionLogsF
|
|
|
115
115
|
repetitionsTarget: '',
|
|
116
116
|
rir: '',
|
|
117
117
|
rirTarget: '',
|
|
118
|
-
exercise:
|
|
118
|
+
exercise: exercise,
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
121
|
return log;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
+
import { Exercise, ExerciseAdapter } from "components/Exercises/models/exercise";
|
|
2
3
|
import { Translation, TranslationAdapter } from "components/Exercises/models/translation";
|
|
3
4
|
import { ENGLISH_LANGUAGE_CODE, LANGUAGE_SHORT_ENGLISH } from "utils/consts";
|
|
4
5
|
import { makeHeader, makeUrl } from "utils/url";
|
|
5
|
-
import {
|
|
6
|
+
import { ResponseType } from "./responseType";
|
|
6
7
|
|
|
7
8
|
export const EXERCISE_PATH = 'exercise';
|
|
8
9
|
export const EXERCISE_TRANSLATION_PATH = 'exercise-translation';
|
|
9
|
-
export const EXERCISE_SEARCH_PATH = 'exercise/search';
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
/*
|
|
@@ -15,7 +15,7 @@ export const EXERCISE_SEARCH_PATH = 'exercise/search';
|
|
|
15
15
|
export const getExerciseTranslations = async (id: number): Promise<Translation[]> => {
|
|
16
16
|
const url = makeUrl(EXERCISE_PATH, { query: { exercise: id } });
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
-
const { data } = await axios.get<ResponseType<
|
|
18
|
+
const { data } = await axios.get<ResponseType<Translation>>(url, {
|
|
19
19
|
headers: makeHeader(),
|
|
20
20
|
});
|
|
21
21
|
const adapter = new TranslationAdapter();
|
|
@@ -24,19 +24,34 @@ export const getExerciseTranslations = async (id: number): Promise<Translation[]
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
/*
|
|
27
|
-
*
|
|
27
|
+
* Search for exercises by name using the exerciseinfo endpoint
|
|
28
28
|
*/
|
|
29
|
-
export const searchExerciseTranslations = async (name: string,
|
|
29
|
+
export const searchExerciseTranslations = async (name: string,languageCode: string = ENGLISH_LANGUAGE_CODE,searchEnglish: boolean = true): Promise<Exercise[]> => {
|
|
30
30
|
const languages = [languageCode];
|
|
31
31
|
if (languageCode !== LANGUAGE_SHORT_ENGLISH && searchEnglish) {
|
|
32
32
|
languages.push(LANGUAGE_SHORT_ENGLISH);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
const url = makeUrl('exerciseinfo', {
|
|
36
|
+
query: {
|
|
37
|
+
name__search: name,
|
|
38
|
+
language__code: languages.join(','),
|
|
39
|
+
limit: 50,
|
|
40
|
+
}
|
|
41
|
+
});
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
try {
|
|
44
|
+
const { data } = await axios.get<ResponseType<Exercise>>(url);
|
|
45
|
+
|
|
46
|
+
if (!data || !data.results || !Array.isArray(data.results)) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const adapter = new ExerciseAdapter();
|
|
51
|
+
return data.results.map((item: unknown) => adapter.fromJson(item));
|
|
52
|
+
} catch {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
40
55
|
};
|
|
41
56
|
|
|
42
57
|
|
|
@@ -1,35 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Generic paginated response from the wger API
|
|
3
|
+
*/
|
|
3
4
|
export interface ResponseType<T> {
|
|
4
5
|
count: number,
|
|
5
6
|
next: number | null,
|
|
6
7
|
previous: number | null,
|
|
7
8
|
results: T[]
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
-
export interface ExerciseSearchResponse {
|
|
11
|
-
value: string,
|
|
12
|
-
data: {
|
|
13
|
-
id: number,
|
|
14
|
-
base_id: number,
|
|
15
|
-
name: string,
|
|
16
|
-
category: string,
|
|
17
|
-
image: string | null,
|
|
18
|
-
image_thumbnail: string | null,
|
|
19
|
-
},
|
|
20
|
-
exercise?: Exercise
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ExerciseSearchType {
|
|
24
|
-
suggestions: ExerciseSearchResponse[];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface IngredientSearchResponse {
|
|
28
|
-
value: string,
|
|
29
|
-
data: {
|
|
30
|
-
id: number,
|
|
31
|
-
name: string,
|
|
32
|
-
image: string | null,
|
|
33
|
-
image_thumbnail: string | null,
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,23 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
import { Exercise } from "components/Exercises/models/exercise";
|
|
2
|
+
import { Category } from "components/Exercises/models/category";
|
|
3
|
+
import { Translation } from "components/Exercises/models/translation";
|
|
4
|
+
|
|
5
|
+
export const searchResponse: Exercise[] = [
|
|
6
|
+
new Exercise(
|
|
7
|
+
998, // id
|
|
8
|
+
"uuid-998", // uuid
|
|
9
|
+
new Category(8, "Bauch"), // category
|
|
10
|
+
[], // equipment
|
|
11
|
+
[], // muscles
|
|
12
|
+
[], // musclesSecondary
|
|
13
|
+
[], // images
|
|
14
|
+
null, // variationId
|
|
15
|
+
[
|
|
16
|
+
new Translation(
|
|
17
|
+
1149, // id
|
|
18
|
+
"uuid-1149", // uuid
|
|
19
|
+
"Crunches an Negativbank", // name
|
|
20
|
+
"", // description
|
|
21
|
+
1 // language (German)
|
|
22
|
+
)
|
|
23
|
+
], // translations
|
|
24
|
+
[], // videos
|
|
25
|
+
[] // authors
|
|
26
|
+
),
|
|
27
|
+
new Exercise(
|
|
28
|
+
979, // id
|
|
29
|
+
"uuid-979", // uuid
|
|
30
|
+
new Category(11, "Brust"), // category
|
|
31
|
+
[], // equipment
|
|
32
|
+
[], // muscles
|
|
33
|
+
[], // musclesSecondary
|
|
34
|
+
[], // images
|
|
35
|
+
null, // variationId
|
|
36
|
+
[
|
|
37
|
+
new Translation(
|
|
38
|
+
1213, // id
|
|
39
|
+
"uuid-1213", // uuid
|
|
40
|
+
"Crunches am Seil", // name
|
|
41
|
+
"", // description
|
|
42
|
+
1 // language (German)
|
|
43
|
+
)
|
|
44
|
+
], // translations
|
|
45
|
+
[], // videos
|
|
46
|
+
[] // authors
|
|
47
|
+
)
|
|
23
48
|
];
|