Analytics: unique visitors this week + probed-URLs list; Scripture Index: most-studied strip + print; admin warning for unparseable passage references; v2.44.0
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6a5d525d6e
commit
e9d9dd0d50
13 files changed
+143
-9
No files matched your search
+23
-2
@@ -2735,7 +2735,7 @@ function ScriptureIndexPage({ content }: { content: SiteContent }) {
|
||||
|
||||
// Merge entries that share the same reference (a study lesson and an episode can both
|
||||
// cover the same passage) into one row, then group rows by book in canonical Bible order.
|
||||
const { bookGroups, otherRows } = useMemo(() => {
|
||||
const { bookGroups, otherRows, topRows } = useMemo(() => {
|
||||
const rowMap = new Map<string, ScriptureRow>()
|
||||
const order: string[] = []
|
||||
for (const entry of entries) {
|
||||
@@ -2789,7 +2789,12 @@ function ScriptureIndexPage({ content }: { content: SiteContent }) {
|
||||
rows: groupsByBook.get(id)!.sort((a, b) => a.chapter - b.chapter || a.verseStart - b.verseStart),
|
||||
}))
|
||||
other.sort((a, b) => a.displayRef.localeCompare(b.displayRef))
|
||||
return { bookGroups: groups, otherRows: other }
|
||||
// Passages covered by the most lessons/episodes (needs at least two sources to be worth highlighting)
|
||||
const top = [...rowMap.values()]
|
||||
.filter(r => r.bookId && r.sources.length >= 2)
|
||||
.sort((a, b) => b.sources.length - a.sources.length || order.indexOf(a.key) - order.indexOf(b.key))
|
||||
.slice(0, 6)
|
||||
return { bookGroups: groups, otherRows: other, topRows: top }
|
||||
}, [entries])
|
||||
|
||||
// Apply the search box and filters
|
||||
@@ -2886,6 +2891,7 @@ function ScriptureIndexPage({ content }: { content: SiteContent }) {
|
||||
<PageBanner eyebrow="Reference" title="Scripture Index" desc="Every passage covered across our studies and episodes, organized by Scripture reference. Find the lesson or episode for any verse." />
|
||||
<main className="si-main">
|
||||
<div className="section-inner">
|
||||
<h1 className="si-print-title">Scripture Index — {siteTitle}</h1>
|
||||
{loading ? (
|
||||
<p className="si-note">Loading…</p>
|
||||
) : !hasContent ? (
|
||||
@@ -2915,6 +2921,20 @@ function ScriptureIndexPage({ content }: { content: SiteContent }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!filtering && topRows.length > 0 && (
|
||||
<div className="si-top" aria-label="Most-studied passages">
|
||||
<h2 className="si-top-title">Most-studied passages</h2>
|
||||
<div className="si-top-list">
|
||||
{topRows.map(r => (
|
||||
<button key={r.key} type="button" className="si-top-item" onClick={() => setQuery(r.displayRef)}>
|
||||
<span className="si-top-ref">{r.displayRef}</span>
|
||||
<span className="si-top-count">{r.sources.length} sources</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bookGroups.length > 1 && (
|
||||
<div className="si-books" role="group" aria-label="Books covered">
|
||||
{bookGroups.map(g => (
|
||||
@@ -2938,6 +2958,7 @@ function ScriptureIndexPage({ content }: { content: SiteContent }) {
|
||||
)}
|
||||
<button type="button" className="si-link" onClick={() => setAll(true)}>Expand all</button>
|
||||
<button type="button" className="si-link" onClick={() => setAll(false)}>Collapse all</button>
|
||||
<button type="button" className="si-link" onClick={() => { setAll(true); window.setTimeout(() => window.print(), 150) }}>Print index</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user