Spaces:
Running
Running
| // API Base URL | |
| const API_BASE_URL = '/api'; | |
| // DOM Elements | |
| const shareForm = document.getElementById('shareForm'); | |
| const linksContainer = document.getElementById('linksContainer'); | |
| const loadingSpinner = document.getElementById('loadingSpinner'); | |
| const successMessage = document.getElementById('successMessage'); | |
| const successText = document.getElementById('successText'); | |
| // Initialize app | |
| document.addEventListener('DOMContentLoaded', function() { | |
| loadLinks(); | |
| // Handle form submission | |
| shareForm.addEventListener('submit', handleShareSubmit); | |
| }); | |
| // Handle share form submission | |
| async function handleShareSubmit(e) { | |
| e.preventDefault(); | |
| const formData = new FormData(shareForm); | |
| const data = { | |
| name: formData.get('name'), | |
| note: formData.get('note'), | |
| youtube_link: formData.get('youtube_link') | |
| }; | |
| // Validate YouTube URL | |
| if (!isValidYouTubeURL(data.youtube_link)) { | |
| alert('กรุณากรอกลิงก์ YouTube ที่ถูกต้อง'); | |
| return; | |
| } | |
| try { | |
| showLoading(true); | |
| const response = await fetch(`${API_BASE_URL}/posts`, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify(data) | |
| }); | |
| if (!response.ok) { | |
| throw new Error('เกิดข้อผิดพลาดในการแชร์'); | |
| } | |
| const result = await response.json(); | |
| // Show success message | |
| showSuccessMessage('แชร์สำเร็จ!'); | |
| // Clear form | |
| shareForm.reset(); | |
| // Reload links | |
| await loadLinks(); | |
| } catch (error) { | |
| console.error('Error sharing link:', error); | |
| alert('เกิดข้อผิดพลาดในการแชร์: ' + error.message); | |
| } finally { | |
| showLoading(false); | |
| } | |
| } | |
| // Load all shared links | |
| async function loadLinks() { | |
| try { | |
| showLoading(true); | |
| const response = await fetch(`${API_BASE_URL}/posts`); | |
| if (!response.ok) { | |
| throw new Error('ไม่สามารถโหลดลิงก์ได้'); | |
| } | |
| const links = await response.json(); | |
| displayLinks(links); | |
| } catch (error) { | |
| console.error('Error loading links:', error); | |
| linksContainer.innerHTML = ` | |
| <div style="text-align: center; color: #666; padding: 20px;"> | |
| <i class="fas fa-exclamation-triangle"></i> | |
| <p>ไม่สามารถโหลดลิงก์ได้: ${error.message}</p> | |
| </div> | |
| `; | |
| } finally { | |
| showLoading(false); | |
| } | |
| } | |
| // Display links in the container | |
| function displayLinks(links) { | |
| if (links.length === 0) { | |
| linksContainer.innerHTML = ` | |
| <div style="text-align: center; color: #666; padding: 40px;"> | |
| <i class="fab fa-youtube" style="font-size: 3rem; margin-bottom: 15px;"></i> | |
| <p>ยังไม่มีลิงก์ที่แชร์</p> | |
| <p>เป็นคนแรกที่แชร์ลิงก์ YouTube!</p> | |
| </div> | |
| `; | |
| return; | |
| } | |
| linksContainer.innerHTML = links.map(link => createLinkCard(link)).join(''); | |
| // Add event listeners for like and comment buttons | |
| addLinkEventListeners(); | |
| } | |
| // Create HTML for a single link card | |
| function createLinkCard(link) { | |
| const videoId = extractYouTubeVideoId(link.youtube_link); | |
| const embedUrl = videoId ? `https://www.youtube.com/embed/${videoId}` : ''; | |
| const timeAgo = getTimeAgo(new Date(link.created_at)); | |
| return ` | |
| <div class="link-card" data-link-id="${link.id}"> | |
| <div class="link-header"> | |
| <span class="user-name"> | |
| <i class="fas fa-user"></i> ${escapeHtml(link.name)} | |
| </span> | |
| <span class="timestamp">${timeAgo}</span> | |
| </div> | |
| <div class="link-note"> | |
| ${escapeHtml(link.note)} | |
| </div> | |
| ${embedUrl ? ` | |
| <div class="youtube-embed"> | |
| <iframe src="${embedUrl}" | |
| title="YouTube video player" | |
| frameborder="0" | |
| allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" | |
| allowfullscreen> | |
| </iframe> | |
| </div> | |
| ` : ` | |
| <div class="youtube-link"> | |
| <a href="${link.youtube_link}" target="_blank" rel="noopener noreferrer"> | |
| <i class="fab fa-youtube"></i> ดูวิดีโอใน YouTube | |
| </a> | |
| </div> | |
| `} | |
| <div class="link-actions"> | |
| <button class="action-btn like-btn" data-link-id="${link.id}"> | |
| <i class="fas fa-heart"></i> | |
| <span class="like-count">${link.likes}</span> | |
| </button> | |
| <button class="action-btn comment-btn" data-link-id="${link.id}"> | |
| <i class="fas fa-comment"></i> | |
| คอมเมนต์ | |
| </button> | |
| </div> | |
| <div class="comments-section" id="comments-${link.id}" style="display: none;"> | |
| <div class="comment-form"> | |
| <input type="text" placeholder="เขียนคอมเมนต์..." class="comment-input"> | |
| <button type="button" class="add-comment-btn" data-link-id="${link.id}"> | |
| <i class="fas fa-paper-plane"></i> | |
| </button> | |
| </div> | |
| <div class="comments-list" id="comments-list-${link.id}"> | |
| <!-- Comments will be loaded here --> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| // Add event listeners for link interactions | |
| function addLinkEventListeners() { | |
| // Like buttons | |
| document.querySelectorAll('.like-btn').forEach(btn => { | |
| btn.addEventListener('click', handleLike); | |
| }); | |
| // Comment buttons | |
| document.querySelectorAll('.comment-btn').forEach(btn => { | |
| btn.addEventListener('click', toggleComments); | |
| }); | |
| // Add comment buttons | |
| document.querySelectorAll('.add-comment-btn').forEach(btn => { | |
| btn.addEventListener('click', handleAddComment); | |
| }); | |
| // Enter key for comment input | |
| document.querySelectorAll('.comment-input').forEach(input => { | |
| input.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') { | |
| const linkId = this.closest('.comments-section').id.split('-')[1]; | |
| const btn = document.querySelector(`.add-comment-btn[data-link-id="${linkId}"]`); | |
| btn.click(); | |
| } | |
| }); | |
| }); | |
| } | |
| // Handle like button click | |
| async function handleLike(e) { | |
| const linkId = e.currentTarget.dataset.linkId; | |
| const likeBtn = e.currentTarget; | |
| const likeCount = likeBtn.querySelector('.like-count'); | |
| try { | |
| const response = await fetch(`${API_BASE_URL}/posts/${linkId}/like`, { | |
| method: 'POST' | |
| }); | |
| if (!response.ok) { | |
| throw new Error('ไม่สามารถถูกใจได้'); | |
| } | |
| const result = await response.json(); | |
| likeCount.textContent = result.likes; | |
| // Add visual feedback | |
| likeBtn.classList.add('liked'); | |
| setTimeout(() => likeBtn.classList.remove('liked'), 1000); | |
| } catch (error) { | |
| console.error('Error liking post:', error); | |
| alert('เกิดข้อผิดพลาดในการถูกใจ'); | |
| } | |
| } | |
| // Toggle comments section | |
| async function toggleComments(e) { | |
| const linkId = e.currentTarget.dataset.linkId; | |
| const commentsSection = document.getElementById(`comments-${linkId}`); | |
| if (commentsSection.style.display === 'none') { | |
| commentsSection.style.display = 'block'; | |
| await loadComments(linkId); | |
| } else { | |
| commentsSection.style.display = 'none'; | |
| } | |
| } | |
| // Load comments for a specific link | |
| async function loadComments(linkId) { | |
| try { | |
| const response = await fetch(`${API_BASE_URL}/posts/${linkId}/comments`); | |
| if (!response.ok) { | |
| throw new Error('ไม่สามารถโหลดคอมเมนต์ได้'); | |
| } | |
| const comments = await response.json(); | |
| const commentsList = document.getElementById(`comments-list-${linkId}`); | |
| if (comments.length === 0) { | |
| commentsList.innerHTML = '<p style="text-align: center; color: #666; padding: 10px;">ยังไม่มีคอมเมนต์</p>'; | |
| } else { | |
| commentsList.innerHTML = comments.map(comment => ` | |
| <div class="comment"> | |
| <div class="comment-author"> | |
| <i class="fas fa-user"></i> ${escapeHtml(comment.name)} | |
| </div> | |
| <div class="comment-text">${escapeHtml(comment.comment)}</div> | |
| </div> | |
| `).join(''); | |
| } | |
| } catch (error) { | |
| console.error('Error loading comments:', error); | |
| } | |
| } | |
| // Handle add comment | |
| async function handleAddComment(e) { | |
| const linkId = e.currentTarget.dataset.linkId; | |
| const commentsSection = document.getElementById(`comments-${linkId}`); | |
| const commentInput = commentsSection.querySelector('.comment-input'); | |
| const commentText = commentInput.value.trim(); | |
| if (!commentText) { | |
| alert('กรุณาเขียนคอมเมนต์'); | |
| return; | |
| } | |
| // Simple name prompt (in real app, you'd have user authentication) | |
| const name = prompt('กรุณากรอกชื่อของคุณ:'); | |
| if (!name) return; | |
| try { | |
| const response = await fetch(`${API_BASE_URL}/posts/${linkId}/comments`, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| name: name, | |
| comment: commentText | |
| }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error('ไม่สามารถเพิ่มคอมเมนต์ได้'); | |
| } | |
| // Clear input | |
| commentInput.value = ''; | |
| // Reload comments | |
| await loadComments(linkId); | |
| showSuccessMessage('เพิ่มคอมเมนต์สำเร็จ!'); | |
| } catch (error) { | |
| console.error('Error adding comment:', error); | |
| alert('เกิดข้อผิดพลาดในการเพิ่มคอมเมนต์'); | |
| } | |
| } | |
| // Utility functions | |
| function isValidYouTubeURL(url) { | |
| const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)[a-zA-Z0-9_-]{11}/; | |
| return youtubeRegex.test(url); | |
| } | |
| function extractYouTubeVideoId(url) { | |
| const regex = /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/; | |
| const match = url.match(regex); | |
| return match ? match[1] : null; | |
| } | |
| function escapeHtml(text) { | |
| const div = document.createElement('div'); | |
| div.textContent = text; | |
| return div.innerHTML; | |
| } | |
| function getTimeAgo(date) { | |
| const now = new Date(); | |
| const diffInSeconds = Math.floor((now - date) / 1000); | |
| if (diffInSeconds < 60) return 'เมื่อสักครู่'; | |
| if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)} นาทีที่แล้ว`; | |
| if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)} ชั่วโมงที่แล้ว`; | |
| return `${Math.floor(diffInSeconds / 86400)} วันที่แล้ว`; | |
| } | |
| function showLoading(show) { | |
| loadingSpinner.style.display = show ? 'block' : 'none'; | |
| } | |
| function showSuccessMessage(message) { | |
| successText.textContent = message; | |
| successMessage.style.display = 'flex'; | |
| setTimeout(() => { | |
| successMessage.style.display = 'none'; | |
| }, 3000); | |
| } | |