Add interactive rating display and controls to dashboard
This commit is contained in:
@@ -129,21 +129,80 @@ templ Dashboard(user User) {
|
||||
});
|
||||
}
|
||||
|
||||
function renderEbooks(ebooks) {
|
||||
async function renderEbooks(ebooks) {
|
||||
const container = document.getElementById('ebooks-container');
|
||||
container.innerHTML = '';
|
||||
|
||||
ebooks.forEach(ebook => {
|
||||
for (const ebook of ebooks) {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card p-4 rounded-lg border hover:shadow-lg transition-shadow';
|
||||
card.style.cssText = 'background-color: var(--bg-secondary); border-color: var(--border);';
|
||||
|
||||
const coverUrl = ebook.cover_image_path ? ebook.cover_image_path : '/static/placeholder-book.svg';
|
||||
|
||||
// Get user's rating for this ebook
|
||||
const rating = await getEbookRating(ebook.id);
|
||||
const ratingStars = renderRatingStars(ebook.id, rating);
|
||||
|
||||
card.innerHTML = '<div class="flex flex-col h-full"><div class="flex-1"><div class="aspect-w-3 aspect-h-4 mb-3 overflow-hidden rounded"><img src="' + coverUrl + '" alt="Cover" class="w-full h-48 object-cover rounded" onerror="this.src=\'/static/placeholder-book.svg\'"></div><h3 class="font-semibold text-lg mb-1 line-clamp-2" style="color: var(--text-primary)">' + ebook.title + '</h3>' + (ebook.author ? '<p class="text-sm mb-2" style="color: var(--text-secondary)">by ' + ebook.author + '</p>' : '') + '<div class="flex justify-between items-center mt-4"><div class="flex space-x-2"><button onclick="viewEbook(\'' + ebook.id + '\')" class="px-3 py-1 text-sm border rounded hover:opacity-80" style="border-color: var(--border); color: var(--text-secondary)">View</button></div></div></div>';
|
||||
card.innerHTML = '<div class="flex flex-col h-full"><div class="flex-1"><div class="aspect-w-3 aspect-h-4 mb-3 overflow-hidden rounded"><img src="' + coverUrl + '" alt="Cover" class="w-full h-48 object-cover rounded" onerror="this.src=\'/static/placeholder-book.svg\'"></div><h3 class="font-semibold text-lg mb-1 line-clamp-2" style="color: var(--text-primary)">' + ebook.title + '</h3>' + (ebook.author ? '<p class="text-sm mb-2" style="color: var(--text-secondary)">by ' + ebook.author + '</p>' : '') + '<div class="mb-2" id="rating-' + ebook.id + '">' + ratingStars + '</div><div class="flex justify-between items-center mt-4"><div class="flex space-x-2"><button onclick="viewEbook(\'' + ebook.id + '\')" class="px-3 py-1 text-sm border rounded hover:opacity-80" style="border-color: var(--border); color: var(--text-secondary)">View</button></div></div></div>';
|
||||
|
||||
container.appendChild(card);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function getEbookRating(ebookId) {
|
||||
try {
|
||||
const response = await fetch(`/api/ebooks/${ebookId}/rating`, {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('token'),
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
return data.rating || 0;
|
||||
}
|
||||
return 0;
|
||||
} catch (error) {
|
||||
console.error('Error fetching rating:', error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function renderRatingStars(ebookId, currentRating) {
|
||||
let stars = '';
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
const filled = i <= currentRating;
|
||||
const starClass = filled ? 'text-yellow-400' : 'text-gray-400';
|
||||
stars += `<span onclick="setRating('${ebookId}', ${i})" class="cursor-pointer text-xl ${starClass} hover:text-yellow-300 transition-colors">${filled ? '★' : '☆'}</span>`;
|
||||
}
|
||||
return stars;
|
||||
}
|
||||
|
||||
async function setRating(ebookId, rating) {
|
||||
try {
|
||||
const response = await fetch(`/api/ebooks/${ebookId}/rating`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('token'),
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ rating: rating })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const ratingContainer = document.getElementById(`rating-${ebookId}`);
|
||||
if (ratingContainer) {
|
||||
ratingContainer.innerHTML = renderRatingStars(ebookId, data.rating);
|
||||
}
|
||||
} else {
|
||||
console.error('Error setting rating:', await response.text());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error setting rating:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
|
||||
Reference in New Issue
Block a user