'use client'; import { useState, useEffect } from 'react'; import { useParams, useRouter } from 'next/navigation'; import Link from 'next/link'; import Image from 'next/image'; import { storyApi, seriesApi, getImageUrl } from '../../../../lib/api'; import { Story, Collection } from '../../../../types/api'; import AppLayout from '../../../../components/layout/AppLayout'; import Button from '../../../../components/ui/Button'; import LoadingSpinner from '../../../../components/ui/LoadingSpinner'; import { calculateReadingTime } from '../../../../lib/settings'; export default function StoryDetailPage() { const params = useParams(); const router = useRouter(); const storyId = params.id as string; const [story, setStory] = useState(null); const [seriesStories, setSeriesStories] = useState([]); const [collections, setCollections] = useState([]); const [loading, setLoading] = useState(true); const [updating, setUpdating] = useState(false); useEffect(() => { const loadStoryData = async () => { try { setLoading(true); const storyData = await storyApi.getStory(storyId); setStory(storyData); // Load series stories if this story is part of a series if (storyData.seriesId) { const seriesData = await seriesApi.getSeriesStories(storyData.seriesId); setSeriesStories(seriesData); } // Load collections that contain this story const collectionsData = await storyApi.getStoryCollections(storyId); setCollections(collectionsData); } catch (error) { console.error('Failed to load story data:', error); router.push('/library'); } finally { setLoading(false); } }; if (storyId) { loadStoryData(); } }, [storyId, router]); const handleRatingClick = async (newRating: number) => { if (updating || !story) return; try { setUpdating(true); await storyApi.updateRating(story.id, newRating); setStory(prev => prev ? { ...prev, rating: newRating } : null); } catch (error) { console.error('Failed to update rating:', error); } finally { setUpdating(false); } }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); }; const estimateReadingTime = (wordCount: number) => { return calculateReadingTime(wordCount); }; if (loading) { return (
); } if (!story) { return (

Story Not Found

); } return (
{/* Header Actions */}
{/* Left Column - Cover */}
{/* Cover Image */}
{story.coverPath ? ( {story.title} ) : (
📖
)}
{/* Right Column - Story Details */}
{/* Title and Author */}

{story.title}

by {story.authorName}
{/* Quick Stats and Rating */}
{/* Quick Stats */}

Details

Word Count: {story.wordCount.toLocaleString()}
Reading Time: ~{estimateReadingTime(story.wordCount)} min
Added: {formatDate(story.createdAt)}
{story.updatedAt !== story.createdAt && (
Updated: {formatDate(story.updatedAt)}
)}
{/* Rating */}

Your Rating

{[1, 2, 3, 4, 5].map((star) => ( ))}
{story.rating && (

{story.rating}/5 stars

)}
{/* Series Info */} {story.seriesName && (

Part of Series

{story.seriesName} {story.volume && ` - Volume ${story.volume}`}

{/* Series Navigation */} {seriesStories.length > 1 && (

Other stories in this series:

{seriesStories .filter(s => s.id !== story.id) .slice(0, 5) .map((seriesStory) => ( {seriesStory.volume && `${seriesStory.volume}. `} {seriesStory.title} ))} {seriesStories.length > 6 && (

+{seriesStories.length - 6} more stories

)}
)}
)} {/* Collections */} {collections.length > 0 && (

Part of Collections ({collections.length})

{collections.map((collection) => (
{collection.coverImagePath ? ( {`${collection.name} ) : (
{collection.storyCount}
)}

{collection.name}

{collection.storyCount} {collection.storyCount === 1 ? 'story' : 'stories'} {collection.estimatedReadingTime && ( • ~{Math.ceil(collection.estimatedReadingTime / 60)}h reading )}

{collection.rating && (
{collection.rating}
)}
))}
)} {/* Summary */} {story.summary && (

Summary

{story.summary}

)} {/* Tags */} {story.tags && story.tags.length > 0 && (

Tags

{story.tags.map((tag) => ( {tag.name} ))}
)} {/* Source URL */} {story.sourceUrl && ( )} {/* Action Buttons */}
); }