first iteration on frontend, done by claude because i'm lazy with frontend
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
<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="relative flex flex-col min-w-0 break-words bg-white shadow-soft-xl rounded-2xl bg-clip-border">
|
||||
|
||||
<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="mb-2 text-xs font-semibold text-slate-700 uppercase">Email</label>
|
||||
<input
|
||||
v-model="form.email"
|
||||
type="email"
|
||||
required
|
||||
placeholder="you@example.com"
|
||||
class="text-sm focus:shadow-soft-primary-outline ease-soft block w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding py-2 px-3 text-gray-700 transition-all placeholder:text-gray-500 focus:border-fuchsia-300 focus:outline-none focus:transition-shadow"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="mb-2 text-xs font-semibold text-slate-700 uppercase">Password</label>
|
||||
<input
|
||||
v-model="form.password"
|
||||
type="password"
|
||||
required
|
||||
placeholder="••••••••"
|
||||
class="text-sm focus:shadow-soft-primary-outline ease-soft block w-full rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding py-2 px-3 text-gray-700 transition-all placeholder:text-gray-500 focus:border-fuchsia-300 focus:outline-none focus:transition-shadow"
|
||||
/>
|
||||
</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 font-bold text-center text-white uppercase align-middle transition-all ease-in border-0 rounded-lg select-none shadow-soft-md bg-150 bg-x-25 leading-pro text-xs bg-gradient-to-tl from-purple-700 to-pink-500 hover:shadow-soft-2xl hover:scale-102 disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:scale-100"
|
||||
>
|
||||
{{ 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 font-bold text-center text-slate-700 uppercase transition-all ease-in bg-white border border-solid border-gray-300 rounded-lg shadow-soft-sm text-xs hover:shadow-soft-md hover:scale-102"
|
||||
>
|
||||
<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 font-bold text-center text-slate-700 uppercase transition-all ease-in bg-white border border-solid border-gray-300 rounded-lg shadow-soft-sm text-xs hover:shadow-soft-md hover:scale-102"
|
||||
>
|
||||
<i class="fas fa-code-branch 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>
|
||||
Reference in New Issue
Block a user