|
|
@@ -1,5 +1,5 @@
|
|
|
<script setup>
|
|
|
-import { computed, ref, watch } from "vue";
|
|
|
+import { computed, onMounted, ref, watch } from "vue";
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
import BotaoAlterarTema from "../../components/BotaoAlterarTema.vue";
|
|
|
import { useAuth } from "../../composables/useAuth.js";
|
|
|
@@ -15,6 +15,12 @@ const form = ref({
|
|
|
});
|
|
|
const loading = ref(false);
|
|
|
const error = ref("");
|
|
|
+const senhaVisivel = ref(false);
|
|
|
+const loginInputRef = ref(null);
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ loginInputRef.value?.focus();
|
|
|
+});
|
|
|
|
|
|
const canSubmit = computed(() => {
|
|
|
return Boolean(form.value.login.trim() && form.value.senha);
|
|
|
@@ -78,6 +84,7 @@ async function onSubmit() {
|
|
|
<label class="grid gap-1.5">
|
|
|
<span class="text-sm font-medium">Usuario ou email</span>
|
|
|
<input
|
|
|
+ ref="loginInputRef"
|
|
|
v-model="form.login"
|
|
|
type="text"
|
|
|
name="username"
|
|
|
@@ -90,15 +97,32 @@ async function onSubmit() {
|
|
|
|
|
|
<label class="grid gap-1.5">
|
|
|
<span class="text-sm font-medium">Senha</span>
|
|
|
- <input
|
|
|
- v-model="form.senha"
|
|
|
- type="password"
|
|
|
- name="password"
|
|
|
- autocomplete="current-password"
|
|
|
- placeholder="Digite sua senha"
|
|
|
- required
|
|
|
- aria-required="true"
|
|
|
- />
|
|
|
+ <div class="relative">
|
|
|
+ <input
|
|
|
+ v-model="form.senha"
|
|
|
+ :type="senhaVisivel ? 'text' : 'password'"
|
|
|
+ name="password"
|
|
|
+ autocomplete="current-password"
|
|
|
+ placeholder="Digite sua senha"
|
|
|
+ required
|
|
|
+ aria-required="true"
|
|
|
+ class="pr-10"
|
|
|
+ />
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ class="absolute inset-y-0 right-0 flex items-center border-0 bg-transparent px-3 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300"
|
|
|
+ :aria-label="senhaVisivel ? 'Ocultar senha' : 'Mostrar senha'"
|
|
|
+ @click="senhaVisivel = !senhaVisivel"
|
|
|
+ >
|
|
|
+ <svg v-if="!senhaVisivel" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
|
|
+ </svg>
|
|
|
+ <svg v-else class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12c1.292 4.338 5.31 7.5 10.066 7.5.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88" />
|
|
|
+ </svg>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
</label>
|
|
|
|
|
|
<label class="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300">
|
|
|
@@ -112,6 +136,7 @@ async function onSubmit() {
|
|
|
|
|
|
<div
|
|
|
v-if="error"
|
|
|
+ role="alert"
|
|
|
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 }}
|