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:
2019-02-23 13:52:57 +07:00
parent 99bfbe33eb
commit 4e00eaf17d
10 changed files with 107 additions and 221 deletions

View 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>

View 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>

View File

@@ -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>

View File

@@ -23,7 +23,7 @@
<script> <script>
import ListItem from '@/components/ArticlesListItem'; import ListItem from '@/components/Article/Details';
export default { export default {
data() { data() {

View File

@@ -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>

View File

@@ -1,3 +1 @@
const getArticleLevel = levels => levels.join('/'); export const getArticleLevel = levels => levels.join('/');
export default getArticleLevel;

2
src/helpers/index.js Normal file
View File

@@ -0,0 +1,2 @@
export * from '@/helpers/article';
export * from '@/helpers/utils';

4
src/helpers/utils.js Normal file
View 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]];
};

View File

@@ -2,7 +2,7 @@
<v-container grid-list-md v-if="article"> <v-container grid-list-md v-if="article">
<v-layout row wrap> <v-layout row wrap>
<v-flex xs12 xs10 offset-sm1> <v-flex xs12 xs10 offset-sm1>
<article-details :article="article"></article-details> <article-details :article="article" :expandDetails="true"></article-details>
</v-flex> </v-flex>
<v-flex xs12 xs10 offset-sm1 v-for="part in article.parts" :key="part.id"> <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> <article-parts-list-item :part="part" :articleId="article.id"></article-parts-list-item>
@@ -13,8 +13,8 @@
<script> <script>
import ArticleDetails from '@/components/ArticleDetails'; import ArticleDetails from '@/components/Article/Details';
import ArticlePartsListItem from '@/components/ArticlePartsListItem'; import ArticlePartsListItem from '@/components/Article/Part/ListItem';
export default { export default {
props: { props: {