all repos — go-lift @ 092e7440440b8459d82fb90c05c005f9f38e3c51

Lightweight workout tracker prototype..

ui/src/services/api.ts (view raw)

  1import type { 
  2  Exercise, 
  3  Routine, 
  4  RecordRoutine, 
  5  User,
  6  Equipment,
  7  MuscleGroup,
  8  Set,
  9  SuperSet,
 10  RecordExercise, 
 11  WorkoutStats
 12} from '../types/models';
 13
 14// Base API URL - should be configurable via environment variables in a real app
 15const API_BASE_URL = '/api';
 16
 17// Generic fetch with error handling
 18async function fetchApi<T>(
 19  endpoint: string, 
 20  options: RequestInit = {}
 21): Promise<T> {
 22  const url = `${API_BASE_URL}${endpoint}`;
 23  
 24  const response = await fetch(url, {
 25    headers: {
 26      'Content-Type': 'application/json',
 27      ...options.headers,
 28    },
 29    ...options,
 30  });
 31
 32  if (!response.ok) {
 33    const error = await response.text();
 34    throw new Error(error || `API request failed with status ${response.status}`);
 35  }
 36
 37  return response.json();
 38}
 39
 40// Equipment API services
 41export const EquipmentService = {
 42  getAll: () => fetchApi<Equipment[]>('/equipment'),
 43  
 44  getById: (id: number) => fetchApi<Equipment>(`/equipment/${id}`),
 45  
 46  create: (equipment: Equipment) => fetchApi<Equipment>('/equipment', {
 47    method: 'POST',
 48    body: JSON.stringify(equipment),
 49  }),
 50  
 51  update: (id: number, equipment: Equipment) => fetchApi<Equipment>(`/equipment/${id}`, {
 52    method: 'PUT',
 53    body: JSON.stringify(equipment),
 54  }),
 55  
 56  delete: (id: number) => fetchApi<void>(`/equipment/${id}`, {
 57    method: 'DELETE',
 58  }),
 59};
 60
 61// MuscleGroup API services
 62export const MuscleGroupService = {
 63  getAll: () => fetchApi<MuscleGroup[]>('/musclegroups'),
 64  
 65  getById: (id: number) => fetchApi<MuscleGroup>(`/musclegroups/${id}`),
 66  
 67  create: (muscleGroup: MuscleGroup) => fetchApi<MuscleGroup>('/musclegroups', {
 68    method: 'POST',
 69    body: JSON.stringify(muscleGroup),
 70  }),
 71  
 72  update: (id: number, muscleGroup: MuscleGroup) => fetchApi<MuscleGroup>(`/musclegroups/${id}`, {
 73    method: 'PUT',
 74    body: JSON.stringify(muscleGroup),
 75  }),
 76  
 77  delete: (id: number) => fetchApi<void>(`/musclegroups/${id}`, {
 78    method: 'DELETE',
 79  }),
 80};
 81
 82// Exercise API services
 83export const ExerciseService = {
 84  getAll: () => fetchApi<Exercise[]>('/exercises'),
 85  
 86  getById: (id: number) => fetchApi<Exercise>(`/exercises/${id}`),
 87  
 88  create: (exercise: Exercise) => fetchApi<Exercise>('/exercises', {
 89    method: 'POST',
 90    body: JSON.stringify(exercise),
 91  }),
 92  
 93  update: (id: number, exercise: Exercise) => fetchApi<Exercise>(`/exercises/${id}`, {
 94    method: 'PUT',
 95    body: JSON.stringify(exercise),
 96  }),
 97  
 98  delete: (id: number) => fetchApi<void>(`/exercises/${id}`, {
 99    method: 'DELETE',
100  }),
101};
102
103// Set API services
104export const SetService = {
105  getAll: (exerciseId: number) => fetchApi<Set[]>(`/exercises/${exerciseId}/sets`),
106  
107  getById: (id: number) => fetchApi<Set>(`/sets/${id}`),
108  
109  create: (set: Set) => fetchApi<Set>('/sets', {
110    method: 'POST',
111    body: JSON.stringify(set),
112  }),
113  
114  update: (id: number, set: Set) => fetchApi<Set>(`/sets/${id}`, {
115    method: 'PUT',
116    body: JSON.stringify(set),
117  }),
118  
119  delete: (id: number) => fetchApi<void>(`/sets/${id}`, {
120    method: 'DELETE',
121  }),
122};
123
124// SuperSet API services
125export const SuperSetService = {
126  getAll: () => fetchApi<SuperSet[]>('/supersets'),
127  
128  getById: (id: number) => fetchApi<SuperSet>(`/supersets/${id}`),
129  
130  create: (superSet: SuperSet) => fetchApi<SuperSet>('/supersets', {
131    method: 'POST',
132    body: JSON.stringify(superSet),
133  }),
134  
135  update: (id: number, superSet: SuperSet) => fetchApi<SuperSet>(`/supersets/${id}`, {
136    method: 'PUT',
137    body: JSON.stringify(superSet),
138  }),
139  
140  delete: (id: number) => fetchApi<void>(`/supersets/${id}`, {
141    method: 'DELETE',
142  }),
143};
144
145// Routine API services
146export const RoutineService = {
147  getAll: () => fetchApi<Routine[]>('/routines'),
148  
149  getById: (id: number) => fetchApi<Routine>(`/routines/${id}`),
150  
151  create: (routine: Routine) => fetchApi<Routine>('/routines', {
152    method: 'POST',
153    body: JSON.stringify(routine),
154  }),
155  
156  update: (id: number, routine: Routine) => fetchApi<Routine>(`/routines/${id}`, {
157    method: 'PUT',
158    body: JSON.stringify(routine),
159  }),
160  
161  delete: (id: number) => fetchApi<void>(`/routines/${id}`, {
162    method: 'DELETE',
163  }),
164};
165
166// RecordRoutine (Workout) API services
167export const WorkoutService = {
168  getAll: () => fetchApi<RecordRoutine[]>('/recordroutines'),
169  
170  getById: (id: number) => fetchApi<RecordRoutine>(`/recordroutines/${id}`),
171  
172  create: (workout: RecordRoutine) => fetchApi<RecordRoutine>('/recordroutines', {
173    method: 'POST',
174    body: JSON.stringify(workout),
175  }),
176  
177  update: (id: number, workout: RecordRoutine) => fetchApi<RecordRoutine>(`/recordroutines/${id}`, {
178    method: 'PUT',
179    body: JSON.stringify(workout),
180  }),
181  
182  delete: (id: number) => fetchApi<void>(`/recordroutines/${id}`, {
183    method: 'DELETE',
184  }),
185  
186  // Additional method to get workout statistics for the home page
187  getStats: () => fetchApi<WorkoutStats>('/stats'),
188};
189
190// RecordExercise API services
191export const RecordExerciseService = {
192  getAll: (recordRoutineId: number) => fetchApi<RecordExercise[]>(`/recordroutines/${recordRoutineId}/exercises`),
193  
194  getById: (id: number) => fetchApi<RecordExercise>(`/recordexercises/${id}`),
195  
196  create: (recordExercise: RecordExercise) => fetchApi<RecordExercise>('/recordexercises', {
197    method: 'POST',
198    body: JSON.stringify(recordExercise),
199  }),
200  
201  update: (id: number, recordExercise: RecordExercise) => fetchApi<RecordExercise>(`/recordexercises/${id}`, {
202    method: 'PUT',
203    body: JSON.stringify(recordExercise),
204  }),
205  
206  delete: (id: number) => fetchApi<void>(`/recordexercises/${id}`, {
207    method: 'DELETE',
208  }),
209};
210
211// User profile service
212export const ProfileService = {
213  get: async () => {
214    const user = await fetchApi<User>('/users/1');
215    user.birthDate = new Date(user.birthDate).toISOString();
216    return user;
217  },
218  
219  update: async (profile: User) => {
220    profile.birthDate = new Date(profile.birthDate).toISOString();
221    profile.isFemale = profile.isFemale === 'true';
222    profile.weight = +profile.weight;
223    profile.height = +profile.height;
224
225    return await fetchApi<User>('/users/1', {
226    method: 'PUT',
227    body: JSON.stringify(profile),
228  })},
229};