diff --git a/src/App.tsx b/src/App.tsx index e43ff30..a8419e5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,8 +14,7 @@ import { GlobalSearch } from './components/GlobalSearch' import { EpisodeAudioPlayer } from './components/EpisodeAudioPlayer' import './App.css' -const SPOTIFY_EMBED_URL = - 'https://open.spotify.com/embed/show/0Gq1TzoJOdReSZ1gYQi8Xl?utm_source=generator&theme=0' + const CONSENT_KEY = 'vbn_analytics_consent_choice' const HEADLINER_WIDGET_ID = 'WI_cmou3b4q7000701p0o9qmmcfj' @@ -764,7 +763,7 @@ function PodcastHighlightsSection({ content }: { content: SiteContent }) { Podcast Highlights{' '} -
+
{links.map(link => { const hasRichContent = !!( link.embedUrl @@ -772,19 +771,31 @@ function PodcastHighlightsSection({ content }: { content: SiteContent }) { || (link.discussionQuestions ?? []).length > 0 || link.showNotes ) - const label = <>{link.episodeNumber ? `Ep. ${link.episodeNumber}: ` : ''}{link.title || link.url} - // Use external link only when there's a url AND no rich detail-page content - if (!hasRichContent && link.url) { + const dest = (!hasRichContent && link.url) + ? { external: link.url } + : { internal: `/episodes/${link.id}` } + + const inner = ( + <> +
+ {link.episodeNumber && Ep. {link.episodeNumber}} +
+

{link.title || link.url}

+ {link.summary &&

{link.summary}

} + Listen → + + ) + + if ('external' in dest) { return ( - - {label} + + {inner} ) } - // Otherwise always route to the internal detail page return ( - - {label} + + {inner} ) })} @@ -1613,106 +1624,12 @@ function EpisodeDetailPage({ content }: { content: SiteContent }) { } function EpisodesPage({ content }: { content: SiteContent }) { - const [allEpisodes, setAllEpisodes] = useState([]) - const [loading, setLoading] = useState(true) - const [failed, setFailed] = useState(false) const siteTitle = content.seo?.title || DEFAULTS.seo.title usePageMeta( `Episodes | ${siteTitle}`, content.episodesSeoIntro || 'Browse all episodes of Verse by Verse with Nate — expository Bible teaching, one verse at a time.', ) - useEffect(() => { - fetch('/api/episodes/all') - .then(r => (r.ok ? r.json() : Promise.reject(new Error('fetch failed')))) - .then((data: { episodes: Episode[] }) => { - if (data.episodes.length === 0) setFailed(true) - else setAllEpisodes(data.episodes) - setLoading(false) - }) - .catch(() => { - setFailed(true) - setLoading(false) - }) - }, []) - - const archivedSeries = content.archivedSeries ?? [] - - const archivedEpisodeNums = new Set( - archivedSeries.flatMap(s => { - if (!s.episodeRange) return [] - const nums: number[] = [] - for (let i = s.episodeRange.from; i <= s.episodeRange.to; i++) nums.push(i) - return nums - }) - ) - - const currentEpisodes = allEpisodes.filter(ep => { - const num = parseInt(ep.episode, 10) - return isNaN(num) || !archivedEpisodeNums.has(num) - }) - - function episodesForSeries(series: ArchivedSeries) { - if (!series.episodeRange) return [] - const { from, to } = series.episodeRange - return allEpisodes.filter(ep => { - const num = parseInt(ep.episode, 10) - return !isNaN(num) && num >= from && num <= to - }) - } - - function renderEpisodeCards(episodes: Episode[]) { - return ( -
- {episodes.map((ep, idx) => ( - -
- {ep.episode && Ep. {ep.episode}} - {ep.pubDate && {formatPubDate(ep.pubDate)}} - {ep.duration && {ep.duration}} -
-

{ep.title}

- {ep.description &&

{ep.description}

} - - Listen → - -
- ))} -
- ) - } - - const spotifyFallback = ( -
-