diff --git a/templates/book_detail.templ b/templates/book_detail.templ index 2b6b639..70c52a5 100644 --- a/templates/book_detail.templ +++ b/templates/book_detail.templ @@ -19,7 +19,7 @@ templ BookDetail(user User, book handlers.MediaDetail, errorMessage string) { - + @Header(user, "/media/{ uuidToString(book.ID) }")
@@ -103,13 +103,42 @@ templ BookDetail(user User, book handlers.MediaDetail, errorMessage string) {
-
+
- @templ.Raw(renderStars(getBookRating(book.Rating))) - - - ({ fmt.Sprintf("%.1f", float64(getBookRating(book.Rating))/2.0) } / 5) + + + + + + +
if book.CommunityRating.Valid && book.CommunityRating.Float64 > 0 { diff --git a/templates/book_detail_templ.go b/templates/book_detail_templ.go index 89d5d95..1a1282c 100644 --- a/templates/book_detail_templ.go +++ b/templates/book_detail_templ.go @@ -58,7 +58,7 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string) templ var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.ResolveAttributeValue(book.FormatGroup) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 22, Col: 93} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 22, Col: 96} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var3) if templ_7745c5c3_Err != nil { @@ -71,13 +71,26 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string) templ var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(uuidToString(book.LibraryID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 22, Col: 142} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 22, Col: 145} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" data-rating=\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.ResolveAttributeValue(fmt.Sprintf("%d", getBookRating(book.Rating))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 22, Col: 207} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var5) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -85,156 +98,135 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string) templ if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.CoverImagePath.Valid && book.CoverImagePath.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\"")") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" alt=\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.ResolveAttributeValue(book.Title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 39, Col: 24} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" class=\"w-64 h-96 object-cover rounded-lg shadow-xl\" onerror=\"this.src='/static/placeholder-book.svg'\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"{") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\"{") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(book.Title) + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(book.Title) if templ_7745c5c3_Err != nil { return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 54, Col: 89} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.Author.Valid && book.Author.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "

by ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "

by ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(book.Author.String) + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(book.Author.String) if templ_7745c5c3_Err != nil { return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 57, Col: 31} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\" class=\"px-6 py-3 rounded-lg font-semibold\" style=\"background-color: var(--accent); color: white;\">📖 Read Now") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.ActiveConflict != nil || book.ReadingProgress != nil { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ.Raw(renderStars(getBookRating(book.Rating))).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " (") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var11 string - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", float64(getBookRating(book.Rating))/2.0)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 111, Col: 71} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, " / 5)
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.CommunityRating.Valid && book.CommunityRating.Float64 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
Community Rating: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
Community Rating: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -242,210 +234,210 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string) templ if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var12 string templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f / 10", book.CommunityRating.Float64)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 123, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 152, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.Series.Valid && book.Series.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" class=\"px-3 py-1 rounded-full text-sm font-semibold inline-block hover:opacity-80 transition-opacity\" style=\"background-color: var(--accent); color: white; text-decoration: none;\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(book.Series.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 136, Col: 29} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 165, Col: 29} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.SeriesNumber.Valid && book.SeriesNumber.Int32 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "#") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "#") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var15 string templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(book.SeriesNumber.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 138, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 167, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.ReadingDirection.Valid && book.ReadingDirection.String != "" && book.ReadingDirection.String != "auto" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
📖 ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "
📖 ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ToUpper(book.ReadingDirection.String)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 150, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 179, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.AgeRating.Valid && book.AgeRating.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var17 string templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(book.AgeRating.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 162, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 191, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.IsBlackAndWhite.Valid && book.IsBlackAndWhite.Bool { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "B&W") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "B&W") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.StoryArc.Valid && book.StoryArc.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "📚 ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "📚 ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var18 string templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(book.StoryArc.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 180, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 209, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(book.Tags) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.Description.Valid && book.Description.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "

Synopsis

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "

Synopsis

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -455,17 +447,17 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string) templ if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.Summary.Valid && book.Summary.String != "" && book.Summary.String != book.Description.String { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "

Comic Summary

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "

Comic Summary

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -475,760 +467,760 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string) templ if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.MetadataNotes.Valid && book.MetadataNotes.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "

Metadata Notes

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "

