119 lines
2.5 KiB
Go
119 lines
2.5 KiB
Go
package http
|
|
|
|
import (
|
|
"html/template"
|
|
"log/slog"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"git.loyso.art/frx/kurious/internal/common/errors"
|
|
"git.loyso.art/frx/kurious/internal/common/xslice"
|
|
"git.loyso.art/frx/kurious/internal/kurious/app"
|
|
"git.loyso.art/frx/kurious/internal/kurious/app/query"
|
|
"git.loyso.art/frx/kurious/internal/kurious/domain"
|
|
)
|
|
|
|
type courseServer struct {
|
|
app app.Application
|
|
log *slog.Logger
|
|
}
|
|
|
|
type pagination struct {
|
|
page int
|
|
perPage int
|
|
}
|
|
|
|
func (p pagination) LimitOffset() (limit, offset int) {
|
|
if p.page < 0 {
|
|
p.page = 0
|
|
}
|
|
|
|
if p.perPage <= 0 {
|
|
p.perPage = defaultPerPage
|
|
}
|
|
|
|
return p.perPage, p.page * p.perPage
|
|
}
|
|
|
|
func parsePaginationFromQuery(r *http.Request) (out pagination, err error) {
|
|
query := r.URL.Query()
|
|
|
|
if query.Has("page") {
|
|
out.page, err = strconv.Atoi(query.Get("page"))
|
|
if err != nil {
|
|
return out, errors.NewValidationError("page", "bad page value")
|
|
}
|
|
}
|
|
|
|
if query.Has("per_page") {
|
|
out.perPage, err = strconv.Atoi(query.Get("per_page"))
|
|
if err != nil {
|
|
return out, errors.NewValidationError("per_page", "bad per_page value")
|
|
}
|
|
} else {
|
|
out.perPage = 50
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func parseListCoursesParams(r *http.Request) (out listCoursesParams, err error) {
|
|
out.pagination, err = parsePaginationFromQuery(r)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
|
|
query := r.URL.Query()
|
|
out.learningType = query.Get("category")
|
|
out.courseThematic = query.Get("type")
|
|
|
|
return out, nil
|
|
}
|
|
|
|
type listCoursesParams struct {
|
|
pagination
|
|
|
|
courseThematic string
|
|
learningType string
|
|
}
|
|
|
|
type templateCourse domain.Course
|
|
|
|
func mapDomainCourseToTemplate(in ...domain.Course) []templateCourse {
|
|
return xslice.Map(in, func(v domain.Course) templateCourse {
|
|
return templateCourse(v)
|
|
})
|
|
}
|
|
|
|
func (c courseServer) List(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
params, err := parseListCoursesParams(r)
|
|
if err != nil {
|
|
handleError(ctx, err, w, c.log, "unable to parse list courses params")
|
|
return
|
|
}
|
|
|
|
limit, offset := params.LimitOffset()
|
|
|
|
courses, err := c.app.Queries.ListCourses.Handle(ctx, query.ListCourse{
|
|
CourseThematic: params.courseThematic,
|
|
LearningType: params.learningType,
|
|
Limit: limit,
|
|
Offset: offset,
|
|
})
|
|
if err != nil {
|
|
handleError(ctx, err, w, c.log, "unable to list courses")
|
|
}
|
|
|
|
templateCourses := mapDomainCourseToTemplate(courses...)
|
|
|
|
err = template.Must(template.ParseFiles("templates/list.tmpl")).Execute(w, templateCourses)
|
|
if err != nil {
|
|
handleError(ctx, err, w, c.log, "unable to execute template")
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|