From 6599839c145a6bf67bd806a9c400a605f89c37dd Mon Sep 17 00:00:00 2001
From: Aleksandr Muravja <aleks.muravja@gmail.com>
Date: Sat, 1 Mar 2025 09:31:34 +0100
Subject: [PATCH] Moved to templates

---
 .dockerignore                     |   4 +-
 .gitignore                        |   2 +
 server.go                         | 124 ++++++++++++++++++++++++++----
 statik/css/main.css               |   2 +-
 templates/elements/work-item.html |   7 ++
 templates/index.html              |   4 +-
 templates/layouts/base.html       |   6 +-
 templates/parts/footer.html       |   5 ++
 templates/works.html              |  13 ++++
 9 files changed, 145 insertions(+), 22 deletions(-)
 create mode 100644 templates/elements/work-item.html
 create mode 100644 templates/parts/footer.html
 create mode 100644 templates/works.html

diff --git a/.dockerignore b/.dockerignore
index f62f0b7..d55eba6 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -7,4 +7,6 @@
 # Adding Templates
 !templates
 # Additing Statik Files
-!statik
\ No newline at end of file
+!statik
+# Adding templates folder
+!templates
diff --git a/.gitignore b/.gitignore
index b15297d..eeae4bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,5 @@ nbdist/
 #KDE files
 .directory
 
+# Binary files
+varrior
diff --git a/server.go b/server.go
index 258bfbe..885b99b 100644
--- a/server.go
+++ b/server.go
@@ -8,21 +8,40 @@ import (
 	"log"
 	"net/http"
 	"os"
+	"path/filepath"
 )
 
 // PageData holds the data to be passed to the HTML template.
 type PageData struct {
+	Title string
+}
+
+type IndexPageData struct {
+	PageData
 	MyVarValue string
 }
 
+type WorkPageData struct {
+	PageData
+	Name  string
+	Works []Work
+}
+
+type Work struct {
+	Name string
+	URL  string
+}
+
 const (
+	elementsDir  = "templates/elements"
 	layoutsDir   = "templates/layouts"
+	partsDir     = "templates/parts"
 	templatesDir = "templates"
 	extension    = "/*.html"
 )
 
 var (
-	//go:embed templates/* templates/layouts/* statik/css/*
+	//go:embed templates/* templates/elements/*  templates/layouts/* templates/parts/* statik/css/*
 	files     embed.FS
 	templates map[string]*template.Template
 )
