Build and Push Docker Image / build-and-push (push) Successful in 4m15s
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>
44 lines
2.7 KiB
React
44 lines
2.7 KiB
React
// Left rail of the Study stage: every chunk of the project as an outline, with
|
||
// three dots (Observe / Interpret / Apply) showing which notes are written.
|
||
import { formatChunkReference } from '../../utils/bibleUtils.jsx';
|
||
|
||
const filled = (s) => (s ?? '').trim().length > 0;
|
||
|
||
export default function OutlineRail({ project, selectedId, onSelect, onEditOutline }) {
|
||
return (
|
||
<nav aria-label="Chunks" className="flex h-full min-h-0 flex-col">
|
||
<div className="flex items-center justify-between px-3 pb-2 pt-3">
|
||
<span className="text-[11px] uppercase tracking-wide text-[var(--r-sub)]">Outline</span>
|
||
<button type="button" onClick={onEditOutline} className="text-[11px] text-[var(--r-accent)] hover:underline">Edit</button>
|
||
</div>
|
||
<div className="min-h-0 flex-1 overflow-y-auto px-2 pb-4">
|
||
{project.chapters.map((ch, chapterIndex) => (
|
||
<div key={`${ch.bookAbbrev}-${ch.chapter}`} className="mb-3">
|
||
{project.chapters.length > 1 && <p className="px-2 pb-1 text-[11px] text-[var(--r-sub)]">{ch.book} {ch.chapter}</p>}
|
||
{ch.chunks.length === 0 && <p className="px-2 text-xs text-[var(--r-sub)]">No chunks in this chapter.</p>}
|
||
{ch.chunks.map((chunk) => {
|
||
const selected = chunk.id === selectedId;
|
||
const first = ch.verses.find((v) => v.number === chunk.startVerse)?.text ?? '';
|
||
return (
|
||
<button key={chunk.id} type="button" onClick={() => onSelect(chunk.id)} aria-current={selected ? 'true' : undefined}
|
||
className={`mb-1 block w-full rounded-xl border px-2.5 py-2 text-left transition ${selected ? 'border-[var(--r-line)] bg-[var(--r-bg)]' : 'border-transparent hover:bg-black/5'}`}>
|
||
<span className="flex items-center justify-between gap-2">
|
||
<span className="text-[13px] font-medium">{formatChunkReference(project, chapterIndex, chunk, '–')}</span>
|
||
<span className="flex gap-1" aria-hidden="true">
|
||
{['observation', 'interpretation', 'application'].map((f) => (
|
||
<span key={f} className={`h-2 w-2 rounded-full border ${filled(chunk[f]) ? 'border-[var(--r-accent)] bg-[var(--r-accent)]' : 'border-[var(--r-sub)]'}`} />
|
||
))}
|
||
</span>
|
||
</span>
|
||
{chunk.episodeTitle && <span className="mt-0.5 block truncate text-[11px] text-[var(--r-accent)]">{chunk.episodeNumber ? `${chunk.episodeNumber} · ` : ''}{chunk.episodeTitle}</span>}
|
||
<span className="mt-0.5 block truncate font-serif text-xs text-[var(--r-sub)]">{first}</span>
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
))}
|
||
</div>
|
||
</nav>
|
||
);
|
||
}
|