// FlowFlex - Main JavaScript class FlowFlexApp { constructor() { this.currentFeed = 'trending'; this.posts = []; this.seenPosts = new Set(); this.userPreferences = this.getUserPreferences(); this.isLoading = false; this.page = 1; this.init(); } init() { this.bindEvents(); this.loadInitialFeed(); this.setupIntersectionObserver(); this.checkAuthStatus(); } bindEvents() { // Feed filter buttons document.querySelectorAll('.feed-filter-btn').forEach(btn => { btn.addEventListener('click', (e) => { this.switchFeed(e.target.closest('.feed-filter-btn').dataset.filter); }); // Like button functionality document.addEventListener('click', (e) => { if (e.target.closest('.like-btn')) { this.handleLike(e.target.closest('.like-btn')); }); // Save post functionality document.addEventListener('click', (e) => { if (e.target.closest('.save-btn')) { this.handleSave(e.target.closest('.save-btn')); } // Post interaction tracking document.addEventListener('click', (e) => { const postCard = e.target.closest('.post-card'); if (postCard) { this.trackPostInteraction(postCard.dataset.postId); } // Auth modal triggers document.addEventListener('click', (e) => { if (e.target.closest('[data-auth-trigger]')) { this.showAuthModal(); } }); } switchFeed(feedType) { // Update active button document.querySelectorAll('.feed-filter-btn').forEach(btn => { btn.classList.remove('active', 'bg-primary-500', 'text-white'); btn.classList.add('bg-gray-200', 'text-gray-700'); }); const activeBtn = document.querySelector(`[data-filter="${feedType}"]`); activeBtn.classList.remove('bg-gray-200', 'text-gray-700'); activeBtn.classList.add('active', 'bg-primary-500', 'text-white'); this.currentFeed = feedType; this.page = 1; this.posts = []; this.loadFeed(); } async loadInitialFeed() { await this.loadFeed(); } async loadFeed() { if (this.isLoading) return; this.isLoading = true; this.showLoading(); try { // Simulate API call with timeout await new Promise(resolve => setTimeout(resolve, 1000)); const newPosts = await this.fetchPosts(this.currentFeed, this.page); const filteredPosts = this.filterDuplicatePosts(newPosts); if (filteredPosts.length > 0) { this.posts = [...this.posts, ...filteredPosts]; this.renderPosts(filteredPosts); this.page++; } else { this.showEmptyState(); } } catch (error) { console.error('Error loading feed:', error); this.showError('Failed to load posts. Please try again.'); } finally { this.isLoading = false; this.hideLoading(); } } async fetchPosts(feedType, page = 1) { // Using Unsplash API for demo posts (real implementation would use your backend) const accessKey = 'YOUR_UNSPLASH_ACCESS_KEY'; // Replace with actual key const endpoints = { trending: `https://api.unsplash.com/photos?page=${page}&per_page=9&order_by=popular`, following: `https://api.unsplash.com/photos?page=${page}&per_page=9&order_by=latest`, discover: `https://api.unsplash.com/photos/random?count=9`, personalized: `https://api.unsplash.com/photos?page=${page}&per_page=9` }; // For demo purposes, we'll use mock data return this.generateMockPosts(9); } generateMockPosts(count) { const categories = ['nature', 'technology', 'travel', 'food', 'architecture', 'people']; const users = [ { name: 'Alex Johnson', username: 'alexj', followers: 1243 }, { name: 'Sarah Miller', username: 'sarahm', followers: 856 }, { name: 'Mike Chen', username: 'mikec', followers: 2107 }, { name: 'Emma Davis', username: 'emmad', followers: 932 }, { name: 'James Wilson', username: 'jamesw', followers: 1541 } ]; return Array.from({ length: count }, (_, i) => { const user = users[Math.floor(Math.random() * users.length)]; const category = categories[Math.floor(Math.random() * categories.length)]; const postId = `post_${Date.now()}_${i}`; return { id: postId, user: user, image: `http://static.photos/${category}/640x360/${i + 1}`, caption: this.generateMockCaption(category), likes: Math.floor(Math.random() * 1000), comments: Math.floor(Math.random() * 50), shares: Math.floor(Math.random() * 20), timestamp: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000), // Within last 7 days category: category, engagement: Math.random() * 100 }; }); } generateMockCaption(category) { const captions = { nature: ['Beautiful sunset at the beach! π ', 'Morning hike in the mountains ποΈ', 'Peaceful forest walk π²'], technology: ['Working on some exciting new projects! π»', 'Tech conference was amazing! π', 'Latest gadget unboxing π±'], travel: ['Exploring new places! βοΈ', 'Cultural experience of a lifetime π', 'Travel dreams coming true πΊοΈ'], food: ['Delicious homemade meal! π½οΈ', 'Food photography session πΈ', 'Trying out new recipes π¨βπ³'], architecture: ['Modern architecture never fails to impress! ποΈ', 'Historical building tour π°', 'Architectural marvels ποΈ'], people: ['Great time with friends! π₯', 'Community event was fantastic! π', 'Networking and making connections π€'] }; const categoryCaptions = captions[category] || ['Great day! π']; return categoryCaptions[Math.floor(Math.random() * categoryCaptions.length)]; } filterDuplicatePosts(newPosts) { return newPosts.filter(post => !this.seenPosts.has(post.id)); } renderPosts(posts) { const feedContainer = document.getElementById('feed-container'); const emptyState = document.getElementById('empty-state'); if (posts.length === 0 && this.posts.length === 0) { this.showEmptyState(); return; } emptyState.classList.add('hidden'); posts.forEach(post => { this.seenPosts.add(post.id); const postElement = this.createPostElement(post); feedContainer.appendChild(postElement); }); } createPostElement(post) { const postDiv = document.createElement('div'); postDiv.className = 'post-card bg-white rounded-xl shadow-sm overflow-hidden fade-in'; postDiv.dataset.postId = post.id; const timeAgo = this.getTimeAgo(post.timestamp); postDiv.innerHTML = `
@${post.user.username}
${post.caption}