Add podcast platform badges and Headliner widget
This commit is contained in:
+32
@@ -460,6 +460,25 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.headliner-widget-wrap {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.headliner-widget-frame {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 580px;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.headliner-widget-empty {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
color: rgba(255, 255, 255, 0.72);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.platform-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -495,6 +514,19 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.platform-btn-image {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.platform-badge {
|
||||
display: block;
|
||||
width: 150px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* ── About ── */
|
||||
.section-about {
|
||||
background: #0d0d0d;
|
||||
|
||||
+84
-14
@@ -11,6 +11,69 @@ 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'
|
||||
|
||||
function HeadlinerWidget() {
|
||||
const [iframeSrc, setIframeSrc] = useState('')
|
||||
const [status, setStatus] = useState<'loading' | 'ready' | 'empty'>('loading')
|
||||
|
||||
useEffect(() => {
|
||||
const getDiscoUrl = () => {
|
||||
const canonicalHref = document.querySelector('link[rel="canonical"]')?.getAttribute('href')
|
||||
const ogUrl = document.querySelector('meta[property="og:url"]')?.getAttribute('content')
|
||||
const base = canonicalHref || ogUrl
|
||||
if (!base) return window.location.href
|
||||
try {
|
||||
const parsed = new URL(base)
|
||||
return `${parsed.origin}${window.location.pathname}`
|
||||
} catch {
|
||||
return window.location.href
|
||||
}
|
||||
}
|
||||
|
||||
const discoUrl = getDiscoUrl()
|
||||
const discoTitle = document.querySelector('meta[property="og:title"]')?.getAttribute('content') || document.title
|
||||
const src = `https://disco.headliner.link/d/web/widget.html?widgetId=${encodeURIComponent(HEADLINER_WIDGET_ID)}&url=${encodeURIComponent(discoUrl)}&title=${encodeURIComponent(discoTitle)}`
|
||||
|
||||
const sessionId = `SS_siteforge_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`
|
||||
const query = new URLSearchParams({
|
||||
sessionId,
|
||||
url: discoUrl,
|
||||
widgetId: HEADLINER_WIDGET_ID,
|
||||
})
|
||||
|
||||
fetch(`https://api.headliner.link/api/v1/widget/widget-request?${query.toString()}`)
|
||||
.then(r => (r.ok ? r.json() : Promise.reject(new Error('widget request failed'))))
|
||||
.then((data: { results?: unknown[] }) => {
|
||||
if (Array.isArray(data.results) && data.results.length > 0) {
|
||||
setIframeSrc(src)
|
||||
setStatus('ready')
|
||||
return
|
||||
}
|
||||
setStatus('empty')
|
||||
})
|
||||
.catch(() => {
|
||||
// If API probing fails, still attempt iframe rendering.
|
||||
setIframeSrc(src)
|
||||
setStatus('ready')
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
status === 'empty' ? null : (
|
||||
<div className="headliner-widget-wrap" aria-label="Featured listening widget">
|
||||
{status === 'ready' && iframeSrc && (
|
||||
<iframe
|
||||
src={iframeSrc}
|
||||
title="Featured listening widget"
|
||||
loading="lazy"
|
||||
className="headliner-widget-frame"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
function StudyDownloadForm({ buttonText = 'Download Guide' }: { buttonText?: string }) {
|
||||
const [fields, setFields] = useState({ firstName: '', lastName: '', email: '' })
|
||||
@@ -421,28 +484,34 @@ function PlatformButtons({ content }: { content: SiteContent }) {
|
||||
|
||||
return (
|
||||
<div className="platform-buttons">
|
||||
<a href={spotifyUrl} target="_blank" rel="noreferrer" className="platform-btn spotify-btn">
|
||||
<SpotifyIcon />
|
||||
Listen on Spotify
|
||||
<a href={appleUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
|
||||
<img src="/images/apple-podcasts-badge.svg" alt="Listen on Apple Podcasts" className="platform-badge" />
|
||||
</a>
|
||||
<a href={youtubeUrl} target="_blank" rel="noreferrer" className="platform-btn youtube-btn">
|
||||
<YouTubeIcon />
|
||||
YouTube
|
||||
<a href={spotifyUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
|
||||
<img src="/images/listen-on-spotify.svg" alt="Listen on Spotify" className="platform-badge" />
|
||||
</a>
|
||||
<a href={amazonUrl} target="_blank" rel="noreferrer" className="platform-btn amazon-btn">
|
||||
<AmazonMusicIcon />
|
||||
Amazon Music
|
||||
<a href={youtubeUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
|
||||
<img src="/images/watch-on-youtube.svg" alt="Watch on YouTube" className="platform-badge" />
|
||||
</a>
|
||||
<a href={amazonUrl} target="_blank" rel="noreferrer" className="platform-btn platform-btn-image">
|
||||
<img src="/images/listen-on-amazon-music.svg" alt="Listen on Amazon Music" className="platform-badge" />
|
||||
</a>
|
||||
<a href={facebookUrl} target="_blank" rel="noreferrer" className="platform-btn facebook-btn">
|
||||
<FacebookIcon />
|
||||
Facebook
|
||||
</a>
|
||||
<a href={appleUrl} target="_blank" rel="noreferrer" className="platform-btn apple-btn">
|
||||
<img src="/images/apple-podcasts-badge.svg" alt="Listen on Apple Podcasts" className="apple-badge" />
|
||||
</a>
|
||||
{(content.customLinks ?? []).filter(l => l.placement === 'platforms').map(l => (
|
||||
<a key={l.id} href={l.url} target="_blank" rel="noreferrer" className="platform-btn custom-btn">
|
||||
{l.label}
|
||||
<a
|
||||
key={l.id}
|
||||
href={l.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={`platform-btn ${l.imageUrl ? 'platform-btn-image' : 'custom-btn'}`}
|
||||
aria-label={`Listen on ${l.label}`}
|
||||
>
|
||||
{l.imageUrl
|
||||
? <img src={l.imageUrl} alt={`Listen on ${l.label}`} className="platform-badge" />
|
||||
: l.label}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
@@ -1100,6 +1169,7 @@ function EpisodesPage({ content }: { content: SiteContent }) {
|
||||
? spotifyFallback
|
||||
: renderEpisodeCards(currentEpisodes)}
|
||||
<PlatformButtons content={content} />
|
||||
<HeadlinerWidget />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user