import React, { useState, useEffect, memo } from 'react'; import { ArrowLeft, FileText, Star, ChevronRight, Search } from 'lucide-react'; import { getBook } from '../services/api'; import { Section } from '../types/favorites'; import SectionPicker from './SectionPicker'; interface ChapterSelectorProps { book: string; onChapterSelect: (chapter: string) => void; onBack: () => void; formatBookName: (bookName: string) => string; user?: any; onFavoriteChange?: () => void; version?: string; onSearchClick?: () => void; favorites?: Set; sections?: Section[]; onSectionChange?: () => void; } const ChapterSelector: React.FC = memo(({ book, onChapterSelect, onBack, formatBookName, user, onFavoriteChange, version = 'esv', onSearchClick, favorites = new Set(), sections = [], onSectionChange }) => { const [chapters, setChapters] = useState([]); const [loading, setLoading] = useState(true); const [showSectionPicker, setShowSectionPicker] = useState(false); const [pendingChapter, setPendingChapter] = useState(null); useEffect(() => { loadChapters(); }, [book]); const toggleFavorite = async (chapter: string, event: React.MouseEvent, sectionId?: number | null) => { event.stopPropagation(); if (!user) return; const isFavorited = favorites.has(chapter); try { if (isFavorited) { // Remove favorite const response = await fetch('/api/favorites', { credentials: 'include' }); if (response.ok) { const data = await response.json(); const chapterFavorite = data.favorites.find((fav: any) => fav.book === book && fav.chapter === chapter && !fav.verse_start ); if (chapterFavorite) { await fetch(`/api/favorites/${chapterFavorite.id}`, { method: 'DELETE', credentials: 'include' }); console.log('Removed chapter favorite:', chapter); onFavoriteChange?.(); } } } else { // Add favorite - check if we need section picker if (sections.length > 0 && sectionId === undefined) { const defaultSection = sections.find(s => s.is_default); if (defaultSection) { await addFavoriteWithSection(chapter, defaultSection.id); } else { setPendingChapter(chapter); setShowSectionPicker(true); } } else { await addFavoriteWithSection(chapter, sectionId ?? null); } } } catch (error) { console.error('Failed to toggle favorite:', error); } }; const addFavoriteWithSection = async (chapter: string, sectionId: number | null) => { try { const response = await fetch('/api/favorites', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify({ book: book, chapter: chapter, version: version, section_id: sectionId }) }); if (response.ok) { console.log('Added chapter favorite:', chapter, 'to section:', sectionId); onFavoriteChange?.(); } } catch (error) { console.error('Failed to add favorite:', error); } }; const handleSectionSelect = async (sectionId: number | null) => { if (pendingChapter) { await addFavoriteWithSection(pendingChapter, sectionId); setPendingChapter(null); } setShowSectionPicker(false); }; const loadChapters = async () => { try { setLoading(true); const response = await getBook(book, version); if (response.chapters) { const sortedChapters = response.chapters.sort((a, b) => parseInt(a, 10) - parseInt(b, 10)); setChapters(sortedChapters); } else { console.error('API returned no chapters data'); setChapters([]); } } catch (error) { console.error('Failed to load chapters:', error); setChapters([]); } finally { setLoading(false); } }; if (loading) { return (

Loading chapters...

); } return (
{/* Search Bar */}
{/* Breadcrumb Navigation */}
{formatBookName(book)}
{/* Book Title */}

{formatBookName(book)}

Select a chapter to read

{user && (

Click the star to add chapters to your favorites

)}
{/* Chapters Grid */}
{chapters.map((chapter) => (
{user && ( )}
))}
{/* Chapter Count */}

{chapters.length} chapters available

{/* Section Picker Modal */} {showSectionPicker && ( { setShowSectionPicker(false); setPendingChapter(null); }} onSectionCreated={onSectionChange} /> )}
); }); export default ChapterSelector;