- Add Round timer to header and sidebar navigation - Replace Dashboard with Commanders and include Round timer - Remove Quick Actions from dashboard - Bump version to 2.1.4
334 lines
12 KiB
HTML
Executable File
334 lines
12 KiB
HTML
Executable File
<!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>EDH Stats Tracker - Dashboard</title>
|
|
<meta
|
|
name="description"
|
|
content="Track your Magic: The Gathering EDH/Commander games and statistics"
|
|
/>
|
|
<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="app()">
|
|
<!-- 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">
|
|
<div class="flex items-center space-x-4">
|
|
<h1 class="text-2xl font-bold font-mtg">EDH Stats</h1>
|
|
<div class="hidden md:flex space-x-6">
|
|
<a
|
|
href="/commanders.html"
|
|
class="text-white hover:text-edh-accent transition-colors"
|
|
>Commanders</a
|
|
>
|
|
<a
|
|
href="/round-counter.html"
|
|
class="text-white hover:text-edh-accent transition-colors"
|
|
>Round timer</a
|
|
>
|
|
<a
|
|
href="/games.html"
|
|
class="text-white hover:text-edh-accent transition-colors"
|
|
>Game Log</a
|
|
>
|
|
<a
|
|
href="/stats.html"
|
|
class="text-white hover:text-edh-accent transition-colors"
|
|
>Statistics</a
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex items-center space-x-4">
|
|
<!-- Round Counter -->
|
|
<div
|
|
x-show="roundCounter.active"
|
|
class="flex items-center space-x-2 bg-slate-800 px-3 py-2 rounded-lg"
|
|
>
|
|
<span class="text-sm">Round</span>
|
|
<span
|
|
class="text-xl font-bold"
|
|
x-text="roundCounter.current"
|
|
></span>
|
|
<button
|
|
@click="incrementRound()"
|
|
class="ml-2 hover:text-edh-accent"
|
|
>
|
|
+
|
|
</button>
|
|
<button
|
|
@click="resetRoundCounter()"
|
|
class="hover:text-edh-accent"
|
|
title="Reset"
|
|
>
|
|
↺
|
|
</button>
|
|
</div>
|
|
|
|
<!-- User Menu -->
|
|
<div class="relative" x-data="{ userMenuOpen: false }">
|
|
<button
|
|
@click="userMenuOpen = !userMenuOpen"
|
|
class="flex items-center space-x-2 hover:text-edh-accent"
|
|
>
|
|
<svg
|
|
class="w-6 h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
|
></path>
|
|
</svg>
|
|
<span x-text="currentUser?.username"></span>
|
|
<svg
|
|
class="w-4 h-4"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M19 9l-7 7-7-7"
|
|
></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<div
|
|
x-show="userMenuOpen"
|
|
@click.away="userMenuOpen = false"
|
|
x-transition
|
|
class="absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 z-50"
|
|
>
|
|
<a
|
|
href="/profile.html"
|
|
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
|
>Profile</a
|
|
>
|
|
<hr class="my-1" />
|
|
<button
|
|
@click="logout()"
|
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
|
|
>
|
|
Logout
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Menu Button -->
|
|
<button @click="mobileMenuOpen = !mobileMenuOpen" class="md:hidden">
|
|
<svg
|
|
class="w-6 h-6"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M4 6h16M4 12h16M4 18h16"
|
|
></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Menu -->
|
|
<div
|
|
x-show="mobileMenuOpen"
|
|
x-transition
|
|
class="md:hidden mt-4 pt-4 border-t border-edh-secondary"
|
|
>
|
|
<div class="flex flex-col space-y-2">
|
|
<a
|
|
href="/commanders.html"
|
|
class="text-white hover:text-edh-accent transition-colors py-2"
|
|
>Commanders</a
|
|
>
|
|
<a
|
|
href="/round-counter.html"
|
|
class="text-white hover:text-edh-accent transition-colors py-2"
|
|
>Round timer</a
|
|
>
|
|
<a
|
|
href="/games.html"
|
|
class="text-white hover:text-edh-accent transition-colors py-2"
|
|
>Game Log</a
|
|
>
|
|
<a
|
|
href="/stats.html"
|
|
class="text-white hover:text-edh-accent transition-colors py-2"
|
|
>Statistics</a
|
|
>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<main class="container mx-auto px-4 py-8">
|
|
<!-- Quick Stats (loaded via stats-cards-loader.js) -->
|
|
<div id="stats-cards-container"></div>
|
|
|
|
<!-- Recent Games -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
<div class="card">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h2 class="text-xl font-semibold">Recent Games</h2>
|
|
<a href="/games.html" class="text-edh-accent hover:text-edh-primary"
|
|
>Log Game →</a
|
|
>
|
|
</div>
|
|
|
|
<div x-show="loading" class="flex justify-center py-8">
|
|
<div class="loading-spinner w-8 h-8"></div>
|
|
</div>
|
|
|
|
<div x-show="!loading" class="space-y-4">
|
|
<template x-for="game in recentGames" :key="game.id">
|
|
<div
|
|
class="flex items-center justify-between p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
|
|
>
|
|
<div class="flex items-center space-x-4">
|
|
<div class="text-center">
|
|
<p
|
|
class="text-sm text-gray-500"
|
|
x-text="formatDate(game.date)"
|
|
></p>
|
|
<p
|
|
class="text-xs text-gray-400"
|
|
x-text="game.playerCount + ' players'"
|
|
></p>
|
|
</div>
|
|
<div>
|
|
<p class="font-medium" x-text="game.commanderName"></p>
|
|
<div class="flex space-x-1">
|
|
<template x-for="color in game.commanderColors || []">
|
|
<div
|
|
class="w-4 h-4 rounded"
|
|
:class="'color-' + color.toLowerCase()"
|
|
:title="getColorName(color)"
|
|
></div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-right">
|
|
<p
|
|
class="text-sm font-medium"
|
|
:class="game.won ? 'text-green-600' : 'text-red-600'"
|
|
>
|
|
<span x-text="game.won ? 'Won' : 'Lost'"></span>
|
|
</p>
|
|
<p class="text-xs text-gray-500">
|
|
<span x-text="game.rounds + ' rounds'"></span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<div
|
|
x-show="recentGames.length === 0"
|
|
class="text-center py-8 text-gray-500"
|
|
>
|
|
<p>No games logged yet.</p>
|
|
<a
|
|
href="/games.html"
|
|
class="text-edh-accent hover:text-edh-primary"
|
|
>Log your first game</a
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Top Commanders -->
|
|
<div class="card">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h2 class="text-xl font-semibold">Top Commanders</h2>
|
|
<a
|
|
href="/commanders.html"
|
|
class="text-edh-accent hover:text-edh-primary"
|
|
>Manage →</a
|
|
>
|
|
</div>
|
|
|
|
<div x-show="loading" class="flex justify-center py-8">
|
|
<div class="loading-spinner w-8 h-8"></div>
|
|
</div>
|
|
|
|
<div x-show="!loading" class="space-y-4">
|
|
<template
|
|
x-for="commander in topCommanders"
|
|
:key="commander.commanderId"
|
|
>
|
|
<div
|
|
class="flex items-center justify-between p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
|
|
>
|
|
<div class="flex items-center space-x-4">
|
|
<div class="flex space-x-1">
|
|
<template x-for="color in commander.colors" :key="color">
|
|
<div
|
|
class="w-6 h-6 rounded"
|
|
:class="'color-' + color.toLowerCase()"
|
|
:title="getColorName(color)"
|
|
></div>
|
|
</template>
|
|
</div>
|
|
<div>
|
|
<p class="font-medium" x-text="commander.name"></p>
|
|
<p
|
|
class="text-sm text-gray-500"
|
|
x-text="commander.totalGames + ' games'"
|
|
></p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-right">
|
|
<p
|
|
class="font-bold text-edh-primary"
|
|
x-text="(commander.winRate !== undefined && commander.winRate !== null ? commander.winRate : 0) + '%'"
|
|
></p>
|
|
<p class="text-xs text-gray-500">
|
|
<span
|
|
x-text="(commander.avgRounds !== undefined && commander.avgRounds !== null && !isNaN(commander.avgRounds) ? Math.round(commander.avgRounds) : 0) + ' avg rounds'"
|
|
></span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<div
|
|
x-show="topCommanders.length === 0"
|
|
class="text-center py-8 text-gray-500"
|
|
>
|
|
<p>No stats yet.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- 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/app.js"></script>
|
|
<script src="/js/stats-cards-loader.js"></script>
|
|
<script src="/js/footer-loader.js"></script>
|
|
</body>
|
|
</html>
|