147 lines
5.4 KiB
HTML
147 lines
5.4 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}My Favorites - DosVault{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="mb-8">
|
|
<h1 class="text-3xl font-bold mb-2">My Favorites</h1>
|
|
<p class="text-gray-400">Your personally selected game collection</p>
|
|
</div>
|
|
|
|
{% if games %}
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
|
{% for game in games %}
|
|
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700 hover:border-gray-600 transition-colors">
|
|
<div class="flex justify-between items-start mb-3">
|
|
<h3 class="text-lg font-semibold text-blue-400 truncate">{{ game.metadata_obj.title or game.title }}</h3>
|
|
<button onclick="toggleFavorite({{ game.id }})"
|
|
class="text-red-600 hover:text-red-500 text-xl"
|
|
id="favorite-{{ game.id }}">
|
|
♥
|
|
</button>
|
|
</div>
|
|
|
|
{% if game.metadata_obj %}
|
|
<div class="space-y-2 text-sm text-gray-300">
|
|
{% if game.metadata_obj.year %}
|
|
<p><span class="text-gray-400">Year:</span> {{ game.metadata_obj.year }}</p>
|
|
{% endif %}
|
|
{% if game.metadata_obj.developer %}
|
|
<p><span class="text-gray-400">Developer:</span> {{ game.metadata_obj.developer }}</p>
|
|
{% endif %}
|
|
{% if game.metadata_obj.description %}
|
|
<p class="text-xs text-gray-400 line-clamp-3">{{ game.metadata_obj.description[:100] }}{% if game.metadata_obj.description|length > 100 %}...{% endif %}</p>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="mt-4 flex justify-between items-center">
|
|
<a href="/games/{{ game.id }}" class="text-blue-400 hover:text-blue-300 text-sm underline">
|
|
View Details
|
|
</a>
|
|
<button onclick="downloadGame({{ game.id }})"
|
|
class="bg-green-600 hover:bg-green-700 px-3 py-1 rounded text-sm">
|
|
Download
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
{% if total_pages > 1 %}
|
|
<div class="mt-12 flex justify-center">
|
|
<nav class="flex items-center space-x-2">
|
|
{% if current_page > 1 %}
|
|
<a href="?page={{ current_page - 1 }}"
|
|
class="px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded text-sm">
|
|
Previous
|
|
</a>
|
|
{% endif %}
|
|
|
|
{% for page_num in range(1, total_pages + 1) %}
|
|
{% if page_num == current_page %}
|
|
<span class="px-3 py-2 bg-blue-600 rounded text-sm">{{ page_num }}</span>
|
|
{% elif page_num <= current_page + 2 and page_num >= current_page - 2 %}
|
|
<a href="?page={{ page_num }}"
|
|
class="px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded text-sm">
|
|
{{ page_num }}
|
|
</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if current_page < total_pages %}
|
|
<a href="?page={{ current_page + 1 }}"
|
|
class="px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded text-sm">
|
|
Next
|
|
</a>
|
|
{% endif %}
|
|
</nav>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% else %}
|
|
<div class="text-center py-12">
|
|
<div class="text-6xl mb-4">💔</div>
|
|
<h2 class="text-2xl font-bold mb-2">No favorites yet</h2>
|
|
<p class="text-gray-400 mb-6">Start browsing and add games to your favorites collection!</p>
|
|
<a href="/" class="bg-blue-600 hover:bg-blue-700 px-6 py-3 rounded-lg text-white">
|
|
Browse Games
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<script>
|
|
async function toggleFavorite(gameId) {
|
|
const token = localStorage.getItem('authToken');
|
|
if (!token) return;
|
|
|
|
try {
|
|
const response = await fetch(`/games/${gameId}/favorite`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
// Remove the game from favorites view
|
|
location.reload();
|
|
}
|
|
} catch (error) {
|
|
console.error('Error toggling favorite:', error);
|
|
}
|
|
}
|
|
|
|
async function downloadGame(gameId) {
|
|
const token = localStorage.getItem('authToken');
|
|
if (!token) return;
|
|
|
|
try {
|
|
const response = await fetch(`/download/${gameId}`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
const blob = await response.blob();
|
|
const url = window.URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.style.display = 'none';
|
|
a.href = url;
|
|
// Get filename from Content-Disposition header, removing quotes and underscores
|
|
let filename = response.headers.get('Content-Disposition')?.split('filename=')[1] || 'game.zip';
|
|
filename = filename.replace(/^["_]+|["_]+$/g, ''); // Remove quotes and underscores from start and end
|
|
a.download = filename;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
window.URL.revokeObjectURL(url);
|
|
document.body.removeChild(a);
|
|
}
|
|
} catch (error) {
|
|
console.error('Download error:', error);
|
|
}
|
|
}
|
|
</script>
|
|
{% endblock %} |