feat: enhance book detail star rating display with visual half-stars
Improve star rating display on book detail page to show always-visible 5-star rating scale with theme-aware colors and visual half-star rendering. Changes: Enhanced renderStars() function: - Always displays 5 stars (0/5 now shows 5 grey stars instead of empty) - Filled stars use var(--accent) color (theme-aware highlight) - Empty stars use var(--text-secondary) (theme-aware grey, adapts to light/dark themes) - Half-stars use CSS linear-gradient (90deg) to split star vertically: - Left half: var(--accent) (filled, color) - Right half: var(--text-secondary) (empty, grey) - Uses webkit-background-clip and text-fill-color transparent for gradient effect Added getBookRating() helper function: - Returns rating value or 0 if book.Rating is nil - Allows unrated books to display 0/5 (5 grey stars) - Makes rating section always visible instead of hiding when nil Template changes: - Updated rating display to always show (no conditionals) - Removed text-yellow-400 class (colors now inline with theme vars) - Added templ.Raw() wrapper for HTML rendering (prevents escaping) - Simplified rating display logic Benefits: - Users can now see rating scale even when book isn't rated - Visual half-star is much more intuitive than ½ text character - Theme-aware colors adapt to light/dark mode automatically - Follows existing patterns ( UnsafeHTML, CSS variables, etc.) This makes the rating section more discoverable and user-friendly.
This commit is contained in:
+28
-8
@@ -1,7 +1,9 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"bookhoard/internal/database"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
@@ -36,20 +38,30 @@ func uuidToString(id pgtype.UUID) string {
|
||||
}
|
||||
|
||||
// renderStars converts rating (1-10 scale) to star display
|
||||
// Rating scale: 1-10 where odd numbers = half stars (1=0.5★, 3=1.5★, etc.)
|
||||
// Always displays 5 stars total with filled stars in yellow
|
||||
// and empty stars in grey (using theme variable)
|
||||
// Rating scale: 1-10 where each 2 points = 1 full star, odd numbers = half stars
|
||||
func renderStars(rating int32) string {
|
||||
stars := ""
|
||||
const totalStars = 5
|
||||
fullStars := rating / 2
|
||||
hasHalf := rating%2 != 0
|
||||
|
||||
for i := int32(0); i < fullStars; i++ {
|
||||
stars += "★"
|
||||
}
|
||||
if hasHalf {
|
||||
stars += "½"
|
||||
var stars strings.Builder
|
||||
|
||||
for i := int32(0); i < totalStars; i++ {
|
||||
if i < fullStars {
|
||||
// Filled star - accent color (theme-aware highlight)
|
||||
stars.WriteString(`<span style="color: var(--accent);">★</span>`)
|
||||
} else if i == fullStars && hasHalf {
|
||||
// Half star - gradient from accent (left) to grey (right)
|
||||
stars.WriteString(`<span style="background: linear-gradient(90deg, var(--accent) 50%, var(--text-secondary) 50%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">★</span>`)
|
||||
} else {
|
||||
// Empty star - grey using theme variable
|
||||
stars.WriteString(`<span style="color: var(--text-secondary);">★</span>`)
|
||||
}
|
||||
}
|
||||
|
||||
return stars
|
||||
return stars.String()
|
||||
}
|
||||
|
||||
// formatFileSize converts bytes to human-readable format
|
||||
@@ -122,3 +134,11 @@ func getExternalURL(service string, id string, isbn pgtype.Text, title string, a
|
||||
|
||||
return baseURL + searchTerm
|
||||
}
|
||||
|
||||
// getBookRating returns the rating value or 0 if not rated
|
||||
func getBookRating(rating *database.MediaRatings) int32 {
|
||||
if rating != nil {
|
||||
return rating.Rating
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user