diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..721c661 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +run: + @templ generate + @go run cmd/main.go diff --git a/BSI-Portrait_Lorenz_Q.jpg b/assets/BSI-Portrait_Lorenz_Q.jpg similarity index 100% rename from BSI-Portrait_Lorenz_Q.jpg rename to assets/BSI-Portrait_Lorenz_Q.jpg diff --git a/assets/robot.png b/assets/robot.png new file mode 100644 index 0000000..00da917 Binary files /dev/null and b/assets/robot.png differ diff --git a/assets/test.jpg b/assets/test.jpg new file mode 100644 index 0000000..311d563 Binary files /dev/null and b/assets/test.jpg differ diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..87c69d2 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "github.com/labstack/echo/v4" + "github.com/lorenzhohermuth/portfolio/internal/handler" +) + +func main() { + app := echo.New() + + h := handler.Homehandler{} + app.GET("/", h.HandleUserShow) + app.Static("/static", "assets") + + app.Start(":3030") +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4a68653 --- /dev/null +++ b/go.mod @@ -0,0 +1,17 @@ +module github.com/lorenzhohermuth/portfolio + +go 1.22.1 + +require ( + github.com/a-h/templ v0.2.648 // indirect + github.com/labstack/echo/v4 v4.11.4 // indirect + github.com/labstack/gommon v0.4.2 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..707f5c5 --- /dev/null +++ b/go.sum @@ -0,0 +1,25 @@ +github.com/a-h/templ v0.2.648 h1:A1ggHGIE7AONOHrFaDTM8SrqgqHL6fWgWCijQ21Zy9I= +github.com/a-h/templ v0.2.648/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8= +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/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +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.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +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.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= diff --git a/internal/handler/handler.go b/internal/handler/handler.go new file mode 100644 index 0000000..7783fde --- /dev/null +++ b/internal/handler/handler.go @@ -0,0 +1,12 @@ +package handler + +import ( + "github.com/labstack/echo/v4" + "github.com/lorenzhohermuth/portfolio/view/page" +) + +type Homehandler struct {} + +func(h Homehandler) HandleUserShow(ctx echo.Context) error { + return render(ctx, page.ShowHome()) +} diff --git a/internal/handler/util.go b/internal/handler/util.go new file mode 100644 index 0000000..0c45c7a --- /dev/null +++ b/internal/handler/util.go @@ -0,0 +1,10 @@ +package handler + +import ( + "github.com/a-h/templ" + "github.com/labstack/echo/v4" +) + +func render(ctx echo.Context, component templ.Component) error { + return component.Render(ctx.Request().Context(), ctx.Response()) +} diff --git a/view/component/carousel.templ b/view/component/carousel.templ new file mode 100644 index 0000000..5cfac60 --- /dev/null +++ b/view/component/carousel.templ @@ -0,0 +1,22 @@ +package component + +type CarouselEntry struct { + ImgPath string + Title string + Text string +} + +templ Carousel(elm CarouselEntry) { + <div> + <div class="flex items-center gap-x-4"> + <button type="button" class="h-32 w-8 font-black rounded bg-black/20 border-none"> < </button> + <div class="relative text-center"> + <img src={elm.ImgPath} class="h-36 w-64 rounded object-cover"/> + <div class="bg-gradient-to-t from-black/80 absolute bottom-0 left-0 h-36 w-64 rounded"></div> + <p class="absolute text-neutral-300 bottom-0.5 left-5">{elm.Title}</p> + </div> + <button type="button" class="h-32 w-8 font-black rounded bg-black/20 border-none"> > </button> + </div> + <p class="text-center font-thin">{elm.Text}</p> + </div> +} diff --git a/view/component/carousel_templ.go b/view/component/carousel_templ.go new file mode 100644 index 0000000..40491a9 --- /dev/null +++ b/view/component/carousel_templ.go @@ -0,0 +1,80 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.650 +package component + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +type CarouselEntry struct { + ImgPath string + Title string + Text string +} + +func Carousel(elm CarouselEntry) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + 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("<div><div class=\"flex items-center gap-x-4\"><button type=\"button\" class=\"h-32 w-8 font-black rounded bg-black/20 border-none\">< </button><div class=\"relative text-center\"><img src=\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(elm.ImgPath) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/component/carousel.templ`, Line: 14, Col: 25} + } + _, 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("\" class=\"h-36 w-64 rounded object-cover\"><div class=\"bg-gradient-to-t from-black/80 absolute bottom-0 left-0 h-36 w-64 rounded\"></div><p class=\"absolute text-neutral-300 bottom-0.5 left-5\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(elm.Title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/component/carousel.templ`, Line: 16, Col: 69} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div><button type=\"button\" class=\"h-32 w-8 font-black rounded bg-black/20 border-none\">> </button></div><p class=\"text-center font-thin\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(elm.Text) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/component/carousel.templ`, Line: 20, Col: 44} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} diff --git a/view/layout/base.templ b/view/layout/base.templ new file mode 100644 index 0000000..75fe307 --- /dev/null +++ b/view/layout/base.templ @@ -0,0 +1,43 @@ +package layout + +templ Base() { + <!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="UTF-8"/> + <meta name="viewport" content="width=device-width, initial-scale=1.0"/> + <title>Portfolio Lorenz Hohermuth</title> + <script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"></script> + </head> + <body class="m-0 p-0 font-mono font-black"> + + <nav class="flex w-full"> + <div class="bg-orange-500 w-35 flex justify-center"> + <img src="/static/robot.png" height="70"/> + </div> + <div class="container bg-[#3331ee]"> + <ul class="flex items-center justify-center h-full gap-x-4 p-0 list-none m-0"> + <li><a class="no-underline text-[#ff5cdb]" href="#home">Home</a></li> + <li><a class="no-underline text-[#ff5cdb]" href="#projects">Projects</a></li> + <li><a class="no-underline text-[#ff5cdb]" href="#contact">Work</a></li> + </ul> + </div> + </nav> + + <main> + { children... } + </main> + + <footer class="flex text-xs font-thin"> + <div class="bg-gray-500 text-gray-400 p-2 w-1/2 flex justify-center items-center"> + <p>© 2024 Lorenz Hohermuth All rights reserved.</p> + </div> + <div class="bg-gray-800 w-1/2 text-neutral-300 flex justify-center items-center"> + <p> -- <a class=" text-neutral-300" href="https://github.com/lorenzhohermuth">GitHUB</a> -- </p> + </div> + </footer> + + </body> + </html> + +} diff --git a/view/layout/base_templ.go b/view/layout/base_templ.go new file mode 100644 index 0000000..a18349f --- /dev/null +++ b/view/layout/base_templ.go @@ -0,0 +1,43 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.650 +package layout + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +func Base() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + 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("<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Portfolio Lorenz Hohermuth</title><script src=\"https://cdn.jsdelivr.net/npm/@unocss/runtime\"></script></head><body class=\"m-0 p-0 font-mono font-black\"><nav class=\"flex w-full\"><div class=\"bg-orange-500 w-35 flex justify-center\"><img src=\"/static/robot.png\" height=\"70\"></div><div class=\"container bg-[#3331ee]\"><ul class=\"flex items-center justify-center h-full gap-x-4 p-0 list-none m-0\"><li><a class=\"no-underline text-[#ff5cdb]\" href=\"#home\">Home</a></li><li><a class=\"no-underline text-[#ff5cdb]\" href=\"#projects\">Projects</a></li><li><a class=\"no-underline text-[#ff5cdb]\" href=\"#contact\">Work</a></li></ul></div></nav><main>") + 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("</main><footer class=\"flex text-xs font-thin\"><div class=\"bg-gray-500 text-gray-400 p-2 w-1/2 flex justify-center items-center\"><p>© 2024 Lorenz Hohermuth All rights reserved.</p></div><div class=\"bg-gray-800 w-1/2 text-neutral-300 flex justify-center items-center\"><p>-- <a class=\" text-neutral-300\" href=\"https://github.com/lorenzhohermuth\">GitHUB</a> -- </p></div></footer></body></html>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} diff --git a/view/page/home.templ b/view/page/home.templ new file mode 100644 index 0000000..33bc55d --- /dev/null +++ b/view/page/home.templ @@ -0,0 +1,20 @@ +package page + +import "github.com/lorenzhohermuth/portfolio/view/layout" +import "github.com/lorenzhohermuth/portfolio/view/component" + +templ ShowHome() { + @layout.Base(){ + <div class="h-80 bg-[#cdb4f6] flex justify-center items-center"> + Intro + </div> + + <div class="h-80 bg-[#ff5cdb] flex justify-center items-center"> + @component.Carousel(component.CarouselEntry{"/static/test.jpg", "This is a Tree" , "I like Trees"}) + </div> + + <div class="h-80 bg-[#1733d2] flex justify-center items-center"> + Work + </div> + } +} diff --git a/view/page/home_templ.go b/view/page/home_templ.go new file mode 100644 index 0000000..109c53a --- /dev/null +++ b/view/page/home_templ.go @@ -0,0 +1,61 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.650 +package page + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +import "github.com/lorenzhohermuth/portfolio/view/layout" +import "github.com/lorenzhohermuth/portfolio/view/component" + +func ShowHome() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + 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 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"h-80 bg-[#cdb4f6] flex justify-center items-center\">Intro</div><div class=\"h-80 bg-[#ff5cdb] flex justify-center items-center\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = component.Carousel(component.CarouselEntry{"/static/test.jpg", "This is a Tree", "I like Trees"}).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div class=\"h-80 bg-[#1733d2] flex justify-center items-center\">Work</div>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer) + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = layout.Base().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +}