Files
turbovault-app/app/views/games/index.html.erb
2026-03-28 19:24:29 -04:00

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>