package templates import ( "fmt" "bookhoard/internal/services" ) // UnlinkedMatchCards renders the match candidates for one device file's // "find matches" reveal — the /unlinked-books/matches partial response. // Cards are clicked through the delegated data-action handler (rendering // ownership: templ renders, JS only swaps and handles the click). templ UnlinkedMatchCards(progressId string, matches []services.BookMatch) { if len(matches) == 0 {

No matches found. Try manual linking.

} else { for _, match := range matches {
Cover
{ match.Title }
if match.Author != "" {

by { match.Author }

}
{ fmt.Sprintf("%.0f%% confidence", match.Confidence*100) } { match.MatchMethod }
} } } templ UnlinkedBooks(user User, unresolved []UnlinkedBookData, ignored []UnlinkedBookData) { Unlinked Books - Bookhoard @Header(user, "/unlinked")
@UnlinkedBooksSection(unresolved, ignored)
@unlinkedManualLinkModal() } // UnlinkedBooksSection is the whole actionable page body: toolbar, the // unresolved queue, and the collapsed ignored bucket. Every dismiss/ // delete/restore action re-renders this partial server-side (htmx // hx-target="#unlinked-section" outerHTML) so counts and buckets can // never drift from the database after an action. templ UnlinkedBooksSection(unresolved []UnlinkedBookData, ignored []UnlinkedBookData) {
@Icon("sync", "h-5 w-5")

Unlinked Books

Resolve books that couldn't be automatically matched between devices

if len(unresolved) > 0 {
0 selected
}
if len(unresolved) == 0 {
@Icon("check-circle", "h-7 w-7")

All Books Linked!

There are no unlinked books that need manual resolution.

} for _, book := range unresolved { @unlinkedBookCard(book, false) }
if len(ignored) > 0 {
Ignored ({ fmt.Sprintf("%d", len(ignored)) }) — hidden from the queue and the dashboard badge
for _, book := range ignored { @unlinkedBookCard(book, true) }
}
} // unlinkedBookCard renders one queue row. Ignored rows drop the checkbox // and the match/link actions (they are dismissed) and offer Restore + // Delete instead; all action buttons re-render the section server-side. templ unlinkedBookCard(book UnlinkedBookData, ignored bool) {
if !ignored {
}
if book.DeviceType == "koreader" { @Icon("book-open", "h-5 w-5") } else if book.DeviceType == "kobo" { @Icon("library", "h-5 w-5") } else { @Icon("device", "h-5 w-5") }

{ book.TitleFromDevice }

Device: { book.DeviceName } ({ book.DeviceType })

File Path: @Icon("folder", "h-3.5 w-3.5") { book.FilePath }
if book.SHA256 != "" {
SHA-256: { book.SHA256 }
}
Last Synced: { book.LastSyncTime }
if book.ConfidenceScore > 0 {
Auto-Link Confidence: { book.ConfidenceScore }% confidence
}
if ignored {
} else {
}
} // unlinkedManualLinkModal holds the manual-link dialog markup (unchanged // behavior; extracted so the section partial can be re-rendered on its own). templ unlinkedManualLinkModal() { }