"use client"; import { useEffect, useState } from "react"; import { useParams, useRouter } from "next/navigation"; import Link from "next/link"; import { Card } from "@/components/ui/Card"; import { Button } from "@/components/ui/Button"; import { Badge } from "@/components/ui/Badge"; import { api } from "@/lib/api"; import { useAuth } from "@/lib/auth-context"; import { useAudio } from "@/lib/audio-context"; import { useToast } from "@/lib/toast-context"; import { ArrowLeft, Book, Clock, Play, Pause, CheckCircle, Loader2, } from "lucide-react"; interface Audiobook { id: string; title: string; author: string; narrator?: string; description?: string; coverUrl: string | null; duration: number; series?: { name: string; sequence: string; } | null; genres?: string[]; progress: { currentTime: number; progress: number; isFinished: boolean; lastPlayedAt: Date; } | null; } export default function SeriesDetailPage() { const params = useParams(); const router = useRouter(); const { isAuthenticated } = useAuth(); const { toast } = useToast(); const { playAudiobook, currentAudiobook, isPlaying, pause, resume, playbackType, } = useAudio(); const seriesName = decodeURIComponent(params.name as string); const [books, setBooks] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { loadSeries(); }, [seriesName, isAuthenticated]); const loadSeries = async () => { if (!isAuthenticated) return; setIsLoading(true); try { const data = await api.getAudiobookSeries(seriesName); setBooks(Array.isArray(data) ? data : []); } catch (error: any) { console.error("Failed to load series:", error); toast.error("Failed to load series"); } finally { setIsLoading(false); } }; const formatDuration = (seconds: number) => { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (hours > 0) { return `${hours}h ${minutes}m`; } return `${minutes}m`; }; const getCoverUrl = (coverUrl: string | null, size = 300) => { if (!coverUrl) return null; return api.getCoverArtUrl(coverUrl, size); }; if (isLoading) { return (
); } if (books.length === 0) { return (

No books found in this series

); } const firstBook = books[0]; const author = firstBook.author; const genres = firstBook.genres || []; const totalDuration = books.reduce((sum, book) => sum + book.duration, 0); return (
{/* Hero Section */}
{/* Series Cover */}
{firstBook.coverUrl && getCoverUrl(firstBook.coverUrl, 500) ? ( {seriesName} ) : (
)}
{/* Series Info */}
SERIES

{seriesName}

{author} {books.length}{" "} {books.length === 1 ? "book" : "books"} {formatDuration(totalDuration)}
{genres.length > 0 && (
{genres.slice(0, 5).map((genre) => ( {genre} ))}
)}
{/* Books List */}

Books in Series

{books.map((book, index) => { const isCurrentBook = currentAudiobook?.id === book.id && playbackType === "audiobook"; const isBookPlaying = isCurrentBook && isPlaying; return (
{/* Book Number */}
{isBookPlaying ? (
) : ( {book.series?.sequence || index + 1} )}
{/* Book Cover (small) */}
{book.coverUrl && getCoverUrl(book.coverUrl, 100) ? ( {book.title} ) : (
)}
{/* Book Title & Author */}

{book.title}

{book.narrator || book.author}

{/* Progress/Status */} {book.progress?.isFinished ? ( ) : book.progress && book.progress.progress > 0 ? (
{Math.round( book.progress.progress )} %
) : null} {/* Duration */}
{formatDuration(book.duration)}
{/* Play Button */}
); })}
); }