mirror of
https://github.com/Dannecron/ich-lerne-deutsch.git
synced 2025-12-25 21:02:35 +03:00
Add articles list component and store
This commit is contained in:
149
src/components/ArticlesList.vue
Normal file
149
src/components/ArticlesList.vue
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<v-container grid-list-md>
|
||||||
|
<v-layout row wrap>
|
||||||
|
<v-flex xs12 sm10 md8 offset-sm1 offset-md2>
|
||||||
|
<v-container fluid>
|
||||||
|
<v-layout row>
|
||||||
|
<v-flex md8>
|
||||||
|
<v-text-field label="Поиск" v-model="searchTerm"></v-text-field>
|
||||||
|
</v-flex>
|
||||||
|
<v-flex md4>
|
||||||
|
<v-select label="Уровень" :items="levels" v-model="levelTerm" multiple></v-select>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</v-flex>
|
||||||
|
<v-flex v-for="article in filteredArticles" xs12 sm10 md8 offset-sm1 offset-md2 :key="article.id">
|
||||||
|
<v-card color="info" class="white--text">
|
||||||
|
<v-container fluid>
|
||||||
|
<!-- desktop layout -->
|
||||||
|
<v-layout row class="hidden-sm-and-down">
|
||||||
|
<v-flex md3>
|
||||||
|
<v-img
|
||||||
|
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
|
||||||
|
height="100px"
|
||||||
|
>
|
||||||
|
</v-img>
|
||||||
|
<div class="text-xs-center">
|
||||||
|
<v-btn flat color="white">
|
||||||
|
<v-icon left>visibility</v-icon>
|
||||||
|
Youtube
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
</v-flex>
|
||||||
|
<v-flex md9>
|
||||||
|
<v-card-title>
|
||||||
|
<div>
|
||||||
|
<div class="headline">{{ article.title }}</div>
|
||||||
|
<div>{{ article.description }}</div>
|
||||||
|
<v-divider class="white"></v-divider>
|
||||||
|
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts }} частей</div>
|
||||||
|
</div>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
|
||||||
|
<div class="ml-1">
|
||||||
|
<span>{{ article.rating }}</span>
|
||||||
|
<span>({{ article.ratingsCount }})</span>
|
||||||
|
</div>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn class="primary" flat>Открыть</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
|
||||||
|
<!-- tablet and mobile layout -->
|
||||||
|
<div class="hidden-md-and-up">
|
||||||
|
<v-layout row>
|
||||||
|
<v-flex xs4>
|
||||||
|
<v-img
|
||||||
|
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
|
||||||
|
height="100px"
|
||||||
|
>
|
||||||
|
</v-img>
|
||||||
|
</v-flex>
|
||||||
|
<v-flex xs8>
|
||||||
|
<v-card-title>
|
||||||
|
<h4>{{ article.title }}</h4>
|
||||||
|
<v-btn flat color="white">
|
||||||
|
<v-icon left>visibility</v-icon>
|
||||||
|
Youtube
|
||||||
|
</v-btn>
|
||||||
|
</v-card-title>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
|
||||||
|
<v-layout row>
|
||||||
|
<v-flex xs12>
|
||||||
|
<div>{{ article.description }}</div>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
|
||||||
|
<v-layout row>
|
||||||
|
<v-flex xs12>
|
||||||
|
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts }} частей</div>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
|
||||||
|
<v-layout row>
|
||||||
|
<v-flex xs12>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
|
||||||
|
<div class="ml-1">
|
||||||
|
<span>{{ article.rating }}</span>
|
||||||
|
<span>({{ article.ratingsCount }})</span>
|
||||||
|
</div>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn class="primary" flat>Открыть</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</div>
|
||||||
|
</v-container>
|
||||||
|
</v-card>
|
||||||
|
</v-flex>
|
||||||
|
</v-layout>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
levels: ['A1', 'A2', 'B1', 'B2', 'C1', 'C2'],
|
||||||
|
|
||||||
|
searchTerm: null,
|
||||||
|
levelTerm: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
articles() {
|
||||||
|
return this.$store.getters.getArticles;
|
||||||
|
},
|
||||||
|
filteredArticles() {
|
||||||
|
const { articles, searchTerm, levelTerm } = this;
|
||||||
|
let filteredArticles = articles
|
||||||
|
|
||||||
|
if (searchTerm) {
|
||||||
|
filteredArticles = filteredArticles.filter(article =>
|
||||||
|
article.title.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0
|
||||||
|
|| article.description.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (levelTerm.length) {
|
||||||
|
filteredArticles = filteredArticles.filter(article => levelTerm.filter(val => article.level.indexOf(val) !== -1).length > 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredArticles;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getArticleLevel(levels) {
|
||||||
|
return levels.join('/');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
|
|
||||||
|
import articleModule from '@/store/articles';
|
||||||
import generalModule from '@/store/general';
|
import generalModule from '@/store/general';
|
||||||
import userModule from '@/store/user';
|
import userModule from '@/store/user';
|
||||||
|
|
||||||
@@ -8,7 +9,8 @@ Vue.use(Vuex);
|
|||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
modules: {
|
modules: {
|
||||||
userModule,
|
articleModule,
|
||||||
generalModule,
|
generalModule,
|
||||||
|
userModule,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
47
src/store/articles.js
Normal file
47
src/store/articles.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
export default {
|
||||||
|
state: {
|
||||||
|
articles: [
|
||||||
|
{
|
||||||
|
id: 'sgjngsnaada312',
|
||||||
|
title: 'Harry Potter und Stein der Weisen - 1',
|
||||||
|
description: 'Первая глава первой книги о Гарри Поттере',
|
||||||
|
imageId: 'asfgdfhmfgn131',
|
||||||
|
parts: 7,
|
||||||
|
level: ['B2', 'C1'],
|
||||||
|
rating: 4,
|
||||||
|
ratingsCount: 164,
|
||||||
|
youtubePlaylistId: 'asdadsadad',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sgjngsnaadasd2',
|
||||||
|
title: 'Harry Potter und Stein der Weisen - 2',
|
||||||
|
description: 'Вторая глава первой книги о Гарри Поттере',
|
||||||
|
imageId: 'asfgdf111hmfgn131',
|
||||||
|
parts: 7,
|
||||||
|
level: ['B1', 'B2'],
|
||||||
|
rating: 3.5,
|
||||||
|
ratingsCount: 55,
|
||||||
|
youtubePlaylistId: 'asdadsadad234234',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sgjngsdbfd12as',
|
||||||
|
title: 'Harry Potter und Stein der Weisen - 3',
|
||||||
|
description: 'Третья глава первой книги о Гарри Поттере',
|
||||||
|
imageId: 'asfgdfhmfgn13111',
|
||||||
|
parts: 7,
|
||||||
|
level: ['A2'],
|
||||||
|
rating: 2,
|
||||||
|
ratingsCount: 80,
|
||||||
|
youtubePlaylistId: 'asdadsada435346',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
setArticles(state, payload) {
|
||||||
|
state.articles = payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
getArticles: state => state.articles,
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -17,5 +17,5 @@ export default {
|
|||||||
getters: {
|
getters: {
|
||||||
getProcessing: state => state.processing,
|
getProcessing: state => state.processing,
|
||||||
getError: state => state.error,
|
getError: state => state.error,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h2>Articles</h2>
|
<articles-list>
|
||||||
|
|
||||||
|
</articles-list>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ArticlesList from '@/components/ArticlesList';
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
ArticlesList,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
isValid: false,
|
isValid: false,
|
||||||
emailRules: [
|
emailRules: [
|
||||||
(value) => !!value || 'Пожалуйста, введите email',
|
(value) => !!value || 'Пожалуйста, введите email',
|
||||||
(value) => /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
|
(value) => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
|
||||||
],
|
],
|
||||||
passwordRules: [
|
passwordRules: [
|
||||||
(value) => !!value || 'Пожалуйста введите пароль',
|
(value) => !!value || 'Пожалуйста введите пароль',
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
isValid: false,
|
isValid: false,
|
||||||
emailRules: [
|
emailRules: [
|
||||||
(value) => !!value || 'Пожалуйста, введите email',
|
(value) => !!value || 'Пожалуйста, введите email',
|
||||||
(value) => /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
|
(value) => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(value) || 'Неправильный email',
|
||||||
],
|
],
|
||||||
passwordRules: [
|
passwordRules: [
|
||||||
(value) => !!value || 'Пожалуйста введите пароль',
|
(value) => !!value || 'Пожалуйста введите пароль',
|
||||||
|
|||||||
Reference in New Issue
Block a user