From a3dc4eddfaf38f3836f04696e5dad0025cf08396 Mon Sep 17 00:00:00 2001 From: Patryk Hegenberg Date: Wed, 27 Nov 2024 09:38:26 +0100 Subject: [PATCH] refactor: change template generation from go-elem to templ and clean up the repository --- controllers/add.go | 15 + controllers/bewertung.go | 342 ----------------------- controllers/controller.go | 12 + controllers/create.go | 16 ++ controllers/end.go | 13 + controllers/export.go | 43 +++ controllers/parse.go | 46 ++++ controllers/render.go | 11 + controllers/toggle.go | 21 ++ go.mod | 1 + go.sum | 18 +- main.go | 487 +-------------------------------- main_test.go | 34 --- {model => models}/bewertung.go | 10 +- models/maxpunkte.go | 8 + templates/templates.templ | 147 ++++++++++ templates/templates_templ.go | 427 +++++++++++++++++++++++++++++ utils.go | 1 - utils/utils.go | 64 +++++ 19 files changed, 842 insertions(+), 874 deletions(-) create mode 100644 controllers/add.go delete mode 100644 controllers/bewertung.go create mode 100644 controllers/controller.go create mode 100644 controllers/create.go create mode 100644 controllers/end.go create mode 100644 controllers/export.go create mode 100644 controllers/parse.go create mode 100644 controllers/render.go create mode 100644 controllers/toggle.go delete mode 100644 main_test.go rename {model => models}/bewertung.go (66%) create mode 100644 models/maxpunkte.go create mode 100644 templates/templates.templ create mode 100644 templates/templates_templ.go delete mode 100644 utils.go create mode 100644 utils/utils.go diff --git a/controllers/add.go b/controllers/add.go new file mode 100644 index 0000000..a3a5600 --- /dev/null +++ b/controllers/add.go @@ -0,0 +1,15 @@ +package controllers + +import ( + "net/http" + + "github.com/labstack/echo/v4" +) + +func (c *Controller) AddBewertungRoute(ctx echo.Context) error { + new := c.ParseBewertungen(ctx) + if new.Nachname != "" { + *c.Bewertungen = append(*c.Bewertungen, new) + } + return ctx.Redirect(http.StatusSeeOther, "/") +} diff --git a/controllers/bewertung.go b/controllers/bewertung.go deleted file mode 100644 index 8de7a2a..0000000 --- a/controllers/bewertung.go +++ /dev/null @@ -1,342 +0,0 @@ -package controllers - -import ( - "echoTest/model" - "fmt" - "net/http" - "strconv" - - "github.com/chasefleming/elem-go" - "github.com/chasefleming/elem-go/attrs" - "github.com/chasefleming/elem-go/htmx" - "github.com/labstack/echo/v4" -) - -func UpdateGewertetRoute(bewertung model.Bewertung) elem.Node { - checkbox := elem.Input(attrs.Props{ - attrs.Type: "checkbox", - attrs.Checked: strconv.FormatBool(bewertung.Gewertet), - htmx.HXPost: "/toggle/" + strconv.Itoa(bewertung.ID), - htmx.HXTarget: "#bewertung-" + strconv.Itoa(bewertung.ID), - }) - return checkbox -} - -func RenderBewertungenRoute(c echo.Context) error { - return c.HTML(http.StatusOK, renderBewertungen(Bewertungen)) -} - -func ToggleWertungRoute(c echo.Context) error { - id, _ := strconv.Atoi(c.Param("id")) - var updatedBewertung model.Bewertung - for i, bewertung := range Bewertungen { - if bewertung.ID == id { - Bewertungen[i].Gewertet = !bewertung.Gewertet - updatedBewertung = Bewertungen[i] - break - } - } - return c.HTML(http.StatusOK, createBewertungNode(updatedBewertung).Render()) -} -func addBewertungRoute(c echo.Context) error { - new := parseBewertungen(c) - if new.Nachname != "" { - Bewertungen = append(Bewertungen, new) - } - return c.Redirect(http.StatusSeeOther, "/") -} -func parseBewertungen(c echo.Context) Bewertung { - newName := validateName(c) - vorname := c.FormValue("vorname") - if MaxPunkte.HvMax == 0.00 { - hvMax, _ := strconv.ParseFloat(c.FormValue("hv_max"), 64) - lvMax, _ := strconv.ParseFloat(c.FormValue("lv_max"), 64) - hvGewichtung, _ := strconv.ParseFloat(c.FormValue("hv_gewichtung"), 64) - lvGewichtung, _ := strconv.ParseFloat(c.FormValue("lv_gewichtung"), 64) - MaxPunkte.HvMax = hvMax - MaxPunkte.LvMax = lvMax - MaxPunkte.LvGewichtung = lvGewichtung - MaxPunkte.HvGewichtung = hvGewichtung - } - hvPunkte, _ := strconv.ParseFloat(c.FormValue("hv_punkte"), 64) - lvPunkte, _ := strconv.ParseFloat(c.FormValue("lv_punkte"), 64) - hvProzent := 100.00 / maxPunkte.HvMax * hvPunkte - lvProzent := 100.00 / maxPunkte.LvMax * lvPunkte - hvNote := setNote(hvProzent) - lvNote := setNote(lvProzent) - gesamtProzent := hvProzent*maxPunkte.HvGewichtung/100 + lvProzent*maxPunkte.LvGewichtung/100 - gesamtNote := setNote(gesamtProzent) - - // Create a new Bewertung struct - return model.Bewertung{ - ID: len(bewertungen) + 1, - Vorname: string(vorname), - Nachname: string(newName), - HvPunkte: hvPunkte, - HvProzent: hvProzent, - HvNote: int(hvNote), - LvPunkte: lvPunkte, - LvProzent: lvProzent, - LvNote: int(lvNote), - GesamtProzent: gesamtProzent, - GesamtNote: int(gesamtNote), - Gewertet: true, - } -} -func createBewertungNode(bewertung Bewertung) elem.Node { - checkbox := elem.Input(attrs.Props{ - attrs.Type: "checkbox", - attrs.Checked: strconv.FormatBool(bewertung.Gewertet), - htmx.HXPost: "/toggle/" + strconv.Itoa(bewertung.ID), - htmx.HXTarget: "#bewertung-" + strconv.Itoa(bewertung.ID), - htmx.HXSwap: "outerHTML", - }) - - return elem.Tr(attrs.Props{ - attrs.ID: "bewertung-" + strconv.Itoa(bewertung.ID), - }, - elem.Td(nil, checkbox), - elem.Td(nil, elem.Text(bewertung.Vorname)), - elem.Td(nil, elem.Text(bewertung.Nachname)), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.HvPunkte, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.HvProzent, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.Itoa(bewertung.HvNote))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.LvPunkte, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.LvProzent, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.Itoa(bewertung.LvNote))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.GesamtProzent, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.Itoa(bewertung.GesamtNote))), - ) -} - -func renderBewertungen(bewertungen []Bewertung) string { - inputPunkte := elem.Div(nil) - if maxPunkte.HvGewichtung == 0.00 { - inputPunkte = elem.Div(attrs.Props{attrs.Class: "tile is-ancestor"}, - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_max", - attrs.Placeholder: "HV-Max-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_gewichtung", - attrs.Placeholder: "HV-Gewichtung in %", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_max", - attrs.Placeholder: "LV-Max-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_gewichtung", - attrs.Placeholder: "LV-Gewichtung in %", - }, - ), - ), - ) - } else { - inputPunkte = elem.Div(attrs.Props{attrs.Class: "tile is-ancestor"}, - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_max", - attrs.Placeholder: "HV-Max-Punkte", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.HvMax), - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_gewichtung", - attrs.Placeholder: "HV-Gewichtung in %", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.HvGewichtung), - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_max", - attrs.Placeholder: "LV-Max-Punkte", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.LvMax), - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_gewichtung", - attrs.Placeholder: "LV-Gewichtung in %", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.LvGewichtung), - }, - ), - ), - ) - } - - headContent := elem.Head(nil, - elem.Meta(attrs.Props{attrs.Charset: "UTF-8", attrs.Name: "viewport", attrs.Content: "width=device-width, initial-scale=1.0"}), - elem.Script(attrs.Props{attrs.Src: "https://unpkg.com/htmx.org"}), - elem.Link(attrs.Props{attrs.Rel: "stylesheet", attrs.Href: "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"}), - ) - - headerContent := elem.Header(attrs.Props{ - attrs.Class: "navbar", - attrs.Role: "navigation", - attrs.AriaLabel: "main navigation", - }, - elem.Div(attrs.Props{ - attrs.ID: "navbarBasicExample", - attrs.Class: "navbar-menu", - }, - elem.Div(attrs.Props{ - attrs.Class: "navbar-start", - }, - elem.A(attrs.Props{ - attrs.Class: "navbar-item", - }, elem.Text("Home"), - ), - ), - elem.Div(attrs.Props{ - attrs.Class: "navbar-end", - }, - elem.Span(attrs.Props{ - attrs.Class: "navbar-item", - }, - elem.Button(attrs.Props{ - attrs.Class: "button is-primary", - htmx.HXTrigger: "click", - htmx.HXGet: "/end", - }, elem.Text("Beenden"), - ), - ), - ), - ), - ) - - bodyContent := elem.Div(attrs.Props{attrs.Class: "container is-widescreen"}, - elem.Div(attrs.Props{attrs.Class: "card tile is-vertical is-ancestor"}, - elem.Header(attrs.Props{attrs.Class: "card-header"}, - elem.P(attrs.Props{attrs.Class: "card-header-title"}, elem.Text("Englischarbeit"))), - elem.Div(attrs.Props{attrs.Class: "card-content"}, - elem.Div(attrs.Props{attrs.Class: "content tile is-parent is-vertical gap"}, - elem.H1(attrs.Props{attrs.Class: "tilte"}, elem.Text("Bewertungen")), - elem.Form(attrs.Props{attrs.Method: "post", attrs.Action: "/add"}, inputPunkte, - elem.Div(attrs.Props{attrs.Class: "tile is-ancestor"}, - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "vorname", - attrs.Class: "input is-child", - attrs.Placeholder: "Vorname", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "nachname", - attrs.Class: "input is-child", - attrs.Placeholder: "Nachname", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "hv_punkte", - attrs.Class: "input is-child", - attrs.Placeholder: "HV-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "lv_punkte", - attrs.Class: "input is-child", - attrs.Placeholder: "LV-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Button( - attrs.Props{ - attrs.Type: "submit", - attrs.Class: "button tile is-child", - }, - elem.Text("Add"), - ), - ), - ), - ), - elem.Div(attrs.Props{attrs.Class: "table-container"}, - elem.Table(attrs.Props{attrs.Class: "table is-hoverable"}, - elem.THead(nil, - elem.Tr(nil, - elem.Th(nil, elem.Text("Gewertet")), - elem.Th(nil, elem.Text("Vorname")), - elem.Th(nil, elem.Text("Nachname")), - elem.Th(nil, elem.Text("HV-Punkte")), - elem.Th(nil, elem.Text("HV-Prozent")), - elem.Th(nil, elem.Text("HV-Note")), - elem.Th(nil, elem.Text("LV-Punkte")), - elem.Th(nil, elem.Text("LV-Prozent")), - elem.Th(nil, elem.Text("LV-Note")), - elem.Th(nil, elem.Text("Gesamt-Prozent")), - elem.Th(nil, elem.Text("Gesamt-Note")), - ), - ), - elem.TBody(nil, - elem.TransformEach(bewertungen, createBewertungNode)...), - ), - ), - elem.Div(nil, - elem.Button(attrs.Props{ - htmx.HXTrigger: "click", - htmx.HXGet: "/export", - attrs.Class: "button", - }, - elem.Text("export"), - ), - ), - ), - ), - ), - ) - footerContent := elem.Footer(attrs.Props{ - attrs.Class: "footer", - }, - elem.Div(attrs.Props{ - attrs.Class: "content has-text-centered", - }, - elem.P(nil, elem.Text("© 2023 Alle Rechte vorbehalten.")), - ), - ) - - tbodyContent := elem.TBody(nil) - htmlContent := elem.Html(nil, elem.Raw(""), headContent, headerContent, bodyContent, tbodyContent, footerContent) - - return htmlContent.Render() -} diff --git a/controllers/controller.go b/controllers/controller.go new file mode 100644 index 0000000..db852a9 --- /dev/null +++ b/controllers/controller.go @@ -0,0 +1,12 @@ +package controllers + +import "echoTest/models" + +type Controller struct { + Bewertungen *[]models.Bewertung + MaxPunkte *models.MaxPunkte +} + +func NewController(bewertungen *[]models.Bewertung, maxPunkte *models.MaxPunkte) *Controller { + return &Controller{Bewertungen: bewertungen, MaxPunkte: maxPunkte} +} diff --git a/controllers/create.go b/controllers/create.go new file mode 100644 index 0000000..7d8c285 --- /dev/null +++ b/controllers/create.go @@ -0,0 +1,16 @@ +package controllers + +import ( + "context" + "echoTest/models" + "echoTest/templates" + "io" + + "github.com/a-h/templ" +) + +func (c *Controller) CreateBewertungNode(bewertung models.Bewertung) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error { + return templates.BewertungenTable([]models.Bewertung{bewertung}).Render(ctx, w) + }) +} diff --git a/controllers/end.go b/controllers/end.go new file mode 100644 index 0000000..0263caa --- /dev/null +++ b/controllers/end.go @@ -0,0 +1,13 @@ +package controllers + +import ( + "net/http" + "os" + + "github.com/labstack/echo/v4" +) + +func (c *Controller) EndRoute(ctx echo.Context) error { + os.Exit(0) + return ctx.HTML(http.StatusOK, "Tschüss") +} diff --git a/controllers/export.go b/controllers/export.go new file mode 100644 index 0000000..96a9c48 --- /dev/null +++ b/controllers/export.go @@ -0,0 +1,43 @@ +package controllers + +import ( + "fmt" + "log" + "net/http" + "strconv" + + "github.com/jung-kurt/gofpdf" + "github.com/labstack/echo/v4" +) + +func (c *Controller) ExportBewertungenRoute(ctx echo.Context) error { + log.Println("Exporting") + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "B", 12) + pdf.CellFormat(27, 10, "Vorname", "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, "Nachname", "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, "HV-Punkte", "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, "HV-Note", "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, "LV-Punkte", "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, "LV-Note", "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, "Gesamtnote", "1", 0, "", false, 0, "") + pdf.Ln(-1) + pdf.SetFont("Arial", "", 11) + for _, bewertung := range *c.Bewertungen { + pdf.CellFormat(27, 10, bewertung.Vorname, "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, bewertung.Nachname, "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, strconv.FormatFloat(bewertung.HvPunkte, 'f', 2, 64), "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, strconv.FormatInt(int64(bewertung.HvNote), 10), "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, strconv.FormatFloat(bewertung.LvPunkte, 'f', 2, 64), "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, strconv.FormatInt(int64(bewertung.LvNote), 10), "1", 0, "", false, 0, "") + pdf.CellFormat(27, 10, strconv.FormatInt(int64(bewertung.GesamtNote), 10), "1", 0, "", false, 0, "") + pdf.Ln(-1) + } + err := pdf.OutputFileAndClose("bewertungen.pdf") + if err != nil { + fmt.Println("Fehler beim Exportieren der Bewertungen:", err) + return err + } + return ctx.HTML(http.StatusOK, "Export beendet") +} diff --git a/controllers/parse.go b/controllers/parse.go new file mode 100644 index 0000000..4266c47 --- /dev/null +++ b/controllers/parse.go @@ -0,0 +1,46 @@ +package controllers + +import ( + "echoTest/models" + "echoTest/utils" + "strconv" + + "github.com/labstack/echo/v4" +) + +func (c *Controller) ParseBewertungen(ctx echo.Context) models.Bewertung { + newName := utils.ValidateName(ctx, c.Bewertungen) + vorname := ctx.FormValue("vorname") + if c.MaxPunkte.HvMax == 0.00 { + hvMax, _ := strconv.ParseFloat(ctx.FormValue("hv_max"), 64) + lvMax, _ := strconv.ParseFloat(ctx.FormValue("lv_max"), 64) + hvGewichtung, _ := strconv.ParseFloat(ctx.FormValue("hv_gewichtung"), 64) + lvGewichtung, _ := strconv.ParseFloat(ctx.FormValue("lv_gewichtung"), 64) + c.MaxPunkte.HvMax = hvMax + c.MaxPunkte.LvMax = lvMax + c.MaxPunkte.LvGewichtung = lvGewichtung + c.MaxPunkte.HvGewichtung = hvGewichtung + } + hvPunkte, _ := strconv.ParseFloat(ctx.FormValue("hv_punkte"), 64) + lvPunkte, _ := strconv.ParseFloat(ctx.FormValue("lv_punkte"), 64) + hvProzent := 100.00 / c.MaxPunkte.HvMax * hvPunkte + lvProzent := 100.00 / c.MaxPunkte.LvMax * lvPunkte + hvNote := utils.SetNote(hvProzent) + lvNote := utils.SetNote(lvProzent) + gesamtProzent := hvProzent*c.MaxPunkte.HvGewichtung/100 + lvProzent*c.MaxPunkte.LvGewichtung/100 + gesamtNote := utils.SetNote(gesamtProzent) + return models.Bewertung{ + ID: len(*c.Bewertungen) + 1, + Vorname: string(vorname), + Nachname: string(newName), + HvPunkte: hvPunkte, + HvProzent: hvProzent, + HvNote: int(hvNote), + LvPunkte: lvPunkte, + LvProzent: lvProzent, + LvNote: int(lvNote), + GesamtProzent: gesamtProzent, + GesamtNote: int(gesamtNote), + Gewertet: true, + } +} diff --git a/controllers/render.go b/controllers/render.go new file mode 100644 index 0000000..311fbcf --- /dev/null +++ b/controllers/render.go @@ -0,0 +1,11 @@ +package controllers + +import ( + "echoTest/templates" + + "github.com/labstack/echo/v4" +) + +func (c *Controller) RenderBewertungenRoute(ctx echo.Context) error { + return templates.BewertungenPage(*c.Bewertungen, *c.MaxPunkte).Render(ctx.Request().Context(), ctx.Response().Writer) +} diff --git a/controllers/toggle.go b/controllers/toggle.go new file mode 100644 index 0000000..21df1f5 --- /dev/null +++ b/controllers/toggle.go @@ -0,0 +1,21 @@ +package controllers + +import ( + "echoTest/models" + "strconv" + + "github.com/labstack/echo/v4" +) + +func (c *Controller) ToggleWertungRoute(ctx echo.Context) error { + id, _ := strconv.Atoi(ctx.Param("id")) + var updatedBewertung models.Bewertung + for i, bewertung := range *c.Bewertungen { + if bewertung.ID == id { + (*c.Bewertungen)[i].Gewertet = !bewertung.Gewertet + updatedBewertung = (*c.Bewertungen)[i] + break + } + } + return c.CreateBewertungNode(updatedBewertung).Render(ctx.Request().Context(), ctx.Response().Writer) +} diff --git a/go.mod b/go.mod index 22ce536..ffc4fd9 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module echoTest go 1.21.5 require ( + github.com/a-h/templ v0.2.793 github.com/chasefleming/elem-go v0.27.0 github.com/jung-kurt/gofpdf v1.16.2 github.com/labstack/echo/v4 v4.12.0 diff --git a/go.sum b/go.sum index 39e1a2d..11221ed 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ +github.com/a-h/templ v0.2.793 h1:Io+/ocnfGWYO4VHdR0zBbf39PQlnzVCVVD+wEEs6/qY= +github.com/a-h/templ v0.2.793/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/chasefleming/elem-go v0.16.0 h1:kAmR/1tIdnkuEogtG6zDLAWHM7hGbpuD2wjPtbJSHoY= -github.com/chasefleming/elem-go v0.16.0/go.mod h1:hz73qILBIKnTgOujnSMtEj20/epI+f6vg71RUilJAA4= github.com/chasefleming/elem-go v0.27.0 h1:rJhkr7CZuUhx0dN7QAgdKqL+F9Eu5PRTXNxm06h4/9Y= github.com/chasefleming/elem-go v0.27.0/go.mod h1:hz73qILBIKnTgOujnSMtEj20/epI+f6vg71RUilJAA4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -8,11 +8,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc= github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0= -github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= -github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= @@ -34,28 +34,18 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/main.go b/main.go index 4ba7ccd..5cef2ba 100644 --- a/main.go +++ b/main.go @@ -1,47 +1,17 @@ package main import ( - "fmt" - "net/http" - "os" - "os/exec" - "runtime" - "strconv" - - "github.com/chasefleming/elem-go" - "github.com/chasefleming/elem-go/attrs" - "github.com/chasefleming/elem-go/htmx" - "github.com/jung-kurt/gofpdf" + "echoTest/controllers" + "echoTest/models" + "echoTest/utils" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" ) -type Bewertung struct { - Vorname string - Nachname string - ID int - HvPunkte float64 - HvProzent float64 - HvNote int - LvPunkte float64 - LvProzent float64 - LvNote int - GesamtProzent float64 - GesamtNote int - Gewertet bool -} - -type MaxPunkte struct { - HvMax float64 - LvMax float64 - HvGewichtung float64 - LvGewichtung float64 -} - var ( - bewertungen []Bewertung - maxPunkte = MaxPunkte{ + bewertungen []models.Bewertung + maxPunkte = models.MaxPunkte{ HvMax: 0.00, HvGewichtung: 0.00, LvMax: 0.00, @@ -51,452 +21,21 @@ var ( func main() { e := echo.New() - e.Use(middleware.Logger()) e.Use(middleware.Recover()) - e.GET("/", renderBewertungenRoute) - e.POST("/toggle/:id", toggleWertungRoute) - e.POST("/add", addBewertungRoute) - e.GET("/export", exportBewertungenRoute) - e.GET("/end", endRoute) + controller := controllers.NewController(&bewertungen, &maxPunkte) + + e.GET("/", controller.RenderBewertungenRoute) + e.POST("/toggle/:id", controller.ToggleWertungRoute) + e.POST("/add", controller.AddBewertungRoute) + e.GET("/export", controller.ExportBewertungenRoute) + e.GET("/end", controller.EndRoute) go func() { e.Logger.Fatal(e.Start(":3000")) }() - openInBrowser("http://localhost:3000") - + utils.OpenInBrowser("http://localhost:3000") select {} } - -func renderBewertungenRoute(c echo.Context) error { - return c.HTML(http.StatusOK, renderBewertungen(bewertungen)) -} - -func toggleWertungRoute(c echo.Context) error { - id, _ := strconv.Atoi(c.Param("id")) - var updatedBewertung Bewertung - for i, bewertung := range bewertungen { - if bewertung.ID == id { - bewertungen[i].Gewertet = !bewertung.Gewertet - updatedBewertung = bewertungen[i] - break - } - } - return c.HTML(http.StatusOK, createBewertungNode(updatedBewertung).Render()) -} - -func addBewertungRoute(c echo.Context) error { - new := parseBewertungen(c) - if new.Nachname != "" { - bewertungen = append(bewertungen, new) - } - return c.Redirect(http.StatusSeeOther, "/") -} - -func parseBewertungen(c echo.Context) Bewertung { - newName := validateName(c) - vorname := c.FormValue("vorname") - if maxPunkte.HvMax == 0.00 { - hvMax, _ := strconv.ParseFloat(c.FormValue("hv_max"), 64) - lvMax, _ := strconv.ParseFloat(c.FormValue("lv_max"), 64) - hvGewichtung, _ := strconv.ParseFloat(c.FormValue("hv_gewichtung"), 64) - lvGewichtung, _ := strconv.ParseFloat(c.FormValue("lv_gewichtung"), 64) - maxPunkte.HvMax = hvMax - maxPunkte.LvMax = lvMax - maxPunkte.LvGewichtung = lvGewichtung - maxPunkte.HvGewichtung = hvGewichtung - } - hvPunkte, _ := strconv.ParseFloat(c.FormValue("hv_punkte"), 64) - lvPunkte, _ := strconv.ParseFloat(c.FormValue("lv_punkte"), 64) - hvProzent := 100.00 / maxPunkte.HvMax * hvPunkte - lvProzent := 100.00 / maxPunkte.LvMax * lvPunkte - hvNote := setNote(hvProzent) - lvNote := setNote(lvProzent) - gesamtProzent := hvProzent*maxPunkte.HvGewichtung/100 + lvProzent*maxPunkte.LvGewichtung/100 - gesamtNote := setNote(gesamtProzent) - - return Bewertung{ - ID: len(bewertungen) + 1, - Vorname: string(vorname), - Nachname: string(newName), - HvPunkte: hvPunkte, - HvProzent: hvProzent, - HvNote: int(hvNote), - LvPunkte: lvPunkte, - LvProzent: lvProzent, - LvNote: int(lvNote), - GesamtProzent: gesamtProzent, - GesamtNote: int(gesamtNote), - Gewertet: true, - } -} - -func updateGewertetRoute(bewertung Bewertung) elem.Node { - checkbox := elem.Input(attrs.Props{ - attrs.Type: "checkbox", - attrs.Checked: strconv.FormatBool(bewertung.Gewertet), - htmx.HXPost: "/toggle/" + strconv.Itoa(bewertung.ID), - htmx.HXTarget: "#bewertung-" + strconv.Itoa(bewertung.ID), - }) - return checkbox -} - -func createBewertungNode(bewertung Bewertung) elem.Node { - checkbox := elem.Input(attrs.Props{ - attrs.Type: "checkbox", - attrs.Checked: strconv.FormatBool(bewertung.Gewertet), - htmx.HXPost: "/toggle/" + strconv.Itoa(bewertung.ID), - htmx.HXTarget: "#bewertung-" + strconv.Itoa(bewertung.ID), - htmx.HXSwap: "outerHTML", - }) - - return elem.Tr(attrs.Props{ - attrs.ID: "bewertung-" + strconv.Itoa(bewertung.ID), - }, - elem.Td(nil, checkbox), - elem.Td(nil, elem.Text(bewertung.Vorname)), - elem.Td(nil, elem.Text(bewertung.Nachname)), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.HvPunkte, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.HvProzent, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.Itoa(bewertung.HvNote))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.LvPunkte, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.LvProzent, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.Itoa(bewertung.LvNote))), - elem.Td(nil, elem.Text(strconv.FormatFloat(bewertung.GesamtProzent, 'f', 2, 64))), - elem.Td(nil, elem.Text(strconv.Itoa(bewertung.GesamtNote))), - ) -} - -func renderBewertungen(bewertungen []Bewertung) string { - inputPunkte := elem.Div(nil) - if maxPunkte.HvGewichtung == 0.00 { - inputPunkte = elem.Div(attrs.Props{attrs.Class: "tile is-ancestor"}, - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_max", - attrs.Placeholder: "HV-Max-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_gewichtung", - attrs.Placeholder: "HV-Gewichtung in %", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_max", - attrs.Placeholder: "LV-Max-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_gewichtung", - attrs.Placeholder: "LV-Gewichtung in %", - }, - ), - ), - ) - } else { - inputPunkte = elem.Div(attrs.Props{attrs.Class: "tile is-ancestor"}, - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_max", - attrs.Placeholder: "HV-Max-Punkte", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.HvMax), - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "hv_gewichtung", - attrs.Placeholder: "HV-Gewichtung in %", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.HvGewichtung), - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_max", - attrs.Placeholder: "LV-Max-Punkte", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.LvMax), - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Class: "input is-child", - attrs.Type: "text", - attrs.Name: "lv_gewichtung", - attrs.Placeholder: "LV-Gewichtung in %", - attrs.Value: fmt.Sprintf("%.2f", maxPunkte.LvGewichtung), - }, - ), - ), - ) - } - - headContent := elem.Head(nil, - elem.Meta(attrs.Props{attrs.Charset: "UTF-8", attrs.Name: "viewport", attrs.Content: "width=device-width, initial-scale=1.0"}), - elem.Script(attrs.Props{attrs.Src: "https://unpkg.com/htmx.org"}), - elem.Link(attrs.Props{attrs.Rel: "stylesheet", attrs.Href: "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"}), - ) - - headerContent := elem.Header(attrs.Props{ - attrs.Class: "navbar", - attrs.Role: "navigation", - attrs.AriaLabel: "main navigation", - }, - elem.Div(attrs.Props{ - attrs.ID: "navbarBasicExample", - attrs.Class: "navbar-menu", - }, - elem.Div(attrs.Props{ - attrs.Class: "navbar-start", - }, - elem.A(attrs.Props{ - attrs.Class: "navbar-item", - }, elem.Text("Home"), - ), - ), - elem.Div(attrs.Props{ - attrs.Class: "navbar-end", - }, - elem.Span(attrs.Props{ - attrs.Class: "navbar-item", - }, - elem.Button(attrs.Props{ - attrs.Class: "button is-primary", - htmx.HXTrigger: "click", - htmx.HXGet: "/end", - }, elem.Text("Beenden"), - ), - ), - ), - ), - ) - - bodyContent := elem.Div(attrs.Props{attrs.Class: "container is-widescreen"}, - elem.Div(attrs.Props{attrs.Class: "card tile is-vertical is-ancestor"}, - elem.Header(attrs.Props{attrs.Class: "card-header"}, - elem.P(attrs.Props{attrs.Class: "card-header-title"}, elem.Text("Englischarbeit"))), - elem.Div(attrs.Props{attrs.Class: "card-content"}, - elem.Div(attrs.Props{attrs.Class: "content tile is-parent is-vertical gap"}, - elem.H1(attrs.Props{attrs.Class: "tilte"}, elem.Text("Bewertungen")), - elem.Form(attrs.Props{attrs.Method: "post", attrs.Action: "/add"}, inputPunkte, - elem.Div(attrs.Props{attrs.Class: "tile is-ancestor"}, - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "vorname", - attrs.Class: "input is-child", - attrs.Placeholder: "Vorname", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "nachname", - attrs.Class: "input is-child", - attrs.Placeholder: "Nachname", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "hv_punkte", - attrs.Class: "input is-child", - attrs.Placeholder: "HV-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Input(attrs.Props{ - attrs.Type: "text", - attrs.Name: "lv_punkte", - attrs.Class: "input is-child", - attrs.Placeholder: "LV-Punkte", - }, - ), - ), - elem.Div(attrs.Props{attrs.Class: "tile field is-parent"}, - elem.Button( - attrs.Props{ - attrs.Type: "submit", - attrs.Class: "button tile is-child", - }, - elem.Text("Add"), - ), - ), - ), - ), - elem.Div(attrs.Props{attrs.Class: "table-container"}, - elem.Table(attrs.Props{attrs.Class: "table is-hoverable"}, - elem.THead(nil, - elem.Tr(nil, - elem.Th(nil, elem.Text("Gewertet")), - elem.Th(nil, elem.Text("Vorname")), - elem.Th(nil, elem.Text("Nachname")), - elem.Th(nil, elem.Text("HV-Punkte")), - elem.Th(nil, elem.Text("HV-Prozent")), - elem.Th(nil, elem.Text("HV-Note")), - elem.Th(nil, elem.Text("LV-Punkte")), - elem.Th(nil, elem.Text("LV-Prozent")), - elem.Th(nil, elem.Text("LV-Note")), - elem.Th(nil, elem.Text("Gesamt-Prozent")), - elem.Th(nil, elem.Text("Gesamt-Note")), - ), - ), - elem.TBody(nil, - elem.TransformEach(bewertungen, createBewertungNode)...), - ), - ), - elem.Div(nil, - elem.Button(attrs.Props{ - htmx.HXTrigger: "click", - htmx.HXGet: "/export", - attrs.Class: "button", - }, - elem.Text("export"), - ), - ), - ), - ), - ), - ) - footerContent := elem.Footer(attrs.Props{ - attrs.Class: "footer", - }, - elem.Div(attrs.Props{ - attrs.Class: "content has-text-centered", - }, - elem.P(nil, elem.Text("© 2023 Alle Rechte vorbehalten.")), - ), - ) - - tbodyContent := elem.TBody(nil) - htmlContent := elem.Html(nil, elem.Raw(""), headContent, headerContent, bodyContent, tbodyContent, footerContent) - - return htmlContent.Render() -} - -func setNote(prozent float64) float64 { - switch { - case prozent <= 22: - return 6.00 - case prozent <= 49: - return 5.00 - case prozent <= 64: - return 4.00 - case prozent <= 79: - return 3.00 - case prozent <= 94: - return 2.00 - default: - return 1.00 - } -} - -func checkGewichtung(lv, hv float64) bool { - if hv/100+lv/100 > 1 { - return false - } else if hv/100+lv/100 < 1 { - return false - } - return true -} - -// Die Funktion zum Öffnen des Standardbrowsers -func openInBrowser(url string) { - var cmd *exec.Cmd - - switch os := runtime.GOOS; os { - case "darwin": - // macOS - cmd = exec.Command("open", url) - case "windows": - // Windows - cmd = exec.Command("cmd", "/c", "start", url) - default: - // Linux und andere - cmd = exec.Command("xdg-open", url) - } - - err := cmd.Start() - if err != nil { - fmt.Println("Fehler beim Öffnen des Browsers:", err) - } -} - -func validateName(c echo.Context) string { - newNachname := c.FormValue("nachname") - newVorname := c.FormValue("vorname") - for _, bewertung := range bewertungen { - fmt.Printf("Name: %v", bewertung.Nachname) - if bewertung.Nachname == newNachname && bewertung.Vorname == newVorname { - return "" - } - } - return newNachname -} - -func exportBewertungenRoute(c echo.Context) error { - pdf := gofpdf.New("P", "mm", "A4", "") - pdf.AddPage() - - pdf.SetFont("Arial", "B", 12) - pdf.CellFormat(27, 10, "Vorname", "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, "Nachname", "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, "HV-Punkte", "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, "HV-Note", "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, "LV-Punkte", "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, "LV-Note", "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, "Gesamtnote", "1", 0, "", false, 0, "") - pdf.Ln(-1) - - pdf.SetFont("Arial", "", 11) - for _, bewertung := range bewertungen { - pdf.CellFormat(27, 10, bewertung.Vorname, "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, bewertung.Nachname, "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, strconv.FormatFloat(bewertung.HvPunkte, 'f', 2, 64), "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, strconv.FormatInt(int64(bewertung.HvNote), 10), "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, strconv.FormatFloat(bewertung.LvPunkte, 'f', 2, 64), "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, strconv.FormatInt(int64(bewertung.LvNote), 10), "1", 0, "", false, 0, "") - pdf.CellFormat(27, 10, strconv.FormatInt(int64(bewertung.GesamtNote), 10), "1", 0, "", false, 0, "") - pdf.Ln(-1) - } - - err := pdf.OutputFileAndClose("bewertungen.pdf") - if err != nil { - fmt.Println("Fehler beim Exportieren der Bewertungen:", err) - return err - } - - return c.HTML(http.StatusOK, "Export beendet") -} - -func endRoute(c echo.Context) error { - os.Exit(0) - return c.HTML(http.StatusOK, "Tschüss") -} diff --git a/main_test.go b/main_test.go deleted file mode 100644 index a9c4a36..0000000 --- a/main_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/labstack/echo/v4" - "github.com/stretchr/testify/assert" -) - -func TestRenderBewertungenRoute(t *testing.T) { - e := echo.New() - req := httptest.NewRequest(http.MethodGet, "/", nil) - rec := httptest.NewRecorder() - c := e.NewContext(req, rec) - - err := renderBewertungenRoute(c) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, rec.Code) -} - -func TestToggleWertungRoute(t *testing.T) { - e := echo.New() - req := httptest.NewRequest(http.MethodPost, "/toggle/1", nil) - rec := httptest.NewRecorder() - c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues("1") - - err := toggleWertungRoute(c) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, rec.Code) -} diff --git a/model/bewertung.go b/models/bewertung.go similarity index 66% rename from model/bewertung.go rename to models/bewertung.go index 6ad0e79..889d723 100644 --- a/model/bewertung.go +++ b/models/bewertung.go @@ -1,6 +1,5 @@ -package model +package models -// Todo model type Bewertung struct { Vorname string Nachname string @@ -15,10 +14,3 @@ type Bewertung struct { GesamtNote int Gewertet bool } - -type MaxPunkte struct { - HvMax float64 - LvMax float64 - HvGewichtung float64 - LvGewichtung float64 -} diff --git a/models/maxpunkte.go b/models/maxpunkte.go new file mode 100644 index 0000000..32f7c6e --- /dev/null +++ b/models/maxpunkte.go @@ -0,0 +1,8 @@ +package models + +type MaxPunkte struct { + HvMax float64 + LvMax float64 + HvGewichtung float64 + LvGewichtung float64 +} diff --git a/templates/templates.templ b/templates/templates.templ new file mode 100644 index 0000000..183d764 --- /dev/null +++ b/templates/templates.templ @@ -0,0 +1,147 @@ +package templates + +import ( +"strconv" +"fmt" +"echoTest/models" +) + +templ layout(title string) { + + + + + + + {title} + + + + + + +
+ {children...} +
+ + + + +} + +templ BewertungenForm(maxPunkte models.MaxPunkte) { +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+} + +templ BewertungenTable(bewertungen []models.Bewertung) { +
+ + + + + + + + + + + + + + + + + + for _, b := range bewertungen { + + + + + + + + + + + + + + } + +
GewertetVornameNachnameHV-PunkteHV-ProzentHV-NoteLV-PunkteLV-ProzentLV-NoteGesamt-ProzentGesamt-Note
+ + {b.Vorname}{b.Nachname}{fmt.Sprintf("%.2f", b.HvPunkte)}{fmt.Sprintf("%.2f", b.HvProzent)}{strconv.Itoa(b.HvNote)}{fmt.Sprintf("%.2f", b.LvPunkte)}{fmt.Sprintf("%.2f", b.LvProzent)}{strconv.Itoa(b.LvNote)}{fmt.Sprintf("%.2f", b.GesamtProzent)}{strconv.Itoa(b.GesamtNote)}
+
+} + +templ BewertungenPage(bewertungen []models.Bewertung, maxPunkte models.MaxPunkte) { +@layout("Englischarbeit") { +
+
+

Englischarbeit

+
+
+
+

Bewertungen

+ @BewertungenForm(maxPunkte) + @BewertungenTable(bewertungen) +
+ +
+
+
+
+} +} diff --git a/templates/templates_templ.go b/templates/templates_templ.go new file mode 100644 index 0000000..5cfbe54 --- /dev/null +++ b/templates/templates_templ.go @@ -0,0 +1,427 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.793 +package templates + +//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 ( + "echoTest/models" + "fmt" + "strconv" +) + +func layout(title string) 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_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 16, Col: 15} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func BewertungenForm(maxPunkte models.MaxPunkte) 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_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func BewertungenTable(bewertungen []models.Bewertung) 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_Var8 := templ.GetChildren(ctx) + if templ_7745c5c3_Var8 == nil { + templ_7745c5c3_Var8 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, b := range bewertungen { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
GewertetVornameNachnameHV-PunkteHV-ProzentHV-NoteLV-PunkteLV-ProzentLV-NoteGesamt-ProzentGesamt-Note
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(b.Vorname) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 112, Col: 22} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(b.Nachname) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 113, Col: 23} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var14 string + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f", b.HvPunkte)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 114, Col: 44} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f", b.HvProzent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 115, Col: 45} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var16 string + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(b.HvNote)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 116, Col: 35} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var17 string + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f", b.LvPunkte)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 117, Col: 44} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f", b.LvProzent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 118, Col: 45} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(b.LvNote)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 119, Col: 35} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var20 string + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f", b.GesamtProzent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 120, Col: 49} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var21 string + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(b.GesamtNote)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/templates.templ`, Line: 121, Col: 39} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func BewertungenPage(bewertungen []models.Bewertung, maxPunkte models.MaxPunkte) 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_Var22 := templ.GetChildren(ctx) + if templ_7745c5c3_Var22 == nil { + templ_7745c5c3_Var22 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var23 := 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) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Englischarbeit

