Files
rideaware-api/internal/workout/model.go
2026-05-17 20:39:47 -05:00

105 lines
3.3 KiB
Go

package workout
import (
"database/sql/driver"
"encoding/json"
"fmt"
"strings"
"time"
)
type Workout struct {
ID uint `gorm:"primaryKey" json:"id"`
UserID uint `gorm:"not null;index" json:"user_id"`
Title string `gorm:"not null" json:"title"`
Description string `gorm:"default:''" json:"description"`
Type string `gorm:"default:''" json:"type"`
Status string `gorm:"default:'planned'" json:"status"`
ScheduledDate time.Time `gorm:"index" json:"scheduled_date"`
Duration int `gorm:"default:0" json:"duration"`
Distance float64 `gorm:"default:0" json:"distance"`
ElevGain int `gorm:"default:0" json:"elev_gain"`
AvgPower int `gorm:"default:0" json:"avg_power"`
AvgHR int `gorm:"default:0" json:"avg_hr"`
MaxPower int `gorm:"default:0" json:"max_power"`
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"`
RPE int `gorm:"default:0" json:"rpe"`
Notes string `json:"notes"`
Tags Tags `gorm:"type:jsonb;default:'[]'" json:"tags"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// Tags is a JSONB array of string tags for workouts
type Tags []string
// Scan implements the sql.Scanner interface for reading from the database
func (t *Tags) Scan(value interface{}) error {
if value == nil {
*t = Tags{}
return nil
}
switch v := value.(type) {
case []byte:
return json.Unmarshal(v, t)
case string:
return json.Unmarshal([]byte(v), t)
default:
return fmt.Errorf("unsupported type for Tags: %T", value)
}
}
// Value implements the driver.Valuer interface for writing to the database
func (t Tags) Value() (driver.Value, error) {
if t == nil {
return json.Marshal([]string{})
}
return json.Marshal(t)
}
// String returns a comma-separated string representation
func (t Tags) String() string {
return strings.Join(t, ", ")
}
type WorkoutDataJSON struct {
Name string `json:"name"`
Author string `json:"author"`
TotalDuration int `json:"total_duration"`
Segments []WorkoutSegment `json:"segments"`
}
type WorkoutSegment struct {
Type string `json:"type"`
Duration int `json:"duration"`
PowerLow float64 `json:"power_low"`
PowerHigh float64 `json:"power_high"`
Power float64 `json:"power"`
Cadence int `json:"cadence"`
}
// Scan implements sql.Scanner interface
func (w *WorkoutDataJSON) Scan(value interface{}) error {
if value == nil {
*w = WorkoutDataJSON{}
return nil
}
bytes := value.([]byte)
return json.Unmarshal(bytes, &w)
}
// Value implements driver.Valuer interface
func (w WorkoutDataJSON) Value() (driver.Value, error) {
return json.Marshal(w)
}
func (Workout) TableName() string {
return "workouts"
}