All green. You're good to build and deploy. Here's a summary of everything done since your last commit:
--- **🐛 Bugs fixed** - Study hub/lesson pages turned gold — CSS merge error with `.study-index-page` fixed - Lesson announcements not saving — `announcement` field missing from `sanitizeColossiansStudySections` whitelist - 2FA email method blocked with "not configured" — guard checked `totpSecret` instead of `twoFaMethod` - `STUDY_REMINDERS_FILE` constant never defined — server would crash on first reminder write - `sanitizeStudyUsers` stripped all 2FA fields — data lost on every restart - `scheduleStudyReminders` missing from refactored modules **✨ Features added** - Commentary supports paragraph formatting (double newline = new paragraph) - Lesson announcement banner — full-width gold stripe at top of lesson page - "Take the Quiz" renamed to "Discussion Questions" throughout - Students must complete checkpoint before unlocking next lesson (lesson list + Next Lesson button both gate on it) - No checkpoint questions → simple Mark as Completed button as fallback - Truth For Life syndication widget on homepage - Newsletter welcome email updated to your new HTML template **🔧 Maintenance** - `server.js` refactored from 6,013 lines into 12 focused modules
This commit is contained in:
+53
@@ -1056,6 +1056,57 @@ function HomepageNewsletterSection() {
|
||||
)
|
||||
}
|
||||
|
||||
type TflWidgetType = 'audiodevo' | 'abdevotional'
|
||||
|
||||
function TruthForLifeWidget({ type = 'audiodevo' }: { type?: TflWidgetType }) {
|
||||
const containerId = `tfl-syndicate-container-${type}`
|
||||
|
||||
useEffect(() => {
|
||||
// Remove any previous instance of this script to allow re-init on re-mount
|
||||
const existingScript = document.getElementById('tfl-syn-script-' + type)
|
||||
if (existingScript) existingScript.remove()
|
||||
|
||||
// Clear the container so the widget can repopulate it
|
||||
const container = document.getElementById(containerId)
|
||||
if (container) container.innerHTML = ''
|
||||
|
||||
const script = document.createElement('script')
|
||||
script.id = 'tfl-syn-script-' + type
|
||||
script.src = `https://www.truthforlife.org/static/js/responsive/lib/syndicate.js?type=${type}&id=458890`
|
||||
script.type = 'text/javascript'
|
||||
// The TFL script looks for #tfl-syndicate-container by ID — temporarily
|
||||
// rename our container to match, then rename back after the script fires
|
||||
if (container) container.id = 'tfl-syndicate-container'
|
||||
document.body.appendChild(script)
|
||||
|
||||
// Restore the namespaced id after a tick so React doesn't lose track
|
||||
const restore = setTimeout(() => {
|
||||
const el = document.getElementById('tfl-syndicate-container')
|
||||
if (el) el.id = containerId
|
||||
}, 2000)
|
||||
|
||||
return () => {
|
||||
clearTimeout(restore)
|
||||
script.remove()
|
||||
}
|
||||
}, [type])
|
||||
|
||||
return (
|
||||
<section className="section-tfl" aria-label="Truth For Life devotional">
|
||||
<div className="section-inner">
|
||||
<p className="eyebrow">Daily Devotional</p>
|
||||
<h2 className="section-heading">
|
||||
<span className="ornament">✦</span> Truth For Life <span className="ornament">✦</span>
|
||||
</h2>
|
||||
<p className="tfl-attribution">
|
||||
Teaching from <a href="https://www.truthforlife.org" target="_blank" rel="noreferrer" className="tfl-link">Truth For Life</a> with Alistair Begg
|
||||
</p>
|
||||
<div id={containerId} className="tfl-widget-wrap" />
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
function HomepageQACallout() {
|
||||
const [questions, setQuestions] = useState<{ id: string; firstName: string; question: string; answer: string }[]>([])
|
||||
|
||||
@@ -1213,6 +1264,8 @@ function LandingPage({ content }: { content: SiteContent }) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<TruthForLifeWidget type="audiodevo" />
|
||||
|
||||
<ExternalSitesSection content={content} />
|
||||
|
||||
<section className="section-home-jump" aria-label="Homepage navigation">
|
||||
|
||||
Reference in New Issue
Block a user