Add Hardcover shelf sync & unify book mappings

Introduce Hardcover provider support and consolidate per-provider book mapping tables into a unified BookMapping model. Adds two Prisma migrations (add_hardcover_shelves, unify_book_mappings), new backend services (hardcover-api, shelf-sync-core), and provider-specific sync logic and API routes for hardcover shelves with token/list validation. Frontend: new HardcoverForm component, refactor AddShelfModal to support Hardcover, hook updates, and small UI/accessibility tweaks. Also add documentation for Goodreads and Hardcover sync flows and update tests to cover scheduler/prisma helpers.
This commit is contained in:
kikootwo
2026-03-04 10:11:19 -05:00
parent 6ca2e964e8
commit 338331d006
23 changed files with 1613 additions and 1391 deletions
+4 -2
View File
@@ -354,8 +354,9 @@ function ShelfCard({
<div className="flex items-center gap-1">
<button
onClick={onManage}
className="p-2 text-gray-300 hover:text-blue-500 dark:text-gray-600 dark:hover:text-blue-400 transition-all duration-200 rounded-xl hover:bg-blue-50 dark:hover:bg-blue-500/10 opacity-0 group-hover:opacity-100 focus:opacity-100"
className="p-2 text-gray-400 hover:text-blue-500 dark:text-gray-500 dark:hover:text-blue-400 transition-all duration-200 rounded-xl hover:bg-blue-50 dark:hover:bg-blue-500/10 opacity-40 hover:opacity-100 focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-blue-500/40 outline-none"
title="Manage shelf"
aria-label="Manage shelf"
>
<svg
className="w-[18px] h-[18px]"
@@ -373,8 +374,9 @@ function ShelfCard({
</button>
<button
onClick={onConfirmDelete}
className="p-2 text-gray-300 hover:text-red-400 dark:text-gray-600 dark:hover:text-red-400 transition-all duration-200 rounded-xl hover:bg-red-50 dark:hover:bg-red-500/10 opacity-0 group-hover:opacity-100 focus:opacity-100"
className="p-2 text-gray-400 hover:text-red-400 dark:text-gray-500 dark:hover:text-red-400 transition-all duration-200 rounded-xl hover:bg-red-50 dark:hover:bg-red-500/10 opacity-40 hover:opacity-100 focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-red-500/40 outline-none"
title="Remove shelf"
aria-label="Remove shelf"
>
<svg
className="w-[18px] h-[18px]"