Skip to content

Instantly share code, notes, and snippets.

@yoovanr
Last active August 27, 2021 05:10
Show Gist options
  • Save yoovanr/6d48788d9c3a52cfc1686dd839f6ba0f to your computer and use it in GitHub Desktop.
Save yoovanr/6d48788d9c3a52cfc1686dd839f6ba0f to your computer and use it in GitHub Desktop.
[Vue] components/SignInForm.vue
<template>
<form
class="SignInForm"
autocomplete="off"
@submit.prevent="login"
>
<!-- title start -->
<AppTitle bold="Sign in" />
<!-- title end -->
<!-- fieldset start -->
<div class="SignInForm__fieldset">
<input
class="SignInForm__field"
:class="{ 'field--invalid': $v.email.$error }"
type="email"
name="email"
placeholder="Email"
v-model="email"
@input="onChange"
@blur="$v.email.$touch()"
/>
<div
class="form__error"
v-if="!$v.email.required"
>
Email is required.
</div>
</div>
<!-- fieldset end -->
<!-- fieldset start -->
<div v-if="showPassword" class="SignInForm__fieldset">
<input
ref="password"
class="SignInForm__field"
:class="{ 'field--invalid': $v.password.$error }"
type="password"
name="password"
placeholder="Password"
v-model="password"
@blur="$v.password.$touch()"
/>
<div
class="form__error"
v-if="!$v.password.required"
>
Password is required.
</div>
<div
class="form__error"
v-if="!$v.password.minLength"
>
Password should contain at least 8 characters
</div>
<div
class="form__error"
v-if="!$v.password.containsUppercase"
>
Password shoud contain at least 1 uppercase letter.
</div>
<div
class="form__error"
v-if="!$v.password.containsLowercase"
>
Password shoud contain at least 1 lowercase letter.
</div>
<div
class="form__error"
v-if="!$v.password.containsNumber"
>
Password shoud contain at least 1 number.
</div>
</div>
<!-- fieldset end -->
<!-- buttons start -->
<AppButton
fill="solid"
size="large"
type="submit"
:disabled="$v.$invalid || signinLoading"
>
<span v-if="signinLoading">Login...</span>
<span v-else>Continue</span>
</AppButton>
<AppButton
fill="clear"
size="default"
type="button"
@click.native="$router.push({ name: 'forgot-password' })"
>
Forgot password
</AppButton>
<!-- buttons end -->
</form>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { required, email, minLength } from 'vuelidate/lib/validators'
export default {
data () {
return {
email: '',
password: '',
showPassword: false,
}
},
computed: {
...mapGetters('oauth', [
'signinLoading',
])
},
validations () {
const validations = {
email: {
email,
required,
},
}
if (!this.showPassword) {
return validations
} else {
return {
...validations,
password: {
required,
minLength: minLength(8),
containsUppercase (value) {
return /[A-Z]/.test(value)
},
containsLowercase (value) {
return /[a-z]/.test(value)
},
containsNumber (value) {
return /[0-9]/.test(value)
},
},
}
}
},
methods: {
...mapActions('oauth', {
signinAction: 'signin',
}),
login () {
if (!this.showPassword) {
this.showPassword = true
this.$nextTick(() => this.$refs.password.focus())
} else {
this.signinAction({ email: this.email, password: this.password })
}
},
onChange () {
if (this.email.length) {
this.password = ''
this.showPassword = false
}
},
},
}
</script>
<style lang="scss" scoped>
.SignInForm {
font-family: 'Montserrat', sans-serif;
position: relative;
text-align: center;
width: 100%;
max-width: 460px;
margin: 0 auto;
background: #FFF;
padding: 62px 70px;
border-radius: 4px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.10);
z-index: 1;
.AppTitle {
font-weight: 400;
font-family: 'Lato', sans-serif;
text-align: left;
text-transform: uppercase;
margin-bottom: 53px;
}
&__fieldset {
position: relative;
}
&__fieldset:not(:first-of-type) {
margin-top: 18px;
}
&__field {
display: block;
width: 100%;
border: none;
color: #242729;
font-weight: 500;
border-bottom: 2px solid #ADB4C6;
padding: 4px 8px;
transition: border-color .3s;
}
&__field::placeholder {
color: #000;
font-weight: 500;
opacity: 0.32;
letter-spacing: -0.16px;
}
button:first-of-type {
margin-top: 55px;
width: 100%;
}
button:last-of-type {
margin-top: 32px;
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment