document.addEventListener('DOMContentLoaded', () => { const form = document.getElementById('searchForm'); const resultsContainer = document.getElementById('resultsContainer'); const resultsDiv = document.getElementById('results'); const loadingDiv = document.getElementById('loading'); const copyAllBtn = document.getElementById('copyAllBtn'); // Mock data - in a real implementation, this would call a Bluesky API const mockPosts = [ { author: { handle: "nba.bsky.social", displayName: "NBA Official", avatar: "https://static.photos/sport/200x200/1" }, text: "Breaking: The Lakers have just signed a new point guard to bolster their roster for the playoffs! ๐๐ฅ #LakeShow", reposts: 42, timestamp: "2 hours ago", url: "https://bsky.app/profile/nba.bsky.social/post/123" }, { author: { handle: "wojespn.bsky.social", displayName: "Adrian Wojnarowski", avatar: "https://static.photos/people/200x200/2" }, text: "Sources: LeBron James expected to return from injury for the first round of playoffs. Big boost for LA.", reposts: 89, timestamp: "1 hour ago", url: "https://bsky.app/profile/wojespn.bsky.social/post/456" }, { author: { handle: "shams.bsky.social", displayName: "Shams Charania", avatar: "https://static.photos/people/200x200/3" }, text: "The Phoenix Suns are finalizing a deal with veteran center DeAndre Jordan, sources tell @TheAthletic.", reposts: 56, timestamp: "2.5 hours ago", url: "https://bsky.app/profile/shams.bsky.social/post/789" } ]; form.addEventListener('submit', async (e) => { e.preventDefault(); const topic = document.getElementById('topic').value.trim(); const hours = document.getElementById('hours').value; const minReposts = parseInt(document.getElementById('minReposts').value); if (!topic) { alert('Please enter an NBA topic to search for'); return; } // Show loading resultsContainer.classList.remove('hidden'); resultsDiv.innerHTML = ''; loadingDiv.classList.remove('hidden'); // Simulate API delay setTimeout(() => { loadingDiv.classList.add('hidden'); // Filter mock data based on reposts (in a real app, this would be done server-side) const filteredPosts = mockPosts.filter(post => post.reposts >= minReposts); if (filteredPosts.length === 0) { resultsDiv.innerHTML = `
No posts found matching your criteria. Try widening your search parameters.
${post.author.displayName}
@${post.author.handle} ยท ${post.timestamp}
${post.text}
`; resultsDiv.appendChild(postElement); }); feather.replace(); }, 1500); // Simulate network delay }); // Copy all button copyAllBtn.addEventListener('click', () => { const posts = [...document.querySelectorAll('.copy-btn')].map(btn => btn.getAttribute('data-content')); if (posts.length === 0) return; const textToCopy = posts.join('\n\n---\n\n'); navigator.clipboard.writeText(textToCopy).then(() => { showNotification('All posts copied to clipboard!', copyAllBtn); }); }); // Event delegation for copy buttons resultsDiv.addEventListener('click', (e) => { if (e.target.closest('.copy-btn')) { const btn = e.target.closest('.copy-btn'); const text = btn.getAttribute('data-content'); navigator.clipboard.writeText(text).then(() => { showNotification('Copied to clipboard!', btn); }); } }); // Helper function to show notification function showNotification(message, element) { const notification = document.createElement('div'); notification.className = 'copied-notification absolute bg-green-600 text-white text-sm py-1 px-3 rounded-md shadow-lg'; notification.textContent = message; const rect = element.getBoundingClientRect(); notification.style.left = `${rect.left + window.scrollX}px`; notification.style.top = `${rect.top + window.scrollY - 30}px`; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 2000); } // Helper function to escape HTML function escapeHtml(unsafe) { return unsafe .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } });