Add profile page. Extend working with firebase.

Some refactoring of validation rules and page logic.
This commit is contained in:
2019-03-09 13:21:56 +07:00
parent 1c4e31875b
commit 69c94b8658
7 changed files with 324 additions and 42 deletions

View File

@@ -0,0 +1,166 @@
<template>
<div>
<v-card>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">
<v-icon>person</v-icon>
{{ userName }}
</h3>
<h3 class="headline mb-0">
<v-icon>email</v-icon>
{{ userEmail }}
</h3>
</div>
</v-card-title>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn flat color="orange" @click.stop="dialog = true">Изменить</v-btn>
</v-card-actions>
</v-card>
<v-dialog v-model="dialog" persistent max-width="550px">
<v-card>
<v-card-title class="headline">Изменить данные?</v-card-title>
<v-card-text>
<v-alert
type="warning"
class="mb-2"
:value="getError"
>
{{ getError }}
</v-alert>
<v-form id="edit-profile-form" v-model="isValid" @submit.prevent="changeUserData">
<v-text-field
prepend-icon="email"
v-model="email"
name="login"
label="Email"
type="email"
required
:rules="emailRules"
>
</v-text-field>
<v-text-field
prepend-icon="lock"
v-model="password"
name="password"
label="Пароль"
type="password"
required
:rules="passwordRules"
>
</v-text-field>
<h3>Какие данные нужно изменить?</h3>
<v-radio-group v-model="changeType" row>
<v-radio label="Имя" value="changeName"></v-radio>
<v-radio label="Email" value="changeEmail"></v-radio>
<v-radio label="Пароль" value="changePassword"></v-radio>
</v-radio-group>
<v-text-field
v-if="changeType == 'changeName'"
prepend-icon="person"
v-model="newName"
name="newName"
type="text"
label="Новое имя"
required
:rules="nameRules"
>
</v-text-field>
<v-text-field
v-if="changeType == 'changeEmail'"
prepend-icon="email"
v-model="newEmail"
name="newLogin"
type="email"
label="Новый email"
required
:rules="emailRules"
>
</v-text-field>
<v-text-field
v-if="changeType == 'changePassword'"
prepend-icon="lock"
v-model="newPassword"
name="newPassword"
type="password"
label="Новый пароль"
required
:rules="passwordRules"
>
</v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green darken-1" flat @click="dialog = false">Отмена</v-btn>
<v-btn
type="submit"
color="green darken-1"
form="edit-profile-form"
flat
:disabled="getProcessing || !isValid"
>
Изменить
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import { emailRules, passwordRules, nameRules } from "@/helpers";
export default {
data: () => ({
email: null,
password: null,
newEmail: null,
newPassword: null,
newName: null,
changeType: 'changeName',
dialog: false,
isValid: false,
emailRules,
passwordRules,
nameRules
}),
computed: {
...mapGetters(['userName', 'userEmail', 'getProcessing', 'getError']),
},
methods: {
changeUserData() {
const {
email,
password,
newEmail,
newPassword,
newName,
changeType,
} = this;
this.$store.dispatch('changeUserProfileData', {
email,
password,
newEmail,
newPassword,
newName,
changeType,
});
},
},
};
</script>

13
src/helpers/formRules.js Normal file
View File

@@ -0,0 +1,13 @@
export const emailRules = [
(value) => !!value || 'Пожалуйста, введите email',
(value) => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
];
export const passwordRules = [
(value) => !!value || 'Пожалуйста введите пароль',
(value) => (value && value.length >= 6) || 'Пароль слишком короткий - минимум 6 символов',
];
export const nameRules = [
(value) => !!value || 'Пожалуйста введите ваше имя',
];

View File

@@ -1,2 +1,3 @@
export * from '@/helpers/article';
export * from '@/helpers/utils';
export * from '@/helpers/utils';
export * from '@/helpers/formRules';

View File

