From dba5f16bcdbf3bc205afbb8be6703d5a11ce3acc Mon Sep 17 00:00:00 2001 From: nmemmert Date: Tue, 12 May 2026 15:23:17 -0400 Subject: [PATCH] Load draft content in admin while keeping public lesson locks --- server.js | 18 ++++++++++++++++-- src/App.tsx | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 8763847..47971fb 100644 --- a/server.js +++ b/server.js @@ -119,19 +119,33 @@ function isSectionReleased(section) { return releaseTime <= Date.now() } +function redactUnreleasedSection(section) { + if (!section || typeof section !== 'object') return section + if (isSectionReleased(section)) return section + + return { + ...section, + passageText: '', + commentary: '', + greekNotes: [], + studyQuestions: [], + audioEmbedUrl: '', + } +} + function filterSiteContentByReleaseDate(siteContent) { if (!siteContent || typeof siteContent !== 'object' || Array.isArray(siteContent)) return siteContent const filteredStudies = Array.isArray(siteContent.studies) ? siteContent.studies.map(study => { if (!study || typeof study !== 'object') return study - const sections = Array.isArray(study.sections) ? study.sections.filter(isSectionReleased) : [] + const sections = Array.isArray(study.sections) ? study.sections.map(redactUnreleasedSection) : [] return { ...study, sections } }) : siteContent.studies const filteredLegacySections = Array.isArray(siteContent.colossiansStudySections) - ? siteContent.colossiansStudySections.filter(isSectionReleased) + ? siteContent.colossiansStudySections.map(redactUnreleasedSection) : siteContent.colossiansStudySections return { diff --git a/src/App.tsx b/src/App.tsx index bb93bbd..01e1de6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1615,6 +1615,7 @@ function LegalPage({ title, body }: { title: string; body: string[] }) { function AdminShell({ content, onSave }: { content: SiteContent; onSave: (c: SiteContent) => void }) { const [status, setStatus] = useState<'checking' | 'authenticated' | 'unauthenticated' | 'misconfigured'>('checking') + const [adminContent, setAdminContent] = useState(content) const [password, setPassword] = useState('') const [errorMsg, setErrorMsg] = useState('') const [submitting, setSubmitting] = useState(false) @@ -1639,6 +1640,36 @@ function AdminShell({ content, onSave }: { content: SiteContent; onSave: (c: Sit }) }, []) + useEffect(() => { + if (status === 'authenticated') return + setAdminContent(content) + }, [content, status]) + + useEffect(() => { + if (status !== 'authenticated') return + + let cancelled = false + + fetch('/api/admin-content?source=draft') + .then(r => (r.ok ? r.json() : null)) + .then(data => { + if (cancelled) return + if (data?.siteContent) { + setAdminContent(c => ({ ...c, ...data.siteContent })) + } + }) + .catch(() => {}) + + return () => { + cancelled = true + } + }, [status]) + + function handleAdminSave(next: SiteContent) { + setAdminContent(next) + onSave(next) + } + async function handleLogin(e: React.FormEvent) { e.preventDefault() setSubmitting(true) @@ -1714,7 +1745,7 @@ function AdminShell({ content, onSave }: { content: SiteContent; onSave: (c: Sit } if (status === 'authenticated') { - return + return } return (