Files
thrillwiki_django_no_react/backend/templates/components/auth/auth-modal.html
pac7 1208af9696 Update Alpine.js components to use standalone instances
Correctly initialize Alpine.js components by removing unnecessary function calls, ensuring proper scope and state management for UI elements like modals, search, theme toggles, and forms.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: eff39de1-3afa-446d-a965-acaf61837fc7
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d6d61dac-164d-45dd-929f-7dcdfd771b64/eff39de1-3afa-446d-a965-acaf61837fc7/cGHPY6T
2025-09-22 00:15:14 +00:00

368 lines
12 KiB
HTML

{% comment %}
Enhanced Authentication Modal Component
Matches React frontend AuthDialog functionality with modal-based auth
{% endcomment %}
{% load static %}
{% load i18n %}
{% load account socialaccount %}
<!-- Auth Modal Component -->
<div
x-data="authModal"
x-show="open"
x-cloak
x-init="window.authModal = $data"
class="fixed inset-0 z-50 flex items-center justify-center"
@keydown.escape.window="close()"
>
<!-- Modal Overlay -->
<div
x-show="open"
x-transition:enter="transition-opacity ease-linear duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition-opacity ease-linear duration-300"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="fixed inset-0 bg-background/80 backdrop-blur-sm"
@click="close()"
></div>
<!-- Modal Content -->
<div
x-show="open"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="relative w-full max-w-md mx-4 bg-background border rounded-lg shadow-lg"
@click.stop
>
<!-- Close Button -->
<button
@click="close()"
class="absolute top-4 right-4 p-2 text-muted-foreground hover:text-foreground rounded-md hover:bg-accent transition-colors"
>
<i class="fas fa-times w-4 h-4"></i>
</button>
<!-- Login Form -->
<div x-show="mode === 'login'" class="p-6">
<div class="text-center mb-6">
<h2 class="text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-700">
Sign In
</h2>
<p class="text-sm text-muted-foreground mt-2">
Enter your credentials to access your account
</p>
</div>
<!-- Social Login Buttons -->
<div x-show="socialProviders.length > 0" class="mb-6">
<div class="grid grid-cols-2 gap-4" x-show="!socialLoading">
<template x-for="provider in socialProviders" :key="provider.id">
<button
@click="handleSocialLogin(provider.id)"
class="flex items-center justify-center px-4 py-2 text-sm font-medium text-white rounded-md transition-colors"
:class="{
'bg-[#4285F4] hover:bg-[#357AE8]': provider.id === 'google',
'bg-[#5865F2] hover:bg-[#4752C4]': provider.id === 'discord',
'bg-primary hover:bg-primary/90': !['google', 'discord'].includes(provider.id)
}"
>
<i
class="mr-2 w-4 h-4"
:class="{
'fab fa-google': provider.id === 'google',
'fab fa-discord': provider.id === 'discord'
}"
></i>
<span x-text="provider.name"></span>
</button>
</template>
</div>
<div x-show="socialLoading" class="grid grid-cols-2 gap-4">
<div class="h-10 bg-muted animate-pulse rounded-md"></div>
<div class="h-10 bg-muted animate-pulse rounded-md"></div>
</div>
<!-- Divider -->
<div class="relative my-6">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-muted"></div>
</div>
<div class="relative flex justify-center text-xs uppercase">
<span class="bg-background px-2 text-muted-foreground">
Or continue with
</span>
</div>
</div>
</div>
<!-- Login Form -->
<form
@submit.prevent="handleLogin()"
class="space-y-4"
>
<div class="space-y-2">
<label for="login-username" class="text-sm font-medium">
Email or Username
</label>
<input
id="login-username"
type="text"
x-model="loginForm.username"
placeholder="Enter your email or username"
class="input w-full"
required
/>
</div>
<div class="space-y-2">
<label for="login-password" class="text-sm font-medium">
Password
</label>
<div class="relative">
<input
id="login-password"
:type="showPassword ? 'text' : 'password'"
x-model="loginForm.password"
placeholder="Enter your password"
class="input w-full pr-10"
required
/>
<button
type="button"
@click="showPassword = !showPassword"
class="absolute right-3 top-1/2 transform -translate-y-1/2 text-muted-foreground hover:text-foreground"
>
<i :class="showPassword ? 'fas fa-eye-slash' : 'fas fa-eye'" class="w-4 h-4"></i>
</button>
</div>
</div>
<div class="flex items-center justify-between">
<a
href="{% url 'account_reset_password' %}"
class="text-sm text-primary hover:text-primary/80 underline-offset-4 hover:underline font-medium"
>
Forgot password?
</a>
</div>
<!-- Error Messages -->
<div x-show="loginError" class="p-3 text-sm text-destructive-foreground bg-destructive/10 border border-destructive/20 rounded-md">
<span x-text="loginError"></span>
</div>
<button
type="submit"
:disabled="loginLoading"
class="btn btn-default w-full bg-gradient-to-r from-blue-600 to-purple-700 hover:from-blue-700 hover:to-purple-800 text-white"
>
<span x-show="!loginLoading">Sign In</span>
<span x-show="loginLoading" class="flex items-center">
<i class="fas fa-spinner fa-spin mr-2"></i>
Signing in...
</span>
</button>
</form>
<!-- Switch to Register -->
<div class="text-center text-sm text-muted-foreground mt-6">
Don't have an account?
<button
@click="switchToRegister()"
class="text-primary hover:underline font-medium ml-1"
type="button"
>
Sign up
</button>
</div>
</div>
<!-- Register Form -->
<div x-show="mode === 'register'" class="p-6">
<div class="text-center mb-6">
<h2 class="text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-700">
Create Account
</h2>
<p class="text-sm text-muted-foreground mt-2">
Join ThrillWiki to start exploring theme parks
</p>
</div>
<!-- Social Registration Buttons -->
<div x-show="socialProviders.length > 0" class="mb-6">
<div class="grid grid-cols-2 gap-4" x-show="!socialLoading">
<template x-for="provider in socialProviders" :key="provider.id">
<button
@click="handleSocialLogin(provider.id)"
class="flex items-center justify-center px-4 py-2 text-sm font-medium text-white rounded-md transition-colors"
:class="{
'bg-[#4285F4] hover:bg-[#357AE8]': provider.id === 'google',
'bg-[#5865F2] hover:bg-[#4752C4]': provider.id === 'discord',
'bg-primary hover:bg-primary/90': !['google', 'discord'].includes(provider.id)
}"
>
<i
class="mr-2 w-4 h-4"
:class="{
'fab fa-google': provider.id === 'google',
'fab fa-discord': provider.id === 'discord'
}"
></i>
<span x-text="provider.name"></span>
</button>
</template>
</div>
<!-- Divider -->
<div class="relative my-6">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-muted"></div>
</div>
<div class="relative flex justify-center text-xs uppercase">
<span class="bg-background px-2 text-muted-foreground">
Or continue with email
</span>
</div>
</div>
</div>
<!-- Register Form -->
<form
@submit.prevent="handleRegister()"
class="space-y-4"
>
<div class="grid grid-cols-2 gap-4">
<div class="space-y-2">
<label for="register-first-name" class="text-sm font-medium">
First Name
</label>
<input
id="register-first-name"
type="text"
x-model="registerForm.first_name"
placeholder="First name"
class="input w-full"
required
/>
</div>
<div class="space-y-2">
<label for="register-last-name" class="text-sm font-medium">
Last Name
</label>
<input
id="register-last-name"
type="text"
x-model="registerForm.last_name"
placeholder="Last name"
class="input w-full"
required
/>
</div>
</div>
<div class="space-y-2">
<label for="register-email" class="text-sm font-medium">
Email
</label>
<input
id="register-email"
type="email"
x-model="registerForm.email"
placeholder="Enter your email"
class="input w-full"
required
/>
</div>
<div class="space-y-2">
<label for="register-username" class="text-sm font-medium">
Username
</label>
<input
id="register-username"
type="text"
x-model="registerForm.username"
placeholder="Choose a username"
class="input w-full"
required
/>
</div>
<div class="space-y-2">
<label for="register-password" class="text-sm font-medium">
Password
</label>
<div class="relative">
<input
id="register-password"
:type="showPassword ? 'text' : 'password'"
x-model="registerForm.password1"
placeholder="Create a password"
class="input w-full pr-10"
required
/>
<button
type="button"
@click="showPassword = !showPassword"
class="absolute right-3 top-1/2 transform -translate-y-1/2 text-muted-foreground hover:text-foreground"
>
<i :class="showPassword ? 'fas fa-eye-slash' : 'fas fa-eye'" class="w-4 h-4"></i>
</button>
</div>
</div>
<div class="space-y-2">
<label for="register-password2" class="text-sm font-medium">
Confirm Password
</label>
<input
id="register-password2"
:type="showPassword ? 'text' : 'password'"
x-model="registerForm.password2"
placeholder="Confirm your password"
class="input w-full"
required
/>
</div>
<!-- Error Messages -->
<div x-show="registerError" class="p-3 text-sm text-destructive-foreground bg-destructive/10 border border-destructive/20 rounded-md">
<span x-text="registerError"></span>
</div>
<button
type="submit"
:disabled="registerLoading"
class="btn btn-default w-full bg-gradient-to-r from-blue-600 to-purple-700 hover:from-blue-700 hover:to-purple-800 text-white"
>
<span x-show="!registerLoading">Create Account</span>
<span x-show="registerLoading" class="flex items-center">
<i class="fas fa-spinner fa-spin mr-2"></i>
Creating account...
</span>
</button>
</form>
<!-- Switch to Login -->
<div class="text-center text-sm text-muted-foreground mt-6">
Already have an account?
<button
@click="switchToLogin()"
class="text-primary hover:underline font-medium ml-1"
type="button"
>
Sign in
</button>
</div>
</div>
</div>
</div>