Scripture Index: verse of the week (admin override or weekly rotation through covered passages); v2.45.0
Publish Container / build (push) Successful in 17m33s
Publish Container / build (push) Successful in 17m33s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e9d9dd0d50
commit
a1adfa0ef1
6 files changed
+75
-4
No files matched your search
+50
@@ -2838,6 +2838,38 @@ function ScriptureIndexPage({ content }: { content: SiteContent }) {
|
||||
return promise
|
||||
}
|
||||
|
||||
// Verse of the week: the admin's pick if set, otherwise rotate through covered passages by calendar week
|
||||
const [weekIndex] = useState(() => Math.floor(Date.now() / (7 * 24 * 60 * 60 * 1000)))
|
||||
const verseOfWeek = useMemo(() => {
|
||||
const override = content.verseOfTheWeek?.trim()
|
||||
const parsed = override ? parseSIRef(override) : null
|
||||
if (parsed) {
|
||||
const key = `${parsed.bookId}-${parsed.chapter}-${parsed.verseStart}-${parsed.endChapter}-${parsed.verseEnd}`
|
||||
const existing = bookGroups.flatMap(g => g.rows).find(r => r.key === key)
|
||||
return existing ?? {
|
||||
key,
|
||||
displayRef: `${SI_BOOK_NAME[parsed.bookId]} ${parsed.chapter}:${parsed.verseStart}${parsed.verseEnd !== parsed.verseStart ? `-${parsed.verseEnd}` : ''}`,
|
||||
bookId: parsed.bookId, chapter: parsed.chapter, endChapter: parsed.endChapter,
|
||||
verseStart: parsed.verseStart, verseEnd: parsed.verseEnd, sources: [],
|
||||
} as ScriptureRow
|
||||
}
|
||||
const pool = bookGroups.flatMap(g => g.rows)
|
||||
if (pool.length === 0) return null
|
||||
return pool[weekIndex % pool.length]
|
||||
}, [bookGroups, content.verseOfTheWeek, weekIndex])
|
||||
const [votText, setVotText] = useState<string | null>(null)
|
||||
const votKey = verseOfWeek?.key
|
||||
useEffect(() => {
|
||||
if (!verseOfWeek || !verseOfWeek.bookId) return
|
||||
let cancelled = false
|
||||
const verseEnd = verseOfWeek.endChapter !== verseOfWeek.chapter ? Number.MAX_SAFE_INTEGER : verseOfWeek.verseEnd
|
||||
fetchChapter(verseOfWeek.bookId, verseOfWeek.chapter)
|
||||
.then(ch => { if (!cancelled) setVotText(extractVerseRange(ch, verseOfWeek.verseStart, verseEnd) || null) })
|
||||
.catch(() => { if (!cancelled) setVotText(null) })
|
||||
return () => { cancelled = true }
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [votKey])
|
||||
|
||||
function toggleVerse(row: ScriptureRow) {
|
||||
const open = shownVerses.has(row.key)
|
||||
setShownVerses(prev => {
|
||||
@@ -2921,6 +2953,24 @@ function ScriptureIndexPage({ content }: { content: SiteContent }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!filtering && verseOfWeek && (
|
||||
<div className="si-vow">
|
||||
<p className="si-vow-eyebrow">Verse of the week</p>
|
||||
<h2 className="si-vow-ref">{verseOfWeek.displayRef}</h2>
|
||||
{votText && <p className="si-vow-text">“{votText}”</p>}
|
||||
{verseOfWeek.sources.length > 0 && (
|
||||
<div className="si-sources">
|
||||
{verseOfWeek.sources.slice(0, 3).map((src, i) => (
|
||||
<Link key={i} to={src.url} className={`si-chip si-chip--${src.type}`}>
|
||||
<span className="si-chip-kind">{src.type === 'episode' ? 'Episode' : 'Study'}</span>
|
||||
<span className="si-chip-label">{src.label}</span>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!filtering && topRows.length > 0 && (
|
||||
<div className="si-top" aria-label="Most-studied passages">
|
||||
<h2 className="si-top-title">Most-studied passages</h2>
|
||||
|
||||
Reference in new issue
Block a user