You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

94 lines
2.4 KiB

package db
import (
"context"
"database/sql"
"errors"
"time"
_ "github.com/tursodatabase/libsql-client-go/libsql"
)
type Progress struct {
ID string
UserID string
LevelID string
Status string
CompletedAt sql.NullTime
AttemptData sql.NullString
Stars sql.NullInt64
CreatedAt time.Time
UpdatedAt time.Time
}
type ProgressClient struct {
db *sql.DB
}
func NewProgressClient(db *sql.DB) *ProgressClient {
return &ProgressClient{db: db}
}
func (c *ProgressClient) UpsertProgress(ctx context.Context, p *Progress) error {
_, err := c.db.ExecContext(ctx, `
INSERT INTO progress (id, user_id, level_id, status, completed_at, attempt_data, stars)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(user_id, level_id) DO UPDATE SET
status = excluded.status,
completed_at = excluded.completed_at,
attempt_data = excluded.attempt_data,
stars = excluded.stars,
updated_at = CURRENT_TIMESTAMP
`, p.ID, p.UserID, p.LevelID, p.Status, p.CompletedAt, p.AttemptData, p.Stars)
return err
}
func (c *ProgressClient) GetProgressByUser(ctx context.Context, userID string) ([]*Progress, error) {
rows, err := c.db.QueryContext(ctx, `
SELECT id, user_id, level_id, status, completed_at, attempt_data, stars, created_at, updated_at
FROM progress
WHERE user_id = ?
`, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var progressList []*Progress
for rows.Next() {
var p Progress
err := rows.Scan(&p.ID, &p.UserID, &p.LevelID, &p.Status, &p.CompletedAt, &p.AttemptData, &p.Stars, &p.CreatedAt, &p.UpdatedAt)
if err != nil {
return nil, err
}
progressList = append(progressList, &p)
}
return progressList, nil
}
func (c *ProgressClient) GetProgress(ctx context.Context, userID, levelID string) (*Progress, error) {
row := c.db.QueryRowContext(ctx, `
SELECT id, user_id, level_id, status, completed_at, attempt_data, stars, created_at, updated_at
FROM progress
WHERE user_id = ? AND level_id = ?
`, userID, levelID)
var p Progress
err := row.Scan(&p.ID, &p.UserID, &p.LevelID, &p.Status, &p.CompletedAt, &p.AttemptData, &p.Stars, &p.CreatedAt, &p.UpdatedAt)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, err
}
return &p, nil
}
func (c *ProgressClient) DeleteProgress(ctx context.Context, userID, levelID string) error {
_, err := c.db.ExecContext(ctx, `
DELETE FROM progress
WHERE user_id = ? AND level_id = ?
`, userID, levelID)
return err
}