Files
edh-stats/frontend/public/index.html
Michael Skrynski cc4ecd0ce1 Expand game query filters and update UI assets
- Backend: extend filters with dateFrom/dateTo, won, roundsMin/Max and
  colors; implement color identity using jsonb and order by date with
  limit/offset.
- Frontend: adjust slideshow spacing in index.html and include new
  images; bump version to 2.0.5.
2026-01-18 14:07:44 +01:00

273 lines
8.9 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>EDH Stats Tracker</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="min-h-full flex flex-col py-12 px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-center flex-1">
<div class="w-full space-y-8 text-center" x-data="indexApp()">
<div class="max-w-md mx-auto">
<h1 class="text-4xl font-bold font-mtg text-edh-primary mb-4">
EDH Stats
</h1>
<p class="text-xl text-gray-600 mb-8">
Track your Commander games and statistics
</p>
<div class="space-y-4">
<a href="/login.html" class="btn btn-primary w-full">
🎮 Login to Track Games
</a>
<a
x-show="allowRegistration"
href="/register.html"
class="btn btn-secondary w-full"
>
📝 Create New Account
</a>
</div>
</div>
<!-- Preview Slideshow Section -->
<div class="mt-12 max-w-6xl mx-auto">
<div
class="bg-white rounded-lg shadow-lg overflow-hidden"
x-data="slideshow()"
>
<!-- Slides Container with Arrow Navigation -->
<div class="relative bg-gray-100 pt-9 pb-9 overflow-hidden">
<!-- Image Container -->
<div
class="relative aspect-video flex items-center justify-center"
>
<template x-for="(slide, index) in slides" :key="index">
<img
:src="slide.src"
:alt="slide.alt"
x-show="currentSlide === index"
x-transition:fade.duration.500ms
class="w-full h-full object-contain absolute inset-0"
/>
</template>
<!-- Loading Spinner -->
<div
x-show="loading"
class="absolute inset-0 flex items-center justify-center bg-gray-200"
>
<div
class="animate-spin rounded-full h-12 w-12 border-b-2 border-edh-primary"
></div>
</div>
</div>
<!-- Left Arrow Button -->
<button
@click="previousSlide()"
class="absolute left-2 top-1/2 transform -translate-y-1/2 text-gray-600 hover:text-gray-800 hover:bg-gray-200 rounded-full p-2 transition-colors"
title="Previous slide"
>
<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="M15 19l-7-7 7-7"
/>
</svg>
</button>
<!-- Right Arrow Button -->
<button
@click="nextSlide()"
class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-600 hover:text-gray-800 hover:bg-gray-200 rounded-full p-2 transition-colors"
title="Next slide"
>
<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="M9 5l7 7-7 7"
/>
</svg>
</button>
<!-- Play/Pause Button -->
<button
@click="toggleAutoPlay()"
:class="autoPlay ? 'bg-edh-primary text-white' : 'bg-gray-300 text-gray-700'"
class="absolute top-4 right-4 px-3 py-1 rounded text-sm font-medium hover:opacity-80 transition-opacity"
:title="autoPlay ? 'Pause slideshow' : 'Play slideshow'"
>
<span x-show="autoPlay"></span>
<span x-show="!autoPlay"></span>
</button>
</div>
<!-- Slide Indicators (Dots) -->
<div class="bg-white px-6 py-4 flex justify-center gap-2">
<template x-for="(slide, index) in slides" :key="index">
<button
@click="goToSlide(index)"
:class="currentSlide === index ? 'bg-edh-primary' : 'bg-gray-300 hover:bg-gray-400'"
class="w-2 h-2 rounded-full transition-colors"
:title="`Go to slide ${index + 1}: ${slide.title}`"
/>
</template>
</div>
</div>
<p class="text-gray-600 mt-4 text-sm text-center">
Explore all the features of EDH Stats Tracker - track games, manage
commanders, view statistics, and use the round timer
</p>
</div>
</div>
</div>
<script
defer
src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
></script>
<script>
function indexApp() {
return {
allowRegistration: true,
async init() {
await this.checkRegistrationConfig()
},
async checkRegistrationConfig() {
try {
const response = await fetch('/api/auth/config')
if (response.ok) {
const data = await response.json()
this.allowRegistration = data.allowRegistration
} else {
// Default to true if endpoint fails
this.allowRegistration = true
}
} catch (error) {
console.error('Failed to check registration config:', error)
// Default to true if request fails
this.allowRegistration = true
}
}
}
}
function slideshow() {
return {
currentSlide: 0,
autoPlay: true,
autoPlayInterval: null,
loading: false,
slides: [
{
src: '/images/commanders.png',
alt: 'Commander management interface for adding and editing decks with color selection',
title: 'Commanders'
},
{
src: '/images/logs.png',
alt: 'Game logging form for recording game results, player count, and outcomes',
title: 'Log Games'
},
{
src: '/images/round_timer.png',
alt: 'Real-time round counter with automatic game timing and elapsed time tracking',
title: 'Round Timer'
},
{
src: '/images/stats.png',
alt: 'Detailed statistics showing win rates by color, player count, and commander performance',
title: 'Statistics'
}
],
init() {
this.startAutoPlay()
},
nextSlide() {
this.currentSlide = (this.currentSlide + 1) % this.slides.length
this.restartAutoPlay()
},
previousSlide() {
this.currentSlide =
(this.currentSlide - 1 + this.slides.length) % this.slides.length
this.restartAutoPlay()
},
goToSlide(index) {
this.currentSlide = index
this.restartAutoPlay()
},
toggleAutoPlay() {
this.autoPlay = !this.autoPlay
if (this.autoPlay) {
this.startAutoPlay()
} else {
this.stopAutoPlay()
}
},
startAutoPlay() {
this.autoPlayInterval = setInterval(() => {
this.currentSlide = (this.currentSlide + 1) % this.slides.length
}, 5000)
},
stopAutoPlay() {
if (this.autoPlayInterval) {
clearInterval(this.autoPlayInterval)
this.autoPlayInterval = null
}
},
restartAutoPlay() {
this.stopAutoPlay()
if (this.autoPlay) {
this.startAutoPlay()
}
},
destroy() {
this.stopAutoPlay()
}
}
}
document.addEventListener('alpine:init', () => {
Alpine.data('indexApp', indexApp)
Alpine.data('slideshow', slideshow)
})
</script>
<script src="/js/footer-loader.js"></script>
</body>
</html>