diff --git a/src/api/exercises.ts b/src/api/exercises.ts new file mode 100644 index 0000000..dc84adc --- /dev/null +++ b/src/api/exercises.ts @@ -0,0 +1,23 @@ +import { apiClient } from '@/api/client' +import { extractErrorMessage } from '@/api/http' +import type { PaginatedExercises } from '@/types/exercise' + +export interface GetExercisesParams { + page?: number + count?: number +} + +export async function getExercisesApi( + params: GetExercisesParams = {}, +): Promise { + const query = new URLSearchParams() + if (params.page !== undefined) query.set('page', String(params.page)) + if (params.count !== undefined) query.set('count', String(params.count)) + const queryString = query.toString() + + const response = await apiClient.get(`/exercises${queryString ? `?${queryString}` : ''}`) + if (!response.ok) { + throw new Error(await extractErrorMessage(response, 'Failed to load exercises')) + } + return response.json() +} diff --git a/src/components/BottomNav.vue b/src/components/BottomNav.vue index 16049a1..371e387 100644 --- a/src/components/BottomNav.vue +++ b/src/components/BottomNav.vue @@ -19,6 +19,24 @@ const listsStore = useListsStore() listsStore.pendingCount }} + + + + + + + + + Exercises + diff --git a/src/components/ExerciseCard.vue b/src/components/ExerciseCard.vue new file mode 100644 index 0000000..66a6106 --- /dev/null +++ b/src/components/ExerciseCard.vue @@ -0,0 +1,112 @@ + + +
+

{{ exercise.name }}

+

{{ exercise.notes }}

+
+ {{ loadLabel }} + {{ metricLabel }} + {{ + equipment + }} +
+
+ + + + + diff --git a/src/router/index.ts b/src/router/index.ts index dd40680..b9c7874 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -18,6 +18,12 @@ const router = createRouter({ meta: { requiresAuth: true }, props: true, }, + { + path: '/exercises', + name: 'exercises', + component: () => import('../views/ExercisesView.vue'), + meta: { requiresAuth: true }, + }, { path: '/login', name: 'login', diff --git a/src/types/exercise.ts b/src/types/exercise.ts new file mode 100644 index 0000000..cbc7aa8 --- /dev/null +++ b/src/types/exercise.ts @@ -0,0 +1,62 @@ +export enum Equipment { + Unknown = 0, + Floor = 1, + Rings = 2, + PullUpBar = 3, + ParallelBars = 4, + LowBar = 5, + Parallettes = 6, + ResistanceBand = 7, +} + +export enum Load { + Unknown = 0, + Bodyweight = 1, + External = 2, +} + +export enum Metric { + Unknown = 0, + Reps = 1, + Seconds = 2, +} + +export const EQUIPMENT_LABELS: Record = { + [Equipment.Unknown]: 'Unknown', + [Equipment.Floor]: 'Floor', + [Equipment.Rings]: 'Rings', + [Equipment.PullUpBar]: 'Pull-up bar', + [Equipment.ParallelBars]: 'Parallel bars', + [Equipment.LowBar]: 'Low bar', + [Equipment.Parallettes]: 'Parallettes', + [Equipment.ResistanceBand]: 'Resistance band', +} + +export const LOAD_LABELS: Record = { + [Load.Unknown]: 'Unknown', + [Load.Bodyweight]: 'Bodyweight', + [Load.External]: 'External', +} + +export const METRIC_LABELS: Record = { + [Metric.Unknown]: 'Unknown', + [Metric.Reps]: 'Reps', + [Metric.Seconds]: 'Seconds', +} + +export interface Exercise { + id: string + name: string + notes?: string + equipment?: Equipment[] + load?: Load + metric?: Metric + tags?: string[] + modified_at?: string +} + +export interface PaginatedExercises { + data: Exercise[] + total: number + count: number +} diff --git a/src/views/ExercisesView.vue b/src/views/ExercisesView.vue new file mode 100644 index 0000000..05422f7 --- /dev/null +++ b/src/views/ExercisesView.vue @@ -0,0 +1,157 @@ + + + + +