mirror of
https://github.com/Dannecron/ich-lerne-deutsch.git
synced 2025-12-25 12:52:35 +03:00
Add articles list component and store
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<app-header></app-header>
|
||||
|
||||
<v-content>
|
||||
<router-view/>
|
||||
<router-view />
|
||||
</v-content>
|
||||
|
||||
<app-footer></app-footer>
|
||||
|
||||
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 Vuex from 'vuex';
|
||||
|
||||
import articleModule from '@/store/articles';
|
||||
import generalModule from '@/store/general';
|
||||
import userModule from '@/store/user';
|
||||
|
||||
@@ -8,7 +9,8 @@ Vue.use(Vuex);
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules: {
|
||||
userModule,
|
||||
articleModule,
|
||||
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: {
|
||||
getProcessing: state => state.processing,
|
||||
getError: state => state.error,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>Articles</h2>
|
||||
<articles-list>
|
||||
|
||||
</articles-list>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import ArticlesList from '@/components/ArticlesList';
|
||||
export default {
|
||||
components: {
|
||||
ArticlesList,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
isValid: false,
|
||||
emailRules: [
|
||||
(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: [
|
||||
(value) => !!value || 'Пожалуйста введите пароль',
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
isValid: false,
|
||||
emailRules: [
|
||||
(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: [
|
||||
(value) => !!value || 'Пожалуйста введите пароль',
|
||||
|
||||
Reference in New Issue
Block a user