запустил lint:fix

This commit is contained in:
Norbaev 2024-06-25 17:22:17 +05:00
parent 6ea385f1eb
commit caa0326d9a
49 changed files with 3661 additions and 3331 deletions

View File

@ -7,6 +7,7 @@
"private": true,
"scripts": {
"lint": "eslint --ext .js,.vue ./",
"lint:fix": "eslint --ext .js,.vue --fix ./",
"test": "echo \"No test specified\" && exit 0",
"serve": "npx cross-env NODE_ENV=development quasar dev",
"serve:ssr": "quasar dev -m ssr",

View File

@ -1,72 +1,79 @@
<template>
<div class="app">
<AppHeader/>
<div class="app__block">
<Page404 v-if="showErrorPage404"/>
<Page500 v-if="showErrorPage500"/>
<routerView v-else/>
</div>
<Player/>
<AppFooter/>
<div class="app">
<AppHeader />
<div class="app__block">
<Page404 v-if="showErrorPage404" />
<Page500 v-if="showErrorPage500" />
<routerView v-else />
</div>
<Authentication/>
<ChangingUser/>
<Player />
<AppFooter />
</div>
<Authentication />
<ChangingUser />
</template>
<script>
import Page404 from '@/views/Page404.vue';
import Page500 from '@/views/Page500.vue';
import AppHeader from "@/components/app-header.vue";
import AppFooter from "@/components/app-footer.vue";
import Authentication from "@/components/modal/authentication.vue";
import Player from "@/components/player.vue";
import ChangingUser from "@/components/modal/сhanging-user.vue";
import AppHeader from '@/components/app-header.vue';
import AppFooter from '@/components/app-footer.vue';
import Authentication from '@/components/modal/authentication.vue';
import Player from '@/components/player.vue';
import ChangingUser from '@/components/modal/сhanging-user.vue';
export default {
async preFetch({store, currentRoute, previousRoute, redirect, ssrContext, urlPath, publicPath}) {
async preFetch({
store,
currentRoute,
previousRoute,
redirect,
ssrContext,
urlPath,
publicPath,
}) {},
components: {
ChangingUser,
Player,
Authentication,
AppFooter,
AppHeader,
Page404,
Page500,
},
data() {
return {
showSidebarBlock: false,
};
},
computed: {
user() {
return this.$store.state.user;
},
components: {
ChangingUser,
Player,
Authentication,
AppFooter,
AppHeader,
Page404,
Page500,
showErrorPage404() {
return false;
// return this.$store.state.showErrorPage?.response?.status === 404;
},
data() {
return {
showSidebarBlock: false,
};
showErrorPage500() {
return false;
// return this.$store.state.showErrorPage?.response?.status === 500;
},
computed: {
user() {
return this.$store.state.user;
},
showErrorPage404() {
return false
// return this.$store.state.showErrorPage?.response?.status === 404;
},
showErrorPage500() {
return false
// return this.$store.state.showErrorPage?.response?.status === 500;
},
currentPlay() {
return this.$store.state.currentPlay
},
currentPlay() {
return this.$store.state.currentPlay;
},
watch: {},
created() {
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, isPlay: false});
},
mounted() {
},
methods: {
}
},
watch: {},
created() {
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
isPlay: false,
});
},
mounted() {},
methods: {},
};
</script>
<style>
@import "swiper/swiper.css";
@import "assets/css/index.scss";
@import 'swiper/swiper.css';
@import 'assets/css/index.scss';
</style>

View File

@ -1,5 +1,5 @@
import { boot } from 'quasar/wrappers'
import axios from 'axios'
import { boot } from 'quasar/wrappers';
import axios from 'axios';
// Be careful when using SSR for cross-request state pollution
// due to creating a Singleton instance here;
@ -7,18 +7,18 @@ import axios from 'axios'
// good idea to move this instance creation inside of the
// "export default () => {}" function below (which runs individually
// for each client)
const api = axios.create({ baseURL: 'https://api.example.com' })
const api = axios.create({ baseURL: 'https://api.example.com' });
export default boot(({ app }) => {
// for use inside Vue files (Options API) through this.$axios and this.$api
app.config.globalProperties.$axios = axios
app.config.globalProperties.$axios = axios;
// ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
// so you won't necessarily have to import axios in each vue file
app.config.globalProperties.$api = api
app.config.globalProperties.$api = api;
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
// so you can easily perform requests against your app's API
})
});
export { api }
export { api };

View File

@ -1,6 +1,5 @@
import { boot } from 'quasar/wrappers'
import { boot } from 'quasar/wrappers';
// "async" is optional;
// more info on params: https://v2.quasar.dev/quasar-cli/boot-files
export default boot(async ({ app, router }) => {
})
export default boot(async ({ app, router }) => {});

View File

@ -1,83 +1,81 @@
import { boot } from 'quasar/wrappers'
import helpers from '@/utils/helpers'
import VueScrollmagic from 'scrollmagic'
import 'vue-final-modal/style.css'
import { VueFinalModal } from 'vue-final-modal'
import {plugin, defaultConfig, createInput} from '@formkit/vue'
import { ru } from '@formkit/i18n'
import { boot } from 'quasar/wrappers';
import helpers from '@/utils/helpers';
import VueScrollmagic from 'scrollmagic';
import 'vue-final-modal/style.css';
import { VueFinalModal } from 'vue-final-modal';
import { plugin, defaultConfig, createInput } from '@formkit/vue';
import { ru } from '@formkit/i18n';
import maskaInput from '@/components/inputs/maska-input';
import toggle from '@/components/inputs/toggle';
import { vMaska } from 'maska'
import { vMaska } from 'maska';
export default boot(async ({ app, router }) => {
app.config.globalProperties.$router = router
app.use(helpers);
app.scrollMagic = VueScrollmagic;
app.component('VueFinalModal', VueFinalModal);
app.config.globalProperties.$scrollMagic = VueScrollmagic
app.directive('Maska', vMaska);
const confFormKit = {
locales: { ru },
locale: 'ru',
config: {
validationVisibility: 'submit',
classes: {
outer: '$reset field',
wrapper: '$reset field__inner',
label: '$reset field__label',
help: '$reset field__help',
inner: '$reset field__input',
input: '$reset input',
messages: '$reset field__comment',
message: '$reset field__comment-item',
legend: '$reset field__legend',
fieldset: '$reset field__fieldset',
options: '$reset field__options',
option: '$reset field__option',
decorator: '$reset field__decorator'
},
},
messages: {
ru: {
// validation: {
// date_after({ name, args }) {
// if (args[1] === true) return `${name} должна быть в будущем.`;
// if (Array.isArray(args) && args.length) {
// return `${name} должна быть позже ${new Intl.DateTimeFormat(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }).format(typeof args[0] === 'string' ? new Date(Date.parse(args[0])) : args[0]) }`;
// }
// return `${name} должна быть в будущем.`;
// },
// date_before({ name, args }) {
// if (Array.isArray(args) && args.length) {
// return `${name} должна быть раньше ${new Intl.DateTimeFormat(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }).format(typeof args[0] === 'string' ? new Date(Date.parse(args[0])) : args[0]) }`;
// }
// return `${name} должна быть в прошлом.`;
// },
// },
}
},
inputs: {
// datepicker: createInput(datePickerInput, {
// props: ['mode'],
// }),
// select: createInput(multiselectInput, {
// props: ['options', 'placeholder', 'mode', 'searchable'],
// }),
// multiselect: createInput(multiselectInput, {
// props: ['options', 'placeholder', 'mode', 'searchable'],
// }),
maska: createInput(maskaInput, {
props: ['maska', 'placeholder', 'disabled', 'readonly'],
}),
toggle: createInput(toggle, {
props: ['placeholder', 'disabled', 'readonly'],
emits: ['toggle']
}),
},
};
app.use(plugin, defaultConfig(confFormKit));
})
app.config.globalProperties.$router = router;
app.use(helpers);
app.scrollMagic = VueScrollmagic;
app.component('VueFinalModal', VueFinalModal);
app.config.globalProperties.$scrollMagic = VueScrollmagic;
app.directive('Maska', vMaska);
const confFormKit = {
locales: { ru },
locale: 'ru',
config: {
validationVisibility: 'submit',
classes: {
outer: '$reset field',
wrapper: '$reset field__inner',
label: '$reset field__label',
help: '$reset field__help',
inner: '$reset field__input',
input: '$reset input',
messages: '$reset field__comment',
message: '$reset field__comment-item',
legend: '$reset field__legend',
fieldset: '$reset field__fieldset',
options: '$reset field__options',
option: '$reset field__option',
decorator: '$reset field__decorator',
},
},
messages: {
ru: {
// validation: {
// date_after({ name, args }) {
// if (args[1] === true) return `${name} должна быть в будущем.`;
// if (Array.isArray(args) && args.length) {
// return `${name} должна быть позже ${new Intl.DateTimeFormat(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }).format(typeof args[0] === 'string' ? new Date(Date.parse(args[0])) : args[0]) }`;
// }
// return `${name} должна быть в будущем.`;
// },
// date_before({ name, args }) {
// if (Array.isArray(args) && args.length) {
// return `${name} должна быть раньше ${new Intl.DateTimeFormat(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }).format(typeof args[0] === 'string' ? new Date(Date.parse(args[0])) : args[0]) }`;
// }
// return `${name} должна быть в прошлом.`;
// },
// },
},
},
inputs: {
// datepicker: createInput(datePickerInput, {
// props: ['mode'],
// }),
// select: createInput(multiselectInput, {
// props: ['options', 'placeholder', 'mode', 'searchable'],
// }),
// multiselect: createInput(multiselectInput, {
// props: ['options', 'placeholder', 'mode', 'searchable'],
// }),
maska: createInput(maskaInput, {
props: ['maska', 'placeholder', 'disabled', 'readonly'],
}),
toggle: createInput(toggle, {
props: ['placeholder', 'disabled', 'readonly'],
emits: ['toggle'],
}),
},
};
app.use(plugin, defaultConfig(confFormKit));
});

View File

@ -1,8 +1,15 @@
import { boot } from 'quasar/wrappers'
import { boot } from 'quasar/wrappers';
// "async" is optional;
// more info on params: https://v2.quasar.dev/quasar-cli/boot-files
export default boot(async ({ store }) => {
// For Vuex
if (window.__INITIAL_STATE__) store.replaceState(Object.assign(store.state, { metaScheme: window.__INITIAL_STATE__.metaScheme, data: window.__INITIAL_STATE__.data, meta: window.__INITIAL_STATE__.meta }));
})
if (window.__INITIAL_STATE__)
store.replaceState(
Object.assign(store.state, {
metaScheme: window.__INITIAL_STATE__.metaScheme,
data: window.__INITIAL_STATE__.data,
meta: window.__INITIAL_STATE__.meta,
}),
);
});

View File

@ -1,126 +1,118 @@
<template>
<div class="app__content footer">
<div class="footer__top">
<h2 class="h2 m--white">Напишите нам</h2>
<div class="footer__question">
<div class="text">Остались вопросы? Мы с радостью вам ответим!</div>
<button class="button m--white m--arrow footer__question-button">Написать</button>
</div>
</div>
<div class="footer__bottom">
<ul class="footer__menu">
<li
v-for="(item, key) in menu"
:key="key"
:class="['footer__menu-item', item.class]"
>
<router-link
:to="{ name: item.name, params: item.params }"
class="footer__menu-link"
>
{{ item.title }}
</router-link>
</li>
</ul>
<div class="footer__connection">
<ul class="footer__social">
<li
v-for="(item, key) in socialMenu"
:key="key"
:class="['footer__menu-item', item.class]"
>
<router-link
:to="item.link"
class="footer__menu-link"
>
{{ item.title }}
</router-link>
</li>
</ul>
<ul class="footer__connection">
<li class="footer__menu-item"
>
<router-link
to="#"
class="m--underline"
>
it@radio.org
</router-link>
</li>
<li class="footer__menu-item">
<router-link
to="#"
class="m--underline"
>
+7 (900) 000-01-12
</router-link>
</li>
</ul>
</div>
</div>
<div class="app__content footer">
<div class="footer__top">
<h2 class="h2 m--white">Напишите нам</h2>
<div class="footer__question">
<div class="text">Остались вопросы? Мы с радостью вам ответим!</div>
<button class="button m--white m--arrow footer__question-button">
Написать
</button>
</div>
</div>
<div class="footer__bottom">
<ul class="footer__menu">
<li
v-for="(item, key) in menu"
:key="key"
:class="['footer__menu-item', item.class]"
>
<router-link
:to="{ name: item.name, params: item.params }"
class="footer__menu-link"
>
{{ item.title }}
</router-link>
</li>
</ul>
<div class="footer__connection">
<ul class="footer__social">
<li
v-for="(item, key) in socialMenu"
:key="key"
:class="['footer__menu-item', item.class]"
>
<router-link :to="item.link" class="footer__menu-link">
{{ item.title }}
</router-link>
</li>
</ul>
<ul class="footer__connection">
<li class="footer__menu-item">
<router-link to="#" class="m--underline">
it@radio.org
</router-link>
</li>
<li class="footer__menu-item">
<router-link to="#" class="m--underline">
+7 (900) 000-01-12
</router-link>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'AppFooter',
data() {
return {
menu: [
{
name: 'home',
role: 'all',
title: 'О нас'
},
{
name: 'support',
role: 'all',
title: 'Поддержка'
},
{
name: 'rubric',
role: 'all',
title: 'Программы'
},
{
name: 'playlists',
role: 'all',
title: 'Контакты'
},
{
name: 'contacts',
role: 'all',
title: 'Блог'
},
{
name: 'contacts',
role: 'all',
title: 'Карьера'
},
],
socialMenu: [
{
link: '#',
role: 'all',
title: 'Telegram'
},
{
link: '#',
role: 'all',
title: 'VKontakte'
},
{
link: '#',
role: 'all',
title: 'Instagram'
},
{
link: '#',
role: 'all',
title: 'YouTube'
},
]
}
}
}
name: 'AppFooter',
data() {
return {
menu: [
{
name: 'home',
role: 'all',
title: 'О нас',
},
{
name: 'support',
role: 'all',
title: 'Поддержка',
},
{
name: 'rubric',
role: 'all',
title: 'Программы',
},
{
name: 'playlists',
role: 'all',
title: 'Контакты',
},
{
name: 'contacts',
role: 'all',
title: 'Блог',
},
{
name: 'contacts',
role: 'all',
title: 'Карьера',
},
],
socialMenu: [
{
link: '#',
role: 'all',
title: 'Telegram',
},
{
link: '#',
role: 'all',
title: 'VKontakte',
},
{
link: '#',
role: 'all',
title: 'Instagram',
},
{
link: '#',
role: 'all',
title: 'YouTube',
},
],
};
},
};
</script>

View File

@ -1,147 +1,159 @@
<template>
<div class="header">
<div class="app__content header__wrapper">
<div class="header__logo" @click="next('home')">
<img src="@/assets/img/icon/logo.svg" alt="logo"/>
</div>
<ul class="header__menu" :class="showMenu&&'m--active'">
<li class="header__burger m--active m--menu" @click="handlerShowMenu">
<span></span>
</li>
<li class="header__logo m--menu" @click="next('home')">
<img src="@/assets/img/icon/logo.svg" alt="logo"/>
</li>
<li
v-for="(item, key) in menu"
:key="key"
:class="['header__menu-item', item.class]"
>
<router-link
v-if="!item.action"
:to="{ name: item.name, params: item.params }"
class="header__menu-link"
>
{{ item.title }}
</router-link>
<button v-else-if="item.title" class="button" :class="[item.icon, showAuthentication&&'m--active']" @click="handlerClick(item.action)">{{ item.title }}</button>
<button v-else class="header__menu-icon" :class="[item.icon]" @click="handlerClick(item.action)"></button>
</li>
</ul>
<div class="header__burger" @click="handlerShowMenu">
<span></span>
</div>
<div v-if="showMenu" class="app__overlay" @click="handlerShowMenu"></div>
</div>
</div>
<div class="header">
<div class="app__content header__wrapper">
<div class="header__logo" @click="next('home')">
<img src="@/assets/img/icon/logo.svg" alt="logo" />
</div>
<ul class="header__menu" :class="showMenu && 'm--active'">
<li class="header__burger m--active m--menu" @click="handlerShowMenu">
<span></span>
</li>
<li class="header__logo m--menu" @click="next('home')">
<img src="@/assets/img/icon/logo.svg" alt="logo" />
</li>
<li
v-for="(item, key) in menu"
:key="key"
:class="['header__menu-item', item.class]"
>
<router-link
v-if="!item.action"
:to="{ name: item.name, params: item.params }"
class="header__menu-link"
>
{{ item.title }}
</router-link>
<button
v-else-if="item.title"
class="button"
:class="[item.icon, showAuthentication && 'm--active']"
@click="handlerClick(item.action)"
>
{{ item.title }}
</button>
<button
v-else
class="header__menu-icon"
:class="[item.icon]"
@click="handlerClick(item.action)"
></button>
</li>
</ul>
<div class="header__burger" @click="handlerShowMenu">
<span></span>
</div>
<div v-if="showMenu" class="app__overlay" @click="handlerShowMenu"></div>
</div>
</div>
</template>
<script>
export default {
name: 'app-header',
props:{},
data(){
return{
menuList:[
{
name: 'about',
role: 'all',
title: 'О нас'
},
{
name: 'rubric',
role: 'all',
title: 'Рубрики'
},
{
name: 'playlists',
role: 'all',
title: 'Плейлист'
},
{
name: 'podcasts',
role: 'all',
title: 'Подкасты'
},
{
name: 'support',
role: 'all',
title: 'Поддержка'
},
{
name: 'contacts',
role: 'all',
title: 'Контакты'
},
{
name: 'home',
role: 'login',
action: 'login',
icon: 'm--arrow',
title: 'Войти',
class: 'header__btn'
},
{
name: 'profile',
role: 'auth',
icon: 'm--profile',
action: 'profile',
class:'m--tools'
},
{
name: 'exit',
role: 'auth',
icon: 'm--exit',
action: 'exit',
class:'m--tools'
},
],
showMenu: true,
}
},
watch:{
'$route':{
handler(to){
if (this.showMenu){
this.showMenu = false;
}
}
}
},
computed:{
user() {
return this.$store.state.user;
},
menu(){
return this.menuList.filter(item=>{
if (item.role==='all') return true
if (item.role==='auth' && this.user?.id) return !!this.user?.id
if (item.role==='login' && !this.user?.id) return !this.user?.id
return false
})
},
showAuthentication(){
return this.$store.state.showAuthModal
},
},
methods:{
handlerClick(methods){
if (methods==='login'){
this.$store.dispatch('setModal', {auth: true});
}
if (methods==='profile'){
this.next('profile')
}
if(methods==='exit'){
this.$store.dispatch('deathUser');
this.next('home')
}
name: 'app-header',
props: {},
data() {
return {
menuList: [
{
name: 'about',
role: 'all',
title: 'О нас',
},
next(name){
this.$router.push({name})
{
name: 'rubric',
role: 'all',
title: 'Рубрики',
},
handlerShowMenu(){
this.showMenu = !this.showMenu;
}
}
}
{
name: 'playlists',
role: 'all',
title: 'Плейлист',
},
{
name: 'podcasts',
role: 'all',
title: 'Подкасты',
},
{
name: 'support',
role: 'all',
title: 'Поддержка',
},
{
name: 'contacts',
role: 'all',
title: 'Контакты',
},
{
name: 'home',
role: 'login',
action: 'login',
icon: 'm--arrow',
title: 'Войти',
class: 'header__btn',
},
{
name: 'profile',
role: 'auth',
icon: 'm--profile',
action: 'profile',
class: 'm--tools',
},
{
name: 'exit',
role: 'auth',
icon: 'm--exit',
action: 'exit',
class: 'm--tools',
},
],
showMenu: true,
};
},
watch: {
$route: {
handler(to) {
if (this.showMenu) {
this.showMenu = false;
}
},
},
},
computed: {
user() {
return this.$store.state.user;
},
menu() {
return this.menuList.filter((item) => {
if (item.role === 'all') return true;
if (item.role === 'auth' && this.user?.id) return !!this.user?.id;
if (item.role === 'login' && !this.user?.id) return !this.user?.id;
return false;
});
},
showAuthentication() {
return this.$store.state.showAuthModal;
},
},
methods: {
handlerClick(methods) {
if (methods === 'login') {
this.$store.dispatch('setModal', { auth: true });
}
if (methods === 'profile') {
this.next('profile');
}
if (methods === 'exit') {
this.$store.dispatch('deathUser');
this.next('home');
}
},
next(name) {
this.$router.push({ name });
},
handlerShowMenu() {
this.showMenu = !this.showMenu;
},
},
};
</script>

View File

@ -1,25 +1,25 @@
<template>
<input
v-maska
class="input"
:data-maska="props.context.maska?.mask"
:data-maska-tokens="props.context.maska?.tokens"
:value="props.context._value"
:disabled="disabled"
:readonly="readonly"
type="text"
:placeholder="placeholder"
@maska="handleMaska"
>
<input
v-maska
class="input"
:data-maska="props.context.maska?.mask"
:data-maska-tokens="props.context.maska?.tokens"
:value="props.context._value"
:disabled="disabled"
:readonly="readonly"
type="text"
:placeholder="placeholder"
@maska="handleMaska"
/>
</template>
<script setup>
import { defineProps, ref, onUpdated, computed } from 'vue';
const props = defineProps({
context: {
type: Object,
default: () => {}
}
context: {
type: Object,
default: () => {},
},
});
const maska = props.context.maska;
@ -29,7 +29,7 @@ const readonly = props.context.readonly || false;
//const required = props.context.validatin === 'required' && 'required';
function handleMaska($event) {
//console.log('handleInput', $event.target.disabled)
props.context.node.input($event.target.value)
//console.log('handleInput', $event.target.disabled)
props.context.node.input($event.target.value);
}
</script>

View File

@ -1,42 +1,39 @@
<template>
<input
class="input field__checkbox-input"
:id="context.id"
:checked="context._value"
:disabled="disabled"
:readonly="readonly"
type="checkbox"
@change="change"
>
<label class="field__checkbox-label" :for="context.id">
{{ context.label }}
</label>
<input
class="input field__checkbox-input"
:id="context.id"
:checked="context._value"
:disabled="disabled"
:readonly="readonly"
type="checkbox"
@change="change"
/>
<label class="field__checkbox-label" :for="context.id">
{{ context.label }}
</label>
</template>
<script>
import {defineProps, ref, onUpdated, computed} from 'vue';
import { defineProps, ref, onUpdated, computed } from 'vue';
export default {
props: {
context: {
type: Object,
default: () => {
}
}
props: {
context: {
type: Object,
default: () => {},
},
data() {
return {
placeholder: this.context.placeholder || '',
disabled: this.context.disabled || false,
readonly: this.context.readonly || false,
}
},
data() {
return {
placeholder: this.context.placeholder || '',
disabled: this.context.disabled || false,
readonly: this.context.readonly || false,
};
},
methods: {
change() {
this.context.node.input(!this.context._value);
},
methods: {
change() {
this.context.node.input(!this.context._value);
}
}
}
},
};
</script>

View File

@ -1,202 +1,203 @@
<template>
<vue-final-modal
v-model="show"
class="modal__container"
content-class="modal__block"
content-transition="vfm-fade"
overlay-transition="vfm-fade"
:clickToClose="false"
@click-outside="close()"
>
<button
class="button modal__close"
@click="close"
>
</button>
<div class="authentication">
<div class="authentication__tabs tabs">
<button
v-for="item in tabsItems"
:key="`tab-${item.name}`"
class="tabs__item"
:class="currentTabsItem === item.name && 'is-active'"
@click.prevent="changeTab(item.name)"
>
{{ item.label }}
</button>
</div>
<template v-if="currentTabsItem === 'login'">
<FormKit
v-model="formLogin"
type="form"
data-loading="showLoaderSending"
form-class="$reset registration__form form"
submit-label="Войти"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
@click-outside="close"
>
<FormKitSchema :schema="loginForm"/>
</FormKit>
</template>
<template v-else>
<FormKit
v-model="formRegistration"
type="form"
data-loading="showLoaderSending"
form-class="$reset registration__form form"
submit-label="Войти"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
>
<FormKitSchema :schema="registerForm"/>
</FormKit>
</template>
</div>
</vue-final-modal>
<vue-final-modal
v-model="show"
class="modal__container"
content-class="modal__block"
content-transition="vfm-fade"
overlay-transition="vfm-fade"
:clickToClose="false"
@click-outside="close()"
>
<button class="button modal__close" @click="close"></button>
<div class="authentication">
<div class="authentication__tabs tabs">
<button
v-for="item in tabsItems"
:key="`tab-${item.name}`"
class="tabs__item"
:class="currentTabsItem === item.name && 'is-active'"
@click.prevent="changeTab(item.name)"
>
{{ item.label }}
</button>
</div>
<template v-if="currentTabsItem === 'login'">
<FormKit
v-model="formLogin"
type="form"
data-loading="showLoaderSending"
form-class="$reset registration__form form"
submit-label="Войти"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
@click-outside="close"
>
<FormKitSchema :schema="loginForm" />
</FormKit>
</template>
<template v-else>
<FormKit
v-model="formRegistration"
type="form"
data-loading="showLoaderSending"
form-class="$reset registration__form form"
submit-label="Войти"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
>
<FormKitSchema :schema="registerForm" />
</FormKit>
</template>
</div>
</vue-final-modal>
</template>
<script>
import {app} from "@/services";
import { app } from '@/services';
export default {
name: 'authentication',
data() {
return {
currentTabsItem: 'login',
tabsItems: [
{
label: 'Войти',
name: 'login'
},
{
label: 'Зарегистрироваться',
name: 'register'
},
],
formLogin: {},
formRegistration: {},
registerForm: [
{
$formkit: 'text',
name: 'email',
label: 'Ваша почта',
placeholder: 'Ваша почта',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'password',
name: 'password',
label: 'придумайте пароль',
placeholder: 'Придумайте пароль',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'password',
name: 'repeatPassword',
label: 'Повторите пароль',
placeholder: 'Повторите пароль',
validation: 'required',
outerClass: 'field--required'
}
],
loginForm: [
{
$formkit: 'text',
name: 'email',
label: 'Почта',
placeholder: 'Почта',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'password',
name: 'password',
label: 'пароль',
placeholder: 'Пароль',
validation: 'required',
outerClass: 'field--required'
}
],
showLoaderSending: false,
}
},
computed: {
show() {
return this.$store.state.modal.auth
}
},
methods: {
changeTab(tab) {
this.currentTabsItem = tab;
},
submitHandler(data, node) {
if (this.currentTabsItem === 'login') {
app.loginUser(this.formLogin).then(res => {
this.$store.dispatch('setToken', res);
app.user().then(user => {
this.$store.dispatch('setUser', user);
this.close();
this.next('profile');
}).catch(err => {
console.log(err)
})
}).catch(err => {
node.setErrors(
[err.detail],
err.error
)
})
} else {
if (this.formRegistration.password === this.formRegistration.repeatPassword) {
app.createUser(this.formRegistration).then(res => {
this.$store.dispatch('setToken', res);
app.user().then(user => {
this.$store.dispatch('setUser', user);
this.close();
this.next('profile');
}).catch(err => {
console.log(err)
})
}).catch(err => {
node.setErrors(
[err.detail],
err.error
)
console.log(err)
})
} else {
node.setErrors(
['Пароли не совпадают'],
{
password: '',
repeatPassword: '',
}
)
}
}
},
close() {
this.$store.dispatch('setModal', {auth: false});
},
next(name) {
this.$router.push({name});
}
}
}
name: 'authentication',
data() {
return {
currentTabsItem: 'login',
tabsItems: [
{
label: 'Войти',
name: 'login',
},
{
label: 'Зарегистрироваться',
name: 'register',
},
],
formLogin: {},
formRegistration: {},
registerForm: [
{
$formkit: 'text',
name: 'email',
label: 'Ваша почта',
placeholder: 'Ваша почта',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'password',
name: 'password',
label: 'придумайте пароль',
placeholder: 'Придумайте пароль',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'password',
name: 'repeatPassword',
label: 'Повторите пароль',
placeholder: 'Повторите пароль',
validation: 'required',
outerClass: 'field--required',
},
],
loginForm: [
{
$formkit: 'text',
name: 'email',
label: 'Почта',
placeholder: 'Почта',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'password',
name: 'password',
label: 'пароль',
placeholder: 'Пароль',
validation: 'required',
outerClass: 'field--required',
},
],
showLoaderSending: false,
};
},
computed: {
show() {
return this.$store.state.modal.auth;
},
},
methods: {
changeTab(tab) {
this.currentTabsItem = tab;
},
submitHandler(data, node) {
if (this.currentTabsItem === 'login') {
app
.loginUser(this.formLogin)
.then((res) => {
this.$store.dispatch('setToken', res);
app
.user()
.then((user) => {
this.$store.dispatch('setUser', user);
this.close();
this.next('profile');
})
.catch((err) => {
console.log(err);
});
})
.catch((err) => {
node.setErrors([err.detail], err.error);
});
} else {
if (
this.formRegistration.password ===
this.formRegistration.repeatPassword
) {
app
.createUser(this.formRegistration)
.then((res) => {
this.$store.dispatch('setToken', res);
app
.user()
.then((user) => {
this.$store.dispatch('setUser', user);
this.close();
this.next('profile');
})
.catch((err) => {
console.log(err);
});
})
.catch((err) => {
node.setErrors([err.detail], err.error);
console.log(err);
});
} else {
node.setErrors(['Пароли не совпадают'], {
password: '',
repeatPassword: '',
});
}
}
},
close() {
this.$store.dispatch('setModal', { auth: false });
},
next(name) {
this.$router.push({ name });
},
},
};
</script>

View File

@ -1,97 +1,100 @@
<template>
<vue-final-modal
v-model="show"
class="modal__container m--right"
content-class="modal__block m--half rubric-modal"
content-transition="vfm-fade"
overlay-transition="vfm-fade"
:clickToClose="false"
@click-outside="$emit('hideModal')"
>
<template v-if="showLoader">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<template v-else>
<div class="rubric-modal__header">
<div class="title m--white rubric-modal__title">
{{rubrik.name}}
</div>
<button
class="button modal__close rubric-modal__close"
@click="$emit('hideModal')"
>
</button>
</div>
<div class="rubric-modal__cover">
<img :src="`${selfUrl}${rubrik.img}`" alt=""/>
</div>
<div class="rubric-modal__description">
{{rubrik.description}}
</div>
<button class="button m--fit-content m--white m--arrow" v-if="user?.id">Написать</button>
</template>
</vue-final-modal>
<vue-final-modal
v-model="show"
class="modal__container m--right"
content-class="modal__block m--half rubric-modal"
content-transition="vfm-fade"
overlay-transition="vfm-fade"
:clickToClose="false"
@click-outside="$emit('hideModal')"
>
<template v-if="showLoader">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<template v-else>
<div class="rubric-modal__header">
<div class="title m--white rubric-modal__title">
{{ rubrik.name }}
</div>
<button
class="button modal__close rubric-modal__close"
@click="$emit('hideModal')"
></button>
</div>
<div class="rubric-modal__cover">
<img :src="`${selfUrl}${rubrik.img}`" alt="" />
</div>
<div class="rubric-modal__description">
{{ rubrik.description }}
</div>
<button class="button m--fit-content m--white m--arrow" v-if="user?.id">
Написать
</button>
</template>
</vue-final-modal>
</template>
<script>
import {app} from "@/services";
import {selfUrl} from '@/settings';
import { app } from '@/services';
import { selfUrl } from '@/settings';
export default {
name: 'RubricModal',
props: {
showModal: {
type: Boolean,
default() {
return false;
}
},
selectRubric: {
type: String,
default() {
return '';
}
},
},
data() {
return {
selfUrl,
rubrik: {},
showLoader: false
}
},
computed: {
show() {
return this.showModal;
},
user() {
return this.$store.state.user;
},
},
watch: {
'selectRubric': {
handler() {
if (this.selectRubric){
this.getRubrik();
}
}
}
},
methods: {
getRubrik() {
this.showLoader = true;
app.getRubrik(this.selectRubric).then((data) => {
this.showLoader = false;
this.rubrik = data[0];
}).catch(err => {
this.showLoader = false;
console.log(err)
})
},
}
}
name: 'RubricModal',
props: {
showModal: {
type: Boolean,
default() {
return false;
},
},
selectRubric: {
type: String,
default() {
return '';
},
},
},
data() {
return {
selfUrl,
rubrik: {},
showLoader: false,
};
},
computed: {
show() {
return this.showModal;
},
user() {
return this.$store.state.user;
},
},
watch: {
selectRubric: {
handler() {
if (this.selectRubric) {
this.getRubrik();
}
},
},
},
methods: {
getRubrik() {
this.showLoader = true;
app
.getRubrik(this.selectRubric)
.then((data) => {
this.showLoader = false;
this.rubrik = data[0];
})
.catch((err) => {
this.showLoader = false;
console.log(err);
});
},
},
};
</script>

View File

@ -1,109 +1,105 @@
<template>
<vue-final-modal
v-model="show"
class="modal__container"
content-class="modal__block"
content-transition="vfm-fade"
overlay-transition="vfm-fade"
:clickToClose="false"
@click-outside="close()"
>
<button
class="button modal__close"
@click="close"
>
</button>
<div class="modal__content">
<div class="modal__title">Изменение данных</div>
<FormKit
v-model="formData"
type="form"
data-loading="showLoaderSending"
form-class="$reset registration__form form"
submit-label="Войти"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
>
<FormKitSchema :schema="userForm"/>
</FormKit>
</div>
</vue-final-modal>
<vue-final-modal
v-model="show"
class="modal__container"
content-class="modal__block"
content-transition="vfm-fade"
overlay-transition="vfm-fade"
:clickToClose="false"
@click-outside="close()"
>
<button class="button modal__close" @click="close"></button>
<div class="modal__content">
<div class="modal__title">Изменение данных</div>
<FormKit
v-model="formData"
type="form"
data-loading="showLoaderSending"
form-class="$reset registration__form form"
submit-label="Войти"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
>
<FormKitSchema :schema="userForm" />
</FormKit>
</div>
</vue-final-modal>
</template>
<script>
import {app} from "@/services";
import { app } from '@/services';
export default {
name: 'recovery',
data(){
return{
userForm:[
{
$formkit: 'text',
name: 'email',
label: 'Ваша почта',
placeholder: 'Ваша почта',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'password',
name: 'old_password',
label: 'Введите старый пароль',
placeholder: 'Введите старый пароль',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'password',
name: 'password',
label: 'Введите новый пароль',
placeholder: 'Введите новый пароль',
validation: 'required',
outerClass: 'field--required'
}
],
formData: {},
showLoaderSending: false,
}
},
computed: {
user() {
return this.$store.state.user;
},
show(){
return this.$store.state.modal.changingUser;
}
},
mounted() {
this.formData.email = this.user.email;
},
methods:{
submitHandler(data, node){
this.showLoaderSending = true;
app.updateUser(this.formData).then(user=>{
this.showLoaderSending = false;
this.$store.dispatch('setUser', user);
}).catch(err=>{
this.showLoaderSending = false;
node.setErrors(
[err.detail],
err.error
)
})
},
close() {
this.$store.dispatch('setModal', {changingUser: false});
},
next(name){
this.$router.push({name});
}
}
}
name: 'recovery',
data() {
return {
userForm: [
{
$formkit: 'text',
name: 'email',
label: 'Ваша почта',
placeholder: 'Ваша почта',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'password',
name: 'old_password',
label: 'Введите старый пароль',
placeholder: 'Введите старый пароль',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'password',
name: 'password',
label: 'Введите новый пароль',
placeholder: 'Введите новый пароль',
validation: 'required',
outerClass: 'field--required',
},
],
formData: {},
showLoaderSending: false,
};
},
computed: {
user() {
return this.$store.state.user;
},
show() {
return this.$store.state.modal.changingUser;
},
},
mounted() {
this.formData.email = this.user?.email;
},
methods: {
submitHandler(data, node) {
this.showLoaderSending = true;
app
.updateUser(this.formData)
.then((user) => {
this.showLoaderSending = false;
this.$store.dispatch('setUser', user);
})
.catch((err) => {
this.showLoaderSending = false;
node.setErrors([err.detail], err.error);
});
},
close() {
this.$store.dispatch('setModal', { changingUser: false });
},
next(name) {
this.$router.push({ name });
},
},
};
</script>

View File

