package api
import (
"context"
"fmt"
"html/template"
"io/fs"
"log"
"net/http"
"sprintpadawan/lib"
)
var templates *template.Template
func InitTemplates(fsys fs.FS) {
templates = template.Must(template.New("").Funcs(template.FuncMap{
"scaleToOptions": scaleToOptions,
"derefInt": func(i *int) int {
if i == nil {
return 0
}
return *i
},
"slice": func(s string, start, end int) string {
if len(s) == 0 {
return ""
}
if start < 0 {
start = 0
}
if end > len(s) || end <= 0 {
end = len(s)
}
if start > end {
return ""
}
return s[start:end]
},
"dict": func(values ...interface{}) (map[string]interface{}, error) {
if len(values)%2 != 0 {
return nil, fmt.Errorf("odd number of arguments to dict")
}
d := make(map[string]interface{})
for i := 0; i < len(values); i += 2 {
key, ok := values[i].(string)
if !ok {
return nil, fmt.Errorf("dict keys must be strings")
}
d[key] = values[i+1]
}
return d, nil
},
}).ParseFS(fsys, "templates/*.html"))
}
func isHTMX(r *http.Request) bool {
return r.Header.Get("HX-Request") == "true"
}
func renderTemplate(w http.ResponseWriter, name string, data interface{}) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := templates.ExecuteTemplate(w, name, data); err != nil {
log.Printf("template error (%s): %v", name, err)
http.Error(w, "internal server error", http.StatusInternalServerError)
}
}
func renderRoomStories(w http.ResponseWriter, roomID int, user *lib.User) {
room, err := lib.GetRoomByID(roomID)
if err != nil {
http.Error(w, "room not found", http.StatusNotFound)
return
}
data, err := buildRoomData(room, user)
if err != nil {
http.Error(w, "failed to load room data", http.StatusInternalServerError)
return
}
renderTemplate(w, "stories-panel", data)
}
func renderRoomMembers(w http.ResponseWriter, roomID int, user *lib.User) {
room, err := lib.GetRoomByID(roomID)
if err != nil {
http.Error(w, "room not found", http.StatusNotFound)
return
}
data, err := buildRoomData(room, user)
if err != nil {
http.Error(w, "failed to load room data", http.StatusInternalServerError)
return
}
renderTemplate(w, "members-panel", data)
}
func requireAuth(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("session_token")
if err != nil {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
user, err := lib.GetUserFromSession(cookie.Value)
if err != nil || user == nil {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
ctx := context.WithValue(r.Context(), userKey, user)
next.ServeHTTP(w, r.WithContext(ctx))
}
}
func isLoggedIn(r *http.Request) bool {
cookie, err := r.Cookie("session_token")
if err != nil {
return false
}
user, err := lib.GetUserFromSession(cookie.Value)
return err == nil && user != nil
}