feat: extend equipment and workout models with service tracking
This commit is contained in:
@@ -45,6 +45,7 @@ func (h *Handler) CreateWorkout(w http.ResponseWriter, r *http.Request) {
|
||||
Notes string `json:"notes"`
|
||||
WorkoutData *WorkoutDataJSON `json:"workout_data"`
|
||||
FileType string `json:"file_type"`
|
||||
EquipmentID *uint `json:"equipment_id"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -106,6 +107,7 @@ func (h *Handler) CreateWorkout(w http.ResponseWriter, r *http.Request) {
|
||||
Notes: req.Notes,
|
||||
FileType: req.FileType,
|
||||
WorkoutData: *workoutData,
|
||||
EquipmentID: req.EquipmentID,
|
||||
}
|
||||
|
||||
log.Printf("Creating workout: %+v", workout)
|
||||
@@ -211,6 +213,7 @@ func (h *Handler) UpdateWorkout(w http.ResponseWriter, r *http.Request) {
|
||||
MaxHR int `json:"max_hr"`
|
||||
CaloriesBurned int `json:"calories_burned"`
|
||||
Notes string `json:"notes"`
|
||||
EquipmentID *uint `json:"equipment_id"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -267,6 +270,9 @@ func (h *Handler) UpdateWorkout(w http.ResponseWriter, r *http.Request) {
|
||||
if req.Notes != "" {
|
||||
workout.Notes = req.Notes
|
||||
}
|
||||
if req.EquipmentID != nil {
|
||||
workout.EquipmentID = req.EquipmentID
|
||||
}
|
||||
|
||||
if err := h.service.repo.UpdateWorkout(workout); err != nil {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -320,6 +326,26 @@ func (h *Handler) GetWorkoutTypes(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(types)
|
||||
}
|
||||
|
||||
// GetEquipmentStats GET /api/protected/workouts/equipment-stats
|
||||
func (h *Handler) GetEquipmentStats(w http.ResponseWriter, r *http.Request) {
|
||||
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
||||
|
||||
stats, err := h.service.GetEquipmentStats(claims.UserID)
|
||||
if err != nil {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "failed to fetch equipment stats"})
|
||||
return
|
||||
}
|
||||
|
||||
if stats == nil {
|
||||
stats = []EquipmentStat{}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(stats)
|
||||
}
|
||||
|
||||
// UploadWorkoutFile POST /api/protected/workouts/upload
|
||||
func (h *Handler) UploadWorkoutFile(w http.ResponseWriter, r *http.Request) {
|
||||
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
||||
|
||||
@@ -23,6 +23,7 @@ type Workout struct {
|
||||
MaxHR int `gorm:"default:0" json:"max_hr"`
|
||||
CaloriesBurned int `gorm:"default:0" json:"calories_burned"`
|
||||
FileType string `gorm:"default:''" json:"file_type"`
|
||||
EquipmentID *uint `gorm:"index" json:"equipment_id"`
|
||||
FileURL string `gorm:"default:''" json:"file_url"`
|
||||
WorkoutData WorkoutDataJSON `gorm:"type:jsonb" json:"workout_data,omitempty"`
|
||||
Notes string `json:"notes"`
|
||||
|
||||
@@ -62,4 +62,23 @@ func (r *Repository) UpdateWorkout(workout *Workout) error {
|
||||
func (r *Repository) DeleteWorkout(id, userID uint) error {
|
||||
return database.DB.Where("id = ? AND user_id = ?", id, userID).
|
||||
Delete(&Workout{}).Error
|
||||
}
|
||||
|
||||
type EquipmentStat struct {
|
||||
EquipmentID uint `json:"equipment_id"`
|
||||
TotalRides int `json:"total_rides"`
|
||||
TotalDistance float64 `json:"total_distance"`
|
||||
TotalDuration int `json:"total_duration"`
|
||||
}
|
||||
|
||||
func (r *Repository) GetEquipmentStats(userID uint) ([]EquipmentStat, error) {
|
||||
var stats []EquipmentStat
|
||||
if err := database.DB.Model(&Workout{}).
|
||||
Select("equipment_id, COUNT(*) as total_rides, COALESCE(SUM(distance), 0) as total_distance, COALESCE(SUM(duration), 0) as total_duration").
|
||||
Where("user_id = ? AND equipment_id IS NOT NULL", userID).
|
||||
Group("equipment_id").
|
||||
Scan(&stats).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return stats, nil
|
||||
}
|
||||
@@ -85,4 +85,8 @@ func (s *Service) UpdateWorkoutWithMetrics(id, userID uint, distance float64, av
|
||||
|
||||
func (s *Service) DeleteWorkout(id, userID uint) error {
|
||||
return s.repo.DeleteWorkout(id, userID)
|
||||
}
|
||||
|
||||
func (s *Service) GetEquipmentStats(userID uint) ([]EquipmentStat, error) {
|
||||
return s.repo.GetEquipmentStats(userID)
|
||||
}
|
||||
Reference in New Issue
Block a user