Metadata Notes

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var21 string templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(book.MetadataNotes.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 230, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 259, Col: 34} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.ReadingProgress != nil { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "

Reading Progress

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "

Reading Progress

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.ActiveConflict != nil { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "

⚠️ Progress conflict detected - Click \"Sync Progress\" to review and resolve

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "

⚠️ Progress conflict detected - Click \"Sync Progress\" to review and resolve

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "

Progress

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "\">

Progress

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var23 string templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", book.ReadingProgress.Percentage.Float64*100)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 265, Col: 77} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 294, Col: 77} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "%

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "%

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.ReadingProgress.CurrentPage.Valid && book.ReadingProgress.TotalPages.Valid { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "

Page

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "

Page

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var24 string templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.CurrentPage.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 271, Col: 52} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 300, Col: 52} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, " / ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, " / ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var25 string templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.TotalPages.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 271, Col: 96} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 300, Col: 96} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.ReadingProgress.LastReadAt.Valid { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "

Last Read

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "

Last Read

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var26 string templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(FormatTimestamptzInTimezone(book.ReadingProgress.LastReadAt, user.Timezone)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 277, Col: 89} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 306, Col: 89} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.ReadingProgress.LastSyncSource.Valid { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "

Source

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "

Source

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var27 string templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.LastSyncSource.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 283, Col: 75} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 312, Col: 75} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "

Metadata

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "

Metadata

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.Publisher.Valid && book.Publisher.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "

Publisher

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "

Publisher

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var28 string templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(book.Publisher.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 300, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 329, Col: 34} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.DatePublished.Valid { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "

Published

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "

Published

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var29 string templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(book.DatePublished.Time.Format("01-02-2006")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 306, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 335, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.Isbn.Valid && book.Isbn.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "

Isbn

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "

Isbn

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var30 string templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(book.Isbn.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 312, Col: 29} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 341, Col: 29} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.Language.Valid && book.Language.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "

Language

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "

Language

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var31 string templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(book.Language.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 318, Col: 52} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 347, Col: 52} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.Edition.Valid && book.Edition.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "

Edition

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "

Edition

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var32 string templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(book.Edition.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 324, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 353, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.PageCount.Valid && book.PageCount.Int32 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "

Pages

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "

Pages

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var33 string templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(book.PageCount.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 330, Col: 33} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 359, Col: 33} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.Genre.Valid && book.Genre.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "

Genre

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "

Genre

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var34 string templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(book.Genre.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 336, Col: 30} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 365, Col: 30} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.SeriesCount.Valid && book.SeriesCount.Int32 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "

Series Count

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "

Series Count

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var35 string templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(book.SeriesCount.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 343, Col: 35} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 372, Col: 35} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, " items

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, " items

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.Volume.Valid && book.Volume.Int32 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "

Volume

Vol. ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, "

Volume

Vol. ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var36 string templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(book.Volume.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 349, Col: 35} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 378, Col: 35} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.Imprint.Valid && book.Imprint.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "

Imprint

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "

Imprint

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var37 string templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(book.Imprint.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 355, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 384, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.CopyrightYear.Valid && book.CopyrightYear.Int32 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "

Copyright Year

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "

Copyright Year

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var38 string templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(book.CopyrightYear.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 361, Col: 37} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 390, Col: 37} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.MangaType.Valid && book.MangaType.String != "" && book.MangaType.String != "unknown" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "

Manga Type

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "

Manga Type

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var39 string templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ReplaceAll(book.MangaType.String, "_", " ")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 368, Col: 83} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 397, Col: 83} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.ScanInformation.Valid && book.ScanInformation.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "

Scan Info

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "

Scan Info

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var40 string templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(book.ScanInformation.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 374, Col: 94} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 403, Col: 94} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if len(book.AlternateInfo) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "

Alternate Series

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "

Alternate Series

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var41 string templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(string(book.AlternateInfo)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 380, Col: 55} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 409, Col: 55} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if altSeries := getAlternateSeries(book.AlternateInfo); altSeries != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "

Alternate Series

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "

Alternate Series

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var42 string templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(altSeries) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 386, Col: 22} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 415, Col: 22} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if len(book.Contributors) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "

Contributors

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "

Contributors

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var43 string templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(book.Contributors, ", ")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 392, Col: 50} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 421, Col: 50} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "

Format

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "

