mirror of
https://github.com/Dannecron/ich-lerne-deutsch.git
synced 2025-12-25 21:02:35 +03:00
Components refactoring: drop second layout for article.
Move components info subfolders. Combine detail components for list and for page. Improve helpers, add declOfNum function.
This commit is contained in:
85
src/components/Article/Details.vue
Normal file
85
src/components/Article/Details.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<v-card color="info" class="white--text">
|
||||
<v-container fluid>
|
||||
<v-layout row>
|
||||
<v-flex xs4 md3>
|
||||
<v-img
|
||||
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
|
||||
v-bind:height="expandDetails ? '150px' : '100px'"
|
||||
>
|
||||
</v-img>
|
||||
<youtube-button class="hidden-sm-and-down"></youtube-button>
|
||||
</v-flex>
|
||||
<v-flex xs8 md9>
|
||||
<v-card-title>
|
||||
<div :class="{
|
||||
'subheading': $vuetify.breakpoint.smAndDown,
|
||||
'headline': $vuetify.breakpoint.mdAndUp,
|
||||
}"
|
||||
>
|
||||
{{ article.title }}
|
||||
</div>
|
||||
<youtube-button class="hidden-md-and-up"></youtube-button>
|
||||
</v-card-title>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
|
||||
<v-layout row wrap>
|
||||
<v-flex xs12 md8 order-md2>
|
||||
<div>{{ article.description }}</div>
|
||||
</v-flex>
|
||||
<v-flex xs12 md4 order-md1>
|
||||
<div>Уровень: {{ getArticleLevel(article.level) }} {{ partsDescription }}</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 v-if="!expandDetails" class="primary" flat :to="{ name: 'article', params: { articleId: article.id } }">
|
||||
Открыть
|
||||
</v-btn>
|
||||
<v-btn v-if="expandDetails" class="primary" flat>Добавить</v-btn>
|
||||
</v-card-actions>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import YoutubeButton from '@/components/Article/YoutubeButton';
|
||||
import { getArticleLevel, declOfNum } from '@/helpers';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
article: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
expandDetails: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
partsDescription() {
|
||||
const partsCount = this.article.parts.length;
|
||||
const partsCountWord = declOfNum(partsCount, ['часть', 'части', 'частей']);
|
||||
return `${partsCount} ${partsCountWord}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getArticleLevel: getArticleLevel,
|
||||
},
|
||||
components: {
|
||||
YoutubeButton,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
11
src/components/Article/YoutubeButton.vue
Normal file
11
src/components/Article/YoutubeButton.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<v-btn flat color="white">
|
||||
<v-icon left>visibility</v-icon>
|
||||
Youtube
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
};
|
||||
</script>
|
||||
@@ -1,105 +0,0 @@
|
||||
<template>
|
||||
<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="150px"
|
||||
>
|
||||
</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.length }} частей</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.length }} частей</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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import getArticleLevel from '@/helpers/article';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
article: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getArticleLevel: getArticleLevel,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
|
||||
<script>
|
||||
import ListItem from '@/components/ArticlesListItem';
|
||||
import ListItem from '@/components/Article/Details';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
<template>
|
||||
<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.length }} частей</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 :to="{ name: 'article', params: { articleId: article.id } }">
|
||||
Открыть
|
||||
</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.length }} частей</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 :to="{ name: 'article', params: { articleId: article.id } }">
|
||||
Открыть
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</div>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import getArticleLevel from '@/helpers/article';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
article: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getArticleLevel: getArticleLevel,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,3 +1 @@
|
||||
const getArticleLevel = levels => levels.join('/');
|
||||
|
||||
export default getArticleLevel;
|
||||
export const getArticleLevel = levels => levels.join('/');
|
||||
|
||||
2
src/helpers/index.js
Normal file
2
src/helpers/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from '@/helpers/article';
|
||||
export * from '@/helpers/utils';
|
||||
4
src/helpers/utils.js
Normal file
4
src/helpers/utils.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const declOfNum = (number, titles) => {
|
||||
const cases = [2, 0, 1, 1, 1, 2];
|
||||
return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
<v-container grid-list-md v-if="article">
|
||||
<v-layout row wrap>
|
||||
<v-flex xs12 xs10 offset-sm1>
|
||||
<article-details :article="article"></article-details>
|
||||
<article-details :article="article" :expandDetails="true"></article-details>
|
||||
</v-flex>
|
||||
<v-flex xs12 xs10 offset-sm1 v-for="part in article.parts" :key="part.id">
|
||||
<article-parts-list-item :part="part" :articleId="article.id"></article-parts-list-item>
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
|
||||
<script>
|
||||
import ArticleDetails from '@/components/ArticleDetails';
|
||||
import ArticlePartsListItem from '@/components/ArticlePartsListItem';
|
||||
import ArticleDetails from '@/components/Article/Details';
|
||||
import ArticlePartsListItem from '@/components/Article/Part/ListItem';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
||||
Reference in New Issue
Block a user