- Complete GGZ Ecademy Nuxt.js user portal - Learning products browser and management - Member management interface - User authentication and roles - Multi-language support (NL/EN) - Vuex store for state management - Component-based architecture
This commit is contained in:
285
components/Auth/Auth.vue
Normal file
285
components/Auth/Auth.vue
Normal file
@@ -0,0 +1,285 @@
|
||||
<template>
|
||||
<v-form ref="form" v-model="valid" lazy-validation>
|
||||
<v-card tile flat class="mb-6 d-flex flex-column fill-height" width="400">
|
||||
<v-card-title class="txt--text">
|
||||
<h2 class="mt-4" v-if="isLogin">{{ $t('auth.login.title') }}</h2>
|
||||
<h2 class="mt-4" v-if="isForgotten">
|
||||
{{ $t('auth.password_forgotten.title') }}
|
||||
</h2>
|
||||
<h2 class="mt-4" v-if="isReset">
|
||||
{{ $t('auth.password_reset.title') }}
|
||||
</h2>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text class="txt--text">
|
||||
<span v-if="isLogin">{{ $t('auth.login.text') }}</span>
|
||||
<span v-if="isForgotten">{{ $t('auth.password_forgotten.text') }}</span>
|
||||
<span v-if="isReset">{{ $t('auth.password_reset.text') }}</span>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text class="secondary--text" v-if="errors">
|
||||
<errors-list :errors="errors" />
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
name="email"
|
||||
prepend-inner-icon="icon-user"
|
||||
type="text"
|
||||
color="accent"
|
||||
outlined
|
||||
required
|
||||
lines
|
||||
:placeholder="$t('auth.email')"
|
||||
v-model="email"
|
||||
:rules="rules.email"
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
id="password"
|
||||
name="password"
|
||||
:placeholder="$t('auth.password')"
|
||||
prepend-inner-icon="icon-password"
|
||||
type="password"
|
||||
color="accent"
|
||||
outlined
|
||||
v-model="password"
|
||||
:rules="rules.password"
|
||||
v-if="isLogin || isReset"
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
id="password_confirmation"
|
||||
name="password_confirmation"
|
||||
placeholder="Wachtwoord bevestiging"
|
||||
prepend-inner-icon="icon-password"
|
||||
type="password"
|
||||
outlined
|
||||
v-model="passwordConfirmation"
|
||||
:rules="rules.password_confirmation"
|
||||
v-if="isReset"
|
||||
/>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn
|
||||
block
|
||||
color="accent"
|
||||
rounded
|
||||
large
|
||||
depressed
|
||||
v-if="isLogin"
|
||||
@click="validate"
|
||||
:disabled="!valid"
|
||||
>{{ $t('auth.login.cta') }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
block
|
||||
color="accent"
|
||||
rounded
|
||||
large
|
||||
depressed
|
||||
v-if="isForgotten"
|
||||
@click="validate"
|
||||
:disabled="!valid"
|
||||
>{{ $t('auth.password_forgotten.cta') }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
block
|
||||
color="accent"
|
||||
rounded
|
||||
large
|
||||
depressed
|
||||
v-if="isReset"
|
||||
@click="validate"
|
||||
:disabled="!valid || !isValidToken"
|
||||
>{{ $t('auth.password_reset.cta') }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
|
||||
<v-card-actions class="d-flex justify-space-between" v-if="isLogin">
|
||||
<!-- <v-checkbox
|
||||
on-icon="icon-selectionbox-checked"
|
||||
off-icon="icon-selectionbox"
|
||||
style="margin-left: 10px;"
|
||||
v-model="check"
|
||||
:label="$t('auth.keep_logged')"
|
||||
value="secondary"
|
||||
rounded
|
||||
></v-checkbox> -->
|
||||
<nuxt-link
|
||||
class="info--text"
|
||||
:to="localePath('/auth/password-forgotten')"
|
||||
>{{ $t('auth.password_forgotten.question') }}</nuxt-link
|
||||
>
|
||||
</v-card-actions>
|
||||
|
||||
<!-- <v-card-actions class="d-flex justify-space-between" v-if="!isLogin">
|
||||
<nuxt-link
|
||||
class="info--text"
|
||||
:to="localePath('/auth/login')"
|
||||
>{{ $t('auth.account.question') }}</nuxt-link>
|
||||
</v-card-actions> -->
|
||||
</v-card>
|
||||
</v-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import errorsList from '@/components/UI/ErrorsList/ErrorsList'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
errorsList,
|
||||
},
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'login',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
valid: true,
|
||||
check: true,
|
||||
email: '',
|
||||
errors: null,
|
||||
password: '',
|
||||
passwordConfirmation: '',
|
||||
rules: {
|
||||
email: [
|
||||
(v) => !!v || this.$t('auth.validation.email.required'),
|
||||
(v) => v.length <= 50 || this.$t('auth.validation.email.max_length'),
|
||||
(v) =>
|
||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||
v
|
||||
) || this.$t('auth.validation.email.invalid'),
|
||||
],
|
||||
password: [
|
||||
(v) => !!v || this.$t('auth.validation.password.required'),
|
||||
(v) =>
|
||||
(v && v.length >= 8) ||
|
||||
this.$t('auth.validation.password.min_length'),
|
||||
(v) =>
|
||||
(v && v.length <= 20) ||
|
||||
this.$t('auth.validation.password.max_min_length'),
|
||||
],
|
||||
password_confirmation: [
|
||||
(v) =>
|
||||
v === this.password ||
|
||||
this.$t('auth.validation.password.confirmation'),
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isLogin() {
|
||||
return this.mode === 'login'
|
||||
},
|
||||
isForgotten() {
|
||||
return this.mode === 'password-forgotten'
|
||||
},
|
||||
isReset() {
|
||||
return this.mode === 'password-reset'
|
||||
},
|
||||
isValidToken() {
|
||||
return this.$route.query.token.length === 64 && this.$route.query.token
|
||||
},
|
||||
hasErrors() {
|
||||
return this.backendErrors.length > 0
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
async validate() {
|
||||
if (!this.$refs.form.validate()) return
|
||||
if (this.isLogin) await this.login()
|
||||
if (this.isForgotten) await this.askToResetPassword()
|
||||
if (this.isReset) await this.resetPassword()
|
||||
},
|
||||
// reset() {
|
||||
// this.$refs.form.reset()
|
||||
// },
|
||||
// resetValidation() {
|
||||
// this.$refs.form.resetValidation()
|
||||
// },
|
||||
async login() {
|
||||
try {
|
||||
await this.$auth.loginWith('local', {
|
||||
data: {
|
||||
email: this.email,
|
||||
password: this.password,
|
||||
},
|
||||
})
|
||||
this.$router.push('/manager')
|
||||
} catch (error) {
|
||||
this.errors = error.response.data.errors
|
||||
this.$notifier.showMessage({
|
||||
content: error.response.data.message,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
},
|
||||
async askToResetPassword() {
|
||||
if (!this.isForgotten) return
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post('auth/password/email', {
|
||||
email: this.email,
|
||||
})
|
||||
this.$notifier.showMessage({
|
||||
content: this.$t('auth.notifications.request_accepted'),
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
} catch (error) {
|
||||
this.errors = error.response.data.errors
|
||||
this.$notifier.showMessage({
|
||||
content: error.response.data.error,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async resetPassword() {
|
||||
if (!this.isReset) return
|
||||
if (!this.isValidToken) return
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post('auth/password/reset', {
|
||||
email: this.email,
|
||||
password: this.password,
|
||||
password_confirmation: this.passwordConfirmation,
|
||||
token: this.$route.query.token,
|
||||
})
|
||||
this.$notifier.showMessage({
|
||||
content: this.$t('auth.notifications.password_changed'),
|
||||
color: 'success',
|
||||
icon: 'icon-checkmark',
|
||||
})
|
||||
|
||||
this.$router.push('/auth/login')
|
||||
|
||||
} catch (error) {
|
||||
this.errors = error.response.data.errors
|
||||
this.$notifier.showMessage({
|
||||
content: error.response.data.error,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.info--text {
|
||||
text-decoration: none;
|
||||
}
|
||||
.v-card__title,
|
||||
.v-card__text {
|
||||
word-break: normal;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user