Add per-shelf autoRequest toggle

Introduce an autoRequest boolean on Goodreads and Hardcover shelves (default true) so users can pause/resume automatic request creation. Schema, API handlers, hooks and types were updated to accept and persist autoRequest when creating or updating shelves; add endpoints only trigger an immediate resync when the feed/token changes. The shelf sync core and service code now respect autoRequest (skipping request creation and annotating logs when disabled). UI updates include an AddShelf toggle, manage/update payload changes, shelf list props, and visual indicators + toggle actions in the shelf cards.
This commit is contained in:
kikootwo
2026-03-11 09:55:00 -04:00
parent dfc34df3d1
commit 98c89db0a7
15 changed files with 167 additions and 40 deletions
+5 -4
View File
@@ -16,6 +16,7 @@ export interface GoodreadsShelf {
lastSyncAt: string | null;
createdAt: string;
bookCount: number | null;
autoRequest: boolean;
books: ShelfBook[];
}
@@ -27,8 +28,8 @@ export const useGoodreadsShelves = useList;
export function useAddGoodreadsShelf() {
const { addShelf: addGeneric, isLoading, error } = useAdd();
const addShelf = async (rssUrl: string) => {
return addGeneric({ rssUrl });
const addShelf = async (rssUrl: string, autoRequest: boolean = true) => {
return addGeneric({ rssUrl, autoRequest });
};
return { addShelf, isLoading, error };
@@ -39,8 +40,8 @@ export const useDeleteGoodreadsShelf = useDelete;
export function useUpdateGoodreadsShelf() {
const { updateShelf: updateGeneric, isLoading, error } = useUpdate();
const updateShelf = async (shelfId: string, rssUrl: string) => {
return updateGeneric(shelfId, { rssUrl });
const updateShelf = async (shelfId: string, updates: { rssUrl?: string; autoRequest?: boolean }) => {
return updateGeneric(shelfId, updates);
};
return { updateShelf, isLoading, error };
+4 -3
View File
@@ -16,6 +16,7 @@ export interface HardcoverShelf {
lastSyncAt: string | null;
createdAt: string;
bookCount: number | null;
autoRequest: boolean;
books: ShelfBook[];
}
@@ -27,8 +28,8 @@ export const useHardcoverShelves = useList;
export function useAddHardcoverShelf() {
const { addShelf: addGeneric, isLoading, error } = useAdd();
const addShelf = async (apiToken: string, listId: string) => {
return addGeneric({ apiToken, listId });
const addShelf = async (apiToken: string, listId: string, autoRequest: boolean = true) => {
return addGeneric({ apiToken, listId, autoRequest });
};
return { addShelf, isLoading, error };
@@ -41,7 +42,7 @@ export function useUpdateHardcoverShelf() {
const updateShelf = async (
shelfId: string,
updates: { listId?: string; apiToken?: string },
updates: { listId?: string; apiToken?: string; autoRequest?: boolean },
) => {
return updateGeneric(shelfId, updates);
};
+1
View File
@@ -18,6 +18,7 @@ export interface GenericShelf {
lastSyncAt: string | null;
createdAt: string;
bookCount: number | null;
autoRequest: boolean;
books: ShelfBook[];
}
+2 -2
View File
@@ -144,10 +144,10 @@ export async function processGoodreadsShelves(
continue;
}
log.info(`Found ${rssData.books.length} books in shelf "${shelf.name}"`);
log.info(`Found ${rssData.books.length} books in shelf "${shelf.name}"${!shelf.autoRequest ? ' (auto-request disabled)' : ''}`);
const bookData = await processShelfBooks(
'goodreads', rssData.books, shelf.user.id, shelf.id, stats, log, maxLookups,
'goodreads', rssData.books, shelf.user.id, shelf.id, stats, log, maxLookups, shelf.autoRequest,
);
await prisma.goodreadsShelf.update({
+2 -2
View File
@@ -85,10 +85,10 @@ export async function processHardcoverShelves(
continue;
}
log.info(`Found ${fetchedData.books.length} books in list "${shelf.name}" (Hardcover API)`);
log.info(`Found ${fetchedData.books.length} books in list "${shelf.name}" (Hardcover API)${!shelf.autoRequest ? ' (auto-request disabled)' : ''}`);
const bookData = await processShelfBooks(
'hardcover', fetchedData.books, shelf.user.id, shelf.id, stats, log, maxLookups,
'hardcover', fetchedData.books, shelf.user.id, shelf.id, stats, log, maxLookups, shelf.autoRequest,
);
const finalListName =
+2 -1
View File
@@ -72,6 +72,7 @@ export async function processShelfBooks(
stats: ShelfSyncStats,
log: LoggerType,
maxLookups: number,
autoRequest: boolean = true,
): Promise<{ coverUrl: string; asin: string | null; title: string; author: string }[]> {
stats.booksFound += books.length;
@@ -111,7 +112,7 @@ export async function processShelfBooks(
}
}
if (mapping.audibleAsin) {
if (mapping.audibleAsin && autoRequest) {
try {
const result = await createRequestForUser(userId, {
asin: mapping.audibleAsin,