169 lines
4.6 KiB
Go
169 lines
4.6 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"sno/internal/models"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
// QuizRepository defines the interface for quiz data operations.
|
|
type QuizRepository interface {
|
|
GetAllActive(ctx context.Context) ([]models.Quiz, error)
|
|
Create(ctx context.Context, quiz *models.Quiz) (*models.Quiz, error)
|
|
GetByID(ctx context.Context, id int) (*models.Quiz, error)
|
|
Update(ctx context.Context, id int, quiz *models.Quiz) (*models.Quiz, error)
|
|
Delete(ctx context.Context, id int) error
|
|
}
|
|
|
|
// postgresQuizRepository implements the QuizRepository interface for PostgreSQL.
|
|
type postgresQuizRepository struct {
|
|
db *pgxpool.Pool
|
|
}
|
|
|
|
// NewQuizRepository creates a new instance of a quiz repository.
|
|
func NewQuizRepository(db *pgxpool.Pool) QuizRepository {
|
|
return &postgresQuizRepository{db: db}
|
|
}
|
|
|
|
// GetAllActive retrieves all quizzes where is_active is true.
|
|
func (r *postgresQuizRepository) GetAllActive(ctx context.Context) ([]models.Quiz, error) {
|
|
query := `
|
|
SELECT
|
|
id, title, description, image_url, reward_stars,
|
|
has_timer, timer_per_question, can_repeat, repeat_cooldown_hours,
|
|
is_active, created_by, created_at
|
|
FROM quizzes
|
|
WHERE is_active = true
|
|
ORDER BY created_at DESC
|
|
`
|
|
|
|
rows, err := r.db.Query(ctx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var quizzes []models.Quiz
|
|
for rows.Next() {
|
|
var q models.Quiz
|
|
if err := rows.Scan(
|
|
&q.ID, &q.Title, &q.Description, &q.ImageURL, &q.RewardStars,
|
|
&q.HasTimer, &q.TimerPerQuestion, &q.CanRepeat, &q.RepeatCooldownHours,
|
|
&q.IsActive, &q.CreatedBy, &q.CreatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
quizzes = append(quizzes, q)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if quizzes == nil {
|
|
return []models.Quiz{}, nil
|
|
}
|
|
|
|
return quizzes, nil
|
|
}
|
|
|
|
// Create inserts a new quiz into the database.
|
|
func (r *postgresQuizRepository) Create(ctx context.Context, quiz *models.Quiz) (*models.Quiz, error) {
|
|
query := `
|
|
INSERT INTO quizzes (title, description, image_url, reward_stars, has_timer, timer_per_question, can_repeat, repeat_cooldown_hours, created_by)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
RETURNING id, is_active, created_at
|
|
`
|
|
err := r.db.QueryRow(ctx, query,
|
|
quiz.Title, quiz.Description, quiz.ImageURL, quiz.RewardStars, quiz.HasTimer, quiz.TimerPerQuestion, quiz.CanRepeat, quiz.RepeatCooldownHours, quiz.CreatedBy,
|
|
).Scan(&quiz.ID, &quiz.IsActive, &quiz.CreatedAt)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return quiz, nil
|
|
}
|
|
|
|
// GetByID retrieves a single quiz by its ID.
|
|
func (r *postgresQuizRepository) GetByID(ctx context.Context, id int) (*models.Quiz, error) {
|
|
query := `
|
|
SELECT
|
|
id, title, description, image_url, reward_stars,
|
|
has_timer, timer_per_question, can_repeat, repeat_cooldown_hours,
|
|
is_active, created_by, created_at
|
|
FROM quizzes
|
|
WHERE id = $1
|
|
`
|
|
|
|
var q models.Quiz
|
|
err := r.db.QueryRow(ctx, query, id).Scan(
|
|
&q.ID, &q.Title, &q.Description, &q.ImageURL, &q.RewardStars,
|
|
&q.HasTimer, &q.TimerPerQuestion, &q.CanRepeat, &q.RepeatCooldownHours,
|
|
&q.IsActive, &q.CreatedBy, &q.CreatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &q, nil
|
|
}
|
|
|
|
// Update updates an existing quiz
|
|
func (r *postgresQuizRepository) Update(ctx context.Context, id int, quiz *models.Quiz) (*models.Quiz, error) {
|
|
query := `
|
|
UPDATE quizzes
|
|
SET title = $2, description = $3, image_url = $4, reward_stars = $5,
|
|
has_timer = $6, timer_per_question = $7, can_repeat = $8, repeat_cooldown_hours = $9,
|
|
is_active = $10
|
|
WHERE id = $1
|
|
RETURNING id, title, description, image_url, reward_stars,
|
|
has_timer, timer_per_question, can_repeat, repeat_cooldown_hours,
|
|
is_active, created_by, created_at
|
|
`
|
|
|
|
var q models.Quiz
|
|
err := r.db.QueryRow(ctx, query,
|
|
id, quiz.Title, quiz.Description, quiz.ImageURL, quiz.RewardStars,
|
|
quiz.HasTimer, quiz.TimerPerQuestion, quiz.CanRepeat, quiz.RepeatCooldownHours,
|
|
quiz.IsActive,
|
|
).Scan(
|
|
&q.ID, &q.Title, &q.Description, &q.ImageURL, &q.RewardStars,
|
|
&q.HasTimer, &q.TimerPerQuestion, &q.CanRepeat, &q.RepeatCooldownHours,
|
|
&q.IsActive, &q.CreatedBy, &q.CreatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &q, nil
|
|
}
|
|
|
|
// Delete deletes a quiz and its associated questions
|
|
func (r *postgresQuizRepository) Delete(ctx context.Context, id int) error {
|
|
// Start transaction
|
|
tx, err := r.db.Begin(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Rollback(ctx)
|
|
|
|
// Delete associated questions first
|
|
_, err = tx.Exec(ctx, "DELETE FROM questions WHERE quiz_id = $1", id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Delete the quiz
|
|
_, err = tx.Exec(ctx, "DELETE FROM quizzes WHERE id = $1", id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Commit transaction
|
|
return tx.Commit(ctx)
|
|
}
|