File size: 4,735 Bytes
1966bcd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
// Fetch YouTube videos from API
async function fetchVideos() {
try {
// Using a mock API since YouTube API requires authentication
const response = await fetch('https://youtube-v31.p.rapidapi.com/search?q=music&part=snippet&maxResults=24', {
method: 'GET',
headers: {
'X-RapidAPI-Key': 'your-api-key',
'X-RapidAPI-Host': 'youtube-v31.p.rapidapi.com'
}
});
// Fallback to mock data if API fails
if (!response.ok) {
return getMockVideos();
}
const data = await response.json();
return data.items;
} catch (error) {
console.error('Error fetching videos:', error);
return getMockVideos();
}
}
// Mock data for fallback
function getMockVideos() {
return Array(12).fill().map((_, i) => ({
id: { videoId: `mock${i}` },
snippet: {
title: `Awesome Video ${i + 1}`,
channelTitle: `Channel ${i + 1}`,
thumbnails: {
medium: {
url: `http://static.photos/technology/320x240/${i + 100}`
}
},
publishedAt: new Date().toISOString()
}
}));
}
// Render videos to the page
async function renderVideos() {
const videos = await fetchVideos();
const container = document.querySelector('main .grid');
videos.forEach((video, index) => {
const videoCard = document.createElement('custom-video-card');
videoCard.setAttribute('video-id', video.id.videoId);
videoCard.setAttribute('title', video.snippet.title);
videoCard.setAttribute('channel', video.snippet.channelTitle);
videoCard.setAttribute('thumbnail', video.snippet.thumbnails.medium.url);
videoCard.setAttribute('published', video.snippet.publishedAt);
videoCard.style.animationDelay = `${0.1 * (index % 8)}s`;
container.appendChild(videoCard);
});
}
// Initialize the app
document.addEventListener('DOMContentLoaded', () => {
renderVideos();
setupMobileNavigation();
// Toggle dark mode
const html = document.documentElement;
const darkModeToggle = document.createElement('button');
darkModeToggle.innerHTML = '<i data-feather="moon"></i>';
darkModeToggle.className = 'p-2 rounded-full hover:bg-gray-700';
darkModeToggle.addEventListener('click', () => {
html.classList.toggle('dark');
feather.replace();
});
document.querySelector('custom-navbar').shadowRoot.querySelector('.right-section').appendChild(darkModeToggle);
feather.replace();
});
// Mobile navigation setup
function setupMobileNavigation() {
const mobileMenuBtn = document.querySelector('custom-navbar').shadowRoot.querySelector('.mobile-menu-btn');
const sidebar = document.querySelector('custom-sidebar');
const overlay = sidebar.shadowRoot.querySelector('.overlay');
if (mobileMenuBtn && sidebar && overlay) {
mobileMenuBtn.addEventListener('click', () => {
const sidebarElement = sidebar.shadowRoot.querySelector('.sidebar');
sidebarElement.classList.toggle('open');
overlay.classList.toggle('open');
});
overlay.addEventListener('click', () => {
const sidebarElement = sidebar.shadowRoot.querySelector('.sidebar');
sidebarElement.classList.remove('open');
overlay.classList.remove('open');
});
// Close sidebar when clicking on a sidebar item on mobile
const sidebarItems = sidebar.shadowRoot.querySelectorAll('.sidebar-item');
sidebarItems.forEach(item => {
item.addEventListener('click', () => {
if (window.innerWidth < 768) {
const sidebarElement = sidebar.shadowRoot.querySelector('.sidebar');
sidebarElement.classList.remove('open');
overlay.classList.remove('open');
}
});
});
}
}
// Responsive grid layout
function updateGridLayout() {
const container = document.querySelector('main .grid');
if (!container) return;
if (window.innerWidth < 640) {
container.className = 'grid grid-cols-1 gap-3 mobile-p-2';
} else if (window.innerWidth < 768) {
container.className = 'grid grid-cols-2 gap-3';
} else if (window.innerWidth < 1024) {
container.className = 'grid grid-cols-3 gap-4';
} else {
container.className = 'grid grid-cols-4 gap-4';
}
}
// Listen for window resize
window.addEventListener('resize', updateGridLayout);
window.addEventListener('load', updateGridLayout);
|