Generalize study release-date gating across all studies

This commit is contained in:
nmemmert
2026-05-21 12:29:57 -04:00
parent 74e9f57ea5
commit da5f77c3c6
2 changed files with 46 additions and 13 deletions
+19 -3
View File
@@ -114,10 +114,26 @@ function sanitizeUrl(value) {
return '' return ''
} }
function getSectionReleaseTime(section) {
if (!section || typeof section !== 'object') return Number.NaN
const candidateValues = [
section.releasedAt,
section.releaseDate,
section.availableAt,
section.publishAt,
]
for (const candidate of candidateValues) {
if (typeof candidate !== 'string' || !candidate.trim()) continue
const releaseTime = Date.parse(candidate)
if (Number.isFinite(releaseTime)) return releaseTime
}
return Number.NaN
}
function isSectionReleased(section) { function isSectionReleased(section) {
if (!section || typeof section !== 'object') return false const releaseTime = getSectionReleaseTime(section)
if (typeof section.releasedAt !== 'string' || !section.releasedAt.trim()) return false
const releaseTime = Date.parse(section.releasedAt)
if (!Number.isFinite(releaseTime)) return false if (!Number.isFinite(releaseTime)) return false
return releaseTime <= Date.now() return releaseTime <= Date.now()
} }
+27 -10
View File
@@ -97,31 +97,47 @@ function getChapterSummaries(study: StudyProgram) {
}) })
} }
function getSectionReleaseDate(section: StudySection): Date | null {
const candidateValues = [
section?.releasedAt,
(section as StudySection & { releaseDate?: string }).releaseDate,
(section as StudySection & { availableAt?: string }).availableAt,
(section as StudySection & { publishAt?: string }).publishAt,
]
for (const candidate of candidateValues) {
if (typeof candidate !== 'string' || !candidate.trim()) continue
const parsed = new Date(candidate)
if (!Number.isNaN(parsed.getTime())) return parsed
}
return null
}
function isNewLesson(section: StudySection): boolean { function isNewLesson(section: StudySection): boolean {
if (!section.releasedAt) return false const releaseDate = getSectionReleaseDate(section)
const releaseDate = new Date(section.releasedAt) if (!releaseDate) return false
const now = new Date() const now = new Date()
const daysSinceRelease = (now.getTime() - releaseDate.getTime()) / (1000 * 60 * 60 * 24) const daysSinceRelease = (now.getTime() - releaseDate.getTime()) / (1000 * 60 * 60 * 24)
return daysSinceRelease >= 0 && daysSinceRelease <= 14 return daysSinceRelease >= 0 && daysSinceRelease <= 14
} }
function isComingSoon(section: StudySection): boolean { function isComingSoon(section: StudySection): boolean {
if (!section.releasedAt) return false const releaseDate = getSectionReleaseDate(section)
const releaseDate = new Date(section.releasedAt) if (!releaseDate) return false
const now = new Date() const now = new Date()
return releaseDate > now return releaseDate > now
} }
function isSectionReleased(section: StudySection): boolean { function isSectionReleased(section: StudySection): boolean {
if (!section.releasedAt) return false const releaseDate = getSectionReleaseDate(section)
const releaseDate = new Date(section.releasedAt) if (!releaseDate) return false
if (Number.isNaN(releaseDate.getTime())) return false
return releaseDate <= new Date() return releaseDate <= new Date()
} }
function getReleaseDateDisplay(section: StudySection): string { function getReleaseDateDisplay(section: StudySection): string {
if (!section.releasedAt) return '' const date = getSectionReleaseDate(section)
const date = new Date(section.releasedAt) if (!date) return ''
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
} }
@@ -765,12 +781,13 @@ export function ColossiansStudySectionPage({ content }: Props) {
} }
if (!sectionIsReleased) { if (!sectionIsReleased) {
const releaseDateDisplay = getReleaseDateDisplay(section)
return ( return (
<main className="thanks-page" aria-label="Lesson not yet available"> <main className="thanks-page" aria-label="Lesson not yet available">
<div className="thanks-card"> <div className="thanks-card">
<p className="eyebrow">{study.title}</p> <p className="eyebrow">{study.title}</p>
<h1>Lesson Coming Soon</h1> <h1>Lesson Coming Soon</h1>
<p>This lesson will be available on {getReleaseDateDisplay(section)}.</p> <p>{releaseDateDisplay ? `This lesson will be available on ${releaseDateDisplay}.` : 'This lesson will be available soon.'}</p>
<Link to={`/study/${study.slug}`} className="btn-primary">Back to Lessons</Link> <Link to={`/study/${study.slug}`} className="btn-primary">Back to Lessons</Link>
</div> </div>
</main> </main>