diff --git a/server.js b/server.js
index a92825c..50100eb 100644
--- a/server.js
+++ b/server.js
@@ -68,7 +68,7 @@ app.use((_req, res, next) => {
'Content-Security-Policy',
[
"default-src 'self'",
- "script-src 'self' 'unsafe-inline'",
+ "script-src 'self' 'unsafe-inline' https://www.truthforlife.org https://ajax.googleapis.com",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"font-src 'self' https://fonts.gstatic.com",
"img-src 'self' data: https:",
diff --git a/src/App.tsx b/src/App.tsx
index aa12fd3..a4a7fce 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -6,7 +6,7 @@ import QASection from './components/QASection'
import ContactForm from './components/ContactForm'
import { ColossiansStudyIndexPage, ColossiansStudyNotesPage, ColossiansStudySectionPage, StudyLandingPage, StudySignupPage, StudyAccountPage, StudyCommunityPage, StudyQuizPage } from './colossiansStudy'
import { SpotifyIcon } from './icons'
-import type { SiteContent, ArchivedSeries, StudyProgram } from './content'
+import type { SiteContent, StudyProgram } from './content'
import { DEFAULTS } from './content'
import { usePageMeta } from './hooks/usePageMeta'
import { useGlobalSearch } from './hooks/useGlobalSearch'
@@ -253,18 +253,10 @@ function buildCustomResourceDownloadId(id: string) {
return `custom:${id}`
}
-function buildArchivedResourceDownloadId(seriesId: string, linkId: string) {
- return `archived:${seriesId}:${linkId}`
-}
-
function buildCustomDownloadPageId(id: string) {
return `custom--${id}`
}
-function buildArchivedDownloadPageId(seriesId: string, linkId: string) {
- return `archived--${seriesId}--${linkId}`
-}
-
interface DownloadPageResource {
id: string
label: string
@@ -298,25 +290,6 @@ function resolveDownloadPageResource(content: SiteContent, pageId: string | unde
}
}
- if (pageId.startsWith('archived--')) {
- const [, seriesId, linkId] = pageId.split('--')
- const series = (content.archivedSeries ?? []).find(item => item.id === seriesId)
- const link = (series?.resourceLinks ?? []).find(item => item.id === linkId)
- if (!series || !link) return null
-
- return {
- id: pageId,
- label: link.label || series.title || 'Download Resource',
- imageUrl: series.imageUrl,
- summary: link.description || series.description || 'Fill out the form below to access this download from a previous study.',
- tags: [],
- buttonText: `Download ${link.label || series.title || 'Resource'}`,
- resourceId: buildArchivedResourceDownloadId(series.id, link.id),
- amazonUrl: link.amazonUrl,
- amazonLabel: link.amazonLabel,
- }
- }
-
return null
}
@@ -368,23 +341,6 @@ function AnalyticsConsentBanner({ content }: { content: SiteContent }) {
)
}
-interface Episode {
- title: string
- pubDate: string
- link: string
- description: string
- duration: string
- episode: string
-}
-
-function formatPubDate(raw: string): string {
- try {
- return new Date(raw).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
- } catch {
- return raw
- }
-}
-
function SiteSearchBar({ content }: { content: SiteContent }) {
const { query, setQuery, results } = useGlobalSearch(content)
return (
@@ -730,53 +686,26 @@ function PodcastHighlightsSection({ content }: { content: SiteContent }) {
function DownloadLibrarySection({ content }: { content: SiteContent }) {
const resources = (content.customLinks ?? []).filter(link => link.placement === 'resources')
- const archivedWithResources = (content.archivedSeries ?? []).filter(series => (series.resourceLinks ?? []).length > 0)
const [activeTag, setActiveTag] = useState(null)
- const [activeType, setActiveType] = useState<'all' | 'resource' | 'series'>('all')
- if (resources.length === 0 && archivedWithResources.length === 0) return null
+ if (resources.length === 0) return null
const allTags = Array.from(new Set(resources.flatMap(r => r.tags ?? []))).filter(Boolean)
- // Filter resources
const filteredResources = resources.filter(r => {
- const tagOk = !activeTag || (r.tags ?? []).includes(activeTag)
- const typeOk = activeType === 'all' || activeType === 'resource'
- return tagOk && typeOk
+ return !activeTag || (r.tags ?? []).includes(activeTag)
})
- // Filter archived series
- const filteredArchived = archivedWithResources.filter(() => {
- return activeType === 'all' || activeType === 'series'
- })
-
- const hasTypeFilter = resources.length > 0 && archivedWithResources.length > 0
-
return (
Download Library
-
Guides, worksheets, and past study downloads.
+
Guides, worksheets, and study downloads.
- {/* Type + tag filter bar */}
-
- {hasTypeFilter && (
-
0 ? '0.5rem' : 0 }}>
- {(['all', 'resource', 'series'] as const).map(t => (
-
- ))}
-
- )}
- {allTags.length > 0 && (activeType === 'all' || activeType === 'resource') && (
+ {allTags.length > 0 && (
+
)}
- )}
-
+
+ )}
- {filteredResources.length > 0 && (
+ {filteredResources.length > 0 ? (
{filteredResources.map(resource => (
@@ -830,86 +759,18 @@ function DownloadLibrarySection({ content }: { content: SiteContent }) {
))}
- )}
-
- {activeTag !== null && filteredResources.length === 0 && activeType !== 'series' && (
+ ) : (
No downloads tagged "{activeTag}".
)}
-
- {filteredArchived.length > 0 && (
-
-
-
Previous Studies
-
Downloads from earlier series.
-
- {filteredArchived.map(series => (
-
-
-
{series.title || 'Archived Study'}
- {series.description &&
{series.description}
}
-
-
- {(series.resourceLinks ?? []).map(link => (
-
-
- {series.imageUrl && (
-

- )}
-
-
{link.label || series.title || 'Download Resource'}
- {link.description &&
{link.description}
}
-
Open download page →
-
-
-
- ))}
-
-
- ))}
-
- )}
)
}
-function useEpisodesForSeries(seriesId: string | null, archivedSeries: ArchivedSeries[]) {
- const [episodes, setEpisodes] = useState([])
- const [loading, setLoading] = useState(false)
-
- useEffect(() => {
- if (!seriesId) return
- const series = archivedSeries.find(s => s.id === seriesId)
- if (!series?.episodeRange) return
-
- setLoading(true)
- fetch('/api/episodes/all')
- .then(r => r.ok ? r.json() : Promise.reject())
- .then((data: { episodes?: Episode[] }) => {
- const { from, to } = series.episodeRange!
- const filtered = (data.episodes ?? []).filter(ep => {
- const num = parseInt(ep.episode, 10)
- return !isNaN(num) && num >= from && num <= to
- })
- setEpisodes(filtered)
- })
- .catch(() => {})
- .finally(() => setLoading(false))
- }, [seriesId])
-
- return { episodes, loading }
-}
-
function DownloadDetailPage({ content }: { content: SiteContent }) {
const { id } = useParams<{ id: string }>()
const resource = resolveDownloadPageResource(content, id)
- // Resolve related series for archived resources
- const archivedSeriesId = id?.startsWith('archived--') ? id.split('--')[1] : null
- const relatedSeries = archivedSeriesId ? (content.archivedSeries ?? []).find(s => s.id === archivedSeriesId) : null
- const { episodes: relatedEpisodes, loading: epsLoading } = useEpisodesForSeries(archivedSeriesId, content.archivedSeries ?? [])
- const spotifyUrl = content.platformSpotifyUrl || '/episodes'
-
if (!resource) {
return (
@@ -953,39 +814,6 @@ function DownloadDetailPage({ content }: { content: SiteContent }) {
Back to Downloads
- {relatedSeries && (relatedEpisodes.length > 0 || epsLoading) && (
-
-
- Episodes from {relatedSeries.title}
-
- {epsLoading ? (
-
Loading episodes…
- ) : (
-
- )}
-
- )}
)
@@ -1140,28 +968,23 @@ function HomepageNewsletterSection() {
type TflWidgetType = 'audiodevo' | 'abdevotional' | 'resourcead'
function TruthForLifeWidget({ type = 'audiodevo' }: { type?: TflWidgetType }) {
- const iframeHeight = type === 'audiodevo' ? '420' : type === 'resourcead' ? '270' : '800'
const heading = type === 'resourcead' ? 'Recommended Resources' : 'Daily Devotional'
+ const containerId = 'tfl-syndicate-container'
- const srcdoc = `
-
-
-
-
-
-
-
-
-
-`
+ useEffect(() => {
+ const container = document.getElementById(containerId)
+ if (!container) return
+ container.innerHTML = ''
+
+ const existing = document.getElementById('syn_script')
+ if (existing) existing.remove()
+
+ const script = document.createElement('script')
+ script.id = 'syn_script'
+ script.src = `https://www.truthforlife.org/static/js/responsive/lib/syndicate.js?type=${type}&id=458890`
+ script.type = 'text/javascript'
+ container.parentElement?.insertBefore(script, container)
+ }, [type, containerId])
return (
@@ -1176,13 +999,9 @@ function TruthForLifeWidget({ type = 'audiodevo' }: { type?: TflWidgetType }) {
-
@@ -2233,7 +2052,7 @@ function PreviewPage() {
if (previewView === 'start-here') return
if (previewView === 'about') return
if (previewView === 'contact') return
- if (previewView === 'current-series' || previewView === 'archived-series' || previewView === 'episode-highlights') {
+ if (previewView === 'current-series' || previewView === 'episode-highlights') {
return
}
return
@@ -2296,7 +2115,6 @@ export default function App() {
'#qa': '/questions',
'#contact': '/contact',
'#series': '/resources',
- '#archives': '/resources',
'#resources': '/resources',
'#start-here': '/start-here',
}