Files
edh-stats/frontend/public/games.html

431 lines
16 KiB
HTML

<!doctype html>
<html lang="en" class="h-full bg-gray-50">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Games - EDH Stats Tracker</title>
<meta
name="description"
content="Log and track your Magic: The Gathering EDH/Commander games"
/>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="/css/styles.css" />
</head>
<body class="h-full" x-data="gameManager()">
<!-- Navigation Header -->
<header class="bg-slate-900 text-white shadow-lg">
<nav class="container mx-auto px-4 py-4">
<div class="flex justify-between items-center">
<h1 class="text-2xl font-bold font-mtg">Game Log</h1>
<div class="flex space-x-4">
<a
href="/dashboard.html"
class="hover:text-edh-accent transition-colors"
>
← Back to Dashboard
</a>
</div>
</div>
</nav>
</header>
<!-- Main Content -->
<main class="container mx-auto px-4 py-8">
<!-- Header & Action -->
<div class="mb-8 flex justify-between items-center">
<h2 class="text-2xl font-semibold text-gray-900">Recent Games</h2>
<div class="flex space-x-4">
<button @click="exportGames()" class="btn btn-secondary">
Export JSON
</button>
<button @click="showLogForm = !showLogForm" class="btn btn-primary">
<span x-show="!showLogForm">Log New Game</span>
<span x-show="showLogForm">Cancel</span>
</button>
</div>
</div>
<!-- Log Game Form -->
<div
x-show="showLogForm"
x-transition
class="mb-8 card border-2 border-edh-primary/20"
>
<h3 class="text-lg font-semibold mb-6">
<span x-show="!editingGame">Log Game Details</span>
<span x-show="editingGame">Edit Game</span>
</h3>
<form @submit.prevent="handleLogGame">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Date -->
<div>
<label class="form-label">Date Played</label>
<input
type="date"
x-model="formData.date"
class="form-input"
required
/>
</div>
<!-- Commander -->
<div>
<label class="form-label">Commander Played</label>
<select
x-model="formData.commanderId"
class="form-select"
required
>
<option value="">Select a commander...</option>
<template x-for="commander in commanders" :key="commander.id">
<option
:value="commander.id"
x-text="commander.name"
></option>
</template>
</select>
<p
x-show="commanders.length === 0"
class="text-sm text-gray-500 mt-1"
>
No commanders found.
<a href="/commanders.html" class="text-edh-primary underline"
>Add one first!</a
>
</p>
</div>
<!-- Player Count -->
<div>
<label class="form-label">Number of Players</label>
<input
type="number"
x-model="formData.playerCount"
min="2"
max="8"
class="form-input"
required
/>
</div>
<!-- Rounds -->
<div>
<label class="form-label">Rounds Lasted</label>
<input
type="number"
x-model="formData.rounds"
min="1"
max="50"
class="form-input"
required
/>
</div>
<!-- Game Outcome -->
<div class="md:col-span-2">
<label class="form-label mb-2 block">Did you win?</label>
<div class="flex space-x-4">
<label class="inline-flex items-center">
<input
type="radio"
x-model="formData.won"
:value="true"
class="form-radio text-edh-primary"
/>
<span class="ml-2 text-green-700 font-medium"
>Yes, I won! 🏆</span
>
</label>
<label class="inline-flex items-center">
<input
type="radio"
x-model="formData.won"
:value="false"
class="form-radio text-edh-primary"
/>
<span class="ml-2 text-gray-700">No, maybe next time</span>
</label>
</div>
</div>
<!-- Additional Stats -->
<div class="md:col-span-2 space-y-3 p-4 bg-gray-50 rounded-lg">
<label class="inline-flex items-center w-full cursor-pointer">
<input
type="checkbox"
x-model="formData.startingPlayerWon"
class="form-checkbox text-edh-primary rounded"
/>
<span class="ml-2">Did the starting player win?</span>
</label>
<label class="inline-flex items-center w-full cursor-pointer">
<input
type="checkbox"
x-model="formData.solRingTurnOneWon"
class="form-checkbox text-edh-primary rounded"
/>
<span class="ml-2">Did a Turn 1 Sol Ring player win?</span>
</label>
</div>
<!-- Notes -->
<div class="col-span-1 md:col-span-2 w-full">
<label class="form-label">Game Notes</label>
<textarea
x-model="formData.notes"
rows="5"
class="form-textarea w-full"
placeholder="Any memorable moments, combos, or reasons for winning/losing..."
></textarea>
</div>
</div>
<!-- Error Message -->
<div
x-show="serverError"
class="mt-4 p-3 bg-red-100 text-red-700 rounded-lg text-sm"
x-text="serverError"
></div>
<!-- Actions -->
<div class="mt-6 flex justify-end space-x-3">
<button
type="button"
@click="editingGame ? cancelEdit() : (showLogForm = false)"
class="btn btn-secondary"
>
Cancel
</button>
<button
type="submit"
:disabled="editingGame ? editSubmitting : submitting"
class="btn btn-primary"
>
<span x-show="editingGame && editSubmitting">Saving...</span>
<span x-show="editingGame && !editSubmitting">Update Game</span>
<span x-show="!editingGame && submitting">Saving...</span>
<span x-show="!editingGame && !submitting">Log Game</span>
</button>
</div>
</form>
</div>
<!-- Games List -->
<div class="space-y-4">
<!-- Loading State -->
<div
x-show="loading && games.length === 0"
class="flex justify-center py-12"
>
<div class="loading-spinner w-8 h-8"></div>
</div>
<!-- Empty State -->
<div
x-show="!loading && games.length === 0"
class="text-center py-12 bg-white rounded-lg shadow"
>
<p class="text-gray-500 mb-4">No games logged yet.</p>
<button
@click="showLogForm = true"
class="text-edh-primary font-medium hover:underline"
>
Log your first game!
</button>
</div>
<!-- List Items -->
<template x-for="game in games" :key="game.id">
<div
class="card hover:shadow-md transition-shadow border-l-4"
:class="game.won ? 'border-l-green-500' : 'border-l-gray-300'"
>
<div class="flex justify-between items-start">
<div>
<div class="flex items-center space-x-2 mb-1">
<h3
class="font-bold text-lg"
x-text="game.commanderName || getCommanderName(game.commanderId)"
></h3>
<span
x-show="game.won"
class="px-2 py-0.5 rounded text-xs font-bold bg-green-100 text-green-800"
>WIN</span
>
</div>
<p class="text-sm text-gray-500">
<span x-text="formatDate(game.date)"></span>
<span x-text="game.playerCount"></span> Players •
<span x-text="game.rounds"></span> Rounds
</p>
</div>
<div class="flex space-x-2">
<button
@click="editGame(game.id)"
class="text-edh-accent hover:text-edh-primary transition-colors"
title="Edit game"
>
<svg
class="w-6 h-6"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12 21C12 20.4477 12.4477 20 13 20H21C21.5523 20 22 20.4477 22 21C22 21.5523 21.5523 22 21 22H13C12.4477 22 12 21.5523 12 21Z"
fill="currentColor"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M20.7736 8.09994C22.3834 6.48381 22.315 4.36152 21.113 3.06183C20.5268 2.4281 19.6926 2.0233 18.7477 2.00098C17.7993 1.97858 16.8167 2.34127 15.91 3.09985C15.8868 3.11925 15.8645 3.13969 15.8432 3.16111L2.87446 16.1816C2.31443 16.7438 2 17.5051 2 18.2987V19.9922C2 21.0937 2.89197 22 4.00383 22H5.68265C6.48037 22 7.24524 21.6823 7.80819 21.1171L20.7736 8.09994ZM17.2071 5.79295C16.8166 5.40243 16.1834 5.40243 15.7929 5.79295C15.4024 6.18348 15.4024 6.81664 15.7929 7.20717L16.7929 8.20717C17.1834 8.59769 17.8166 8.59769 18.2071 8.20717C18.5976 7.81664 18.5976 7.18348 18.2071 6.79295L17.2071 5.79295Z"
fill="currentColor"
/>
</svg>
</button>
<button
@click="deleteGame(game.id)"
class="text-red-600 hover:text-red-800 transition-colors"
title="Delete game"
>
<svg
class="w-6 h-6"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4 6H20M16 6L15.7294 5.18807C15.4671 4.40125 15.3359 4.00784 15.0927 3.71698C14.8779 3.46013 14.6021 3.26132 14.2905 3.13878C13.9376 3 13.523 3 12.6936 3H11.3064C10.477 3 10.0624 3 9.70951 3.13878C9.39792 3.26132 9.12208 3.46013 8.90729 3.71698C8.66405 4.00784 8.53292 4.40125 8.27064 5.18807L8 6M18 6V16.2C18 17.8802 18 18.7202 17.673 19.362C17.3854 19.9265 16.9265 20.3854 16.362 20.673C15.7202 21 14.8802 21 13.2 21H10.8C9.11984 21 8.27976 21 7.63803 20.673C7.07354 20.3854 6.6146 19.9265 6.32698 19.362C6 18.7202 6 17.8802 6 16.2V6M14 10V17M10 10V17"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
</div>
</div>
<div
x-show="game.notes"
class="mt-3 text-gray-600 text-sm bg-gray-50 p-2 rounded"
>
<span
class="font-semibold text-gray-500 text-xs uppercase tracking-wide"
>Notes:</span
>
<p x-text="game.notes"></p>
</div>
<div class="mt-3 flex flex-wrap gap-2 text-xs text-gray-500">
<span
x-show="game.startingPlayerWon"
class="px-2 py-1 bg-gray-100 rounded"
>Starting Player Won</span
>
<span
x-show="game.solRingTurnOneWon"
class="px-2 py-1 bg-yellow-50 text-yellow-700 rounded border border-yellow-200"
>T1 Sol Ring Win</span
>
</div>
</div>
</template>
<!-- Load More -->
<div x-show="pagination.hasMore" class="flex justify-center pt-8">
<button
@click="loadMore()"
:disabled="pagination.isLoadingMore"
:class="{ 'opacity-50 cursor-not-allowed': pagination.isLoadingMore }"
class="btn btn-secondary flex justify-center items-center space-x-2"
>
<svg
x-show="!pagination.isLoadingMore"
class="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 4v16m8-8H4"
></path>
</svg>
<svg
x-show="pagination.isLoadingMore"
class="animate-spin h-5 w-5"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
<span x-text="pagination.isLoadingMore ? 'Loading...' : 'Load More Games'"></span>
</button>
</div>
</div>
</main>
<!-- Delete Confirmation Modal -->
<div
x-show="deleteConfirm.show"
x-cloak
x-transition
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
@click.self="deleteConfirm.show = false"
>
<div class="bg-white rounded-lg shadow-lg max-w-sm w-full">
<div class="p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-2">Delete Game</h3>
<p class="text-gray-600 mb-6">
Are you sure you want to delete this game record? This action cannot be undone.
</p>
<div class="flex justify-end space-x-3">
<button
@click="deleteConfirm.show = false"
class="btn btn-secondary"
>
Cancel
</button>
<button
@click="confirmDelete()"
:disabled="deleteConfirm.deleting"
class="btn btn-primary bg-red-600 hover:bg-red-700"
>
<span x-show="!deleteConfirm.deleting">Delete Game</span>
<span x-show="deleteConfirm.deleting">Deleting...</span>
</button>
</div>
</div>
</div>
</div>
<!-- Scripts --> <script
defer
src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
></script>
<script src="/js/auth-guard.js"></script>
<script src="/js/games.js"></script>
<script src="/js/footer-loader.js"></script>
</body>
</html>