Add subscribe button to recommendation cardsUnverified
a57ff73 parent: 34e8a2d modified
internal/db/cluster.go +4 -4 | @@ -266,11 +266,11 @@ func (db *DB) GetFeedRecommendations(ctx context.Context, userDID string, limit | ||
| 266 | 266 | results = append(results, map[string]any{ |
| 267 | 267 | "feed_url": feedURL, |
| 268 | 268 | "score": score, |
| 269 | - "title": title, | |
| 270 | - "site_url": siteURL, | |
| 271 | - "description": description, | |
| 269 | + "title": title.String, | |
| 270 | + "site_url": siteURL.String, | |
| 271 | + "description": description.String, | |
| 272 | 272 | "subscriber_count": subCount, |
| 273 | - "favicon_url": faviconURL, | |
| 273 | + "favicon_url": faviconURL.String, | |
| 274 | 274 | }) |
| 275 | 275 | } |
| 276 | 276 | return results, rows.Err() |
| @@ -266,11 +266,11 @@ func (db *DB) GetFeedRecommendations(ctx context.Context, userDID string, limit | |||
| 266 | results = append(results, map[string]any{ | 266 | results = append(results, map[string]any{ |
| 267 | "feed_url": feedURL, | 267 | "feed_url": feedURL, |
| 268 | "score": score, | 268 | "score": score, |
| 269 | - "title": title, | 269 | + "title": title.String, |
| 270 | - "site_url": siteURL, | 270 | + "site_url": siteURL.String, |
| 271 | - "description": description, | 271 | + "description": description.String, |
| 272 | "subscriber_count": subCount, | 272 | "subscriber_count": subCount, |
| 273 | - "favicon_url": faviconURL, | 273 | + "favicon_url": faviconURL.String, |
| 274 | }) | 274 | }) |
| 275 | } | 275 | } |
| 276 | return results, rows.Err() | 276 | return results, rows.Err() |
modified
internal/tmpl/dashboard.html +1 -1 | @@ -126,7 +126,7 @@ | ||
| 126 | 126 | <h2 class="text-lg font-semibold text-spot-text mb-4">Recommended feeds</h2> |
| 127 | 127 | <div class="space-y-3"> |
| 128 | 128 | {{range .FeedRecommendations}} |
| 129 | - {{template "recommendation-card.html" .}} | |
| 129 | + {{template "recommendation-card.html" (dict "title" .title "feed_url" .feed_url "description" .description "favicon_url" .favicon_url "subscriber_count" .subscriber_count "CSRFToken" $.CSRFToken)}} | |
| 130 | 130 | {{end}} |
| 131 | 131 | </div> |
| 132 | 132 | </div> |
| @@ -126,7 +126,7 @@ | |||
| 126 | <h2 class="text-lg font-semibold text-spot-text mb-4">Recommended feeds</h2> | 126 | <h2 class="text-lg font-semibold text-spot-text mb-4">Recommended feeds</h2> |
| 127 | <div class="space-y-3"> | 127 | <div class="space-y-3"> |
| 128 | {{range .FeedRecommendations}} | 128 | {{range .FeedRecommendations}} |
| 129 | - {{template "recommendation-card.html" .}} | 129 | + {{template "recommendation-card.html" (dict "title" .title "feed_url" .feed_url "description" .description "favicon_url" .favicon_url "subscriber_count" .subscriber_count "CSRFToken" $.CSRFToken)}} |
| 130 | {{end}} | 130 | {{end}} |
| 131 | </div> | 131 | </div> |
| 132 | </div> | 132 | </div> |
modified
internal/tmpl/feeds.html +1 -1 | @@ -42,7 +42,7 @@ | ||
| 42 | 42 | <h2 class="text-sm font-bold text-spot-text uppercase tracking-wide mb-3">Recommended feeds</h2> |
| 43 | 43 | <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3"> |
| 44 | 44 | {{range .FeedRecommendations}} |
| 45 | - {{template "recommendation-card.html" .}} | |
| 45 | + {{template "recommendation-card.html" (dict "title" .title "feed_url" .feed_url "description" .description "favicon_url" .favicon_url "subscriber_count" .subscriber_count "CSRFToken" $.CSRFToken)}} | |
| 46 | 46 | {{end}} |
| 47 | 47 | </div> |
| 48 | 48 | </div> |
| @@ -42,7 +42,7 @@ | |||
| 42 | <h2 class="text-sm font-bold text-spot-text uppercase tracking-wide mb-3">Recommended feeds</h2> | 42 | <h2 class="text-sm font-bold text-spot-text uppercase tracking-wide mb-3">Recommended feeds</h2> |
| 43 | <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3"> | 43 | <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3"> |
| 44 | {{range .FeedRecommendations}} | 44 | {{range .FeedRecommendations}} |
| 45 | - {{template "recommendation-card.html" .}} | 45 | + {{template "recommendation-card.html" (dict "title" .title "feed_url" .feed_url "description" .description "favicon_url" .favicon_url "subscriber_count" .subscriber_count "CSRFToken" $.CSRFToken)}} |
| 46 | {{end}} | 46 | {{end}} |
| 47 | </div> | 47 | </div> |
| 48 | </div> | 48 | </div> |
modified
internal/tmpl/partials/recommendation-card.html +9 -2 | @@ -2,13 +2,20 @@ | ||
| 2 | 2 | <div class="bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition"> |
| 3 | 3 | <div class="flex items-center justify-between gap-2"> |
| 4 | 4 | <div class="min-w-0 flex items-center gap-2"> |
| 5 | - {{if .favicon_url}}{{if .favicon_url.Valid}}<img src="{{.favicon_url.String}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}}{{end}} | |
| 5 | + {{if .favicon_url}}<img src="{{.favicon_url}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}} | |
| 6 | 6 | <div class="min-w-0"> |
| 7 | 7 | <div class="font-bold text-sm text-spot-text truncate">{{if .title}}{{.title}}{{else}}{{.feed_url}}{{end}}</div> |
| 8 | 8 | {{if .description}}<p class="text-xs text-spot-secondary truncate mt-0.5">{{.description}}</p>{{end}} |
| 9 | 9 | </div> |
| 10 | 10 | </div> |
| 11 | - <span class="text-xs text-spot-secondary shrink-0">{{.subscriber_count}} subs</span> | |
| 11 | + <div class="flex items-center gap-2 shrink-0"> | |
| 12 | + <span class="text-xs text-spot-secondary">{{.subscriber_count}} subs</span> | |
| 13 | + <form hx-post="/feeds/add" hx-target="closest .bg-spot-surface" hx-swap="outerHTML" class="inline"> | |
| 14 | + {{csrfInput .CSRFToken}} | |
| 15 | + <input type="hidden" name="feed_url" value="{{.feed_url}}"> | |
| 16 | + <button type="submit" class="text-xs font-bold uppercase tracking-button text-spot-green hover:brightness-110 transition">Subscribe</button> | |
| 17 | + </form> | |
| 18 | + </div> | |
| 12 | 19 | </div> |
| 13 | 20 | </div> |
| 14 | 21 | {{end}} |
| @@ -2,13 +2,20 @@ | |||
| 2 | <div class="bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition"> | 2 | <div class="bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition"> |
| 3 | <div class="flex items-center justify-between gap-2"> | 3 | <div class="flex items-center justify-between gap-2"> |
| 4 | <div class="min-w-0 flex items-center gap-2"> | 4 | <div class="min-w-0 flex items-center gap-2"> |
| 5 | - {{if .favicon_url}}{{if .favicon_url.Valid}}<img src="{{.favicon_url.String}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}}{{end}} | 5 | + {{if .favicon_url}}<img src="{{.favicon_url}}" class="w-4 h-4 rounded shrink-0" loading="lazy">{{end}} |
| 6 | <div class="min-w-0"> | 6 | <div class="min-w-0"> |
| 7 | <div class="font-bold text-sm text-spot-text truncate">{{if .title}}{{.title}}{{else}}{{.feed_url}}{{end}}</div> | 7 | <div class="font-bold text-sm text-spot-text truncate">{{if .title}}{{.title}}{{else}}{{.feed_url}}{{end}}</div> |
| 8 | {{if .description}}<p class="text-xs text-spot-secondary truncate mt-0.5">{{.description}}</p>{{end}} | 8 | {{if .description}}<p class="text-xs text-spot-secondary truncate mt-0.5">{{.description}}</p>{{end}} |
| 9 | </div> | 9 | </div> |
| 10 | </div> | 10 | </div> |
| 11 | - <span class="text-xs text-spot-secondary shrink-0">{{.subscriber_count}} subs</span> | 11 | + <div class="flex items-center gap-2 shrink-0"> |
| 12 | + <span class="text-xs text-spot-secondary">{{.subscriber_count}} subs</span> | ||
| 13 | + <form hx-post="/feeds/add" hx-target="closest .bg-spot-surface" hx-swap="outerHTML" class="inline"> | ||
| 14 | + {{csrfInput .CSRFToken}} | ||
| 15 | + <input type="hidden" name="feed_url" value="{{.feed_url}}"> | ||
| 16 | + <button type="submit" class="text-xs font-bold uppercase tracking-button text-spot-green hover:brightness-110 transition">Subscribe</button> | ||
| 17 | + </form> | ||
| 18 | + </div> | ||
| 12 | </div> | 19 | </div> |
| 13 | </div> | 20 | </div> |
| 14 | {{end}} | 21 | {{end}} |