@ -1,123 +1,142 @@
<template>
<div
v-if="total && false"
class="pagination"
<div v-if="total && false" class="pagination">
<router-link
class="pagination__btn m--prev"
:to="{
path: url,
query: Object.assign({}, query, { page: goPrev }),
hash: hash,
}"
>
<router-link class="pagination__btn m--prev"
:to="{ path: url, query: Object.assign({}, query, { page: goPrev }), hash: hash }"
</router-link>
<ul class="pagination__list">
<li v-for="page in pagesArray" :key="`page-${page.value}`">
<router-link
class="pagination__link"
:class="[page.value === currentPage && 'm--current']"
:to="{
path: url,
query: Object.assign({}, query, { page: page.value }),
hash: hash,
}"
:event="page.value ? 'click' : ''"
>
{{ page.text }}
</router-link>
<ul class="pagination__list">
<li
v-for="page in pagesArray"
:key="`page-${page.value}`"
>
<router-link
class="pagination__link"
:class="[page.value === currentPage && 'm--current']"
:to="{ path: url, query: Object.assign({}, query, { page: page.value }), hash: hash }"
:event="page.value ? 'click' : ''"
>
{{ page.text }}
</router-link>
</li>
</ul>
<router-link class="pagination__btn m--next"
:to="{ path: url, query: Object.assign({}, query, { page: goForward }), hash: hash }"
>
</router-link>
</div>
</li>
</ul>
<router-link
class="pagination__btn m--next"
:to="{
path: url,
query: Object.assign({}, query, { page: goForward }),
hash: hash,
}"
>
</router-link>
</div>
</template>
<script>
export default {
props: {
total: {
type: Number,
default() {
return 0;
}
},
limit: {
type: Number,
default() {
return 10;
}
},
currentPage: {
type: Number,
default() {
return 1;
}
},
query: {
type: Object,
default() {
return {};
}
},
hash: {
type: String,
default() {
return '';
}
},
url: {
type: String,
default() {
return '';
}
}
props: {
total: {
type: Number,
default() {
return 0;
},
},
data() {
return {}
limit: {
type: Number,
default() {
return 10;
},
},
computed: {
step() {
return 1
},
pages() {
const pagesCount = Math.ceil(this.total / this.limit);
return this.$helpers.range(1, pagesCount || 1);
},
pagesArray() {
const count = Math.ceil(this.total / this.limit);
let items = [];
[...Array(count).keys()].map(i => i + 1).forEach(item => {
if (count <= 4) {
items.push({text: item, value: item});
} else {
if (item === 1 && this.currentPage !== item && this.currentPage - 1 !== 1 && this.currentPage - 2 !== 1) {
items.push({text: '1', value: 1});
items.push({text: '...', value: null});
} else if (item === count && this.currentPage + 1 !== count && this.currentPage + 2 !== count) {
items.push({text: '...', value: null});
items.push({text: count, value: count});
} else {
let deltaPrev = (count - this.currentPage <= 3) ? 3 : 2;
let deltaAfter = (this.currentPage <= 3) ? 4 - this.currentPage : 2;
if (item > this.currentPage - deltaPrev && item < this.currentPage + deltaAfter) {
console.log(item)
items.push({text: item, value: item});
}
}
}
});
return items
},
goForward() {
return `${this.currentPage + this.step}`
},
goPrev() {
return `${this.currentPage - this.step}`
},
currentPage: {
type: Number,
default() {
return 1;
},
},
mounted() {
query: {
type: Object,
default() {
return {};
},
},
beforeDestroy() {
hash: {
type: String,
default() {
return '';
},
},
created() {
url: {
type: String,
default() {
return '';
},
},
methods: {},
},
data() {
return {};
},
computed: {
step() {
return 1;
},
pages() {
const pagesCount = Math.ceil(this.total / this.limit);
return this.$helpers.range(1, pagesCount || 1);
},
pagesArray() {
const count = Math.ceil(this.total / this.limit);
let items = [];
[...Array(count).keys()]
.map((i) => i + 1)
.forEach((item) => {
if (count <= 4) {
items.push({ text: item, value: item });
} else {
if (
item === 1 &&
this.currentPage !== item &&
this.currentPage - 1 !== 1 &&
this.currentPage - 2 !== 1
) {
items.push({ text: '1', value: 1 });
items.push({ text: '...', value: null });
} else if (
item === count &&
this.currentPage + 1 !== count &&
this.currentPage + 2 !== count
) {
items.push({ text: '...', value: null });
items.push({ text: count, value: count });
} else {
let deltaPrev = count - this.currentPage <= 3 ? 3 : 2;
let deltaAfter = this.currentPage <= 3 ? 4 - this.currentPage : 2;
if (
item > this.currentPage - deltaPrev &&
item < this.currentPage + deltaAfter
) {
console.log(item);
items.push({ text: item, value: item });
}
}
}
});
return items;
},
goForward() {
return `${this.currentPage + this.step}`;
},
goPrev() {
return `${this.currentPage - this.step}`;
},
},
mounted() {},
beforeDestroy() {},
created() {},
methods: {},
};
</script>

View File

@ -1,318 +1,403 @@
<template>
<div class="player">
<div class="player__cover">
<q-skeleton v-if="loaderPlay" height="100%"/>
<img v-else :src="currentPlay.art" alt="player"/>
</div>
<div class="player__content">
<div class="player__top">
<q-skeleton v-if="loaderPlay" type="circle" class="player__btn m--skeleton"/>
<template v-else>
<button v-if="currentPlay.isPlay" @click="handlerPause" class="button player__btn m--pause">
</button>
<button v-else @click="handlerPlay" class="button player__btn m--play">
</button>
</template>
<div class="player__executor">
<q-skeleton v-if="loaderPlay" class="player__executor m--skeleton"/>
<template v-else>
{{ currentPlay.title || '—' }}
</template>
<span>
<q-skeleton v-if="loaderPlay"/>
<template v-else>
{{ currentPlay.artist || '—' }}
</template>
</span>
</div>
<template v-if="user?.id">
<q-skeleton v-if="loaderPlay" class="player__favorites m--skeleton"/>
<div v-else class="player__favorites" :class="[isFavorites&&'m--active']" @click="handlerFavorites">
</div>
</template>
<div class="player__tools">
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton"/>
<FormKit
v-else
v-model="isUserMusic"
type="toggle"
label="Включить мою музыку"
:disabled="!user?.id || userSongList.length === 0"
/>
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton"/>
<div v-else class="player__volume">
<span @click="changeVolume('set')"/>
<input type="range" v-model="songVolume" @change="changeVolume">
</div>
</div>
</div>
<div class="player__bottom">
<div class="player__time" :class="!loaderPlay&&!isUserMusic&&'m--ether'">
<q-skeleton v-if="loaderPlay"/>
<template v-else-if="isUserMusic">
{{ getTime(playerInfo.currentTime) }} / {{ getTime(playerInfo.duration) }}
</template>
<template v-else>
Эфир
</template>
</div>
<div class="player__progress">
<q-skeleton v-if="loaderPlay" height="5px"/>
<input v-else :disabled="!isUserMusic" type="range" v-model="playerInfo.progress">
</div>
</div>
</div>
</div>
<div class="player">
<div class="player__cover">
<q-skeleton v-if="loaderPlay" height="100%" />
<img v-else :src="currentPlay.art" alt="player" />
</div>
<div class="player__content">
<div class="player__top">
<q-skeleton
v-if="loaderPlay"
type="circle"
class="player__btn m--skeleton"
/>
<template v-else>
<button
v-if="currentPlay.isPlay"
@click="handlerPause"
class="button player__btn m--pause"
></button>
<button
v-else
@click="handlerPlay"
class="button player__btn m--play"
></button>
</template>
<div class="player__executor">
<q-skeleton v-if="loaderPlay" class="player__executor m--skeleton" />
<template v-else>
{{ currentPlay.title || '—' }}
</template>
<span>
<q-skeleton v-if="loaderPlay" />
<template v-else>
{{ currentPlay.artist || '—' }}
</template>
</span>
</div>
<template v-if="user?.id">
<q-skeleton v-if="loaderPlay" class="player__favorites m--skeleton" />
<div
v-else
class="player__favorites"
:class="[isFavorites && 'm--active']"
@click="handlerFavorites"
></div>
</template>
<div class="player__tools">
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton" />
<FormKit
v-else
v-model="isUserMusic"
type="toggle"
label="Включить мою музыку"
:disabled="!user?.id || userSongList.length === 0"
/>
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton" />
<div v-else class="player__volume">
<span @click="changeVolume('set')" />
<input type="range" v-model="songVolume" @change="changeVolume" />
</div>
</div>
</div>
<div class="player__bottom">
<div
class="player__time"
:class="!loaderPlay && !isUserMusic && 'm--ether'"
>
<q-skeleton v-if="loaderPlay" />
<template v-else-if="isUserMusic">
{{ getTime(playerInfo.currentTime) }} /
{{ getTime(playerInfo.duration) }}
</template>
<template v-else> Эфир </template>
</div>
<div class="player__progress">
<q-skeleton v-if="loaderPlay" height="5px" />
<input
v-else
:disabled="!isUserMusic"
type="range"
v-model="playerInfo.progress"
/>
</div>
</div>
</div>
</div>
</template>
<script>
import {app, audio as Player} from "@/services";
import { app, audio as Player } from '@/services';
export default {
name: 'player',
components: {},
data() {
return {
isFavorites: false,
isPlayRadio: false,
connection: null,
isUserMusic: !this.$store.state.currentPlay.live,
songVolume: this.$store.state.currentPlay.volume,
playerInfo: {
progress: 0,
currentTime: 0,
duration: 0
},
}
},
computed: {
user() {
return this.$store.state.user;
},
currentPlay() {
return this.$store.state.currentPlay
},
player() {
return this.$store.state.player
},
userSongList() {
return this.$store.state.userFavorite?.songs || []
},
loaderPlay() {
return this.$store.state.currentPlay.isLoader
}
},
watch: {
'currentPlay': {
immediate: false,
handler(to, from) {
if (this.isUserMusic === this.currentPlay.live) {
this.isUserMusic = !this.currentPlay.live;
}
if (this.user?.id && to.id !== from.id) {
this.checkSongIsFavorite();
}
if (!this.currentPlay.live && to.id !== from.id) {
this.getAudio(this.currentPlay.azura_id);
}
},
},
'userSongList': {
immediate: false,
handler(to, from) {
if (this.user?.id && to.length !== from.length) {
this.checkSongIsFavorite();
}
},
},
'isUserMusic': {
immediate: false,
handler() {
if (this.isUserMusic === this.currentPlay.live) {
this.changeLive();
}
},
},
},
created() {
this.connectionPlayer();
},
mounted() {
console.log(this.currentPlay)
this.$store.dispatch('initPlayer');
if (this.user?.id) {
this.checkSongIsFavorite();
this.getSongList();
}
this.playerInfo.progress = this.currentPlay.live ? 100 : 0;
if (!this.currentPlay.live && this.userSongList?.length > 0) {
this.$store.dispatch('setCurrentPlay', {...this.userSongList[this.currentPlay.currentIndex || 0], live: false});
this.getAudio(this.userSongList[this.currentPlay.currentIndex || 0]?.azura_id);
if (this.player.target) {
this.player.target.addEventListener('timeupdate', this.updateProgress)
}
}
if (!this.user?.id){
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, live: true, isLoader: true, currentIndex: null});
}
},
methods: {
connectionPlayer() {
if (this.connection) {
this.connection.removePlay();
}
this.connection = new Player();
this.connection.init();
this.connection.onHandler(this.getPlaying);
},
checkSongIsFavorite() {
app.getCheckFavoriteSong(this.currentPlay.azura_id || this.currentPlay.id).then(res => {
this.isFavorites = res.is_favorite;
}).catch(err => {
console.error(err)
})
},
removeFavorites(song) {
app.removeFavorites(song).then(() => {
this.getSongList();
}).catch(err => {
this.showLoader = false;
console.error(err)
})
},
getPlaying(e) {
const jsonData = JSON.parse(e.data)
if (jsonData?.pub?.data) {
const data = jsonData?.pub?.data;
if (this.currentPlay.live) {
if (data.np.station.listen_url !== this.player.target.src) {
console.log('data.np.station.listen_url', data.np.station.listen_url)
this.$store.dispatch('changePlayer', data.np.station.listen_url);
const params = {
...this.currentPlay,
...data.np.now_playing.song,
azura_id: data.np.now_playing.song.id,
isLoader: false,
live: true,
currentIndex: null
}
delete params.unique_id;
this.$store.dispatch('setCurrentPlay', params);
}
}
}
},
updateProgress(e) {
this.playerInfo = {
...this.playerInfo,
progress: this.player.target.currentTime / this.player.target.duration * 100,
currentTime: this.player.target.currentTime
}
if (this.player.target.currentTime === this.player.target.duration){
let currentIndex = this.currentPlay.currentIndex + 1;
if (!this.userSongList[currentIndex]?.azura_id || currentIndex === null){
currentIndex = 0;
}
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, ...this.userSongList[currentIndex], currentIndex})
}
},
handlerPlay() {
console.log(this.currentPlay)
console.log(this.player)
this.$store.dispatch('handlerPlayer', {play: true});
},
handlerPause() {
this.$store.dispatch('handlerPlayer', {pause: true});
},
getSongList() {
app.getFavoriteList().then(res => {
this.$store.dispatch('setUserFavorite', {songs: res})
console.log('res.length' ,res.length)
if (res.length === 0){
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, live: true, isLoader: true});
}
}).catch(err => {
console.error(err)
})
},
handlerFavorites() {
if (this.user?.id) {
const params = {...this.currentPlay, azura_id: Number(this.currentPlay.id)?this.currentPlay.azura_id:this.currentPlay.id};
if (!this.isFavorites) {
delete params.id;
app.createFavoriteForUser(params).then(() => {
this.isFavorites = !this.isFavorites;
this.getSongList();
}).catch(err => {
console.error(err)
})
} else {
console.log(params)
app.removeFavorites(params).then(()=>{
this.getSongList();
}).catch(err=>{
console.error(err)
})
}
} else {
this.$emit('shopAuthentication', true)
}
name: 'player',
components: {},
data() {
return {
isFavorites: false,
isPlayRadio: false,
connection: null,
isUserMusic: !this.$store.state.currentPlay.live,
songVolume: this.$store.state.currentPlay.volume,
playerInfo: {
progress: 0,
currentTime: 0,
duration: 0,
},
};
},
computed: {
user() {
return this.$store.state.user;
},
currentPlay() {
return this.$store.state.currentPlay;
},
player() {
return this.$store.state.player;
},
userSongList() {
return this.$store.state.userFavorite?.songs || [];
},
loaderPlay() {
return this.$store.state.currentPlay.isLoader;
},
},
watch: {
currentPlay: {
immediate: false,
handler(to, from) {
if (this.isUserMusic === this.currentPlay.live) {
this.isUserMusic = !this.currentPlay.live;
}
if (this.user?.id && to.id !== from.id) {
this.checkSongIsFavorite();
}
if (!this.currentPlay.live && to.id !== from.id) {
this.getAudio(this.currentPlay.azura_id);
}
},
},
userSongList: {
immediate: false,
handler(to, from) {
if (this.user?.id && to.length !== from.length) {
this.checkSongIsFavorite();
}
},
},
isUserMusic: {
immediate: false,
handler() {
if (this.isUserMusic === this.currentPlay.live) {
this.changeLive();
}
},
},
},
created() {
this.connectionPlayer();
},
mounted() {
console.log(this.currentPlay);
this.$store.dispatch('initPlayer');
if (this.user?.id) {
this.checkSongIsFavorite();
this.getSongList();
}
this.playerInfo.progress = this.currentPlay.live ? 100 : 0;
if (!this.currentPlay.live && this.userSongList?.length > 0) {
this.$store.dispatch('setCurrentPlay', {
...this.userSongList[this.currentPlay.currentIndex || 0],
live: false,
});
this.getAudio(
this.userSongList[this.currentPlay.currentIndex || 0]?.azura_id,
);
if (this.player.target) {
this.player.target.addEventListener('timeupdate', this.updateProgress);
}
}
if (!this.user?.id) {
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
live: true,
isLoader: true,
currentIndex: null,
});
}
},
methods: {
connectionPlayer() {
if (this.connection) {
this.connection.removePlay();
}
this.connection = new Player();
this.connection.init();
this.connection.onHandler(this.getPlaying);
},
checkSongIsFavorite() {
app
.getCheckFavoriteSong(this.currentPlay.azura_id || this.currentPlay.id)
.then((res) => {
this.isFavorites = res.is_favorite;
})
.catch((err) => {
console.error(err);
});
},
removeFavorites(song) {
app
.removeFavorites(song)
.then(() => {
this.getSongList();
})
.catch((err) => {
this.showLoader = false;
console.error(err);
});
},
getPlaying(e) {
const jsonData = JSON.parse(e.data);
if (jsonData?.pub?.data) {
const data = jsonData?.pub?.data;
if (this.currentPlay.live) {
if (data.np.station.listen_url !== this.player.target.src) {
console.log(
'data.np.station.listen_url',
data.np.station.listen_url,
);
this.$store.dispatch('changePlayer', data.np.station.listen_url);
const params = {
...this.currentPlay,
...data.np.now_playing.song,
azura_id: data.np.now_playing.song.id,
isLoader: false,
live: true,
currentIndex: null,
};
delete params.unique_id;
this.$store.dispatch('setCurrentPlay', params);
}
}
}
},
updateProgress(e) {
this.playerInfo = {
...this.playerInfo,
progress:
(this.player.target.currentTime / this.player.target.duration) * 100,
currentTime: this.player.target.currentTime,
};
if (this.player.target.currentTime === this.player.target.duration) {
let currentIndex = this.currentPlay.currentIndex + 1;
if (
!this.userSongList[currentIndex]?.azura_id ||
currentIndex === null
) {
currentIndex = 0;
}
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
...this.userSongList[currentIndex],
currentIndex,
});
}
},
handlerPlay() {
console.log(this.currentPlay);
console.log(this.player);
this.$store.dispatch('handlerPlayer', { play: true });
},
handlerPause() {
this.$store.dispatch('handlerPlayer', { pause: true });
},
getSongList() {
app
.getFavoriteList()
.then((res) => {
this.$store.dispatch('setUserFavorite', { songs: res });
console.log('res.length', res.length);
if (res.length === 0) {
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
live: true,
isLoader: true,
});
}
})
.catch((err) => {
console.error(err);
});
},
handlerFavorites() {
if (this.user?.id) {
const params = {
...this.currentPlay,
azura_id: Number(this.currentPlay.id)
? this.currentPlay.azura_id
: this.currentPlay.id,
};
if (!this.isFavorites) {
delete params.id;
app
.createFavoriteForUser(params)
.then(() => {
this.isFavorites = !this.isFavorites;
this.getSongList();
})
.catch((err) => {
console.error(err);
});
} else {
console.log(params);
app
.removeFavorites(params)
.then(() => {
this.getSongList();
})
.catch((err) => {
console.error(err);
});
}
} else {
this.$emit('shopAuthentication', true);
}
},
changeVolume(type) {
let volume = this.songVolume;
if (type === 'set') {
volume = this.songVolume === 0 ? 0.9 : 0.01;
this.songVolume = this.songVolume === 0 ? 100 : 0;
} else {
volume = this.songVolume / 100;
}
if (volume === 0) volume = 0.01;
this.$store.dispatch('handlerPlayer', { volume });
},
getAudio(id) {
app
.getAudio(id)
.then((res) => {
const blob = new Blob([res], { type: 'application/audio' });
const audioUrl = URL.createObjectURL(blob);
this.$store.dispatch('changePlayer', audioUrl);
this.player.target.addEventListener(
'timeupdate',
this.updateProgress,
);
},
changeVolume(type) {
let volume = this.songVolume;
if (type === 'set') {
volume = this.songVolume === 0 ? 0.9 : 0.01;
this.songVolume = this.songVolume === 0 ? 100 : 0;
} else {
volume = this.songVolume / 100;
}
if (volume === 0) volume = 0.01
this.$store.dispatch('handlerPlayer', {volume});
},
getAudio(id) {
app.getAudio(id).then(res => {
const blob = new Blob([res], {type: 'application/audio'});
const audioUrl = URL.createObjectURL(blob);
this.$store.dispatch('changePlayer', audioUrl);
this.player.target.addEventListener('timeupdate', this.updateProgress);
blob.arrayBuffer().then((buffer) => {
var audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
audioContext.decodeAudioData(buffer, (decodedData) => {
this.playerInfo.duration = decodedData.duration;
});
});
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
isLoader: false,
});
})
.catch((err) => {
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
isLoader: false,
});
console.debug(err);
});
},
changeLive() {
if (this.currentPlay.live) {
console.log('избранное');
this.playerInfo.progress = 0;
const params = {
...this.userSongList[this.currentPlay.currentIndex || 0],
live: false,
isLoader: true,
};
if (!this.currentPlay.currentIndex) params.currentIndex = 0;
this.$store.dispatch('setCurrentPlay', params);
} else {
this.playerInfo.progress = 100;
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
live: true,
isLoader: true,
});
console.log('поток');
}
},
getTime(value) {
let minutes = Math.floor(value / 60);
let seconds = Math.round(value % 60);
blob.arrayBuffer().then(buffer => {
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
audioContext.decodeAudioData(buffer, (decodedData) => {
this.playerInfo.duration = decodedData.duration;
});
});
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, isLoader: false})
}).catch(err => {
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, isLoader: false})
console.debug(err)
})
},
changeLive() {
if (this.currentPlay.live) {
console.log('избранное')
this.playerInfo.progress = 0;
const params = {...this.userSongList[this.currentPlay.currentIndex || 0], live: false, isLoader: true};
if (!this.currentPlay.currentIndex) params.currentIndex = 0;
this.$store.dispatch('setCurrentPlay', params);
} else {
this.playerInfo.progress = 100;
this.$store.dispatch('setCurrentPlay', {...this.currentPlay, live: true, isLoader: true});
console.log('поток')
}
},
getTime(value) {
let minutes = Math.floor(value / 60);
let seconds = Math.round(value % 60);
let paddedMinutes = minutes < 10 ? "0" + minutes : minutes;
let paddedSeconds = seconds < 10 ? "0" + seconds : seconds;
if (!paddedMinutes) paddedMinutes = '00';
if (!paddedSeconds) paddedSeconds = '00';
return `${paddedMinutes}:${paddedSeconds}`;
},
}
}
let paddedMinutes = minutes < 10 ? '0' + minutes : minutes;
let paddedSeconds = seconds < 10 ? '0' + seconds : seconds;
if (!paddedMinutes) paddedMinutes = '00';
if (!paddedSeconds) paddedSeconds = '00';
return `${paddedMinutes}:${paddedSeconds}`;
},
},
};
</script>

View File

@ -1,27 +1,27 @@
<template>
<div class="playlist-item" @click="selectPlaylist">
<div class="playlist-item__cover"></div>
<div>{{playlist.name}}</div>
<div @click="editPlaylist">...</div>
</div>
<div class="playlist-item" @click="selectPlaylist">
<div class="playlist-item__cover"></div>
<div>{{ playlist.name }}</div>
<div @click="editPlaylist">...</div>
</div>
</template>
<script>
export default {
name: 'playlist-item',
props:{
playlist:{
type: Object,
default: () => {}
}
},
methods:{
editPlaylist(){
this.$emit('editPlaylist', this.playlist)
},
selectPlaylist(){
this.$emit('selectPlaylist', this.playlist)
}
}
}
name: 'playlist-item',
props: {
playlist: {
type: Object,
default: () => {},
},
},
methods: {
editPlaylist() {
this.$emit('editPlaylist', this.playlist);
},
selectPlaylist() {
this.$emit('selectPlaylist', this.playlist);
},
},
};
</script>

View File

