// Commentary and interlinear text for the chapter of the selected chunk. // Each loads only while its section is expanded; results are cached for the visit. import { useEffect, useState } from 'react'; const commentaryCache = {}; // "commentaryId/BOOK/chapter" -> data const interlinearCache = {}; // BOOK -> whole-book interlinear data export function useStudyResources({ project, selectedChunk, selectedChunkChapterIndex, collapsedSections }) { const [commentarySource, setCommentarySource] = useState('matthew-henry'); const [commentaryData, setCommentaryData] = useState(null); // { content: [...] } for current chapter const [commentaryLoading, setCommentaryLoading] = useState(false); const [commentaryError, setCommentaryError] = useState(''); const [interlinearData, setInterlinearData] = useState(null); const [interlinearLoading, setInterlinearLoading] = useState(false); const [interlinearError, setInterlinearError] = useState(''); const loadInterlinearChapter = async (bookAbbrev, chapterNumber) => { if (interlinearCache[bookAbbrev]) return interlinearCache[bookAbbrev]; const res = await fetch(`/interlinear/${bookAbbrev}.json`); if (!res.ok) throw new Error('No interlinear data for this book.'); const data = await res.json(); interlinearCache[bookAbbrev] = data; return data; }; const loadCommentaryChapter = async (commentaryId, bookAbbrev, chapterNumber) => { const cacheKey = `${commentaryId}/${bookAbbrev}/${chapterNumber}`; if (commentaryCache[cacheKey]) return commentaryCache[cacheKey]; const res = await fetch(`https://bible.helloao.org/api/c/${commentaryId}/${bookAbbrev}/${chapterNumber}.json`); const contentType = res.headers.get('content-type') || ''; if (!res.ok || !contentType.includes('json')) throw new Error(`No ${commentaryId} commentary for this chapter.`); const data = await res.json(); commentaryCache[cacheKey] = data; return data; }; useEffect(() => { if (collapsedSections.commentary) return; if (selectedChunkChapterIndex < 0) return; const chapter = project.chapters[selectedChunkChapterIndex]; setCommentaryLoading(true); setCommentaryError(''); loadCommentaryChapter(commentarySource, chapter.bookAbbrev, chapter.chapter) .then((data) => setCommentaryData(data)) .catch((err) => { setCommentaryData(null); setCommentaryError(err.message); }) .finally(() => setCommentaryLoading(false)); }, [commentarySource, selectedChunk?.id, selectedChunkChapterIndex, collapsedSections.commentary]); useEffect(() => { if (collapsedSections.interlinear) return; if (selectedChunkChapterIndex < 0) return; const chapter = project.chapters[selectedChunkChapterIndex]; setInterlinearLoading(true); setInterlinearError(''); loadInterlinearChapter(chapter.bookAbbrev, chapter.chapter) .then((data) => setInterlinearData(data?.[String(chapter.chapter)] ?? null)) .catch((err) => { setInterlinearData(null); setInterlinearError(err.message); }) .finally(() => setInterlinearLoading(false)); }, [selectedChunk?.id, selectedChunkChapterIndex, collapsedSections.interlinear]); return { commentarySource, setCommentarySource, commentaryData, commentaryLoading, commentaryError, interlinearData, interlinearLoading, interlinearError, }; }