86 lines
2.7 KiB
JavaScript
86 lines
2.7 KiB
JavaScript
const CLIPS_JSON_URL = '/data/clips.json';
|
|
|
|
const clipPlaySVG = '<svg viewBox="0 0 24 24" fill="#fff"><path d="M8 5v14l11-7z"/></svg>';
|
|
|
|
function renderClipCard(clip, featured) {
|
|
const card = document.createElement('div');
|
|
card.className = 'clip-card' + (featured ? ' clip-card-featured' : '');
|
|
if (clip.youtube_id) card.dataset.youtubeId = clip.youtube_id;
|
|
|
|
const hasVideo = !!clip.youtube_id;
|
|
const epLabel = clip.episode_number ? `Episode ${clip.episode_number}` : '';
|
|
|
|
const thumbStyle = clip.thumbnail
|
|
? `style="background-image: url('/${clip.thumbnail}'); background-size: cover; background-position: center;"`
|
|
: '';
|
|
|
|
card.innerHTML = `
|
|
<div class="clip-card-inner" ${thumbStyle}>
|
|
<div class="clip-card-overlay">
|
|
<span class="clip-episode-label">${epLabel}</span>
|
|
<h3 class="clip-card-title">${clip.title || ''}</h3>
|
|
<p class="clip-card-desc">${clip.description || ''}</p>
|
|
${hasVideo ? `<button class="clip-play-btn" aria-label="Play clip">${clipPlaySVG}</button>` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
if (hasVideo) {
|
|
card.querySelector('.clip-play-btn').addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
const inner = card.querySelector('.clip-card-inner');
|
|
inner.innerHTML = `<iframe src="https://www.youtube-nocookie.com/embed/${clip.youtube_id}?autoplay=1&rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>`;
|
|
});
|
|
}
|
|
|
|
return card;
|
|
}
|
|
|
|
async function fetchClips() {
|
|
try {
|
|
const res = await fetch(CLIPS_JSON_URL);
|
|
if (!res.ok) throw new Error('Failed to fetch clips');
|
|
return await res.json();
|
|
} catch (err) {
|
|
console.error('Error loading clips:', err);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async function initClipsPage() {
|
|
const clips = await fetchClips();
|
|
if (!clips.length) return;
|
|
|
|
const featuredContainer = document.querySelector('.clips-featured');
|
|
const gridContainer = document.querySelector('.clips-grid');
|
|
|
|
if (featuredContainer) {
|
|
clips.filter(c => c.featured).forEach(clip => {
|
|
featuredContainer.appendChild(renderClipCard(clip, true));
|
|
});
|
|
}
|
|
|
|
if (gridContainer) {
|
|
clips.forEach(clip => {
|
|
gridContainer.appendChild(renderClipCard(clip, false));
|
|
});
|
|
}
|
|
}
|
|
|
|
async function renderFeaturedClipsInline(containerId) {
|
|
const container = document.getElementById(containerId);
|
|
if (!container) return;
|
|
|
|
const clips = await fetchClips();
|
|
const featured = clips.filter(c => c.featured);
|
|
|
|
featured.forEach(clip => {
|
|
container.appendChild(renderClipCard(clip, true));
|
|
});
|
|
}
|
|
|
|
// Auto-init if clips page containers exist
|
|
if (document.querySelector('.clips-featured') || document.querySelector('.clips-grid')) {
|
|
initClipsPage();
|
|
}
|