Format

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var44 string templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(book.MimeType.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 398, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 427, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.FileSize.Valid && book.FileSize.Int64 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "

File Size

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "

File Size

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var45 string templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinStringErrs(formatFileSize(book.FileSize.Int64)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 403, Col: 48} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 432, Col: 48} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.GoodreadsID.Valid || book.OpenlibraryID.Valid || book.GoogleBooksID.Valid || book.Asin.Valid || book.Isbn.Valid || book.WebUrl.Valid { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "

External Links

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "

External Links

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.GoodreadsID.Valid && book.GoodreadsID.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "📚 Goodreads ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">📚 Goodreads ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "📚 Goodreads ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">📚 Goodreads ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.OpenlibraryID.Valid && book.OpenlibraryID.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "📖 Open Library ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">📖 Open Library ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "📖 Open Library ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">📖 Open Library ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.GoogleBooksID.Valid && book.GoogleBooksID.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "🔍 Google Books ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">🔍 Google Books ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "🔍 Google Books ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">🔍 Google Books ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.Asin.Valid && book.Asin.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "🛒 Amazon ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">🛒 Amazon ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if book.Isbn.Valid && book.Isbn.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "🛒 Amazon ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">🛒 Amazon ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if book.WebUrl.Valid && book.WebUrl.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "🔗 ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-sm hover:underline flex items-center gap-1\" style=\"color: var(--accent);\">🔗 ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var55 string templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.JoinStringErrs(getDomainName(book.WebUrl.String)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 504, Col: 50} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 533, Col: 50} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var55)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 133, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(book.Collections) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 134, "

Collections

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 133, "

Collections

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, col := range book.Collections { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 135, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 135, "\" class=\"px-3 py-2 rounded-lg border flex items-center gap-2 hover:opacity-80 transition-opacity\" style=\"border-color: { col.Color.String }; background-color: var(--bg-primary); text-decoration: none;\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var57 string templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(col.Icon.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 525, Col: 69} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 554, Col: 69} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 136, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var58 string templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(col.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 526, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail.templ`, Line: 555, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1248,7 +1240,7 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string) templ if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/web/src/book-detail.ts b/web/src/book-detail.ts index b5c8117..e97f01c 100644 --- a/web/src/book-detail.ts +++ b/web/src/book-detail.ts @@ -97,6 +97,9 @@ interface MetadataEditorState { coverFile: Blob | null; coverAction: string; saving: boolean; + userRating: number; + ratingHover: number; + ratingSaving: boolean; toggleSection(section: string): void; showMetadataEditor(): void; hideMetadataEditor(): void; @@ -104,6 +107,10 @@ interface MetadataEditorState { generateCover(): Promise; removeCover(): void; saveMetadata(): Promise; + starFill(i: number): string; + ratingText(): string; + setRating(value: number): Promise; + clearRating(): Promise; resolveConflict(conflictId: string, winner: string): Promise; } @@ -136,6 +143,9 @@ Alpine.data("bookDetail", () => { coverFile: null as Blob | null, coverAction: "keep", saving: false, + userRating: 0, + ratingHover: 0, + ratingSaving: false, editorTags: initialTags, tagSearch: "", tagSuggestions: [] as TagSuggestion[], @@ -178,6 +188,9 @@ Alpine.data("bookDetail", () => { }, init() { + const ratingAttr = document.body.getAttribute("data-rating"); + this.userRating = ratingAttr ? parseInt(ratingAttr, 10) || 0 : 0; + const link = document.getElementById("back-link"); if (!link) return; const storageKey = "book_detail_back"; @@ -207,6 +220,77 @@ Alpine.data("bookDetail", () => { this.openSections[section] = !this.openSections[section]; }, + starFill(i: number): string { + const display = this.ratingHover || this.userRating; + if (i * 2 <= display) { + return "color: var(--accent);"; + } else if (i * 2 - 1 === display) { + return "background: linear-gradient(90deg, var(--accent) 50%, var(--text-secondary) 50%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;"; + } + return "color: var(--text-secondary);"; + }, + + ratingText(): string { + if (this.userRating === 0) return "(not rated)"; + return `(${(this.userRating / 2).toFixed(1)} / 5)`; + }, + + async setRating(value: number) { + if (this.ratingSaving) return; + this.ratingSaving = true; + const mediaId = getMediaId(); + try { + const resp = await fetch(`/api/media-items/${mediaId}/rating`, { + method: "POST", + headers: { + Authorization: getAuthHeader(), + "Content-Type": "application/json", + }, + body: JSON.stringify({ rating: value }), + }); + if (!resp.ok) { + const err = await resp.json().catch(() => ({})); + throw new Error(err.error || "Failed to save rating"); + } + this.userRating = value; + this.ratingHover = 0; + showToast("Rating saved", "success"); + } catch (e) { + showToast( + e instanceof Error ? e.message : "Failed to save rating", + "error", + ); + } finally { + this.ratingSaving = false; + } + }, + + async clearRating() { + if (this.ratingSaving) return; + this.ratingSaving = true; + const mediaId = getMediaId(); + try { + const resp = await fetch(`/api/media-items/${mediaId}/rating`, { + method: "DELETE", + headers: { Authorization: getAuthHeader() }, + }); + if (!resp.ok) { + const err = await resp.json().catch(() => ({})); + throw new Error(err.error || "Failed to clear rating"); + } + this.userRating = 0; + this.ratingHover = 0; + showToast("Rating cleared", "success"); + } catch (e) { + showToast( + e instanceof Error ? e.message : "Failed to clear rating", + "error", + ); + } finally { + this.ratingSaving = false; + } + }, + handleCoverUpload(event: Event) { const input = event.target as HTMLInputElement; const file = input.files?.[0];