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

315 lines
11 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>Login - EDH Stats Tracker</title>
<meta
name="description"
content="Login to track your Magic: The Gathering EDH/Commander games"
/>
<link rel="stylesheet" href="/css/styles.css" />
</head>
<body
class="h-full flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8"
>
<div class="max-w-md w-full space-y-8" x-data="loginWithRegistration()">
<!-- Header -->
<div class="text-center">
<h1 class="text-4xl font-bold font-mtg text-edh-primary mb-2">
EDH Stats
</h1>
<h2 class="text-xl text-gray-600">Sign in to your account</h2>
</div>
<!-- Login Form -->
<div class="card">
<form class="space-y-6" @submit.prevent="handleLogin">
<!-- Username Field -->
<div>
<label for="username" class="form-label">Username</label>
<div class="relative">
<input
id="username"
name="username"
type="text"
required
x-model="formData.username"
@input="validateUsername()"
:class="errors.username ? 'border-red-500 focus:ring-red-500' : ''"
class="form-input pl-10"
placeholder="Enter your username"
/>
<div
class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"
>
<svg
class="h-5 w-5 text-gray-400"
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>
</div>
</div>
<p
x-show="errors.username"
x-text="errors.username"
class="form-error"
></p>
</div>
<!-- Password Field -->
<div>
<label for="password" class="form-label">Password</label>
<div class="relative">
<input
id="password"
name="password"
:type="showPassword ? 'text' : 'password'"
required
x-model="formData.password"
@input="validatePassword()"
:class="errors.password ? 'border-red-500 focus:ring-red-500' : ''"
class="form-input pl-10 pr-10"
placeholder="Enter your password"
/>
<div
class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"
>
<svg
class="h-5 w-5 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
></path>
</svg>
</div>
<button
type="button"
@click="showPassword = !showPassword"
class="absolute inset-y-0 right-0 pr-3 flex items-center"
>
<svg
x-show="!showPassword"
class="h-5 w-5 text-gray-400 hover:text-gray-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
></path>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
></path>
</svg>
<svg
x-show="showPassword"
class="h-5 w-5 text-gray-400 hover:text-gray-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
></path>
</svg>
</button>
</div>
<p
x-show="errors.password"
x-text="errors.password"
class="form-error"
></p>
</div>
<!-- Remember Me -->
<div class="flex items-center justify-between">
<div class="flex items-center">
<input
id="remember"
name="remember"
type="checkbox"
x-model="formData.remember"
class="h-4 w-4 text-edh-accent focus:ring-edh-accent border-gray-300 rounded"
/>
<label for="remember" class="ml-2 block text-sm text-gray-900">
Remember me
</label>
</div>
<div class="text-sm">
<a
href="#"
class="font-medium text-edh-accent hover:text-edh-primary"
>
Forgot password?
</a>
</div>
</div>
<!-- Error Message -->
<div
x-show="serverError"
x-transition
class="rounded-md bg-red-50 p-4"
>
<div class="flex">
<div class="flex-shrink-0">
<svg
class="h-5 w-5 text-red-400"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
clip-rule="evenodd"
/>
</svg>
</div>
<div class="ml-3">
<p class="text-sm text-red-800" x-text="serverError"></p>
</div>
</div>
</div>
<!-- Submit Button -->
<div>
<button
type="submit"
:disabled="loading"
class="btn btn-primary w-full flex justify-center items-center space-x-2"
:class="{ 'opacity-50 cursor-not-allowed': loading }"
>
<svg
x-show="!loading"
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="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"
></path>
</svg>
<svg
x-show="loading"
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="loading ? 'Signing in...' : 'Sign in'"></span>
</button>
</div>
<!-- Register Link -->
<div class="text-center" x-show="allowRegistration">
<p class="text-sm text-gray-600">
Don't have an account?
<a
href="/register.html"
class="font-medium text-edh-accent hover:text-edh-primary"
>
Sign up
</a>
</p>
</div>
</form>
</div>
<!-- Test Credentials (for development) -->
<div class="card bg-blue-50 border-blue-200">
<h3 class="text-sm font-medium text-blue-800 mb-2">
Test Credentials (Development)
</h3>
<div class="text-xs text-blue-700 space-y-1">
<p><strong>Username:</strong> testuser</p>
<p><strong>Password:</strong> password123</p>
<p><strong>Username:</strong> magictg</p>
<p><strong>Password:</strong> password123</p>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://cdn.tailwindcss.com"></script>
<script
defer
src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
></script>
<script src="/js/auth.js"></script>
<script>
function loginWithRegistration() {
return {
...loginForm(),
allowRegistration: true,
async init() {
// Check registration config
await this.checkRegistrationConfig()
// Call parent init if it exists
if (typeof super.init === 'function') {
super.init()
}
},
async checkRegistrationConfig() {
try {
const response = await fetch('/api/auth/config')
if (response.ok) {
const data = await response.json()
this.allowRegistration = data.allowRegistration
} else {
this.allowRegistration = true
}
} catch (error) {
console.error('Failed to check registration config:', error)
this.allowRegistration = true
}
}
}
}
</script>
</body>
</html>