refactor: Transition to authentication system and remove identity management
- Replace identity management with a new authentication system across the application. - Update App.vue to integrate LoginDialog and remove PasswordDialog. - Modify Navbar.vue to handle user authentication state and logout functionality. - Enhance Home.vue to display user information upon login. - Implement routing changes in index.ts to enforce authentication requirements for protected routes.
This commit is contained in:
parent
5ceb12ca3b
commit
be4ab13b32
11 changed files with 1065 additions and 96 deletions
217
src/pages/Login.vue
Normal file
217
src/pages/Login.vue
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
<template>
|
||||
<div class="container py-8 space-y-6">
|
||||
<div class="flex flex-col items-center justify-center min-h-[60vh] space-y-8">
|
||||
<!-- Welcome Section -->
|
||||
<div class="text-center space-y-4">
|
||||
<div class="flex justify-center">
|
||||
<img src="@/assets/logo-72px.png" alt="Logo" class="h-24 w-24" />
|
||||
</div>
|
||||
<h1 class="text-4xl font-bold tracking-tight">Welcome to Ario</h1>
|
||||
<p class="text-xl text-muted-foreground max-w-md">
|
||||
Your secure platform for events and community management
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Login Card -->
|
||||
<Card class="w-full max-w-md">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-center">Sign In</CardTitle>
|
||||
<CardDescription class="text-center">
|
||||
Enter your credentials to access your account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="username">Username or Email</Label>
|
||||
<Input
|
||||
id="username"
|
||||
v-model="loginForm.username"
|
||||
placeholder="Enter your username or email"
|
||||
@keydown.enter="handleLogin"
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="password">Password</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
v-model="loginForm.password"
|
||||
placeholder="Enter your password"
|
||||
@keydown.enter="handleLogin"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="error" class="text-sm text-destructive text-center">
|
||||
{{ error }}
|
||||
</p>
|
||||
<Button
|
||||
@click="handleLogin"
|
||||
:disabled="isLoading || !canLogin"
|
||||
class="w-full"
|
||||
>
|
||||
<span v-if="isLoading" class="animate-spin mr-2">⚡</span>
|
||||
Sign In
|
||||
</Button>
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Don't have an account?
|
||||
<Button variant="link" @click="showRegister = true" class="p-0 h-auto">
|
||||
Create one
|
||||
</Button>
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<!-- Register Card -->
|
||||
<Card v-if="showRegister" class="w-full max-w-md">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-center">Create Account</CardTitle>
|
||||
<CardDescription class="text-center">
|
||||
Create a new account to get started
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="reg-username">Username</Label>
|
||||
<Input
|
||||
id="reg-username"
|
||||
v-model="registerForm.username"
|
||||
placeholder="Choose a username"
|
||||
@keydown.enter="handleRegister"
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="reg-email">Email (optional)</Label>
|
||||
<Input
|
||||
id="reg-email"
|
||||
type="email"
|
||||
v-model="registerForm.email"
|
||||
placeholder="Enter your email"
|
||||
@keydown.enter="handleRegister"
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="reg-password">Password</Label>
|
||||
<Input
|
||||
id="reg-password"
|
||||
type="password"
|
||||
v-model="registerForm.password"
|
||||
placeholder="Choose a password"
|
||||
@keydown.enter="handleRegister"
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="reg-password-repeat">Confirm Password</Label>
|
||||
<Input
|
||||
id="reg-password-repeat"
|
||||
type="password"
|
||||
v-model="registerForm.password_repeat"
|
||||
placeholder="Confirm your password"
|
||||
@keydown.enter="handleRegister"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="error" class="text-sm text-destructive text-center">
|
||||
{{ error }}
|
||||
</p>
|
||||
<Button
|
||||
@click="handleRegister"
|
||||
:disabled="isLoading || !canRegister"
|
||||
class="w-full"
|
||||
>
|
||||
<span v-if="isLoading" class="animate-spin mr-2">⚡</span>
|
||||
Create Account
|
||||
</Button>
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Already have an account?
|
||||
<Button variant="link" @click="showRegister = false" class="p-0 h-auto">
|
||||
Sign in
|
||||
</Button>
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { auth } from '@/composables/useAuth'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
const showRegister = ref(false)
|
||||
const isLoading = ref(false)
|
||||
const error = ref('')
|
||||
|
||||
// Login form
|
||||
const loginForm = ref({
|
||||
username: '',
|
||||
password: ''
|
||||
})
|
||||
|
||||
// Register form
|
||||
const registerForm = ref({
|
||||
username: '',
|
||||
email: '',
|
||||
password: '',
|
||||
password_repeat: ''
|
||||
})
|
||||
|
||||
const canLogin = computed(() => {
|
||||
return loginForm.value.username.trim() && loginForm.value.password.trim()
|
||||
})
|
||||
|
||||
const canRegister = computed(() => {
|
||||
const { username, password, password_repeat } = registerForm.value
|
||||
return username.trim() && password.trim() && password === password_repeat && password.length >= 6
|
||||
})
|
||||
|
||||
async function handleLogin() {
|
||||
if (!canLogin.value) return
|
||||
|
||||
try {
|
||||
isLoading.value = true
|
||||
error.value = ''
|
||||
|
||||
await auth.login({
|
||||
username: loginForm.value.username,
|
||||
password: loginForm.value.password
|
||||
})
|
||||
|
||||
toast.success('Login successful!')
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : 'Login failed'
|
||||
toast.error('Login failed. Please check your credentials.')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleRegister() {
|
||||
if (!canRegister.value) return
|
||||
|
||||
try {
|
||||
isLoading.value = true
|
||||
error.value = ''
|
||||
|
||||
await auth.register({
|
||||
username: registerForm.value.username,
|
||||
email: registerForm.value.email || undefined,
|
||||
password: registerForm.value.password,
|
||||
password_repeat: registerForm.value.password_repeat
|
||||
})
|
||||
|
||||
toast.success('Registration successful!')
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : 'Registration failed'
|
||||
toast.error('Registration failed. Please try again.')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue