Files
solopm-server/web/src/pages/auth/LoginPage.vue
T

110 lines
3.3 KiB
Vue

<template>
<div class="min-h-screen flex items-center justify-center bg-gray-50">
<div class="w-full max-w-md px-4">
<div class="card">
<div class="p-6 pb-0 text-center">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-xl bg-gradient-to-tl from-purple-700 to-pink-500 shadow-soft-2xl mb-4">
<i class="fas fa-rocket text-white text-xl"></i>
</div>
<h5 class="font-bold">Sign in to SoloPM</h5>
<p class="mb-0 text-sm">Enter your credentials to continue</p>
</div>
<div class="p-6">
<form @submit.prevent="handleLogin">
<div class="mb-4">
<label class="form-label">Email</label>
<input
v-model="form.email"
type="email"
required
placeholder="you@example.com"
class="form-input"
/>
</div>
<div class="mb-4">
<label class="form-label">Password</label>
<input
v-model="form.password"
type="password"
required
placeholder="••••••••"
class="form-input"
/>
</div>
<p v-if="error" class="text-xs text-red-600 mb-3">{{ error }}</p>
<button
type="submit"
:disabled="loading"
class="inline-block w-full px-6 py-3 btn-primary"
>
{{ loading ? 'Signing in…' : 'Sign In' }}
</button>
</form>
<div class="relative my-5 flex items-center">
<div class="flex-grow border-t border-gray-300"></div>
<span class="mx-3 text-xs text-slate-500 uppercase font-semibold">or</span>
<div class="flex-grow border-t border-gray-300"></div>
</div>
<div class="flex flex-col gap-3">
<a
href="/api/auth/github"
class="inline-flex items-center justify-center w-full px-6 py-2.5 btn-white"
>
<i class="fab fa-github mr-2 text-base"></i>
Sign in with GitHub
</a>
<a
href="/api/auth/gitea"
class="inline-flex items-center justify-center w-full px-6 py-2.5 btn-white"
>
<i class="fab fa-git-alt mr-2 text-base"></i>
Sign in with Gitea
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import { authApi } from '@/api/auth'
const router = useRouter()
const route = useRoute()
const auth = useAuthStore()
const form = ref({ email: '', password: '' })
const loading = ref(false)
const error = ref('')
async function handleLogin() {
error.value = ''
loading.value = true
try {
const { data } = await authApi.login(form.value)
auth.setToken(data.token)
auth.setUser(data.user)
const redirect = String(route.query.redirect || '/dashboard')
router.push(redirect)
} catch {
error.value = 'Invalid email or password.'
} finally {
loading.value = false
}
}
</script>