Bewertungen

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = BewertungenForm(maxPunkte).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = BewertungenTable(bewertungen).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout("Englischarbeit").Render(templ.WithChildren(ctx, templ_7745c5c3_Var23), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/utils.go b/utils.go deleted file mode 100644 index 06ab7d0..0000000 --- a/utils.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..31a90a7 --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,64 @@ +package utils + +import ( + "echoTest/models" + "fmt" + "os/exec" + "runtime" + + "github.com/labstack/echo/v4" +) + +func SetNote(prozent float64) float64 { + switch { + case prozent <= 22: + return 6.00 + case prozent <= 49: + return 5.00 + case prozent <= 64: + return 4.00 + case prozent <= 79: + return 3.00 + case prozent <= 94: + return 2.00 + default: + return 1.00 + } +} + +func CheckGewichtung(lv, hv float64) bool { + if hv/100+lv/100 > 1 { + return false + } else if hv/100+lv/100 < 1 { + return false + } + return true +} + +func OpenInBrowser(url string) { + var cmd *exec.Cmd + switch os := runtime.GOOS; os { + case "darwin": + cmd = exec.Command("open", url) + case "windows": + cmd = exec.Command("cmd", "/c", "start", url) + default: + cmd = exec.Command("xdg-open", url) + } + err := cmd.Start() + if err != nil { + fmt.Println("Fehler beim Öffnen des Browsers:", err) + } +} + +func ValidateName(c echo.Context, bewertungen *[]models.Bewertung) string { + newNachname := c.FormValue("nachname") + newVorname := c.FormValue("vorname") + for _, bewertung := range *bewertungen { + fmt.Printf("Name: %v", bewertung.Nachname) + if bewertung.Nachname == newNachname && bewertung.Vorname == newVorname { + return "" + } + } + return newNachname +}