Redesign study landing page: track cards, numbered steps, tidier hero and Q&A callout, themed progress bars; v2.10.8
Publish Container / build (push) Has been cancelled

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-09 10:41:18 -04:00
1 parent 52568db82b
commit 669cd6555c
4 files changed
+296 -116

No files matched your search

+95 -113
View File
@@ -911,8 +911,8 @@ export function StudyLandingPage({ content }: Props) {
<span style={{ color: '#7a7060', fontSize: '0.9rem' }}>{study.completedLessons}/{study.totalLessons} lessons completed</span>
<span style={{ color: '#7a7060', fontSize: '0.9rem' }}>{study.noteCount} notes</span>
</div>
<div style={{ marginTop: '0.75rem', height: '10px', width: '100%', background: '#27231b', borderRadius: '999px', overflow: 'hidden' }}>
<div style={{ width: `${progress}%`, height: '100%', background: '#e0c070' }} />
<div className="study-progress-track" role="progressbar" aria-valuemin={0} aria-valuemax={100} aria-valuenow={progress} style={{ marginTop: '0.75rem' }}>
<div className="study-progress-fill" style={{ width: `${progress}%` }} />
</div>
</div>
<div className="study-module-row-right" style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
@@ -942,6 +942,54 @@ export function StudyLandingPage({ content }: Props) {
)
}
const availableCount = activeStudies.length + completeStudies.length
const renderTrackCard = (study: StudyProgram, variant: 'active' | 'complete' | 'planned') => {
const releasedCount = study.sections.filter(isSectionReleased).length
const nextLabel = getNextReleaseLabel(study)
const book = variant === 'complete' ? (content.finishedBooks ?? []).find(item => item.studySlug === study.slug) : undefined
const body = (
<>
<div className="study-track-top">
<span className={`study-track-status study-track-status--${variant}`}>
{variant === 'active' ? 'In progress · start anytime' : variant === 'complete' ? 'Complete · self-paced' : 'Coming soon'}
</span>
{study.difficulty && <span className={`study-difficulty study-difficulty--${study.difficulty}`}>{study.difficulty}</span>}
</div>
<h3 className="study-track-title">{study.title}</h3>
<p className="study-track-desc">{study.description}</p>
<ul className="study-track-facts">
{variant === 'planned' ? (
<li>
{study.startsAt && new Date(study.startsAt).getTime() > Date.now()
? `Starts ${new Date(study.startsAt).toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })}`
: 'Preparing lesson structure and media'}
</li>
) : (
<>
<li>{variant === 'complete' ? `All ${study.sections.length} lessons available` : releasedCount > 0 ? `${releasedCount} of ${study.sections.length} lessons available` : 'Lessons will be published soon'}</li>
{variant === 'active' && nextLabel && <li>Next lesson: {nextLabel}</li>}
{study.estimatedHours ? <li>About {study.estimatedHours} hours</li> : null}
</>
)}
</ul>
{variant !== 'planned' && <span className="study-track-cta">View lessons →</span>}
</>
)
return (
<div className="study-track-wrap" key={study.id}>
{variant === 'planned'
? <article className="study-track-card study-track-card--planned" aria-disabled="true">{body}</article>
: <Link to={`/study/${study.slug}`} className="study-track-card">{body}</Link>}
{book && (
<p className="study-track-listen">
Just want to listen? <Link to={`/finished/${book.id}`}>Open the audio playlist — no account needed →</Link>
</p>
)}
</div>
)
}
return (
<main className="study-index-page" aria-label="Study hub">
<section className="section-study-course-hero">
@@ -950,16 +998,22 @@ export function StudyLandingPage({ content }: Props) {
<h1>Study at Your Own Pace</h1>
<p className="study-course-hero-copy">Pick a study track, move lesson by lesson on your own schedule, and keep personal notes as you grow through each passage.</p>
<div className="study-course-meta">
<span>{activeStudies.length + completeStudies.length} {activeStudies.length + completeStudies.length === 1 ? 'study' : 'studies'} available{completeStudies.length > 0 ? ` (${completeStudies.length} finished, start anytime)` : ''}{plannedStudies.length > 0 ? ` · ${plannedStudies.length} coming soon` : ''}</span>
<span>Self-paced flow</span>
<span>Self-paced</span>
<span>Personal notes</span>
<span>Audio + commentary</span>
<span>Free account</span>
</div>
<div className="study-course-hero-actions">
{firstActiveStudyFirstReleasedSection && <Link to={`/study/${firstActiveStudy.slug}/${firstActiveStudyFirstReleasedSection.id}`} className="btn-primary">Start Learning</Link>}
<Link to="/study/signup" className="btn-primary">Create Account or Login</Link>
<Link to="/study/account" className="btn-secondary">My Account</Link>
{firstActiveStudyFirstReleasedSection
? <Link to={`/study/${firstActiveStudy.slug}/${firstActiveStudyFirstReleasedSection.id}`} className="btn-primary">Start Learning</Link>
: <a href="#study-tracks" className="btn-primary">Browse Studies</a>}
<Link to="/study/signup" className="btn-secondary">Create Free Account or Sign In</Link>
</div>
<p className="study-hub-count">
{availableCount} {availableCount === 1 ? 'study' : 'studies'} available
{completeStudies.length > 0 ? ` (${completeStudies.length} finished, start anytime)` : ''}
{plannedStudies.length > 0 ? ` · ${plannedStudies.length} coming soon` : ''}
</p>
</div>
</section>
@@ -969,63 +1023,33 @@ export function StudyLandingPage({ content }: Props) {
<p>How It Works</p>
<h2>A Simple Self-Paced Rhythm</h2>
</div>
<div className="study-hub-flow-grid">
<article className="study-hub-flow-card">
<p className="study-module-lesson">Step 1</p>
<h3>Choose Your Track</h3>
<p>Start with any active study and begin at lesson one, or jump back in where you left off.</p>
</article>
<article className="study-hub-flow-card">
<p className="study-module-lesson">Step 2</p>
<h3>Work Each Lesson</h3>
<p>Read the text, listen to audio, review commentary, and process key Greek word notes.</p>
</article>
<article className="study-hub-flow-card">
<p className="study-module-lesson">Step 3</p>
<h3>Save Notes and Continue</h3>
<p>Keep personal notes per lesson and build your own study archive over time.</p>
</article>
</div>
<ol className="study-hub-steps">
{[
{ title: 'Choose Your Track', body: 'Start with any active study and begin at lesson one, or jump back in where you left off.' },
{ title: 'Work Each Lesson', body: 'Read the text, listen to audio, review commentary, and process key Greek word notes.' },
{ title: 'Save Notes and Continue', body: 'Keep personal notes per lesson and build your own study archive over time.' },
].map((step, index) => (
<li className="study-hub-step" key={step.title}>
<span className="study-hub-step-number" aria-hidden="true">{index + 1}</span>
<h3>{step.title}</h3>
<p>{step.body}</p>
</li>
))}
</ol>
</div>
</section>
<section id="study-tracks" className="section-study-module" aria-label="Available studies">
<div className="section-inner">
<div className="study-module-header">
<p>Available Now</p>
<h2>Current Study Tracks</h2>
{activeStudies.length > 0 && (
<section id="study-tracks" className="section-study-module" aria-label="Available studies">
<div className="section-inner">
<div className="study-module-header">
<p>Available Now</p>
<h2>Current Study Tracks</h2>
</div>
<div className="study-track-grid">{activeStudies.map(study => renderTrackCard(study, 'active'))}</div>
</div>
<div className="study-module-list">
{activeStudies.map(study => (
(() => {
const releasedCount = study.sections.filter(isSectionReleased).length
return (
<Link key={study.id} to={`/study/${study.slug}`} className="study-module-row">
<div className="study-module-row-left">
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', marginBottom: '0.5rem', flexWrap: 'wrap' }}>
<p className="study-module-lesson">Start Anytime</p>
{study.difficulty && <span style={{ backgroundColor: study.difficulty === 'advanced' ? '#d32f2f' : (study.difficulty === 'intermediate' ? '#f57c00' : '#388e3c'), color: '#fff', padding: '0.25rem 0.75rem', borderRadius: '16px', fontSize: '0.75rem', fontWeight: '600', textTransform: 'capitalize' }}>{study.difficulty}</span>}
</div>
<h3>{study.title}</h3>
<p>{study.description}</p>
{study.estimatedHours && <p style={{ fontSize: '0.875rem', color: '#666', marginTop: '0.5rem' }}>⏱ {study.estimatedHours} hours</p>}
</div>
<div className="study-module-row-right">
<p className="study-module-focus">Track Snapshot</p>
<p>{releasedCount > 0 ? `${releasedCount} lessons available now` : 'Lessons will be published soon.'}</p>
<p>{(() => {
const next = getNextReleaseLabel(study)
if (next) return `Next lesson: ${next}`
return study.sections.length > 0 ? 'New lessons release on a regular schedule.' : 'Pacing details coming with first lesson release.'
})()}</p>
</div>
</Link>
)
})()
))}
</div>
</div>
</section>
</section>
)}
{completeStudies.length > 0 && (
<section className="section-study-module" aria-label="Finished studies" id="finished-studies">
@@ -1034,32 +1058,7 @@ export function StudyLandingPage({ content }: Props) {
<p>Study On Your Own Time</p>
<h2>Finished Studies</h2>
</div>
<div className="study-module-list">
{completeStudies.map(study => {
const book = (content.finishedBooks ?? []).find(item => item.studySlug === study.slug)
return (
<div key={study.id}>
<Link to={`/study/${study.slug}`} className="study-module-row">
<div className="study-module-row-left">
<p className="study-module-lesson">Complete · Start Anytime</p>
<h3>{study.title}</h3>
<p>{study.description}</p>
</div>
<div className="study-module-row-right">
<p className="study-module-focus">Self-Paced</p>
<p>All {study.sections.length} lessons available now</p>
<p>No schedule — go as fast or slow as you like.</p>
</div>
</Link>
{book && (
<p style={{ margin: '0.4rem 0 0', fontSize: '0.9rem' }}>
Just want to listen? <Link to={`/finished/${book.id}`}>Open the audio playlist — no account needed →</Link>
</p>
)}
</div>
)
})}
</div>
<div className="study-track-grid">{completeStudies.map(study => renderTrackCard(study, 'complete'))}</div>
</div>
</section>
)}
@@ -1071,41 +1070,24 @@ export function StudyLandingPage({ content }: Props) {
<p>Coming Soon</p>
<h2>Next Study Tracks</h2>
</div>
<div className="study-module-list">
{plannedStudies.map(study => (
<article key={study.id} className="study-module-row study-module-row--disabled" aria-disabled="true">
<div className="study-module-row-left">
<p className="study-module-lesson">Planned</p>
<h3>{study.title}</h3>
<p>{study.description}</p>
</div>
<div className="study-module-row-right">
<p className="study-module-focus">Status</p>
<p>{study.startsAt && new Date(study.startsAt).getTime() > Date.now()
? `Starts ${new Date(study.startsAt).toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })}`
: 'Preparing lesson structure and media.'}</p>
</div>
</article>
))}
</div>
<div className="study-track-grid">{plannedStudies.map(study => renderTrackCard(study, 'planned'))}</div>
</div>
</section>
)}
<section className="section-study-module" aria-label="Q&A">
<div className="section-inner" style={{ textAlign: 'center', padding: '3rem 1rem' }}>
<p className="eyebrow">Have a question from the Word?</p>
<h2 style={{ fontSize: '1.5rem', fontWeight: 700, margin: '0.5rem 0 0.75rem', color: '#f0e9cc' }}>Ask Nate a Question</h2>
<p style={{ color: '#8a7f5a', maxWidth: '480px', margin: '0 auto 1.5rem', fontSize: '0.95rem' }}>
Submit a Bible or theology question and it may be answered in a future episode or the Q&amp;A archive.
</p>
<div style={{ display: 'flex', gap: '0.75rem', justifyContent: 'center', flexWrap: 'wrap' }}>
<a href="/questions" className="btn-primary">Browse Q&amp;A Archive →</a>
<a href="/contact" className="btn-secondary">Submit a Question</a>
<div className="section-inner">
<div className="study-hub-ask">
<p className="eyebrow">Have a question from the Word?</p>
<h2>Ask Nate a Question</h2>
<p>Submit a Bible or theology question and it may be answered in a future episode or the Q&amp;A archive.</p>
<div className="study-hub-ask-actions">
<Link to="/questions" className="btn-primary">Browse Q&amp;A Archive →</Link>
<Link to="/contact" className="btn-secondary">Submit a Question</Link>
</div>
</div>
</div>
</section>
</main>
)
}