mirror of
https://github.com/ryankazokas/turbovault-app.git
synced 2026-04-16 23:22:53 +00:00
156 lines
7.4 KiB
Plaintext
156 lines
7.4 KiB
Plaintext
<div>
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h1 class="text-3xl font-bold">My Games</h1>
|
|
<div class="flex items-center space-x-2">
|
|
<div id="bulk-actions" style="display: none;" class="mr-4">
|
|
<button type="button" onclick="bulkEdit()" class="px-4 py-2 bg-purple-600 text-white rounded hover:bg-purple-700">
|
|
Bulk Edit (<span id="selected-count">0</span>)
|
|
</button>
|
|
</div>
|
|
<%= link_to "Import CSV", import_games_path, class: "px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700" %>
|
|
<%= link_to "Add Game", new_game_path, class: "px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700" %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<%= form_with url: games_path, method: :get, class: "bg-white p-4 rounded-lg shadow mb-6" do |f| %>
|
|
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
|
<div>
|
|
<%= f.text_field :search, placeholder: "Search games...", value: params[:search], class: "w-full rounded-md border-gray-300" %>
|
|
</div>
|
|
|
|
<div>
|
|
<%= f.select :platform_id, options_from_collection_for_select(@platforms, :id, :name, params[:platform_id]), { include_blank: "All Platforms" }, class: "w-full rounded-md border-gray-300" %>
|
|
</div>
|
|
|
|
<div>
|
|
<%= f.select :genre_id, options_from_collection_for_select(@genres, :id, :name, params[:genre_id]), { include_blank: "All Genres" }, class: "w-full rounded-md border-gray-300" %>
|
|
</div>
|
|
|
|
<div>
|
|
<%= f.select :format, options_for_select([["Physical", "physical"], ["Digital", "digital"]], params[:format]), { include_blank: "All Formats" }, class: "w-full rounded-md border-gray-300" %>
|
|
</div>
|
|
|
|
<div>
|
|
<%= f.select :completion_status, options_for_select([["Backlog", "backlog"], ["Currently Playing", "currently_playing"], ["Completed", "completed"], ["On Hold", "on_hold"], ["Not Playing", "not_playing"]], params[:completion_status]), { include_blank: "All Statuses" }, class: "w-full rounded-md border-gray-300" %>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4 flex justify-between">
|
|
<%= f.submit "Filter", class: "px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700" %>
|
|
<%= link_to "Clear Filters", games_path, class: "px-4 py-2 bg-gray-200 rounded hover:bg-gray-300" %>
|
|
</div>
|
|
<% end %>
|
|
|
|
<!-- Sort -->
|
|
<div class="mb-4">
|
|
<span class="text-gray-600 mr-2">Sort by:</span>
|
|
<%= link_to "Alphabetical", games_path(filter_params_for_sort("alphabetical")), class: "text-indigo-600 hover:text-indigo-800 mr-4" %>
|
|
<%= link_to "Recently Added", games_path(filter_params_for_sort("recent")), class: "text-indigo-600 hover:text-indigo-800 mr-4" %>
|
|
<%= link_to "Highest Rated", games_path(filter_params_for_sort("rated")), class: "text-indigo-600 hover:text-indigo-800" %>
|
|
</div>
|
|
|
|
<!-- Games List -->
|
|
<% if @games.any? %>
|
|
<div class="bg-white rounded-lg shadow overflow-hidden">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left">
|
|
<input type="checkbox" id="select-all" class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" onchange="toggleAll(this)">
|
|
</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Title</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Platform</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Format</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Rating</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
<% @games.each do |game| %>
|
|
<tr>
|
|
<td class="px-6 py-4">
|
|
<input type="checkbox" name="game_ids[]" value="<%= game.id %>" class="game-checkbox rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" onchange="updateBulkActions()">
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<%= link_to game.title, game, class: "text-indigo-600 hover:text-indigo-800 font-medium" %>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
<%= game.platform.name %>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <%= game.physical? ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800' %>">
|
|
<%= game.format.titleize %>
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
<%= game.completion_status&.titleize || "N/A" %>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
<%= game.user_rating ? "⭐ #{game.user_rating}/5" : "Not rated" %>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
|
<%= link_to "View", game, class: "text-indigo-600 hover:text-indigo-900 mr-2" %>
|
|
<%= link_to "Edit", edit_game_path(game), class: "text-blue-600 hover:text-blue-900 mr-2" %>
|
|
<%= button_to "Delete", game, method: :delete, data: { turbo_confirm: "Are you sure you want to delete '#{game.title}'? This action cannot be undone." }, class: "text-red-600 hover:text-red-900" %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination would go here -->
|
|
<div class="mt-4">
|
|
<%#= paginate @games %>
|
|
</div>
|
|
<% else %>
|
|
<div class="bg-white p-8 rounded-lg shadow text-center">
|
|
<p class="text-gray-500 mb-4">No games found matching your filters.</p>
|
|
<%= link_to "Clear Filters", games_path, class: "text-indigo-600 hover:text-indigo-800" %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
|
|
<script>
|
|
function toggleAll(checkbox) {
|
|
const gameCheckboxes = document.querySelectorAll('.game-checkbox');
|
|
gameCheckboxes.forEach(cb => {
|
|
cb.checked = checkbox.checked;
|
|
});
|
|
updateBulkActions();
|
|
}
|
|
|
|
function updateBulkActions() {
|
|
const checkedBoxes = document.querySelectorAll('.game-checkbox:checked');
|
|
const count = checkedBoxes.length;
|
|
const bulkActions = document.getElementById('bulk-actions');
|
|
const selectedCount = document.getElementById('selected-count');
|
|
|
|
if (count > 0) {
|
|
bulkActions.style.display = 'block';
|
|
selectedCount.textContent = count;
|
|
} else {
|
|
bulkActions.style.display = 'none';
|
|
document.getElementById('select-all').checked = false;
|
|
}
|
|
}
|
|
|
|
function bulkEdit() {
|
|
const checkedBoxes = document.querySelectorAll('.game-checkbox:checked');
|
|
const gameIds = Array.from(checkedBoxes).map(cb => cb.value);
|
|
|
|
if (gameIds.length === 0) {
|
|
alert('Please select at least one game');
|
|
return;
|
|
}
|
|
|
|
// Build URL with game IDs
|
|
const params = new URLSearchParams();
|
|
gameIds.forEach(id => params.append('game_ids[]', id));
|
|
|
|
window.location.href = '<%= bulk_edit_games_path %>?' + params.toString();
|
|
}
|
|
</script>
|