Files
study-bible-project/src/components/study/CommentaryChunkTab.jsx
T
nmemmertandClaude Sonnet 5.5 31abee0695
Build and Push Docker Image / build-and-push (push) Successful in 4m15s
Redesign the study side: Outline, Study, Script and Export stages
Studies now move through a stage bar in the reader's themes. Outline splits
chunks by clicking between verses (join merges notes) and suggests chunks from
section headings. Study is three panes: outline, passage with an Observe /
Interpret / Apply accordion, and commentary / word study / cross-refs / people
& places for the chunk; original words are added by clicking them in the
interlinear. Script drafts an outline from notes; Export holds files and the
share link. Home, Import and the Pronunciation guide are restyled. Study
projects are BSB only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 10:13:46 -04:00

57 lines
3.2 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Commentary for the chunk's verse range, from seven open sources. Some sources
// comment on whole passages, so when nothing starts inside the range we show the
// closest earlier entry. "Add to notes" quotes a paragraph, with its citation, into
// the chunk's background notes.
import { COMMENTARIES } from '../../hooks/useVerseStudy.js';
import { formatChunkReference } from '../../utils/bibleUtils.jsx';
export default function CommentaryChunkTab({ resources, chunk, project, chapterIndex, updateChunk, notify }) {
const { commentarySource, setCommentarySource, commentaryData, commentaryLoading, commentaryError } = resources;
const source = COMMENTARIES.find((c) => c.id === commentarySource) ?? COMMENTARIES[0];
const items = (commentaryData?.chapter?.content ?? []).filter((i) => i.type === 'verse').sort((a, b) => a.number - b.number);
let entries = items.filter((i) => i.number >= chunk.startVerse && i.number <= chunk.endVerse);
let earlier = false;
if (entries.length === 0) {
const before = [...items].reverse().find((i) => i.number <= chunk.startVerse);
if (before) { entries = [before]; earlier = true; }
}
const ref = formatChunkReference(project, chapterIndex, chunk, '–');
const quote = (text, verse) => {
const citation = `${text} (${source.name}, ${ref.split(':')[0]}:${verse})`;
const existing = chunk.generalNotes ?? '';
updateChunk(chunk.id, { generalNotes: existing ? `${existing}\n\n${citation}` : citation });
notify('Added to background notes.', 1600);
};
return (
<div>
<select aria-label="Commentary source" value={source.id} onChange={(e) => setCommentarySource(e.target.value)}
className="mb-3 w-full rounded-lg border border-[var(--r-line)] bg-[var(--r-bg)] px-2 py-1.5 text-sm text-[var(--r-text)]">
{COMMENTARIES.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
</select>
{commentaryLoading && <p className="text-sm text-[var(--r-sub)]">Loading commentary…</p>}
{commentaryError && <p className="text-sm text-[var(--r-sub)]">{commentaryError}</p>}
{!commentaryLoading && !commentaryError && commentaryData && entries.length === 0 && (
<p className="text-sm text-[var(--r-sub)]">No commentary found for {ref}.</p>
)}
{!commentaryLoading && !commentaryError && entries.map((v) => (
<div key={v.number} className="mb-4">
<p className="mb-1 text-xs font-medium text-[var(--r-sub)]">{earlier ? `Notes on the passage starting at verse ${v.number}` : `Verse ${v.number}`}</p>
{(v.content ?? []).map((p, i) => {
const text = typeof p === 'string' ? p : '';
if (!text) return null;
return (
<div key={i} className="group mb-2">
<p className="whitespace-pre-line text-[13px] leading-relaxed">{text}</p>
<button type="button" onClick={() => quote(text, v.number)} className="mt-0.5 text-[11px] text-[var(--r-accent)] opacity-70 hover:underline hover:opacity-100">Add to notes</button>
</div>
);
})}
</div>
))}
<p className="mt-2 text-[10px] text-[var(--r-sub)]">{source.credit}</p>
</div>
);
}