fix: properly map book IDs from search to API UUIDs in Bible reader

Updates BibleReaderApp to handle the mismatch between numeric book IDs
used by SearchNavigator (1-66) and UUID book IDs required by the API.

Changes:
- Add loadBooks() to fetch book metadata on mount
- Map numeric orderNum to UUID book IDs for API calls
- Implement proper hasNextChapter logic using actual chapter counts
- Store books array and versionId in state
- Update loadChapter to convert numeric bookId to UUID before API call

This ensures the Bible reader works correctly with the existing database
schema while maintaining a simple numeric interface for the SearchNavigator.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-11 20:17:13 +00:00
parent aefe54751b
commit 1dc4d761b5

View File

@@ -8,31 +8,78 @@ import { ReadingView } from './reading-view'
import { VersDetailsPanel } from './verse-details-panel'
import { ReadingSettings } from './reading-settings'
interface BookInfo {
id: string // UUID
orderNum: number
bookKey: string
name: string
chapterCount: number
}
export function BibleReaderApp() {
const [bookId, setBookId] = useState(1) // Genesis
const [bookId, setBookId] = useState(1) // Genesis (numeric ID from search)
const [chapter, setChapter] = useState(1)
const [currentChapter, setCurrentChapter] = useState<BibleChapter | null>(null)
const [selectedVerse, setSelectedVerse] = useState<BibleVerse | null>(null)
const [detailsPanelOpen, setDetailsPanelOpen] = useState(false)
const [settingsOpen, setSettingsOpen] = useState(false)
const [loading, setLoading] = useState(false)
const [loading, setLoading] = useState(true)
const [bookmarks, setBookmarks] = useState<Set<string>>(new Set())
const [books, setBooks] = useState<BookInfo[]>([])
const [versionId, setVersionId] = useState<string>('')
// Load chapter on navigation
// Load books on mount
useEffect(() => {
loadChapter(bookId, chapter)
}, [bookId, chapter])
loadBooks()
}, [])
async function loadChapter(bookId: number, chapterNum: number) {
// Load chapter when bookId or chapter changes
useEffect(() => {
if (books.length > 0) {
loadChapter(bookId, chapter)
}
}, [bookId, chapter, books])
async function loadBooks() {
try {
const response = await fetch('/api/bible/books')
if (response.ok) {
const json = await response.json()
if (json.success && json.books) {
const bookMap: BookInfo[] = json.books.map((book: any) => ({
id: book.id,
orderNum: book.orderNum,
bookKey: book.bookKey,
name: book.name,
chapterCount: book.chapters.length
}))
setBooks(bookMap)
setVersionId(json.version.id)
}
}
} catch (error) {
console.error('Error loading books:', error)
}
}
async function loadChapter(numericBookId: number, chapterNum: number) {
setLoading(true)
try {
// Find the book by orderNum
const book = books.find(b => b.orderNum === numericBookId)
if (!book) {
console.error('Book not found for orderNum:', numericBookId)
setCurrentChapter(null)
return
}
// Try cache first
const chapterId = `${bookId}-${chapterNum}`
const chapterId = `${book.id}-${chapterNum}`
let data = await getCachedChapter(chapterId)
// If not cached, fetch from API
if (!data) {
const response = await fetch(`/api/bible/chapter?book=${bookId}&chapter=${chapterNum}`)
const response = await fetch(`/api/bible/chapter?book=${book.id}&chapter=${chapterNum}`)
if (response.ok) {
const json = await response.json()
data = json.chapter
@@ -40,6 +87,8 @@ export function BibleReaderApp() {
// Cache it
if (data) {
data.id = chapterId
data.bookId = numericBookId // Keep numeric ID for consistency
data.chapter = chapterNum
await cacheChapter(data)
}
} else {
@@ -112,11 +161,19 @@ export function BibleReaderApp() {
chapter={currentChapter}
loading={loading}
onPrevChapter={() => chapter > 1 && setChapter(chapter - 1)}
onNextChapter={() => setChapter(chapter + 1)}
onNextChapter={() => {
const book = books.find(b => b.orderNum === bookId)
if (book && chapter < book.chapterCount) {
setChapter(chapter + 1)
}
}}
onVerseClick={handleVerseClick}
onSettingsOpen={() => setSettingsOpen(true)}
hasPrevChapter={chapter > 1}
hasNextChapter={true} // TODO: Check actual chapter count based on book
hasNextChapter={(() => {
const book = books.find(b => b.orderNum === bookId)
return book ? chapter < book.chapterCount : false
})()}
/>
) : (
<Box sx={{ p: 4, textAlign: 'center' }}>