139 lines
5.4 KiB
Vue
139 lines
5.4 KiB
Vue
<script setup>
|
|
import { ref } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
import Button from 'primevue/button'
|
|
import InputText from 'primevue/inputtext'
|
|
import Password from 'primevue/password'
|
|
|
|
const router = useRouter()
|
|
const authStore = useAuthStore()
|
|
|
|
const username = ref('')
|
|
const password = ref('')
|
|
const fullName = ref('')
|
|
const loading = ref(false)
|
|
|
|
const handleRegister = async () => {
|
|
if (!username.value.trim() || !password.value.trim()) {
|
|
authStore.error = 'Please fill in all required fields'
|
|
return
|
|
}
|
|
|
|
loading.value = true
|
|
const success = await authStore.register({
|
|
username: username.value,
|
|
password: password.value,
|
|
fullName: fullName.value
|
|
})
|
|
|
|
if (success) {
|
|
// Auto-login after successful registration
|
|
const loginSuccess = await authStore.login({
|
|
username: username.value,
|
|
password: password.value
|
|
})
|
|
|
|
if (loginSuccess) {
|
|
router.push('/')
|
|
} else {
|
|
router.push('/login')
|
|
}
|
|
}
|
|
loading.value = false
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="h-screen w-full flex items-center justify-center bg-slate-950 overflow-hidden relative">
|
|
<!-- Animated Background Blur -->
|
|
<div class="absolute top-1/4 left-1/4 w-96 h-96 bg-violet-600/20 blur-[120px] rounded-full animate-pulse"></div>
|
|
<div class="absolute bottom-1/4 right-1/4 w-96 h-96 bg-cyan-600/20 blur-[120px] rounded-full animate-pulse"
|
|
style="animation-delay: 1s;"></div>
|
|
|
|
<div
|
|
class="glass-panel p-10 rounded-3xl border border-white/10 bg-white/5 backdrop-blur-xl w-full max-w-md z-10 flex flex-col items-center gap-8 shadow-2xl">
|
|
<div class="text-center">
|
|
<div
|
|
class="w-16 h-16 bg-gradient-to-tr from-violet-600 to-cyan-500 rounded-2xl flex items-center justify-center text-3xl mb-6 mx-auto shadow-lg shadow-violet-500/20">
|
|
🚀
|
|
</div>
|
|
<h1 class="text-3xl font-bold text-white mb-2 tracking-tight">Create Account</h1>
|
|
<p class="text-slate-400 text-sm">Join the workspace</p>
|
|
</div>
|
|
|
|
<div class="w-full flex flex-col gap-4">
|
|
<div class="flex flex-col gap-1.5">
|
|
<label class="text-slate-400 text-[10px] font-bold uppercase tracking-widest ml-1">Username</label>
|
|
<div class="relative">
|
|
<InputText v-model="username" placeholder="Choose a username"
|
|
class="w-full !bg-slate-900/50 !border-white/10 !text-white !p-4 !rounded-xl focus:!border-violet-500 !transition-all" />
|
|
<i class="pi pi-user absolute right-4 top-1/2 -translate-y-1/2 text-slate-500"></i>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex flex-col gap-1.5">
|
|
<label class="text-slate-400 text-[10px] font-bold uppercase tracking-widest ml-1">Full Name (Optional)</label>
|
|
<div class="relative">
|
|
<InputText v-model="fullName" placeholder="John Doe"
|
|
class="w-full !bg-slate-900/50 !border-white/10 !text-white !p-4 !rounded-xl focus:!border-violet-500 !transition-all" />
|
|
<i class="pi pi-id-card absolute right-4 top-1/2 -translate-y-1/2 text-slate-500"></i>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex flex-col gap-1.5">
|
|
<label class="text-slate-400 text-[10px] font-bold uppercase tracking-widest ml-1">Password</label>
|
|
<div class="relative">
|
|
<Password v-model="password" placeholder="••••••••"
|
|
inputClass="w-full !bg-slate-900/50 !border-white/10 !text-white !p-4 !rounded-xl focus:!border-violet-500 !transition-all"
|
|
toggleMask @keyup.enter="handleRegister" class="w-full" />
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="authStore.error" class="text-red-400 text-xs ml-1 flex items-center gap-1.5 animate-bounce">
|
|
<i class="pi pi-exclamation-circle"></i>
|
|
{{ authStore.error }}
|
|
</div>
|
|
|
|
<Button label="Create Account" icon="pi pi-user-plus" :loading="loading" @click="handleRegister"
|
|
class="w-full !py-4 !rounded-xl !bg-gradient-to-r !from-violet-600 !to-cyan-500 !border-none !font-bold !text-lg !shadow-xl !shadow-violet-900/20 hover:scale-[1.02] active:scale-[0.98] transition-all" />
|
|
|
|
<div class="text-center mt-2">
|
|
<span class="text-slate-500 text-sm">Already have an account? </span>
|
|
<router-link to="/login" class="text-violet-400 hover:text-violet-300 transition-colors text-sm font-semibold">
|
|
Sign in
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.glass-panel {
|
|
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
@keyframes pulse {
|
|
|
|
0%,
|
|
100% {
|
|
transform: scale(1);
|
|
opacity: 0.2;
|
|
}
|
|
|
|
50% {
|
|
transform: scale(1.1);
|
|
opacity: 0.3;
|
|
}
|
|
}
|
|
|
|
.animate-pulse {
|
|
animation: pulse 8s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
}
|
|
|
|
:deep(.p-password-input) {
|
|
width: 100%;
|
|
}
|
|
</style>
|