arimelody-web/admin/blog/blog.go

134 lines
3.9 KiB
Go
Raw Normal View History

2025-11-07 01:04:10 +00:00
package blog
import (
"arimelody-web/admin/core"
"arimelody-web/admin/templates"
"arimelody-web/controller"
"arimelody-web/model"
"fmt"
"net/http"
"os"
"slices"
)
func Handler(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
mux := http.NewServeMux()
2025-11-08 14:13:42 +00:00
mux.Handle("/blogs/{id}", serveBlogPost(app))
mux.Handle("/blogs/", serveBlogIndex(app))
2025-11-07 01:04:10 +00:00
mux.ServeHTTP(w, r)
})
}
type (
blogPostCollection struct {
2025-11-07 01:04:10 +00:00
Year int
Posts []*model.BlogPost
2025-11-07 01:04:10 +00:00
}
)
func (c *blogPostCollection) Clone() blogPostCollection {
return blogPostCollection{
Year: c.Year,
Posts: slices.Clone(c.Posts),
}
}
2025-11-07 02:35:51 +00:00
func serveBlogIndex(app *model.AppState) http.Handler {
2025-11-07 01:04:10 +00:00
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2025-11-07 02:35:51 +00:00
session := r.Context().Value("session").(*model.Session)
2025-11-07 01:04:10 +00:00
posts, err := controller.GetBlogPosts(app.DB, false, -1, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog posts: %v\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
collections := []*blogPostCollection{}
collection := blogPostCollection{
Posts: []*model.BlogPost{},
Year: -1,
}
2025-11-07 01:04:10 +00:00
for i, post := range posts {
if i == 0 {
collection.Year = post.PublishDate.Year()
2025-11-07 01:04:10 +00:00
}
if post.PublishDate.Year() != collection.Year {
clone := collection.Clone()
collections = append(collections, &clone)
collection = blogPostCollection{
Year: post.PublishDate.Year(),
Posts: []*model.BlogPost{},
}
2025-11-07 01:04:10 +00:00
}
collection.Posts = append(collection.Posts, post)
2025-11-07 01:04:10 +00:00
if i == len(posts) - 1 {
collections = append(collections, &collection)
2025-11-07 01:04:10 +00:00
}
}
type blogsData struct {
core.AdminPageData
TotalPosts int
Collections []*blogPostCollection
2025-11-07 01:04:10 +00:00
}
err = templates.BlogsTemplate.Execute(w, blogsData{
AdminPageData: core.AdminPageData{
Path: r.URL.Path,
2025-11-07 01:04:10 +00:00
Session: session,
},
TotalPosts: len(posts),
Collections: collections,
})
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Error rendering admin blog index: %v\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
})
}
2025-11-07 02:35:51 +00:00
func serveBlogPost(app *model.AppState) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session := r.Context().Value("session").(*model.Session)
blogID := r.PathValue("id")
post, err := controller.GetBlogPost(app.DB, blogID)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog %s: %v\n", blogID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
if post == nil {
2025-11-07 02:35:51 +00:00
http.NotFound(w, r)
return
}
type blogPostData struct {
core.AdminPageData
Post *model.BlogPost
}
err = templates.EditBlogTemplate.Execute(w, blogPostData{
AdminPageData: core.AdminPageData{
Path: r.URL.Path,
2025-11-07 02:35:51 +00:00
Session: session,
},
Post: post,
})
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Error rendering admin edit page for blog %s: %v\n", blogID, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
})
}