|
@@ -0,0 +1,120 @@
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { computed, ref } from "vue";
|
|
|
|
|
+import { useRoute, useRouter } from "vue-router";
|
|
|
|
|
+import BotaoAlterarTema from "../../components/BotaoAlterarTema.vue";
|
|
|
|
|
+import { useAuth } from "../../composables/useAuth.js";
|
|
|
|
|
+
|
|
|
|
|
+const router = useRouter();
|
|
|
|
|
+const route = useRoute();
|
|
|
|
|
+const { login } = useAuth();
|
|
|
|
|
+
|
|
|
|
|
+const form = ref({
|
|
|
|
|
+ login: "",
|
|
|
|
|
+ senha: "",
|
|
|
|
|
+ rememberMe: false
|
|
|
|
|
+});
|
|
|
|
|
+const loading = ref(false);
|
|
|
|
|
+const error = ref("");
|
|
|
|
|
+
|
|
|
|
|
+const canSubmit = computed(() => {
|
|
|
|
|
+ return Boolean(form.value.login.trim() && form.value.senha);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+async function onSubmit() {
|
|
|
|
|
+ if (!canSubmit.value || loading.value) return;
|
|
|
|
|
+
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ error.value = "";
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ await login(form.value);
|
|
|
|
|
+ const redirect = typeof route.query.redirect === "string" ? route.query.redirect : "/";
|
|
|
|
|
+ await router.replace(redirect);
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ error.value = err?.message || "Falha ao realizar login.";
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loading.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="relative min-h-screen overflow-hidden bg-background text-foreground">
|
|
|
|
|
+ <div
|
|
|
|
|
+ aria-hidden="true"
|
|
|
|
|
+ class="pointer-events-none absolute inset-0 z-0 bg-[radial-gradient(900px_520px_at_20%_10%,rgba(37,99,235,0.12),transparent_60%),radial-gradient(700px_520px_at_85%_35%,rgba(162,102,255,0.10),transparent_60%)] dark:hidden"
|
|
|
|
|
+ />
|
|
|
|
|
+ <div
|
|
|
|
|
+ aria-hidden="true"
|
|
|
|
|
+ class="pointer-events-none absolute inset-0 z-0 hidden bg-[radial-gradient(900px_520px_at_20%_10%,rgba(91,140,255,0.18),transparent_60%),radial-gradient(700px_520px_at_85%_35%,rgba(162,102,255,0.14),transparent_60%)] dark:block"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <header class="relative z-10 flex items-center justify-between px-6 py-5">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="text-[16px] font-extrabold tracking-[0.14em]">ORACULO</div>
|
|
|
|
|
+ <div class="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
|
|
|
|
+ Acesso ao assistente interno
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <BotaoAlterarTema />
|
|
|
|
|
+ </header>
|
|
|
|
|
+
|
|
|
|
|
+ <main class="relative z-10 flex min-h-[calc(100vh-88px)] items-center justify-center px-4 pb-8">
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="w-full max-w-md rounded-[28px] border border-gray-200 bg-white/80 p-6 shadow-sm backdrop-blur-md dark:border-white/10 dark:bg-gradient-to-b dark:from-[#101827] dark:to-[#070b16] dark:shadow-[0_18px_50px_rgba(0,0,0,0.35)]"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="text-2xl font-extrabold tracking-tight">Entrar</div>
|
|
|
|
|
+ <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
|
|
|
|
+ Informe seu usuario ou email e sua senha para acessar o sistema.
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <form class="mt-6 grid gap-4" @submit.prevent="onSubmit">
|
|
|
|
|
+ <label class="grid gap-1.5">
|
|
|
|
|
+ <span class="text-sm font-medium">Usuario ou email</span>
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-model="form.login"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ autocomplete="username"
|
|
|
|
|
+ placeholder="Digite seu login"
|
|
|
|
|
+ />
|
|
|
|
|
+ </label>
|
|
|
|
|
+
|
|
|
|
|
+ <label class="grid gap-1.5">
|
|
|
|
|
+ <span class="text-sm font-medium">Senha</span>
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-model="form.senha"
|
|
|
|
|
+ type="password"
|
|
|
|
|
+ autocomplete="current-password"
|
|
|
|
|
+ placeholder="Digite sua senha"
|
|
|
|
|
+ />
|
|
|
|
|
+ </label>
|
|
|
|
|
+
|
|
|
|
|
+ <label class="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300">
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-model="form.rememberMe"
|
|
|
|
|
+ type="checkbox"
|
|
|
|
|
+ class="!h-4 !w-4 rounded border-gray-300 !p-0"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span>Manter conectado neste navegador</span>
|
|
|
|
|
+ </label>
|
|
|
|
|
+
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="error"
|
|
|
|
|
+ class="rounded-xl border border-red-300 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-500/40 dark:bg-red-500/10 dark:text-red-200"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ error }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="submit"
|
|
|
|
|
+ class="mt-2 inline-flex items-center justify-center rounded-xl border border-primary bg-primary px-4 py-2.5 text-sm font-semibold text-primary-foreground transition-colors hover:border-[var(--primary-600)] hover:bg-[var(--primary-600)]"
|
|
|
|
|
+ :disabled="!canSubmit || loading"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ loading ? "Entrando..." : "Entrar" }}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </main>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|