diff --git a/internal/models/contest.go b/internal/models/contest.go index 366e416..ceedf75 100644 --- a/internal/models/contest.go +++ b/internal/models/contest.go @@ -8,3 +8,10 @@ type Contest struct { CreatedAt *time.Time `db:"created_at"` UpdatedAt *time.Time `db:"updated_at"` } + +type ContestsListItem struct { + Id int32 `db:"id"` + Title string `db:"title"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` +} diff --git a/internal/tester/delivery.go b/internal/tester/delivery.go index 58eeea0..1764f57 100644 --- a/internal/tester/delivery.go +++ b/internal/tester/delivery.go @@ -6,7 +6,7 @@ import ( ) type Handlers interface { - ListContests(c *fiber.Ctx) error + ListContests(c *fiber.Ctx, params testerv1.ListContestsParams) error CreateContest(c *fiber.Ctx) error DeleteContest(c *fiber.Ctx, id int32) error GetContest(c *fiber.Ctx, id int32) error diff --git a/internal/tester/delivery/rest/handlers.go b/internal/tester/delivery/rest/handlers.go index 56cfedc..0ef381c 100644 --- a/internal/tester/delivery/rest/handlers.go +++ b/internal/tester/delivery/rest/handlers.go @@ -19,8 +19,33 @@ func NewTesterHandlers(problemsUC tester.ProblemUseCase, contestsUC tester.Conte } } -func (h *TesterHandlers) ListContests(c *fiber.Ctx) error { - return c.SendStatus(fiber.StatusNotImplemented) +func (h *TesterHandlers) ListContests(c *fiber.Ctx, params testerv1.ListContestsParams) error { + contests, count, err := h.contestsUC.ListContests(c.Context(), params.Page, params.PageSize) + if err != nil { + return c.SendStatus(pkg.ToREST(err)) + } + + resp := testerv1.ListContestsResponse{ + Contests: make([]testerv1.ContestsListItem, len(contests)), + Page: params.Page, + MaxPage: func() int32 { + if count%params.PageSize == 0 { + return count / params.PageSize + } + return count/params.PageSize + 1 + }(), + } + + for i, contest := range contests { + resp.Contests[i] = testerv1.ContestsListItem{ + Id: contest.Id, + Title: contest.Title, + CreatedAt: contest.CreatedAt, + UpdatedAt: contest.UpdatedAt, + } + } + + return c.JSON(resp) } func (h *TesterHandlers) ListProblems(c *fiber.Ctx, params testerv1.ListProblemsParams) error { diff --git a/internal/tester/pg_repository.go b/internal/tester/pg_repository.go index 0f045a3..0d610c4 100644 --- a/internal/tester/pg_repository.go +++ b/internal/tester/pg_repository.go @@ -21,4 +21,5 @@ type ContestRepository interface { AddParticipant(ctx context.Context, contestId int32, userId int32) (int32, error) DeleteParticipant(ctx context.Context, participantId int32) error ReadRichTasks(ctx context.Context, contestId int32) ([]*models.RichTask, error) + ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) } diff --git a/internal/tester/repository/pg_contests_repository.go b/internal/tester/repository/pg_contests_repository.go index dc706ab..4325866 100644 --- a/internal/tester/repository/pg_contests_repository.go +++ b/internal/tester/repository/pg_contests_repository.go @@ -158,3 +158,27 @@ func (r *ContestRepository) ReadRichTasks(ctx context.Context, contestId int32) } return tasks, nil } + +const ( + readContestsListQuery = `SELECT id, title, created_at, updated_at FROM contests LIMIT ? OFFSET ?` + countContestsQuery = "SELECT COUNT(*) FROM contests" +) + +func (r *ContestRepository) ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) { + const op = "ContestRepository.ReadTasks" + + var tasks []*models.ContestsListItem + query := r.db.Rebind(readContestsListQuery) + err := r.db.SelectContext(ctx, &tasks, query, pageSize, (page-1)*pageSize) + if err != nil { + return nil, 0, handlePgErr(err, op) + } + + var count int32 + err = r.db.GetContext(ctx, &count, countContestsQuery) + if err != nil { + return nil, 0, handlePgErr(err, op) + } + + return tasks, count, nil +} diff --git a/internal/tester/usecase.go b/internal/tester/usecase.go index 5457e6b..7db6c68 100644 --- a/internal/tester/usecase.go +++ b/internal/tester/usecase.go @@ -21,4 +21,5 @@ type ContestUseCase interface { AddParticipant(ctx context.Context, contestId int32, userId int32) (int32, error) DeleteParticipant(ctx context.Context, participantId int32) error ReadRichTasks(ctx context.Context, contestId int32) ([]*models.RichTask, error) + ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) } diff --git a/internal/tester/usecase/contests_usecase.go b/internal/tester/usecase/contests_usecase.go index 796978e..06759e2 100644 --- a/internal/tester/usecase/contests_usecase.go +++ b/internal/tester/usecase/contests_usecase.go @@ -49,3 +49,7 @@ func (uc *ContestUseCase) DeleteParticipant(ctx context.Context, participantId i func (uc *ContestUseCase) ReadRichTasks(ctx context.Context, contestId int32) ([]*models.RichTask, error) { return uc.contestRepo.ReadRichTasks(ctx, contestId) } + +func (uc *ContestUseCase) ListContests(ctx context.Context, page int32, pageSize int32) ([]*models.ContestsListItem, int32, error) { + return uc.contestRepo.ListContests(ctx, page, pageSize) +} diff --git a/proto b/proto index 55846c7..ac0eb56 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 55846c7a2b06b7dcd78fc001b322bdb96a5c8bca +Subproject commit ac0eb56bb9dee9f0933f858e16d61c9e40c89a29