feat: initial commit

This commit is contained in:
2025-06-10 21:09:58 +02:00
commit 1fb753469e
84 changed files with 3912 additions and 0 deletions

View File

@ -0,0 +1,41 @@
package component
import (
"bytes"
"context"
"forge.cadoles.com/wpetit/kouiz/internal/http/form"
common "forge.cadoles.com/wpetit/kouiz/internal/http/handler/webui/common/component"
"github.com/pkg/errors"
"github.com/yuin/goldmark"
"log/slog"
)
type QuizPageVModel struct {
}
func NewQuizForm() *form.Form {
return form.New(
form.NewField(
"project",
form.Attrs{},
form.NonEmpty("Ce champ ne doit pas être vide."),
),
)
}
templ QuizPage(vmodel QuizPageVModel) {
@common.AppPage(common.WithPageOptions(
common.WithTitle("Quiz"),
)) {
}
}
func markdownToHTML(ctx context.Context, text string) string {
var buff bytes.Buffer
if err := goldmark.Convert([]byte(text), &buff); err != nil {
slog.ErrorContext(ctx, "could not convert markdown to html", slog.Any("error", errors.WithStack(err)))
return ""
}
return buff.String()
}

View File

@ -0,0 +1,89 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.819
package component
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import (
"bytes"
"context"
"forge.cadoles.com/wpetit/kouiz/internal/http/form"
common "forge.cadoles.com/wpetit/kouiz/internal/http/handler/webui/common/component"
"github.com/pkg/errors"
"github.com/yuin/goldmark"
"log/slog"
)
type QuizPageVModel struct {
}
func NewQuizForm() *form.Form {
return form.New(
form.NewField(
"project",
form.Attrs{},
form.NonEmpty("Ce champ ne doit pas être vide."),
),
)
}
func QuizPage(vmodel QuizPageVModel) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
return nil
})
templ_7745c5c3_Err = common.AppPage(common.WithPageOptions(
common.WithTitle("Quiz"),
)).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func markdownToHTML(ctx context.Context, text string) string {
var buff bytes.Buffer
if err := goldmark.Convert([]byte(text), &buff); err != nil {
slog.ErrorContext(ctx, "could not convert markdown to html", slog.Any("error", errors.WithStack(err)))
return ""
}
return buff.String()
}
var _ = templruntime.GeneratedTemplate

View File

@ -0,0 +1,31 @@
package quiz
import (
"net/http"
"forge.cadoles.com/wpetit/kouiz/internal/store"
)
type Handler struct {
mux *http.ServeMux
store *store.Store
}
// ServeHTTP implements http.Handler.
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.mux.ServeHTTP(w, r)
}
func NewHandler(store *store.Store) *Handler {
h := &Handler{
mux: http.NewServeMux(),
store: store,
}
h.mux.HandleFunc("GET /", h.getQuizPage)
h.mux.HandleFunc("POST /", h.handleQuizForm)
return h
}
var _ http.Handler = &Handler{}

View File

@ -0,0 +1,63 @@
package quiz
import (
"net/http"
"forge.cadoles.com/wpetit/kouiz/internal/http/handler/webui/common"
"forge.cadoles.com/wpetit/kouiz/internal/http/handler/webui/quiz/component"
"github.com/a-h/templ"
"github.com/pkg/errors"
)
func (h *Handler) getQuizPage(w http.ResponseWriter, r *http.Request) {
vmodel, err := h.fillQuizPageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
issue := component.QuizPage(*vmodel)
templ.Handler(issue).ServeHTTP(w, r)
}
func (h *Handler) fillQuizPageVModel(r *http.Request) (*component.QuizPageVModel, error) {
vmodel := &component.QuizPageVModel{}
err := common.FillViewModel(
r.Context(), vmodel, r,
)
if err != nil {
return nil, errors.WithStack(err)
}
return vmodel, nil
}
func (h *Handler) handleQuizForm(w http.ResponseWriter, r *http.Request) {
quizForm := component.NewQuizForm()
if err := quizForm.Handle(r); err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel, err := h.fillQuizPageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
if errs := quizForm.Validate(); errs != nil {
page := component.QuizPage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
return
}
page := component.QuizPage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
}
func (h *Handler) handleError(w http.ResponseWriter, r *http.Request, err error) {
common.HandleError(w, r, errors.WithStack(err))
}