69 lines
3.2 KiB
Vue
69 lines
3.2 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { Activity } from 'lucide-vue-next'
|
|
|
|
const router = useRouter()
|
|
const email = ref('')
|
|
const password = ref('')
|
|
const errorMsg = ref('')
|
|
const loading = ref(false)
|
|
|
|
const handleLogin = async () => {
|
|
errorMsg.value = ''
|
|
loading.value = true
|
|
|
|
const apiBase = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080/api/v1'
|
|
|
|
try {
|
|
const res = await fetch(`${apiBase}/auth/login`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email: email.value, password: password.value })
|
|
})
|
|
|
|
if (!res.ok) throw new Error('Invalid credentials')
|
|
|
|
const data = await res.json()
|
|
if (data.data && data.data.token) {
|
|
localStorage.setItem('jwt_token', data.data.token)
|
|
router.push('/dashboard')
|
|
} else {
|
|
throw new Error(data.message || 'Login failed')
|
|
}
|
|
} catch (err: any) {
|
|
errorMsg.value = err.message || 'Login failed'
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
</script>
|
|
<template>
|
|
<div class="h-screen w-full flex items-center justify-center relative bg-[#0B1120]">
|
|
<div class="glass-panel w-full max-w-sm p-8 z-10 flex flex-col items-center">
|
|
<div class="w-12 h-12 rounded-xl bg-gradient-to-br from-brand-primary to-blue-600 flex items-center justify-center mb-6">
|
|
<Activity color="white" :size="24" />
|
|
</div>
|
|
<h2 class="text-2xl font-bold text-white mb-2">Welcome Back</h2>
|
|
<p class="text-zinc-400 text-sm text-center mb-8">Sign in to orchestrate your AI reply strategy.</p>
|
|
|
|
<form @submit.prevent="handleLogin" class="w-full space-y-4">
|
|
<div v-if="errorMsg" class="bg-red-500/10 text-red-400 p-3 rounded-lg text-sm text-center">
|
|
{{ errorMsg }}
|
|
</div>
|
|
<div>
|
|
<label class="text-xs font-semibold text-zinc-500 uppercase tracking-widest block mb-2">Email</label>
|
|
<input v-model="email" type="email" required placeholder="founder@startup.com" class="w-full bg-black/20 border border-white/10 rounded-lg px-4 py-3 text-white placeholder-zinc-600 focus:outline-none focus:border-brand-primary/50 focus:ring-1 focus:ring-brand-primary/50 transition-all cursor-text pointer-events-auto" style="pointer-events: auto;" />
|
|
</div>
|
|
<div>
|
|
<label class="text-xs font-semibold text-zinc-500 uppercase tracking-widest block mb-2">Password</label>
|
|
<input v-model="password" type="password" required placeholder="••••••••" class="w-full bg-black/20 border border-white/10 rounded-lg px-4 py-3 text-white placeholder-zinc-600 focus:outline-none focus:border-brand-primary/50 focus:ring-1 focus:ring-brand-primary/50 transition-all cursor-text pointer-events-auto" style="pointer-events: auto;" />
|
|
</div>
|
|
<button type="submit" :disabled="loading" class="w-full bg-brand-primary hover:bg-blue-500 disabled:opacity-50 text-white font-medium rounded-lg px-4 py-3 mt-4 transition-all hover:shadow-[0_0_20px_rgba(59,130,246,0.3)] duration-300">
|
|
{{ loading ? 'Signing In...' : 'Sign In' }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</template>
|