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); | |
} | |