anycoder-4d1c0cbc / components /InteractiveBook.js
LukeDunsMoto's picture
Upload components/InteractiveBook.js with huggingface_hub
cf2403d verified
Raw
History Blame Contribute Delete
4.38 kB
import { useState, useEffect } from 'react'
import { ChevronLeft, ChevronRight, Edit3, Bookmark } from 'lucide-react'
import ProgressTracker from './ProgressTracker'
import QuizComponent from './QuizComponent'
import CommentSection from './CommentSection'
import RatingComponent from './RatingComponent'
import ImageGallery from './ImageGallery'
import VideoPlayer from './VideoPlayer'
import CodeBlock from './CodeBlock'
import QuoteBox from './QuoteBox'
export default function InteractiveBook({ content, components, currentPage, onPageChange, onEdit }) {
const [pages, setPages] = useState([])
const [bookmarks, setBookmarks] = useState(new Set())
useEffect(() => {
if (content) {
const paragraphs = content.split('\n\n').filter(p => p.trim())
setPages(paragraphs)
}
}, [content])
const toggleBookmark = (pageIndex) => {
setBookmarks(prev => {
const newBookmarks = new Set(prev)
if (newBookmarks.has(pageIndex)) {
newBookmarks.delete(pageIndex)
} else {
newBookmarks.add(pageIndex)
}
return newBookmarks
})
}
const renderComponent = (component, index) => {
const props = {
key: component.id,
data: component.data,
onUpdate: (newData) => {
// Update component data logic would go here
}
}
switch (component.type) {
case 'quiz':
return <QuizComponent {...props} />
case 'comment':
return <CommentSection {...props} />
case 'rating':
return <RatingComponent {...props} />
case 'image':
return <ImageGallery {...props} />
case 'video':
return <VideoPlayer {...props} />
case 'code':
return <CodeBlock {...props} />
case 'quote':
return <QuoteBox {...props} />
default:
return null
}
}
if (pages.length === 0) return null
return (
<div className="max-w-4xl mx-auto">
<div className="bg-white rounded-xl shadow-lg p-8 mb-6">
<div className="flex items-center justify-between mb-6">
<h2 className="text-2xl font-bold text-gray-900">Your Interactive Book</h2>
<button
onClick={onEdit}
className="flex items-center space-x-2 px-4 py-2 text-sm font-medium text-blue-600 bg-blue-50 rounded-lg hover:bg-blue-100 transition-colors"
>
<Edit3 className="h-4 w-4" />
<span>Edit</span>
</button>
</div>
<ProgressTracker
totalPages={pages.length}
currentPage={currentPage}
bookmarks={bookmarks}
/>
<div className="prose prose-lg max-w-none mb-8">
<p className="text-gray-700 leading-relaxed">{pages[currentPage]}</p>
</div>
{components.map(renderComponent)}
<div className="flex items-center justify-between pt-6 border-t">
<button
onClick={() => onPageChange(Math.max(0, currentPage - 1))}
disabled={currentPage === 0}
className="flex items-center space-x-2 px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
<ChevronLeft className="h-4 w-4" />
<span>Previous</span>
</button>
<button
onClick={() => toggleBookmark(currentPage)}
className={`flex items-center space-x-2 px-4 py-2 text-sm font-medium rounded-lg transition-colors ${
bookmarks.has(currentPage)
? 'text-yellow-600 bg-yellow-50 hover:bg-yellow-100'
: 'text-gray-700 bg-gray-100 hover:bg-gray-200'
}`}
>
<Bookmark className="h-4 w-4" />
<span>{bookmarks.has(currentPage) ? 'Bookmarked' : 'Bookmark'}</span>
</button>
<button
onClick={() => onPageChange(Math.min(pages.length - 1, currentPage + 1))}
disabled={currentPage === pages.length - 1}
className="flex items-center space-x-2 px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
<span>Next</span>
<ChevronRight className="h-4 w-4" />
</button>
</div>
</div>
</div>
)
}