76 lines
2.5 KiB
Vue
76 lines
2.5 KiB
Vue
<template>
|
|
<div class="grid min-h-dvh lg:grid-cols-[1.05fr_1fr]">
|
|
<!-- Left panel: login image -->
|
|
<section class="brand-panel relative hidden overflow-hidden lg:flex lg:items-center lg:justify-center">
|
|
<img src="/login.png" alt="Login" class="absolute inset-0 h-full w-full object-cover" />
|
|
<h1 class="relative z-10 -mt-48 font-display text-5xl font-extrabold tracking-[-0.03em] text-white drop-shadow-lg">MY WORKSPACE</h1>
|
|
</section>
|
|
|
|
<section class="flex items-center justify-center p-6 sm:p-10" style="background: var(--canvas)">
|
|
<div class="w-full max-w-[360px]">
|
|
<div class="mb-8">
|
|
<span class="eyebrow">My Workspace</span>
|
|
<h2 class="page-title mt-2">Sign in</h2>
|
|
<p class="page-subtitle mt-2">Projects, documents and tasks in one place.</p>
|
|
</div>
|
|
|
|
<form @submit.prevent="submit">
|
|
<div class="field">
|
|
<label for="username">Username</label>
|
|
<InputText id="username" v-model.trim="username" class="w-full" autocomplete="username" autofocus />
|
|
</div>
|
|
<div class="field">
|
|
<label for="password">Password</label>
|
|
<Password
|
|
id="password"
|
|
v-model="password"
|
|
class="w-full"
|
|
inputClass="w-full"
|
|
toggleMask
|
|
:feedback="false"
|
|
autocomplete="current-password"
|
|
/>
|
|
</div>
|
|
<Message v-if="error" severity="error" variant="simple" class="mb-3 w-full">{{ error }}</Message>
|
|
<Button type="submit" label="Sign in" class="w-full" :loading="loading" />
|
|
</form>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useAuthStore } from '../../stores/auth'
|
|
import { errorMessage } from '../../services/api'
|
|
|
|
const auth = useAuthStore()
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
|
|
const username = ref('')
|
|
const password = ref('')
|
|
const loading = ref(false)
|
|
const error = ref('')
|
|
|
|
async function submit() {
|
|
error.value = ''
|
|
if (!username.value || !password.value) {
|
|
error.value = 'Enter your username and password'
|
|
return
|
|
}
|
|
loading.value = true
|
|
try {
|
|
await auth.login(username.value, password.value)
|
|
const redirect = typeof route.query.redirect === 'string' ? route.query.redirect : null
|
|
router.push(redirect ?? (auth.isAdmin ? '/projects' : '/select-project'))
|
|
} catch (e) {
|
|
error.value = errorMessage(e)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
</style>
|