diff --git a/src/components/Article/Details.vue b/src/components/Article/Details.vue index a900e30..f78d11f 100644 --- a/src/components/Article/Details.vue +++ b/src/components/Article/Details.vue @@ -45,7 +45,17 @@ Открыть - Добавить + + Добавить + +
+ work_outline + Добавлено {{ getArticleAddedAt(article.id) | formattedDate }} +
@@ -54,6 +64,7 @@ diff --git a/src/store.js b/src/store.js index a1cf36a..d3af844 100644 --- a/src/store.js +++ b/src/store.js @@ -4,6 +4,7 @@ import Vuex from 'vuex'; import articleModule from '@/store/articles'; import generalModule from '@/store/general'; import userModule from '@/store/user'; +import userDataModule from '@/store/userData'; Vue.use(Vuex); @@ -12,5 +13,6 @@ export default new Vuex.Store({ articleModule, generalModule, userModule, + userDataModule, }, }); diff --git a/src/store/user.js b/src/store/user.js index f040096..86a9b31 100644 --- a/src/store/user.js +++ b/src/store/user.js @@ -54,9 +54,10 @@ export default { signOut() { firebase.auth().signOut(); }, - stateChanged({ commit }, payload) { + stateChanged({ commit, dispatch }, payload) { if (payload) { commit('setUser', payload.uid); + dispatch('loadUserData', payload.uid); } else { commit('unSetUser'); } @@ -64,5 +65,6 @@ export default { }, getters: { isUserAuthentificated: state => state.user.isAuthentificated, + userId: state => state.user.uid, }, }; diff --git a/src/store/userData.js b/src/store/userData.js new file mode 100644 index 0000000..f44b301 --- /dev/null +++ b/src/store/userData.js @@ -0,0 +1,111 @@ +import Vue from 'vue'; + +const defaultUserData = { + articles: {}, + words: {}, +}; + +export default { + state: { + userData: defaultUserData, + }, + actions: { + loadUserData({ commit }, userId) { + commit('setProcessing', true); + + let userDataRef = Vue.$db.collection('userData').doc(userId); + userDataRef.get() + .then((data) => { + let userData = data.exists ? data.data() : defaultUserData; + + if (!userData.articles) { + userData.articles = {}; + } + + commit('setUserData', userData); + }) + .catch(e => window.console.error(e)); + + commit('setProcessing', false); + }, + addUserArticle({ commit, getters }, articleId) { + commit('setProcessing', true); + + const userDataRef = Vue.$db.collection('userData').doc(getters.userId); + const article = { + addedAt: new Date(), + parts: {}, + }; + + userDataRef.set({ + articles: { + [articleId]: article, + } + }, { merge: true }) + .then(() => commit('addUserArticle', { articleId, article })) + .catch(e => window.console.error(e)); + + commit('setProcessing', false); + }, + updateUserArticlePartStats({ commit, getters }, { articleId, partId }) { + const userDataRef = Vue.$db.collection('userData').doc(getters.userId); + const timestamp = new Date(); + const articles = getters.userData.articles; + + if (!articles.hasOwnProperty(articleId) || !articles[articleId].parts.hasOwnProperty(partId)) { + userDataRef.update({ + [`articles.${articleId}.parts.${partId}.addedAt`]: timestamp, + }) + .then(() => commit('addUserArticlePart', { articleId, partId, timestamp })) + .catch(e => window.console.error(e)); + } + + userDataRef.update({ + [`articles.${articleId}.parts.${partId}.lastOpenedAt`]: timestamp, + }) + .then(() => commit('openUserArticlePart', { articleId, partId, timestamp })) + .catch(e => window.console.error(e)); + }, + finishUserArticlePart({ commit, getters }, { articleId, partId, rating }) { + commit('setProcessing', true); + + const userDataRef = Vue.$db.collection('userData').doc(getters.userId); + const timestamp = new Date(); + + userDataRef.update({ + [`articles.${articleId}.parts.${partId}.finishedAt`]: timestamp, + [`articles.${articleId}.parts.${partId}.rating`]: rating, + }) + .then(() => commit('finishUserArticlePart', { articleId, partId, timestamp, rating })) + .catch(e => window.console.error(e)); + + commit('setProcessing', false); + } + }, + mutations: { + setUserData(state, payload) { + Vue.set(state, 'userData', payload); + }, + addUserArticle(state, { articleId, article }) { + Vue.set(state.userData.articles, articleId, article); + }, + addUserArticlePart(state, { articleId, partId, timestamp }) { + if (state.userData.articles[articleId].parts[partId]) { + Vue.set(state.userData.articles[articleId].parts[partId], 'addedAt', timestamp); + return; + } + + Vue.set(state.userData.articles[articleId].parts, partId, { addedAt: timestamp }); + }, + openUserArticlePart(state, { articleId, partId, timestamp }) { + Vue.set(state.userData.articles[articleId].parts[partId], 'lastOpenedAt', timestamp); + }, + finishUserArticlePart(state, { articleId, partId, timestamp, rating }) { + Vue.set(state.userData.articles[articleId].parts[partId], 'finishedAt', timestamp); + Vue.set(state.userData.articles[articleId].parts[partId], 'rating', rating); + }, + }, + getters: { + userData: state => state.userData, + }, +}; diff --git a/src/views/ArticlePart.vue b/src/views/ArticlePart.vue index dd678fe..72963a0 100644 --- a/src/views/ArticlePart.vue +++ b/src/views/ArticlePart.vue @@ -1,12 +1,58 @@ @@ -31,13 +77,56 @@ BookPartContent, BookPartWords, }, + computed: { + currentUserArticle() { + const articles = this.$store.getters.userData.articles; + if (!articles) { + return null; + } + return articles[this.articleId]; + }, + currentUserArticlePart() { + const article = this.currentUserArticle; + if (!article) { + return null; + } + + const articleParts = article.parts; + if (!articleParts) { + return null; + } + + return articleParts[this.partId]; + }, + finishedAt() { + const articlePart = this.currentUserArticlePart; + return articlePart ? articlePart.finishedAt : null + }, + storedRating() { + const articlePart = this.currentUserArticlePart; + return articlePart ? articlePart.rating : 0; + } + }, + methods: { + finishWork() { + this.$store.dispatch('finishUserArticlePart', { + articleId: this.articleId, + partId: this.partId, + rating: this.rating, + }); + this.finishDialog = false; + } + }, data: () => ({ part: null, + finishDialog: false, + rating: 0, }), created() { + const { articleId, partId } = this; Vue.$db.collection('articleParts') - .where('articleId', '==', this.articleId) - .where('articlePartId', '==', this.partId) + .where('articleId', '==', articleId) + .where('articlePartId', '==', partId) .get() .then((querySnapshot) => { const snapDocs = querySnapshot.docs; @@ -45,7 +134,13 @@ this.part = Object.assign({}, snapDocs[0].data()); } }) - .catch(e => console.error(e)); + .then(() => { + this.$store.dispatch('updateUserArticlePartStats', { + articleId, + partId, + }); + }) + .catch(e => window.console.error(e)); } };