package handlers import ( "fmt" "net/http" "strings" "git.soup.land/soup/lookbook/internal/components" "git.soup.land/soup/lookbook/internal/data/image" "git.soup.land/soup/lookbook/internal/data/item" "git.soup.land/soup/lookbook/internal/data/tag" "git.soup.land/soup/lookbook/internal/services" "git.soup.land/soup/sxgo/ssr" ) type itemPageData struct { Item item.Row Images []image.Row TagNames []string AllTagNames []string HasAuth bool } func (d itemPageData) Render(sw *ssr.Writer) error { return sw.Tmpl(d, `
{{if .Images}} {{.Item.Title}} {{else}}
No preview image cached.
{{end}}

{{if .Item.Title}}{{.Item.Title}}{{else}}{{.Item.SourceURL}}{{end}}

{{if .Item.SiteName}}
{{.Item.SiteName}}
{{end}} {{if .Item.Description}}

{{.Item.Description}}

{{end}} {{.Item.SourceURL}}
Tags
{{range .TagNames}} {{.}} {{else}} No tags {{end}}
`) } func HandleGetItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error { id, err := parseID(r.PathValue("id")) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) return nil } row, err := item.QFindByID(r.Context(), rc.DB, id) if err != nil { return fmt.Errorf("find item: %w", err) } if row == nil { http.NotFound(w, r) return nil } images, err := image.QListByItem(r.Context(), rc.DB, id) if err != nil { return fmt.Errorf("list images: %w", err) } tags, err := tag.QListByItem(r.Context(), rc.DB, id) if err != nil { return fmt.Errorf("list item tags: %w", err) } allTags, err := tag.QList(r.Context(), rc.DB) if err != nil { return fmt.Errorf("list tags: %w", err) } var tagNames []string for _, row := range tags { tagNames = append(tagNames, row.Name) } var allTagNames []string for _, row := range allTags { allTagNames = append(allTagNames, row.Name) } authed, err := isAuthenticated(r, rc) if err != nil { return fmt.Errorf("auth status: %w", err) } w.Header().Set("Content-Type", "text/html; charset=utf-8") sw := ssr.NewWriter(w, rc.TmplCache) data := itemPageData{ Item: *row, Images: images, TagNames: tagNames, AllTagNames: allTagNames, HasAuth: authed, } return components.Page{ Title: "Item", Content: data, ShowNav: true, HasAuth: authed, }.Render(sw) } func HandlePostItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error { if !requireAuth(w, r, rc) { return nil } if err := r.ParseForm(); err != nil { http.Error(w, "Bad Request", http.StatusBadRequest) return nil } sourceURL := strings.TrimSpace(r.FormValue("url")) if sourceURL == "" { http.Error(w, "URL required", http.StatusBadRequest) return nil } _, err := services.CreateItemFromURL(r.Context(), rc.DB, sourceURL) if err != nil { return fmt.Errorf("create item: %w", err) } http.Redirect(w, r, "/", http.StatusSeeOther) return nil } func HandlePostItemTags(rc *RequestContext, w http.ResponseWriter, r *http.Request) error { if !requireAuth(w, r, rc) { return nil } id, err := parseID(r.PathValue("id")) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) return nil } if err := r.ParseForm(); err != nil { http.Error(w, "Bad Request", http.StatusBadRequest) return nil } tags := parseTags(r.FormValue("tags")) if err := tag.QReplaceItemTags(r.Context(), rc.DB, id, tags); err != nil { return fmt.Errorf("update tags: %w", err) } w.WriteHeader(http.StatusNoContent) return nil } func HandleDeleteItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error { if !requireAuth(w, r, rc) { return nil } id, err := parseID(r.PathValue("id")) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) return nil } if err := item.QSoftDelete(r.Context(), rc.DB, id); err != nil { return fmt.Errorf("delete item: %w", err) } http.Redirect(w, r, "/", http.StatusSeeOther) return nil } func HandleRefreshItem(rc *RequestContext, w http.ResponseWriter, r *http.Request) error { if !requireAuth(w, r, rc) { return nil } id, err := parseID(r.PathValue("id")) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) return nil } row, err := item.QFindByID(r.Context(), rc.DB, id) if err != nil { return fmt.Errorf("find item: %w", err) } if row == nil { http.NotFound(w, r) return nil } if err := services.RefreshItemFromURL(r.Context(), rc.DB, *row); err != nil { return fmt.Errorf("refresh item: %w", err) } http.Redirect(w, r, fmt.Sprintf("/items/%d", id), http.StatusSeeOther) return nil } func parseTags(value string) []string { var tags []string for _, tagValue := range strings.Split(value, ",") { clean := strings.TrimSpace(tagValue) if clean == "" { continue } tags = append(tags, clean) } return tags }