package db import ( "me-fit/types" "me-fit/utils" "database/sql" "errors" "time" "github.com/google/uuid" ) var ( ErrWorkoutNotExists = errors.New("Workout does not exist") ) type WorkoutDb interface { InsertWorkout(userId uuid.UUID, workout *WorkoutInsert) (*Workout, error) GetWorkouts(userId uuid.UUID) ([]Workout, error) DeleteWorkout(userId uuid.UUID, rowId int) error } type WorkoutDbSqlite struct { db *sql.DB } func NewWorkoutDbSqlite(db *sql.DB) *WorkoutDbSqlite { return &WorkoutDbSqlite{db: db} } type WorkoutInsert struct { Date time.Time Type string Sets int Reps int } type Workout struct { RowId int Date time.Time Type string Sets int Reps int } func NewWorkoutInsert(date time.Time, workoutType string, sets int, reps int) *WorkoutInsert { return &WorkoutInsert{Date: date, Type: workoutType, Sets: sets, Reps: reps} } func NewWorkoutFromInsert(rowId int, workoutInsert *WorkoutInsert) *Workout { return &Workout{RowId: rowId, Date: workoutInsert.Date, Type: workoutInsert.Type, Sets: workoutInsert.Sets, Reps: workoutInsert.Reps} } func (db WorkoutDbSqlite) InsertWorkout(userId uuid.UUID, workout *WorkoutInsert) (*Workout, error) { var rowId int err := db.db.QueryRow(` INSERT INTO workout (user_id, date, type, sets, reps) VALUES (?, ?, ?, ?, ?) RETURNING rowid`, userId, workout.Date, workout.Type, workout.Sets, workout.Reps).Scan(&rowId) if err != nil { utils.LogError("Error inserting workout", err) return nil, types.ErrInternal } return NewWorkoutFromInsert(rowId, workout), nil } func (db WorkoutDbSqlite) GetWorkouts(userId uuid.UUID) ([]Workout, error) { rows, err := db.db.Query("SELECT rowid, date, type, sets, reps FROM workout WHERE user_id = ? ORDER BY date desc", userId) if err != nil { utils.LogError("Could not get workouts", err) return nil, types.ErrInternal } var workouts = make([]Workout, 0) for rows.Next() { var ( workout Workout date string ) err = rows.Scan(&workout.RowId, &date, &workout.Type, &workout.Sets, &workout.Reps) if err != nil { utils.LogError("Could not scan workout", err) return nil, types.ErrInternal } workout.Date, err = time.Parse("2006-01-02 15:04:05-07:00", date) if err != nil { utils.LogError("Could not parse date", err) return nil, types.ErrInternal } workouts = append(workouts, workout) } return workouts, nil } func (db WorkoutDbSqlite) DeleteWorkout(userId uuid.UUID, rowId int) error { res, err := db.db.Exec("DELETE FROM workout WHERE user_id = ? AND rowid = ?", userId, rowId) if err != nil { return types.ErrInternal } rows, err := res.RowsAffected() if err != nil { return types.ErrInternal } if rows == 0 { return ErrWorkoutNotExists } return nil }