feat: implement achievements
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
pb "datarush/pkg/api/achievements"
|
||||
)
|
||||
|
||||
type AchievementRepository struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func NewAchievementRepository(db *sqlx.DB) *AchievementRepository {
|
||||
return &AchievementRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *AchievementRepository) CreateAchievement(ctx context.Context, achievement *pb.Achievement) (*pb.Achievement, error) {
|
||||
query := `INSERT INTO achievements (name, description, icon_url)
|
||||
VALUES ($1, $2, $3) RETURNING id`
|
||||
|
||||
var createdAchievement pb.Achievement
|
||||
err := r.db.QueryRowContext(ctx, query, achievement.Name, achievement.Description, achievement.IconUrl).
|
||||
Scan(&createdAchievement.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
createdAchievement.Name = achievement.Name
|
||||
createdAchievement.Description = achievement.Description
|
||||
createdAchievement.IconUrl = achievement.IconUrl
|
||||
|
||||
return &createdAchievement, nil
|
||||
}
|
||||
|
||||
func (r *AchievementRepository) GetAchievement(ctx context.Context, id string) (*pb.Achievement, error) {
|
||||
query := `SELECT id, name, description, icon_url
|
||||
FROM achievements WHERE id = $1`
|
||||
|
||||
var achievement pb.Achievement
|
||||
err := r.db.QueryRowContext(ctx, query, id).
|
||||
Scan(&achievement.Id, &achievement.Name, &achievement.Description, &achievement.IconUrl)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &achievement, nil
|
||||
}
|
||||
|
||||
func (r *AchievementRepository) EditAchievement(ctx context.Context, achievement *pb.Achievement) (*pb.Achievement, error) {
|
||||
query := `UPDATE achievements SET name = $1, description = $2, icon_url = $3, updated_at = NOW()
|
||||
WHERE id = $4`
|
||||
|
||||
_, err := r.db.ExecContext(ctx, query, achievement.Name, achievement.Description, achievement.IconUrl, achievement.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return achievement, nil
|
||||
}
|
||||
|
||||
func (r *AchievementRepository) DeleteAchievement(ctx context.Context, id string) error {
|
||||
_, err := r.db.ExecContext(ctx, "DELETE FROM achievements WHERE id = $1", id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *AchievementRepository) ListAchievements(ctx context.Context) ([]*pb.Achievement, error) {
|
||||
query := `SELECT id, name, description, icon_url FROM achievements ORDER BY created_at DESC`
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var achievements []*pb.Achievement
|
||||
for rows.Next() {
|
||||
var achievement pb.Achievement
|
||||
|
||||
err := rows.Scan(&achievement.Id, &achievement.Name, &achievement.Description, &achievement.IconUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
achievements = append(achievements, &achievement)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return achievements, nil
|
||||
}
|
||||
|
||||
func (r *AchievementRepository) GetUserAchievements(ctx context.Context, userID string) ([]*pb.AchievementUser, error) {
|
||||
query := `SELECT a.id, a.name, a.description, a.icon_url, ua.received_at
|
||||
FROM user_achievements ua
|
||||
INNER JOIN achievements a ON ua.achievement_id = a.id
|
||||
WHERE ua.user_id = $1
|
||||
ORDER BY ua.received_at DESC`
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, query, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var userAchievements []*pb.AchievementUser
|
||||
for rows.Next() {
|
||||
var achievement pb.Achievement
|
||||
var receivedAt time.Time
|
||||
|
||||
err := rows.Scan(
|
||||
&achievement.Id,
|
||||
&achievement.Name,
|
||||
&achievement.Description,
|
||||
&achievement.IconUrl,
|
||||
&receivedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userAchievement := &pb.AchievementUser{
|
||||
Achievement: &achievement,
|
||||
ReceivedAt: timestamppb.New(receivedAt),
|
||||
}
|
||||
|
||||
userAchievements = append(userAchievements, userAchievement)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return userAchievements, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "datarush/pkg/api/achievements"
|
||||
)
|
||||
|
||||
type AchievementRepository interface {
|
||||
CreateAchievement(ctx context.Context, achievement *pb.Achievement) (*pb.Achievement, error)
|
||||
GetAchievement(ctx context.Context, id string) (*pb.Achievement, error)
|
||||
EditAchievement(ctx context.Context, achievement *pb.Achievement) (*pb.Achievement, error)
|
||||
DeleteAchievement(ctx context.Context, id string) error
|
||||
ListAchievements(ctx context.Context) ([]*pb.Achievement, error)
|
||||
GetUserAchievements(ctx context.Context, userID string) ([]*pb.AchievementUser, error)
|
||||
}
|
||||
Reference in New Issue
Block a user