@ -1,41 +1,41 @@
<template>
<div class="playlist-roster">
<PlaylistItem
v-for="item in list"
:key="`playlist_${item.id}`"
:playlist="item"
@selectPlaylist="selectPlaylist"
@editPlaylist="editPlaylist"
/>
<div class="playlist-item m--create" @click="createPlaylist">
<div class="playlist-item__cover"></div>
<div>Создать плейлист</div>
</div>
</div>
<div class="playlist-roster">
<PlaylistItem
v-for="item in list"
:key="`playlist_${item.id}`"
:playlist="item"
@selectPlaylist="selectPlaylist"
@editPlaylist="editPlaylist"
/>
<div class="playlist-item m--create" @click="createPlaylist">
<div class="playlist-item__cover"></div>
<div>Создать плейлист</div>
</div>
</div>
</template>
<script>
import PlaylistItem from "@/components/playlist-item.vue";
import PlaylistItem from '@/components/playlist-item.vue';
export default {
name: 'playlist-roster',
components: {PlaylistItem},
props: {
list: {
type: Array,
default: () => []
}
},
methods: {
createPlaylist() {
this.$emit('createPlaylist')
},
selectPlaylist(params) {
this.$router.push({name: 'playlist', params: {id: params.id}})
},
editPlaylist(params) {
this.$router.push({name: 'playlist-edit', params: {id: params.id}})
}
}
}
name: 'playlist-roster',
components: { PlaylistItem },
props: {
list: {
type: Array,
default: () => [],
},
},
methods: {
createPlaylist() {
this.$emit('createPlaylist');
},
selectPlaylist(params) {
this.$router.push({ name: 'playlist', params: { id: params.id } });
},
editPlaylist(params) {
this.$router.push({ name: 'playlist-edit', params: { id: params.id } });
},
},
};
</script>

View File

@ -1,70 +1,93 @@
<template>
<div class="rubric-block">
<div class="rubric-block__header">
<h2 class="h2 rubric-block__header-title">
Рубрики
</h2>
<button class="button m--arrow rubric-block__link" v-if="$route.name !== 'rubric'" @click="next('rubric')">Смотреть все</button>
<div class="p rubric-block__description">
IT-радио - это уникальная платформа для обмена опытом, знаниями и обсуждения актуальных вопросов, связанных с разработкой программного обеспечения, искусственного интеллекта, интернета вещей и других направлений IT-индустрии
</div>
</div>
<template v-if="showLoader">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<div v-else class="rubric-block__list">
<div class="rubric-block__item" v-for="rubrik in rubriks" :key="`rubrik_${rubrik.id}`">
<div class="title rubric-block__title">{{rubrik.name}}</div>
<div class="p rubric-block__description m--50">{{rubrik.title}}</div>
<button class="button m--arrow rubric-block__btn" @click="showModalRubric(rubrik.id)">Узнать больше</button>
</div>
</div>
<div class="rubric-block">
<div class="rubric-block__header">
<h2 class="h2 rubric-block__header-title">Рубрики</h2>
<button
class="button m--arrow rubric-block__link"
v-if="$route.name !== 'rubric'"
@click="next('rubric')"
>
Смотреть все
</button>
<div class="p rubric-block__description">
IT-радио - это уникальная платформа для обмена опытом, знаниями и
обсуждения актуальных вопросов, связанных с разработкой программного
обеспечения, искусственного интеллекта, интернета вещей и других
направлений IT-индустрии
</div>
</div>
<RubricModal :showModal="isShowModalRubric" @hideModal="hiddenModalRubric" :selectRubric="ModalTemplate"/>
<template v-if="showLoader">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<div v-else class="rubric-block__list">
<div
class="rubric-block__item"
v-for="rubrik in rubriks"
:key="`rubrik_${rubrik.id}`"
>
<div class="title rubric-block__title">{{ rubrik.name }}</div>
<div class="p rubric-block__description m--50">{{ rubrik.title }}</div>
<button
class="button m--arrow rubric-block__btn"
@click="showModalRubric(rubrik.id)"
>
Узнать больше
</button>
</div>
</div>
</div>
<RubricModal
:showModal="isShowModalRubric"
@hideModal="hiddenModalRubric"
:selectRubric="ModalTemplate"
/>
</template>
<script>
import RubricModal from "@/components/modal/rubric-modal.vue";
import {app} from "@/services";
import RubricModal from '@/components/modal/rubric-modal.vue';
import { app } from '@/services';
export default {
name: 'rubric-block',
components: {RubricModal},
data(){
return{
isShowModalRubric: false,
ModalTemplate:null,
rubriks: [],
showLoader: false,
}
name: 'rubric-block',
components: { RubricModal },
data() {
return {
isShowModalRubric: false,
ModalTemplate: null,
rubriks: [],
showLoader: false,
};
},
created() {
this.getRubriks();
},
methods: {
getRubriks() {
this.showLoader = true;
app
.getRubriks()
.then((data) => {
this.showLoader = false;
this.rubriks = data;
})
.catch((err) => {
this.showLoader = false;
console.log(err);
});
},
created() {
this.getRubriks();
},
methods:{
getRubriks() {
this.showLoader = true;
app.getRubriks().then((data) => {
this.showLoader = false;
this.rubriks = data;
}).catch(err => {
this.showLoader = false;
console.log(err)
})
},
showModalRubric(key){
this.ModalTemplate = key
this.isShowModalRubric = true;
},
hiddenModalRubric(){
this.isShowModalRubric = false;
},
next(name){
this.$router.push({name})
}
}
}
showModalRubric(key) {
this.ModalTemplate = key;
this.isShowModalRubric = true;
},
hiddenModalRubric() {
this.isShowModalRubric = false;
},
next(name) {
this.$router.push({ name });
},
},
};
</script>

View File

@ -1,92 +1,133 @@
<template>
<div class="song-item" :class="[selectSong&&'m--select']" @click="handlerSelectSong">
<div class="song-item__selected" :class="[!isPlay&&'m--stop']">
<svg width="33" height="28" viewBox="0 0 33 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="" d="M0 15C0 13.6193 1.11929 12.5 2.5 12.5C3.88071 12.5 5 13.6193 5 15V27.5H0V15Z" fill="#7138F4"/>
<path d="M7 9C7 7.61929 8.11929 6.5 9.5 6.5C10.8807 6.5 12 7.61929 12 9V27.5H7V9Z" fill="#7138F4"/>
<path d="M14 12C14 10.6193 15.1193 9.5 16.5 9.5C17.8807 9.5 19 10.6193 19 12V27.5H14V12Z" fill="#7138F4"/>
<path d="M21 3C21 1.61929 22.1193 0.5 23.5 0.5C24.8807 0.5 26 1.61929 26 3V27.5H21V3Z" fill="#7138F4"/>
<path d="M28 20C28 18.6193 29.1193 17.5 30.5 17.5C31.8807 17.5 33 18.6193 33 20V27.5H28V20Z" fill="#7138F4"/>
</svg>
</div>
<div>
<button v-if="isPlay" @click.stop="handlerPause" class="button song-item__btn m--pause">
</button>
<button v-else @click.stop="handlerPlay" class="button song-item__btn m--play">
</button>
</div>
<div class="song-item__info">
<span>{{song.title}}</span>
{{song.artist}}
</div>
<div class="song-item__tools">
<button class="button song-item__btn m--small m--favorites" @click.stop="removeSong"></button>
<button class="button song-item__btn m--small m--add" :class="songAlreadyAddPlaylist&&'m--already'" @click.stop="songAlreadyAddPlaylist?removeToPlaylist():addPlaylist()"></button>
</div>
</div>
<div
class="song-item"
:class="[selectSong && 'm--select']"
@click="handlerSelectSong"
>
<div class="song-item__selected" :class="[!isPlay && 'm--stop']">
<svg
width="33"
height="28"
viewBox="0 0 33 28"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
class=""
d="M0 15C0 13.6193 1.11929 12.5 2.5 12.5C3.88071 12.5 5 13.6193 5 15V27.5H0V15Z"
fill="#7138F4"
/>
<path
d="M7 9C7 7.61929 8.11929 6.5 9.5 6.5C10.8807 6.5 12 7.61929 12 9V27.5H7V9Z"
fill="#7138F4"
/>
<path
d="M14 12C14 10.6193 15.1193 9.5 16.5 9.5C17.8807 9.5 19 10.6193 19 12V27.5H14V12Z"
fill="#7138F4"
/>
<path
d="M21 3C21 1.61929 22.1193 0.5 23.5 0.5C24.8807 0.5 26 1.61929 26 3V27.5H21V3Z"
fill="#7138F4"
/>
<path
d="M28 20C28 18.6193 29.1193 17.5 30.5 17.5C31.8807 17.5 33 18.6193 33 20V27.5H28V20Z"
fill="#7138F4"
/>
</svg>
</div>
<div>
<button
v-if="isPlay"
@click.stop="handlerPause"
class="button song-item__btn m--pause"
></button>
<button
v-else
@click.stop="handlerPlay"
class="button song-item__btn m--play"
></button>
</div>
<div class="song-item__info">
<span>{{ song.title }}</span>
{{ song.artist }}
</div>
<div class="song-item__tools">
<button
class="button song-item__btn m--small m--favorites"
@click.stop="removeSong"
></button>
<button
class="button song-item__btn m--small m--add"
:class="songAlreadyAddPlaylist && 'm--already'"
@click.stop="
songAlreadyAddPlaylist ? removeToPlaylist() : addPlaylist()
"
></button>
</div>
</div>
</template>
<script>
export default {
name: 'song-item',
props:{
selectSong:{
type: Boolean,
default(){
return false
}
},
song:{
type: Object,
default(){
return {}
}
},
playSong:{
type: Boolean,
default(){
return false
}
},
songAlreadyAddPlaylist:{
type: Boolean,
default(){
return false
}
},
},
watch: {
'playSong': {
immediate: true,
handler() {
this.isPlay = this.playSong;
},
}
},
data(){
return{
isPlay: this.playSong
}
},
methods:{
handlerPlay() {
this.$emit('playSong', {...this.song, live: false, isPlay: true,})
},
handlerPause() {
this.$emit('pauseSong', {...this.song, live: false, isPlay: false,})
},
handlerSelectSong(){
this.$emit('selectSong', {...this.song, live: false})
},
removeSong(){
this.$emit('removeSong', this.song);
},
addPlaylist(){
this.$emit('addPlaylist', this.song);
},
removeToPlaylist(){
this.$emit('removePlaylist', this.song);
}
}
}
name: 'song-item',
props: {
selectSong: {
type: Boolean,
default() {
return false;
},
},
song: {
type: Object,
default() {
return {};
},
},
playSong: {
type: Boolean,
default() {
return false;
},
},
songAlreadyAddPlaylist: {
type: Boolean,
default() {
return false;
},
},
},
watch: {
playSong: {
immediate: true,
handler() {
this.isPlay = this.playSong;
},
},
},
data() {
return {
isPlay: this.playSong,
};
},
methods: {
handlerPlay() {
this.$emit('playSong', { ...this.song, live: false, isPlay: true });
},
handlerPause() {
this.$emit('pauseSong', { ...this.song, live: false, isPlay: false });
},
handlerSelectSong() {
this.$emit('selectSong', { ...this.song, live: false });
},
removeSong() {
this.$emit('removeSong', this.song);
},
addPlaylist() {
this.$emit('addPlaylist', this.song);
},
removeToPlaylist() {
this.$emit('removePlaylist', this.song);
},
},
};
</script>

View File

@ -1,72 +1,76 @@
<template>
<div class="song-list">
<SongItem
v-for="song in songList"
:key="song"
:song="song"
:playSong="song.azura_id === currentPlay.azura_id? currentPlay.isPlay: false"
:selectSong="song.azura_id === currentPlay.azura_id"
:songAlreadyAddPlaylist="songAlreadyAdd"
@selectSong="handlerSelectSong"
@playSong="handlerPlaySong"
@pauseSong="handlerPauseSong"
@removeSong="removeSong"
@addPlaylist="addPlaylist"
@removePlaylist="removePlaylist"
/>
</div>
<div class="song-list">
<SongItem
v-for="song in songList"
:key="song"
:song="song"
:playSong="
song.azura_id === currentPlay.azura_id ? currentPlay.isPlay : false
"
:selectSong="song.azura_id === currentPlay.azura_id"
:songAlreadyAddPlaylist="songAlreadyAdd"
@selectSong="handlerSelectSong"
@playSong="handlerPlaySong"
@pauseSong="handlerPauseSong"
@removeSong="removeSong"
@addPlaylist="addPlaylist"
@removePlaylist="removePlaylist"
/>
</div>
</template>
<script>
import SongItem from "@/components/song-item.vue";
import SongItem from '@/components/song-item.vue';
export default {
name: 'song-list',
components: {SongItem},
props: {
songList: {
type: Array,
default: () => []
},
songAlreadyAdd: {
type: Boolean,
default: () => false
}
},
data() {
return {}
},
computed: {
currentPlay() {
return this.$store.state.currentPlay
}
},
methods: {
handlerSelectSong(params) {
const data = {...this.currentPlay, ...params, isLoader: true};
data.currentIndex = this.songList.findIndex(el=>el.azura_id === params.azura_id);
this.$store.dispatch('setCurrentPlay', data);
console.log('handlerSelectSong')
},
handlerPlaySong(params) {
this.$store.dispatch('setCurrentPlay', params);
console.log('handlerPlaySong')
// this.$store.dispatch('handlerPlayer', {pause: true});
},
handlerPauseSong(params) {
this.$store.dispatch('setCurrentPlay', params);
console.log('handlerPauseSong')
// this.$store.dispatch('handlerPlayer', {play: true});
},
removeSong(song){
this.$emit('removeSong', song)
},
addPlaylist(song){
this.$emit('addPlaylist', song)
},
removePlaylist(song){
this.$emit('removePlaylist', song)
}
}
}
name: 'song-list',
components: { SongItem },
props: {
songList: {
type: Array,
default: () => [],
},
songAlreadyAdd: {
type: Boolean,
default: () => false,
},
},
data() {
return {};
},
computed: {
currentPlay() {
return this.$store.state.currentPlay;
},
},
methods: {
handlerSelectSong(params) {
const data = { ...this.currentPlay, ...params, isLoader: true };
data.currentIndex = this.songList.findIndex(
(el) => el.azura_id === params.azura_id,
);
this.$store.dispatch('setCurrentPlay', data);
console.log('handlerSelectSong');
},
handlerPlaySong(params) {
this.$store.dispatch('setCurrentPlay', params);
console.log('handlerPlaySong');
// this.$store.dispatch('handlerPlayer', {pause: true});
},
handlerPauseSong(params) {
this.$store.dispatch('setCurrentPlay', params);
console.log('handlerPauseSong');
// this.$store.dispatch('handlerPlayer', {play: true});
},
removeSong(song) {
this.$emit('removeSong', song);
},
addPlaylist(song) {
this.$emit('addPlaylist', song);
},
removePlaylist(song) {
this.$emit('removePlaylist', song);
},
},
};
</script>

View File

@ -1,25 +1,29 @@
<template>
<div class="support-block">
<h2 class="h2">Поддержи нас</h2>
<div class="support-block__list">
<div class="support-block__item m--one-circle">
<div class="title">Донат</div>
Мы будем рады, если вы поддержите нас любой суммой! Все средства пойдут на дальнейшее развитие проекта
</div>
<div class="support-block__item m--two-circle">
<div class="title">Дело</div>
Если вы фотографируете, монтируете, пишете, корректируете, занимаетесь продвижением или делаете еще что-нибудь классное и думаете, что можете быть нам полезны на волонтерских началах свяжитесь с нами через форму
</div>
<div class="support-block__item m--three-circle">
<div class="title">Развитие</div>
Расскажите о нашем проекте в соцсетях! Можно поделиться любым нашим постом, видео в ютубе или рассказать о нас в своей аудитории
</div>
</div>
</div>
<div class="support-block">
<h2 class="h2">Поддержи нас</h2>
<div class="support-block__list">
<div class="support-block__item m--one-circle">
<div class="title">Донат</div>
Мы будем рады, если вы поддержите нас любой суммой! Все средства пойдут
на дальнейшее развитие проекта
</div>
<div class="support-block__item m--two-circle">
<div class="title">Дело</div>
Если вы фотографируете, монтируете, пишете, корректируете, занимаетесь
продвижением или делаете еще что-нибудь классное и думаете, что можете
быть нам полезны на волонтерских началах свяжитесь с нами через форму
</div>
<div class="support-block__item m--three-circle">
<div class="title">Развитие</div>
Расскажите о нашем проекте в соцсетях! Можно поделиться любым нашим
постом, видео в ютубе или рассказать о нас в своей аудитории
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SupportBlock'
}
name: 'SupportBlock',
};
</script>

View File

@ -1,102 +1,108 @@
<template>
<div class="team">
<div class="team__header">
<h2 class="h2 team__title">
Наша команда
</h2>
<div class="team__description">
На IT волне команда профессионалов неутомимо трудится, чтобы дарить слушателям самые свежие и актуальные
новости из мира технологий, отвечать на их вопросы и обсуждать горячие темы на IT радио.
</div>
</div>
<template v-if="showLoader">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<Swiper
v-else
:slides-per-view="4"
:space-between="20"
:modules="modules"
:pagination="{
el: '.team__progress',
clickable: true,
type: 'progressbar',
}"
:breakpoints="{
0: {
slidesPerView: 1,
},
450: {
slidesPerView: 1.5,
},
768: {
slidesPerView: 2.5,
},
1020:{
slidesPerView: 3,
},
1280: {
slidesPerView: 4,
},
}"
class="team__slider"
>
<SwiperSlide class="team__item" v-for="employee in team" :key="employee.id">
<div class="team__cover">
<img :src="`${selfUrl + employee.img_person}`" alt="user"/>
</div>
<div class="team__name">
{{ employee.name }} {{ employee.last_name }}
<span>{{ employee.position }}</span>
</div>
</SwiperSlide>
</Swiper>
<div class="team__tools">
<div class="team__progress" ref="progressBar">
<span></span>
</div>
<router-link :to="{name: 'about'}" class="m--link">
Больше о нас
</router-link>
</div>
</div>
<div class="team">
<div class="team__header">
<h2 class="h2 team__title">Наша команда</h2>
<div class="team__description">
На IT волне команда профессионалов неутомимо трудится, чтобы дарить
слушателям самые свежие и актуальные новости из мира технологий,
отвечать на их вопросы и обсуждать горячие темы на IT радио.
</div>
</div>
<template v-if="showLoader">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<Swiper
v-else
:slides-per-view="4"
:space-between="20"
:modules="modules"
:pagination="{
el: '.team__progress',
clickable: true,
type: 'progressbar',
}"
:breakpoints="{
0: {
slidesPerView: 1,
},
450: {
slidesPerView: 1.5,
},
768: {
slidesPerView: 2.5,
},
1020: {
slidesPerView: 3,
},
1280: {
slidesPerView: 4,
},
}"
class="team__slider"
>
<SwiperSlide
class="team__item"
v-for="employee in team"
:key="employee.id"
>
<div class="team__cover">
<img :src="`${selfUrl + employee.img_person}`" alt="user" />
</div>
<div class="team__name">
{{ employee.name }} {{ employee.last_name }}
<span>{{ employee.position }}</span>
</div>
</SwiperSlide>
</Swiper>
<div class="team__tools">
<div class="team__progress" ref="progressBar">
<span></span>
</div>
<router-link :to="{ name: 'about' }" class="m--link">
Больше о нас
</router-link>
</div>
</div>
</template>
<script>
import 'swiper/css';
import {Swiper, SwiperSlide} from "swiper/vue";
import {Pagination, Scrollbar} from "swiper/modules";
import {app} from "@/services";
import {selfUrl} from '@/settings';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Pagination, Scrollbar } from 'swiper/modules';
import { app } from '@/services';
import { selfUrl } from '@/settings';
export default {
name: 'team',
components: {Swiper, SwiperSlide},
data() {
return {
selfUrl,
team: [],
showLoader: false,
modules: [Scrollbar, Pagination],
}
},
created() {
this.getTeams();
},
methods: {
getTeams() {
this.showLoader = true;
app.getTeams().then((data) => {
this.showLoader = false;
this.team = data;
}).catch(err => {
this.showLoader = false;
console.log(err)
})
}
}
}
name: 'team',
components: { Swiper, SwiperSlide },
data() {
return {
selfUrl,
team: [],
showLoader: false,
modules: [Scrollbar, Pagination],
};
},
created() {
this.getTeams();
},
methods: {
getTeams() {
this.showLoader = true;
app
.getTeams()
.then((data) => {
this.showLoader = false;
this.team = data;
})
.catch((err) => {
this.showLoader = false;
console.log(err);
});
},
},
};
</script>

