// The Outline stage: choose a chapter, then cut it into chunks by clicking between
// verses (or let the section headings suggest them). Each chunk becomes one unit of
// study in the next stage.
import { STUDY_TEMPLATES, getTemplate } from '../utils/studyTemplates.js';
import { useApp } from '../context/AppContext.js';
import { useChunkBuilder } from '../hooks/useChunkBuilder.js';
import StudioShell from '../components/study/StudioShell.jsx';
import { bookOptions, formatChunkReference } from '../utils/bibleUtils.jsx';
const inputCls = 'mt-1 block w-full rounded-xl border border-[var(--r-line)] bg-[var(--r-bg)] px-3 py-2 text-sm text-[var(--r-text)] focus:outline-none focus:ring-2 focus:ring-[var(--r-line)]';
const smallBtn = 'rounded-lg border border-[var(--r-line)] px-2.5 py-1.5 text-xs hover:bg-black/5 disabled:opacity-40';
const primaryBtn = 'rounded-xl bg-[var(--r-accent)] px-5 py-2.5 text-sm font-medium text-[var(--r-on)] hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40';
// Band tints that alternate from chunk to chunk so neighbouring chunks are easy to tell apart.
const BANDS = ['color-mix(in srgb, var(--r-accent) 13%, transparent)', 'color-mix(in srgb, var(--r-sub) 17%, transparent)'];
function PassageForm({ setup, onField, onTitleChange, onLoad, loading, error, withTitle, userTemplates = [], onDeleteTemplate }) {
return (
);
}
export default function SetupPage() {
const { project, setProject, allChunks, updateProject, setCurrentPage, userTemplates, deleteUserTemplate } = useApp();
const b = useChunkBuilder({ project, setProject, updateProject, allChunks, setCurrentPage, userTemplates });
const { activeChapter, activeChapterIndex } = b;
const chapters = project?.chapters ?? [];
const onTitleChange = (val) => { b.setTitleEdited(true); b.handleSetupField('title', val); };
const select = (id) => updateProject((current) => ({ ...current, selectedChunkId: id }));
// Which chunk (if any) each verse of the active chapter belongs to
const chunkOf = (n) => activeChapter?.chunks.findIndex((c) => n >= c.startVerse && n <= c.endVerse) ?? -1;
const prevChapter = chapters[activeChapterIndex - 1];
const spilledFromPrev = (n) => !!prevChapter && prevChapter.bookAbbrev === activeChapter.bookAbbrev
&& prevChapter.chunks.some((c) => Number.isInteger(c.spilloverEndVerse) && n <= c.spilloverEndVerse);
const lastVerse = activeChapter?.verses.at(-1)?.number ?? 0;
const uncovered = activeChapter ? activeChapter.verses.some((v) => chunkOf(v.number) < 0 && !spilledFromPrev(v.number)) : false;
return (
{!project && (
New study
Pick a chapter, then cut it into chunks. You’ll study one chunk at a time.
)}
{project && (
{chapters.map((ch, idx) => (
))}
{b.showAddChapterForm && (
)}
{activeChapter && (
Scripture & Chunks
{activeChapter.book} {activeChapter.chapter} ({project.translation})
Click the line between two verses to split or join chunks. Or click a verse, then shift-click another, to make a chunk from that range.
b.setVerseSearch(e.target.value)} placeholder="Search verses in this chapter…"
className="mb-3 w-full rounded-xl border border-[var(--r-line)] bg-[var(--r-bg)] px-3 py-2 text-sm text-[var(--r-text)] focus:outline-none focus:ring-2 focus:ring-[var(--r-line)]" />
{activeChapter.verses
.filter((v) => v.text.toLowerCase().includes(b.verseSearch.trim().toLowerCase()))
.map((verse) => {
const n = verse.number;
const ci = chunkOf(n);
const chunk = ci >= 0 ? activeChapter.chunks[ci] : null;
const inRange = b.rangeStart !== null && n >= Math.min(b.rangeStart, b.rangeEnd) && n <= Math.max(b.rangeStart, b.rangeEnd);
const isFirst = chunk && chunk.startVerse === n;
const next = activeChapter.chunks.find((c) => c.startVerse === n + 1);
const insideChunk = chunk && n < chunk.endVerse && !chunk.spilloverEndVerse;
const endsChunk = chunk && chunk.endVerse === n && next && chunk.id;
const showGutter = n < lastVerse && !b.verseSearch.trim();
return (
{isFirst && (
)}
{showGutter && (insideChunk ? (
) : endsChunk ? (
) : !chunk && !spilledFromPrev(n) ? (
) :
)}
);
})}
)}
{activeChapter && (
)}
)}
);
}