22 <div class =" card w-96 flex-shrink-0 bg-base-lighter shadow-2xl" >
33 <div class =" card-body" >
44 <form action =" " method =" post" @submit.prevent =" onLogin" ref =" form" class =" flex flex-col gap-8" >
5- <label class =" input input-bordered flex items-center gap-2 border-2 has-[:focus]:input-primary" >
6- <mdi:account class =" has-[+:focus]:text-primary" />
7- <input
8- type =" text"
9- class =" grow"
10- :placeholder =" $t('label.username')"
11- name =" username"
12- autocomplete =" username"
13- autofocus
14- required
15- />
5+ <label class =" form-control w-full" >
6+ <label
7+ class =" input input-bordered flex items-center gap-2 border-2 has-[:focus]:input-primary"
8+ :class =" { 'input-error': error }"
9+ >
10+ <mdi:account class =" has-[+:focus]:text-primary" :class =" { 'text-error': error }" />
11+ <input
12+ type =" text"
13+ class =" grow"
14+ :class =" { 'text-error': error }"
15+ :placeholder =" $t('label.username')"
16+ name =" username"
17+ autocomplete =" username"
18+ autofocus
19+ required
20+ :disabled =" loading"
21+ />
22+ </label >
23+ <label class =" label" v-if =" error" >
24+ <span class =" label-text-alt text-error" >
25+ {{ $t("error.invalid-auth") }}
26+ </span >
27+ </label >
1628 </label >
17- <label class =" input input-bordered flex items-center gap-2 border-2 has-[:focus]:input-primary " >
18- <mdi:key class =" has-[+ :focus]:text -primary" / >
19- < input
20- type = " password "
21- class = " grow "
22- :placeholder = " $t('label.password') "
23- name = " password"
24- autocomplete = " current- password"
25- autofocus
26- required
27- />
28- </ label >
29- < label class = " label text-red " v-if = " error " >
30- {{ $t("error.invalid-auth") }}
29+ <label class =" form-control w-full " >
30+ <label class =" input input-bordered flex items-center gap-2 border-2 has-[:focus]:input -primary" >
31+ < mdi:key class = " has-[+:focus]:text-primary " />
32+ < input
33+ type = " password "
34+ class = " grow "
35+ :placeholder = " $t('label. password') "
36+ name = " password"
37+ autocomplete = " current-password "
38+ autofocus
39+ required
40+ :disabled = " loading "
41+ / >
42+ </ label >
3143 </label >
3244
33- <button class =" btn btn-primary uppercase" type =" submit" >{{ $t("button.login") }}</button >
45+ <button class =" btn btn-primary uppercase" type =" submit" :disabled =" loading" >
46+ <span class =" loading loading-spinner" v-if =" loading" ></span >
47+ {{ $t("button.login") }}
48+ </button >
3449 </form >
3550 </div >
3651 </div >
@@ -42,10 +57,12 @@ const { t } = useI18n();
4257setTitle (t (" title.login" ));
4358
4459const error = ref (false );
60+ const loading = ref (false );
4561const form = ref <HTMLFormElement >();
4662const params = new URLSearchParams (window .location .search );
4763
4864async function onLogin() {
65+ loading .value = true ;
4966 const response = await fetch (withBase (" /api/token" ), {
5067 body: new FormData (form .value ),
5168 method: " POST" ,
@@ -61,6 +78,7 @@ async function onLogin() {
6178 } else {
6279 error .value = true ;
6380 }
81+ loading .value = false ;
6482}
6583 </script >
6684<route lang="yaml">
0 commit comments