@@ -36,15 +55,12 @@ func init() {
 }
 
 func main() {
-	statikFS, err := fs.Sub(files, "statik")
-	if err != nil {
-		log.Fatal(err)
-	}
 
 	// Define a handler function for the root endpoint ("/").
 	http.HandleFunc("/", HomePage)
+	http.HandleFunc("/works", WorksPage)
 	// Serving Static Files as well
-	http.Handle("/statik", http.FileServer(http.FS(statikFS)))
+	http.HandleFunc("/statik/", serveStatic)
 
 	// Define the port to listen on.
 	port := ":1234"
@@ -53,7 +69,7 @@ func main() {
 	log.Printf("Starting server on %s...", port)
 
 	// Start the HTTP server.
-	err = http.ListenAndServe(port, nil)
+	err := http.ListenAndServe(port, nil)
 	if err != nil {
 		log.Fatal("Server error:", err)
 	}
@@ -72,7 +88,8 @@ func loadTemplates() error {
 			continue
 		}
 
-		pt, err := template.ParseFS(files, templatesDir+"/"+tmpl.Name(), layoutsDir+extension)
+		pt, err := template.ParseFS(files, templatesDir+"/"+tmpl.Name(),
+			layoutsDir+extension, partsDir+extension, elementsDir+extension)
 		if err != nil {
 			return err
 		}
@@ -83,25 +100,35 @@ func loadTemplates() error {
 }
 
 const homePage = "index.html"
+const worksPage = "works.html"
 
-func HomePage(w http.ResponseWriter, _ *http.Request) {
-	t, ok := templates[homePage]
+func renderTemplate(w http.ResponseWriter, tmplName string, data any) {
+	t, ok := templates[tmplName]
 	if !ok {
-		log.Printf("template %s not found", homePage)
+		log.Printf("template %s not found", tmplName)
+		http.Error(w, "Template not found", http.StatusNotFound)
 		return
 	}
-	// Define the data to be passed to the HTML template.
-	data := readVar()
 
-	// Execute the template and write the result to the response.
 	if err := t.Execute(w, data); err != nil {
 		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
 		log.Printf("Error executing template: %v", err)
 		return
 	}
+	log.Printf("Serving Template: %s", tmplName)
+}
+
+func HomePage(w http.ResponseWriter, r *http.Request) {
+	data := readVar()
+	renderTemplate(w, homePage, data)
+}
+
+func WorksPage(w http.ResponseWriter, r *http.Request) {
+	data := readMyWorks()
+	renderTemplate(w, worksPage, data)
 }
 
-func readVar() PageData {
+func readVar() IndexPageData {
 	// Get the value of the environment variable "MY_VAR".
 	myVarValue := os.Getenv("MY_VAR")
 
@@ -111,8 +138,73 @@ func readVar() PageData {
 	}
 
 	// Define the data to be passed to the HTML template.
-	data := PageData{
+	data := IndexPageData{
+		PageData:   PageData{Title: "Home Page"},
 		MyVarValue: myVarValue,
 	}
 	return data
 }
+
+func readMyWorks() WorkPageData {
+	works := []Work{
+		{Name: "KLab.sh", URL: "https://klab.sh"},
+		{Name: "Hop179", URL: "https://hop179.net"},
+	}
+	return WorkPageData{
+		PageData: PageData{Title: "Works Page"},
+		Name:     "Aleks",
+		Works:    works,
+	}
+}
+func serveStatic(w http.ResponseWriter, r *http.Request) {
+	// Extract the correct file path
+	filePath := r.URL.Path[len("/statik/"):]
+	fullPath := "statik/" + filePath
+
+	// Log request details
+	log.Printf("Serving static file: %s", fullPath)
+
+	// Read the file from embedded FS
+	content, err := fs.ReadFile(files, fullPath)
+	if err != nil {
+		log.Printf("Static file not found: %s", err)
+		http.NotFound(w, r)
+		return
+	}
+
+	// Set the correct Content-Type
+	mimeType := detectMimeType(filePath)
+	w.Header().Set("Content-Type", mimeType)
+	w.WriteHeader(http.StatusOK)
+
+	// Serve the file content
+	_, writeErr := w.Write(content)
+	if writeErr != nil {
+		log.Printf("Error writing response: %s", writeErr)
+	}
+}
+
+func detectMimeType(file string) string {
+	switch filepath.Ext(file) {
+	case ".css":
+		return "text/css"
+	case ".js":
+		return "application/javascript"
+	case ".png":
+		return "image/png"
+	case ".jpg", ".jpeg":
+		return "image/jpeg"
+	case ".gif":
+		return "image/gif"
+	case ".svg":
+		return "image/svg+xml"
+	case ".woff":
+		return "font/woff"
+	case ".woff2":
+		return "font/woff2"
+	case ".ttf":
+		return "font/ttf"
+	default:
+		return "application/octet-stream"
+	}
+}
diff --git a/statik/css/main.css b/statik/css/main.css
index 6df7dd7..d2db527 100644
--- a/statik/css/main.css
+++ b/statik/css/main.css
@@ -1,3 +1,3 @@
 body {
-    background-color: #54b6fc;
+    background-color: #00fe80;
 }
\ No newline at end of file
diff --git a/templates/elements/work-item.html b/templates/elements/work-item.html
new file mode 100644
index 0000000..6938ddf
--- /dev/null
+++ b/templates/elements/work-item.html
@@ -0,0 +1,7 @@
+{{define "work-item"}}
+<div class="work-item">
+    <h3>{{.Name}}</h3>
+    <p>URL: {{.URL}}</p>
+    <p><a href="{{.URL}}">View</a></p>
+</div>
+{{end}}
diff --git a/templates/index.html b/templates/index.html
index 194b887..fade95b 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -1,6 +1,6 @@
-<!-- Content of index.html: -->
 {{template "base" .}}
 {{define "content"}}
 <h1>Value of MY_VAR: {{.MyVarValue}}</h1>
-{{end}}
+<a href="/works">Test Works</a>
 
+{{end}}
\ No newline at end of file
diff --git a/templates/layouts/base.html b/templates/layouts/base.html
index 2ac561e..643e411 100644
--- a/templates/layouts/base.html
+++ b/templates/layouts/base.html
@@ -1,14 +1,16 @@
 <!-- Content of base.html: -->
 {{define "base"}}
+<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <meta charset="utf-8">
-    <title>Varrior</title>
+    <title>Varrior|{{.Title}}</title>
     <link rel="stylesheet" type="text/css" href="/statik/css/main.css" />
 </head>
 <body>
     {{template "content" .}}
+    {{template "footer"}}
 </body>
 </html>
-{{end}}
+{{end}}
\ No newline at end of file
diff --git a/templates/parts/footer.html b/templates/parts/footer.html
new file mode 100644
index 0000000..0217411
--- /dev/null
+++ b/templates/parts/footer.html
@@ -0,0 +1,5 @@
+{{define "footer"}}
+<footer>
+    <p>Footer</p>
+</footer>
+{{end}}
diff --git a/templates/works.html b/templates/works.html
new file mode 100644
index 0000000..356e06c
--- /dev/null
+++ b/templates/works.html
@@ -0,0 +1,13 @@
+{{template "base" .}}
+{{define "content"}}
+<h1>My Works</h1>
+<a href="/">Home</a></br>
+{{if .Works}}
+<h2>I am {{ .Name }} and I did following projects: </h2></br>
+<ul>
+    {{range .Works}}
+        <li>{{template "work-item" .}}</li>
+    {{end}}
+</ul>
+{{end}}
+{{end}}
\ No newline at end of file
-- 
GitLab