View File

@ -1,7 +1,12 @@
import { route } from 'quasar/wrappers'
import store from '@/store'
import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
import routes from './routes'
import { route } from 'quasar/wrappers';
import store from '@/store';
import {
createRouter,
createMemoryHistory,
createWebHistory,
createWebHashHistory,
} from 'vue-router';
import routes from './routes';
/*
* If not building with SSR mode, you can
@ -13,50 +18,57 @@ import routes from './routes'
*/
export default route(function (/* { store, ssrContext } */) {
const createHistory = process.env.SERVER
? createMemoryHistory
: (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory)
const createHistory = process.env.SERVER
? createMemoryHistory
: process.env.VUE_ROUTER_MODE === 'history'
? createWebHistory
: createWebHashHistory;
const Router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
//document.getElementById('app').scrollIntoView({ behavior: 'smooth' });
//if (to.query.page) return;
return new Promise((resolve) => {
resolve({ left: 0, top: 0 });
})
}
},
routes,
linkActiveClass: 'is-subactive',
linkExactActiveClass: 'is-active',
const Router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else {
//document.getElementById('app').scrollIntoView({ behavior: 'smooth' });
//if (to.query.page) return;
return new Promise((resolve) => {
resolve({ left: 0, top: 0 });
});
}
},
routes,
linkActiveClass: 'is-subactive',
linkExactActiveClass: 'is-active',
// Leave this as is and make changes in quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode
// quasar.conf.js -> build -> publicPath
history: createHistory(process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE)
})
// Leave this as is and make changes in quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode
// quasar.conf.js -> build -> publicPath
history: createHistory(
process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE,
),
});
Router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth) && !process.env.SERVER) {
if (store.state.user && store.state.user?.id) {
next();
} else {
next({ name: 'home' });
this.$store.dispatch('setShowAuthModal', true);
}
} else {
next();
}
});
Router.beforeEach((to, from, next) => {
if (
to.matched.some((record) => record.meta.requiresAuth) &&
!process.env.SERVER
) {
if (store.state.user && store.state.user?.id) {
next();
} else {
next({ name: 'home' });
this.$store.dispatch('setShowAuthModal', true);
}
} else {
next();
}
});
Router.afterEach((to, from) => {
if (to.name !== from.name && to.name === 'page404' && from.name) {
if (!process.env.SERVER) window.history.replaceState({}, null, from.path);
}
});
Router.afterEach((to, from) => {
if (to.name !== from.name && to.name === 'page404' && from.name) {
if (!process.env.SERVER) window.history.replaceState({}, null, from.path);
}
});
return Router
})
return Router;
});

View File

