package web
import (
"html/template"
"net/http"
"sort"
"time"
"github.com/domagojzecevic/cammonitor/internal/auth"
"github.com/domagojzecevic/cammonitor/internal/footage"
webtemplates "github.com/domagojzecevic/cammonitor/internal/web/templates"
"github.com/go-chi/chi/v5"
)
type Handler struct {
index *footage.Index
}
type ShellData struct {
Title string
User *auth.User
Months []MonthGroup
CurrentDate string
ActiveTab string
Content any
}
type MonthGroup struct {
Label string
Days []string
}
type DayPageData struct {
Date string
ImageCount int
VideoCount int
}
func NewHandler(index *footage.Index) *Handler {
return &Handler{index: index}
}
func (h *Handler) Index(w http.ResponseWriter, r *http.Request) {
days := h.dayList()
if len(days) == 0 {
h.render(w, r, ShellData{
Title: "CamMonitor",
Content: DayPageData{
Date: "No footage",
},
})
return
}
http.Redirect(w, r, "/day/"+days[0]+"/images", http.StatusFound)
}
func (h *Handler) DayOverview(w http.ResponseWriter, r *http.Request) {
date := chi.URLParam(r, "date")
day, ok := h.day(date)
if !ok {
http.NotFound(w, r)
return
}
h.render(w, r, ShellData{
Title: "CamMonitor " + date,
CurrentDate: date,
Content: DayPageData{
Date: date,
ImageCount: len(day.Images),
VideoCount: len(day.Videos),
},
})
}
func (h *Handler) render(w http.ResponseWriter, r *http.Request, data ShellData) {
data.User, _ = auth.UserFromContext(r.Context())
data.Months = groupDaysByMonth(h.dayList())
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := shellTemplate.ExecuteTemplate(w, "base", data); err != nil {
http.Error(w, "render page failed", http.StatusInternalServerError)
}
}
func (h *Handler) dayList() []string {
if h.index == nil {
return nil
}
return h.index.DayList()
}
func (h *Handler) day(date string) (*footage.DayEntry, bool) {
if h.index == nil {
return nil, false
}
return h.index.Day(date)
}
func groupDaysByMonth(days []string) []MonthGroup {
groups := make(map[string][]string)
labels := make([]string, 0)
for _, day := range days {
if len(day) != len("20060102") {
continue
}
parsed, err := time.Parse("20060102", day)
if err != nil {
continue
}
label := parsed.Format("2006-01")
if _, ok := groups[label]; !ok {
labels = append(labels, label)
}
groups[label] = append(groups[label], day)
}
sort.Sort(sort.Reverse(sort.StringSlice(labels)))
monthGroups := make([]MonthGroup, 0, len(labels))
for _, label := range labels {
monthGroups = append(monthGroups, MonthGroup{
Label: label,
Days: groups[label],
})
}
return monthGroups
}
var shellTemplate = template.Must(template.ParseFS(
webtemplates.FS,
webtemplates.Base,
webtemplates.Day,
))