115 lines
4.1 KiB
Vue
115 lines
4.1 KiB
Vue
<template>
|
|
<div class="container h-screen-main">
|
|
<div class="flex justify-center items-center min-h-full">
|
|
<div class="w-full max-w-md p-8">
|
|
<h2 class="text-center text-2xl mb-4 font-semibold">LOGIN</h2>
|
|
<form action="#" method="post" class="w-full grid gap-2" @submit.prevent="signIn">
|
|
<label for="account" class="relative">
|
|
<p class="text-sm font-normal mb-2">Account</p>
|
|
<span class="absolute flex bottom-1 left-0 items-center pl-2 pr-2 border-r border-neutral-300 h-[26px]">
|
|
<IconMember class="h-5 w-5 fill-current"/>
|
|
</span>
|
|
<input type="text" id="account" class="w-full border border-neutral-300 rounded py-1 pl-10 pr-2 focus:outline-none focus:border-primary focus:ring-1 " :class="{'border-danger':isInvalid}" required autofocus v-model.trim="auth.username" @change="changeHandler($event)"/>
|
|
</label>
|
|
<label for="passwordt" class="relative block">
|
|
<p class="text-sm font-normal mb-2">Password</p>
|
|
<span class="absolute flex bottom-1 left-0 items-center pl-2 pr-2 border-r border-neutral-300 h-[26px]">
|
|
<IconLockKey class="h-5 w-5 fill-current"/>
|
|
</span>
|
|
<input :type="showPassword ? 'text' : 'password'" id="password" aria-describedby="password-addon" class="w-full border border-neutral-300 rounded py-1 pl-10 pr-2 focus:outline-none focus:border-primary focus:ring-1 " :class="{'border-danger':isInvalid}" required v-model.trim="auth.password" @change="changeHandler($event)"/>
|
|
<span class="absolute bottom-2 right-4 inline-flex items-center cursor-pointer" v-show="auth.password" @click="showPassword = !showPassword">
|
|
<IconEyeClose class="h-5 w-5" v-if="showPassword"/>
|
|
<IconEyeOpen class="h-5 w-5" v-else/>
|
|
</span>
|
|
</label>
|
|
<p class="my-4 text-danger">
|
|
<span v-show="isInvalid">
|
|
<IconWarnTriangle class="h-4 w-5 mx-2 mb-[2px] inline-block text-danger"/>Incorrect account or password.
|
|
</span>
|
|
</p>
|
|
<button type="submit" class="w-full btn btn-lg" :class="this.isDisabled ? 'btn-disable' : 'btn-c-primary'" :disabled="isDisabledButton">
|
|
Log in
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { storeToRefs } from 'pinia';
|
|
import loginStore from '@/stores/login.js';
|
|
import IconMember from '@/components/icons/IconMember.vue';
|
|
import IconLockKey from '@/components/icons/IconLockKey.vue';
|
|
import IconEyeOpen from '@/components/icons/IconEyeOpen.vue';
|
|
import IconEyeClose from '@/components/icons/IconEyeClose.vue';
|
|
import IconWarnTriangle from '@/components/icons/IconWarnTriangle.vue';
|
|
|
|
export default {
|
|
data(){
|
|
return {
|
|
isDisabled: true,
|
|
showPassword: false,
|
|
name: 'hellow world'
|
|
}
|
|
},
|
|
setup() {
|
|
// 調用函數,獲取 Store
|
|
const store = loginStore();
|
|
// 調用 store 裡的 state
|
|
const { auth, isInvalid } = storeToRefs(store);
|
|
// 調用 store 裡的 action
|
|
const { signIn } = store;
|
|
|
|
return {
|
|
auth,
|
|
isInvalid,
|
|
signIn,
|
|
}
|
|
},
|
|
components: {
|
|
IconMember,
|
|
IconLockKey,
|
|
IconEyeOpen,
|
|
IconEyeClose,
|
|
IconWarnTriangle
|
|
},
|
|
computed: {
|
|
/**
|
|
* if input no value , disabled.
|
|
*/
|
|
isDisabledButton() {
|
|
let inputAreSpaces = this.auth.username === '' || this.auth.password === '';
|
|
return this.isDisabled = inputAreSpaces ? true : false;
|
|
},
|
|
},
|
|
methods: {
|
|
/**
|
|
* when input onChange value , isInvalid === false.
|
|
*/
|
|
changeHandler(event) {
|
|
let inputValue = event.target.value;
|
|
if(inputValue !== '')this.isInvalid = false;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* Hide the eyes from a password input in MS Edge */
|
|
input::-ms-reveal,
|
|
input::-ms-clear {
|
|
display: none;
|
|
}
|
|
/* Hide the keys from the inputs in safair */
|
|
input::-webkit-contacts-auto-fill-button,
|
|
input::-webkit-credentials-auto-fill-button {
|
|
visibility: hidden;
|
|
display: none !important;
|
|
pointer-events: none;
|
|
height: 0;
|
|
width: 0;
|
|
margin: 0;
|
|
}
|
|
</style>
|