@ -1,145 +1,145 @@
import home from "@/views/home.vue";
import rubric from "@/views/rubric.vue";
import playlists from "@/views/playlists.vue";
import support from "@/views/support.vue";
import contacts from "@/views/contacts.vue";
import podcasts from "@/views/podcasts.vue";
import about from "@/views/about.vue";
import profile from "@/views/profile.vue";
import playlist from "@/views/playlist.vue";
import playlistCreate from "@/views/playlist-edit.vue";
import home from '@/views/home.vue';
import rubric from '@/views/rubric.vue';
import playlists from '@/views/playlists.vue';
import support from '@/views/support.vue';
import contacts from '@/views/contacts.vue';
import podcasts from '@/views/podcasts.vue';
import about from '@/views/about.vue';
import profile from '@/views/profile.vue';
import playlist from '@/views/playlist.vue';
import playlistCreate from '@/views/playlist-edit.vue';
const routes = [
{
path: '/',
name: 'home',
component: home,
meta: {
title: 'Главная',
isAuth: false
},
{
path: '/',
name: 'home',
component: home,
meta: {
title: 'Главная',
isAuth: false,
},
{
path: '/about',
name: 'about',
component: about,
meta: {
title: 'О нас',
isAuth: false
},
},
{
path: '/about',
name: 'about',
component: about,
meta: {
title: 'О нас',
isAuth: false,
},
{
path: '/rubric',
name: 'rubric',
component: rubric,
meta: {
title: 'Рубрики',
isAuth: false
},
},
{
path: '/rubric',
name: 'rubric',
component: rubric,
meta: {
title: 'Рубрики',
isAuth: false,
},
{
path: '/playlists',
name: 'playlists',
component: playlists,
meta: {
title: 'Плейлисты',
isAuth: false
},
},
{
path: '/playlists',
name: 'playlists',
component: playlists,
meta: {
title: 'Плейлисты',
isAuth: false,
},
{
path: '/podcasts',
name: 'podcasts',
component: podcasts,
meta: {
title: 'Подкасты',
isAuth: false
},
},
{
path: '/podcasts',
name: 'podcasts',
component: podcasts,
meta: {
title: 'Подкасты',
isAuth: false,
},
{
path: '/support',
name: 'support',
component: support,
meta: {
title: 'Поддержка',
isAuth: false
},
},
{
path: '/support',
name: 'support',
component: support,
meta: {
title: 'Поддержка',
isAuth: false,
},
{
path: '/contacts',
name: 'contacts',
component: contacts,
meta: {
title: 'Контакты',
isAuth: false
},
},
{
path: '/contacts',
name: 'contacts',
component: contacts,
meta: {
title: 'Контакты',
isAuth: false,
},
{
path: '/profile',
name: 'profile',
component: profile,
meta: {
title: 'Личный кабинет',
isAuth: false
},
children: [
{
path: 'playlist/:id',
name: 'playlist',
component: playlist,
meta: {
title: 'Плейлист',
requiresAuth: true
},
props: true,
},
{
path: 'playlist-create/:id',
name: 'playlist-create',
component: playlistCreate,
meta: {
title: 'Плейлист',
requiresAuth: true
},
props: true,
},{
path: 'playlist-edit/:id',
name: 'playlist-edit',
component: playlistCreate,
meta: {
title: 'Плейлист',
requiresAuth: true
},
props: true,
},
]
},
{
path: '/profile',
name: 'profile',
component: profile,
meta: {
title: 'Личный кабинет',
isAuth: false,
},
children: [
{
path: 'playlist/:id',
name: 'playlist',
component: playlist,
meta: {
title: 'Плейлист',
requiresAuth: true,
},
props: true,
},
{
path: 'playlist-create/:id',
name: 'playlist-create',
component: playlistCreate,
meta: {
title: 'Плейлист',
requiresAuth: true,
},
props: true,
},
{
path: 'playlist-edit/:id',
name: 'playlist-edit',
component: playlistCreate,
meta: {
title: 'Плейлист',
requiresAuth: true,
},
props: true,
},
],
},
// {
// path: '/error500',
// name: 'page500',
// component: () => import('@/views/Page500.vue'),
// meta: {
// title: 'Ошибка 500',
// showSidebarAuth: true,
// },
// }, {
// path: '/error404',
// name: 'error404',
// component: () => import('@/views/Page404.vue'),
// meta: {
// title: 'Ошибка 404',
// showSidebarAuth: true,
// },
// }, {
// path: '/:catchAll(.*)*',
// name: 'page404',
// component: () => import('@/views/Page404.vue'),
// meta: {
// title: 'Ошибка 404',
// showSidebarAuth: true,
// },
// },
// {
// path: '/error500',
// name: 'page500',
// component: () => import('@/views/Page500.vue'),
// meta: {
// title: 'Ошибка 500',
// showSidebarAuth: true,
// },
// }, {
// path: '/error404',
// name: 'error404',
// component: () => import('@/views/Page404.vue'),
// meta: {
// title: 'Ошибка 404',
// showSidebarAuth: true,
// },
// }, {
// path: '/:catchAll(.*)*',
// name: 'page404',
// component: () => import('@/views/Page404.vue'),
// meta: {
// title: 'Ошибка 404',
// showSidebarAuth: true,
// },
// },
];
export default routes
export default routes;

View File

@ -1,173 +1,216 @@
import {urlPath as settings} from '@/settings';
import {REST, RESTError} from './rest';
import { urlPath as settings } from '@/settings';
import { REST, RESTError } from './rest';
export default class extends REST {
static get settings() {
return settings;
}
static user(params) {
return this._get(`user`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static loginUser(params) {
return this._post(`token`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static createUser(params) {
return this._post(`user/create_user`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static get settings() {
return settings;
}
static user(params) {
return this._get(`user`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static loginUser(params) {
return this._post(`token`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static createUser(params) {
return this._post(`user/create_user`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static updateUser(params) {
return this._post(`user/update_user`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static updateUser(params) {
return this._post(`user/update_user`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Не удалось создать пользователя');
});
}
static getTeams(station, params) {
return this._get(`radio/teams`, params, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении команды');
});
}
static getTeams(station, params) {
return this._get(`radio/teams`, params, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении команды');
});
}
static getCheckFavoriteSong(id){
return this._get(`radio/song/check_is_favorite/${id}`, {}, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при проверке песни');
});
}
static getAllSong(){
return this._get(`radio/song/get_all_song`, {}, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получениии всех песен');
});
}
static getAudio(id){
return this._get(`radio/song/get_audio/${id}`, {}, {}, false, true).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получениии песни');
});
}
static createFavoriteForUser(params){
return this._post(`radio/song/add_favorite`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getCheckFavoriteSong(id) {
return this._get(`radio/song/check_is_favorite/${id}`, {}, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при проверке песни');
});
}
static getAllSong() {
return this._get(`radio/song/get_all_song`, {}, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получениии всех песен');
});
}
static getAudio(id) {
return this._get(`radio/song/get_audio/${id}`, {}, {}, false, true)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получениии песни');
});
}
static createFavoriteForUser(params) {
return this._post(`radio/song/add_favorite`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static removeFavoriteForUser(params){
return this._post(`radio/song/delete_song`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static removeFavoriteForUser(params) {
return this._post(`radio/song/delete_song`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getFavoriteList(params){
return this._get(`radio/song`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getRubriks() {
return this._get(`radio/rubriks`, {}, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении рубрик');
});
}
static getRubrik(id) {
return this._get(`radio/rubriks/${id}`, {}, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении рубрик');
});
}
static getFavoriteList(params) {
return this._get(`radio/song`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getRubriks() {
return this._get(`radio/rubriks`, {}, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении рубрик');
});
}
static getRubrik(id) {
return this._get(`radio/rubriks/${id}`, {}, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении рубрик');
});
}
static removeFavorites(params) {
return this._post(`radio/song/delete_song`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении рубрик');
});
}
static removeFavorites(params) {
return this._post(`radio/song/delete_song`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении рубрик');
});
}
static getPlaylists() {
return this._get(`radio/playlists`, {}, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getPlaylist(id) {
return this._get(`radio/playlists/${id}`, {}, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getPlaylists() {
return this._get(`radio/playlists`, {}, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getPlaylist(id) {
return this._get(`radio/playlists/${id}`, {}, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static addSongToPlaylist(params) {
return this._post(`radio/playlists/add_to_playlist`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static removeSongToPlaylist(params) {
return this._post(`radio/playlists/delete_song_with_playlist`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при удаления треков из плейлиста');
});
}
static updatePlaylist(params) {
return this._post(`radio/playlists/update_playlist`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при удаления треков из плейлиста');
});
}
static addSongToPlaylist(params) {
return this._post(`radio/playlists/add_to_playlist`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static removeSongToPlaylist(params) {
return this._post(`radio/playlists/delete_song_with_playlist`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при удаления треков из плейлиста');
});
}
static updatePlaylist(params) {
return this._post(`radio/playlists/update_playlist`, {}, params)
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при удаления треков из плейлиста');
});
}
static createPlaylists() {
return this._post(`radio/playlists/create_playlist`, {}, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static createPlaylists() {
return this._post(`radio/playlists/create_playlist`, {}, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getNews(station, params) {
return this._get(`radio.mp3`, params, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getProfiles(station, params) {
return this._get(`radio.mp3`, params, {}).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getNews(station, params) {
return this._get(`radio.mp3`, params, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static getProfiles(station, params) {
return this._get(`radio.mp3`, params, {})
.then((data) => {
return data;
})
.catch((error) => {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
}

View File

@ -1,6 +1,5 @@
import { urlPathAudio as settings } from '@/settings';
import { urlPathAudio as settings, urlPathAudio } from '@/settings';
import { REST, RESTError } from './rest';
import { urlPathAudio } from '@/settings';
export default class extends REST {
static get settings() {

View File

@ -4,88 +4,115 @@ import store from '@/store';
import cache from '@/utils/cache';
class RESTError extends Error {
constructor(error, message, params={}) {
let detail = error.response && error.response.data && (error.response.data.detail || error.response.data.error && error.response.data.error.detail);
let header = (message || error.message) + (detail ? ': ' + detail : '');
super(header);
constructor(error, message, params = {}) {
let detail =
error.response &&
error.response.data &&
(error.response.data.detail ||
(error.response.data.error && error.response.data.error.detail));
let header = (message || error.message) + (detail ? ': ' + detail : '');
super(header);
this.name = this.constructor.name;
this.parent = error;
this.detail = detail;
this.response = error.response;
for (let k in params) {
this[k] = params[k];
}
//if (this.response && (this.response.status === 401 || this.response.status === 403)) {
if (this.response && (this.response.status === 401)) {
store.dispatch('deathUser');
store.dispatch('setShowAuthModal', true);
} else {
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = (new Error(header)).stack;
}
}
this.name = this.constructor.name;
this.parent = error;
this.detail = detail;
this.response = error.response;
for (let k in params) {
this[k] = params[k];
}
//if (this.response && (this.response.status === 401 || this.response.status === 403)) {
if (this.response && this.response.status === 401) {
store.dispatch('deathUser');
store.dispatch('setShowAuthModal', true);
} else {
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = new Error(header).stack;
}
}
}
}
class REST {
static get settings() {
throw new Error('settings must be overridden');
}
static _get(url, params={}, extraParams, use_cache=false, isBlob=false) {
return this._request('get', url, params, {}, {}, extraParams, use_cache, isBlob);
}
static _post(url, params, data) {
return this._request('post', url, params, data);
}
static _put(url, params, data) {
return this._request('put', url, params, data);
}
static _patch(url, params, data) {
return this._request('patch', url, params, data);
}
static _delete(url, params, data) {
return this._request('delete', url, params, data);
}
static _request(method, url, params={}, data={}, extraData={}, extraParams={}, use_cache=false, isBlob=false) {
let cache_key = null;
return ajax.request({
method,
url: `${this.settings}${url ? '/' : ''}${url}/`,
params,
data,
extraData,
extraParams,
headers: this._getAuthHeaders(),
responseType: this._getResponseType(isBlob),
}).then((response) => {
if (cache_key) {
cache.set(cache_key, response.data);
}
return response.data;
});
}
static _getResponseType(value){
if (value) {
return 'arraybuffer'
static get settings() {
throw new Error('settings must be overridden');
}
static _get(
url,
params = {},
extraParams,
use_cache = false,
isBlob = false,
) {
return this._request(
'get',
url,
params,
{},
{},
extraParams,
use_cache,
isBlob,
);
}
static _post(url, params, data) {
return this._request('post', url, params, data);
}
static _put(url, params, data) {
return this._request('put', url, params, data);
}
static _patch(url, params, data) {
return this._request('patch', url, params, data);
}
static _delete(url, params, data) {
return this._request('delete', url, params, data);
}
static _request(
method,
url,
params = {},
data = {},
extraData = {},
extraParams = {},
use_cache = false,
isBlob = false,
) {
let cache_key = null;
return ajax
.request({
method,
url: `${this.settings}${url ? '/' : ''}${url}/`,
params,
data,
extraData,
extraParams,
headers: this._getAuthHeaders(),
responseType: this._getResponseType(isBlob),
})
.then((response) => {
if (cache_key) {
cache.set(cache_key, response.data);
}
return response.data;
});
}
static _getResponseType(value) {
if (value) {
return 'arraybuffer';
}
static _getAuthHeaders() {
if (store.state.token) {
return { 'Authorization': `Bearer ${store.state.token}` };
}
}
static _cancelToken() {
return ajax.cancelToken();
}
static _getAuthHeaders() {
if (store.state.token) {
return { Authorization: `Bearer ${store.state.token}` };
}
}
static _cancelToken() {
return ajax.cancelToken();
}
}
export default REST;
export {
RESTError,
REST
};
export { RESTError, REST };

View File

@ -1,53 +1,45 @@
//throw new Error('Settings module must be replaced depending on mode');
const ajax = {
timeout: process.env.AJAX_TIMEOUT,
responseType: process.env.AJAX_RESPONSE_TYPE,
responseEncoding: process.env.AJAX_ENCODING
timeout: process.env.AJAX_TIMEOUT,
responseType: process.env.AJAX_RESPONSE_TYPE,
responseEncoding: process.env.AJAX_ENCODING,
};
const cache = {
storage: process.env.CACHE_STORAGE
storage: process.env.CACHE_STORAGE,
};
const serviceUrl = {
selfUrl: process.env.SERVICE_SELF_URL,
url: process.env.SERVICE_URL,
protocol: process.env.SERVICE_PROTOCOL,
port: process.env.SERVICE_PORT,
api: process.env.SERVICE_API,
apiAudio: process.env.SERVICE_URL_AUDIO,
localPath: '//localhost',
onLocal: (process.env.SERVICE_ON_LOCAL === 'true')
}
selfUrl: process.env.SERVICE_SELF_URL,
url: process.env.SERVICE_URL,
protocol: process.env.SERVICE_PROTOCOL,
port: process.env.SERVICE_PORT,
api: process.env.SERVICE_API,
apiAudio: process.env.SERVICE_URL_AUDIO,
localPath: '//localhost',
onLocal: process.env.SERVICE_ON_LOCAL === 'true',
};
let urlPath = `${serviceUrl.protocol}:${serviceUrl.url}${serviceUrl.api}`;
let urlPathAudio = `${serviceUrl.protocol}:${serviceUrl.apiAudio}`;
if (process.env.CLIENT) {
if (serviceUrl.onLocal || window.location.hostname === 'localhost') {
urlPath = `${serviceUrl.localPath}:${serviceUrl.port}${serviceUrl.api}`;
}
if (serviceUrl.onLocal || window.location.hostname === 'localhost') {
urlPath = `${serviceUrl.localPath}:${serviceUrl.port}${serviceUrl.api}`;
}
}
let selfUrl = `${serviceUrl.protocol}:${serviceUrl.url}`
let selfUrl = `${serviceUrl.protocol}:${serviceUrl.url}`;
let selfPath = `${serviceUrl.protocol}:${serviceUrl.selfUrl}`;
const robotsTxt = {
filePath: '/robots.txt',
host: selfPath,
policy: [
{
userAgent: process.env.ROBOTS_USER_AGENT,
allow: JSON.parse(process.env.ROBOTS_ALLOW || null),
disallow: JSON.parse(process.env.ROBOTS_DISALLOW || null),
}
]
filePath: '/robots.txt',
host: selfPath,
policy: [
{
userAgent: process.env.ROBOTS_USER_AGENT,
allow: JSON.parse(process.env.ROBOTS_ALLOW || null),
disallow: JSON.parse(process.env.ROBOTS_DISALLOW || null),
},
],
};
export {
selfUrl,
ajax,
cache,
urlPath,
urlPathAudio,
selfPath,
robotsTxt,
};
export { selfUrl, ajax, cache, urlPath, urlPathAudio, selfPath, robotsTxt };

View File

@ -1,144 +1,143 @@
import {createStore} from 'vuex'
import { createStore } from 'vuex';
import VuexPersist from 'vuex-persist';
const vuexPersist = new VuexPersist({
key: 'it-radio',
//storage: window.localStorage
key: 'it-radio',
//storage: window.localStorage
});
// Vue.use(Vuex);
export default createStore({
state() {
return {
token: null,
refreshToken: null,
user: null,
modal:{
auth: false,
changingUser: false
},
showAuthModal: false,
station: {
id: 1
},
currentPlay: {
isPlay: false,
isLoader: false,
live: true,
volume: 50,
currentIndex: null,
},
player: {
target: null,
},
userFavorite: {
podcast: [],
playlist: [],
songs: []
}
}
state() {
return {
token: null,
refreshToken: null,
user: null,
modal: {
auth: false,
changingUser: false,
},
showAuthModal: false,
station: {
id: 1,
},
currentPlay: {
isPlay: false,
isLoader: false,
live: true,
volume: 50,
currentIndex: null,
},
player: {
target: null,
},
userFavorite: {
podcast: [],
playlist: [],
songs: [],
},
};
},
plugins: [vuexPersist.plugin],
mutations: {
user(state, user) {
state.user = user;
},
plugins: [vuexPersist.plugin],
mutations: {
user(state, user) {
state.user = user;
},
updateToken(state, tokens) {
state.token = tokens.access;
state.refreshToken = tokens.refresh;
},
removeToken(state) {
state.token = null;
state.refreshToken = null;
},
setCurrentPlay(state, song) {
state.currentPlay = song;
},
setModal(state, show) {
state.modal = {...state.modal, ...show}
},
setPlayer(state, params) {
state.player = {...state.player, ...params}
},
initPlayer(state) {
state.player.target = document.createElement('audio')
state.player.target.src = '';
state.player.target.preload = 'auto';
state.player.target.controls = true;
state.player.target.volume = 0.5;
console.log('initPlayer', state.player.target)
},
changePlayer(state, params) {
const awaitPlay = () => {
if (state.player.target.readyState >= 4) {
if (state.currentPlay.isPlay){
state.player.target.play();
}
state.currentPlay.isLoader = false;
state.player.target.removeEventListener('canplaythrough', awaitPlay);
} else {
awaitPlay();
}
}
state.player.target.src = params;
state.player.src = params;
console.log(state.player.target.src)
// state.currentPlay.isLoader = true;
state.player.target.addEventListener('canplaythrough', awaitPlay)
},
handlerPlayer(state, params) {
if (params.pause) {
state.currentPlay.isPlay = false;
state.player.target.pause();
}
if (params.play) {
if (state.player.target.readyState >= 3){
state.currentPlay.isPlay = true;
state.player.target.play();
}
}
if (params.volume) {
state.player.target.volume = params.volume;
}
},
setUserFavorite(state, params) {
state.userFavorite = {...state.userFavorite, ...params}
}
updateToken(state, tokens) {
state.token = tokens.access;
state.refreshToken = tokens.refresh;
},
actions: {
setToken(context, tokens) {
context.commit('updateToken', tokens);
},
setUser(context, user) {
context.commit('user', user);
},
deathUser(context) {
context.commit('user', {});
context.commit('removeToken');
},
setCurrentPlay(context, song) {
context.commit('setCurrentPlay', song);
},
setModal(context, show) {
context.commit('setModal', show);
},
setPlayer(context, params) {
context.commit('setPlayer', params);
},
initPlayer(context) {
context.commit('initPlayer');
},
handlerPlayer(context, params) {
context.commit('handlerPlayer', params);
},
changePlayer(context, params) {
context.commit('changePlayer', params);
},
setUserFavorite(context, params) {
context.commit('setUserFavorite', params);
},
}
removeToken(state) {
state.token = null;
state.refreshToken = null;
},
setCurrentPlay(state, song) {
state.currentPlay = song;
},
setModal(state, show) {
state.modal = { ...state.modal, ...show };
},
setPlayer(state, params) {
state.player = { ...state.player, ...params };
},
initPlayer(state) {
state.player.target = document.createElement('audio');
state.player.target.src = '';
state.player.target.preload = 'auto';
state.player.target.controls = true;
state.player.target.volume = 0.5;
console.log('initPlayer', state.player.target);
},
changePlayer(state, params) {
const awaitPlay = () => {
if (state.player.target.readyState >= 4) {
if (state.currentPlay.isPlay) {
state.player.target.play();
}
state.currentPlay.isLoader = false;
state.player.target.removeEventListener('canplaythrough', awaitPlay);
} else {
awaitPlay();
}
};
state.player.target.src = params;
state.player.src = params;
console.log(state.player.target.src);
// state.currentPlay.isLoader = true;
state.player.target.addEventListener('canplaythrough', awaitPlay);
},
handlerPlayer(state, params) {
if (params.pause) {
state.currentPlay.isPlay = false;
state.player.target.pause();
}
if (params.play) {
if (state.player.target.readyState >= 3) {
state.currentPlay.isPlay = true;
state.player.target.play();
}
}
if (params.volume) {
state.player.target.volume = params.volume;
}
},
setUserFavorite(state, params) {
state.userFavorite = { ...state.userFavorite, ...params };
},
},
actions: {
setToken(context, tokens) {
context.commit('updateToken', tokens);
},
setUser(context, user) {
context.commit('user', user);
},
deathUser(context) {
context.commit('user', {});
context.commit('removeToken');
},
setCurrentPlay(context, song) {
context.commit('setCurrentPlay', song);
},
setModal(context, show) {
context.commit('setModal', show);
},
setPlayer(context, params) {
context.commit('setPlayer', params);
},
initPlayer(context) {
context.commit('initPlayer');
},
handlerPlayer(context, params) {
context.commit('handlerPlayer', params);
},
changePlayer(context, params) {
context.commit('changePlayer', params);
},
setUserFavorite(context, params) {
context.commit('setUserFavorite', params);
},
},
});

View File

@ -1,2 +1 @@
export function someAction (/* context */) {
}
export function someAction(/* context */) {}

View File

@ -1,2 +1 @@
export function someGetter (/* state */) {
}
export function someGetter(/* state */) {}

View File

@ -1,12 +1,12 @@
import state from './state'
import * as getters from './getters'
import * as mutations from './mutations'
import * as actions from './actions'
import state from './state';
import * as getters from './getters';
import * as mutations from './mutations';
import * as actions from './actions';
export default {
namespaced: true,
getters,
mutations,
actions,
state
}
state,
};

View File

@ -1,2 +1 @@
export function someMutation (/* state */) {
}
export function someMutation(/* state */) {}

View File

@ -1,5 +1,5 @@
export default function () {
return {
//
}
};
}

View File

@ -3,88 +3,91 @@ import axios from 'axios';
import { ajax as settings } from '@/settings';
export default class {
static get(params) {
return this.request(_defaults({ method: 'get' }, params));
static get(params) {
return this.request(_defaults({ method: 'get' }, params));
}
static post(params) {
return this.request(_defaults({ method: 'post' }, params));
}
static put(params) {
return this.request(_defaults({ method: 'put' }, params));
}
static patch(params) {
return this.request(_defaults({ method: 'patch' }, params));
}
static delete(params) {
return this.request(_defaults({ method: 'delete' }, params));
}
static request(params) {
if (params.extraData) {
params.data = this.__append_extra_data(params.data, params.extraData);
delete params.extraData;
}
static post(params) {
return this.request(_defaults({ method: 'post' }, params));
if (params.extraParams) {
params.params = this.__append_extra_params(
params.params,
params.extraParams,
);
delete params.extraParams;
}
static put(params) {
return this.request(_defaults({ method: 'put' }, params));
}
static patch(params) {
return this.request(_defaults({ method: 'patch' }, params));
}
static delete(params) {
return this.request(_defaults({ method: 'delete' }, params));
}
static request(params) {
if (params.extraData) {
params.data = this.__append_extra_data(params.data, params.extraData);
delete params.extraData;
}
if (params.extraParams) {
params.params = this.__append_extra_params(params.params, params.extraParams);
delete params.extraParams;
}
/*
/*
if (params.cancel) {
params.cancelToken = this.CancelToken(params.cancel);
delete params.cancel;
}
*/
return axios.request(_defaults({}, params, this.settings));
}
/*
return axios.request(_defaults({}, params, this.settings));
}
/*
static cancelToken() {
return axios.CancelToken.source();
}
*/
static getUri(params) {
return axios.getUri(params);
}
static __append_extra_data(data, extra) {
data = data || {};
static getUri(params) {
return axios.getUri(params);
}
static __append_extra_data(data, extra) {
data = data || {};
if (process.env.CLIENT && data instanceof FormData) {
for (let k in extra) {
data.append(k, extra[k]);
}
} else if (data instanceof URLSearchParams) {
for (let k in extra) {
data.append(k, extra[k]);
}
} else if (typeof data === 'string') {
for (let k in extra) {
if (data !== '') data += '&';
data += encodeURIComponent(k) + '=' + encodeURIComponent(data[k]);
}
} else if (typeof data === 'object') {
for (let k in extra) {
data[k] = extra[k];
}
} else {
throw new Error('Can\'t append extra data to this type of data');
}
return data;
if (process.env.CLIENT && data instanceof FormData) {
for (let k in extra) {
data.append(k, extra[k]);
}
} else if (data instanceof URLSearchParams) {
for (let k in extra) {
data.append(k, extra[k]);
}
} else if (typeof data === 'string') {
for (let k in extra) {
if (data !== '') data += '&';
data += encodeURIComponent(k) + '=' + encodeURIComponent(data[k]);
}
} else if (typeof data === 'object') {
for (let k in extra) {
data[k] = extra[k];
}
} else {
throw new Error("Can't append extra data to this type of data");
}
static __append_extra_params(data, extra) {
data = data || {};
return data;
}
static __append_extra_params(data, extra) {
data = data || {};
if (data instanceof URLSearchParams) {
for (let k in extra) {
data.append(k, extra[k]);
}
} else if (typeof data === 'object') {
for (let k in extra) {
data[k] = extra[k];
}
} else {
throw new Error('Can\'t append extra params to this type of params');
}
return data;
}
static get settings() {
return settings;
if (data instanceof URLSearchParams) {
for (let k in extra) {
data.append(k, extra[k]);
}
} else if (typeof data === 'object') {
for (let k in extra) {
data[k] = extra[k];
}
} else {
throw new Error("Can't append extra params to this type of params");
}
return data;
}
static get settings() {
return settings;
}
}

View File

@ -2,74 +2,71 @@ import _keys from 'lodash/keys';
import { cache as settings } from '@/settings';
class Converter {
static encode(value) {
return this.__isComplex(value) ? JSON.stringify(value) : value;
}
static decode(value) {
return this.__isJSON(value) ? JSON.parse(value) : value;
}
static __isComplex(value) {
return (value instanceof Array || typeof value === 'object');
}
static __isJSON(value) {
return (typeof value === 'string' && /^(\{|\[)/.test(value));
}
static encode(value) {
return this.__isComplex(value) ? JSON.stringify(value) : value;
}
static decode(value) {
return this.__isJSON(value) ? JSON.parse(value) : value;
}
static __isComplex(value) {
return value instanceof Array || typeof value === 'object';
}
static __isJSON(value) {
return typeof value === 'string' && /^(\{|\[)/.test(value);
}
}
class TempStorage {
constructor() {
this.__data = {};
}
getItem(key) {
return this.__data[key];
}
setItem(key, value) {
this.__data[key] = value;
}
removeItem(key) {
delete this.__data[key];
}
clear() {
this.__data = {};
}
get length() {
return _keys(this.__data).length;
}
constructor() {
this.__data = {};
}
getItem(key) {
return this.__data[key];
}
setItem(key, value) {
this.__data[key] = value;
}
removeItem(key) {
delete this.__data[key];
}
clear() {
this.__data = {};
}
get length() {
return _keys(this.__data).length;
}
}
class Cache {
constructor(storage) {
if (storage === 'tempStorage') {
this._storage = new TempStorage();
} else {
if (!(storage in window)) {
throw new Error(`Storage ${storage} is not supported`);
}
this._storage = window[storage];
}
constructor(storage) {
if (storage === 'tempStorage') {
this._storage = new TempStorage();
} else {
if (!(storage in window)) {
throw new Error(`Storage ${storage} is not supported`);
}
this._storage = window[storage];
}
get(key) {
return Converter.decode(this._storage.getItem(key));
}
set(key, value) {
this._storage.setItem(key, Converter.encode(value));
}
remove(key) {
this._storage.removeItem(key);
}
clear() {
this._storage.clear();
}
key(ns, type, data) {
let key = ns + ':' + type;
if (data) {
key += ':' + JSON.stringify(data, _keys(data).sort());
}
return key;
}
get(key) {
return Converter.decode(this._storage.getItem(key));
}
set(key, value) {
this._storage.setItem(key, Converter.encode(value));
}
remove(key) {
this._storage.removeItem(key);
}
clear() {
this._storage.clear();
}
key(ns, type, data) {
let key = ns + ':' + type;
if (data) {
key += ':' + JSON.stringify(data, _keys(data).sort());
}
return key;
}
}
export default new Cache(settings.storage);

View File

@ -1,25 +1,20 @@
const helpers = {
range: (start, end, step = 1, toFixed = null) => {
let arr = []
range: (start, end, step = 1, toFixed = null) => {
let arr = [];
while(start <= end) {
if (toFixed)
start = Number(start.toFixed(toFixed))
arr.push(start)
start += step
}
return arr
},
}
while (start <= end) {
if (toFixed) start = Number(start.toFixed(toFixed));
arr.push(start);
start += step;
}
return arr;
},
};
export default {
install (app) {
app.helpers = helpers
app.config.globalProperties.$helpers = helpers
}
}
export {
helpers
}
install(app) {
app.helpers = helpers;
app.config.globalProperties.$helpers = helpers;
},
};
export { helpers };

View File

@ -1,61 +1,54 @@
<template>
<div class="app__main m--error-404">
<div
:class="['page404', this.user?.id? 'auth': null]"
>
<div :class="['container']">
<div class="page404__block">
<div
class="page404__info"
>
<div class="page404__info-title">
404
</div>
<div class="page404__info-subtitle">
Мы не можем найти то, что вы ищете
</div>
<div class="page404__info-content">
Возможно, запрашиваемая вами страница была перенесена или удалена. Также возможно, что вы допустили небольшую опечатку при вводе адреса такое случается даже с нами, поэтому еще раз внимательно проверьте.
</div>
<div class="page404__info-bottom">
Переходите на главную страницу, там вы сможете найти много полезной информации!
</div>
<div class="page404__info-button">
<button
class="button button-blue"
@click="next()"
>
На главную
</button>
</div>
</div>
</div>
<div class="app__main m--error-404">
<div :class="['page404', this.user?.id ? 'auth' : null]">
<div :class="['container']">
<div class="page404__block">
<div class="page404__info">
<div class="page404__info-title">404</div>
<div class="page404__info-subtitle">
Мы не можем найти то, что вы ищете
</div>
<div class="page404__info-content">
Возможно, запрашиваемая вами страница была перенесена или удалена.
Также возможно, что вы допустили небольшую опечатку при вводе
адреса такое случается даже с нами, поэтому еще раз внимательно
проверьте.
</div>
<div class="page404__info-bottom">
Переходите на главную страницу, там вы сможете найти много
полезной информации!
</div>
<div class="page404__info-button">
<button class="button button-blue" @click="next()">
На главную
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Page404',
components: {
},
data() {
return {
}
},
computed: {
user() {
return this.$store.state.user;
},
},
mounted() {
console.log(this.user)
},
methods: {
next() {
this.$router.push({ name: 'home' });
}
},
}
export default {
name: 'Page404',
components: {},
data() {
return {};
},
computed: {
user() {
return this.$store.state.user;
},
},
mounted() {
console.log(this.user);
},
methods: {
next() {
this.$router.push({ name: 'home' });
},
},
};
</script>

View File

@ -1,60 +1,47 @@
<template>
<div class="app__main m--error-500">
<div
:class="['page500']"
>
<div :class="['container']">
<div class="page500__block">
<div
class="page500__info"
>
<div class="page500__info-title">
Упс!
</div>
<div class="page500__info-subtitle">
Что то пошло не так!
</div>
<div class="page500__info-content">
Мы уже знаем об этом и делаем все возможное!
</div>
<div class="page500__info-bottom">
Переходите на главную страницу, там вы сможете найти много полезной информации!
</div>
<div class="page500__info-button">
<button
class="button button-blue"
@click="next()"
>
На главную
</button>
</div>
</div>
</div>
<div class="app__main m--error-500">
<div :class="['page500']">
<div :class="['container']">
<div class="page500__block">
<div class="page500__info">
<div class="page500__info-title">Упс!</div>
<div class="page500__info-subtitle">Что то пошло не так!</div>
<div class="page500__info-content">
Мы уже знаем об этом и делаем все возможное!
</div>
<div class="page500__info-bottom">
Переходите на главную страницу, там вы сможете найти много
полезной информации!
</div>
<div class="page500__info-button">
<button class="button button-blue" @click="next()">
На главную
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Page404',
components: {
},
data() {
return {
}
},
computed: {
user() {
return this.$store.state.user;
},
},
mounted() {
},
methods: {
next() {
this.$router.push({ name: 'home' });
}
},
}
export default {
name: 'Page404',
components: {},
data() {
return {};
},
computed: {
user() {
return this.$store.state.user;
},
},
mounted() {},
methods: {
next() {
this.$router.push({ name: 'home' });
},
},
};
</script>

View File

@ -1,103 +1,113 @@
<template>
<div class="about">
<div class="app__content">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'О нас', route: { name: 'about' } },
]"
/>
<div class="about__header">
<div class="about__header-top">
<div class="about__header-left">
<h1 class="h2">О нас</h1>
<div class="text about__header-description">IT-радио это не просто обычная радиостанция, мы ваши
партнеры в творчестве и современных технологиях.
</div>
</div>
<div class="about__header-right">
</div>
</div>
<div class="text about__header-bottom">
Наша миссия воплотить ваши мечты в реальность, шаг за шагом. Благодаря разнообразной команде ведущих, журналистов, разработчиков и новаторов, мы постоянно расширяем границы возможного в цифровом мире.
</div>
</div>
<div class="about__description">
<h2 class="h2">Мы здесь, чтобы открыть глаза на мир IT</h2>
<div class="about__description-info">
<div class="text about__description-item m--left">
IT-радио это уникальный проект, который объединяет в себе самых ярких представителей IT-индустрии, а также экспертов из различных областей, чтобы поделиться своими знаниями и опытом с широкой аудиторией.
</div>
<div class="text about__description-item">
Мы команда, которая верит в силу теплой улыбки и дружеской беседы.
</div>
</div>
</div>
<video class="about__video" playsinline="" autoplay="" loop="" muted="">
<source src="@/assets/videos/about.mp4" type="video/mp4">
</video>
<div class="about__description">
<div class="about__description-info">
<div class="text about__description-item m--left">
Основанное с целью переосмыслить радио через призму современного и инновационного подхода, мы стали больше, чем просто радиостанцией, мы сообщество родственных душ, которые разделяют страсть к артистизму, развитию и инновациям.
</div>
<div class="text about__description-item">
Каждое шоу на IT-радио включает в себя актуальные темы, новости, обзоры, интервью с экспертами и многое другое.
</div>
</div>
</div>
</div>
<div class="about__gallery">
<div class="about__gallery-item m--gallery-item-one">
</div>
<div class="about__gallery-item m--gallery-item-two">
</div>
<div class="about__gallery-item m--gallery-item-three">
</div>
</div>
<Team/>
<div class="app__content">
<div class="about__history">
<div class="about__history-header">
<h2 class="h2 about__history-title">История радиостанции</h2>
<div class="title about__history-date">Дата</div>
</div>
<div class="about__history-list">
<div class="about__history-item">
<div class="title m--white about__history-title">Событие кратко 1</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
<div class="about__history-item">
<div class="title m--white about__history-title">Событие кратко 2</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
<div class="about__history-item">
<div class="title m--white about__history-title">Событие кратко 3</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
<div class="about__history-item">
<div class="title m--white about__history-title">Событие кратко 4</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
</div>
</div>
<SupportBlock/>
</div>
</div>
<div class="about">
<div class="app__content">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'О нас', route: { name: 'about' } },
]"
/>
<div class="about__header">
<div class="about__header-top">
<div class="about__header-left">
<h1 class="h2">О нас</h1>
<div class="text about__header-description">
IT-радио это не просто обычная радиостанция, мы ваши партнеры в
творчестве и современных технологиях.
</div>
</div>
<div class="about__header-right"></div>
</div>
<div class="text about__header-bottom">
Наша миссия воплотить ваши мечты в реальность, шаг за шагом.
Благодаря разнообразной команде ведущих, журналистов, разработчиков и
новаторов, мы постоянно расширяем границы возможного в цифровом мире.
</div>
</div>
<div class="about__description">
<h2 class="h2">Мы здесь, чтобы открыть глаза на мир IT</h2>
<div class="about__description-info">
<div class="text about__description-item m--left">
IT-радио это уникальный проект, который объединяет в себе самых
ярких представителей IT-индустрии, а также экспертов из различных
областей, чтобы поделиться своими знаниями и опытом с широкой
аудиторией.
</div>
<div class="text about__description-item">
Мы команда, которая верит в силу теплой улыбки и дружеской беседы.
</div>
</div>
</div>
<video class="about__video" playsinline="" autoplay="" loop="" muted="">
<source src="@/assets/videos/about.mp4" type="video/mp4" />
</video>
<div class="about__description">
<div class="about__description-info">
<div class="text about__description-item m--left">
Основанное с целью переосмыслить радио через призму современного и
инновационного подхода, мы стали больше, чем просто радиостанцией,
мы сообщество родственных душ, которые разделяют страсть к
артистизму, развитию и инновациям.
</div>
<div class="text about__description-item">
Каждое шоу на IT-радио включает в себя актуальные темы, новости,
обзоры, интервью с экспертами и многое другое.
</div>
</div>
</div>
</div>
<div class="about__gallery">
<div class="about__gallery-item m--gallery-item-one"></div>
<div class="about__gallery-item m--gallery-item-two"></div>
<div class="about__gallery-item m--gallery-item-three"></div>
</div>
<Team />
<div class="app__content">
<div class="about__history">
<div class="about__history-header">
<h2 class="h2 about__history-title">История радиостанции</h2>
<div class="title about__history-date">Дата</div>
</div>
<div class="about__history-list">
<div class="about__history-item">
<div class="title m--white about__history-title">
Событие кратко 1
</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
<div class="about__history-item">
<div class="title m--white about__history-title">
Событие кратко 2
</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
<div class="about__history-item">
<div class="title m--white about__history-title">
Событие кратко 3
</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
<div class="about__history-item">
<div class="title m--white about__history-title">
Событие кратко 4
</div>
<div class="about__history-date">Ноябрь 2023</div>
</div>
</div>
</div>
<SupportBlock />
</div>
</div>
</template>
<script>
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
import Team from "@/components/team.vue";
import SupportBlock from "@/components/support-block.vue";
import AppBreadcrumbs from '@/components/app-breadcrumbs.vue';
import Team from '@/components/team.vue';
import SupportBlock from '@/components/support-block.vue';
export default {
name: 'about',
components: {SupportBlock, Team, AppBreadcrumbs}
}
name: 'about',
components: { SupportBlock, Team, AppBreadcrumbs },
};
</script>

View File

@ -1,112 +1,131 @@
<template>
<div class="app__content contacts">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Контакты', route: { name: 'contacts' } },
]"
/>
<h1 class="h2">Контакты</h1>
<div class="contacts__content">
<div class="contacts__info">
<div class="text contacts__item">
<span class="title">Телефон</span>
+7 (900) 000-00-00
</div>
<div class="text contacts__item">
<span class="title">Почта</span>
it-radio@info.org
</div>
<div class="text contacts__item">
<span class="title">Адрес</span>
г. Челябинск, Адрес
</div>
<div class="text contacts__item">
<span class="title">Соц. сети</span>
<div class="contacts__social">
<div class="contacts__social m--telegram"></div>
<div class="contacts__social m--vk"></div>
</div>
</div>
</div>
<div class="contacts__map">
<div class="contacts__map-frame" style="position:relative;overflow:hidden;"><a href="https://yandex.ru/maps/56/chelyabinsk/?utm_medium=mapframe&utm_source=maps" style="color:#eee;font-size:12px;position:absolute;top:0px;">Челябинск</a><a href="https://yandex.ru/maps/geo/chelyabinsk/53159527/?ll=61.421984%2C55.159071&utm_medium=mapframe&utm_source=maps&z=14.04" style="color:#eee;font-size:12px;position:absolute;top:14px;">Челябинск Яндекс Карты</a><iframe src="https://yandex.ru/map-widget/v1/?ll=61.421984%2C55.159071&mode=poi&poi%5Bpoint%5D=61.399655%2C55.160475&poi%5Buri%5D=ymapsbm1%3A%2F%2Fgeo%3Fdata%3DCgg1MzE1OTUyNxIg0KDQvtGB0YHQuNGPLCDQp9C10LvRj9Cx0LjQvdGB0LoiCg04nHVCFb2jXEI%2C&z=14.04" width="100%" height="100%" frameborder="1" allowfullscreen="true" style="position:relative;"></iframe></div> </div>
<FormKit
v-model="formData"
type="form"
data-loading="showLoaderSending"
form-class="$reset contacts__form form"
submit-label="Отправить"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--arrow m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
@click-outside="$emit('hideModal')"
>
<div class="title">Напишите нам</div>
<FormKitSchema :schema="schema"/>
</FormKit>
</div>
<SupportBlock/>
</div>
<div class="app__content contacts">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Контакты', route: { name: 'contacts' } },
]"
/>
<h1 class="h2">Контакты</h1>
<div class="contacts__content">
<div class="contacts__info">
<div class="text contacts__item">
<span class="title">Телефон</span>
+7 (900) 000-00-00
</div>
<div class="text contacts__item">
<span class="title">Почта</span>
it-radio@info.org
</div>
<div class="text contacts__item">
<span class="title">Адрес</span>
г. Челябинск, Адрес
</div>
<div class="text contacts__item">
<span class="title">Соц. сети</span>
<div class="contacts__social">
<div class="contacts__social m--telegram"></div>
<div class="contacts__social m--vk"></div>
</div>
</div>
</div>
<div class="contacts__map">
<div
class="contacts__map-frame"
style="position: relative; overflow: hidden"
>
<a
href="https://yandex.ru/maps/56/chelyabinsk/?utm_medium=mapframe&utm_source=maps"
style="color: #eee; font-size: 12px; position: absolute; top: 0px"
>Челябинск</a
><a
href="https://yandex.ru/maps/geo/chelyabinsk/53159527/?ll=61.421984%2C55.159071&utm_medium=mapframe&utm_source=maps&z=14.04"
style="color: #eee; font-size: 12px; position: absolute; top: 14px"
>Челябинск Яндекс Карты</a
><iframe
src="https://yandex.ru/map-widget/v1/?ll=61.421984%2C55.159071&mode=poi&poi%5Bpoint%5D=61.399655%2C55.160475&poi%5Buri%5D=ymapsbm1%3A%2F%2Fgeo%3Fdata%3DCgg1MzE1OTUyNxIg0KDQvtGB0YHQuNGPLCDQp9C10LvRj9Cx0LjQvdGB0LoiCg04nHVCFb2jXEI%2C&z=14.04"
width="100%"
height="100%"
frameborder="1"
allowfullscreen="true"
style="position: relative"
></iframe>
</div>
</div>
<FormKit
v-model="formData"
type="form"
data-loading="showLoaderSending"
form-class="$reset contacts__form form"
submit-label="Отправить"
:disabled="showLoaderSending"
:loading="showLoaderSending ? true : undefined"
:submit-attrs="{
inputClass: '$reset button m--white m--arrow m--w-100',
wrapperClass: '$reset registration__form-submit form__submit',
outerClass: '$reset',
}"
@submit="submitHandler"
@click-outside="$emit('hideModal')"
>
<div class="title">Напишите нам</div>
<FormKitSchema :schema="schema" />
</FormKit>
</div>
<SupportBlock />
</div>
</template>
<script>
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
import SupportBlock from "@/components/support-block.vue";
import AppBreadcrumbs from '@/components/app-breadcrumbs.vue';
import SupportBlock from '@/components/support-block.vue';
export default {
name: 'contacts',
components: {SupportBlock, AppBreadcrumbs},
data(){
return{
formData: {},
schema: [
{
$formkit: 'text',
name: 'name',
label: 'ФИО',
placeholder: 'ФИО',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'text',
name: 'name',
label: 'Название организации',
placeholder: 'Название организации',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'maska',
name: 'phone',
maska: { mask: '+7 (###) ###-##-##' },
label: 'Контактный телефон',
placeholder: '+7 (###) ###-##-##',
validation: 'required',
outerClass: 'field--required'
},
{
$formkit: 'textarea',
name: 'message',
label: 'Сообщение',
placeholder: 'Сообщение',
validation: 'required',
outerClass: 'field--required'
}
],
showLoaderSending: false
}
},
methods:{
submitHandler(){
}
}
}
name: 'contacts',
components: { SupportBlock, AppBreadcrumbs },
data() {
return {
formData: {},
schema: [
{
$formkit: 'text',
name: 'name',
label: 'ФИО',
placeholder: 'ФИО',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'text',
name: 'name',
label: 'Название организации',
placeholder: 'Название организации',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'maska',
name: 'phone',
maska: { mask: '+7 (###) ###-##-##' },
label: 'Контактный телефон',
placeholder: '+7 (###) ###-##-##',
validation: 'required',
outerClass: 'field--required',
},
{
$formkit: 'textarea',
name: 'message',
label: 'Сообщение',
placeholder: 'Сообщение',
validation: 'required',
outerClass: 'field--required',
},
],
showLoaderSending: false,
};
},
methods: {
submitHandler() {},
},
};
</script>

View File

@ -1,133 +1,140 @@
<template>
<div class="home">
<div class="home__meaning" ref="targetWrapper">
<div class="app__content">
<p class="text home__subtitle">
Мы цифровое <span>онлайн радио.</span><br/>
Помогаем разобраться в том, что такое <span>IT.</span><br/>
Находимся в <span>Челябинске</span>, но вещаем на весь <span>Мир</span><br/>
</p>
<h1 class="home__title" ref="targetTitle">
IT-Радио <span id="targetTitleSpan">радиостанция про сферу</span> технологий <br/> и развитие
<span id="targetTitleSpan">в IT</span>
<!-- IT Радио -->
<!-- <span id="targetTitleSpan">радиостанция</span>-->
<!-- <br/>-->
<!-- <span id="targetTitleSpan">про сферу</span> технологий<br/>-->
<!-- и развитие <span id="targetTitleSpan">в IT</span><br/>-->
</h1>
</div>
<div class="home__banner" ref="target">
</div>
</div>
<template v-if="true">
<div class="app__content">
<div class="home__description">
<div class="home__info">
<div class="text home__info--item">
IT-RADIO. 2023
<span>
Сегодня IT-сфера развивается настолько быстро, что следить за всеми новинками и изменениями в ней становится все сложнее.<br/><br/> Но есть способ всегда быть в курсе последних новостей и событий это IT-радио.
</span>
</div>
<h2 class="h2 m--border">
Открывая новые горизонты в мире технологий
</h2>
<div class="text home__info--item m--circle">
<span>
IT-радио это уникальный проект, который объединяет в себе самых ярких представителей IT-индустрии, а также экспертов из различных областей, чтобы поделиться своими знаниями и опытом с широкой аудиторией.<br/><br/>
Каждое шоу на IT-радио включает в себя актуальные темы, новости, обзоры, интервью с экспертами и многое другое.
</span>
</div>
</div>
<div class="home__content">
<div class="home__content--item m--one-circle">
<span class="title">Музыка</span>
Нам важно создать комфортную атмосферу, которая поможет сосредоточиться на задачах и улучшит
продуктивность.
</div>
<div class="home__content--item m--two-circle">
<span class="title">Подкасты</span>
Возможность задать вопросы профессионалам из разных областей IT
</div>
<div class="home__content--item m--three-circle">
<span class="title">Новости</span>
Обзоры последних новинок и изменений в IT-индустрии
</div>
</div>
</div>
</div>
<Team/>
<div class="app__content">
<RubricBlock/>
</div>
<div class="home__social">
<div class="home__social--tools">
<div class="home__social--description">
<h2 class="h2 m--white">Соц сети</h2>
<div class="text">
Следите за обновлениями и новыми постами на IT Radio, чтобы быть в курсе последних новостей
и
событий в мире IT, а также следить за анонсами и обновлениями!
</div>
</div>
<div class="home__social--btns">
<button class="button m--blur">Telegram</button>
<button class="button m--blur">VKontakte</button>
<button class="button m--blur">Instagram</button>
<button class="button m--blur">YouTube</button>
</div>
</div>
</div>
<div class="app__content">
<blog/>
</div>
</template>
</div>
<div class="home">
<div class="home__meaning" ref="targetWrapper">
<div class="app__content">
<p class="text home__subtitle">
Мы цифровое <span>онлайн радио.</span><br />
Помогаем разобраться в том, что такое <span>IT.</span><br />
Находимся в <span>Челябинске</span>, но вещаем на весь <span>Мир</span
><br />
</p>
<h1 class="home__title" ref="targetTitle">
IT-Радио
<span id="targetTitleSpan">радиостанция про сферу</span> технологий
<br />
и развитие
<span id="targetTitleSpan">в IT</span>
<!-- IT Радио -->
<!-- <span id="targetTitleSpan">радиостанция</span>-->
<!-- <br/>-->
<!-- <span id="targetTitleSpan">про сферу</span> технологий<br/>-->
<!-- и развитие <span id="targetTitleSpan">в IT</span><br/>-->
</h1>
</div>
<div class="home__banner" ref="target"></div>
</div>
<template v-if="true">
<div class="app__content">
<div class="home__description">
<div class="home__info">
<div class="text home__info--item">
IT-RADIO. 2023
<span>
Сегодня IT-сфера развивается настолько быстро, что следить за
всеми новинками и изменениями в ней становится все сложнее.<br /><br />
Но есть способ всегда быть в курсе последних новостей и событий
это IT-радио.
</span>
</div>
<h2 class="h2 m--border">
Открывая новые горизонты в мире технологий
</h2>
<div class="text home__info--item m--circle">
<span>
IT-радио это уникальный проект, который объединяет в себе
самых ярких представителей IT-индустрии, а также экспертов из
различных областей, чтобы поделиться своими знаниями и опытом с
широкой аудиторией.<br /><br />
Каждое шоу на IT-радио включает в себя актуальные темы, новости,
обзоры, интервью с экспертами и многое другое.
</span>
</div>
</div>
<div class="home__content">
<div class="home__content--item m--one-circle">
<span class="title">Музыка</span>
Нам важно создать комфортную атмосферу, которая поможет
сосредоточиться на задачах и улучшит продуктивность.
</div>
<div class="home__content--item m--two-circle">
<span class="title">Подкасты</span>
Возможность задать вопросы профессионалам из разных областей IT
</div>
<div class="home__content--item m--three-circle">
<span class="title">Новости</span>
Обзоры последних новинок и изменений в IT-индустрии
</div>
</div>
</div>
</div>
<Team />
<div class="app__content">
<RubricBlock />
</div>
<div class="home__social">
<div class="home__social--tools">
<div class="home__social--description">
<h2 class="h2 m--white">Соц сети</h2>
<div class="text">
Следите за обновлениями и новыми постами на IT Radio, чтобы быть в
курсе последних новостей и событий в мире IT, а также следить за
анонсами и обновлениями!
</div>
</div>
<div class="home__social--btns">
<button class="button m--blur">Telegram</button>
<button class="button m--blur">VKontakte</button>
<button class="button m--blur">Instagram</button>
<button class="button m--blur">YouTube</button>
</div>
</div>
</div>
<div class="app__content">
<blog />
</div>
</template>
</div>
</template>
<script>
import {gsap} from "gsap";
import {ScrollTrigger} from "gsap/ScrollTrigger";
import Team from "@/components/team.vue";
import RubricBlock from "components/rubric-block.vue";
import Blog from "components/blog.vue";
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import Team from '@/components/team.vue';
import RubricBlock from 'components/rubric-block.vue';
import Blog from 'components/blog.vue';
export default {
name: 'home',
components: {Blog, RubricBlock, Team},
created() {
},
mounted() {
this.initScene();
},
methods: {
initScene() {
gsap.registerPlugin(ScrollTrigger);
gsap.to(this.$refs.target, {
scale: 1,
scrollTrigger: {
trigger: this.$refs.targetWrapper,
scrub: true,
start: 0,
end: 600,
pin: true,
},
},
);
gsap.to(this.$refs.targetTitle, {
color: 'transparent',
backgroundImage: 'linear-gradient(91.17deg, #C6F1F7 -4.01%, #F983E9 36.14%, #B877FF 77.44%, #C2E9CD 106.11%)',
scrollTrigger: {
trigger: this.$refs.targetWrapper,
scrub: true,
start: 0,
end: 600,
},
},
);
}
}
}
name: 'home',
components: { Blog, RubricBlock, Team },
created() {},
mounted() {
this.initScene();
},
methods: {
initScene() {
gsap.registerPlugin(ScrollTrigger);
gsap.to(this.$refs.target, {
scale: 1,
scrollTrigger: {
trigger: this.$refs.targetWrapper,
scrub: true,
start: 0,
end: 600,
pin: true,
},
});
gsap.to(this.$refs.targetTitle, {
color: 'transparent',
backgroundImage:
'linear-gradient(91.17deg, #C6F1F7 -4.01%, #F983E9 36.14%, #B877FF 77.44%, #C2E9CD 106.11%)',
scrollTrigger: {
trigger: this.$refs.targetWrapper,
scrub: true,
start: 0,
end: 600,
},
});
},
},
};
</script>

View File

@ -1,179 +1,203 @@
<template>
<div class="playlist-edit">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Личный кабинет', route: { name: 'profile' } },
$route.name==='playlist-create'?
{ name: 'Добавление плейлиста', route: { name: 'playlist-create' } }:
{ name: 'Редактирование плейлиста', route: { name: 'playlist-edit' } },
]"/>
<h1 class="h2 playlist__title m--margin">{{ $route.name === 'playlist-create' ? 'Новый плейлист' : playlist.name }}</h1>
<button class="playlist-edit__upload" @click="handlerUploadCover">Добавить обложку</button>
<div class="field__input m--hidden">
<input
id="cover"
ref="coverInput"
accept=".jpg,.png,.svg"
class="input"
type="file"
name="logo"
>
</div>
<FormKit
v-model="playlist.name"
type="text"
outer-class="playlist-edit__search"
inner-class="m--search"
placeholder="Название плейлиста"
></FormKit>
<div class="playlist-edit__list">
<div class="playlist-edit__item">
<div class="playlist-edit__title">Поиск по каталогу</div>
<template v-if="showLoaderSongs">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<SongList
v-else-if="songsFiltered.length>0"
:songList="songsFiltered"
class="m--column"
@addPlaylist="addPlaylist"
/>
<div v-else>Каталог музыки пуст!</div>
</div>
<div class="playlist-edit__item">
<div class="playlist-edit__title">Добавленные треки</div>
<template v-if="showLoaderPlaylist">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<SongList
v-else-if="playlist.song?.length>0"
:songList="playlist.song"
class="m--column"
:songAlreadyAdd="true"
@removePlaylist="removePlaylist"
/>
<div v-else>Добавьте музыку в плейлист!</div>
</div>
</div>
</div>
<div class="playlist-edit">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Личный кабинет', route: { name: 'profile' } },
$route.name === 'playlist-create'
? { name: 'Добавление плейлиста', route: { name: 'playlist-create' } }
: {
name: 'Редактирование плейлиста',
route: { name: 'playlist-edit' },
},
]"
/>
<h1 class="h2 playlist__title m--margin">
{{ $route.name === 'playlist-create' ? 'Новый плейлист' : playlist.name }}
</h1>
<button class="playlist-edit__upload" @click="handlerUploadCover">
Добавить обложку
</button>
<div class="field__input m--hidden">
<input
id="cover"
ref="coverInput"
accept=".jpg,.png,.svg"
class="input"
type="file"
name="logo"
/>
</div>
<FormKit
v-model="playlist.name"
type="text"
outer-class="playlist-edit__search"
inner-class="m--search"
placeholder="Название плейлиста"
></FormKit>
<div class="playlist-edit__list">
<div class="playlist-edit__item">
<div class="playlist-edit__title">Поиск по каталогу</div>
<template v-if="showLoaderSongs">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<SongList
v-else-if="songsFiltered.length > 0"
:songList="songsFiltered"
class="m--column"
@addPlaylist="addPlaylist"
/>
<div v-else>Каталог музыки пуст!</div>
</div>
<div class="playlist-edit__item">
<div class="playlist-edit__title">Добавленные треки</div>
<template v-if="showLoaderPlaylist">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<SongList
v-else-if="playlist.song?.length > 0"
:songList="playlist.song"
class="m--column"
:songAlreadyAdd="true"
@removePlaylist="removePlaylist"
/>
<div v-else>Добавьте музыку в плейлист!</div>
</div>
</div>
</div>
</template>
<script>
import {app} from "@/services";
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
import SongList from "@/components/song-list.vue";
import { app } from '@/services';
import AppBreadcrumbs from '@/components/app-breadcrumbs.vue';
import SongList from '@/components/song-list.vue';
export default {
name: 'playlist-edit',
components: {SongList, AppBreadcrumbs},
data() {
return {
playlist: {},
songs: [],
showLoaderSongs: false,
showLoaderPlaylist: false,
}
},
created() {
this.getAllSong();
this.getPlaylist();
},
computed: {
songsFiltered() {
return this.songs.filter(song => {
const alreadyAdd = this.playlist.song.find(item => item.azura_id === song.azura_id)
return !alreadyAdd
})
}
},
methods: {
getPlaylist() {
this.showLoaderPlaylist = true;
app.getPlaylist(this.$route.params.id).then(res => {
this.showLoaderPlaylist = false;
this.playlist = res;
}).catch(err => {
this.showLoaderPlaylist = false;
console.error(err)
})
},
getAllSong() {
this.showLoaderSongs = true;
app.getAllSong().then(res => {
this.showLoaderSongs = false;
this.songs = res;
}).catch(err => {
this.showLoaderSongs = false;
console.error(err)
})
},
addPlaylist(song) {
console.log(song)
const params = {
playlist_id: this.$route.params.id,
...song
}
this.showLoaderSongs = true;
this.showLoaderPlaylist = true;
app.addSongToPlaylist(params).then(() => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.getPlaylist();
}).catch(err => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err)
})
},
removePlaylist(song) {
const params = {
playlist_id: this.$route.params.id,
azura_id: song.azura_id
}
this.showLoaderSongs = true;
this.showLoaderPlaylist = true;
app.removeSongToPlaylist(params).then(() => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.getPlaylist();
}).catch(err => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err)
})
},
handlerUploadCover(){
let logoInput = this.$refs.coverInput;
let click = new MouseEvent('click');
name: 'playlist-edit',
components: { SongList, AppBreadcrumbs },
data() {
return {
playlist: {},
songs: [],
showLoaderSongs: false,
showLoaderPlaylist: false,
};
},
created() {
this.getAllSong();
this.getPlaylist();
},
computed: {
songsFiltered() {
return this.songs.filter((song) => {
const alreadyAdd = this.playlist.song.find(
(item) => item.azura_id === song.azura_id,
);
return !alreadyAdd;
});
},
},
methods: {
getPlaylist() {
this.showLoaderPlaylist = true;
app
.getPlaylist(this.$route.params.id)
.then((res) => {
this.showLoaderPlaylist = false;
this.playlist = res;
})
.catch((err) => {
this.showLoaderPlaylist = false;
console.error(err);
});
},
getAllSong() {
this.showLoaderSongs = true;
app
.getAllSong()
.then((res) => {
this.showLoaderSongs = false;
this.songs = res;
})
.catch((err) => {
this.showLoaderSongs = false;
console.error(err);
});
},
addPlaylist(song) {
console.log(song);
const params = {
playlist_id: this.$route.params.id,
...song,
};
this.showLoaderSongs = true;
this.showLoaderPlaylist = true;
app
.addSongToPlaylist(params)
.then(() => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.getPlaylist();
})
.catch((err) => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err);
});
},
removePlaylist(song) {
const params = {
playlist_id: this.$route.params.id,
azura_id: song.azura_id,
};
this.showLoaderSongs = true;
this.showLoaderPlaylist = true;
app
.removeSongToPlaylist(params)
.then(() => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.getPlaylist();
})
.catch((err) => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err);
});
},
handlerUploadCover() {
let logoInput = this.$refs.coverInput;
let click = new MouseEvent('click');
logoInput.onchange = this.uploadCover;
logoInput.dispatchEvent(click);
},
uploadCover(event){
let file = event.target.files ? event.target.files[0] : null
if (file) {
const data = new FormData();
data.append('playlist_art', file);
data.append('playlist_id', this.$route.params.id);
app.updatePlaylist(data).then((res) => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.playlist = res;
}).catch(err => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err)
})
}
}
}
}
logoInput.onchange = this.uploadCover;
logoInput.dispatchEvent(click);
},
uploadCover(event) {
let file = event.target.files ? event.target.files[0] : null;
if (file) {
const data = new FormData();
data.append('playlist_art', file);
data.append('playlist_id', this.$route.params.id);
app
.updatePlaylist(data)
.then((res) => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.playlist = res;
})
.catch((err) => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err);
});
}
},
},
};
</script>

View File

@ -1,55 +1,63 @@
<template>
<div class="playlist">
<template v-if="showLoaderPlaylist">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<template v-else>
<div class="playlist__header">
<div class="playlist__back" @click="handlerBack"></div>
<div class="h2 playlist__title">{{ playlist.name }}</div>
<div class="playlist__edit" @click="next({name: 'playlist-edit', params:{id:this.playlist.id}})"></div>
</div>
<SongList :songList="playlist.song" :songAlreadyAdd="true"/>
</template>
</div>
<div class="playlist">
<template v-if="showLoaderPlaylist">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<template v-else>
<div class="playlist__header">
<div class="playlist__back" @click="handlerBack"></div>
<div class="h2 playlist__title">{{ playlist.name }}</div>
<div
class="playlist__edit"
@click="
next({ name: 'playlist-edit', params: { id: this.playlist.id } })
"
></div>
</div>
<SongList :songList="playlist.song" :songAlreadyAdd="true" />
</template>
</div>
</template>
<script>
import {app} from "@/services";
import SongList from "@/components/song-list.vue";
import { app } from '@/services';
import SongList from '@/components/song-list.vue';
export default {
name: 'playlist',
components: {SongList},
data() {
return {
showLoaderPlaylist: false,
playlist: {}
}
},
created() {
this.getPlaylist();
},
methods: {
getPlaylist() {
this.showLoaderPlaylist = true;
app.getPlaylist(this.$route.params.id).then(res => {
this.showLoaderPlaylist = false;
this.playlist = res;
}).catch(err => {
this.showLoaderPlaylist = false;
console.error(err)
})
},
handlerBack() {
this.$router.go(-1);
},
next(params) {
this.$router.push(params);
}
}
}
name: 'playlist',
components: { SongList },
data() {
return {
showLoaderPlaylist: false,
playlist: {},
};
},
created() {
this.getPlaylist();
},
methods: {
getPlaylist() {
this.showLoaderPlaylist = true;
app
.getPlaylist(this.$route.params.id)
.then((res) => {
this.showLoaderPlaylist = false;
this.playlist = res;
})
.catch((err) => {
this.showLoaderPlaylist = false;
console.error(err);
});
},
handlerBack() {
this.$router.go(-1);
},
next(params) {
this.$router.push(params);
},
},
};
</script>

View File

@ -1,109 +1,109 @@
<template>
<div class="app__content playlists">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Плейлист', route: { name: 'playlists' } },
]"
/>
<div class="playlists__content">
<h1 class="h2">Плейлист</h1>
<div class="playlists__tabs tabs m--btns">
<button
v-for="item in tabsItems"
:key="`tab-${item.name}`"
class="button"
:class="currentTabsItem === item.name && 'is-active'"
@click.prevent="changeTab(item.name)"
>
{{ item.label }}
</button>
</div>
<div class="playlists__list">
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
</div>
<Pagination :total="37" :limit="5" :currentPage="currentPage || 1" />
<div class="app__content playlists">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Плейлист', route: { name: 'playlists' } },
]"
/>
<div class="playlists__content">
<h1 class="h2">Плейлист</h1>
<div class="playlists__tabs tabs m--btns">
<button
v-for="item in tabsItems"
:key="`tab-${item.name}`"
class="button"
:class="currentTabsItem === item.name && 'is-active'"
@click.prevent="changeTab(item.name)"
>
{{ item.label }}
</button>
</div>
<div class="playlists__list">
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
<div class="playlists__item">
<div class="title m--white playlists__time">09:00</div>
<div class="text playlists__param">Исполнитель</div>
<div class="text playlists__param m--long">Название трека</div>
</div>
</div>
<Pagination :total="37" :limit="5" :currentPage="currentPage || 1" />
</div>
</div>
</template>
<script>
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
import Pagination from "@/components/pagination.vue";
import AppBreadcrumbs from '@/components/app-breadcrumbs.vue';
import Pagination from '@/components/pagination.vue';
// import { audio } from "@/services";
export default {
name: 'playlists',
components: {Pagination, AppBreadcrumbs},
data(){
return{
currentTabsItem: 'today',
currentPage: 1,
tabsItems:[
{
label: 'Вчера',
name: 'yesterday'
},
{
label: 'Сегодня',
name: 'today'
},
{
label: 'Завтра',
name: 'tomorrow'
},
],
station: this.$store.state.station
}
name: 'playlists',
components: { Pagination, AppBreadcrumbs },
data() {
return {
currentTabsItem: 'today',
currentPage: 1,
tabsItems: [
{
label: 'Вчера',
name: 'yesterday',
},
{
label: 'Сегодня',
name: 'today',
},
{
label: 'Завтра',
name: 'tomorrow',
},
],
station: this.$store.state.station,
};
},
watch: {
'$route.query.page': {
handler(from) {
this.currentPage = Number(from);
},
},
watch:{
'$route.query.page': {
handler(from) {
this.currentPage = Number(from);
},
}
},
created() {
// this.getPlayList();
},
methods: {
// getPlayList(){
// audio.getPlayList(this.station.id).then(res => {
// let groups = res
// // this.$store.dispatch('setMeta', {});
// // this.$store.dispatch('fetchDataByKey', { data: groups, key: 'groups' });
// // this.showLoaderSending.groups = false;
// }).catch(err => {
// // this.showLoaderSending.groups = false;
// console.error(err)
// })
// },
changeTab(tab) {
this.currentTabsItem = tab;
},
created() {
// this.getPlayList();
},
methods:{
// getPlayList(){
// audio.getPlayList(this.station.id).then(res => {
// let groups = res
// // this.$store.dispatch('setMeta', {});
// // this.$store.dispatch('fetchDataByKey', { data: groups, key: 'groups' });
// // this.showLoaderSending.groups = false;
// }).catch(err => {
// // this.showLoaderSending.groups = false;
// console.error(err)
// })
// },
changeTab(tab){
this.currentTabsItem = tab;
}
}
}
},
};
</script>

View File

@ -1,11 +1,9 @@
<template>
<div>
</div>
<div></div>
</template>
<script>
export default {
name: 'podcasts'
}
name: 'podcasts',
};
</script>

View File

@ -1,171 +1,198 @@
<template>
<div class="app__content profile">
<template v-if="$route.name !== 'playlist-edit' && $route.name !== 'playlist-create'">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Личный кабинет', route: { name: 'profile' } },
]"
/>
<h1 class="h2 profile__title">{{ user.email }}</h1>
<button class="button m--text-link" @click="showRecovery">Редактировать профиль</button>
<div class="profile__tabs tabs m--btns">
<button
v-for="item in tabsItems"
:key="`tab-${item.name}`"
class="button"
:class="currentTabsItem === item.name && 'is-active'"
@click.prevent="changeTab(item.name)"
>
{{ item.label }}
</button>
</div>
</template>
<template v-if="$route.name === 'profile'">
<template v-if="currentTabsItem==='music'">
<template v-if="showLoaderSong">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<SongList v-else :songList="userFavorite.songs" @removeSong="removeFavorites"/>
</template>
<template v-if="currentTabsItem==='playlists'">
<template v-if="showLoaderPlaylist">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<PlaylistRoster
v-else
:list="userFavorite.playlist"
@createPlaylist="createPlayList"
/>
</template>
</template>
<routerView v-else/>
</div>
<div class="app__content profile">
<template
v-if="
$route.name !== 'playlist-edit' && $route.name !== 'playlist-create'
"
>
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Личный кабинет', route: { name: 'profile' } },
]"
/>
<h1 class="h2 profile__title">{{ user.email }}</h1>
<button class="button m--text-link" @click="showRecovery">
Редактировать профиль
</button>
<div class="profile__tabs tabs m--btns">
<button
v-for="item in tabsItems"
:key="`tab-${item.name}`"
class="button"
:class="currentTabsItem === item.name && 'is-active'"
@click.prevent="changeTab(item.name)"
>
{{ item.label }}
</button>
</div>
</template>
<template v-if="$route.name === 'profile'">
<template v-if="currentTabsItem === 'music'">
<template v-if="showLoaderSong">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<SongList
v-else
:songList="userFavorite.songs"
@removeSong="removeFavorites"
/>
</template>
<template v-if="currentTabsItem === 'playlists'">
<template v-if="showLoaderPlaylist">
<div class="loader">
<div class="spinner" />
Загрузка данных
</div>
</template>
<PlaylistRoster
v-else
:list="userFavorite.playlist"
@createPlaylist="createPlayList"
/>
</template>
</template>
<routerView v-else />
</div>
</template>
<script>
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
import SongList from "@/components/song-list.vue";
import {app} from "@/services";
import PlaylistRoster from "@/components/playlist-roster.vue";
import AppBreadcrumbs from '@/components/app-breadcrumbs.vue';
import SongList from '@/components/song-list.vue';
import { app } from '@/services';
import PlaylistRoster from '@/components/playlist-roster.vue';
export default {
name: 'profile',
components: {PlaylistRoster, SongList, AppBreadcrumbs},
data() {
return {
currentTabsItem: 'music',
tabsItems: [
{
label: 'Музыка',
name: 'music'
},
{
label: 'Подкасты',
name: 'podcasts'
},
{
label: 'Плейлисты',
name: 'playlists'
},
],
showLoaderSong: false,
showLoaderPlaylist: false,
showLoaderPodcast: true,
}
},
computed: {
user() {
return this.$store.state.user;
},
userFavorite() {
return this.$store.state.userFavorite
}
},
watch: {
'$route': {
immediate: true,
handler(to, from) {
if (!from && to?.hash && to?.name==='"profile"'){
console.log('1')
this.currentTabsItem = to?.hash.replace('#', '') || 'music';
}
if (to?.hash !== from?.hash && to?.name === from?.name || !from?.name && !from?.hash){
console.log('2')
if (to.hash) {
this.currentTabsItem = to?.hash.replace('#', '') || 'music';
} else {
this.currentTabsItem = 'music';
}
}
else {
console.log('3')
if (to?.name === 'playlist') {
this.currentTabsItem = 'playlists'
}
}
},
},
},
created() {
this.getSongList();
this.getPlaylists();
},
methods: {
getSongList() {
this.showLoaderSong = true;
app.getFavoriteList().then(res => {
this.showLoaderSong = false;
this.$store.dispatch('setUserFavorite', {songs: res});
}).catch(err => {
this.showLoaderSong = false;
console.error(err)
})
},
changeTab(tab) {
this.currentTabsItem = tab;
if (this.$route.name === 'profile') {
this.$router.push({name: this.$route.name, hash: `#${tab}`});
} else {
this.$router.push({name: 'profile', hash: `#${tab}`});
}
},
removeFavorites(song) {
this.showLoaderSong = true;
app.removeFavorites(song).then(() => {
this.showLoaderSong = false;
this.getSongList();
}).catch(err => {
this.showLoaderSong = false;
console.error(err)
})
},
showRecovery() {
this.$store.dispatch('setModal', {changingUser: true});
},
getPlaylists() {
this.showLoaderPlaylist = true;
app.getPlaylists().then(res => {
this.showLoaderPlaylist = false;
this.$store.dispatch('setUserFavorite', {playlist: res});
}).catch(err => {
this.showLoaderPlaylist = false;
console.error(err)
})
},
createPlayList() {
app.createPlaylists().then(res=>{
this.$router.push({name: 'playlist-create', params: {id: res.id}});
}).catch(err=>{
console.error(err)
})
}
}
}
name: 'profile',
components: { PlaylistRoster, SongList, AppBreadcrumbs },
data() {
return {
currentTabsItem: 'music',
tabsItems: [
{
label: 'Музыка',
name: 'music',
},
{
label: 'Подкасты',
name: 'podcasts',
},
{
label: 'Плейлисты',
name: 'playlists',
},
],
showLoaderSong: false,
showLoaderPlaylist: false,
showLoaderPodcast: true,
};
},
computed: {
user() {
return this.$store.state.user;
},
userFavorite() {
return this.$store.state.userFavorite;
},
},
watch: {
$route: {
immediate: true,
handler(to, from) {
if (!from && to?.hash && to?.name === '"profile"') {
console.log('1');
this.currentTabsItem = to?.hash.replace('#', '') || 'music';
}
if (
(to?.hash !== from?.hash && to?.name === from?.name) ||
(!from?.name && !from?.hash)
) {
console.log('2');
if (to.hash) {
this.currentTabsItem = to?.hash.replace('#', '') || 'music';
} else {
this.currentTabsItem = 'music';
}
} else {
console.log('3');
if (to?.name === 'playlist') {
this.currentTabsItem = 'playlists';
}
}
},
},
},
created() {
this.getSongList();
this.getPlaylists();
},
methods: {
getSongList() {
this.showLoaderSong = true;
app
.getFavoriteList()
.then((res) => {
this.showLoaderSong = false;
this.$store.dispatch('setUserFavorite', { songs: res });
})
.catch((err) => {
this.showLoaderSong = false;
console.error(err);
});
},
changeTab(tab) {
this.currentTabsItem = tab;
if (this.$route.name === 'profile') {
this.$router.push({ name: this.$route.name, hash: `#${tab}` });
} else {
this.$router.push({ name: 'profile', hash: `#${tab}` });
}
},
removeFavorites(song) {
this.showLoaderSong = true;
app
.removeFavorites(song)
.then(() => {
this.showLoaderSong = false;
this.getSongList();
})
.catch((err) => {
this.showLoaderSong = false;
console.error(err);
});
},
showRecovery() {
this.$store.dispatch('setModal', { changingUser: true });
},
getPlaylists() {
this.showLoaderPlaylist = true;
app
.getPlaylists()
.then((res) => {
this.showLoaderPlaylist = false;
this.$store.dispatch('setUserFavorite', { playlist: res });
})
.catch((err) => {
this.showLoaderPlaylist = false;
console.error(err);
});
},
createPlayList() {
app
.createPlaylists()
.then((res) => {
this.$router.push({
name: 'playlist-create',
params: { id: res.id },
});
})
.catch((err) => {
console.error(err);
});
},
},
};
</script>

View File

@ -1,21 +1,21 @@
<template>
<div class="app__content rubric">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Рубрики', route: { name: 'rubric' } },
]"
/>
<RubricBlock/>
</div>
<div class="app__content rubric">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
{ name: 'Рубрики', route: { name: 'rubric' } },
]"
/>
<RubricBlock />
</div>
</template>
<script>
import RubricBlock from "@/components/rubric-block.vue";
import AppBreadcrumbs from "@/components/app-breadcrumbs.vue";
import RubricBlock from '@/components/rubric-block.vue';
import AppBreadcrumbs from '@/components/app-breadcrumbs.vue';
export default {
name: 'rubric',
components: {AppBreadcrumbs, RubricBlock}
}
name: 'rubric',
components: { AppBreadcrumbs, RubricBlock },
};
</script>

View File

@ -1,11 +1,9 @@
<template>
<div>
</div>
<div></div>
</template>
<script>
export default {
name: 'support'
}
name: 'support',
};
</script>