/** * Component: Watch Button (Series / Author) * Documentation: documentation/features/watched-lists.md * * Reusable toggle button for watching/unwatching a series or author. * Shows a confirmation modal before watching. Unwatching is instant. */ 'use client'; import React, { useState } from 'react'; import { useWatchedSeries, useAddWatchedSeries, useDeleteWatchedSeries } from '@/lib/hooks/useWatchedSeries'; import { useWatchedAuthors, useAddWatchedAuthor, useDeleteWatchedAuthor } from '@/lib/hooks/useWatchedAuthors'; import { ConfirmModal } from './ConfirmModal'; interface WatchSeriesButtonProps { seriesAsin: string; seriesTitle: string; coverArtUrl?: string; } export function WatchSeriesButton({ seriesAsin, seriesTitle, coverArtUrl }: WatchSeriesButtonProps) { const { series } = useWatchedSeries(); const { addSeries, isLoading: isAdding } = useAddWatchedSeries(); const { deleteSeries, isLoading: isDeleting } = useDeleteWatchedSeries(); const [error, setError] = useState(null); const [showConfirm, setShowConfirm] = useState(false); const watchedEntry = series.find((s) => s.seriesAsin === seriesAsin); const isWatching = !!watchedEntry; const isLoading = isAdding || isDeleting; const handleClick = async () => { setError(null); if (isWatching && watchedEntry) { // Unwatch immediately (no confirmation needed) try { await deleteSeries(watchedEntry.id); } catch (err) { setError(err instanceof Error ? err.message : 'Failed'); } } else { // Show confirmation before watching setShowConfirm(true); } }; const handleConfirmWatch = async () => { setShowConfirm(false); setError(null); try { await addSeries(seriesAsin, seriesTitle, coverArtUrl); } catch (err) { setError(err instanceof Error ? err.message : 'Failed'); } }; return (
{error && ( {error} )} setShowConfirm(false)} onConfirm={handleConfirmWatch} title={`Watch "${seriesTitle}"?`} message={`This will request all books in "${seriesTitle}" that aren't already in your library, and automatically request new releases as they're added to the series. Continue?`} confirmText="Watch" isLoading={isAdding} />
); } interface WatchAuthorButtonProps { authorAsin: string; authorName: string; coverArtUrl?: string; } export function WatchAuthorButton({ authorAsin, authorName, coverArtUrl }: WatchAuthorButtonProps) { const { authors } = useWatchedAuthors(); const { addAuthor, isLoading: isAdding } = useAddWatchedAuthor(); const { deleteAuthor, isLoading: isDeleting } = useDeleteWatchedAuthor(); const [error, setError] = useState(null); const [showConfirm, setShowConfirm] = useState(false); const watchedEntry = authors.find((a) => a.authorAsin === authorAsin); const isWatching = !!watchedEntry; const isLoading = isAdding || isDeleting; const handleClick = async () => { setError(null); if (isWatching && watchedEntry) { // Unwatch immediately (no confirmation needed) try { await deleteAuthor(watchedEntry.id); } catch (err) { setError(err instanceof Error ? err.message : 'Failed'); } } else { // Show confirmation before watching setShowConfirm(true); } }; const handleConfirmWatch = async () => { setShowConfirm(false); setError(null); try { await addAuthor(authorAsin, authorName, coverArtUrl); } catch (err) { setError(err instanceof Error ? err.message : 'Failed'); } }; return (
{error && ( {error} )} setShowConfirm(false)} onConfirm={handleConfirmWatch} title={`Watch "${authorName}"?`} message={`This will request all books by "${authorName}" that aren't already in your library, and automatically request new releases. Continue?`} confirmText="Watch" isLoading={isAdding} />
); }