mirror of
https://github.com/Dannecron/ich-lerne-deutsch.git
synced 2025-12-25 21:02:35 +03:00
Add profile page. Extend working with firebase.
Some refactoring of validation rules and page logic.
This commit is contained in:
166
src/components/User/ProfileData.vue
Normal file
166
src/components/User/ProfileData.vue
Normal 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
13
src/helpers/formRules.js
Normal 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 || 'Пожалуйста введите ваше имя',
|
||||||
|
];
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from '@/helpers/article';
|
export * from '@/helpers/article';
|
||||||
export * from '@/helpers/utils';
|
export * from '@/helpers/utils';
|
||||||
|
export * from '@/helpers/formRules';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
import firebase from 'firebase/app';
|
import firebase from 'firebase/app';
|
||||||
import 'firebase/auth';
|
import 'firebase/auth';
|
||||||
|
|
||||||
@@ -6,16 +7,25 @@ export default {
|
|||||||
user: {
|
user: {
|
||||||
isAuthentificated: false,
|
isAuthentificated: false,
|
||||||
uid: null,
|
uid: null,
|
||||||
|
email: null,
|
||||||
|
name: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
setUser(state, payload) {
|
setUser(state, { id, email}) {
|
||||||
state.user.isAuthentificated = true;
|
state.user.isAuthentificated = true;
|
||||||
state.user.uid = payload;
|
state.user.uid = id;
|
||||||
|
state.user.email = email;
|
||||||
},
|
},
|
||||||
unSetUser(state) {
|
unSetUser(state) {
|
||||||
state.user.isAuthentificated = false;
|
state.user.isAuthentificated = false;
|
||||||
state.user.uid = null;
|
state.user.uid = null;
|
||||||
|
},
|
||||||
|
setUserName(state, name) {
|
||||||
|
Vue.set(state.user, 'name', name);
|
||||||
|
},
|
||||||
|
setUserEmail(state, email) {
|
||||||
|
Vue.set(state.user, 'email', email);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@@ -23,10 +33,15 @@ export default {
|
|||||||
commit('setProcessing', true);
|
commit('setProcessing', true);
|
||||||
commit('clearError');
|
commit('clearError');
|
||||||
|
|
||||||
const { email, password } = payload;
|
const { email, password, name } = payload;
|
||||||
firebase.auth()
|
firebase.auth()
|
||||||
.createUserWithEmailAndPassword(email, password)
|
.createUserWithEmailAndPassword(email, password)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
firebase.auth().currentUser
|
||||||
|
.updateProfile({
|
||||||
|
displayName: name,
|
||||||
|
})
|
||||||
|
.then(() => commit('setUserName', name));
|
||||||
commit('setProcessing', false);
|
commit('setProcessing', false);
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
@@ -56,15 +71,60 @@ export default {
|
|||||||
},
|
},
|
||||||
stateChanged({ commit, dispatch }, payload) {
|
stateChanged({ commit, dispatch }, payload) {
|
||||||
if (payload) {
|
if (payload) {
|
||||||
commit('setUser', payload.uid);
|
commit('setUser', payload);
|
||||||
|
commit('setUserName', payload.displayName);
|
||||||
dispatch('loadUserData', payload.uid);
|
dispatch('loadUserData', payload.uid);
|
||||||
} else {
|
} else {
|
||||||
commit('unSetUser');
|
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: {
|
getters: {
|
||||||
isUserAuthentificated: state => state.user.isAuthentificated,
|
isUserAuthentificated: state => state.user.isAuthentificated,
|
||||||
userId: state => state.user.uid,
|
userId: state => state.user.uid,
|
||||||
|
userName: state => state.user.name,
|
||||||
|
userEmail: state => state.user.email,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,44 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<v-container grid-list-md>
|
||||||
<h2>Profile</h2>
|
<v-layout row wrap>
|
||||||
</div>
|
<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>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
import UserProfileData from '@/components/User/ProfileData';
|
||||||
|
|
||||||
}
|
export default {
|
||||||
|
beforeMount() {
|
||||||
|
this.$store.commit('clearError');
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
tabMode: 'myData',
|
||||||
|
}),
|
||||||
|
components: {
|
||||||
|
UserProfileData,
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<v-form id="sign-in-form" v-model="isValid" @submit.prevent="signIn">
|
<v-form id="sign-in-form" v-model="isValid" @submit.prevent="signIn">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
prepend-icon="person"
|
prepend-icon="email"
|
||||||
v-model="email"
|
v-model="email"
|
||||||
name="login"
|
name="login"
|
||||||
label="Email"
|
label="Email"
|
||||||
@@ -52,21 +52,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { emailRules, passwordRules } from '@/helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
beforeMount() {
|
||||||
return {
|
this.$store.commit('clearError');
|
||||||
email: null,
|
|
||||||
password: null,
|
|
||||||
isValid: false,
|
|
||||||
emailRules: [
|
|
||||||
(value) => !!value || 'Пожалуйста, введите email',
|
|
||||||
(value) => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
|
|
||||||
],
|
|
||||||
passwordRules: [
|
|
||||||
(value) => !!value || 'Пожалуйста введите пароль',
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
data: () => ({
|
||||||
|
email: null,
|
||||||
|
password: null,
|
||||||
|
isValid: false,
|
||||||
|
|
||||||
|
emailRules,
|
||||||
|
passwordRules,
|
||||||
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
error() {
|
error() {
|
||||||
return this.$store.getters.getError;
|
return this.$store.getters.getError;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<v-toolbar-title>Регистрация</v-toolbar-title>
|
<v-toolbar-title>Регистрация</v-toolbar-title>
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-alert
|
<v-alert
|
||||||
:value="error"
|
:value="error"
|
||||||
type="warning"
|
type="warning"
|
||||||
>
|
>
|
||||||
@@ -18,6 +18,17 @@
|
|||||||
<v-form id="sign-up-form" v-model="isValid" @submit.prevent="signUp">
|
<v-form id="sign-up-form" v-model="isValid" @submit.prevent="signUp">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
prepend-icon="person"
|
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"
|
v-model="email"
|
||||||
name="login"
|
name="login"
|
||||||
label="Email"
|
label="Email"
|
||||||
@@ -52,22 +63,22 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { emailRules, passwordRules, nameRules } from '@/helpers';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
beforeMount() {
|
||||||
return {
|
this.$store.commit('clearError');
|
||||||
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 символов',
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
data: () => ({
|
||||||
|
email: null,
|
||||||
|
password: null,
|
||||||
|
name: null,
|
||||||
|
isValid: false,
|
||||||
|
|
||||||
|
emailRules,
|
||||||
|
passwordRules,
|
||||||
|
nameRules,
|
||||||
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
error() {
|
error() {
|
||||||
return this.$store.getters.getError;
|
return this.$store.getters.getError;
|
||||||
@@ -88,8 +99,8 @@
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
signUp() {
|
signUp() {
|
||||||
const { email, password } = this;
|
const { email, password, name } = this;
|
||||||
this.$store.dispatch('signUp', { email, password });
|
this.$store.dispatch('signUp', { email, password, name });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user