// Portfolio Data - In a real app, this would come from an API const portfolioData = { categories: [ { id: 'ads', title: 'Commercial Ads', description: 'Professional advertising campaigns and promotional content', videos: [ { id: 1, title: 'Tech Startup Launch', thumbnail: 'http://static.photos/technology/320x240/1', duration: '2:30', views: '15.2K', description: 'Dynamic product launch campaign for innovative tech company', videoUrl: '#', tags: ['Technology', 'Corporate', 'Branding'] }, { id: 2, title: 'Fashion Brand Campaign', thumbnail: 'http://static.photos/retail/320x240/2', duration: '1:45', views: '23.7K', description: 'High-fashion brand identity video for luxury clothing line', videoUrl: '#', tags: ['Fashion', 'Luxury', 'Lifestyle'] } ] }, { id: 'music-videos', title: 'Music Videos', description: 'Creative visual storytelling for musical artists', videos: [ { id: 3, title: 'Indie Rock Journey', thumbnail: 'http://static.photos/music/320x240/3', duration: '4:15', views: '89.4K', description: 'Narrative music video following band tour experience', videoUrl: '#', tags: ['Music', 'Tour', 'Narrative'] }, { id: 4, title: 'Electronic Visualizer', thumbnail: 'http://static.photos/abstract/320x240/4', duration: '3:20', views: '45.1K', description: 'Abstract visual experience for electronic music track', videoUrl: '#', tags: ['Electronic', 'Abstract', 'Visual'] } ] }, { id: 'weddings', title: 'Wedding Films', description: 'Emotional storytelling for life\'s most precious moments', videos: [ { id: 5, title: 'Mountain Wedding', thumbnail: 'http://static.photos/nature/320x240/5', duration: '8:30', views: '12.8K', description: 'Breathtaking outdoor wedding ceremony and celebration', videoUrl: '#', tags: ['Outdoor', 'Romantic', 'Nature'] }, { id: 6, title: 'Urban Celebration', thumbnail: 'http://static.photos/cityscape/320x240/6', duration: '6:45', views: '9.3K', description: 'Modern city wedding with rooftop reception', videoUrl: '#', tags: ['Urban', 'Modern', 'Celebration'] } ] }, { id: 'travel', title: 'Travel Content', description: 'Capturing the beauty and essence of destinations worldwide', videos: [ { id: 7, title: 'Japanese Adventure', thumbnail: 'http://static.photos/travel/320x240/7', duration: '5:10', views: '67.2K', description: 'Cultural exploration through Japan\'s most iconic locations', videoUrl: '#', tags: ['Japan', 'Culture', 'Adventure'] }, { id: 8, title: 'European Summer', thumbnail: 'http://static.photos/aerial/320x240/8', duration: '4:45', views: '52.9K', description: 'Summer journey across Mediterranean coastlines', videoUrl: '#', tags: ['Europe', 'Summer', 'Coastal'] } ] }, { id: 'corporate', title: 'Corporate Videos', description: 'Professional business communication and brand storytelling', videos: [ { id: 9, title: 'Company Culture', thumbnail: 'http://static.photos/office/320x240/9', duration: '3:15', views: '8.7K', description: 'Internal culture video showcasing team values and environment', videoUrl: '#', tags: ['Corporate', 'Culture', 'Internal'] }, { id: 10, title: 'Annual Report', thumbnail: 'http://static.photos/finance/320x240/10', duration: '2:50', views: '6.3K', description: 'Animated financial report with company achievements', videoUrl: '#', tags: ['Finance', 'Report', 'Animation'] } ] }, { id: 'reels', title: 'Social Media Reels', description: 'Engaging short-form content optimized for social platforms', videos: [ { id: 11, title: 'Viral Challenge', thumbnail: 'http://static.photos/gaming/320x240/11', duration: '0:45', views: '245K', description: 'Trending dance challenge with creative transitions', videoUrl: '#', tags: ['Trending', 'Dance', 'Viral'] }, { id: 12, title: 'Brand Awareness', thumbnail: 'http://static.photos/minimal/320x240/12', duration: '0:30', views: '189K', description: 'Quick brand message with engaging visual effects', videoUrl: '#', tags: ['Brand', 'Awareness', 'Effects'] } ] }, { id: 'documentary', title: 'Documentary', description: 'In-depth storytelling and real-life narratives', videos: [ { id: 13, title: 'Environmental Impact', thumbnail: 'http://static.photos/science/320x240/13', duration: '12:30', views: '34.6K', description: 'Climate change documentary featuring expert interviews', videoUrl: '#', tags: ['Environment', 'Science', 'Interview'] }, { id: 14, title: 'Community Stories', thumbnail: 'http://static.photos/people/320x240/14', duration: '15:45', views: '28.9K', description: 'Local community resilience and cultural preservation', videoUrl: '#', tags: ['Community', 'Culture', 'Resilience'] } ] } ] }; // Initialize the portfolio document.addEventListener('DOMContentLoaded', function() { initializePortfolio(); setupEventListeners(); }); function initializePortfolio() { const container = document.getElementById('portfolio-container'); portfolioData.categories.forEach(category => { const categorySection = createCategorySection(category); container.appendChild(categorySection); }); } function createCategorySection(category) { const section = document.createElement('section'); section.className = 'mb-12 fade-in-up'; section.innerHTML = `

${category.title}

${category.description}

${category.videos.map(video => `
${video.title}
${video.duration}

${video.title}

${video.views} views

${video.tags.map(tag => ` ${tag} `).join('')}
`).join('')}
`; return section; } function setupEventListeners() { // Video thumbnail click handler document.addEventListener('click', function(e) { const thumbnail = e.target.closest('.video-thumbnail'); if (thumbnail) { const videoId = thumbnail.getAttribute('data-video-id'); openVideoModal(videoId); } }); // Navigation scroll behavior window.addEventListener('scroll', throttle(handleScroll, 100)); } function openVideoModal(videoId) { const modal = document.querySelector('custom-video-modal'); if (modal) { modal.setAttribute('video-id', videoId); modal.setAttribute('open', 'true'); } } function handleScroll() { const nav = document.querySelector('custom-navigation'); if (window.scrollY > 100) { nav.setAttribute('scrolled', 'true'); } else { nav.setAttribute('scrolled', 'false'); } } // Utility function to throttle events function throttle(func, limit) { let inThrottle; return function() { const args = arguments; const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } } } // Export for use in components if needed window.portfolioData = portfolioData;