@@ -1,3 +1,4 @@
import Vue from 'vue';
import firebase from 'firebase/app';
import 'firebase/auth';
@@ -6,16 +7,25 @@ export default {
user: {
isAuthentificated: false,
uid: null,
email: null,
name: null,
},
},
mutations: {
setUser(state, payload) {
setUser(state, { id, email}) {
state.user.isAuthentificated = true;
state.user.uid = payload;
state.user.uid = id;
state.user.email = email;
},
unSetUser(state) {
state.user.isAuthentificated = false;
state.user.uid = null;
},
setUserName(state, name) {
Vue.set(state.user, 'name', name);
},
setUserEmail(state, email) {
Vue.set(state.user, 'email', email);
}
},
actions: {
@@ -23,10 +33,15 @@ export default {
commit('setProcessing', true);
commit('clearError');
const { email, password } = payload;
const { email, password, name } = payload;
firebase.auth()
.createUserWithEmailAndPassword(email, password)
.then(() => {
firebase.auth().currentUser
.updateProfile({
displayName: name,
})
.then(() => commit('setUserName', name));
commit('setProcessing', false);
})
.catch(function(error) {
@@ -56,15 +71,60 @@ export default {
},
stateChanged({ commit, dispatch }, payload) {
if (payload) {
commit('setUser', payload.uid);
commit('setUser', payload);
commit('setUserName', payload.displayName);
dispatch('loadUserData', payload.uid);
} else {
commit('unSetUser');
}
}
},
changeUserProfileData({ commit }, payload) {
const { email, password } = payload;
const credential = firebase.auth.EmailAuthProvider.credential(email, password);
commit('setProcessing', true);
commit('clearError');
firebase.auth().currentUser.reauthenticateAndRetrieveDataWithCredential(credential)
.then(() => {
const { changeType } = payload;
const reauthenticatedUser = firebase.auth().currentUser;
if (changeType === 'changeName') {
const { newName } = payload;
return reauthenticatedUser.updateProfile({
displayName: newName,
})
.then(() => commit('setUserName', newName))
}
if (changeType === 'changeEmail') {
const { newEmail } = payload;
return reauthenticatedUser.updateEmail(newEmail)
.then(() => commit('setUserEmail', newEmail))
}
if (changeType === 'changePassword') {
const { newPassword } = payload;
return reauthenticatedUser.updatePassword(newPassword);
}
throw Error('invalid change type');
})
.then(() => commit('setProcessing', false))
.catch((e) => {
window.console.error(e);
const { message } = e;
commit('setProcessing', false);
commit('setError', message);
});
},
},
getters: {
isUserAuthentificated: state => state.user.isAuthentificated,
userId: state => state.user.uid,
userName: state => state.user.name,
userEmail: state => state.user.email,
},
};

View File

@@ -1,12 +1,44 @@
<template>
<div>
<h2>Profile</h2>
</div>
<v-container grid-list-md>
<v-layout row wrap>
<v-flex xs12 sm10 offset-sm1>
<v-tabs v-model="tabMode" color="accent" dark fixed-tabs slider-color="success">
<v-tab :key="'myData'" ripple>
Мои данные
</v-tab>
<v-tab :key="'myArticles'" ripple>
Мои статьи
</v-tab>
<v-tab :key="'myWords'" ripple>
Мои слова
</v-tab>
<v-tab-item :key="'myData'">
<user-profile-data></user-profile-data>
</v-tab-item>
<v-tab-item :key="'myArticles'">
</v-tab-item>
<v-tab-item :key="'myWords'">
</v-tab-item>
</v-tabs>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import UserProfileData from '@/components/User/ProfileData';
export default {
}
beforeMount() {
this.$store.commit('clearError');
},
data: () => ({
tabMode: 'myData',
}),
components: {
UserProfileData,
},
};
</script>

View File

@@ -17,7 +17,7 @@
<v-form id="sign-in-form" v-model="isValid" @submit.prevent="signIn">
<v-text-field
prepend-icon="person"
prepend-icon="email"
v-model="email"
name="login"
label="Email"
@@ -52,21 +52,20 @@
</template>
<script>
import { emailRules, passwordRules } from '@/helpers';
export default {
data() {
return {
email: null,
password: null,
isValid: false,
emailRules: [
(value) => !!value || 'Пожалуйста, введите email',
(value) => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
],
passwordRules: [
(value) => !!value || 'Пожалуйста введите пароль',
],
};
beforeMount() {
this.$store.commit('clearError');
},
data: () => ({
email: null,
password: null,
isValid: false,
emailRules,
passwordRules,
}),
computed: {
error() {
return this.$store.getters.getError;

View File

@@ -8,7 +8,7 @@
<v-toolbar-title>Регистрация</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-alert
<v-alert
:value="error"
type="warning"
>
@@ -18,6 +18,17 @@
<v-form id="sign-up-form" v-model="isValid" @submit.prevent="signUp">
<v-text-field
prepend-icon="person"
v-model="name"
name="name"
label="Имя"
type="text"
required
:rules="nameRules"
>
</v-text-field>
<v-text-field
prepend-icon="email"
v-model="email"
name="login"
label="Email"
@@ -52,22 +63,22 @@
</template>
<script>
import { emailRules, passwordRules, nameRules } from '@/helpers';
export default {
data() {
return {
email: null,
password: null,
isValid: false,
emailRules: [
(value) => !!value || 'Пожалуйста, введите email',
(value) => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
],
passwordRules: [
(value) => !!value || 'Пожалуйста введите пароль',
(value) => (value && value.length >= 6) || 'Пароль слишком короткий - минимум 6 символов',
],
};
beforeMount() {
this.$store.commit('clearError');
},
data: () => ({
email: null,
password: null,
name: null,
isValid: false,
emailRules,
passwordRules,
nameRules,
}),
computed: {
error() {
return this.$store.getters.getError;
@@ -88,8 +99,8 @@
},
methods: {
signUp() {
const { email, password } = this;
this.$store.dispatch('signUp', { email, password });
const { email, password, name } = this;
this.$store.dispatch('signUp', { email, password, name });
},
},
}