all repos — go-lift @ 2e1c54060dc6096e5772a13f5248451e86b03f6d

Lightweight workout tracker prototype..

src/api/crud.go (view raw)

  1package api
  2
  3import (
  4	"encoding/json"
  5	"errors"
  6	"net/http"
  7
  8	"github.com/birabittoh/go-lift/src/database"
  9	"gorm.io/gorm"
 10)
 11
 12// Routines handlers
 13func getRoutinesHandler(db *gorm.DB) http.HandlerFunc {
 14	return func(w http.ResponseWriter, r *http.Request) {
 15		var routines []database.Routine
 16		result := db.Preload("Exercises").Preload("Supersets").Preload("Supersets.Sets").Find(&routines)
 17		if result.Error != nil {
 18			jsonError(w, http.StatusInternalServerError, "Failed to fetch routines: "+result.Error.Error())
 19			return
 20		}
 21		jsonResponse(w, http.StatusOK, routines)
 22	}
 23}
 24
 25func getRoutineHandler(db *gorm.DB) http.HandlerFunc {
 26	return func(w http.ResponseWriter, r *http.Request) {
 27		id := r.PathValue("id")
 28		var routine database.Routine
 29		result := db.Preload("Exercises").Preload("Supersets").Preload("Supersets.Sets").First(&routine, id)
 30		if result.Error != nil {
 31			if errors.Is(result.Error, gorm.ErrRecordNotFound) {
 32				jsonError(w, http.StatusNotFound, "Routine not found")
 33				return
 34			}
 35			jsonError(w, http.StatusInternalServerError, "Failed to fetch routine: "+result.Error.Error())
 36			return
 37		}
 38		jsonResponse(w, http.StatusOK, routine)
 39	}
 40}
 41
 42func createRoutineHandler(db *gorm.DB) http.HandlerFunc {
 43	return func(w http.ResponseWriter, r *http.Request) {
 44		var routine database.Routine
 45		if err := json.NewDecoder(r.Body).Decode(&routine); err != nil {
 46			jsonError(w, http.StatusBadRequest, "Invalid request body: "+err.Error())
 47			return
 48		}
 49
 50		if err := db.Create(&routine).Error; err != nil {
 51			jsonError(w, http.StatusInternalServerError, "Failed to create routine: "+err.Error())
 52			return
 53		}
 54
 55		// Reload with associations
 56		db.Preload("Exercises").Preload("Supersets").Preload("Supersets.Sets").First(&routine, routine.ID)
 57
 58		jsonResponse(w, http.StatusCreated, routine)
 59	}
 60}
 61
 62func updateRoutineHandler(db *gorm.DB) http.HandlerFunc {
 63	return func(w http.ResponseWriter, r *http.Request) {
 64		id := r.PathValue("id")
 65		var routine database.Routine
 66
 67		// Check if exists
 68		if err := db.First(&routine, id).Error; err != nil {
 69			if errors.Is(err, gorm.ErrRecordNotFound) {
 70				jsonError(w, http.StatusNotFound, "Routine not found")
 71				return
 72			}
 73			jsonError(w, http.StatusInternalServerError, "Database error: "+err.Error())
 74			return
 75		}
 76
 77		// Parse update data
 78		if err := json.NewDecoder(r.Body).Decode(&routine); err != nil {
 79			jsonError(w, http.StatusBadRequest, "Invalid request body: "+err.Error())
 80			return
 81		}
 82
 83		// Save with associations
 84		if err := db.Session(&gorm.Session{FullSaveAssociations: true}).Save(&routine).Error; err != nil {
 85			jsonError(w, http.StatusInternalServerError, "Failed to update routine: "+err.Error())
 86			return
 87		}
 88
 89		// Reload complete data
 90		db.Preload("Exercises").Preload("Supersets").Preload("Supersets.Sets").First(&routine, id)
 91		jsonResponse(w, http.StatusOK, routine)
 92	}
 93}
 94
 95func deleteRoutineHandler(db *gorm.DB) http.HandlerFunc {
 96	return func(w http.ResponseWriter, r *http.Request) {
 97		id := r.PathValue("id")
 98		if err := db.Delete(&database.Routine{}, id).Error; err != nil {
 99			jsonError(w, http.StatusInternalServerError, "Failed to delete routine: "+err.Error())
100			return
101		}
102		jsonResponse(w, http.StatusOK, map[string]string{"message": "Routine deleted successfully"})
103	}
104}
105
106// Exercises handlers
107func getExercisesHandler(db *gorm.DB) http.HandlerFunc {
108	return func(w http.ResponseWriter, r *http.Request) {
109		var exercises []database.Exercise
110		if err := db.Find(&exercises).Error; err != nil {
111			jsonError(w, http.StatusInternalServerError, "Failed to fetch exercises: "+err.Error())
112			return
113		}
114		jsonResponse(w, http.StatusOK, exercises)
115	}
116}
117
118func getExerciseHandler(db *gorm.DB) http.HandlerFunc {
119	return func(w http.ResponseWriter, r *http.Request) {
120		id := r.PathValue("id")
121		var exercise database.Exercise
122		if err := db.First(&exercise, id).Error; err != nil {
123			if errors.Is(err, gorm.ErrRecordNotFound) {
124				jsonError(w, http.StatusNotFound, "Exercise not found")
125				return
126			}
127			jsonError(w, http.StatusInternalServerError, "Failed to fetch exercise: "+err.Error())
128			return
129		}
130		jsonResponse(w, http.StatusOK, exercise)
131	}
132}
133
134func createExerciseHandler(db *gorm.DB) http.HandlerFunc {
135	return func(w http.ResponseWriter, r *http.Request) {
136		var exercise database.Exercise
137		if err := json.NewDecoder(r.Body).Decode(&exercise); err != nil {
138			jsonError(w, http.StatusBadRequest, "Invalid request body: "+err.Error())
139			return
140		}
141
142		if err := db.Create(&exercise).Error; err != nil {
143			jsonError(w, http.StatusInternalServerError, "Failed to create exercise: "+err.Error())
144			return
145		}
146
147		jsonResponse(w, http.StatusCreated, exercise)
148	}
149}
150
151func updateExerciseHandler(db *gorm.DB) http.HandlerFunc {
152	return func(w http.ResponseWriter, r *http.Request) {
153		id := r.PathValue("id")
154
155		// Verify exercise exists
156		var exercise database.Exercise
157		if err := db.First(&exercise, id).Error; err != nil {
158			if errors.Is(err, gorm.ErrRecordNotFound) {
159				jsonError(w, http.StatusNotFound, "Exercise not found")
160				return
161			}
162			jsonError(w, http.StatusInternalServerError, "Database error: "+err.Error())
163			return
164		}
165
166		// Parse update data
167		if err := json.NewDecoder(r.Body).Decode(&exercise); err != nil {
168			jsonError(w, http.StatusBadRequest, "Invalid request body: "+err.Error())
169			return
170		}
171
172		if err := db.Save(&exercise).Error; err != nil {
173			jsonError(w, http.StatusInternalServerError, "Failed to update exercise: "+err.Error())
174			return
175		}
176
177		jsonResponse(w, http.StatusOK, exercise)
178	}
179}
180
181func deleteExerciseHandler(db *gorm.DB) http.HandlerFunc {
182	return func(w http.ResponseWriter, r *http.Request) {
183		id := r.PathValue("id")
184		if err := db.Delete(&database.Exercise{}, id).Error; err != nil {
185			jsonError(w, http.StatusInternalServerError, "Failed to delete exercise: "+err.Error())
186			return
187		}
188		jsonResponse(w, http.StatusOK, map[string]string{"message": "Exercise deleted successfully"})
189	}
190}
191
192// RecordRoutines handlers
193func getRecordRoutinesHandler(db *gorm.DB) http.HandlerFunc {
194	return func(w http.ResponseWriter, r *http.Request) {
195		var records []database.RecordRoutine
196		result := db.Preload("RecordExercises").Preload("Routine.Exercises").Preload("Routine.Supersets").Find(&records)
197		if result.Error != nil {
198			jsonError(w, http.StatusInternalServerError, "Failed to fetch record routines: "+result.Error.Error())
199			return
200		}
201		jsonResponse(w, http.StatusOK, records)
202	}
203}
204
205func getRecordRoutineHandler(db *gorm.DB) http.HandlerFunc {
206	return func(w http.ResponseWriter, r *http.Request) {
207		id := r.PathValue("id")
208		var record database.RecordRoutine
209		result := db.Preload("Routine").Preload("Routine.Exercises").Preload("Routine.Supersets").First(&record, id)
210		if result.Error != nil {
211			if errors.Is(result.Error, gorm.ErrRecordNotFound) {
212				jsonError(w, http.StatusNotFound, "Record routine not found")
213				return
214			}
215			jsonError(w, http.StatusInternalServerError, "Failed to fetch record routine: "+result.Error.Error())
216			return
217		}
218		jsonResponse(w, http.StatusOK, record)
219	}
220}
221
222func createRecordRoutineHandler(db *gorm.DB) http.HandlerFunc {
223	return func(w http.ResponseWriter, r *http.Request) {
224		var record database.RecordRoutine
225		if err := json.NewDecoder(r.Body).Decode(&record); err != nil {
226			jsonError(w, http.StatusBadRequest, "Invalid request body: "+err.Error())
227			return
228		}
229
230		if err := db.Create(&record).Error; err != nil {
231			jsonError(w, http.StatusInternalServerError, "Failed to create record routine: "+err.Error())
232			return
233		}
234
235		// Reload with associations
236		db.Preload("Routine").Preload("Routine.Exercises").Preload("Routine.Supersets").First(&record, record.ID)
237
238		jsonResponse(w, http.StatusCreated, record)
239	}
240}
241
242func updateRecordRoutineHandler(db *gorm.DB) http.HandlerFunc {
243	return func(w http.ResponseWriter, r *http.Request) {
244		id := r.PathValue("id")
245		var record database.RecordRoutine
246
247		// Check if exists
248		if err := db.First(&record, id).Error; err != nil {
249			if errors.Is(err, gorm.ErrRecordNotFound) {
250				jsonError(w, http.StatusNotFound, "Record routine not found")
251				return
252			}
253			jsonError(w, http.StatusInternalServerError, "Database error: "+err.Error())
254			return
255		}
256
257		// Parse update data
258		if err := json.NewDecoder(r.Body).Decode(&record); err != nil {
259			jsonError(w, http.StatusBadRequest, "Invalid request body: "+err.Error())
260			return
261		}
262
263		// Save with associations
264		if err := db.Session(&gorm.Session{FullSaveAssociations: true}).Save(&record).Error; err != nil {
265			jsonError(w, http.StatusInternalServerError, "Failed to update record routine: "+err.Error())
266			return
267		}
268
269		// Reload complete data
270		db.Preload("Routine").Preload("Routine.Exercises").Preload("Routine.Supersets").First(&record, id)
271		jsonResponse(w, http.StatusOK, record)
272	}
273}
274
275func deleteRecordRoutineHandler(db *gorm.DB) http.HandlerFunc {
276	return func(w http.ResponseWriter, r *http.Request) {
277		id := r.PathValue("id")
278		if err := db.Delete(&database.RecordRoutine{}, id).Error; err != nil {
279			jsonError(w, http.StatusInternalServerError, "Failed to delete record routine: "+err.Error())
280			return
281		}
282		jsonResponse(w, http.StatusOK, map[string]string{"message": "Record routine deleted successfully"})
283	}
284}