diff --git a/src/services/api.js b/src/services/api.js index 693490b..934c672 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -62,26 +62,26 @@ api.interceptors.response.use( export const calendarApi = { async getWorkouts() { - const { data } = await api.get('/protected/workouts') + const { data } = await api.get('/api/protected/workouts') return data }, async getWorkoutsByMonth(year, month) { - const { data } = await api.get('/protected/workouts/month', { + const { data } = await api.get('/api/protected/workouts/month', { params: { year, month } }) return data }, async getWorkoutsByWeek(year, week) { - const { data } = await api.get('/protected/workouts/week', { + const { data } = await api.get('/api/protected/workouts/week', { params: { year, week } }) return data }, async getWorkoutsByRange(startDate, endDate) { - const { data } = await api.get('/protected/workouts/range', { + const { data } = await api.get('/api/protected/workouts/range', { params: { start: startDate, end: endDate @@ -91,29 +91,29 @@ export const calendarApi = { }, async createWorkout(workout) { - const { data } = await api.post('/protected/workouts', workout) + const { data } = await api.post('/api/protected/workouts', workout) return data }, async updateWorkout(workoutId, workout) { - const { data } = await api.put(`/protected/workouts?id=${workoutId}`, workout) + const { data } = await api.put(`/api/protected/workouts?id=${workoutId}`, workout) return data }, async rescheduleWorkout(workoutId, newDate) { - const { data } = await api.put(`/protected/workouts/reschedule?id=${workoutId}`, { + const { data } = await api.put(`/api/protected/workouts/reschedule?id=${workoutId}`, { scheduled_date: newDate }) return data }, async deleteWorkout(workoutId) { - const { data } = await api.delete(`/protected/workouts?id=${workoutId}`) + const { data } = await api.delete(`/api/protected/workouts?id=${workoutId}`) return data }, async scheduleFromTemplate(templateId, templateName, templateType, duration, scheduledDate, workoutData = null) { - const { data } = await api.post('/protected/workouts/schedule-template', { + const { data } = await api.post('/api/protected/workouts/schedule-template', { template_id: templateId, template_name: templateName, template_type: templateType, @@ -130,7 +130,7 @@ export const calendarApi = { if (scheduledDate) { formData.append('scheduled_date', scheduledDate) } - const { data } = await api.post('/protected/workouts/upload', formData, { + const { data } = await api.post('/api/protected/workouts/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } @@ -139,7 +139,7 @@ export const calendarApi = { }, async exportICS(startDate, endDate) { - const response = await api.get('/protected/workouts/export/ics', { + const response = await api.get('/api/protected/workouts/export/ics', { params: { start: startDate, end: endDate }, responseType: 'blob' }) @@ -147,50 +147,77 @@ export const calendarApi = { }, async getWorkoutTypes() { - const { data } = await api.get('/protected/workout-types') + const { data } = await api.get('/api/protected/workout-types') return data }, async completeWorkout(workoutId, completionData) { - const { data } = await api.post(`/protected/workouts/complete?id=${workoutId}`, completionData) + const { data } = await api.post(`/api/protected/workouts/complete?id=${workoutId}`, completionData) return data + }, + + async importActivity(file, opts = {}) { + const formData = new FormData() + formData.append('file', file) + if (opts.title) formData.append('title', opts.title) + if (opts.workout_id) formData.append('workout_id', String(opts.workout_id)) + if (opts.equipment_id) formData.append('equipment_id', String(opts.equipment_id)) + if (opts.notes) formData.append('notes', opts.notes) + const { data } = await api.post('/api/protected/workouts/import', formData, { + headers: { 'Content-Type': 'multipart/form-data' } + }) + return data + }, + + async exportFIT(workoutId) { + const response = await api.get(`/api/protected/workouts/export/fit?id=${workoutId}`, { + responseType: 'blob' + }) + return response.data + }, + + async exportZWO(workoutId) { + const response = await api.get(`/api/protected/workouts/export/zwo?id=${workoutId}`, { + responseType: 'blob' + }) + return response.data } } export const recurringApi = { async create(schedule) { - const { data } = await api.post('/protected/workouts/recurring', schedule) + const { data } = await api.post('/api/protected/workouts/recurring', schedule) return data }, async list() { - const { data } = await api.get('/protected/workouts/recurring') + const { data } = await api.get('/api/protected/workouts/recurring') return data }, async delete(scheduleId, deleteFuture = true) { - const { data } = await api.delete(`/protected/workouts/recurring?id=${scheduleId}&delete_future=${deleteFuture}`) + const { data } = await api.delete(`/api/protected/workouts/recurring?id=${scheduleId}&delete_future=${deleteFuture}`) return data } } export const sessionApi = { async getSessions() { - const { data } = await api.get('/protected/sessions', { + const { data } = await api.get('/api/protected/sessions', { headers: { 'X-Refresh-Token': localStorage.getItem('refresh_token') } }) return data.sessions || [] }, async revokeSession(sessionId) { - const { data } = await api.delete(`/protected/sessions/${sessionId}`, { + const { data } = await api.delete(`/api/protected/sessions/${sessionId}`, { headers: { 'X-Refresh-Token': localStorage.getItem('refresh_token') } }) return data }, async revokeAllOtherSessions() { - const { data } = await api.delete('/protected/sessions/all', { + const { data } = await api.delete('/api/protected/sessions/all', { headers: { 'X-Refresh-Token': localStorage.getItem('refresh_token') } }) return data @@ -199,32 +226,32 @@ export const sessionApi = { export const onboardingApi = { async getStatus() { - const { data } = await api.get('/protected/onboarding/status') + const { data } = await api.get('/api/protected/onboarding/status') return data }, async saveProfile(profileData) { - const { data } = await api.post('/protected/onboarding/profile', profileData) + const { data } = await api.post('/api/protected/onboarding/profile', profileData) return data }, async saveMetrics(metricsData) { - const { data } = await api.post('/protected/onboarding/metrics', metricsData) + const { data } = await api.post('/api/protected/onboarding/metrics', metricsData) return data }, async submitFTPTest(testData) { - const { data } = await api.post('/protected/onboarding/ftp-test', testData) + const { data } = await api.post('/api/protected/onboarding/ftp-test', testData) return data }, async getFTPHistory() { - const { data } = await api.get('/protected/onboarding/ftp-history') + const { data } = await api.get('/api/protected/onboarding/ftp-history') return data }, async calculateHRZones(maxHR, restingHR) { - const { data } = await api.post('/protected/onboarding/hr-zones', { + const { data } = await api.post('/api/protected/onboarding/hr-zones', { max_hr: maxHR, resting_hr: restingHR }) @@ -232,7 +259,7 @@ export const onboardingApi = { }, async estimateFTP(fitnessLevel, weight) { - const { data } = await api.post('/protected/onboarding/estimate-ftp', { + const { data } = await api.post('/api/protected/onboarding/estimate-ftp', { fitness_level: fitnessLevel, weight: weight }) @@ -240,148 +267,158 @@ export const onboardingApi = { }, async estimateMaxHR(age) { - const { data } = await api.post('/protected/onboarding/estimate-max-hr', { age }) + const { data } = await api.post('/api/protected/onboarding/estimate-max-hr', { age }) return data }, async completeEquipmentStep() { - const { data } = await api.post('/protected/onboarding/equipment') + const { data } = await api.post('/api/protected/onboarding/equipment') return data }, async savePreferences(preferences) { - const { data } = await api.post('/protected/onboarding/preferences', preferences) + const { data } = await api.post('/api/protected/onboarding/preferences', preferences) return data }, async complete() { - const { data } = await api.post('/protected/onboarding/complete') + const { data } = await api.post('/api/protected/onboarding/complete') return data }, async skip() { - const { data } = await api.post('/protected/onboarding/skip') + const { data } = await api.post('/api/protected/onboarding/skip') return data } } export const equipmentApi = { async create(equipment) { - const { data } = await api.post('/protected/equipment', equipment) + const { data } = await api.post('/api/protected/equipment', equipment) return data }, async list() { - const { data } = await api.get('/protected/equipment') + const { data } = await api.get('/api/protected/equipment') return data }, async update(equipmentId, equipment) { - const { data } = await api.put(`/protected/equipment?id=${equipmentId}`, equipment) + const { data } = await api.put(`/api/protected/equipment?id=${equipmentId}`, equipment) return data }, async delete(equipmentId) { - const { data } = await api.delete(`/protected/equipment?id=${equipmentId}`) + const { data } = await api.delete(`/api/protected/equipment?id=${equipmentId}`) return data }, async getTrainingZones() { - const { data } = await api.get('/protected/zones') + const { data } = await api.get('/api/protected/zones') + return data + }, + + async recordService(equipmentId) { + const { data } = await api.post(`/api/protected/equipment/service?id=${equipmentId}`) + return data + }, + + async getServiceStatus(equipmentId) { + const { data } = await api.get(`/api/protected/equipment/service-status?id=${equipmentId}`) return data } } export const teamsApi = { async create(team) { - const { data } = await api.post('/protected/teams', team) + const { data } = await api.post('/api/protected/teams', team) return data }, async list() { - const { data } = await api.get('/protected/teams') + const { data } = await api.get('/api/protected/teams') return data.teams || [] }, async get(teamId) { - const { data } = await api.get(`/protected/teams/${teamId}`) + const { data } = await api.get(`/api/protected/teams/${teamId}`) return data }, async update(teamId, team) { - const { data } = await api.put(`/protected/teams/${teamId}`, team) + const { data } = await api.put(`/api/protected/teams/${teamId}`, team) return data }, async delete(teamId) { - const { data } = await api.delete(`/protected/teams/${teamId}`) + const { data } = await api.delete(`/api/protected/teams/${teamId}`) return data }, async getMembers(teamId) { - const { data } = await api.get(`/protected/teams/${teamId}/members`) + const { data } = await api.get(`/api/protected/teams/${teamId}/members`) return data.members || [] }, async updateMemberRole(teamId, userId, role) { - const { data } = await api.put(`/protected/teams/${teamId}/members/${userId}/role`, { role }) + const { data } = await api.put(`/api/protected/teams/${teamId}/members/${userId}/role`, { role }) return data }, async removeMember(teamId, userId) { - const { data } = await api.delete(`/protected/teams/${teamId}/members/${userId}`) + const { data } = await api.delete(`/api/protected/teams/${teamId}/members/${userId}`) return data }, async leave(teamId) { - const { data } = await api.delete(`/protected/teams/${teamId}/leave`) + const { data } = await api.delete(`/api/protected/teams/${teamId}/leave`) return data }, async sendInvite(teamId, email, role) { - const { data } = await api.post(`/protected/teams/${teamId}/invite`, { email, role }) + const { data } = await api.post(`/api/protected/teams/${teamId}/invite`, { email, role }) return data }, async getTeamInvites(teamId) { - const { data } = await api.get(`/protected/teams/${teamId}/invites`) + const { data } = await api.get(`/api/protected/teams/${teamId}/invites`) return data.invites || [] }, async cancelInvite(teamId, inviteId) { - const { data } = await api.delete(`/protected/teams/${teamId}/invites/${inviteId}`) + const { data } = await api.delete(`/api/protected/teams/${teamId}/invites/${inviteId}`) return data }, async getMyInvites() { - const { data } = await api.get('/protected/invites') + const { data } = await api.get('/api/protected/invites') return data.invites || [] }, async acceptInvite(token) { - const { data } = await api.post('/protected/invites/accept', { token }) + const { data } = await api.post('/api/protected/invites/accept', { token }) return data }, async declineInvite(token) { - const { data } = await api.post('/protected/invites/decline', { token }) + const { data } = await api.post('/api/protected/invites/decline', { token }) return data } } export const coachingApi = { async getAthletes() { - const { data } = await api.get('/protected/coaching/athletes') + const { data } = await api.get('/api/protected/coaching/athletes') return data.athletes || [] }, async getCoaches() { - const { data } = await api.get('/protected/coaching/coaches') + const { data } = await api.get('/api/protected/coaching/coaches') return data.coaches || [] }, async requestCoaching(coachId, note = null) { - const { data } = await api.post('/protected/coaching/request', { + const { data } = await api.post('/api/protected/coaching/request', { coach_id: coachId, note: note }) @@ -389,41 +426,41 @@ export const coachingApi = { }, async acceptRequest(relationId) { - const { data } = await api.post('/protected/coaching/accept', { + const { data } = await api.post('/api/protected/coaching/accept', { relation_id: relationId }) return data }, async endRelationship(athleteId) { - const { data } = await api.delete(`/protected/coaching/${athleteId}`) + const { data } = await api.delete(`/api/protected/coaching/${athleteId}`) return data } } export const oauthApi = { async getAccounts() { - const { data } = await api.get('/protected/oauth/accounts') + const { data } = await api.get('/api/protected/oauth/accounts') return data.accounts || [] }, async linkStrava(code) { - const { data } = await api.post('/protected/oauth/link/strava', { code }) + const { data } = await api.post('/api/protected/oauth/link/strava', { code }) return data }, async linkGoogle() { - const { data } = await api.post('/protected/oauth/link/google') + const { data } = await api.post('/api/protected/oauth/link/google') return data }, async unlink(provider) { - const { data } = await api.delete(`/protected/oauth/unlink/${provider}`) + const { data } = await api.delete(`/api/protected/oauth/unlink/${provider}`) return data }, async syncStrava() { - const { data } = await api.post('/protected/oauth/strava/sync') + const { data } = await api.post('/api/protected/oauth/strava/sync') return data }, @@ -431,4 +468,87 @@ export const oauthApi = { getStravaAuthUrl: () => `${API_BASE_URL}/api/oauth/strava` } +export const statsApi = { + async getSummary() { + const { data } = await api.get('/api/protected/stats/summary') + return data + }, + + async getWeeklyStats(weeks = 12) { + const { data } = await api.get('/api/protected/stats/weekly', { params: { weeks } }) + return data + }, + + async getMonthlyStats(months = 12) { + const { data } = await api.get('/api/protected/stats/monthly', { params: { months } }) + return data + }, + + async getPersonalBests() { + const { data } = await api.get('/api/protected/stats/personal-bests') + return data + } +} + +export const templatesApi = { + async list(category = '') { + const params = {} + if (category) params.category = category + const { data } = await api.get('/api/protected/workout-templates', { params }) + return data + }, + + async getDetail(id) { + const { data } = await api.get(`/api/protected/workout-templates/detail?id=${id}`) + return data + }, + + async createFromTemplate(payload) { + const { data } = await api.post('/api/protected/workouts/from-template', payload) + return data + } +} + +export const integrationsApi = { + async garminAuth() { + const { data } = await api.get('/api/protected/garmin/auth') + return data + }, + + async garminStatus() { + const { data } = await api.get('/api/protected/garmin/status') + return data + }, + + async garminDisconnect() { + const { data } = await api.delete('/api/protected/garmin/disconnect') + return data + }, + + async pushToGarmin(workoutId) { + const { data } = await api.post(`/api/protected/workouts/push/garmin?id=${workoutId}`) + return data + }, + + async wahooAuth() { + const { data } = await api.get('/api/protected/wahoo/auth') + return data + }, + + async wahooStatus() { + const { data } = await api.get('/api/protected/wahoo/status') + return data + }, + + async wahooDisconnect() { + const { data } = await api.delete('/api/protected/wahoo/disconnect') + return data + }, + + async pushToWahoo(workoutId) { + const { data } = await api.post(`/api/protected/workouts/push/wahoo?id=${workoutId}`) + return data + } +} + export default api diff --git a/src/services/workoutLibraryApi.js b/src/services/workoutLibraryApi.js index cae3989..54fb280 100644 --- a/src/services/workoutLibraryApi.js +++ b/src/services/workoutLibraryApi.js @@ -3,19 +3,19 @@ import api from './api' export const workoutLibraryApi = { // Get workout types, categories, and difficulties async getTypes() { - const { data } = await api.get('/protected/library/types') + const { data } = await api.get('/api/protected/library/types') return data }, // Get system-provided workouts async getSystemWorkouts() { - const { data } = await api.get('/protected/library/system') + const { data } = await api.get('/api/protected/library/system') return data }, // Browse public workouts (paginated) async browseWorkouts(page = 1, pageSize = 20) { - const { data } = await api.get('/protected/library/browse', { + const { data } = await api.get('/api/protected/library/browse', { params: { page, page_size: pageSize } }) return data @@ -23,7 +23,7 @@ export const workoutLibraryApi = { // Search/filter workouts async searchWorkouts(params = {}) { - const { data } = await api.get('/protected/library/search', { + const { data } = await api.get('/api/protected/library/search', { params: { q: params.search || undefined, type: params.type || undefined, @@ -38,73 +38,73 @@ export const workoutLibraryApi = { // Get workouts by type async getWorkoutsByType(type) { - const { data } = await api.get(`/protected/library/type/${type}`) + const { data } = await api.get(`/api/protected/library/type/${type}`) return data }, // Get workouts by category async getWorkoutsByCategory(category) { - const { data } = await api.get(`/protected/library/category/${category}`) + const { data } = await api.get(`/api/protected/library/category/${category}`) return data }, // Get single workout details async getWorkout(workoutId) { - const { data } = await api.get(`/protected/library/${workoutId}`) + const { data } = await api.get(`/api/protected/library/${workoutId}`) return data }, // Get current user's custom workouts async getUserWorkouts() { - const { data } = await api.get('/protected/library/mine') + const { data } = await api.get('/api/protected/library/mine') return data }, // Get user's favorited workouts async getFavorites() { - const { data } = await api.get('/protected/library/favorites') + const { data } = await api.get('/api/protected/library/favorites') return data }, // Create custom workout async createWorkout(workout) { - const { data } = await api.post('/protected/library', workout) + const { data } = await api.post('/api/protected/library', workout) return data }, // Update user's workout async updateWorkout(workoutId, workout) { - const { data } = await api.put(`/protected/library/${workoutId}`, workout) + const { data } = await api.put(`/api/protected/library/${workoutId}`, workout) return data }, // Delete user's workout async deleteWorkout(workoutId) { - const { data } = await api.delete(`/protected/library/${workoutId}`) + const { data } = await api.delete(`/api/protected/library/${workoutId}`) return data }, // Mark workout as used async recordUsage(workoutId) { - const { data } = await api.post(`/protected/library/${workoutId}/use`) + const { data } = await api.post(`/api/protected/library/${workoutId}/use`) return data }, // Add to favorites async addFavorite(workoutId) { - const { data } = await api.post(`/protected/library/${workoutId}/favorite`) + const { data } = await api.post(`/api/protected/library/${workoutId}/favorite`) return data }, // Remove from favorites async removeFavorite(workoutId) { - const { data } = await api.delete(`/protected/library/${workoutId}/favorite`) + const { data } = await api.delete(`/api/protected/library/${workoutId}/favorite`) return data }, // Rate workout (1-5 stars + optional comment) async rateWorkout(workoutId, rating, comment = null) { - const { data } = await api.post(`/protected/library/${workoutId}/rate`, { + const { data } = await api.post(`/api/protected/library/${workoutId}/rate`, { rating, comment: comment || undefined }) @@ -113,7 +113,7 @@ export const workoutLibraryApi = { // Schedule a library workout to a specific date async scheduleToCalendar(workout, scheduledDate) { - const { data } = await api.post('/protected/workouts/schedule-template', { + const { data } = await api.post('/api/protected/workouts/schedule-template', { template_id: workout.id, template_name: workout.name, template_type: workout.type, diff --git a/src/stores/auth.js b/src/stores/auth.js index 540b03e..2028e57 100644 --- a/src/stores/auth.js +++ b/src/stores/auth.js @@ -125,7 +125,7 @@ export const useAuthStore = defineStore('auth', () => { error.value = null try { - const { data } = await api.get('/protected/profile') + const { data } = await api.get('/api/protected/profile') return data } catch (err) { error.value = err.response?.data?.error || 'Failed to fetch profile' @@ -140,7 +140,7 @@ export const useAuthStore = defineStore('auth', () => { error.value = null try { - const { data } = await api.put('/protected/profile', profileData) + const { data } = await api.put('/api/protected/profile', profileData) return data } catch (err) { error.value = err.response?.data?.error || 'Failed to update profile'