@wger-project/react-components 25.11.22 → 26.1.18
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/assets/ajax-loader.gif +0 -0
- package/build/assets/index.css +1 -1
- package/build/assets/slick.svg +14 -0
- package/build/locales/de/translation.json +25 -6
- package/build/locales/en/translation.json +12 -0
- package/build/locales/es/translation.json +22 -3
- package/build/locales/fr/translation.json +10 -1
- package/build/locales/hi/translation.json +8 -0
- package/build/locales/nl/translation.json +350 -239
- package/build/locales/pt_BR/translation.json +349 -255
- package/build/locales/ru/translation.json +39 -3
- package/build/locales/uk/translation.json +10 -1
- package/build/main.js +170 -166
- package/build/main.js.map +1 -1
- package/package.json +8 -2
- package/src/components/BodyWeight/TableDashboard/TableDashboard.tsx +4 -6
- package/src/components/Calendar/Components/CalendarComponent.test.tsx +18 -22
- package/src/components/Calendar/Components/CalendarComponent.tsx +11 -8
- package/src/components/Calendar/Components/CalendarHeader.tsx +3 -3
- package/src/components/Calendar/Components/Entries.tsx +8 -3
- package/src/components/Dashboard/CalendarCard.tsx +16 -0
- package/src/components/Dashboard/ConfigurableDashboard.test.ts +128 -0
- package/src/components/Dashboard/ConfigurableDashboard.tsx +479 -0
- package/src/components/Dashboard/DashboardCard.tsx +122 -0
- package/src/components/Dashboard/EmptyCard.tsx +3 -3
- package/src/components/Dashboard/MeasurementCard.test.tsx +75 -0
- package/src/components/Dashboard/MeasurementCard.tsx +101 -0
- package/src/components/Dashboard/NutritionCard.tsx +88 -96
- package/src/components/Dashboard/RoutineCard.tsx +54 -69
- package/src/components/Dashboard/TrophiesCard.test.tsx +63 -0
- package/src/components/Dashboard/TrophiesCard.tsx +84 -0
- package/src/components/Dashboard/WeightCard.test.tsx +0 -10
- package/src/components/Dashboard/WeightCard.tsx +36 -42
- package/src/components/Exercises/Detail/Head/ExerciseDeleteDialog.tsx +1 -1
- package/src/components/Measurements/Screens/MeasurementCategoryOverview.tsx +1 -1
- package/src/components/Measurements/models/Category.ts +13 -2
- package/src/components/Measurements/models/Entry.ts +13 -2
- package/src/components/Trophies/components/TrophiesDetail.test.tsx +34 -0
- package/src/components/Trophies/components/TrophiesDetail.tsx +88 -0
- package/src/components/Trophies/models/trophy.test.ts +33 -0
- package/src/components/Trophies/models/trophy.ts +75 -0
- package/src/components/Trophies/models/userTrophy.test.ts +38 -0
- package/src/components/Trophies/models/userTrophy.ts +67 -0
- package/src/components/Trophies/models/userTrophyProgression.test.ts +43 -0
- package/src/components/Trophies/models/userTrophyProgression.ts +68 -0
- package/src/components/Trophies/queries/trophies.ts +31 -0
- package/src/components/Trophies/services/trophies.ts +22 -0
- package/src/components/Trophies/services/userTrophies.ts +33 -0
- package/src/components/Trophies/services/userTrophyProgression.ts +16 -0
- package/src/components/WorkoutRoutines/Detail/WorkoutStats.tsx +1 -1
- package/src/components/WorkoutRoutines/widgets/forms/DayTypeSelect.tsx +1 -2
- package/src/components/WorkoutRoutines/widgets/forms/SlotForm.tsx +0 -4
- package/src/components/index.ts +0 -2
- package/src/index.tsx +0 -46
- package/src/pages/Calendar/index.tsx +2 -2
- package/src/pages/WeightOverview/index.tsx +1 -1
- package/src/routes.tsx +87 -79
- package/src/services/exerciseTranslation.ts +5 -6
- package/src/services/measurements.ts +10 -17
- package/src/services/video.test.ts +4 -4
- package/src/tests/trophies/trophiesTestData.ts +80 -0
- package/src/utils/consts.ts +18 -3
- package/src/utils/url.test.ts +32 -1
- package/src/utils/url.ts +24 -3
- package/src/components/Carousel/carousel.module.css +0 -43
- package/src/components/Carousel/carousel.module.css.map +0 -1
- package/src/components/Carousel/carousel.module.scss +0 -46
- package/src/components/Carousel/index.tsx +0 -66
- package/src/components/Dashboard/Dashboard.tsx +0 -22
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
2
|
+
import { getTrophies } from "components/Trophies/services/trophies";
|
|
3
|
+
import { getUserTrophies, setTrophyAsNotified } from "components/Trophies/services/userTrophies";
|
|
4
|
+
import { getUserTrophyProgression } from "components/Trophies/services/userTrophyProgression";
|
|
5
|
+
import { QueryKey } from "utils/consts";
|
|
6
|
+
|
|
7
|
+
export const useTrophiesQuery = () => useQuery({
|
|
8
|
+
queryFn: () => getTrophies(),
|
|
9
|
+
queryKey: [QueryKey.TROPHIES],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const useUserTrophiesQuery = () => useQuery({
|
|
13
|
+
queryFn: () => getUserTrophies(),
|
|
14
|
+
queryKey: [QueryKey.USER_TROPHIES],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const useSetTrophyAsNotifiedQuery = () => {
|
|
18
|
+
const queryClient = useQueryClient();
|
|
19
|
+
|
|
20
|
+
return useMutation({
|
|
21
|
+
mutationFn: (trophyId: number) => setTrophyAsNotified(trophyId),
|
|
22
|
+
onSuccess: () => queryClient.invalidateQueries({
|
|
23
|
+
queryKey: [QueryKey.USER_TROPHIES]
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const useUserTrophyProgressionQuery = () => useQuery({
|
|
29
|
+
queryFn: () => getUserTrophyProgression(),
|
|
30
|
+
queryKey: [QueryKey.USER_TROPHY_PROGRESSION],
|
|
31
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Trophy } from "components/Trophies/models/trophy";
|
|
2
|
+
import { API_MAX_PAGE_SIZE, ApiPath } from "utils/consts";
|
|
3
|
+
import { fetchPaginated } from "utils/requests";
|
|
4
|
+
import { makeHeader, makeUrl } from "utils/url";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export const getTrophies = async (): Promise<Trophy[]> => {
|
|
8
|
+
|
|
9
|
+
const url = makeUrl(
|
|
10
|
+
ApiPath.API_TROPHIES_PATH,
|
|
11
|
+
{ query: { limit: API_MAX_PAGE_SIZE } }
|
|
12
|
+
);
|
|
13
|
+
const out: Trophy[] = [];
|
|
14
|
+
|
|
15
|
+
for await (const page of fetchPaginated(url, makeHeader())) {
|
|
16
|
+
for (const logData of page) {
|
|
17
|
+
out.push(Trophy.fromJson(logData));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
};
|
|
22
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { UserTrophy } from "components/Trophies/models/userTrophy";
|
|
3
|
+
import { API_MAX_PAGE_SIZE, ApiPath } from "utils/consts";
|
|
4
|
+
import { fetchPaginated } from "utils/requests";
|
|
5
|
+
import { makeHeader, makeUrl } from "utils/url";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export const getUserTrophies = async (): Promise<UserTrophy[]> => {
|
|
9
|
+
|
|
10
|
+
const url = makeUrl(
|
|
11
|
+
ApiPath.API_USER_TROPHIES_PATH,
|
|
12
|
+
{ query: { limit: API_MAX_PAGE_SIZE } }
|
|
13
|
+
);
|
|
14
|
+
const out: UserTrophy[] = [];
|
|
15
|
+
|
|
16
|
+
for await (const page of fetchPaginated(url, makeHeader())) {
|
|
17
|
+
for (const logData of page) {
|
|
18
|
+
out.push(UserTrophy.fromJson(logData));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export const setTrophyAsNotified = async (trophyId: number): Promise<void> => {
|
|
26
|
+
|
|
27
|
+
await axios.patch(
|
|
28
|
+
makeUrl(ApiPath.API_USER_TROPHIES_PATH, { id: trophyId }),
|
|
29
|
+
{ id: trophyId, "is_notified": true },
|
|
30
|
+
{ headers: makeHeader() }
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { ApiUserTrophyType, UserTrophyProgression } from "components/Trophies/models/userTrophyProgression";
|
|
3
|
+
import { ApiPath } from "utils/consts";
|
|
4
|
+
import { makeHeader, makeUrl } from "utils/url";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export const getUserTrophyProgression = async (): Promise<UserTrophyProgression[]> => {
|
|
8
|
+
|
|
9
|
+
const { data: trophyData } = await axios.get(
|
|
10
|
+
makeUrl(ApiPath.API_USER_TROPHY_PROGRESSION_PATH),
|
|
11
|
+
{ headers: makeHeader() }
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
return trophyData.map((item: ApiUserTrophyType) => UserTrophyProgression.fromJson(item));
|
|
15
|
+
};
|
|
16
|
+
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
import React, { useState } from "react";
|
|
31
31
|
import { useTranslation } from "react-i18next";
|
|
32
32
|
import { useParams } from "react-router-dom";
|
|
33
|
-
import { CartesianGrid, Legend, Line, LineChart,
|
|
33
|
+
import { CartesianGrid, Legend, Line, LineChart, Tooltip, XAxis, YAxis } from 'recharts';
|
|
34
34
|
import { getLanguageByShortName } from "services";
|
|
35
35
|
import { generateChartColors } from "utils/colors";
|
|
36
36
|
import { makeLink, WgerLink } from "utils/url";
|
|
@@ -10,8 +10,7 @@ interface DayTypeSelectProps {
|
|
|
10
10
|
|
|
11
11
|
export const DayTypeSelect = (props: DayTypeSelectProps) => {
|
|
12
12
|
const { t } = useTranslation();
|
|
13
|
-
const [field
|
|
14
|
-
|
|
13
|
+
const [field] = useField(props.fieldName);
|
|
15
14
|
const options = [
|
|
16
15
|
{
|
|
17
16
|
value: 'custom',
|
|
@@ -10,10 +10,6 @@ export const SlotForm = (props: { slot: Slot, routineId: number }) => {
|
|
|
10
10
|
const editSlotQuery = useEditSlotQuery(props.routineId);
|
|
11
11
|
const [slotComment, setSlotComment] = useState<string>(props.slot.comment);
|
|
12
12
|
|
|
13
|
-
const handleChange = (value: string) => {
|
|
14
|
-
setSlotComment(value);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
13
|
const handleBlur = () => {
|
|
18
14
|
editSlotQuery.mutate(Slot.clone(props.slot, { comment: slotComment }));
|
|
19
15
|
};
|
package/src/components/index.ts
CHANGED
package/src/index.tsx
CHANGED
|
@@ -4,9 +4,6 @@ import { ThemeProvider } from '@mui/material/styles';
|
|
|
4
4
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
5
5
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
6
6
|
import { LoadingWidget } from "components/Core/LoadingWidget/LoadingWidget";
|
|
7
|
-
import { NutritionCard } from "components/Dashboard/NutritionCard";
|
|
8
|
-
import { RoutineCard } from "components/Dashboard/RoutineCard";
|
|
9
|
-
import { WeightCard } from "components/Dashboard/WeightCard";
|
|
10
7
|
import { IngredientSearch } from "components/Nutrition/components/IngredientSearch";
|
|
11
8
|
import React, { Suspense } from 'react';
|
|
12
9
|
import { createRoot } from "react-dom/client";
|
|
@@ -123,49 +120,6 @@ renderComponentShadowDom('react-page');
|
|
|
123
120
|
/*
|
|
124
121
|
* Components used in the wger django app, don't change the IDs here
|
|
125
122
|
*/
|
|
126
|
-
const weightDashboard = document.getElementById("react-weight-dashboard");
|
|
127
|
-
if (weightDashboard) {
|
|
128
|
-
const root = createRoot(weightDashboard);
|
|
129
|
-
root.render(
|
|
130
|
-
<Suspense fallback={<LoadingWidget />}>
|
|
131
|
-
<ThemeProvider theme={theme}>
|
|
132
|
-
<QueryClientProvider client={queryClient}>
|
|
133
|
-
<WeightCard />
|
|
134
|
-
</QueryClientProvider>
|
|
135
|
-
</ThemeProvider>
|
|
136
|
-
</Suspense>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const nutritionDashboard = document.getElementById('react-nutrition-dashboard');
|
|
141
|
-
if (nutritionDashboard) {
|
|
142
|
-
const root = createRoot(nutritionDashboard);
|
|
143
|
-
root.render(
|
|
144
|
-
<Suspense fallback={<LoadingWidget />}>
|
|
145
|
-
<ThemeProvider theme={theme}>
|
|
146
|
-
<QueryClientProvider client={queryClient}>
|
|
147
|
-
<NutritionCard />
|
|
148
|
-
</QueryClientProvider>
|
|
149
|
-
</ThemeProvider>
|
|
150
|
-
</Suspense>
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const routineDashboard = document.getElementById('react-routine-dashboard');
|
|
155
|
-
if (routineDashboard) {
|
|
156
|
-
const root = createRoot(routineDashboard);
|
|
157
|
-
root.render(
|
|
158
|
-
<Suspense fallback={<LoadingWidget />}>
|
|
159
|
-
<ThemeProvider theme={theme}>
|
|
160
|
-
<QueryClientProvider client={queryClient}>
|
|
161
|
-
<RoutineCard />
|
|
162
|
-
</QueryClientProvider>
|
|
163
|
-
</ThemeProvider>
|
|
164
|
-
</Suspense>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
169
123
|
const ingredientSearchBox = document.getElementById("react-ingredient-search");
|
|
170
124
|
if (ingredientSearchBox) {
|
|
171
125
|
const root = createRoot(ingredientSearchBox);
|
package/src/routes.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigurableDashboard } from "components/Dashboard/ConfigurableDashboard";
|
|
2
2
|
import { ExerciseOverview } from "components/Exercises/ExerciseOverview";
|
|
3
3
|
import { MeasurementCategoryDetail } from "components/Measurements/Screens/MeasurementCategoryDetail";
|
|
4
4
|
import { MeasurementCategoryOverview } from "components/Measurements/Screens/MeasurementCategoryOverview";
|
|
@@ -6,6 +6,7 @@ import { BmiCalculator } from "components/Nutrition/components/BmiCalculator";
|
|
|
6
6
|
import { NutritionDiaryOverview } from "components/Nutrition/components/NutritionDiaryOverview";
|
|
7
7
|
import { PlanDetail } from "components/Nutrition/components/PlanDetail";
|
|
8
8
|
import { PlansOverview } from "components/Nutrition/components/PlansOverview";
|
|
9
|
+
import { TrophiesDetail } from "components/Trophies/components/TrophiesDetail";
|
|
9
10
|
import { RoutineAdd } from "components/WorkoutRoutines/Detail/RoutineAdd";
|
|
10
11
|
import { RoutineDetail } from "components/WorkoutRoutines/Detail/RoutineDetail";
|
|
11
12
|
import { RoutineDetailsTable } from "components/WorkoutRoutines/Detail/RoutineDetailsTable";
|
|
@@ -42,96 +43,103 @@ import { Route, Routes } from "react-router-dom";
|
|
|
42
43
|
* See also src/utils/url.ts
|
|
43
44
|
*/
|
|
44
45
|
export const WgerRoutes = () => {
|
|
45
|
-
return
|
|
46
|
-
<
|
|
46
|
+
return (
|
|
47
|
+
<Routes>
|
|
48
|
+
<Route path="/:lang">
|
|
49
|
+
<Route path="routine">
|
|
50
|
+
<Route index element={<RoutineOverview />} />
|
|
51
|
+
<Route path="overview" element={<RoutineOverview />} />
|
|
52
|
+
<Route path="calendar" element={<Calendar />} />
|
|
53
|
+
<Route path="add" element={<RoutineAdd />} />
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
<Route path=":routineId">
|
|
56
|
+
<Route path="day/:dayId">
|
|
57
|
+
<Route path="add-logs" element={<SessionAdd />} />
|
|
58
|
+
</Route>
|
|
59
|
+
<Route path="edit">
|
|
60
|
+
<Route index element={<RoutineEdit />} />
|
|
61
|
+
<Route path="progression/:slotId" element={<SlotProgressionEdit />} />
|
|
62
|
+
</Route>
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<Route path="
|
|
57
|
-
|
|
58
|
-
<Route path="edit">
|
|
59
|
-
<Route index element={<RoutineEdit />} />
|
|
60
|
-
<Route path="progression/:slotId" element={<SlotProgressionEdit />} />
|
|
64
|
+
<Route path="view" element={<RoutineDetail />} />
|
|
65
|
+
<Route path="table" element={<RoutineDetailsTable />} />
|
|
66
|
+
<Route path="logs" element={<WorkoutLogs />} />
|
|
67
|
+
<Route path="statistics" element={<WorkoutStats />} />
|
|
61
68
|
</Route>
|
|
62
69
|
|
|
63
|
-
<Route path="
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<Route path="view" element={<TemplateDetail />} />
|
|
70
|
+
<Route path="templates">
|
|
71
|
+
<Route path=":routineId">
|
|
72
|
+
<Route path="view" element={<TemplateDetail />} />
|
|
73
|
+
</Route>
|
|
74
|
+
<Route path="overview">
|
|
75
|
+
<Route path="private" element={<PrivateTemplateOverview />} />
|
|
76
|
+
<Route path="public" element={<PublicTemplateOverview />} />
|
|
77
|
+
</Route>
|
|
72
78
|
</Route>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
</Route>
|
|
80
|
+
<Route path="measurement">
|
|
81
|
+
<Route index element={<MeasurementCategoryOverview />} />
|
|
82
|
+
<Route path="overview" element={<MeasurementCategoryOverview />} />
|
|
83
|
+
<Route path="category/:categoryId" element={<MeasurementCategoryDetail />}></Route>
|
|
84
|
+
</Route>
|
|
85
|
+
<Route path="exercise">
|
|
86
|
+
<Route index element={<ExerciseOverview />} />
|
|
87
|
+
<Route path="overview" element={<ExerciseOverview />} />
|
|
88
|
+
<Route path=":exerciseId" element={<ExerciseDetailPage />}>
|
|
89
|
+
<Route path="view" element={<ExerciseDetailPage />}>
|
|
90
|
+
<Route path=":slug" element={<ExerciseDetailPage />} />
|
|
91
|
+
</Route>
|
|
76
92
|
</Route>
|
|
93
|
+
<Route path="contribute" element={<AddExercise />} />
|
|
77
94
|
</Route>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
<Route index element={<MeasurementCategoryOverview />} />
|
|
82
|
-
<Route path="overview" element={<MeasurementCategoryOverview />} />
|
|
83
|
-
<Route path="category/:categoryId" element={<MeasurementCategoryDetail />}>
|
|
95
|
+
<Route path="weight">
|
|
96
|
+
<Route path="overview" element={<WeightOverview />} />
|
|
97
|
+
<Route path="add" element={<AddWeight />} />
|
|
84
98
|
</Route>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
<Route path="nutrition">
|
|
100
|
+
<Route path="overview" element={<PlansOverview />} />
|
|
101
|
+
<Route path=":planId">
|
|
102
|
+
<Route path="view" element={<PlanDetail />} />
|
|
103
|
+
<Route path=":date" element={<NutritionDiaryOverview />} />
|
|
104
|
+
<Route path="diary" element={<NutritionDiaryOverview />} />
|
|
105
|
+
</Route>
|
|
106
|
+
<Route path="calculator">
|
|
107
|
+
<Route path="bmi" element={<BmiCalculator />} />
|
|
108
|
+
<Route path="calories" element={<CaloriesCalculator />} />
|
|
109
|
+
</Route>
|
|
110
|
+
<Route path="ingredient">
|
|
111
|
+
<Route path="overview" element={<Ingredients />} />
|
|
92
112
|
</Route>
|
|
93
113
|
</Route>
|
|
94
|
-
<Route path="
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<Route path="add" element={<AddWeight />} />
|
|
99
|
-
</Route>
|
|
100
|
-
<Route path="nutrition">
|
|
101
|
-
<Route path="overview" element={<PlansOverview />} />
|
|
102
|
-
<Route path=":planId">
|
|
103
|
-
<Route path="view" element={<PlanDetail />} />
|
|
104
|
-
<Route path=":date" element={<NutritionDiaryOverview />} />
|
|
105
|
-
<Route path="diary" element={<NutritionDiaryOverview />} />
|
|
114
|
+
<Route path="software">
|
|
115
|
+
<Route path="about-us" element={<About />} />
|
|
116
|
+
<Route path="api" element={<ApiPage />} />
|
|
117
|
+
<Route path="equipment" element={<Equipments />} />
|
|
106
118
|
</Route>
|
|
107
|
-
<Route path="
|
|
108
|
-
|
|
109
|
-
<Route path="
|
|
119
|
+
<Route path="login" element={<Login />} />
|
|
120
|
+
<Route path="user">
|
|
121
|
+
<Route path="preferences" element={<Preferences />} />
|
|
110
122
|
</Route>
|
|
111
|
-
<Route path="
|
|
112
|
-
<Route
|
|
123
|
+
<Route path="dashboard">
|
|
124
|
+
<Route index element={<ConfigurableDashboard />} />
|
|
125
|
+
<Route path="" element={<ConfigurableDashboard />} />
|
|
126
|
+
</Route>
|
|
127
|
+
<Route path="trophies">
|
|
128
|
+
<Route index element={<TrophiesDetail />} />
|
|
129
|
+
<Route path="" element={<TrophiesDetail />} />
|
|
113
130
|
</Route>
|
|
114
131
|
</Route>
|
|
115
|
-
<Route path="
|
|
116
|
-
<Route path="about-us" element={<About />} />
|
|
117
|
-
<Route path="api" element={<ApiPage />} />
|
|
118
|
-
<Route path="equipment" element={<Equipments />} />
|
|
119
|
-
</Route>
|
|
120
|
-
<Route path="login" element={<Login />} />
|
|
121
|
-
<Route path="user">
|
|
122
|
-
<Route path="preferences" element={<Preferences />} />
|
|
123
|
-
</Route>
|
|
124
|
-
</Route>
|
|
125
|
-
<Route path="/" element={<Dashboard />} />
|
|
132
|
+
<Route path="/" element={<ConfigurableDashboard />} />
|
|
126
133
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
{/* This route matches when no other route matches, so a 404 */}
|
|
135
|
+
<Route
|
|
136
|
+
path="*"
|
|
137
|
+
element={
|
|
138
|
+
<main style={{ padding: "1rem" }}>
|
|
139
|
+
<p>404, Page NOT FOUND</p>
|
|
140
|
+
</main>
|
|
141
|
+
}
|
|
142
|
+
/>
|
|
143
|
+
</Routes>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
@@ -14,7 +14,6 @@ export const EXERCISE_TRANSLATION_PATH = 'exercise-translation';
|
|
|
14
14
|
*/
|
|
15
15
|
export const getExerciseTranslations = async (id: number): Promise<Translation[]> => {
|
|
16
16
|
const url = makeUrl(EXERCISE_PATH, { query: { exercise: id } });
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
17
|
const { data } = await axios.get<ResponseType<Translation>>(url, {
|
|
19
18
|
headers: makeHeader(),
|
|
20
19
|
});
|
|
@@ -26,7 +25,7 @@ export const getExerciseTranslations = async (id: number): Promise<Translation[]
|
|
|
26
25
|
/*
|
|
27
26
|
* Search for exercises by name using the exerciseinfo endpoint
|
|
28
27
|
*/
|
|
29
|
-
export const searchExerciseTranslations = async (name: string,languageCode: string = ENGLISH_LANGUAGE_CODE,searchEnglish: boolean = true): Promise<Exercise[]> => {
|
|
28
|
+
export const searchExerciseTranslations = async (name: string, languageCode: string = ENGLISH_LANGUAGE_CODE, searchEnglish: boolean = true): Promise<Exercise[]> => {
|
|
30
29
|
const languages = [languageCode];
|
|
31
30
|
if (languageCode !== LANGUAGE_SHORT_ENGLISH && searchEnglish) {
|
|
32
31
|
languages.push(LANGUAGE_SHORT_ENGLISH);
|
|
@@ -34,19 +33,19 @@ export const searchExerciseTranslations = async (name: string,languageCode: stri
|
|
|
34
33
|
|
|
35
34
|
const url = makeUrl('exerciseinfo', {
|
|
36
35
|
query: {
|
|
37
|
-
name__search: name,
|
|
38
|
-
language__code: languages.join(','),
|
|
36
|
+
"name__search": name,
|
|
37
|
+
"language__code": languages.join(','),
|
|
39
38
|
limit: 50,
|
|
40
39
|
}
|
|
41
40
|
});
|
|
42
41
|
|
|
43
42
|
try {
|
|
44
43
|
const { data } = await axios.get<ResponseType<Exercise>>(url);
|
|
45
|
-
|
|
44
|
+
|
|
46
45
|
if (!data || !data.results || !Array.isArray(data.results)) {
|
|
47
46
|
return [];
|
|
48
47
|
}
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
const adapter = new ExerciseAdapter();
|
|
51
50
|
return data.results.map((item: unknown) => adapter.fromJson(item));
|
|
52
51
|
} catch {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import { MeasurementCategory
|
|
3
|
-
import { MeasurementEntry
|
|
2
|
+
import { MeasurementCategory } from "components/Measurements/models/Category";
|
|
3
|
+
import { MeasurementEntry } from "components/Measurements/models/Entry";
|
|
4
4
|
import { ApiMeasurementCategoryType } from 'types';
|
|
5
5
|
import { API_MAX_PAGE_SIZE } from "utils/consts";
|
|
6
6
|
import { dateToYYYYMMDD } from "utils/date";
|
|
@@ -18,8 +18,6 @@ export type MeasurementQueryOptions = {
|
|
|
18
18
|
export const getMeasurementCategories = async (options?: MeasurementQueryOptions): Promise<MeasurementCategory[]> => {
|
|
19
19
|
const { filtersetQueryCategories = {}, filtersetQueryEntries = {} } = options || {};
|
|
20
20
|
|
|
21
|
-
const adapter = new MeasurementCategoryAdapter();
|
|
22
|
-
const entryAdapter = new MeasurementEntryAdapter();
|
|
23
21
|
const categories: MeasurementCategory[] = [];
|
|
24
22
|
const categoryUrl = makeUrl(API_MEASUREMENTS_CATEGORY_PATH, {
|
|
25
23
|
query: {
|
|
@@ -30,7 +28,7 @@ export const getMeasurementCategories = async (options?: MeasurementQueryOptions
|
|
|
30
28
|
|
|
31
29
|
for await (const page of fetchPaginated(categoryUrl, makeHeader())) {
|
|
32
30
|
for (const catData of page) {
|
|
33
|
-
categories.push(
|
|
31
|
+
categories.push(MeasurementCategory.fromJson(catData));
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
34
|
|
|
@@ -48,7 +46,7 @@ export const getMeasurementCategories = async (options?: MeasurementQueryOptions
|
|
|
48
46
|
// Collect all pages of entries
|
|
49
47
|
for await (const page of fetchPaginated(url, makeHeader())) {
|
|
50
48
|
for (const entries of page) {
|
|
51
|
-
out.push(
|
|
49
|
+
out.push(MeasurementEntry.fromJson(entries));
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
52
|
return out;
|
|
@@ -73,15 +71,14 @@ export const getMeasurementCategory = async (id: number): Promise<MeasurementCat
|
|
|
73
71
|
{ headers: makeHeader() },
|
|
74
72
|
);
|
|
75
73
|
|
|
76
|
-
const category =
|
|
77
|
-
const adapter = new MeasurementEntryAdapter();
|
|
74
|
+
const category = MeasurementCategory.fromJson(receivedCategories);
|
|
78
75
|
const measurements: MeasurementEntry[] = [];
|
|
79
76
|
const url = makeUrl(API_MEASUREMENTS_ENTRY_PATH, { query: { category: category.id } });
|
|
80
77
|
|
|
81
78
|
// Collect all pages of entries
|
|
82
79
|
for await (const page of fetchPaginated(url, makeHeader())) {
|
|
83
80
|
for (const entries of page) {
|
|
84
|
-
measurements.push(
|
|
81
|
+
measurements.push(MeasurementEntry.fromJson(entries));
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
|
|
@@ -105,8 +102,7 @@ export const addMeasurementCategory = async (data: AddMeasurementCategoryParams)
|
|
|
105
102
|
{ headers: makeHeader() }
|
|
106
103
|
);
|
|
107
104
|
|
|
108
|
-
|
|
109
|
-
return adapter.fromJson(response.data);
|
|
105
|
+
return MeasurementCategory.fromJson(response.data);
|
|
110
106
|
};
|
|
111
107
|
|
|
112
108
|
export interface editMeasurementCategoryParams {
|
|
@@ -125,8 +121,7 @@ export const editMeasurementCategory = async (data: editMeasurementCategoryParam
|
|
|
125
121
|
{ headers: makeHeader() }
|
|
126
122
|
);
|
|
127
123
|
|
|
128
|
-
|
|
129
|
-
return adapter.fromJson(response.data);
|
|
124
|
+
return MeasurementCategory.fromJson(response.data);
|
|
130
125
|
};
|
|
131
126
|
|
|
132
127
|
export const deleteMeasurementCategory = async (id: number): Promise<void> => {
|
|
@@ -157,8 +152,7 @@ export const editMeasurementEntry = async (data: editMeasurementParams): Promise
|
|
|
157
152
|
{ headers: makeHeader() }
|
|
158
153
|
);
|
|
159
154
|
|
|
160
|
-
|
|
161
|
-
return adapter.fromJson(response.data);
|
|
155
|
+
return MeasurementEntry.fromJson(response.data);
|
|
162
156
|
};
|
|
163
157
|
|
|
164
158
|
export interface AddMeasurementParams {
|
|
@@ -181,6 +175,5 @@ export const addMeasurementEntry = async (data: AddMeasurementParams): Promise<M
|
|
|
181
175
|
{ headers: makeHeader() }
|
|
182
176
|
);
|
|
183
177
|
|
|
184
|
-
|
|
185
|
-
return adapter.fromJson(response.data);
|
|
178
|
+
return MeasurementEntry.fromJson(response.data);
|
|
186
179
|
};
|
|
@@ -11,17 +11,17 @@ describe("Exercise video service API tests", () => {
|
|
|
11
11
|
id: 1,
|
|
12
12
|
uuid: "b1c934fa-c4f8-4d84-8cb4-7802be0d284c",
|
|
13
13
|
exercise: 258,
|
|
14
|
-
exercise_uuid: "6260e3aa-e46b-4b4b-8ada-58bfd0922d3a",
|
|
14
|
+
"exercise_uuid": "6260e3aa-e46b-4b4b-8ada-58bfd0922d3a",
|
|
15
15
|
video: "http://localhost:8000/media/exercise-video/258/b1c934fa-c4f8-4d84-8cb4-7802be0d284c.mp4",
|
|
16
|
-
is_main: false,
|
|
16
|
+
"is_main": false,
|
|
17
17
|
size: 0,
|
|
18
18
|
duration: "0.00",
|
|
19
19
|
width: 0,
|
|
20
20
|
height: 0,
|
|
21
21
|
codec: "",
|
|
22
|
-
codec_long: "",
|
|
22
|
+
"codec_long": "",
|
|
23
23
|
license: 2,
|
|
24
|
-
license_author: null,
|
|
24
|
+
"license_author": null,
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const video = new ExerciseVideo(
|