Commit 4e3da12c authored by iia10's avatar iia10

Initial commit

parent 40057d07
Pipeline #2920 failed with stages
in 0 seconds
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# sw
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This diff is collapsed.
{
"name": "sw",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-axios": "^2.1.5",
"vue-router": "^3.3.4",
"vuetify": "^2.3.3",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-plugin-router": "^4.4.6",
"@vue/cli-plugin-vuex": "~4.4.0",
"@vue/cli-service": "~4.4.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.19.0",
"sass-loader": "^8.0.0",
"vue-cli-plugin-vuetify": "~2.0.6",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<v-app dark class="bg">
<v-navigation-drawer app v-model="drawer" clipped fixed temporary dark>
<v-list dense>
<v-list-item v-for="item in btnList" :key="item.title" :to="item.route">
<v-list-item-content>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar app dark max-width="1200" class="mx-auto" color="transparent" elevation="0" absolute>
<router-link to="/" tag="span" style="cursor: pointer;">
<v-avatar class="" size="100" tile>
<v-img :src="logoSrc" contain>
</v-img>
</v-avatar>
</router-link>
<v-spacer></v-spacer>
<v-btn text v-for="(btn, i) in btnList" :key="i" :to="btn.route" class="hidden-sm-and-down ma-1" small right @click="goLoad()">
{{btn.title}}
</v-btn>
<v-app-bar-nav-icon @click.stop="drawer = !drawer" class="hidden-md-and-up">
</v-app-bar-nav-icon>
</v-app-bar>
<v-content>
<v-main>
<v-container fluid>
<v-row>
<router-view></router-view>
</v-row>
</v-container>
</v-main>
</v-content>
</v-app>
</template>
<script>
import Vue from 'vue'
Vue.prototype.$eventBus = new Vue();
export default {
name: 'App',
components: {},
created: function () {
this.$vuetify.theme.dark = true
},
data: () => ({
drawer: null,
logoSrc: require('@/assets/logo.png'),
}),
computed: {
btnList() {
return [{
'title': 'Главная',
'route': '/'
},
{
'title': 'Любимые герои',
'route': '/fav'
},
]
},
},
methods: {
goLoad(){
this.$eventBus.$emit('alert');
}
}
};
</script>
<style scoped>
.bg {
background-color: #0c0c0d !important;
background-image: linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, .6)), url("assets/stars.png") !important;
background-repeat: no-repeat !important;
background-attachment: fixed !important;
background-origin: initial;
background-clip: initial;
background-color: initial;
background-size: cover !important;
}
.appBar {
color: rgba(0, 0, 0, 0) !important;
background-color: rgba(0, 0, 0, 0) !important;
}
</style>
\ No newline at end of file
<template>
<v-col cols="12" xs="12" sm="4" md="4" lg="4" xl="4">
<v-card class="mx-auto swCard" max-width="500" outlined dark color="transparent">
<v-list-item three-line>
<v-list-item-content>
<div class="overline mb-4">{{name}}</div>
<v-list-item-subtitle>Место рождения: {{planet.name}}</v-list-item-subtitle>
<v-list-item-subtitle>Пол: {{gender | genderName}}</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-avatar tile size="80" color="grey">
<v-img :src="img()"></v-img>
</v-list-item-avatar>
</v-list-item>
</v-card>
</v-col>
</template>
<script>
export default {
name: 'FavCard',
components: {
},
props: ['id', 'name', 'homeworld', 'gender', 'loadState'],
data: () => ({
planet: [],
trueID: null,
}),
filters: {
genderName: function (value) {
if (!value) return ''
if (value == 'male') {
return value = 'Мужской'
}
if (value == 'female') {
return value = 'Женский'
} else {
return value = 'Нет сведений'
}
},
},
async created() {
try {
let str = this.id;
let last = str.toString().slice(-3).replace(/[\s.,/]/g, '');
str = parseInt(last)
this.trueID = str;
this.axios.get(this.homeworld).then(response => {
this.planet = response.data;
});
} catch (e) {
console.error(e);
}
},
async updated() {
try {
let str = this.id;
let last = str.toString().slice(-3).replace(/[\s.,/]/g, '');
str = parseInt(last)
this.trueID = str;
} catch (e) {
console.error(e);
}
},
computed: {
},
methods: {
img() {
return ('https://starwars-visualguide.com/assets/img/characters/' + this.trueID + '.jpg');
},
}
};
</script>
<style scoped>
.swCard {
border: 1px solid #d4a001 !important;
}
</style>
\ No newline at end of file
<template>
<v-col cols="12" xs="12" sm="4" md="4" lg="4" xl="4">
<v-card class="mx-auto swCard" max-width="500" outlined dark color="transparent">
<v-list-item three-line>
<v-list-item-content>
<div class="overline mb-4">{{name}}</div>
<v-list-item-subtitle>Место рождения: {{planet.name}}</v-list-item-subtitle>
<v-list-item-subtitle>Пол: {{gender | genderName}}</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-avatar tile size="80" color="grey">
<v-img :src="img()"></v-img>
</v-list-item-avatar>
</v-list-item>
<v-card-actions>
<v-tooltip right color="black">
<template v-slot:activator="{ on, attrs }">
<v-btn class="ma-2" text icon color="white" v-bind="attrs" dark v-on="on" @click="addToFav()">
<v-icon>mdi-heart</v-icon>
</v-btn>
</template>
<span>Добавить в любимых героев</span>
</v-tooltip>
</v-card-actions>
</v-card>
</v-col>
</template>
<script>
export default {
name: 'Home',
components: {
},
props: ['id', 'name', 'homeworld', 'gender', 'loadState'],
data: () => ({
planet: [],
trueID: null,
}),
filters: {
genderName: function (value) {
if (!value) return ''
if (value == 'male') {
return value = 'Мужской'
}
if (value == 'female') {
return value = 'Женский'
} else {
return value = 'Нет сведений'
}
},
},
async created() {
try {
let str = this.id;
let last = str.toString().slice(-3).replace(/[\s.,/]/g, '');
str = parseInt(last)
this.trueID = str;
this.axios.get(this.homeworld).then(response => {
this.planet = response.data;
});
} catch (e) {
console.error(e);
}
},
async updated() {
try {
let str = this.id;
let last = str.toString().slice(-3).replace(/[\s.,/]/g, '');
str = parseInt(last)
this.trueID = str;
} catch (e) {
console.error(e);
}
},
computed: {
},
methods: {
img() {
return ('https://starwars-visualguide.com/assets/img/characters/' + this.trueID + '.jpg');
},
addToFav(){
this.$store.commit('addToFav', {
id: this.id,
name: this.name,
gender: this.gender,
homeworld: this.homeworld,
url: this.url
})
}
}
};
</script>
<style scoped>
.swCard {
border: 1px solid #d4a001 !important;
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import vuetify from './plugins/vuetify';
import router from './router'
import axios from "axios";
import VueAxios from "vue-axios";
Vue.use(VueAxios, axios);
Vue.config.productionTip = false
new Vue({
store,
vuetify,
router,
render: h => h(App)
}).$mount('#app')
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
Vue.use(Vuetify);
export default new Vuetify({
});
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import FavHeroes from '../views/FavHeroes.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/fav',
name: 'FavHeroes',
component: FavHeroes
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let people = window.localStorage.getItem('people');
let fav = window.localStorage.getItem('fav');
export default new Vuex.Store({
state: {
people: people ? JSON.parse(people) : [],
fav: fav ? JSON.parse(fav) : [],
},
getters: {
peopleCount: (state) => {
return state.people.length;
}
},
mutations: {
localPeople(state){
window.localStorage.setItem('people', JSON.stringify(state.people));
},
localFav(state){
window.localStorage.setItem('fav', JSON.stringify(state.fav));
},
addToFav(state, payload){
state.fav.push({
id: payload.id,
name: payload.name,
gender: payload.gender,
homeworld: payload.homeworld,
url: payload.url
})
this.commit('localFav');
},
allPeople(state, payload){
state.people.push(payload)
this.commit('localPeople');
},
},
actions: {
},
modules: {}
})
\ No newline at end of file
<template>
<v-container fluid>
<v-row>
<FavCard v-for="(item, i) in this.$store.state.fav" :key="i" :name="item.name"
:homeworld="item.homeworld" :gender="item.gender" :id="item.id"></FavCard>
<div class="mx-auto" v-if="this.$store.state.fav.length == 0">
<p class="mx-auto" style="color:white">Тут пока пусто</p>
</div>
</v-row>
</v-container>
</template>
<script>
import FavCard from '@/components/FavCard.vue';
export default {
components: {
FavCard
},
}
</script>
\ No newline at end of file
<template>
<v-container>
<v-row>
<v-container>
<v-row v-if="filteredList">
<v-col class="d-flex" cols="12" sm="6">
<v-text-field label="Введите имя персонажа" outlined v-model="search" dark clearable dense
@click:clear="clearSearch"></v-text-field>
</v-col>
<v-col class="d-flex" cols="12" sm="6">
<v-select dense :items="genders" label="Пол" outlined v-model="gender" dark clearable>
</v-select>
</v-col>
</v-row>
</v-container>
<template v-if="filteredList">
<HeroesCard v-for="(item, i) in filteredList.slice(this.startP, this.endP)" :key="i" :name="item.name"
:homeworld="item.homeworld" :gender="item.gender" :id="item.url"></HeroesCard>
</template>
<div class="mx-auto" v-if="this.$store.state.people.length == 0">
<p class="mx-auto" style="color:white">Загружаю данные
<v-progress-circular :size="50" color="amber" indeterminate class="mx-auto ml-4">
</v-progress-circular>
</p>
</div>
<v-overlay :value="overlay">
<v-progress-circular indeterminate size="64"></v-progress-circular>
</v-overlay>
</v-row>
<div class="text-center" v-if="filteredList">
<v-btn dark :disabled="page == 0" class="ma-1" @click="prevPage">
<v-icon>
mdi-arrow-left-circle-outline
</v-icon>
</v-btn>
<v-btn dark :disabled="page >= ctn" class="ma-1" @click="nextPage">
<v-icon>
mdi-arrow-right-circle-outline
</v-icon>
</v-btn>
</div>
</v-container>
</template>
<script>
import HeroesCard from '@/components/HeroesCard.vue';
import Vue from 'vue'
Vue.prototype.$eventBus = new Vue();
export default {
name: 'Home',
components: {
HeroesCard
},
data: () => ({
rm: [],
res: [],
search: null,
genders: ['male', 'female', 'n/a'],
gender: null,
page: 0,
size: 9,
ctn: null,
startP: null,
endP: null,
overlay: false,
}),
created() {},
updated() {
this.pageCount();
this.displayedPersons();
},
filters: {},
watch: {
overlay(val) {
val && setTimeout(() => {
this.overlay = false
}, 1000)
},
},
mounted() {
this.getPages();