Initial commit

This commit is contained in:
Developer
2025-04-21 16:03:20 +02:00
commit 2832896157
22874 changed files with 3092801 additions and 0 deletions

8
resources/css/app.css vendored Normal file
View File

@@ -0,0 +1,8 @@
/* Reset */
@import 'tailwindcss/base';
/* Components */
@import 'tailwindcss/components';
/* Utilities */
@import 'tailwindcss/utilities';
@import 'common';

169
resources/css/common.css vendored Normal file
View File

@@ -0,0 +1,169 @@
:root {
--swiper-theme-color: #FF5722 !important;
}
.grid-auto {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-auto-flow: row dense;
}
.button-default, button.default{
background-color: transparent;
border: transparent;
}
.contain{
contain: layout;
}
.drop-shadow-custom{
filter: drop-shadow(1px 1px 10px black);
}
.mediaCount2{
@apply grid;
@apply gap-3;
@apply grid-cols-2;
}
.mediaCount3{
@apply grid;
@apply gap-3;
@apply grid-cols-3;
}
.gradient-profile{
&:after{
content: '';
position: absolute;
top:0;
left:0;
right: 0;
bottom: 0;
background: linear-gradient(180deg, rgba(44, 34, 54, 0.3) 0%, rgba(44, 34, 54, 0.3) 100%);
}
}
.btn-spinner,
.btn-spinner:after {
border-radius: 50%;
width: 1.5em;
height: 1.5em;
}
.btn-spinner {
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 0.2em solid white;
border-right: 0.2em solid white;
border-bottom: 0.2em solid white;
border-left: 0.2em solid transparent;
transform: translateZ(0);
animation: spinning 1s infinite linear;
}
#nprogress .bar {
height: 5px !important;
}
@keyframes spinning {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.custom-input-range {
height: 22px;
-webkit-appearance: none;
background: transparent;
}
.custom-input-range:focus {
outline: none;
}
.custom-input-range::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000;
background: #2C2236;
border-radius: 10px;
border: 0px solid #000000;
}
.custom-input-range::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #000000;
border: 1px solid #F26627;
height: 15px;
width: 15px;
border-radius: 25px;
background: #F26627;
cursor: pointer;
-webkit-appearance: none;
margin-top: -5.5px;
}
.custom-input-range:focus::-webkit-slider-runnable-track {
background: #2C2236;
}
.custom-input-range::-moz-range-track {
width: 100%;
height: 5px;
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000;
background: #2C2236;
border-radius: 10px;
border: 0px solid #000000;
}
.custom-input-range::-moz-range-thumb {
box-shadow: 0px 0px 0px #000000;
border: 1px solid #F26627;
height: 15px;
width: 15px;
border-radius: 25px;
background: #F26627;
cursor: pointer;
}
.custom-input-range::-ms-track {
width: 100%;
height: 5px;
cursor: pointer;
animate: 0.2s;
background: transparent;
border-color: transparent;
color: transparent;
}
.custom-input-range::-ms-fill-lower {
background: #2C2236;
border: 0px solid #000000;
border-radius: 20px;
box-shadow: 0px 0px 0px #000000;
}
.custom-input-range::-ms-fill-upper {
background: #2C2236;
border: 0px solid #000000;
border-radius: 20px;
box-shadow: 0px 0px 0px #000000;
}
.custom-input-range::-ms-thumb {
margin-top: 1px;
box-shadow: 0px 0px 0px #000000;
border: 1px solid #F26627;
height: 15px;
width: 15px;
border-radius: 25px;
background: #F26627;
cursor: pointer;
}
.custom-input-range:focus::-ms-fill-lower {
background: #2C2236;
}
.custom-input-range:focus::-ms-fill-upper {
background: #2C2236;
}

View File

@@ -0,0 +1,125 @@
<template>
<meta-head title="Авторизация">
<meta name="description" content="Авторизация">
</meta-head>
<div class="header-simple flex items-center justify-center p-2 bg-orange">
<img class="block h-12" src="/image/logotype.svg" alt="">
</div>
<div class="min-h-[calc(100vh-64px)] place-items-center grid md:pt-3"
style="background-image: url('/image/auth-bg.jpg');">
<div class="w-full md:w-auto max-w-7xl mx-auto ">
<div class="md:grid grid-cols-12 ">
<div class="col-span-7 bg-indigo-200">
<div class="p-4 lg:p-28">
<h1 class="font-medium text-xl md:text-2xl lg:text-4xl text-white text-center">Войти</h1>
<div class="auth-form mt-7">
<form @submit.prevent="submit" class="space-y-6">
<div>
<div class="relative">
<div class="absolute inset-y-0 left-5 text-gray flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="flex-shrink-0">
<path
d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z">
</path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</div>
<input
v-model="form.email"
autocapitalize="off"
class="w-full pl-14 h-12 md:h-16 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border-transparent bg-indigo-100 rounded-md placeholder-gray"
type="email" placeholder="E-mail">
</div>
<div v-if="form.errors.email" class="form-error text-sm text-red">{{ form.errors.email }}</div>
</div>
<div>
<div class="relative">
<div class="absolute inset-y-0 left-5 text-gray flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="flex-shrink-0">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</div>
<input
v-model="form.password"
class="w-full pl-14 h-12 md:h-16 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border-transparent bg-indigo-100 rounded-md placeholder-gray"
type="password" placeholder="Пароль">
</div>
<div v-if="form.errors.password" class="form-error text-sm text-red">{{ form.errors.password }}</div>
</div>
<div class="flex items-center">
<input id="remember" v-model="form.remember" type="checkbox" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="remember" class="select-none ml-3 text-gray">Запомни меня</label>
</div>
<div class="text-center">
<loading-button :loading="form.processing" class="mx-3 my-1 px-12 py-3 transition shadow-none hover:shadow-classic2 inline-flex items-center justify-center text-base rounded-full text-white bg-orange focus:outline-none" type="submit">Войти</loading-button>
</div>
</form>
</div>
</div>
</div>
<div class="col-span-5 bg-center bg-cover" style="background-image: url('image/orange-auth.jpg');">
<div class="py-4 lg:py-28 px-4">
<div class="font-medium text-xl md:text-2xl lg:text-4xl !leading-relaxed text-white text-center">Заработай на своем
творчестве первый миллион </div>
<div class="font-medium text-xl md:text-2xl lg:text-4xl !leading-relaxed text-white text-center">Присоединяйся к 4Teaser
прямо сейчас!</div>
<div class="text-center mt-4 md:mt-10">
<inertia-link
:href="route('register')"
class="mx-3 my-1 px-12 py-3 transition shadow-none hover:shadow-classic2 inline-flex items-center justify-center text-base rounded-full text-white border border-white bg-transparent focus:outline-none">
Зарегистрироваться
</inertia-link>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import LoadingButton from "@/Shared/Form/LoadingButton";
import MetaHead from '@/Shared/MetaHead'
export default {
components: {
MetaHead,
LoadingButton,
},
setup() {
const form = Inertia.form({
email: null,
password: null,
remember: false,
});
const submit = () => {
form.post(route("login.store"));
};
return {
form,
submit,
};
},
}
</script>

View File

@@ -0,0 +1,135 @@
<template>
<meta-head title="Авторизация">
<meta name="description" content="Авторизация">
</meta-head>
<div class="header-simple flex items-center justify-center p-2 bg-orange">
<img class="block h-12" src="/image/logotype.svg" alt="">
</div>
<div class="min-h-[calc(100vh-64px)] place-items-center grid md:pt-3"
style="background-image: url('/image/auth-bg.jpg');">
<div class="w-full md:w-auto max-w-7xl mx-auto ">
<div class="md:grid grid-cols-12 ">
<div class="col-span-7 bg-indigo-200">
<div class="p-4 lg:p-28">
<h1 class="font-medium text-xl md:text-2xl lg:text-4xl text-white text-center">Регистрация</h1>
<div class="auth-form mt-7">
<form @submit.prevent="submit" class="space-y-6">
<div>
<div class="relative">
<div class="absolute inset-y-0 left-5 text-gray flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
</div>
<input
v-model="form.first_name"
autocapitalize="off"
class="w-full pl-14 h-12 md:h-16 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border-transparent bg-indigo-100 rounded-md placeholder-gray"
type="text" placeholder="Имя">
</div>
<div v-if="form.errors.email" class="form-error text-sm text-red">{{ form.errors.first_name }}</div>
</div>
<div>
<div class="relative">
<div class="absolute inset-y-0 left-5 text-gray flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="flex-shrink-0">
<path
d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z">
</path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</div>
<input
v-model="form.email"
autocapitalize="off"
class="w-full pl-14 h-12 md:h-16 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border-transparent bg-indigo-100 rounded-md placeholder-gray"
type="email" placeholder="E-mail">
</div>
<div v-if="form.errors.email" class="form-error text-sm text-red">{{ form.errors.email }}</div>
</div>
<div>
<div class="relative">
<div class="absolute inset-y-0 left-5 text-gray flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="flex-shrink-0">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</div>
<input
v-model="form.password"
class="w-full pl-14 h-12 md:h-16 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border-transparent bg-indigo-100 rounded-md placeholder-gray"
type="password" placeholder="Пароль">
</div>
<div v-if="form.errors.password" class="form-error text-sm text-red">{{ form.errors.password }}</div>
</div>
<div class="text-center">
<loading-button :loading="form.processing" class="mx-3 my-1 px-12 py-3 transition shadow-none hover:shadow-classic2 inline-flex items-center justify-center text-base rounded-full text-white bg-orange focus:outline-none" type="submit">Зарегистрироваться</loading-button>
</div>
</form>
</div>
</div>
</div>
<div class="col-span-5 bg-center bg-cover" style="background-image: url('image/orange-auth.jpg');">
<div class="py-4 lg:py-28 px-4 flex flex-col h-full justify-center">
<div class="font-medium text-xl md:text-2xl lg:text-4xl !leading-relaxed text-white text-center">
Уже есть учетная запись?
</div>
<div class="text-center mt-4 md:mt-10">
<inertia-link
:href="route('login')"
class="mx-3 my-1 px-12 py-3 transition shadow-none hover:shadow-classic2 inline-flex items-center justify-center text-base rounded-full text-white border border-white bg-transparent focus:outline-none">
Войти
</inertia-link>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import LoadingButton from "@/Shared/Form/LoadingButton";
import MetaHead from '@/Shared/MetaHead'
export default {
components: {
MetaHead,
LoadingButton,
},
setup() {
const form = Inertia.form({
first_name: null,
email: null,
password: null,
});
const submit = () => {
form.post(route("register.store"));
};
return {
form,
submit,
};
},
}
</script>

View File

@@ -0,0 +1,98 @@
<template>
<meta-head title="Новинки"></meta-head>
<div class="mb-6 py-3 md:py-14 xl:py-20 banner relative bg-center bg-no-repeat bg-cover"
style="background-image: url('/image/bg-home.jpg');">
<div class="h-60 lg:h-96 flex justify-center items-center text-center">
<div class="max-w-4xl text-gray px-3">
<p class="text-md md:text-2xl">Социальная сеть для творческих людей</p>
<h1
class="mt-4 md:mt-8 text-xl md:text-2xl lg:text-3xl xl:text-5xl text-white font-semibold xl:leading-relaxed">
Зарабатывай на
своем творчестве вместе с 4Teaser</h1>
<!-- <button type="button"
class="mt-8 inline-flex tracking-wide items-center px-8 md:px-12 py-3 border border-white text-sm lg:text-lg text-white rounded-full bg-transparent hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2">
Присоединиться
</button> -->
</div>
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 buttons-filter-line">
<div class=" relative mb-5">
<div class="absolute inset-y-0 left-3 flex items-center z-[1]">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z" />
</svg>
</div>
<input
class="relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 h-14" placeholder="Поиск"
type="search">
</div>
<div class="grid gap-2 md:gap-5 grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">
<inertia-link :href="route('dashboard')"
:class="[active_button == 'new' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center rounded-md text-white focus:outline-none']">
Новинки
</inertia-link >
<inertia-link :href="route('dashboard')"
:data="{ filter: 'hot' }"
:class="[active_button == 'hot' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center shadow-classic rounded-md text-white focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path
d="M14.422 6.243c-3.57-2.172-1.895-5.238-1.824-5.365A.586.586 0 0012.09 0c-1.837 0-3.276.522-4.276 1.552-1.71 1.76-1.63 4.498-1.597 5.667.004.13.007.242.007.325 0 .868.14 1.67.263 2.377.079.456.147.85.16 1.159.012.331-.048.407-.05.41-.01.01-.081.049-.276.049a.657.657 0 01-.53-.235c-.565-.634-.604-2.365-.496-3.307a.586.586 0 00-.582-.654c-1.521 0-2.658 2.488-2.658 4.712 0 1.046.21 2.07.625 3.045a8.081 8.081 0 001.7 2.527C5.894 19.157 7.89 20 10 20c2.119 0 4.114-.83 5.618-2.34a7.892 7.892 0 002.327-5.605c0-2.692-2.107-4.95-3.523-5.812zM10 18.828c-3.671 0-6.773-3.101-6.773-6.773 0-.893.213-1.83.585-2.571.086-.173.175-.322.263-.447.01.967.163 2.284.841 3.046.366.41.852.627 1.405.627.518 0 .912-.156 1.172-.466.486-.578.337-1.436.148-2.524-.115-.66-.245-1.409-.245-2.176 0-.1-.003-.22-.007-.359-.032-1.107-.099-3.412 1.265-4.817.613-.63 1.467-1.014 2.55-1.145-.123.406-.228.92-.232 1.497-.01 1.27.476 3.085 2.841 4.524 1.145.696 2.96 2.618 2.96 4.811A6.78 6.78 0 0110 18.828z" />
</svg>
Популярные
</inertia-link >
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 my-6">
<button class="button-default text-gray text-lg">Очистить фильтры</button>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 cards-block rounded-md bg-indigo-200 shadow-classic grid gap-2 lg:gap-4 grid-cards p-2 lg:p-5">
<feed
:self-feed="false"
:feeds="feeds"
/>
</div>
</div>
</template>
<script>
import Feed from "@/Shared/Feed/Feed";
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
export default {
layout: Layout,
components: {
MetaHead,
Feed
},
props: {
feeds: Array,
active_button: String,
},
methods: {
},
}
</script>

View File

@@ -0,0 +1,99 @@
<template>
<meta-head title="Новости"></meta-head>
<div class="mt-16 container mx-auto px-2 md:px-6 2xl:px-28 buttons-filter-line">
<div class="items-center grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-4 2xl:gap-12">
<dropdown-menu>
<MenuItems class="origin-top-left absolute left-0 mt-2 w-64 bg-indigo-300 shadow-lg max-h-60 rounded-md text-base ring-1 ring-indigo-200 overflow-auto focus:outline-none">
<MenuItem>
<inertia-link :href="route('video.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-200 text-gray-light">
<VideoCameraIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Загрузить видео
</inertia-link>
</MenuItem>
<MenuItem>
<inertia-link :href="route('image.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-200 text-gray-light">
<PhotographIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Загрузить изображение
</inertia-link>
</MenuItem>
<MenuItem>
<inertia-link :href="route('music.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-200 text-gray-light">
<MusicNoteIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Загрузить музыку
</inertia-link>
</MenuItem>
</MenuItems>
</dropdown-menu>
<inertia-link
:href='route("feeds.layoutsidebar.image")'
:class="[active_button == 'image' ? 'bg-orange' : 'bg-indigo-200 hover:bg-orange', 'transition inline-flex items-center px-3 py-3 lg:px-7 lg:py-5 justify-center shadow-classic text-sm rounded-md text-white focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M4.167 3.333a.833.833 0 00-.834.834v11.666c0 .46.373.834.834.834h11.666c.46 0 .834-.373.834-.834V4.167a.833.833 0 00-.834-.834H4.167zm-2.5.834a2.5 2.5 0 012.5-2.5h11.666a2.5 2.5 0 012.5 2.5v11.666a2.5 2.5 0 01-2.5 2.5H4.167a2.5 2.5 0 01-2.5-2.5V4.167z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M7.083 6.667a.417.417 0 100 .833.417.417 0 000-.833zM5 7.083a2.083 2.083 0 114.167 0 2.083 2.083 0 01-4.167 0zM12.744 7.744a.833.833 0 011.179 0l4.166 4.167a.834.834 0 01-1.178 1.178l-3.578-3.577-8.577 8.577a.833.833 0 01-1.179-1.178l9.167-9.167z" />
</svg>
<span class="truncate">Изображения</span>
</inertia-link>
<inertia-link
:href='route("feeds.layoutsidebar.video")'
:class="[active_button == 'video' ? 'bg-orange' : 'bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-7 lg:py-5 justify-center shadow-classic text-sm rounded-md text-white focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M3.483 2.5a.983.983 0 00-.983.983v13.034c0 .543.44.983.983.983h13.034c.543 0 .983-.44.983-.983V3.483a.983.983 0 00-.983-.983H3.483zm-2.65.983a2.65 2.65 0 012.65-2.65h13.034a2.65 2.65 0 012.65 2.65v13.034a2.65 2.65 0 01-2.65 2.65H3.483a2.65 2.65 0 01-2.65-2.65V3.483z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M5.833.833c.46 0 .834.373.834.834v16.666a.833.833 0 11-1.667 0V1.667c0-.46.373-.834.833-.834zM14.167.833c.46 0 .833.373.833.834v16.666a.833.833 0 11-1.667 0V1.667c0-.46.373-.834.834-.834z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M.833 10c0-.46.373-.833.834-.833h16.666a.833.833 0 010 1.666H1.667A.833.833 0 01.833 10zM.833 5.833c0-.46.373-.833.834-.833h4.166a.833.833 0 010 1.667H1.667a.833.833 0 01-.834-.834zM.833 14.167c0-.46.373-.834.834-.834h4.166a.833.833 0 010 1.667H1.667a.833.833 0 01-.834-.833zM13.333 14.167c0-.46.373-.834.834-.834h4.166a.833.833 0 010 1.667h-4.166a.833.833 0 01-.834-.833zM13.333 5.833c0-.46.373-.833.834-.833h4.166a.833.833 0 010 1.667h-4.166a.833.833 0 01-.834-.834z" /></svg>
<span class="truncate">Видео</span>
</inertia-link>
<inertia-link
:href='route("feeds.layoutsidebar.music")'
:class="[active_button == 'music' ? 'bg-orange' : 'bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-7 lg:py-5 justify-center shadow-classic text-sm rounded-md text-white focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.399 12.399a2.5 2.5 0 011.768-.732H17.5c.46 0 .833.373.833.833v1.667a2.5 2.5 0 01-2.5 2.5h-1.666a2.5 2.5 0 01-1.768-4.268zm1.768.934a.833.833 0 000 1.667h1.666a.833.833 0 00.834-.833v-.834h-2.5zm-11.768.733a2.5 2.5 0 011.768-.733H7.5c.46 0 .833.373.833.834v1.666a2.5 2.5 0 01-2.5 2.5H4.167a2.5 2.5 0 01-1.768-4.267zM4.167 15a.833.833 0 100 1.667h1.666a.833.833 0 00.834-.834V15h-2.5z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.039 1.864c.187.158.294.391.294.636v10a.833.833 0 01-1.666 0V3.484L8.333 4.873v9.294a.833.833 0 01-1.666 0v-10c0-.408.294-.755.696-.822l10-1.667a.833.833 0 01.676.186z"/></svg>
<span class="truncate">Музыка</span>
</inertia-link>
</div>
</div>
<div class="feeds-user-list mt-5 container mx-auto px-2 md:px-6 2xl:px-28 space-y-4 lg:space-y-8">
<feed-list
:self-feed="false"
:feeds="feeds"
/>
</div>
</template>
<script>
import FeedList from "@/Shared/FeedList/FeedList";
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
import {
PhotographIcon,
VideoCameraIcon,
MusicNoteIcon,
} from '@heroicons/vue/solid'
import { MenuItem, MenuItems } from '@headlessui/vue'
import DropdownMenu from '@/Shared/Form/DropdownMenu'
export default {
components: {
FeedList,
MetaHead,
DropdownMenu,
MenuItem,
MenuItems,
PhotographIcon,
MusicNoteIcon,
VideoCameraIcon
},
layout: Layout,
props: {
feeds: Array,
active_button: String,
},
}
</script>

View File

@@ -0,0 +1,128 @@
<template>
<meta-head title="Загрузить изображение"></meta-head>
<div class="mt-16 container mx-auto px-2 md:px-6 2xl:px-28 buttons-filter-line">
<form @submit.prevent="submit" class=" bg-indigo-200 shadow-classic rounded-md p-5">
<div class="mb-4 flex items-center text-gray-light text-lg font-medium">
<inertia-link :href="route('profile.user', $page.props.auth.user.username)" class="block hover:underline">
Вернуться
</inertia-link>
<span class="px-3">/</span>
<h1 class="text-gray">Загрузка изображения</h1>
</div>
<div class="space-y-5">
<div class="flex flex-col">
<text-input v-model="form.title" :error="form.errors.title" type="text" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Название" />
</div>
<div class="flex flex-col">
<textarea-input v-model="form.body" :error="form.errors.body" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md" cols="30" rows="4" label="Описание" />
</div>
<div class="flex flex-col">
<file-input-multiple
v-model="form.photos"
:error="form.errors.photos"
label="Выбрать изображения"
/>
</div>
<div class="text-gray-light">
<input class="w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md" placeholder="#tags" type="text">
</div>
<div>
<div class="text-gray-light text-lg mb-2">Тип контента</div>
<div class="flex space-x-6">
<div class="flex items-center">
<input id="feed-paid-1" v-model="paid" value="0" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="feed-paid-1" class="select-none ml-3 text-gray">Бесплатный</label>
</div>
<div class="flex items-center">
<input id="feed-paid-2" v-model="paid" value="1" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="feed-paid-2" class="select-none ml-3 text-gray">Платный</label>
</div>
</div>
</div>
<div class="space-y-5" v-if="contentPaid == 1">
<div class="flex flex-col">
<text-input v-model="form.price" :error="form.errors.price" type="number" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Цена" />
</div>
<div class="flex flex-col">
<file-input-multiple
v-model="form.photos_paid"
:error="form.errors.photos_paid"
label="Выбрать изображения"
/>
</div>
</div>
</div>
<div class="mt-12 flex flex-wrap -my-1 -mx-3">
<progress
class="mx-3 my-1 w-full"
v-if="form.progress"
:value="form.progress.percentage"
max="100"
>
{{ form.progress.percentage }}%
</progress>
<loading-button :loading="form.processing" class="mx-3 my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-orange focus:outline-none" type="submit">
Создать
</loading-button>
<button type="button"
class="mx-3 my-1 transition shadow-none hover:shadow-classic inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-indigo-300 focus:outline-none">
Отменить
</button>
</div>
</form>
</div>
</template>
<script>
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
import TextInput from '@/Shared/Form/TextInput'
import FileInputMultiple from '@/Shared/Form/FileInputMultiple'
import TextareaInput from '@/Shared/Form/TextareaInput'
import LoadingButton from "@/Shared/Form/LoadingButton";
import { useForm } from "@inertiajs/inertia-vue3";
export default {
components: {
MetaHead,
TextInput,
FileInputMultiple,
LoadingButton,
TextareaInput,
},
layout: Layout,
data(){
return {
paid: 0,
contentPaid: 0,
}
},
watch:{
paid(value){
this.contentPaid = value;
this.form.is_paid = value;
}
},
setup() {
const form = useForm({
title: null,
body: null,
price: null,
photos: null,
photos_paid: null,
is_paid: 0
});
const submit = () => {
form.post(route("image.store"));
};
return { form, submit }
},
}
</script>

View File

@@ -0,0 +1,97 @@
<template>
<meta-head title="Изображения"></meta-head>
<div class="mb-6 py-3 banner relative bg-center bg-no-repeat bg-cover"
style="background-image: url('/image/bg-home.jpg');">
<div class="h-52 flex justify-center items-center text-center">
<div class="max-w-4xl text-gray px-3">
<h1
class=" text-xl md:text-2xl lg:text-3xl xl:text-5xl text-white font-semibold xl:leading-relaxed">
Изображения</h1>
<inertia-link :href="route('image.create')"
class="mt-8 inline-flex tracking-wide items-center px-8 md:px-12 py-3 border border-white text-sm lg:text-lg text-white rounded-full bg-transparent hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2">
Загрузить
</inertia-link>
</div>
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 buttons-filter-line">
<div class=" relative mb-5">
<div class="absolute inset-y-0 left-3 flex items-center z-[1]">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z" />
</svg>
</div>
<input
class="relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 h-14" placeholder="Поиск"
type="search">
</div>
<div class="grid gap-2 md:gap-5 grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">
<inertia-link :href="route('list.images')"
:class="[active_button == 'new' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center rounded-md text-white focus:outline-none']">
Новинки
</inertia-link >
<inertia-link :href="route('list.images')"
:data="{ filter: 'hot' }"
:class="[active_button == 'hot' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center shadow-classic rounded-md text-white focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path
d="M14.422 6.243c-3.57-2.172-1.895-5.238-1.824-5.365A.586.586 0 0012.09 0c-1.837 0-3.276.522-4.276 1.552-1.71 1.76-1.63 4.498-1.597 5.667.004.13.007.242.007.325 0 .868.14 1.67.263 2.377.079.456.147.85.16 1.159.012.331-.048.407-.05.41-.01.01-.081.049-.276.049a.657.657 0 01-.53-.235c-.565-.634-.604-2.365-.496-3.307a.586.586 0 00-.582-.654c-1.521 0-2.658 2.488-2.658 4.712 0 1.046.21 2.07.625 3.045a8.081 8.081 0 001.7 2.527C5.894 19.157 7.89 20 10 20c2.119 0 4.114-.83 5.618-2.34a7.892 7.892 0 002.327-5.605c0-2.692-2.107-4.95-3.523-5.812zM10 18.828c-3.671 0-6.773-3.101-6.773-6.773 0-.893.213-1.83.585-2.571.086-.173.175-.322.263-.447.01.967.163 2.284.841 3.046.366.41.852.627 1.405.627.518 0 .912-.156 1.172-.466.486-.578.337-1.436.148-2.524-.115-.66-.245-1.409-.245-2.176 0-.1-.003-.22-.007-.359-.032-1.107-.099-3.412 1.265-4.817.613-.63 1.467-1.014 2.55-1.145-.123.406-.228.92-.232 1.497-.01 1.27.476 3.085 2.841 4.524 1.145.696 2.96 2.618 2.96 4.811A6.78 6.78 0 0110 18.828z" />
</svg>
Популярные
</inertia-link >
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 my-6">
<button class="button-default text-gray text-lg">Очистить фильтры</button>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 cards-block rounded-md bg-indigo-200 shadow-classic grid gap-2 lg:gap-4 grid-cards p-2 lg:p-5">
<feed
:self-feed="false"
:feeds="feeds"
/>
</div>
</div>
</template>
<script>
import Feed from "@/Shared/Feed/Feed";
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
export default {
layout: Layout,
components: {
MetaHead,
Feed
},
props: {
feeds: Array,
active_button: String,
},
methods: {
},
}
</script>

View File

@@ -0,0 +1,159 @@
<template>
<meta-head title="Загрузить музыку"></meta-head>
<div class="mt-16 container mx-auto px-2 md:px-6 2xl:px-28 buttons-filter-line">
<form @submit.prevent="submit" class=" bg-indigo-200 shadow-classic rounded-md p-5">
<div class="mb-4 flex items-center text-gray-light text-lg font-medium">
<inertia-link :href="route('profile.user', $page.props.auth.user.username)" class="block hover:underline">
Вернуться
</inertia-link>
<span class="px-3">/</span>
<h1 class="text-gray">Загрузка музыки</h1>
</div>
<div class="space-y-5">
<div class="flex flex-col">
<text-input v-model="form.title" :error="form.errors.title" type="text" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Название" />
</div>
<div class="flex flex-col">
<textarea-input v-model="form.body" :error="form.errors.body" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md" cols="30" rows="4" label="Описание" />
</div>
<div class="flex flex-col">
<file-input
v-model="form.preview"
accept="image/png, image/jpeg, image/jpg"
:error="form.errors.preview"
label="Загрузить превью"
/>
</div>
<div class="flex flex-col">
<file-input-multiple
@fileTime='saveTimeFile'
v-model="form.musics"
accept=".mp3"
:error="form.errors.musics"
label="Выбрать музыку"
/>
</div>
<div class="text-gray-light">
<input class="w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md" placeholder="#tags" type="text">
</div>
<div>
<div class="text-gray-light text-lg mb-2">Тип контента</div>
<div class="flex space-x-6">
<div class="flex items-center">
<input id="feed-paid-1" v-model="paid" value="0" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="feed-paid-1" class="select-none ml-3 text-gray">Бесплатный</label>
</div>
<div class="flex items-center">
<input id="feed-paid-2" v-model="paid" value="1" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="feed-paid-2" class="select-none ml-3 text-gray">Платный</label>
</div>
</div>
</div>
<div class="space-y-5" v-if="contentPaid == 1">
<div class="flex flex-col">
<text-input v-model="form.price" :error="form.errors.price" type="number" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Цена" />
</div>
<div class="flex flex-col">
<file-input-multiple
@fileTime='savePaidTimeFile'
v-model="form.musics_paid"
accept=".mp3"
:error="form.errors.musics_paid"
label="Выбрать музыку"
/>
</div>
</div>
</div>
<div class="mt-12 flex flex-wrap -my-1 -mx-3">
<progress
class="mx-3 my-1 w-full"
v-if="form.progress"
:value="form.progress.percentage"
max="100"
>
{{ form.progress.percentage }}%
</progress>
<loading-button :loading="form.processing" class="mx-3 my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-orange focus:outline-none" type="submit">
Создать
</loading-button>
<button type="button"
class="mx-3 my-1 transition shadow-none hover:shadow-classic inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-indigo-300 focus:outline-none">
Отменить
</button>
</div>
</form>
</div>
</template>
<script>
import Layout from "@/Shared/Layout";
import MetaHead from "@/Shared/MetaHead";
import TextInput from "@/Shared/Form/TextInput";
import FileInputMultiple from "@/Shared/Form/FileInputMultiple";
import FileInput from "@/Shared/Form/FileInput";
import TextareaInput from "@/Shared/Form/TextareaInput";
import LoadingButton from "@/Shared/Form/LoadingButton";
import { useForm } from "@inertiajs/inertia-vue3";
export default {
layout: Layout,
components: {
MetaHead,
TextInput,
FileInput,
FileInputMultiple,
LoadingButton,
TextareaInput,
},
watch: {
paid(value) {
this.contentPaid = value;
this.form.is_paid = value;
},
},
data() {
return {
paid: 0,
contentPaid: 0,
};
},
setup() {
const form = useForm({
title: null,
body: null,
preview: null,
musics: null,
musics_paid: null,
price: null,
is_paid: 0,
times: [],
times_paid: [],
});
const submit = () => {
form.post(route("music.store"));
};
const saveTimeFile = (time) => {
form.times.push(time);
};
const savePaidTimeFile = (time) => {
form.times_paid.push(time);
};
return { form, submit, saveTimeFile, savePaidTimeFile };
},
};
</script>

View File

@@ -0,0 +1,97 @@
<template>
<meta-head title="Музыка"></meta-head>
<div class="mb-6 py-3 banner relative bg-center bg-no-repeat bg-cover"
style="background-image: url('/image/bg-home.jpg');">
<div class="h-52 flex justify-center items-center text-center">
<div class="max-w-4xl text-gray px-3">
<h1
class=" text-xl md:text-2xl lg:text-3xl xl:text-5xl text-white font-semibold xl:leading-relaxed">
Музыка</h1>
<inertia-link :href="route('music.create')"
class="mt-8 inline-flex tracking-wide items-center px-8 md:px-12 py-3 border border-white text-sm lg:text-lg text-white rounded-full bg-transparent hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2">
Загрузить
</inertia-link>
</div>
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 buttons-filter-line">
<div class=" relative mb-5">
<div class="absolute inset-y-0 left-3 flex items-center z-[1]">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z" />
</svg>
</div>
<input
class="relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 h-14" placeholder="Поиск"
type="search">
</div>
<div class="grid gap-2 md:gap-5 grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">
<inertia-link :href="route('list.musics')"
:class="[active_button == 'new' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center rounded-md text-white focus:outline-none']">
Новинки
</inertia-link >
<inertia-link :href="route('list.musics')"
:data="{ filter: 'hot' }"
:class="[active_button == 'hot' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center shadow-classic rounded-md text-white focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path
d="M14.422 6.243c-3.57-2.172-1.895-5.238-1.824-5.365A.586.586 0 0012.09 0c-1.837 0-3.276.522-4.276 1.552-1.71 1.76-1.63 4.498-1.597 5.667.004.13.007.242.007.325 0 .868.14 1.67.263 2.377.079.456.147.85.16 1.159.012.331-.048.407-.05.41-.01.01-.081.049-.276.049a.657.657 0 01-.53-.235c-.565-.634-.604-2.365-.496-3.307a.586.586 0 00-.582-.654c-1.521 0-2.658 2.488-2.658 4.712 0 1.046.21 2.07.625 3.045a8.081 8.081 0 001.7 2.527C5.894 19.157 7.89 20 10 20c2.119 0 4.114-.83 5.618-2.34a7.892 7.892 0 002.327-5.605c0-2.692-2.107-4.95-3.523-5.812zM10 18.828c-3.671 0-6.773-3.101-6.773-6.773 0-.893.213-1.83.585-2.571.086-.173.175-.322.263-.447.01.967.163 2.284.841 3.046.366.41.852.627 1.405.627.518 0 .912-.156 1.172-.466.486-.578.337-1.436.148-2.524-.115-.66-.245-1.409-.245-2.176 0-.1-.003-.22-.007-.359-.032-1.107-.099-3.412 1.265-4.817.613-.63 1.467-1.014 2.55-1.145-.123.406-.228.92-.232 1.497-.01 1.27.476 3.085 2.841 4.524 1.145.696 2.96 2.618 2.96 4.811A6.78 6.78 0 0110 18.828z" />
</svg>
Популярные
</inertia-link >
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 my-6">
<button class="button-default text-gray text-lg">Очистить фильтры</button>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 cards-block rounded-md bg-indigo-200 shadow-classic grid gap-2 lg:gap-4 grid-cards p-2 lg:p-5">
<feed
:self-feed="false"
:feeds="feeds"
/>
</div>
</div>
</template>
<script>
import Feed from "@/Shared/Feed/Feed";
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
export default {
layout: Layout,
components: {
MetaHead,
Feed
},
props: {
feeds: Array,
active_button: String,
},
methods: {
},
}
</script>

View File

@@ -0,0 +1,45 @@
<template>
<meta-head title="Профиль юзера"></meta-head>
<profile-header :user='user' :counts='counts' />
<profile-menu :user='user' />
<div class="mt-12 xl:container xl:mx-auto px-2 md:px-3">
<div class="grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 cards-block rounded-md bg-indigo-200 shadow-classic grid gap-2 lg:gap-4 grid-cards p-2 lg:p-5">
<feed
:self-user="user.id"
:self-feed="true"
:feeds="feeds"
/>
</div>
</div>
</template>
<script>
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
import ProfileHeader from '@/Shared/Partials/ProfileHeader'
import ProfileMenu from '@/Shared/Partials/ProfileMenu'
import Feed from "@/Shared/Feed/Feed";
export default {
layout: Layout,
components: {
Feed,
MetaHead,
ProfileHeader,
ProfileMenu,
},
props: {
user: Object,
feeds: Array,
counts: Object,
}
}
</script>

View File

@@ -0,0 +1,155 @@
<template>
<meta-head title="Читаемые пользователи"></meta-head>
<profile-header :user='user' :counts='counts' />
<profile-menu :user='user' />
<div class="mt-12 xl:container xl:mx-auto px-2 md:px-3">
<div class="cards-block rounded-md bg-indigo-200 shadow-classic p-2 lg:p-5">
<div class=" space-y-3 md:space-y-0 md:flex items-center">
<div class="flex-1 md:mr-10">
<div class="relative">
<div class="absolute inset-y-0 left-3 flex items-center z-10">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" > <path fill-rule="evenodd" clip-rule="evenodd" d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z"/> </svg>
</div>
<input v-model="form.search" class=" relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 " placeholder="Поиск" type="search"/>
</div>
</div>
<div class="flex space-x-6 md:mr-10">
<div class="flex items-center">
<input id="user-sex-1" v-model="form.leader" value="1" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-1" class="select-none ml-3 text-gray text-xs md:text-base">По лидерам</label>
</div>
<div class="flex items-center">
<input id="user-sex-2" v-model="form.leader" value="0" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-2" class="select-none ml-3 text-gray text-xs md:text-base">Не по лидерам</label>
</div>
</div>
<div class="text-gray-light">
<button @click="resetSearch()" class="default">Сбросить</button>
</div>
</div>
<div v-show="readers.length" class="mt-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 grid gap-2 lg:gap-4 grid-cards">
<div v-for="reader in readers" :key='reader.id' class="group mb-5 user-card relative">
<div v-if="user.is_auth_user" class="absolute inset-x-0 top-4 z-10 flex justify-center">
<toggle
@clicked='leader'
:user_id='reader.id'
:enabled="reader.is_leader"
textin='Сделать лидером' textout='Убрать лидера' />
</div>
<div class="absolute inset-x-0 bottom-4 z-10 flex justify-center">
<div class="flex flex-col items-center">
<inertia-link :href="route('profile.user', reader.username)" class="block flex-shrink-0">
<user-avatar :user='reader' size='small' class="border border-white shadow-classic h-20 w-20 text-lg" />
</inertia-link>
<inertia-link :href="route('profile.user', reader.username)" class="mt-2 block text-white text-sm text-center">
<p>{{reader.name}}</p>
<p class="text-xs">{{reader.username}}</p>
</inertia-link>
</div>
</div>
<div class="gradient-profile relative overflow-hidden">
<user-banner class="w-full h-72 bg-indigo-300" :user='reader' size='banner' />
</div>
<div v-if="user.is_auth_user" class="transition-opacity sm:opacity-0 group-hover:opacity-100 absolute w-full text-center">
<button @click="susbscribe(reader.id)" class="leading-none focus:outline-none hover:underline text-sm text-orange-dark">Отписаться</button>
</div>
</div>
</div>
</div>
<div v-show="readers.length == 0">
<p class=" text-center md:text-2xl text-gray-light">Пользователи не найдены</p>
</div>
</div>
</template>
<script>
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
import ProfileHeader from '@/Shared/Partials/ProfileHeader'
import ProfileMenu from '@/Shared/Partials/ProfileMenu'
import UserAvatar from '@/Shared/Misc/UserAvatar'
import UserBanner from '@/Shared/Misc/UserBanner'
import Toggle from '@/Shared/Form/Toggle'
import filter from 'lodash/filter';
import pickBy from 'lodash/pickBy';
import throttle from 'lodash/throttle';
import { Inertia } from "@inertiajs/inertia";
export default {
layout: Layout,
components: {
MetaHead,
Toggle,
UserAvatar,
UserBanner,
ProfileHeader,
ProfileMenu,
},
props: {
user: Object,
readers: Array,
counts: Object,
filters: Object,
},
data() {
return {
form: {
search: this.filters.search,
leader: this.filters.leader,
},
}
},
watch: {
form: {
handler: throttle(function() {
let query = pickBy(this.form)
const params = Object.keys(query).length ? query : { remember: 'forget' };
const url = route('profile.readers', this.user.username);
Inertia.get(url, params, { replace: true, preserveScroll: true, preserveState: true } )
}, 300),
deep: true,
},
},
methods:{
resetSearch(){
this.form.search = '';
this.form.leader = '';
},
susbscribe(user_id)
{
Inertia.post(route('users.subs', user_id), {}, { preserveScroll: true, preserveState: true })
},
leader(user_id)
{
let current_user = filter(this.readers, function (x) {
return x.id === user_id;
});
if(current_user){
current_user = current_user[0];
Inertia.post(route('users.leader', user_id), {vote: current_user.is_leader}, { preserveScroll: true, preserveState: true })
}
}
}
}
</script>

View File

@@ -0,0 +1,136 @@
<template>
<meta-head title="Подписчики"></meta-head>
<profile-header :user='user' :counts='counts' />
<profile-menu :user='user' />
<div class="mt-12 xl:container xl:mx-auto px-2 md:px-3">
<div class="cards-block rounded-md bg-indigo-200 shadow-classic p-2 lg:p-5">
<div class=" space-y-3 md:space-y-0 md:flex items-center">
<div class="flex-1 md:mr-10">
<div class="relative">
<div class="absolute inset-y-0 left-3 flex items-center z-10">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" > <path fill-rule="evenodd" clip-rule="evenodd" d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z"/> </svg>
</div>
<input v-model="form.search" class=" relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 " placeholder="Поиск" type="search"/>
</div>
</div>
<div class="flex space-x-6 md:mr-10">
<div class="flex items-center">
<input id="user-sex-1" v-model="form.sub" value="1" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-1" class="select-none ml-3 text-gray text-xs md:text-base">По подписчикам</label>
</div>
<div class="flex items-center">
<input id="user-sex-2" v-model="form.sub" value="0" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-2" class="select-none ml-3 text-gray text-xs md:text-base">Не по подписчикам</label>
</div>
</div>
<div class="text-gray-light">
<button @click="resetSearch()" class="default">Сбросить</button>
</div>
</div>
<div v-show="subscribers.length" class="mt-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 grid gap-2 lg:gap-4 grid-cards">
<div v-for="subscriber in subscribers" :key='subscriber.id' class=" user-card relative">
<div v-if="user.is_auth_user" class="absolute inset-x-0 top-4 z-10 flex justify-center">
<toggle
@clicked='susbscribe'
:user_id='subscriber.id'
:enabled="subscriber.is_sub"
textin='Подписаться' textout='Отписаться' />
</div>
<div class="absolute inset-x-0 bottom-4 z-10 flex justify-center">
<div class="flex flex-col items-center">
<inertia-link :href="route('profile.user', subscriber.username)" class="block flex-shrink-0">
<user-avatar :user='subscriber' size='small' class="border border-white shadow-classic h-20 w-20 text-lg" />
</inertia-link>
<inertia-link :href="route('profile.user', subscriber.username)" class="mt-2 block text-white text-sm text-center">
<p>{{subscriber.name}}</p>
<p class="text-xs">{{subscriber.username}}</p>
</inertia-link>
</div>
</div>
<div class="gradient-profile relative overflow-hidden">
<user-banner class="w-full h-72 bg-indigo-300" :user='subscriber' size='banner' />
</div>
</div>
</div>
</div>
<div v-show="subscribers.length == 0">
<p class=" text-center md:text-2xl text-gray-light">Пользователи не найдены</p>
</div>
</div>
</template>
<script>
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
import ProfileHeader from '@/Shared/Partials/ProfileHeader'
import ProfileMenu from '@/Shared/Partials/ProfileMenu'
import UserAvatar from '@/Shared/Misc/UserAvatar'
import UserBanner from '@/Shared/Misc/UserBanner'
import Toggle from '@/Shared/Form/Toggle'
import pickBy from 'lodash/pickBy';
import throttle from 'lodash/throttle';
import { Inertia } from "@inertiajs/inertia";
export default {
layout: Layout,
components: {
MetaHead,
Toggle,
UserAvatar,
UserBanner,
ProfileHeader,
ProfileMenu,
},
props: {
user: Object,
subscribers: Array,
counts: Object,
filters: Object,
},
data() {
return {
form: {
search: this.filters.search,
sub: this.filters.sub,
},
}
},
watch: {
form: {
handler: throttle(function() {
let query = pickBy(this.form)
const params = Object.keys(query).length ? query : { remember: 'forget' };
const url = route('profile.subs', this.user.username);
Inertia.get(url, params, { replace: true, preserveScroll: true, preserveState: true } )
}, 300),
deep: true,
},
},
methods:{
resetSearch(){
this.form.search = '';
this.form.sub = '';
},
susbscribe(user_id)
{
Inertia.post(route('users.subs', user_id), {}, { preserveScroll: true, preserveState: true })
},
}
}
</script>

View File

@@ -0,0 +1,84 @@
<template>
<meta-head title="Доход"></meta-head>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="mt-16 shadow-classic rounded-md bg-indigo-200">
<div class="flex flex-col md:grid grid-cols-6 lg:grid-cols-5">
<settings-menu />
<div class="col-span-4">
<div class="border-b border-indigo-300">
<div class="flex justify-between px-4 2xl:px-28 my-4 lg:my-8">
<div class="flex flex-col text-white">
<span class="text-lg">Баланс:</span>
<span class="text-3xl">{{$page.props.balance}}</span>
</div>
<button @click="testPaid" type="button"
class="my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-pink focus:outline-none">
Пополнить
</button>
<button type="button"
class="my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-orange focus:outline-none">
Вывести
</button>
</div>
</div>
<div class="my-4 lg:my-8">
<div class="py-4 px-4 2xl:px-28 md:text-lg text-white">История операций:</div>
<div class="divide-y divide-indigo-300 ">
<div v-for="point in points" :key="point.id" class="py-4 px-4 2xl:px-28 lg:items-center flex flex-col lg:grid gap-2 lg:gap-5 grid-cols-12">
<div class="col-span-5 flex items-center">
<div class="flex-shrink-0 mr-3 lg:mr-8">
<svg :class="[point.direction == 0 ? 'text-green rotate-90' : '-rotate-90 text-red', 'transform w-8 h-8']">
<use xlink:href="#arrow-up-circle"></use>
</svg>
</div>
<div class="flex flex-col">
<p class="truncate text-base lg:text-lg font-semibold text-gray">{{point.date}}</p>
<p class="truncate lg:mt-1 text-base text-gray-light">{{point.time}}</p>
</div>
</div>
<div class="col-span-2 text-left lg:text-center text-white xl:text-xl font-semibold">
{{point.point}}
</div>
<div class="col-span-5 text-left lg:text-right text-gray-light xl:text-lg">
{{point.type}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import Layout from '@/Shared/Layout'
import SettingsMenu from '@/Shared/LayoutParts/SettingsMenu'
import MetaHead from '@/Shared/MetaHead'
export default {
layout: Layout,
components: {
MetaHead,
SettingsMenu,
},
props:{
points: Array,
},
methods: {
testPaid(){
Inertia.post(route("users.testPaid"), {
preserveScroll: true,
preserveState: true,
});
}
},
}
</script>

View File

@@ -0,0 +1,128 @@
<template>
<meta-head title="Оповещения"></meta-head>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="mt-16 shadow-classic rounded-md bg-indigo-200">
<div class="flex flex-col md:grid grid-cols-6 lg:grid-cols-5">
<settings-menu />
<div class="col-span-4">
<div data-simplebar class="max-h-[500px] overflow-auto my-4 lg:my-8">
<div class="divide-y divide-indigo-300">
<div class="py-4 px-4 2xl:px-28 lg:items-center flex flex-col lg:grid gap-2 lg:gap-5 grid-cols-12 md:space-x-4">
<div class="col-span-4 flex items-center">
<div class="flex-shrink-0 mr-5">
<div class="w-14 h-14 md:w-20 md:h-20 rounded-full bg-cover bg-center" style="background-image: url('/image/card1.jpg');"></div>
</div>
<div class="flex flex-col">
<p class="truncate text-base lg:text-lg font-semibold text-orange">Сергей Сергеев</p>
<p class="truncate lg:mt-1 text-base text-gray-light">10 сен в 17:20</p>
</div>
</div>
<div class="col-span-6 text-white xl:text-xl">
оценил(а) вашу фотографию
</div>
<div class="col-span-2 flex lg:justify-end">
<img class="object-cover w-20 h-20" src="/image/user_card2.png" alt="">
</div>
</div>
<div class="py-4 px-4 2xl:px-28 lg:items-center flex flex-col lg:grid gap-2 lg:gap-5 grid-cols-12 md:space-x-4">
<div class="col-span-4 flex items-center">
<div class="flex-shrink-0 mr-5">
<div class="w-14 h-14 md:w-20 md:h-20 rounded-full bg-cover bg-center" style="background-image: url('/image/card1.jpg');"></div>
</div>
<div class="flex flex-col">
<p class="truncate text-base lg:text-lg font-semibold text-orange">Сергей Сергеев</p>
<p class="truncate lg:mt-1 text-base text-gray-light">10 сен в 17:20</p>
</div>
</div>
<div class="col-span-6 flex flex-col text-white xl:text-xl">
<span>оставил(а) комментарий:</span>
<span class="truncate text-base text-gray-light">Очень красиво</span>
</div>
<div class="col-span-2 flex lg:justify-end">
<a href="#" class="text-pink text-lg">Перейти</a>
</div>
</div>
<div class="py-4 px-4 2xl:px-28 lg:items-center flex flex-col lg:grid gap-2 lg:gap-5 grid-cols-12 md:space-x-4">
<div class="col-span-4 flex items-center">
<div class="flex-shrink-0 mr-5">
<div class="w-14 h-14 md:w-20 md:h-20 rounded-full bg-cover bg-center" style="background-image: url('/image/card1.jpg');"></div>
</div>
<div class="flex flex-col">
<p class="truncate text-base lg:text-lg font-semibold text-orange">Сергей Сергеев</p>
<p class="truncate lg:mt-1 text-base text-gray-light">10 сен в 17:20</p>
</div>
</div>
<div class="col-span-6 flex flex-col text-white xl:text-xl">
<span>оставил(а) комментарий:</span>
<span class="truncate text-base text-gray-light">Очень красиво</span>
</div>
<div class="col-span-2 flex lg:justify-end">
<a href="#" class="text-pink text-lg">Перейти</a>
</div>
</div>
<div class="py-4 px-4 2xl:px-28 lg:items-center flex flex-col lg:grid gap-2 lg:gap-5 grid-cols-12 md:space-x-4">
<div class="col-span-4 flex items-center">
<div class="flex-shrink-0 mr-5">
<div class="w-14 h-14 md:w-20 md:h-20 rounded-full bg-cover bg-center" style="background-image: url('/image/card1.jpg');"></div>
</div>
<div class="flex flex-col">
<p class="truncate text-base lg:text-lg font-semibold text-orange">Сергей Сергеев</p>
<p class="truncate lg:mt-1 text-base text-gray-light">10 сен в 17:20</p>
</div>
</div>
<div class="col-span-6 flex flex-col text-white xl:text-xl">
<span>оставил(а) комментарий:</span>
<span class="truncate text-base text-gray-light">Очень красиво</span>
</div>
<div class="col-span-2 flex lg:justify-end">
<a href="#" class="text-pink text-lg">Перейти</a>
</div>
</div>
<div class="py-4 px-4 2xl:px-28 lg:items-center flex flex-col lg:grid gap-2 lg:gap-5 grid-cols-12 md:space-x-4">
<div class="col-span-4 flex items-center">
<div class="flex-shrink-0 mr-5">
<div class="w-14 h-14 md:w-20 md:h-20 rounded-full bg-cover bg-center" style="background-image: url('/image/card1.jpg');"></div>
</div>
<div class="flex flex-col">
<p class="truncate text-base lg:text-lg font-semibold text-orange">Сергей Сергеев</p>
<p class="truncate lg:mt-1 text-base text-gray-light">10 сен в 17:20</p>
</div>
</div>
<div class="col-span-6 flex flex-col text-white xl:text-xl">
<span>оставил(а) комментарий:</span>
<span class="truncate text-base text-gray-light">Очень красиво</span>
</div>
<div class="col-span-2 flex lg:justify-end">
<a href="#" class="text-pink text-lg">Перейти</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Layout from '@/Shared/Layout'
import SettingsMenu from '@/Shared/LayoutParts/SettingsMenu'
import MetaHead from '@/Shared/MetaHead'
export default {
layout: Layout,
components: {
MetaHead,
SettingsMenu,
},
methods: {
},
}
</script>

View File

@@ -0,0 +1,195 @@
<template>
<meta-head title="Мои настройки"></meta-head>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="mt-16 shadow-classic rounded-md bg-indigo-200">
<div class="flex flex-col md:grid grid-cols-6 lg:grid-cols-5">
<settings-menu />
<div class="col-span-4">
<div class="m-4 lg:m-8">
<div class="flex flex-col xl:flex-row">
<div class="xl:mr-24">
<div class="flex items-center">
<div class="flex-shrink-0 mr-5">
<user-avatar :user='user' class="w-20 h-20 text-lg" />
</div>
<div class="flex flex-col">
<p class="text-base lg:text-xl font-semibold text-gray">{{user.name}}</p>
<p class="lg:mt-1 text-base text-gray-light">@{{user.username}}</p>
</div>
</div>
<input ref="fileavatar" class="hidden" accept="image/png, image/jpeg, image/jpg" type="file" @change="previewFiles">
<input ref="filebanner" class="hidden" accept="image/png, image/jpeg, image/jpg" type="file" @change="previewFilesBanner">
<div>
<div v-if="$page.props.errors.avatar" class="text-red lg:text-lg">
{{$page.props.errors.avatar}}
</div>
<button v-if="!user.photo_path" @click="changeAvatar" class="hover:underline mt-2 text-left lg:mt-5 default lg:text-lg text-orange">
Изменить фото профиля
</button>
<button v-else @click="removeAvatar" class="hover:underline mt-2 text-left lg:mt-5 default lg:text-lg text-red">
Удалить фото
</button>
</div>
</div>
<div class="mt-5 xl:mt-0">
<div class="flex items-center">
<div class="flex-shrink-0 mr-5">
<user-banner class="w-60 lg:w-96 h-20 rounded-xl bg-indigo-300" :user='user' size='banner' />
</div>
</div>
<div>
<div v-if="$page.props.errors.banner" class="text-red lg:text-lg">
{{$page.props.errors.banner}}
</div>
<button v-if="!user.banner_path" @click="changeBanner" class="hover:underline mt-2 text-left lg:mt-5 default lg:text-lg text-orange">
Изменить баннер профиля
</button>
<button v-else @click="removeBanner" class="hover:underline mt-2 text-left lg:mt-5 default lg:text-lg text-red">
Удалить баннер
</button>
</div>
</div>
</div>
<form @submit.prevent="submit" class="mt-10 grid gap-4 lg:gap-10 grid-cols-1 lg:grid-cols-2">
<div class="flex flex-col">
<text-input v-model="form.first_name" :error="form.errors.first_name" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Имя" />
</div>
<div class="flex flex-col">
<text-input v-model="form.last_name" :error="form.errors.last_name" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Фамилия" />
</div>
<div class="flex flex-col">
<text-input v-model="form.username" :error="form.errors.username" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Тег" />
</div>
<div class="flex flex-col">
<text-input v-model="form.date_of_birth" :error="form.errors.date_of_birth" type="date" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Дата рождения" />
</div>
<div class="flex flex-col">
<text-input v-model="form.email" :error="form.errors.email" type="email" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Почта" />
</div>
<div class="flex flex-col">
<text-input v-model="form.phone" :error="form.errors.phone" type="tel" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Телефон" />
</div>
<div>
<div class="text-gray-light text-lg mb-2">Пол</div>
<div class="flex space-x-6">
<div class="flex items-center">
<input id="user-sex-1" v-model="form.sex" value="1" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-1" class="select-none ml-3 text-gray">Женский</label>
</div>
<div class="flex items-center">
<input id="user-sex-2" v-model="form.sex" value="2" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-2" class="select-none ml-3 text-gray">Мужской</label>
</div>
</div>
</div>
<div class="lg:col-span-2">
<div class="flex flex-col">
<textarea-input label="О себе" v-model="form.about" :error="form.errors.about" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md" cols="30" rows="2"></textarea-input>
</div>
</div>
<div class="flex flex-wrap -my-1 -mx-3">
<loading-button :loading="form.processing" class="mx-3 my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-orange focus:outline-none" type="submit">Сохранить</loading-button>
<button type="button"
class="mx-3 my-1 default text-lg text-orange">
Удалить аккаунт
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Layout from '@/Shared/Layout'
import SettingsMenu from '@/Shared/LayoutParts/SettingsMenu'
import LoadingButton from "@/Shared/Form/LoadingButton";
import UserAvatar from '@/Shared/Misc/UserAvatar'
import UserBanner from '@/Shared/Misc/UserBanner'
import MetaHead from '@/Shared/MetaHead'
import TextInput from '@/Shared/Form/TextInput'
import TextareaInput from '@/Shared/Form/TextareaInput'
import { useForm } from "@inertiajs/inertia-vue3";
import { Inertia } from "@inertiajs/inertia";
import { toRefs } from "vue";
export default {
layout: Layout,
components: {
MetaHead,
UserAvatar,
UserBanner,
TextInput,
TextareaInput,
LoadingButton,
SettingsMenu,
},
props: {
user: Object,
},
methods: {
previewFilesBanner(event){
const file = event.target.files[0];
Inertia.post(route("image.banner"), {
_method: 'put',
banner: file,
})
},
previewFiles(event){
const file = event.target.files[0];
Inertia.post(route("image.avatar"), {
_method: 'put',
avatar: file,
})
},
changeBanner(){
this.$refs.filebanner.click();
},
removeBanner(){
Inertia.post(route("image.banner.remove"), {
_method: 'delete',
})
},
changeAvatar(){
this.$refs.fileavatar.click();
},
removeAvatar(){
Inertia.post(route("image.avatar.remove"), {
_method: 'delete',
})
}
},
setup(props) {
const { user } = toRefs(props);
const form = useForm({
first_name: user.value.first_name,
last_name: user.value.last_name,
username: user.value.username,
email: user.value.email,
phone: user.value.phone,
sex: user.value.sex,
date_of_birth: user.value.date_of_birth,
about: user.value.about,
password: null,
});
const submit = () => {
form.put(route("users.update", user.value.id));
};
return { form, submit }
},
}
</script>

View File

@@ -0,0 +1,47 @@
<template>
<meta-head title="Покупки"></meta-head>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="mt-16 shadow-classic rounded-md bg-indigo-200">
<div class="flex flex-col md:grid grid-cols-6 lg:grid-cols-5">
<settings-menu />
<div class="col-span-4">
<div class="m-4 lg:m-8 grid grid-cols-2 sm:grid-cols-3 xl:grid-cols-4 gap-2 lg:gap-4">
<inertia-link :href="route('setting.show.purchases', feed.id)" v-for="feed in feeds" :key="feed.id" class="block contain relative overflow-hidden">
<feed-header-misc :count="1" :type="feed.type" />
<div>
<feed-preview class="w-full h-36 md:h-72 object-cover" :type="feed.type" :source='feed.preview' />
</div>
<p class="mt-2 text-gray-light text-sm">Цена: {{feed.price}}</p>
<p class="mt-2 text-gray-light text-sm">Дата покупки: {{feed.purchase_date}}</p>
</inertia-link>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Layout from "@/Shared/Layout";
import SettingsMenu from "@/Shared/LayoutParts/SettingsMenu";
import MetaHead from "@/Shared/MetaHead";
import Feed from "@/Shared/Feed/Feed";
import FeedHeaderMisc from "@/Shared/Feed/HeaderMisc";
import FeedPreview from "@/Shared/Feed/FeedPreview";
export default {
layout: Layout,
components: {
Feed,
MetaHead,
SettingsMenu,
FeedHeaderMisc,
FeedPreview,
},
props: {
feeds: Array,
},
methods: {},
};
</script>

View File

@@ -0,0 +1,95 @@
<template>
<meta-head title="Скачать медиа контент"></meta-head>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="mt-16 shadow-classic rounded-md bg-indigo-200">
<div class="flex flex-col md:grid grid-cols-6 lg:grid-cols-5">
<settings-menu />
<div class="col-span-4 p-5">
<div class="mb-4 flex items-center text-gray-light text-lg font-medium">
<inertia-link :href="route('setting.purchases')" class="block hover:underline">Вернуться</inertia-link>
<span class="px-3">/</span>
<h1 class="text-gray">Скачать медиа контент</h1>
</div>
<div class="my-8 flex items-center justify-between">
<inertia-link :href="route('profile.user', seller.username)" class="flex items-center">
<div class="flex-shrink-0 block mr-2 md:mr-4">
<user-avatar :user='seller' size='small' class="w-10 h-10 md:w-16 md:h-16 text-lg" />
</div>
<div class="flex flex-col">
<span class="text-sm md:text-base block font-medium text-white">{{ seller.name }}</span>
<span class="text-xs text-gray-light">продавец</span>
</div>
</inertia-link>
<div class="text-right">
<p class="mt-2 text-gray-light text-sm">Цена: {{purchase.price}}</p>
<p class="mt-2 text-gray-light text-sm">Дата покупки: {{purchase.purchase_date}}</p>
</div>
</div>
<div v-if="purchase.title" class="text-lg text-gray font-semibold">
{{purchase.title}}
</div>
<div v-if="purchase.body" class="text-lg mt-4 text-gray-light" v-html="purchase.body"></div>
<div class="mt-4 ">
<component
:is="currentTypeNode"
:purchase="purchase"
></component>
</div>
<div class="mt-12 flex -mx-3 -my-1 flex-wrap">
<a :href="route('download.purchases', purchase.id)" class="mx-3 my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-orange focus:outline-none">
Скачать архив
</a>
<inertia-link :href="route('setting.purchases')"
class="mx-3 my-1 transition shadow-none hover:shadow-classic inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-indigo-300 focus:outline-none">
Вернуться
</inertia-link>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Layout from "@/Shared/Layout";
import MetaHead from "@/Shared/MetaHead";
import PurchaseImages from "@/Shared/Purchase/PurchaseImages";
import PurchaseMusics from "@/Shared/Purchase/PurchaseMusics";
import SettingsMenu from "@/Shared/LayoutParts/SettingsMenu";
import UserAvatar from '@/Shared/Misc/UserAvatar'
export default {
layout: Layout,
components: {
MetaHead,
PurchaseImages,
PurchaseMusics,
SettingsMenu,
UserAvatar,
},
props: {
purchase: Object,
seller: Object,
},
computed: {
currentTypeNode() {
return "purchase-" + this.purchase.type;
},
},
};
</script>

View File

@@ -0,0 +1,78 @@
<template>
<meta-head title="Тарифы"></meta-head>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="mt-16 shadow-classic rounded-md bg-indigo-200">
<div class="flex flex-col md:grid grid-cols-6 lg:grid-cols-5">
<settings-menu />
<div class="col-span-4">
<div class="mx-4 2xl:mx-28 my-8">
<h2 class="text-xl lg:text-2xl xl:text-4xl text-white font-semibold">
Выберите тариф, который подходит именно вам
</h2>
<p class="mt-4 lg:text-xl xl:text-2xl text-white">
Более 1 млн фотографий, видео и музыки в постоянном доступе для вас!
</p>
<p v-if="lastSubscription" class="mt-4 xl:text-xl text-green">
Дата окончания подписки:
<span class="block md:inline-block">{{ lastSubscription.endDateTime }} ({{ lastSubscription.package.name }})</span>
</p>
<div v-for="plan in plans" :key='plan.id' :class="[lastSubscription?.package.id === plan.id ? 'border-l-4 lg:border-l-8 border-orange' : '' ,'mt-7 p-7 xl:mt-14 xl:p-14 shadow-classic rounded-md bg-indigo-100']">
<div class="flex flex-col lg:grid grid-cols-6 gap-3 items-center">
<div class="col-start-1 col-end-4 flex flex-col items-center lg:items-start text-center lg:text-left">
<span class="text-xl md:text-2xl lg:text-3xl xl:text-4xl text-white font-medium">{{plan.name}}</span>
<span class="mt-4 text-lg xl:text-2xl text-gray-light">For individuals that need advanced recording & editing.</span>
</div>
<div class="col-start-5 col-end-7 flex flex-col items-center">
<span class="text-3xl lg:text-4xl xl:text-6xl text-white font-bold">{{plan.price}}</span>
<button type="button"
@click="subsPlan(plan.id)"
:class="[lastSubscription?.package.id === plan.id ? 'bg-white border border-green text-green' : 'text-white bg-pink hover:shadow-pink' , 'mt-4 my-1 transition shadow-none inline-flex items-center px-8 py-3 justify-center text-base rounded-3xl focus:outline-none']">
<span v-if="lastSubscription?.package.id === plan.id">
активен
</span>
<span v-else>
выбрать тариф
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import Layout from '@/Shared/Layout'
import SettingsMenu from '@/Shared/LayoutParts/SettingsMenu'
import MetaHead from '@/Shared/MetaHead'
export default {
layout: Layout,
components: {
MetaHead,
SettingsMenu,
},
props:{
plans: Array,
lastSubscription: Object,
},
methods: {
subsPlan(id) {
Inertia.post(route("users.plan", id), {
preserveScroll: true,
preserveState: true,
});
},
},
}
</script>

View File

@@ -0,0 +1,132 @@
<template>
<meta-head title="Пользователи"></meta-head>
<div class="mt-16 container mx-auto px-2 md:px-6 2xl:px-28 buttons-filter-line">
<div class="md:flex items-center mb-5">
<div class="flex-1 relative mb-5 md:mb-0 md:mr-10">
<div class="absolute inset-y-0 left-3 flex items-center z-[1]">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z" />
</svg>
</div>
<input
v-model="form.search"
class="relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 h-14" placeholder="Поиск"
type="search">
</div>
<div>
<div class="flex space-x-6">
<div class="flex items-center">
<input id="user-sex-1" v-model="form.sex" value="1" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-1" class="select-none ml-3 text-gray text-xs md:text-base">Женский</label>
</div>
<div class="flex items-center">
<input id="user-sex-2" v-model="form.sex" value="2" type="radio" class="h-5 w-5 text-orange border-gray-light focus:ring-transparent focus:ring-offset-transparent">
<label for="user-sex-2" class="select-none ml-3 text-gray text-xs md:text-base">Мужской</label>
</div>
</div>
</div>
</div>
<div v-show="users.length" class="grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 cards-block rounded-md bg-indigo-200 shadow-classic grid gap-2 lg:gap-4 grid-cards p-2 lg:p-5">
<div v-for="user in users" :key='user.id' class=" user-card relative">
<div class="absolute inset-x-0 top-4 z-10 flex justify-center">
<toggle
@clicked='susbscribe'
:user_id='user.id'
:enabled="user.is_sub"
textin='Подписаться' textout='Отписаться' />
</div>
<div class="absolute inset-x-0 bottom-4 z-10 flex justify-center">
<div class="flex flex-col items-center">
<inertia-link :href="route('profile.user', user.username)" class="block flex-shrink-0">
<user-avatar :user='user' size='small' class="border border-white shadow-classic h-20 w-20 text-lg" />
</inertia-link>
<inertia-link :href="route('profile.user', user.username)" class="mt-2 block text-white text-sm text-center">
<p class="">{{user.name}}</p>
<p class="text-xs">{{user.username}}</p>
</inertia-link>
</div>
</div>
<div class="gradient-profile relative overflow-hidden">
<user-banner class="h-72 bg-indigo-300" :user='user' size='banner' />
</div>
</div>
</div>
<div v-show="users.length == 0">
<p class=" text-center md:text-2xl text-gray-light ">Пользователи не найдены</p>
</div>
</div>
</template>
<script>
import MetaHead from '@/Shared/MetaHead'
import Toggle from '@/Shared/Form/Toggle'
import UserAvatar from '@/Shared/Misc/UserAvatar'
import UserBanner from '@/Shared/Misc/UserBanner'
import Layout from '@/Shared/Layout'
import throttle from 'lodash/throttle'
import pickBy from 'lodash/pickBy'
import { Inertia } from "@inertiajs/inertia";
export default {
components: {
MetaHead,
UserAvatar,
UserBanner,
Toggle,
},
layout: Layout,
props: {
users: Array,
filters: Object,
},
data() {
return {
form: {
search: this.filters.search,
sex: this.filters.sex,
},
}
},
watch: {
form: {
handler: throttle(function() {
let query = pickBy(this.form)
Inertia.get(this.route('users.index', Object.keys(query).length ? query : { remember: 'forget' }),
{},
{
preserveScroll: true,
preserveState: true,
}
)
}, 300),
deep: true,
},
},
methods:{
susbscribe(user_id)
{
Inertia.post(route('users.subs', user_id), {}, { preserveScroll: true, preserveState: true })
}
}
}
</script>

View File

@@ -0,0 +1,101 @@
<template>
<meta-head title="Загрузить видео"></meta-head>
<div class="mt-16 container mx-auto px-2 md:px-6 2xl:px-28 buttons-filter-line">
<form @submit.prevent="submit" class=" bg-indigo-200 shadow-classic rounded-md p-5">
<div class="mb-4 flex items-center text-gray-light text-lg font-medium">
<inertia-link :href="route('profile.user', $page.props.auth.user.username)" class="block hover:underline">
Вернуться
</inertia-link>
<span class="px-3">/</span>
<h1 class="text-gray">Загрузка видео</h1>
</div>
<div class="space-y-5">
<div class="flex flex-col">
<text-input v-model="form.title" :error="form.errors.title" type="text" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light" label="Название" />
</div>
<div class="flex flex-col">
<textarea-input v-model="form.body" :error="form.errors.body" class="focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md" cols="30" rows="4" label="Описание" />
</div>
<div class="flex flex-col">
<file-input-multiple
v-model="form.videos"
accept=".mp4"
:error="form.errors.videos"
label="Выбрать видео"
/>
</div>
<div class="flex flex-col">
<file-input
v-model="form.preview"
accept="image/png, image/jpeg, image/jpg"
:error="form.errors.preview"
label="Загрузить превью"
/>
</div>
<div class="text-gray-light">
<input class="w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md" placeholder="#tags" type="text">
</div>
</div>
<div class="mt-12 flex flex-wrap -my-1 -mx-3">
<progress
class="mx-3 my-1 w-full"
v-if="form.progress"
:value="form.progress.percentage"
max="100"
>
{{ form.progress.percentage }}%
</progress>
<loading-button :loading="form.processing" class="mx-3 my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-orange focus:outline-none" type="submit">
Создать
</loading-button>
<button type="button"
class="mx-3 my-1 transition shadow-none hover:shadow-classic inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-indigo-300 focus:outline-none">
Отменить
</button>
</div>
</form>
</div>
</template>
<script>
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
import TextInput from '@/Shared/Form/TextInput'
import FileInputMultiple from '@/Shared/Form/FileInputMultiple'
import FileInput from '@/Shared/Form/FileInput'
import TextareaInput from '@/Shared/Form/TextareaInput'
import LoadingButton from "@/Shared/Form/LoadingButton";
import { useForm } from "@inertiajs/inertia-vue3";
export default {
components: {
MetaHead,
TextInput,
FileInput,
FileInputMultiple,
LoadingButton,
TextareaInput,
},
layout: Layout,
setup() {
const form = useForm({
title: null,
body: null,
preview: null,
videos: null,
});
const submit = () => {
form.post(route("video.store"));
};
return { form, submit }
},
}
</script>

View File

@@ -0,0 +1,97 @@
<template>
<meta-head title="Видео"></meta-head>
<div class="mb-6 py-3 banner relative bg-center bg-no-repeat bg-cover"
style="background-image: url('/image/bg-home.jpg');">
<div class="h-52 flex justify-center items-center text-center">
<div class="max-w-4xl text-gray px-3">
<h1
class=" text-xl md:text-2xl lg:text-3xl xl:text-5xl text-white font-semibold xl:leading-relaxed">
Видео</h1>
<inertia-link :href="route('video.create')"
class="mt-8 inline-flex tracking-wide items-center px-8 md:px-12 py-3 border border-white text-sm lg:text-lg text-white rounded-full bg-transparent hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2">
Загрузить
</inertia-link>
</div>
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 buttons-filter-line">
<div class=" relative mb-5">
<div class="absolute inset-y-0 left-3 flex items-center z-[1]">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="currentColor">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z" />
</svg>
</div>
<input
class="relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 h-14" placeholder="Поиск"
type="search">
</div>
<div class="grid gap-2 md:gap-5 grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">
<inertia-link :href="route('list.videos')"
:class="[active_button == 'new' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center rounded-md text-white focus:outline-none']">
Новинки
</inertia-link >
<inertia-link :href="route('list.videos')"
:data="{ filter: 'hot' }"
:class="[active_button == 'hot' ? 'bg-orange shadow-classic2' : 'shadow-classic bg-indigo-200 hover:bg-orange' , 'transition inline-flex items-center px-3 py-3 lg:px-6 lg:py-6 xl:px-10 text-sm lg:text-lg justify-center shadow-classic rounded-md text-white focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path
d="M14.422 6.243c-3.57-2.172-1.895-5.238-1.824-5.365A.586.586 0 0012.09 0c-1.837 0-3.276.522-4.276 1.552-1.71 1.76-1.63 4.498-1.597 5.667.004.13.007.242.007.325 0 .868.14 1.67.263 2.377.079.456.147.85.16 1.159.012.331-.048.407-.05.41-.01.01-.081.049-.276.049a.657.657 0 01-.53-.235c-.565-.634-.604-2.365-.496-3.307a.586.586 0 00-.582-.654c-1.521 0-2.658 2.488-2.658 4.712 0 1.046.21 2.07.625 3.045a8.081 8.081 0 001.7 2.527C5.894 19.157 7.89 20 10 20c2.119 0 4.114-.83 5.618-2.34a7.892 7.892 0 002.327-5.605c0-2.692-2.107-4.95-3.523-5.812zM10 18.828c-3.671 0-6.773-3.101-6.773-6.773 0-.893.213-1.83.585-2.571.086-.173.175-.322.263-.447.01.967.163 2.284.841 3.046.366.41.852.627 1.405.627.518 0 .912-.156 1.172-.466.486-.578.337-1.436.148-2.524-.115-.66-.245-1.409-.245-2.176 0-.1-.003-.22-.007-.359-.032-1.107-.099-3.412 1.265-4.817.613-.63 1.467-1.014 2.55-1.145-.123.406-.228.92-.232 1.497-.01 1.27.476 3.085 2.841 4.524 1.145.696 2.96 2.618 2.96 4.811A6.78 6.78 0 0110 18.828z" />
</svg>
Популярные
</inertia-link >
</div>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3 my-6">
<button class="button-default text-gray text-lg">Очистить фильтры</button>
</div>
<div class="xl:container xl:mx-auto px-2 md:px-3">
<div class="grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 cards-block rounded-md bg-indigo-200 shadow-classic grid gap-2 lg:gap-4 grid-cards p-2 lg:p-5">
<feed
:self-feed="false"
:feeds="feeds"
/>
</div>
</div>
</template>
<script>
import Feed from "@/Shared/Feed/Feed";
import Layout from '@/Shared/Layout'
import MetaHead from '@/Shared/MetaHead'
export default {
layout: Layout,
components: {
MetaHead,
Feed
},
props: {
feeds: Array,
active_button: String,
},
methods: {
},
}
</script>

View File

@@ -0,0 +1,306 @@
<template>
<div class="col-span-7 md:col-span-5 lg:col-span-3 player-widget">
<div
@click="openFull"
ref="topbar"
class="
player-line
rounded-md
transition-colors
bg-transparent
hover:bg-orange-min
flex
items-center
space-x-3
p-2
cursor-pointer
"
>
<button @click.stop="skipTrack('prev')" class="focus:outline-none text-gray-600 hover:text-gray-800">
<svg
class="w-4 h-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polygon points="19 20 9 12 19 4 19 20"></polygon>
<line x1="5" y1="19" x2="5" y2="5"></line>
</svg>
</button>
<button
@click.stop="toggleAudio"
class="
flex
h-8
items-center
justify-center
w-8
transition-colors
text-gray-600
hover:text-gray-800
"
>
<PlayIcon v-show="!playing" class="w-8 h-8" />
<StopIcon v-show="playing" class="w-8 h-8" />
</button>
<button @click.stop="skipTrack('next')" class="focus:outline-none text-gray-600 hover:text-gray-800">
<svg
class="w-4 h-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polygon points="5 4 15 12 5 20 5 4"></polygon>
<line x1="19" y1="5" x2="19" y2="19"></line>
</svg>
</button>
<div v-show="count_playlist" class="text-base truncate select-none">
{{ currentSong.name }}
</div>
</div>
<teleport to="body">
<div v-if="open_drop">
<div
style="
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 9998;
background: black;
opacity: 0.2;
"
@click="open_drop = false"
/>
<div
ref="dropdown"
class="z-[9999] player-widget-list w-full lg:w-[48rem]"
>
<div class="shadow-classic rounded-md bg-indigo-200">
<div
v-show="count_playlist"
@click.prevent="updateSeek"
class="overflow-hidden bg-orange relative h-2 mt-2 mb-2"
>
<div
:style="{ transform: `translate3d(${playerProgress}, 0, 0)` }"
class="will-change-transform absolute transition-transform h-full bg-white flex items-center justify-end w-full"
>
</div>
</div>
<div
class="
p-2
lg:p-4
rounded-md
items-center
grid grid-cols-1
md:grid-cols-10
cursor-pointer
"
>
<div class="col-span-7 flex items-center space-x-3">
<button @click.stop="skipTrack('prev')" class="focus:outline-none text-gray">
<svg
class="w-4 h-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polygon points="19 20 9 12 19 4 19 20"></polygon>
<line x1="5" y1="19" x2="5" y2="5"></line>
</svg>
</button>
<button
@click.stop="toggleAudio"
class="
flex
h-8
items-center
justify-center
w-8
transition-colors
text-gray
"
>
<PlayIcon v-show="!playing" class="w-8 h-8" />
<StopIcon v-show="playing" class="w-8 h-8" />
</button>
<button @click.stop="skipTrack('next')" class="focus:outline-none text-gray">
<svg
class="w-4 h-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polygon points="5 4 15 12 5 20 5 4"></polygon>
<line x1="19" y1="5" x2="19" y2="19"></line>
</svg>
</button>
<div class="text-gray-light text-base truncate select-none">
{{ currentSong.name }}
</div>
</div>
<div v-show="count_playlist" class="col-span-1 text-center text-gray-light text-xs select-none">
{{ seek }}
</div>
<div v-show="count_playlist" class="col-span-2 mt-2 md:mt-0 md:ml-auto flex items-center">
<input class="w-full custom-input-range" type="range" v-model="volume" @click.stop="" @input="updateVolume(volume)" max="1" step="0.1" />
<span class="text-gray-light ml-1.5 text-xs">{{ volume * 100 + "%" }}</span>
</div>
</div>
<div class="choices-tabs">
<div class="border-b border-indigo-300">
<nav class="-mb-px flex" aria-label="Tabs">
<a v-for="tab in tabs" :key="tab.key" href="#" @click.prevent="changeTab(tab.key)"
:class="[
current_tab === tab.key ? 'border-orange text-white' : 'border-transparent text-gray-light hover:text-white',
'w-1/2 lg:w-1/4 py-3 lg:py-4 px-1 text-center text-sm border-b-2',
]"
>{{tab.name}}</a>
</nav>
</div>
</div>
<div>
<!-- <audio-tab /> -->
<keep-alive>
<component :is="currentTabComponent"></component>
</keep-alive>
</div>
</div>
</div>
</div>
</teleport>
</div>
</template>
<script>
import Popper from "popper.js";
import { PlayIcon } from "@heroicons/vue/solid";
import { StopIcon } from "@heroicons/vue/solid";
import AudioTabNow from "@/Shared/Tabs/AudioTabNow";
import AudioTabLoaded from "@/Shared/Tabs/AudioTabLoaded";
import { mapActions, mapGetters, mapState } from "vuex";
export default {
name: "Player",
components: {
AudioTabNow,
AudioTabLoaded,
PlayIcon,
StopIcon
},
data() {
return {
tabs: [
{key: 'now', name: 'Текущая'},
{key: 'loaded', name: 'Загруженная'},
{key: 'history', name: 'История'},
],
open_drop: false,
popper: null,
volume: 0.5,
};
},
created() {
this.loadExsitPlaylist();
this.changeVolume(this.volume_step);
this.volume = this.volume_step;
},
computed: {
currentTabComponent() {
return 'audio-tab-' + this.current_tab
},
...mapGetters(["playing", "count_playlist", "volume_step"]),
...mapState({
current_tab: (state) => state.player.tab,
seek: (state) => state.player.seek,
duration: (state) => state.player.duration,
playerProgress: (state) => state.player.playerProgress,
currentSong: (state) => state.player.currentSong,
}),
},
watch: {
open_drop(open_drop) {
if (open_drop) {
this.$nextTick(() => {
if (window.matchMedia("(min-width: 1024px)").matches) {
this.popper = new Popper(this.$refs.topbar, this.$refs.dropdown, {
placement: "bottom-start",
modifiers: {
preventOverflow: { boundariesElement: "scrollParent" },
},
});
}else {
this.popper = new Popper(this.$refs.topbar, this.$refs.dropdown, {
placement: 'bottom-end',
modifiers: {
preventOverflow: {
boundariesElement: 'scrollParent',
padding: 0,
},
offset: {
enabled: true,
offset: '0, 10'
}
},
});
}
});
} else if (this.popper) {
setTimeout(() => this.popper.destroy(), 100);
}
},
},
methods: {
...mapActions([
"toggleAudio",
"updateSeek",
"skipTrack",
"changeVolume",
"tabName",
"loadExsitPlaylist",
]),
openFull() {
this.open_drop = !this.open_drop;
},
updateVolume(volume) {
this.changeVolume(volume);
},
changeTab(name){
this.tabName(name);
},
},
};
</script>

View File

@@ -0,0 +1,62 @@
<template>
<modal-feed
@close-modal="closeModal"
@destroyFeed="destroyFeed"
:modalFeed='modalFeed' :open="show" />
<div v-for="feed in feedLists" :key="feed.id">
<feed-node @open-modal="openModal" :feed="feed" />
</div>
</template>
<script>
import FeedNode from "@/Shared/Feed/FeedNode";
import ModalFeed from "@/Shared/Overlay/ModalFeed";
import { filter } from "lodash";
export default {
components: {
FeedNode,
ModalFeed,
},
props: {
feeds: Array,
selfFeed: Boolean,
selfUser: {
type: Number,
default: 0,
},
},
data() {
return {
showLoadButton: true,
show: false,
entity: {},
feedLists: [],
complaints: [],
modalFeed: {},
};
},
mounted() {
this.feedLists = this.feeds;
},
methods: {
destroyFeed(){
const that = this;
this.feedLists = filter(this.feedLists, function (x) {
return x.id !== that.modalFeed.id;
});
},
openModal(feed) {
this.show = true;
this.modalFeed = feed;
},
closeModal() {
this.show = false;
}
},
};
</script>

View File

@@ -0,0 +1,67 @@
<template>
<component
@click.prevent="openModal(feed)"
@like-feed="likeFeed"
:is="currentTypeNode"
:feed_id="feed.id"
:user="feed.user"
:entity="feed.entity"
></component>
<p class="mt-2 text-gray-light text-sm" v-if="feed.entity.price">Цена: {{feed.entity.price}}</p>
<p class="mt-2 text-gray-light text-sm" v-if="feed.entity.purchase_date">Дата покупки: {{feed.entity.purchase_date}}</p>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import FeedImages from "@/Shared/Feed/Images";
import FeedVideos from "@/Shared/Feed/Videos";
import FeedMusics from "@/Shared/Feed/Musics";
import { usePage } from "@inertiajs/inertia-vue3";
export default {
components: {
FeedImages,
FeedVideos,
FeedMusics,
},
props: {
feed: Object,
},
emits: ["openModal"],
computed: {
authUser() {
return usePage().props.value.auth.user;
},
currentTypeNode() {
// if (this.feed.entity.is_paid && this.authUser.id !== this.feed.user.id) {
// return "feed-paids";
// }
return "feed-" + this.feed.type.toLowerCase();
},
},
methods: {
openModal(feed) {
this.$emit("openModal", feed);
},
likeFeed() {
Inertia.post(
route("feed.like", this.feed.id),
{},
{
preserveScroll: true,
preserveState: true,
}
);
if (this.feed.entity.liked) {
this.feed.entity.liked = false;
this.feed.entity.likes--;
} else {
this.feed.entity.liked = true;
this.feed.entity.likes++;
}
},
},
};
</script>

View File

@@ -0,0 +1,24 @@
<template>
<img :src="setImage()" alt="" />
</template>
<script>
export default {
components: { },
props: {
source: String,
type: String,
},
methods: {
setImage() {
if(this.source){
return this.source;
}
if(this.type == 'music'){
return '/image/modalimg1.jpg';
}
return '/image/card4.jpg';
},
},
};
</script>

View File

@@ -0,0 +1,63 @@
<template>
<div
class="
transition-opacity
ease-out
flex
items-center
justify-center
opacity-0
group-hover:opacity-100
bg-indigo-300 bg-opacity-75
z-10
absolute
inset-x-0
bottom-0
p-2
md:p-3
"
>
<div class="misc-info flex space-x-4">
<div :class="[is_like ? 'text-red' : 'text-gray-light', 'flex items-center']">
<button @click.stop="$emit('likeFeed')" class="default">
<svg class="w-5 h-5 flex-shrink-0">
<use xlink:href="#heart"></use>
</svg>
</button>
<span v-show="likes" class="ml-2 text-sm">{{ likes }}</span>
</div>
<div class="flex items-center text-gray-light">
<button class="default">
<svg class="w-5 h-5 flex-shrink-0">
<use xlink:href="#message-circle"></use>
</svg>
</button>
<span v-show="comments" class="ml-2 text-sm">{{
comments
}}</span>
</div>
</div>
<div class="hidden count-views">
<div class="flex items-center text-gray-light">
<span class="mr-2 text-sm">1000</span>
<svg class="w-5 h-5 flex-shrink-0">
<use xlink:href="#eye"></use>
</svg>
</div>
</div>
</div>
</template>
<script>
export default {
components: {},
emits: ["likeFeed"],
props: {
likes: Number,
comments: Number,
is_like: Boolean,
},
};
</script>

View File

@@ -0,0 +1,24 @@
<template>
<div class="absolute z-10 top-3 right-3">
<div class="flex items-center text-white">
<span v-if="count > 1" class="mr-1 text-sm">
{{ count }}
</span>
<svg class="drop-shadow-custom w-5 h-5">
<use v-if="type == 'images'" xlink:href="#imagefeed"></use>
<use v-if="type == 'videos'" xlink:href="#filmmark"></use>
<use v-if="type == 'musics'" xlink:href="#musicmark"></use>
</svg>
</div>
</div>
</template>
<script>
export default {
components: { },
props: {
count: Number,
type: String,
},
};
</script>

View File

@@ -0,0 +1,44 @@
<template>
<div
class="card-block contain group cursor-pointer relative overflow-hidden"
>
<feed-header-misc
:count="entity.collection_medias.length"
type="images"
/>
<feed-footer-misc
:is_like="entity.liked"
:likes="entity.likes"
:comments="entity.comments"
@like-feed="likeFeed"
/>
<div class="relative overflow-hidden">
<img
class="w-full h-36 md:h-72 object-cover"
:src="entity.preview"
alt=""
/>
</div>
</div>
</template>
<script>
import FeedFooterMisc from "@/Shared/Feed/FooterMisc";
import FeedHeaderMisc from "@/Shared/Feed/HeaderMisc";
export default {
components: { FeedFooterMisc, FeedHeaderMisc },
emits: ["likeFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,94 @@
<template>
<div
class="card-block contain group cursor-pointer relative overflow-hidden"
>
<feed-header-misc
:count="entity.collection_medias.length"
type="musics"
/>
<div :class="[playlist_id === feed_id ? '' : 'transition-opacity ease-out opacity-0 group-hover:opacity-100' , ' absolute inset-0 z-10 flex items-center justify-center']">
<div class="w-full grid grid-cols-7 items-center p-1 md:p-3 bg-indigo-300 bg-opacity-75">
<div @click.stop="" class="col-span-1 flex mr-3 text-white">
<div @click.prevent="startPlay(entity.collection_medias[0])" class="inline-block transition-colors hover:text-orange">
<button :class="[ currentSong?.id === entity.collection_medias[0].id ? '' : 'hidden', 'default' ]">
<svg :class="[ playing ? 'hidden' : 'block', 'w-4 h-4 md:w-6 md:h-6' ]">
<use xlink:href="#play"></use>
</svg>
<svg :class="[ playing ? 'block' : 'hidden', 'w-4 h-4 md:w-6 md:h-6' ]">
<use xlink:href="#pause"></use>
</svg>
</button>
<button :class="[ currentSong?.id !== entity.collection_medias[0].id ? '' : 'hidden', 'default' ]">
<svg class="w-4 h-4 md:w-6 md:h-6">
<use xlink:href="#play"></use>
</svg>
</button>
</div>
</div>
<div class="col-span-6 flex flex-col text-white" v-show="playlist_id === feed_id">
<span class="text-xs md:text-base text-gray font-semibold truncate">{{ currentSong.name }}</span>
<span class="text-xs md:text-sm text-gray-light truncate">{{ seek }}</span>
</div>
<div class="col-span-6 flex flex-col text-white" v-show="playlist_id !== feed_id">
<span class="text-xs md:text-base text-gray font-semibold truncate">{{entity.collection_medias[0].name}}</span>
<span class="text-xs md:text-sm text-gray-light truncate">{{entity.collection_medias[0].time}}</span>
</div>
</div>
</div>
<feed-footer-misc
:is_like="entity.liked"
:likes="entity.likes"
:comments="entity.comments"
@like-feed="likeFeed"
/>
<div class="relative overflow-hidden">
<feed-preview class="w-full h-36 md:h-72 object-cover" type="music" :source='entity.preview' />
</div>
</div>
</template>
<script>
import { mapActions, mapState, mapGetters } from "vuex";
import FeedFooterMisc from "@/Shared/Feed/FooterMisc";
import FeedHeaderMisc from "@/Shared/Feed/HeaderMisc";
import FeedPreview from "@/Shared/Feed/FeedPreview";
export default {
components: { FeedFooterMisc, FeedHeaderMisc, FeedPreview },
emits: ["likeFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
computed: {
...mapGetters(["playing"]),
...mapState({
seek: (state) => state.player.seek,
playlist_id: (state) => state.player.playlist_id,
currentSong: (state) => state.player.currentSong,
}),
},
methods: {
...mapActions(["toggleAudio", "newCurrentPlaylist"]),
startPlay(music) {
if (this.currentSong?.id === music.id) {
this.toggleAudio();
return;
}
this.newCurrentPlaylist([this.entity.collection_medias[0], this.entity.collection_medias, this.feed_id]);
},
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,41 @@
<template>
<div
class="card-block contain group cursor-pointer relative overflow-hidden"
>
<feed-header-misc
:count="entity.collection_medias.length"
type="videos"
/>
<feed-footer-misc
:is_like="entity.liked"
:likes="entity.likes"
:comments="entity.comments"
@like-feed="likeFeed"
/>
<div class="relative overflow-hidden">
<feed-preview class="w-full h-36 md:h-72 object-cover" :source='entity.preview' />
</div>
</div>
</template>
<script>
import FeedFooterMisc from "@/Shared/Feed/FooterMisc";
import FeedHeaderMisc from "@/Shared/Feed/HeaderMisc";
import FeedPreview from "@/Shared/Feed/FeedPreview";
export default {
components: { FeedFooterMisc, FeedHeaderMisc, FeedPreview },
emits: ["likeFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,41 @@
<template>
<div class="mt-3 md:mt-6 feed-footer">
<div class="flex justify-between">
<div class="misc-info flex space-x-4">
<like-count @likeFeed="likeFeed" :likes="likes" :liked="liked" />
<comment-count :comments="comments" />
<share-count />
</div>
<view-count />
</div>
</div>
</template>
<script>
import LikeCount from "@/Shared/Misc/LikeCount";
import ViewCount from "@/Shared/Misc/ViewCount";
import CommentCount from "@/Shared/Misc/CommentCount";
import ShareCount from "@/Shared/Misc/ShareCount";
export default {
components: {
LikeCount,
CommentCount,
ShareCount,
ViewCount,
},
emits:['likeFeed'],
props: {
comments: Number,
likes: Number,
liked: Boolean,
},
methods:{
likeFeed(){
this.$emit('likeFeed');
},
}
};
</script>

View File

@@ -0,0 +1,62 @@
<template>
<div @click.stop="" class="feed-header flex items-center justify-between">
<div class="flex items-center">
<inertia-link :href="route('profile.user', user.username)" class="flex-shrink-0 block mr-2 md:mr-4">
<user-avatar :user='user' size='small' class="w-10 h-10 md:w-14 md:h-14 text-lg" />
</inertia-link>
<inertia-link :href="route('profile.user', user.username)" class="flex flex-col">
<span class="hover:underline text-sm md:text-base block font-medium text-white">{{ user.name }}</span>
<span class="hover:underline text-xs text-gray-light">{{created_at}}</span>
</inertia-link>
</div>
<div class="flex-shrink-0 text-white">
<dropdown-menu-point>
<MenuItems class="origin-top-right absolute right-0 mt-2 w-64 bg-indigo-300 shadow-lg max-h-60 rounded-md text-base ring-1 ring-indigo-200 overflow-auto focus:outline-none">
<MenuItem v-if="user.id === $page.props.auth.user.id">
<button @click="onRemoveFeed()" class="w-full group flex items-center px-4 py-2 text-base hover:bg-indigo-100 text-gray-light">
<MinusCircleIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Удалить
</button>
</MenuItem>
<MenuItem v-if="user.id !== $page.props.auth.user.id">
<inertia-link :href="route('video.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-100 text-gray-light">
<ExclamationIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Пожаловаться
</inertia-link>
</MenuItem>
</MenuItems>
</dropdown-menu-point>
</div>
</div>
</template>
<script>
import UserAvatar from '@/Shared/Misc/UserAvatar'
import DropdownMenuPoint from '@/Shared/Form/DropdownMenuPoint'
import { MenuItem, MenuItems } from '@headlessui/vue'
import {
MinusCircleIcon,
ExclamationIcon,
} from '@heroicons/vue/solid'
export default {
components: {
UserAvatar,
DropdownMenuPoint,
MinusCircleIcon,
ExclamationIcon,
MenuItem,
MenuItems,
},
emits: ['onRemoveFeed'],
props: {
user: Object,
created_at: String,
},
methods:{
onRemoveFeed(){
this.$emit('onRemoveFeed');
},
}
};
</script>

View File

@@ -0,0 +1,72 @@
<template>
<modal-feed
@close-modal="closeModal"
:modalFeed='modalFeed'
:open="show"
@destroyFeed="destroyFeed"
/>
<div v-for="feed in feedLists" :key="feed.id">
<feed-list-node @onRemoveFeed="onRemoveFeed" @open-modal="openModal" :feed="feed" />
</div>
</template>
<script>
import FeedListNode from "@/Shared/FeedList/FeedListNode";
import ModalFeed from "@/Shared/Overlay/ModalFeed";
import { Inertia } from "@inertiajs/inertia";
import filter from 'lodash/filter';
export default {
components: {
FeedListNode,
ModalFeed,
},
props: {
feeds: Array,
selfFeed: Boolean,
selfUser: {
type: Number,
default: 0,
},
},
data() {
return {
showLoadButton: true,
show: false,
entity: {},
feedLists: [],
complaints: [],
modalFeed: {},
};
},
mounted() {
this.feedLists = this.feeds;
},
methods: {
onRemoveFeed(id){
Inertia.delete(route('feed.destroy', id), { preserveScroll: true, preserveState: true })
this.destroyFeed(id);
},
destroyFeed(id = null){
const that = this;
this.feedLists = filter(this.feedLists, function (x) {
if(id){
return x.id !== id;
}
return x.id !== that.modalFeed.id;
});
},
openModal(feed) {
this.show = true;
this.modalFeed = feed;
},
closeModal() {
this.show = false;
}
},
};
</script>

View File

@@ -0,0 +1,68 @@
<template>
<component
@click.prevent="openModal(feed)"
@onRemoveFeed='onRemoveFeed'
@like-feed="likeFeed"
:is="currentTypeNode"
:feed_id="feed.id"
:user="feed.user"
:entity="feed.entity"
></component>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import FeedImages from "@/Shared/FeedList/Images";
import FeedVideos from "@/Shared/FeedList/Videos";
import FeedMusics from "@/Shared/FeedList/Musics";
import { usePage } from "@inertiajs/inertia-vue3";
export default {
components: {
FeedImages,
FeedVideos,
FeedMusics,
},
props: {
feed: Object,
},
emits: ["openModal", "onRemoveFeed"],
computed: {
authUser() {
return usePage().props.value.auth.user;
},
currentTypeNode() {
if (this.feed.entity.is_paid && this.authUser.id !== this.feed.user.id) {
//return "feed-paid-" + this.feed.type.toLowerCase();
}
return "feed-" + this.feed.type.toLowerCase();
},
},
methods: {
onRemoveFeed(id) {
this.$emit("onRemoveFeed", id);
},
openModal(feed) {
this.$emit("openModal", feed);
},
likeFeed() {
Inertia.post(
route("feed.like", this.feed.id),
{},
{
preserveScroll: true,
preserveState: true,
}
);
if (this.feed.entity.liked) {
this.feed.entity.liked = false;
this.feed.entity.likes--;
} else {
this.feed.entity.liked = true;
this.feed.entity.likes++;
}
},
},
};
</script>

View File

@@ -0,0 +1,75 @@
<template>
<div class="">
<div class="flex items-center border-b border-indigo-100">
<div class="flex-shrink-0 mr-5 w-28 md:w-56">
<feed-preview class="h-28 w-28 md:w-56 md:h-56 object-cover" type="music" :source='preview' />
</div>
<div class="flex flex-col">
<span class="text-base md:text-xl font-semibold text-gray">{{title}}</span>
</div>
</div>
<div data-simplebar class="max-h-72 overflow-auto">
<div class="divide-y divide-indigo-100">
<div
@click.prevent="startPlay(media)"
v-for="media in medias" :key="media.id"
:class="[currentSong?.id === media.id ? 'bg-indigo-300 bg-opacity-25' : 'hover:bg-indigo-300 hover:bg-opacity-25', 'p-4 flex items-center space-x-4']">
<div class="flex">
<toggle-play-button :media_id="media.id" />
</div>
<div class="flex-1 text-sm text-gray-light">
{{media.name}}
</div>
<div class="text-sm text-gray-light">
<div v-if="currentSong?.id === media.id">{{seek}}</div>
<span v-else>{{media.time}}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState, mapGetters } from "vuex";
import FeedPreview from "@/Shared/Feed/FeedPreview";
import TogglePlayButton from "@/Shared/Misc/TogglePlayButton";
export default {
components: {
FeedPreview,
TogglePlayButton,
},
props: {
medias: Array,
feed_id: Number,
title: String,
preview: String,
},
methods: {
...mapActions(["toggleAudio", "newCurrentPlaylist", "skipToIndexByMusic"]),
startPlay(music) {
if (this.currentSong?.id === music.id) {
this.toggleAudio();
return;
}
// if (this.playlist_id === this.feed_id) {
// this.skipToIndexByMusic(music);
// return;
// }
this.newCurrentPlaylist([music, this.medias, this.feed_id]);
},
},
computed: {
...mapGetters(["playing"]),
...mapState({
playlist_id: (state) => state.player.playlist_id,
seek: (state) => state.player.seek,
currentSong: (state) => state.player.currentSong,
}),
},
};
</script>

View File

@@ -0,0 +1,95 @@
<template>
<div @click.stop="" class="mt-3 rounded-md bg-indigo-300 p-4"
v-if="disabled === 0 && is_paid && $page.props.auth.user.id !== user_id">
<div v-if="bought == 0" class="flex items-center justify-center">
<div class="mr-5 mb-2 md:mb-0 font-bold text-center md:text-left w-full md:w-auto">
Цена: {{price}}
</div>
<div>
<button @click="purchaseFeed" type="button" class="my-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-3 justify-center text-sm md:text-base rounded-md text-white bg-pink focus:outline-none">
Купить
</button>
</div>
</div>
<div v-else class="flex flex-wrap items-center justify-center">
<div class="mr-5 mb-2 md:mb-0 font-bold text-center md:text-left w-full md:w-auto">
Данный товар вами куплен
</div>
<button v-if="disable_btn == 0 && paid_open == 0" @click="replaceFeed" type="button" class="my-1 mx-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-3 justify-center text-sm md:text-base rounded-md text-white bg-orange focus:outline-none">
Показать
</button>
<inertia-link :href="route('setting.show.purchases', feed_id)" class="my-1 mx-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-3 justify-center text-sm md:text-base rounded-md text-white bg-pink focus:outline-none">
Скачать
</inertia-link>
</div>
</div>
<div @click.stop="" v-else-if="is_paid && $page.props.auth.user.id === user_id" class="p-4 text-center">
<button v-if="paid_open === 0" @click="replaceFeed" type="button" class="my-1 mx-1 transition shadow-none hover:shadow-classic2 inline-flex items-center px-8 py-1 md:py-2 justify-center text-sm rounded-md text-white bg-orange focus:outline-none">
Показать платный контент
</button>
</div>
</template>
<script>
import axios from "axios";
export default {
components: {},
emits: ["onReplaceFeed"],
props: {
user_id: Number,
is_paid: Boolean,
feed_id: Number,
price: String,
paid_open: {
type: Number,
default: 0,
},
},
data() {
return {
bought: 0,
disable_btn: 0,
disabled: 1,
};
},
mounted() {
if (this.is_paid) {
axios
.post(route("feeds.purchase_check", this.feed_id))
.then(({ data }) => {
if (data === 1) {
this.bought = 1;
}
this.disabled = 0;
});
}
},
methods: {
purchaseFeed() {
axios.post(route("feed.purchase", this.feed_id)).then(({ data }) => {
if (data.error == 1) {
alert(data.msg);
} else {
this.$emit("onReplaceFeed", data);
this.disable_btn = 1;
this.bought = 1;
}
});
},
replaceFeed() {
axios.post(route("feeds.replace", this.feed_id)).then(({ data }) => {
if (data.collection) {
this.$emit("onReplaceFeed", data);
this.disable_btn = 1;
}
});
},
},
};
</script>

View File

@@ -0,0 +1,68 @@
<template>
<div class="shadow-classic rounded-md bg-indigo-200 p-3 md:px-5 md:py-7">
<feed-header @onRemoveFeed='onRemoveFeed' :created_at='entity.created_at_humans' :user='user' />
<div class="mt-3 md:mt-6 feed-body">
<div class="mb-3 md:mb-6 text-gray text-sm md:text-base">
<div @click.stop="">
{{entity.body}}
</div>
<feed-paid-block
@onReplaceFeed='onReplaceFeed'
:is_paid='entity.is_paid'
:user_id='user.id'
:price='entity.price'
:feed_id='feed_id'
:paid_open='entity.paid_open'
/>
</div>
<div class="grid gap-1 md:gap-3 grid-cols-2 md:grid-cols-[repeat(auto-fit,minmax(280px,1fr))]">
<div v-for="media in entity.collection_medias" :key="media.id">
<img class="w-full h-full object-cover" :src="media.url" alt="">
</div>
</div>
</div>
<feed-footer
@likeFeed='likeFeed'
:likes='entity.likes'
:liked='entity.liked'
:comments='entity.comments'
/>
</div>
</template>
<script>
import FeedHeader from "@/Shared/FeedList/FeedHeader";
import FeedFooter from "@/Shared/FeedList/FeedFooter";
import FeedPaidBlock from "@/Shared/FeedList/FeedPaidBlock";
export default {
components: {
FeedHeader,
FeedFooter,
FeedPaidBlock,
},
emits: ["likeFeed", "onRemoveFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
onReplaceFeed(data) {
this.entity.collection_medias = data.collection;
this.entity.preview = data.preview;
this.entity.paid_open = 1;
},
onRemoveFeed() {
this.$emit("onRemoveFeed", this.feed_id);
},
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,66 @@
<template>
<div class="shadow-classic rounded-md bg-indigo-200 p-3 md:px-5 md:py-7">
<feed-header :created_at='entity.created_at_humans' :user='user' />
<div @click.stop="" class="mt-3 md:mt-6 feed-body">
<div class="mb-3 md:mb-6 text-gray text-sm md:text-base">
<div @click.stop="">
{{entity.body}}
</div>
<feed-paid-block
@onReplaceFeed='onReplaceFeed'
:is_paid='entity.is_paid'
:user_id='user.id'
:price='entity.price'
:feed_id='feed_id'
:paid_open='entity.paid_open'
/>
</div>
<feed-music-body
:feed_id='feed_id'
:title='entity.title'
:preview='entity.preview'
:medias='entity.collection_medias'
/>
</div>
<feed-footer
@likeFeed='likeFeed'
:likes='entity.likes'
:liked='entity.liked'
:comments='entity.comments'
/>
</div>
</template>
<script>
import FeedHeader from "@/Shared/FeedList/FeedHeader";
import FeedFooter from "@/Shared/FeedList/FeedFooter";
import FeedMusicBody from "@/Shared/FeedList/FeedMusicBody";
import FeedPaidBlock from "@/Shared/FeedList/FeedPaidBlock";
export default {
components: {
FeedHeader,
FeedFooter,
FeedMusicBody,
FeedPaidBlock,
},
emits: ["likeFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
onReplaceFeed(data) {
this.entity.collection_medias = data.collection;
this.entity.preview = data.preview;
this.entity.paid_open = 1;
},
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,48 @@
<template>
<div class="shadow-classic rounded-md bg-indigo-200 p-3 md:px-5 md:py-7">
<feed-header :created_at='entity.created_at_humans' :user='user' />
<div @click.stop="" class="mt-3 md:mt-6 feed-body">
<div class="mb-3 md:mb-6 text-gray text-sm md:text-base">
{{entity.body}}
</div>
<div class="grid gap-1 md:gap-3 grid-cols-2 md:grid-cols-[repeat(auto-fit,minmax(280px,1fr))]">
<div v-for="media in entity.collection_medias" :key="media.id">
<video :src="media.url" controls></video>
</div>
</div>
</div>
<feed-footer
@likeFeed='likeFeed'
:likes='entity.likes'
:liked='entity.liked'
:comments='entity.comments'
/>
</div>
</template>
<script>
import FeedHeader from '@/Shared/FeedList/FeedHeader'
import FeedFooter from '@/Shared/FeedList/FeedFooter'
export default {
components: {
FeedHeader,
FeedFooter,
},
emits: ["likeFeed"],
props: {
entity: Object,
user: Object,
feed_id: Number,
},
methods: {
likeFeed() {
this.$emit("likeFeed");
},
},
};
</script>

View File

@@ -0,0 +1,71 @@
<template>
<button type="button" @click="show = true">
<slot />
<teleport to="body">
<div v-if="show">
<div style="position: fixed; top: 0; right: 0; left: 0; bottom: 0; z-index: 99998;" @click="show = false" />
<div ref="dropdown" style="position: absolute; z-index: 99999;" @click.stop="show = autoClose ? false : true">
<slot name="dropdown" />
</div>
</div>
</teleport>
</button>
</template>
<script>
import Popper from 'popper.js'
export default {
props: {
placement: {
type: String,
default: 'bottom-end',
},
offset: {
type: String,
default: '0, 10',
},
boundary: {
type: String,
default: 'scrollParent',
},
autoClose: {
type: Boolean,
default: true,
},
},
data() {
return {
show: false,
}
},
watch: {
show(show) {
if (show) {
this.$nextTick(() => {
this.popper = new Popper(this.$el, this.$refs.dropdown, {
placement: this.placement,
modifiers: {
preventOverflow: { boundariesElement: this.boundary, padding: 0},
offset: {
enabled: true,
offset: this.offset
}
},
})
})
} else if (this.popper) {
setTimeout(() => this.popper.destroy(), 100)
}
},
},
mounted() {
document.addEventListener('keydown', (e) => {
if (e.keyCode === 27) {
this.show = false
}
})
},
}
</script>

View File

@@ -0,0 +1,27 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<template>
<Menu as="div" class="relative inline-block text-left z-50">
<div>
<MenuButton class="transition inline-flex items-center justify-center shadow-classic2 rounded-full bg-orange text-white focus:outline-none w-12 h-12">
<svg class="h-4 w-4 md:h-5 md:w-5 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
</MenuButton>
</div>
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
<slot />
</transition>
</Menu>
</template>
<script>
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
export default {
components: {
Menu,
MenuButton,
MenuItem,
MenuItems,
},
}
</script>

View File

@@ -0,0 +1,27 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<template>
<Menu as="div" v-slot="{ open }" class="relative inline-block text-left z-50">
<div>
<MenuButton class="transition inline-flex items-center justify-center focus:outline-none ">
<svg :class="[open ? 'rotate-90' : 'rotate-180' ,'transform-gpu transition-transform transform w-6 h-6']">
<use xlink:href="#more-vertical"></use>
</svg>
</MenuButton>
</div>
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
<slot />
</transition>
</Menu>
</template>
<script>
import { Menu, MenuButton } from '@headlessui/vue'
export default {
components: {
Menu,
MenuButton,
},
}
</script>

View File

@@ -0,0 +1,53 @@
<template>
<div>
<label v-if="label" class="text-gray-light text-lg mb-2">{{ label }}:</label>
<div :class="{ error: error }">
<input ref="file" type="file" :accept="accept" class="hidden" @change="change">
<div v-if="!modelValue" class="py-2">
<button type="button" class="px-6 py-2 bg-indigo-300 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:outline-none focus:border-transparent rounded-sm text-sm text-white" @click="browse">
Выбрать файл
</button>
</div>
<div v-else class="flex justify-center items-start max-w-lg mt-3 p-2 border rounded-md">
<div class="flex-1 pr-1 text-gray">{{ modelValue.name }} <span class="text-xs text-gray-light">({{ filesize(modelValue.size) }})</span></div>
<button type="button" class="px-4 py-1 bg-indigo-300 hover:bg-indigo-100 rounded-sm text-xs font-medium text-white" @click="remove">
Удалить
</button>
</div>
</div>
<div v-if="error" class="text-red text-sm">{{ error }}</div>
</div>
</template>
<script>
export default {
props: {
modelValue: File,
label: String,
accept: String,
error: String,
},
watch: {
modelValue(value) {
if (!value) {
this.$refs.file.value = ''
}
},
},
methods: {
filesize(size) {
var i = Math.floor(Math.log(size) / Math.log(1024))
return (size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]
},
browse() {
this.$refs.file.click()
},
change(e) {
this.$emit('update:modelValue', e.target.files[0])
},
remove() {
this.$emit('update:modelValue', null)
},
},
}
</script>

View File

@@ -0,0 +1,111 @@
<template>
<div>
<label v-if="label" class="text-gray-light text-lg mb-2">{{ label }}:</label>
<div :class="{ error: error }">
<input
ref="file"
type="file"
:accept="accept"
multiple
class="hidden"
@change="change"
/>
<div v-if="!modelValue" class="py-2">
<button
type="button"
class="px-6 py-2 bg-indigo-300 focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:outline-none focus:border-transparent rounded-sm text-sm text-white"
@click="browse"
>
Выбрать файлы
</button>
</div>
<div v-else class="flex flex-col justify-center max-w-lg mt-3 p-2 border rounded-md">
<div
v-for="(file, index) in modelValue"
:key="index"
class="flex items-center justify-between p-1"
>
<div class="flex-1 pr-1 text-gray">
{{ file.name }}
<span class="text-xs text-gray-light"
>({{ filesize(file.size) }})</span
>
</div>
<button
type="button"
class="px-4 py-1 bg-indigo-300 hover:bg-indigo-100 rounded-sm text-xs font-medium text-white"
@click="remove(index)"
>
Удалить
</button>
</div>
</div>
</div>
<div v-if="error" class="text-red text-sm">{{ error }}</div>
</div>
</template>
<script>
import helper from "@/includes/helper";
export default {
props: {
modelValue: FileList,
label: String,
accept: String,
error: String,
},
emits:['fileTime', 'update:modelValue'],
methods: {
filesize(size) {
var i = Math.floor(Math.log(size) / Math.log(1024));
return (
(size / Math.pow(1024, i)).toFixed(2) * 1 +
" " +
["B", "kB", "MB", "GB", "TB"][i]
);
},
browse() {
this.$refs.file.click();
},
change(e) {
const files = Array.from(e.target.files);
const that = this;
files.map(function (file) {
if(file.type === "audio/mpeg"){
var audioCtx = new (AudioContext || webkitAudioContext)();
var readerAudio = new FileReader();
readerAudio.readAsArrayBuffer(file);
readerAudio.onload = function(ev) {
audioCtx.decodeAudioData(ev.target.result).then(function(buffer) {
that.$emit("fileTime", file.name + ',' + that.formatTimeSong(buffer.duration));
});
};
}
});
this.$emit("update:modelValue", e.target.files);
},
formatTimeSong(value) {
return helper.formatTime(value);
},
remove(file_index) {
const dt = new DataTransfer();
let files = Array.from(this.$refs.file.files);
files.map(function (file, index) {
if (index !== file_index) {
dt.items.add(file);
}
});
if (dt.files.length) {
this.$refs.file.files = dt.files;
this.$emit("update:modelValue", dt.files);
} else {
this.$refs.file.files = null;
this.$emit("update:modelValue", null);
}
},
},
};
</script>

View File

@@ -0,0 +1,14 @@
<template>
<button :disabled="loading">
<div v-if="loading" class="btn-spinner mr-2" />
<slot />
</button>
</template>
<script>
export default {
props: {
loading: Boolean,
},
}
</script>

View File

@@ -0,0 +1,37 @@
<template>
<label class="text-gray-light text-lg mb-2" v-if="label" :for="id">{{ label }}:</label>
<input :id="id" ref="input" v-bind="$attrs" :class="{ error: error }" :type="type" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
<div v-if="error">{{ error }}</div>
</template>
<script>
export default {
props: {
id: {
type: String,
default() {
return `select-input-${Math.random() * 1000}`;
},
},
type: {
type: String,
default: 'text',
},
modelValue: String,
label: String,
error: String,
},
emits: ['update:modelValue'],
methods: {
focus() {
this.$refs.input.focus()
},
select() {
this.$refs.input.select()
},
setSelectionRange(start, end) {
this.$refs.input.setSelectionRange(start, end)
},
},
}
</script>

View File

@@ -0,0 +1,30 @@
<template>
<label class="text-gray-light text-lg mb-2" v-if="label" :for="id">{{ label }}:</label>
<textarea :id="id" ref="input" v-bind="$attrs" :class="{ error: error }" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
<div v-if="error" class="text-red text-sm">{{ error }}</div>
</template>
<script>
export default {
inheritAttrs: false,
props: {
id: {
type: String,
default() {
return `select-input-${Math.random() * 1000}`;
},
},
modelValue: String,
label: String,
error: String,
},
methods: {
focus() {
this.$refs.input.focus()
},
select() {
this.$refs.input.select()
},
},
}
</script>

View File

@@ -0,0 +1,40 @@
<template>
<SwitchGroup @click="clicked" as="div" class="flex items-center">
<Switch v-model="enabled" :class="[enabled ? 'bg-orange' : 'bg-indigo-200', 'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500']">
<!-- <span class="sr-only">Use setting</span> -->
<span aria-hidden="true" :class="[enabled ? 'translate-x-5' : 'translate-x-0', 'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200']" />
</Switch>
<SwitchLabel as="span" class="ml-3">
<span v-show="!enabled" class="text-sm text-white">{{textin}}</span>
<span v-show="enabled" class="text-sm text-white">{{textout}}</span>
</SwitchLabel>
</SwitchGroup>
</template>
<script>
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue'
export default {
components: {
Switch,
SwitchGroup,
SwitchLabel,
},
emits: ['clicked'],
props: {
textin: String,
textout: String,
user_id: Number,
enabled: {
type: Boolean,
default: false
},
},
methods: {
clicked(){
this.$emit('clicked', this.user_id);
}
}
}
</script>

View File

@@ -0,0 +1,35 @@
<template>
<header-bar />
<div class="min-h-screen flex overflow-hidden">
<sidebar />
<div class="flex-1 flex flex-col overflow-hidden">
<div class="bg-indigo-300 flex-1 flex items-stretch overflow-hidden">
<main class="flex-1 overflow-y-auto pb-10">
<section class="min-w-0 flex-1 h-full flex flex-col overflow-hidden lg:order-last">
<flash-messages />
<slot />
</section>
</main>
<sidebar-secondary v-if="$page.props.sidebar_layout" />
</div>
</div>
</div>
</template>
<script>
import FlashMessages from '@/Shared/Misc/FlashMessages'
import HeaderBar from '@/Shared/LayoutParts/HeaderBar'
import Sidebar from '@/Shared/LayoutParts/Sidebar'
import SidebarSecondary from '@/Shared/LayoutParts/SidebarSecondary'
export default {
components: {
FlashMessages,
HeaderBar,
Sidebar,
SidebarSecondary,
}
}
</script>

View File

@@ -0,0 +1,35 @@
<template>
<header-bar />
<div class="min-h-screen flex overflow-hidden">
<sidebar />
<div class="flex-1 flex flex-col overflow-hidden">
<div class="bg-indigo-300 flex-1 flex items-stretch overflow-hidden">
<main class="flex-1 overflow-y-auto pb-10">
<section class="min-w-0 flex-1 h-full flex flex-col overflow-hidden lg:order-last">
<flash-messages />
<slot />
</section>
</main>
<sidebar-secondary />
</div>
</div>
</div>
</template>
<script>
import FlashMessages from '@/Shared/Misc/FlashMessages'
import HeaderBar from '@/Shared/LayoutParts/HeaderBar'
import Sidebar from '@/Shared/LayoutParts/Sidebar'
import SidebarSecondary from '@/Shared/LayoutParts/SidebarSecondary'
export default {
components: {
FlashMessages,
HeaderBar,
Sidebar,
SidebarSecondary,
},
}
</script>

View File

@@ -0,0 +1,384 @@
<template>
<header class="w-full sticky top-0 z-[100]">
<div class="relative z-10 bg-orange shadow-xl">
<div
class="
grid grid-cols-12
items-center
pt-2.5
pb-2.5
px-4
sm:px-6
md:space-x-5
lg:space-x-10
"
>
<inertia-link :href="route('dashboard')" class="col-span-1 block flex-shrink-0">
<div class="block md:hidden font-bold text-indigo-300 text-2xl">
T
</div>
<img class="hidden md:block" src="/image/logotype.svg" alt="" />
</inertia-link >
<audio-player />
<div class="col-span-4 h-12 hidden md:flex">
<form class="main-search w-full flex md:ml-0" action="#" method="GET">
<label for="search_field" class="sr-only">Поиск контента</label>
<div
class="relative w-full text-gray-400 focus-within:text-gray-600"
>
<input
name="search_field"
id="search_field"
class="
h-full
w-full
rounded-md
border-transparent
py-2
pr-11
pl-4
text-base
bg-orange-dark
text-white
placeholder-gray
focus:border-transparent
focus:outline-none
focus:ring-2 focus:ring-orange-dark
"
placeholder="Глобальный поиск..."
type="search"
/>
<div
class="
pointer-events-none
absolute
inset-y-0
right-4
flex
items-center
text-gray
"
>
<svg
class="flex-shrink-0 h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z"
/>
</svg>
</div>
</div>
</form>
</div>
<div
class="
col-span-4
md:col-span-2
lg:col-span-4
flex
items-center
justify-end
space-x-2
sm:ml-6
sm:space-x-6
"
>
<inertia-link :href="route('setting.money')" class="hidden lg:block default text-sm text-white">
Баланс: {{$page.props.balance}}
</inertia-link>
<button
type="button"
class="
flex
md:hidden
p-1
rounded-full
items-center
justify-center
text-white
focus:outline-none
"
>
<svg
class="w-5 h-5 md:h-6 md:w-6"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</button>
<div class="relative">
<div
class="
absolute
top-0
right-1
w-2
h-2
md:w-3
md:h-3
bg-pink
rounded-full
"
></div>
<inertia-link
:href="route('setting.notify')"
class="
flex
p-1
rounded-full
items-center
justify-center
text-white
focus:outline-none
"
>
<svg
class="w-5 h-5 md:h-6 md:w-6"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
</svg>
</inertia-link>
</div>
<dropdown class="flex md:hidden user-menu h-12 w-12 rounded-full items-center justify-center focus:outline-none" placement="bottom-start">
<svg class="h-6 w-6 text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" > <line x1="3" y1="12" x2="21" y2="12"></line> <line x1="3" y1="6" x2="21" y2="6"></line> <line x1="3" y1="18" x2="21" y2="18"></line> </svg>
<template v-slot:dropdown>
<div class="mobile-user-menu z-50 bg-orange-dark rounded-b-lg">
<div
class="absolute z-50 right-0 top-[-16px] mr-[20px] sm:mr-[20px]"
>
</div>
<ul class="p-6 text-white space-y-6">
<li>
<inertia-link :href="route('setting.money')">Баланс: {{$page.props.balance}}</inertia-link>
</li>
<li>
<inertia-link :href="route('profile.user', $page.props.auth.user.username)">Профиль</inertia-link>
</li>
<li>
<inertia-link :href="route('feeds.layoutsidebar')">Новости</inertia-link>
</li>
<li>
<a href="#"><span class="text-xs rounded-full mr-1">(5)</span> Сообщения</a>
</li>
<li>
<inertia-link :href="route('list.images')">Изображения</inertia-link>
</li>
<li>
<inertia-link :href="route('list.videos')">Видео</inertia-link>
</li>
<li>
<inertia-link :href="route('list.musics')">Музыка</inertia-link>
</li>
<li>
<inertia-link :href="route('users.index')">Пользователи</inertia-link>
</li>
<li>
<inertia-link :href="route('setting.index')">Настройки</inertia-link>
</li>
<li>
<inertia-link as="button" :href="route('logout')" method="delete">Выйти</inertia-link>
</li>
</ul>
</div>
</template>
</dropdown>
<div class="hidden md:block relative flex-shrink-0">
<inertia-link
:href="route('profile.user', $page.props.auth.user.username)"
class="
bg-white
rounded-full
flex
text-sm
focus:outline-none
focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500
"
>
<user-avatar :user='$page.props.auth.user' size='small' class="w-9 h-9 md:h-12 md:w-12 text-lg" />
</inertia-link>
</div>
</div>
</div>
</div>
</header>
<div class=" hidden w-[48rem] z-50 main-search-list shadow-classic rounded-md bg-indigo-200 overflow-hidden " >
<div class="">
<div data-simplebar class="overflow-auto max-h-72">
<div class="text-gray-light divide-y divide-indigo-300">
<!-- s -->
<div class="flex cursor-pointer items-center p-3 hover:bg-indigo-300">
<div class="flex-shrink-0 mr-5">
<img
class="object-cover w-10 h-10"
src="/image/user_card2.png"
alt=""
/>
</div>
<div class="flex-1">
Lorem, ipsum dolor sit amet consectetur
<mark class="text-orange bg-transparent">consectetur</mark> asdasd
....
</div>
<div class="ml-5 flex-shrink-0">
<svg class="drop-shadow-custom w-5 h-5">
<use xlink:href="#musicmark"></use>
</svg>
</div>
</div>
<!-- e -->
<!-- s -->
<div class="flex cursor-pointer items-center p-3 hover:bg-indigo-300">
<div class="flex-shrink-0 mr-5">
<img
class="object-cover w-10 h-10"
src="/image/user_card2.png"
alt=""
/>
</div>
<div class="flex-1">
<mark class="text-orange bg-transparent">consectetur</mark> Lorem,
ipsum dolor sit amet consectetur asdasd ....
</div>
<div class="ml-5 flex-shrink-0">
<svg class="drop-shadow-custom w-5 h-5">
<use xlink:href="#filmmark"></use>
</svg>
</div>
</div>
<!-- e -->
<!-- s -->
<div class="flex cursor-pointer items-center p-3 hover:bg-indigo-300">
<div class="flex-shrink-0 mr-5">
<img
class="object-cover w-10 h-10"
src="/image/user_card2.png"
alt=""
/>
</div>
<div class="flex-1">
<mark class="text-orange bg-transparent">consectetur</mark> Lorem,
ipsum dolor sit amet consectetur asdasd ....
</div>
<div class="ml-5 flex-shrink-0">
<svg class="drop-shadow-custom w-5 h-5">
<use xlink:href="#filmmark"></use>
</svg>
</div>
</div>
<!-- e -->
<!-- s -->
<div class="flex cursor-pointer items-center p-3 hover:bg-indigo-300">
<div class="flex-shrink-0 mr-5">
<img
class="object-cover w-10 h-10"
src="/image/user_card2.png"
alt=""
/>
</div>
<div class="flex-1">
<mark class="text-orange bg-transparent">consectetur</mark> Lorem,
ipsum dolor sit amet consectetur asdasd ....
</div>
<div class="ml-5 flex-shrink-0">
<svg class="drop-shadow-custom w-5 h-5">
<use xlink:href="#filmmark"></use>
</svg>
</div>
</div>
<!-- e -->
<!-- s -->
<div class="flex cursor-pointer items-center p-3 hover:bg-indigo-300">
<div class="flex-shrink-0 mr-5">
<img
class="object-cover w-10 h-10"
src="/image/user_card2.png"
alt=""
/>
</div>
<div class="flex-1">
<mark class="text-orange bg-transparent">consectetur</mark> Lorem,
ipsum dolor sit amet consectetur asdasd ....
</div>
<div class="ml-5 flex-shrink-0">
<svg class="drop-shadow-custom w-5 h-5">
<use xlink:href="#filmmark"></use>
</svg>
</div>
</div>
<!-- e -->
<!-- s -->
<div class="flex cursor-pointer items-center p-3 hover:bg-indigo-300">
<div class="flex-shrink-0 mr-5">
<img
class="object-cover w-10 h-10"
src="/image/user_card2.png"
alt=""
/>
</div>
<div class="flex-1">
<mark class="text-orange bg-transparent">consectetur</mark> Lorem,
ipsum dolor sit amet consectetur asdasd ....
</div>
<div class="ml-5 flex-shrink-0">
<svg class="drop-shadow-custom w-5 h-5">
<use xlink:href="#filmmark"></use>
</svg>
</div>
</div>
<!-- e -->
</div>
</div>
</div>
</div>
</template>
<script>
import Dropdown from '@/Shared/Form/Dropdown'
import UserAvatar from '@/Shared/Misc/UserAvatar'
import AudioPlayer from '@/Shared/AudioPlayer'
export default {
components: {
AudioPlayer,
UserAvatar,
Dropdown,
}
}
</script>

View File

@@ -0,0 +1,42 @@
<template>
<div class="md:py-7 col-span-2 lg:col-span-1 border-r border-indigo-300">
<ul class="flex md:block text-base lg:text-xl xl:text-2xl text-gray-light overflow-x-auto">
<li
:class="[$page.component === 'Settings/SettingsProfile' ?
'md:border-l-4 md:border-b-0 border-b-2 border-pink text-white' :
'hover:text-white' ,'px-6 py-4']">
<inertia-link :href="route('setting.index')">Профиль</inertia-link>
</li>
<li
:class="[$page.url.startsWith('/settings/purchases') ?
'md:border-l-4 md:border-b-0 border-b-2 border-pink text-white' :
'hover:text-white' ,'px-6 py-4']">
<inertia-link :href="route('setting.purchases')">Покупки</inertia-link>
</li>
<li class="px-6 py-4 hover:text-white"><a href="#">Избранное</a></li>
<li
:class="[$page.component === 'Settings/SettingsMoney' ?
'md:border-l-4 md:border-b-0 border-b-2 border-pink text-white' :
'hover:text-white' ,'px-6 py-4']">
<inertia-link :href="route('setting.money')">Доход</inertia-link>
</li>
<li
:class="[$page.component === 'Settings/SettingsTarif' ?
'md:border-l-4 md:border-b-0 border-b-2 border-pink text-white' :
'hover:text-white' ,'px-6 py-4']">
<inertia-link :href="route('setting.tarif')">Тарифы</inertia-link>
</li>
<li
:class="[$page.component === 'Settings/SettingsNotify' ?
'md:border-l-4 md:border-b-0 border-b-2 border-pink text-white' :
'hover:text-white' ,'px-6 py-4']">
<inertia-link :href="route('setting.notify')">Оповещения</inertia-link>
</li>
<li class="px-6 py-4 hover:text-white"><a href="#">Сообщения</a></li>
</ul>
</div>
</template>

View File

@@ -0,0 +1,98 @@
<template>
<div class="hidden w-28 bg-indigo-200 overflow-y-auto md:block">
<div class="w-full py-6 flex flex-col items-center">
<div class="flex-1 w-full px-2 space-y-1">
<inertia-link :class="$page.url.startsWith('/profile') ? 'text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium' : 'text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs' " :href="route('profile.user', $page.props.auth.user.username)">
<svg :class="$page.url.startsWith('/profile') ? 'text-white h-6 w-6' : 'text-indigo-300 group-hover:text-white h-6 w-6' " xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
<span class="mt-2">Профиль</span>
</inertia-link>
<inertia-link :href="route('setting.money')"
class="lg:hidden text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs">
<svg class="text-green group-hover:text-white h-6 w-6" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><line x1="12" y1="1" x2="12" y2="23"></line><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path></svg>
<span class="mt-2">{{$page.props.balance}}</span>
</inertia-link>
<a href="#"
class="relative text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs">
<div class="absolute top-1 right-1 w-2 h-2 md:w-5 md:h-5 bg-pink rounded-full text-xs flex justify-center items-center text-white">5</div>
<svg class="text-indigo-300 group-hover:text-white h-6 w-6" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
<span class="mt-2">Сообщения</span>
</a>
<inertia-link :class="$page.component === 'Feed/Index' ? 'text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium' : 'text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs' " :href="route('feeds.layoutsidebar')">
<svg :class="$page.component === 'Feed/Index' ? 'text-white h-6 w-6' : 'text-indigo-300 group-hover:text-white h-6 w-6' " xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
</svg>
<span class="mt-2">Новости</span>
</inertia-link>
<inertia-link :class="$page.component === 'Image/Feed' ? 'text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium' : 'text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs' " :href="route('list.images')">
<svg :class="$page.component === 'Image/Feed' ? 'text-white h-6 w-6' : 'text-indigo-300 group-hover:text-white h-6 w-6' " xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span class="mt-2">Изображения</span>
</inertia-link>
<inertia-link :class="$page.component === 'Video/Feed' ? 'text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium' : 'text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs' " :href="route('list.videos')">
<svg :class="$page.component === 'Video/Feed' ? 'text-white h-6 w-6' : 'text-indigo-300 group-hover:text-white h-6 w-6' " xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
<span class="mt-2">Видео</span>
</inertia-link>
<inertia-link :class="$page.component === 'Music/Feed' ? 'text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium' : 'text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs' " :href="route('list.musics')">
<svg :class="$page.component === 'Music/Feed' ? 'text-white h-6 w-6' : 'text-indigo-300 group-hover:text-white h-6 w-6' " xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3" />
</svg>
<span class="mt-2">Музыка</span>
</inertia-link>
<inertia-link :class="$page.component === 'User/Index' ? 'text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium' : 'text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs' " :href="route('users.index')">
<svg :class="$page.component === 'User/Index' ? 'text-white h-6 w-6' : 'text-indigo-300 group-hover:text-white h-6 w-6' " xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
<span class="mt-2">Пользователи</span>
</inertia-link>
<inertia-link :class="$page.component.startsWith('Settings') ? 'text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium' : 'text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs' " :href="route('setting.index')">
<svg :class="$page.component.startsWith('Settings') ? 'text-white h-6 w-6' : 'text-indigo-300 group-hover:text-white h-6 w-6' " xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span class="mt-2">Настройки</span>
</inertia-link>
<inertia-link
as="button"
:href="route('logout')" method="delete"
class="relative text-gray-light hover:bg-orange hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs">
<svg class="text-indigo-300 group-hover:text-white h-6 w-6" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" /></svg>
<span class="mt-2">Выйти</span>
</inertia-link>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,27 @@
<template>
<section class="mt-16 hidden lg:w-[19rem] xl:w-[26rem] 2xl:w-[32rem] overflow-y-auto lg:block pr-5 2xl:pr-28">
<div class=" bg-indigo-200 shadow-classic rounded-md p-5">
<span class="block text-white font-medium">Лидеры</span>
<div class="mt-5 space-y-5">
<div class="flex items-center">
<div class="flex-shrink-0 mr-2 md:mr-4">
<div class="w-10 h-10 md:w-14 md:h-14 rounded-full bg-cover bg-center" style="background-image: url('/image/card1.jpg');"></div>
</div>
<div class="flex flex-col">
<a href="#" class="hover:underline text-sm md:text-base block text-white">Андрей Гаврилов</a>
<span class="text-xs text-gray-light">Фотограф, музыкант</span>
</div>
</div>
<div class="flex items-center">
<div class="flex-shrink-0 mr-2 md:mr-4">
<div class="w-10 h-10 md:w-14 md:h-14 rounded-full bg-cover bg-center" style="background-image: url('/image/card3.jpg');"></div>
</div>
<div class="flex flex-col">
<a href="#" class="hover:underline text-sm md:text-base block text-white">Владислав Сергеев</a>
<span class="text-xs text-gray-light">Дизайнер</span>
</div>
</div>
</div>
</div>
</section>
</template>

View File

@@ -0,0 +1,17 @@
<template>
<Head :title="title ? `${title} - Тизер` : 'Тизер'">
<slot />
</Head>
</template>
<script>
import { Head } from "@inertiajs/inertia-vue3";
export default {
components: {
Head,
},
props: {
title: String,
},
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<div class="flex items-center text-gray-light">
<svg class="w-5 h-5 flex-shrink-0">
<use xlink:href="#message-circle"></use>
</svg>
<span v-show="comments" class="ml-2 text-sm">{{
comments
}}</span>
</div>
</template>
<script>
export default {
components: {
},
props: {
comments: Number,
},
};
</script>

View File

@@ -0,0 +1,58 @@
<template>
<div>
<div v-if="$page.props.flash.success && show" class="mx-auto mt-4 mb-4 flex items-center justify-between bg-green rounded max-w-3xl">
<div class="flex items-center">
<svg class="ml-4 mr-2 flex-shrink-0 w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><polygon points="0 11 2 9 7 14 18 3 20 5 7 18" /></svg>
<div class="py-4 text-white text-sm font-medium">{{ $page.props.flash.success }}</div>
</div>
<button type="button" class="group mr-2 p-2" @click="show = false">
<svg class="block w-2 h-2 fill-green-800 group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" width="235.908" height="235.908" viewBox="278.046 126.846 235.908 235.908"><path d="M506.784 134.017c-9.56-9.56-25.06-9.56-34.62 0L396 210.18l-76.164-76.164c-9.56-9.56-25.06-9.56-34.62 0-9.56 9.56-9.56 25.06 0 34.62L361.38 244.8l-76.164 76.165c-9.56 9.56-9.56 25.06 0 34.62 9.56 9.56 25.06 9.56 34.62 0L396 279.42l76.164 76.165c9.56 9.56 25.06 9.56 34.62 0 9.56-9.56 9.56-25.06 0-34.62L430.62 244.8l76.164-76.163c9.56-9.56 9.56-25.06 0-34.62z" /></svg>
</button>
</div>
<div v-if="($page.props.flash.error || Object.keys($page.props.errors).length > 0) && show" class="mx-auto mt-4 mb-4 flex items-center justify-between bg-red rounded max-w-3xl">
<div class="flex items-center">
<svg class="ml-4 mr-2 flex-shrink-0 w-4 h-4 fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm1.41-1.41A8 8 0 1 0 15.66 4.34 8 8 0 0 0 4.34 15.66zm9.9-8.49L11.41 10l2.83 2.83-1.41 1.41L10 11.41l-2.83 2.83-1.41-1.41L8.59 10 5.76 7.17l1.41-1.41L10 8.59l2.83-2.83 1.41 1.41z" /></svg>
<div v-if="$page.props.flash.error" class="py-4 text-white text-sm font-medium">{{ $page.props.flash.error }}</div>
<div v-else class="py-4 text-white text-sm font-medium">
<span v-if="Object.keys($page.props.errors).length === 1">There is one form error.</span>
<span v-else>There are {{ Object.keys($page.props.errors).length }} form errors.</span>
</div>
</div>
<button type="button" class="group mr-2 p-2" @click="show = false">
<svg class="block w-2 h-2 fill-red-800 group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" width="235.908" height="235.908" viewBox="278.046 126.846 235.908 235.908"><path d="M506.784 134.017c-9.56-9.56-25.06-9.56-34.62 0L396 210.18l-76.164-76.164c-9.56-9.56-25.06-9.56-34.62 0-9.56 9.56-9.56 25.06 0 34.62L361.38 244.8l-76.164 76.165c-9.56 9.56-9.56 25.06 0 34.62 9.56 9.56 25.06 9.56 34.62 0L396 279.42l76.164 76.165c9.56 9.56 25.06 9.56 34.62 0 9.56-9.56 9.56-25.06 0-34.62L430.62 244.8l76.164-76.163c9.56-9.56 9.56-25.06 0-34.62z" /></svg>
</button>
</div>
</div>
</template>
<script>
//import { ref, watch } from 'vue'
export default {
// setup() {
// const show = ref(true)
// watch('$page.props.flash', function(){
// this.show = true
// });
// return {
// show,
// };
// },
data() {
return {
show: true,
}
},
watch: {
'$page.props.flash': {
handler() {
this.show = true
},
deep: true,
},
},
}
</script>

View File

@@ -0,0 +1,35 @@
<template>
<div
:class="[
liked ? 'text-red' : 'text-gray-light',
'flex items-center',
]"
>
<button @click.stop="likeFeed" class="default">
<svg class="w-5 h-5 flex-shrink-0">
<use xlink:href="#heart"></use>
</svg>
</button>
<span v-show="likes" class="ml-2 text-sm">{{
likes
}}</span>
</div>
</template>
<script>
export default {
components: {
},
emits:['likeFeed'],
props: {
likes: Number,
liked: Boolean,
},
methods:{
likeFeed(){
this.$emit('likeFeed');
}
}
};
</script>

View File

@@ -0,0 +1,20 @@
<template>
<div class="flex items-center text-gray-light">
<svg class="w-5 h-5 flex-shrink-0">
<use xlink:href="#share"></use>
</svg>
<span v-show="shares" class="ml-2 text-sm">{{
shares
}}</span>
</div>
</template>
<script>
export default {
components: {
},
props: {
shares: Number,
},
};
</script>

View File

@@ -0,0 +1,32 @@
<template>
<button :class="[ currentSong?.id === media_id ? '' : 'hidden', 'default' ]">
<svg :class="[ playing ? 'hidden' : 'block', 'w-6 h-6' ]">
<use xlink:href="#play"></use>
</svg>
<svg :class="[ playing ? 'block' : 'hidden', 'w-6 h-6' ]">
<use xlink:href="#pause"></use>
</svg>
</button>
<button :class="[ currentSong?.id !== media_id ? '' : 'hidden', 'default' ]">
<svg class="w-6 h-6">
<use xlink:href="#play"></use>
</svg>
</button>
</template>
<script>
import { mapState, mapGetters } from "vuex";
export default {
components: {
},
props: {
media_id: Number,
},
computed: {
...mapGetters(["playing"]),
...mapState({
currentSong: (state) => state.player.currentSong,
}),
},
};
</script>

View File

@@ -0,0 +1,31 @@
<template>
<div
v-if="user.photo_path"
class="rounded-full bg-cover bg-center"
:style="setBackground()"
></div>
<div
v-else
:style="`background-color:${user.color};`"
class="rounded-full font-bold flex items-center justify-center text-white"
>
{{ user.user_char }}
</div>
</template>
<script>
export default {
props: {
user: Object,
size: {
type: String,
default: 'small',
},
},
methods: {
setBackground() {
return `background-image: url(/img/${this.user.photo_path}?p=${this.size});`;
},
},
};
</script>

View File

@@ -0,0 +1,28 @@
<template>
<div
v-if="user.banner_path"
class="bg-cover bg-center"
:style="setBackground()"
></div>
<div
v-else
class="bg-cover bg-center"
></div>
</template>
<script>
export default {
props: {
user: Object,
size: {
type: String,
default: 'small',
},
},
methods: {
setBackground() {
return `background-image: url(/img/${this.user.banner_path}?p=${this.size});`;
},
},
};
</script>

View File

@@ -0,0 +1,10 @@
<template>
<div class="hidden">
<div class="flex items-center text-gray-light">
<span class="mr-2 text-sm">1030</span>
<svg class="w-5 h-5 flex-shrink-0">
<use xlink:href="#eye"></use>
</svg>
</div>
</div>
</template>

View File

@@ -0,0 +1,112 @@
<template>
<TransitionRoot as="template" :show="open">
<Dialog as="div" static class="fixed z-[1000] inset-0 overflow-y-auto" @close="staticCloseModal" :open="open">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
<DialogOverlay class="fixed inset-0 bg-indigo-200 bg-opacity-75 transition-opacity" />
</TransitionChild>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100" leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<div class="inline-block align-bottom bg-indigo-300 md:rounded-md text-left overflow-hidden shadow-xl transform transition-all md:my-8 md:align-middle md:max-w-5xl w-full">
<div class="md:grid grid-cols-12">
<button @click="staticCloseModal" class="flex md:hidden w-full items-center justify-center p-3 bg-indigo-300 text-gray-light text-sm border-b border-indigo-100">Закрыть</button>
<modal-feed-media
:type='feed.type'
:feed_id='feed.id'
:title='feed.entity.title'
:preview='feed.entity.preview'
:medias='feed.entity.collection_medias'
/>
<modal-feed-body
@onRemoveFeed='onRemoveFeed'
@disableModal='checkCloseModal'
:user='feed.user'
:feed_id='feed.id'
:entity='feed.entity'
/>
</div>
</div>
</TransitionChild>
</div>
<modal-warning
@closeWarningModal="closeWarningModal"
@closeModal="staticCloseModal"
:feed_id='modalFeedId'
:open="warningShow"
/>
</Dialog>
</TransitionRoot>
</template>
<script>
import ModalWarning from "@/Shared/Overlay/ModalWarning";
import { Dialog, DialogOverlay, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue'
import ModalFeedMedia from '@/Shared/Overlay/ModalFeedMedia'
import ModalFeedBody from '@/Shared/Overlay/ModalFeedBody'
export default {
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
ModalFeedMedia,
ModalFeedBody,
ModalWarning,
},
emits: ['onRemoveFeed', 'closeModal', 'destroyFeed'],
props: {
modalFeed: Object,
open: {
type: Boolean,
default: false,
},
},
data() {
return {
disabled: 0,
modalFeedId: 0,
warningShow: false,
feed: {}
}
},
watch: {
open(open){
if (open) {
this.feed = this.modalFeed;
}else{
}
}
},
methods: {
closeWarningModal()
{
this.warningShow = false;
this.$emit('destroyFeed');
},
onRemoveFeed(feed_id){
this.modalFeedId = feed_id;
this.warningShow = true;
},
checkCloseModal(value){
this.disabled = value;
},
staticCloseModal(){
if(!this.disabled){
this.$emit('closeModal', false);
}
},
}
}
</script>

View File

@@ -0,0 +1,224 @@
<template>
<div class="col-span-5 modal-body flex flex-col">
<div class="modal-head mb-3 px-2 py-4 md:py-4 md:px-6 flex justify-between items-center border-b border-indigo-100">
<div class="flex items-center space-x-4">
<inertia-link :href="route('profile.user', user.username)" class="flex-shrink-0 block">
<user-avatar :user='user' size='small' class="w-12 h-12 md:w-16 md:h-16 border-2 border-orange text-lg" />
</inertia-link>
<inertia-link :href="route('profile.user', user.username)" class="flex flex-col">
<p class="text-base md:text-xl font-semibold text-gray">{{user.name}}</p>
<p class="min-h-[24px]">
<span v-show="user.count_posts" class="md:mt-1 text-sm text-gray-light">{{user.count_posts}} {{countPosts}}</span>
</p>
</inertia-link>
</div>
<div class="text-white">
<dropdown-menu-point>
<MenuItems class="origin-top-right absolute right-0 mt-2 w-64 bg-indigo-200 shadow-lg max-h-60 rounded-md text-base ring-1 ring-indigo-100 overflow-auto focus:outline-none">
<MenuItem v-if="user.id === $page.props.auth.user.id">
<button @click="onRemoveFeed()" class="w-full group flex items-center px-4 py-2 text-base hover:bg-indigo-300 text-gray-light">
<MinusCircleIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Удалить
</button>
</MenuItem>
<MenuItem v-if="user.id !== $page.props.auth.user.id">
<inertia-link :href="route('video.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-300 text-gray-light">
<ExclamationIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Пожаловаться
</inertia-link>
</MenuItem>
</MenuItems>
</dropdown-menu-point>
</div>
</div>
<div data-simplebar class="modal-feed max-h-[29rem] overflow-auto">
<div class="p-2 md:py-4 md:px-6 space-y-3 md:space-y-6">
<div v-if="entity.body" class="comment-line comment-line--head flex flex-col text-gray text-sm">
<div class="flex group">
<inertia-link :href="route('profile.user', user.username)" class="flex-shrink-0 block mr-3">
<user-avatar :user='user' size='small' class="w-10 h-10 border border-orange text-xs" />
</inertia-link>
<div>
<inertia-link :href="route('profile.user', user.username)" class="font-semibold underline inline-block mr-2">
{{user.username}}
</inertia-link>
{{entity.body}}
<div class="transition-opacity opacity-0 group-hover:opacity-100 flex space-x-4">
<span class="text-xs text-gray-light">{{entity.created_at_humans}}</span>
</div>
</div>
</div>
</div>
<div v-for="comment in comments" :key='comment.id' class="comment-line flex flex-col text-gray text-sm">
<user-comment :creator_id='user.id' :comment='comment' />
</div>
</div>
</div>
<div class="modal-footer mt-auto p-2 md:py-4 md:px-6 border-t border-indigo-100">
<feed-paid-block
@onReplaceFeed='onReplaceFeed'
:is_paid='entity.is_paid'
:user_id='user.id'
:price='entity.price'
:feed_id='feed_id'
:paid_open='entity.paid_open'
class="text-white"
/>
<div class="misc-info mt-2 md:mt-0 mb-2 flex flex-row-reverse">
<div class="flex space-x-4">
<like-count @likeFeed='likeFeed' :likes='entity.likes' :liked='entity.liked' />
<comment-count :comments='entity.comments' />
<share-count />
</div>
<div class="mr-auto flex text-gray-light">
<button class="default">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5 flex-shrink-0"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path></svg>
</button>
</div>
</div>
<div class="modal-send flex">
<div class="flex-1">
<textarea required v-model="new_comment" class="pl-0 pr-2 resize-none bg-indigo-300 w-full outline-none focus:ring-transparent focus:border-transparent focus:ring-offset-0 text-base text-gray border-transparent" placeholder="Написать комментарий..."></textarea>
</div>
<div class="mt-1 flex-shrink-0 text-pink">
<button @click="addComment" class="default">
<svg class="w-8 h-8 flex-shrink-0">
<use xlink:href="#arrow-circle"></use>
</svg>
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { Inertia } from "@inertiajs/inertia";
import axios from "axios";
import helper from "@/includes/helper";
import DropdownMenuPoint from "@/Shared/Form/DropdownMenuPoint";
import { MenuItem, MenuItems } from "@headlessui/vue";
import { MinusCircleIcon, ExclamationIcon } from "@heroicons/vue/solid";
import FeedPaidBlock from "@/Shared/FeedList/FeedPaidBlock";
import UserAvatar from "@/Shared/Misc/UserAvatar";
import LikeCount from "@/Shared/Misc/LikeCount";
import CommentCount from "@/Shared/Misc/CommentCount";
import ShareCount from "@/Shared/Misc/ShareCount";
import UserComment from "@/Shared/Partials/UserComment";
export default {
components: {
DropdownMenuPoint,
MenuItem,
MenuItems,
MinusCircleIcon,
ExclamationIcon,
UserAvatar,
LikeCount,
ShareCount,
CommentCount,
UserComment,
FeedPaidBlock,
},
props: {
user: Object,
entity: Object,
feed_id: Number,
},
emits: ["disableModal", "onRemoveFeed"],
data() {
return {
new_comment: null,
comments: [],
};
},
mounted() {
console.log(this.entity)
this.loadComments();
this.loadCountPostsUser();
},
unmounted() {
this.comments = [];
},
computed: {
countPosts() {
return helper.declNumPosts(this.user.count_posts);
},
},
methods: {
onReplaceFeed(data) {
this.entity.collection_medias = data.collection;
this.entity.preview = data.preview;
this.entity.paid_open = 1;
},
loadCountPostsUser() {
if (
typeof this.user.count_posts === "undefined" ||
parseInt(this.user.count_posts, 10) === 0
) {
axios.post(route("user.posts.count", this.user.id)).then(({ data }) => {
this.user.count_posts = data;
});
}
},
onRemoveFeed() {
this.$emit("onRemoveFeed", this.feed_id);
},
loadComments() {
this.$emit("disableModal", 1);
axios.post(route("feed.comments", this.feed_id)).then(({ data }) => {
for (const prop in data) {
this.comments.push(data[prop]);
}
this.$emit("disableModal", 0);
});
},
addComment() {
this.$emit("disableModal", 1);
axios
.post(route("feed.comments.add", this.feed_id), {
body: this.new_comment,
})
.then(({ data }) => {
this.comments.push(data);
this.entity.comments++;
this.$emit("disableModal", 0);
});
this.new_comment = null;
},
likeFeed() {
Inertia.post(
route("feed.like", this.feed_id),
{},
{
preserveScroll: true,
preserveState: true,
}
);
if (this.entity.liked) {
this.entity.liked = false;
this.entity.likes--;
} else {
this.entity.liked = true;
this.entity.likes++;
}
},
},
};
</script>

View File

@@ -0,0 +1,37 @@
<template>
<div class="col-span-7 modal-media">
<component
:title="title"
:feed_id="feed_id"
:preview="preview"
:medias="medias"
:is="currentModalMedia"
></component>
</div>
</template>
<script>
import ModalFeedMediaImages from "@/Shared/Overlay/ModalFeedMediaImages";
import ModalFeedMediaVideos from "@/Shared/Overlay/ModalFeedMediaVideos";
import ModalFeedMediaMusics from "@/Shared/Overlay/ModalFeedMediaMusics";
export default {
components: {
ModalFeedMediaImages,
ModalFeedMediaVideos,
ModalFeedMediaMusics,
},
props: {
medias: Array,
type: String,
feed_id: Number,
title: String,
preview: String,
},
computed: {
currentModalMedia() {
return "modal-feed-media-" + this.type.toLowerCase();
},
},
methods: {},
};
</script>

View File

@@ -0,0 +1,33 @@
<template>
<swiper class="h-full" :grabCursor="true" navigation :pagination="{ clickable: true }">
<swiper-slide v-for="media in medias" :key="media.id">
<img class="w-full h-full object-cover" :src="media.url" alt="" />
</swiper-slide>
</swiper>
</template>
<script>
import SwiperCore, { Navigation, Pagination } from 'swiper/core';
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";
// import "swiper/components/navigation/navigation.min.css";
// import "swiper/components/pagination/pagination.min.css";
SwiperCore.use([Navigation, Pagination]);
export default {
components: {
Swiper,
SwiperSlide,
},
props: {
medias: Array,
title: String,
preview: String,
},
methods: {},
};
</script>

View File

@@ -0,0 +1,87 @@
<template>
<div class="modal-media h-full border-r border-indigo-100">
<div class="flex items-center border-b border-indigo-100">
<div class="flex-shrink-0 mr-5">
<feed-preview
class="h-28 w-28 md:w-56 md:h-56 object-cover"
type="music"
:source="preview"
/>
</div>
<div class="flex flex-col">
<span class="text-base md:text-xl font-semibold text-gray">{{
title
}}</span>
</div>
</div>
<div data-simplebar class="max-h-72 overflow-auto">
<div class="divide-y divide-indigo-100">
<div
@click.prevent="startPlay(media)"
v-for="media in medias"
:key="media.id"
:class="[
currentSong?.id === media.id
? 'bg-indigo-200 bg-opacity-25'
: 'hover:bg-indigo-200 hover:bg-opacity-25',
'p-4 flex items-center space-x-4',
]"
>
<div class="flex">
<toggle-play-button :media_id="media.id" />
</div>
<div class="flex-1 text-sm text-gray-light">
{{ media.name }}
</div>
<div class="text-sm text-gray-light">
<div v-if="currentSong?.id === media.id">{{ seek }}</div>
<span v-else>{{ media.time }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState, mapGetters } from "vuex";
import FeedPreview from "@/Shared/Feed/FeedPreview";
import TogglePlayButton from "@/Shared/Misc/TogglePlayButton";
export default {
components: {
FeedPreview,
TogglePlayButton,
},
props: {
medias: Array,
title: String,
preview: String,
feed_id: Number,
},
methods: {
...mapActions(["toggleAudio", "newCurrentPlaylist", "skipToIndexByMusic"]),
startPlay(music) {
if (this.currentSong?.id === music.id) {
this.toggleAudio();
return;
}
// if (this.playlist_id === this.feed_id) {
// this.skipToIndexByMusic(music);
// return;
// }
this.newCurrentPlaylist([music, this.medias, this.feed_id]);
},
},
computed: {
...mapGetters(["playing"]),
...mapState({
playlist_id: (state) => state.player.playlist_id,
seek: (state) => state.player.seek,
currentSong: (state) => state.player.currentSong,
}),
},
};
</script>

View File

@@ -0,0 +1,32 @@
<template>
<swiper class="h-full" :grabCursor="true" navigation :pagination="{ clickable: true }">
<swiper-slide v-for="media in medias" class="aspect-w-16 aspect-h-12 md:aspect-h-9" :key="media.id">
<video :src="media.url" controls></video>
</swiper-slide>
</swiper>
</template>
<script>
import SwiperCore, { Navigation, Pagination } from 'swiper/core';
import { Swiper, SwiperSlide } from "swiper/vue";
import "swiper/swiper-bundle.css";
// import "swiper/components/navigation/navigation.min.css";
// import "swiper/components/pagination/pagination.min.css";
SwiperCore.use([Navigation, Pagination]);
export default {
components: {
Swiper,
SwiperSlide,
},
props: {
medias: Array,
title: String,
preview: String,
},
methods: {},
};
</script>

View File

@@ -0,0 +1,90 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<template>
<TransitionRoot as="template" :show="open">
<Dialog as="div" static class="fixed z-[1000] inset-0 overflow-y-auto" @close="staticCloseModal" :open="open">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
<DialogOverlay class="fixed inset-0 bg-indigo-200 bg-opacity-75 transition-opacity" />
</TransitionChild>
<!-- This element is to trick the browser into centering the modal contents. -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100" leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<div class="inline-block align-bottom bg-indigo-300 rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-orange sm:mx-0 sm:h-10 sm:w-10">
<ExclamationIcon class="h-6 w-6 text-red-600" aria-hidden="true" />
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<DialogTitle as="h3" class="text-lg leading-6 font-medium text-gray-light">
Удалить контент
</DialogTitle>
<div class="mt-2">
<p class="text-sm text-gray-light">
Вы уверены, что хотите удалить этот контент? Восстановить можно, но будет сложно!
</p>
</div>
</div>
</div>
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<button type="button"
@click="remove"
class="mx-3 my-1 transition shadow-none hover:shadow-pink inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-pink focus:outline-none">
Удалить
</button>
<button type="button"
@click="staticCloseModal"
class="mx-3 my-1 transition shadow-none hover:shadow-classic inline-flex items-center px-8 py-3 justify-center text-base rounded-md text-white bg-indigo-300 focus:outline-none">
Отменить
</button>
</div>
</div>
</TransitionChild>
</div>
</Dialog>
</TransitionRoot>
</template>
<script>
import { Dialog, DialogOverlay, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue'
import { ExclamationIcon } from '@heroicons/vue/outline'
import { Inertia } from "@inertiajs/inertia";
export default {
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
ExclamationIcon,
},
emits: ['closeWarningModal', 'closeModal', 'destroyFeed'],
props: {
feed_id: Number,
open: {
type: Boolean,
default: false,
},
},
methods:{
staticCloseModal(){
this.$emit('closeWarningModal', false);
},
remove()
{
this.$emit('closeWarningModal', false);
this.$nextTick(() => {
this.$emit('closeModal', false);
})
Inertia.delete(route('feed.destroy', this.feed_id), { preserveScroll: true, preserveState: true })
}
}
}
</script>

View File

@@ -0,0 +1,96 @@
<template>
<div class="gradient-profile relative">
<user-banner class="h-56 xl:h-80 bg-indigo-200" :user='user' size='hero' />
</div>
<div class="-mt-24 xl:-mt-32 relative xl:container xl:mx-auto px-2 md:px-3">
<div class="flex flex-col md:flex-row">
<div class="flex-shrink-0 self-center md:self-start md:mr-6 2xl:mr-10">
<user-avatar :user='user' size='medium' class="shadow-classic object-cover w-48 h-48 xl:w-64 xl:h-64 text-5xl" />
</div>
<div class="w-full">
<div class="h-24 xl:h-32 hidden md:block"></div>
<div class="mt-2 ">
<div class="-mx-2 -my-2 lg:-mx-4 lg:-my-4 flex flex-col md:flex-row flex-wrap xl:flex-nowrap">
<div class="max-w-[300px] text-center md:text-left mx-2 my-2 lg:mx-4 lg:my-4 flex flex-shrink-0 flex-col self-center md:self-start">
<h1 class="md:mb-3 text-2xl xl:text-4xl font-semibold text-white">{{ user.name }}</h1>
<h2 class="text-base xl:text-xl text-gray-light">@{{ user.username }}</h2>
</div>
<div class="mx-2 my-2 lg:mx-4 lg:my-4 self-center flex flex-1 flex-col">
<div class="md:mt-2">
<div class="flex 2xl:text-lg text-white -mx-4">
<inertia-link :href="route('profile.user', user.username)" class="block mx-4">
<span class="text-orange">{{counts.feeds}}</span> {{countPosts}}
</inertia-link>
<inertia-link :href="route('profile.subs', user.username)" class="block mx-4">
<span class="text-orange">{{counts.subscribers }}</span> {{countSubs}}
</inertia-link>
<inertia-link :href="route('profile.readers', user.username)" class="block mx-4">
<span class="text-orange">{{counts.readers}}</span> в читаемых
</inertia-link>
</div>
<div class="mt-4 text-gray-light text-sm">{{user.about}}</div>
</div>
</div>
<div class="mx-2 my-2 lg:mx-4 lg:my-4 2xl:flex-shrink-0 self-center text-center">
<inertia-link v-if="user.is_auth_user" class="inline-flex tracking-wide items-center px-4 py-3 border border-white text-sm 2xl:text-base text-white rounded-full bg-transparent hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2" :href="route('setting.index')">
Редактировать профиль
</inertia-link>
<toggle v-else
@clicked='susbscribe'
:user_id='user.id'
:enabled="user.is_sub"
textin='Подписаться' textout='Отписаться' />
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import UserAvatar from "@/Shared/Misc/UserAvatar";
import UserBanner from "@/Shared/Misc/UserBanner";
import Toggle from "@/Shared/Form/Toggle";
import helper from "@/includes/helper";
import { Inertia } from "@inertiajs/inertia";
export default {
components: {
Toggle,
UserAvatar,
UserBanner,
},
props: {
user: Object,
counts: Object,
},
computed: {
countPosts() {
return helper.declNumPosts(this.counts.posts);
},
countReaders() {
return helper.declNumReaders(this.counts.readers);
},
countSubs() {
return helper.declNumSubs(this.counts.subscribers);
},
},
methods: {
susbscribe(user_id) {
Inertia.post(
route("users.subs", user_id),
{},
{ preserveScroll: true, preserveState: true }
);
},
},
};
</script>

View File

@@ -0,0 +1,77 @@
<template>
<div class="mt-12 xl:container xl:mx-auto px-2 md:px-3 buttons-filter-line">
<div class="flex">
<div class="flex flex-wrap -mx-2 -my-2 lg:-mx-4 lg:-my-4">
<inertia-link :href="route('profile.user', user.username)"
:class="[$page.component === 'Profile/Index' ? 'shadow-classic2 bg-orange text-white' : 'shadow-classic text-gray bg-indigo-200 hover:bg-orange hover:text-white', 'mx-2 my-2 lg:mx-4 lg:my-4 py-3 px-6 xl:px-10 transition inline-flex items-center justify-center text-sm xl:text-base rounded-md focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.167 3.333a.833.833 0 00-.833.834v11.666c0 .46.373.834.833.834h11.667c.46 0 .833-.373.833-.834V4.167a.833.833 0 00-.833-.834H4.167zm-2.5.834a2.5 2.5 0 012.5-2.5h11.667a2.5 2.5 0 012.5 2.5v11.666a2.5 2.5 0 01-2.5 2.5H4.167a2.5 2.5 0 01-2.5-2.5V4.167z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M1.667 7.5c0-.46.373-.833.833-.833h15a.833.833 0 110 1.666h-15a.833.833 0 01-.833-.833z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 6.667c.46 0 .834.373.834.833v10a.833.833 0 01-1.667 0v-10c0-.46.373-.833.833-.833z"/></svg>
Публикации
</inertia-link>
<inertia-link :href="route('profile.readers', user.username)"
:class="[$page.component === 'Profile/Readers' ? 'shadow-classic2 bg-orange text-white' : 'shadow-classic text-gray bg-indigo-200 hover:bg-orange hover:text-white', 'mx-2 my-2 lg:mx-4 lg:my-4 py-3 px-6 xl:px-10 transition inline-flex items-center justify-center text-sm xl:text-base rounded-md focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><polyline points="17 11 19 13 23 9"></polyline></svg>
Читаемые
</inertia-link>
<inertia-link :href="route('profile.subs', user.username)"
:class="[$page.component === 'Profile/Subs' ? 'shadow-classic2 bg-orange text-white' : 'shadow-classic text-gray bg-indigo-200 hover:bg-orange hover:text-white', 'mx-2 my-2 lg:mx-4 lg:my-4 py-3 px-6 xl:px-10 transition inline-flex items-center justify-center text-sm xl:text-base rounded-md focus:outline-none']">
<svg class="-ml-1 mr-2 h-4 w-4 md:h-5 md:w-5 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
Подписчики
</inertia-link>
</div>
<div v-if="user.is_auth_user" class="ml-auto">
<dropdown-menu>
<MenuItems class="origin-top-right absolute right-0 mt-2 w-64 bg-indigo-300 shadow-lg max-h-60 rounded-md text-base ring-1 ring-indigo-200 overflow-auto focus:outline-none">
<MenuItem>
<inertia-link :href="route('video.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-200 text-gray-light">
<VideoCameraIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Загрузить видео
</inertia-link>
</MenuItem>
<MenuItem>
<inertia-link :href="route('image.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-200 text-gray-light">
<PhotographIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Загрузить изображение
</inertia-link>
</MenuItem>
<MenuItem>
<inertia-link :href="route('music.create')" class="group flex items-center px-4 py-2 text-base hover:bg-indigo-200 text-gray-light">
<MusicNoteIcon class="mr-3 h-5 w-5 text-gray-400 group-hover:text-orange" aria-hidden="true" />
Загрузить музыку
</inertia-link>
</MenuItem>
</MenuItems>
</dropdown-menu>
</div>
</div>
</div>
</template>
<script>
import {
PhotographIcon,
VideoCameraIcon,
MusicNoteIcon,
} from "@heroicons/vue/solid";
import { MenuItem, MenuItems } from "@headlessui/vue";
import DropdownMenu from "@/Shared/Form/DropdownMenu";
export default {
components: {
DropdownMenu,
MenuItem,
MenuItems,
PhotographIcon,
MusicNoteIcon,
VideoCameraIcon,
},
props: {
user: Object,
},
};
</script>

View File

@@ -0,0 +1,67 @@
<template>
<div class="flex group">
<inertia-link :href="route('profile.user', comment.user.username)" class="block flex-shrink-0 mr-3">
<user-avatar
:user="comment.user"
size="small"
:class="[
creator_id == comment.user.id ? 'border border-orange' : '',
'text-xs w-10 h-10',
]"
/>
</inertia-link>
<div class="flex-1 mr-3">
<inertia-link :href="route('profile.user', comment.user.username)" class="font-semibold underline inline-block mr-2">{{
comment.user.username
}}</inertia-link>
{{ comment.body }}
<div
class="
transition-opacity
opacity-0
group-hover:opacity-100
flex
space-x-4
"
>
<span class="text-xs text-gray-light">{{
comment.created_at_humans
}}</span>
<span
class="
text-xs text-gray-light
font-semibold
hover:underline
cursor-pointer
"
>ответить</span
>
</div>
</div>
<div class="flex-shrink-0">
<button class="button-default">
<svg class="w-3 h-3">
<use xlink:href="#heart"></use>
</svg>
</button>
</div>
</div>
</template>
<script>
import UserAvatar from '@/Shared/Misc/UserAvatar'
export default {
components: {
UserAvatar
},
props: {
comment: Object,
creator_id: Number,
},
methods:{
likeFeed(){
this.$emit('likeFeed');
}
}
};
</script>

View File

@@ -0,0 +1,38 @@
<template>
<section>
<h2 class="text-base text-gray font-semibold">Превью:</h2>
<div class="mt-3 grid grid-cols-2 sm:grid-cols-3 gap-2 lg:gap-4">
<div v-for="common_media in purchase.common_medias" :key="common_media.id">
<div data-fancybox="preview" :data-src="common_media.url" class="cursor-pointer">
<img :src="common_media.url" class="w-full h-36 md:h-72 object-cover" alt="">
</div>
<a :href="common_media.url" download class="hover:text-orange transition-colors mt-2 text-gray-light text-sm">Скачать</a>
</div>
</div>
</section>
<section class="mt-6">
<h2 class="text-base text-gray font-semibold">Медиа материалы:</h2>
<div class="mt-3 grid grid-cols-2 sm:grid-cols-3 gap-2 lg:gap-4">
<div v-for="paid_media in purchase.paid_medias" :key="paid_media.id">
<div data-fancybox="paid" :data-src="paid_media.url" class="cursor-pointer">
<img :src="paid_media.url" class="w-full h-36 md:h-72 object-cover" alt="">
</div>
<a :href="paid_media.url" download class="hover:text-orange transition-colors mt-2 text-gray-light text-sm">Скачать</a>
</div>
</div>
</section>
</template>
<script>
import { Fancybox } from "@fancyapps/ui/src/Fancybox/Fancybox.js";
import "@fancyapps/ui/dist/fancybox.css";
export default {
components: {},
props: {
purchase: Object,
},
};
</script>

View File

@@ -0,0 +1,38 @@
<template>
<section>
<h2 class="text-base text-gray font-semibold">Превью:</h2>
<div class="mt-3 ">
<feed-music-body
:feed_id='purchase.id'
:title='purchase.title'
:preview='purchase.preview'
:medias='purchase.common_medias'
/>
</div>
</section>
<section class="mt-6">
<h2 class="text-base text-gray font-semibold">Медиа материалы:</h2>
<div class="mt-3">
<feed-music-body
:feed_id='purchase.id'
:title='purchase.title'
:preview='purchase.preview'
:medias='purchase.paid_medias'
/>
</div>
</section>
</template>
<script>
import FeedMusicBody from "@/Shared/FeedList/FeedMusicBody";
export default {
components: {
FeedMusicBody,
},
props: {
purchase: Object,
},
};
</script>

View File

@@ -0,0 +1,73 @@
<template>
<div class="mt-2 p-2 lg:p-4">
<div class="relative">
<div class="absolute inset-y-0 left-3 flex items-center z-10">
<svg class="flex-shrink-0 h-5 w-5 text-gray-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" > <path fill-rule="evenodd" clip-rule="evenodd" d="M11 4a7 7 0 100 14 7 7 0 000-14zm-9 7a9 9 0 1118 0 9 9 0 01-18 0z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M15.943 15.943a1 1 0 011.414 0l4.35 4.35a1 1 0 01-1.414 1.414l-4.35-4.35a1 1 0 010-1.414z"/> </svg>
</div>
<input class=" relative w-full focus:ring-4 focus:ring-offset-1 focus:ring-orange focus:ring-opacity-20 focus:ring-offset-orange focus:border-transparent text-gray border border-indigo-300 bg-indigo-200 rounded-md placeholder-gray-light !pl-10 " placeholder="Поиск музыки" type="search"/>
</div>
</div>
<div data-simplebar class="max-h-72 overflow-auto">
<div class="mt-2 divide-y divide-indigo-100">
<div
@click="toggleAudioLocal(listsMusic)"
v-for="listsMusic in listsMusics"
:key="listsMusic.id" class="
hover:bg-indigo-300 hover:bg-opacity-25 p-4 flex items-center space-x-4"
>
<div class="flex">
<button class="default">
<svg class="w-6 h-6">
<use v-show="!listsMusic.playing" xlink:href="#play"></use>
<use v-show="listsMusic.playing" xlink:href="#pause"></use>
</svg>
</button>
</div>
<div class="flex flex-1 text-sm text-gray-light">
{{ listsMusic.name }}
</div>
<div class="text-sm text-gray-light">
<span v-show="!listsMusic.playing">{{listsMusic.time}}</span>
<span v-show="listsMusic.playing">{{seek}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters, mapState } from "vuex";
export default {
components: {},
data() {
return {};
},
mounted() {
this.initLoadedPlaylist();
},
computed: {
...mapGetters(["tab_now"]),
...mapState({
seek: (state) => state.player.seek,
currentSong: (state) => state.player.currentSong,
listsMusics: (state) => state.player.playlist,
}),
},
methods: {
...mapActions(["initLoadedPlaylist", "toggleAudio", "skipToIndexByMusic"]),
toggleAudioLocal(music) {
if (this.tab_now && this.currentSong?.id === music.id) {
this.toggleAudio();
return;
}
this.skipToIndexByMusic(music);
},
},
};
</script>

View File

@@ -0,0 +1,72 @@
<template>
<div data-simplebar class="max-h-72 overflow-auto">
<div class="mt-2 divide-y divide-indigo-100">
<div
@click="toggleAudioLocal(listsMusic)"
v-for="listsMusic in listsMusics"
:key="listsMusic.id"
:class="[
currentSong?.id === listsMusic.id
? 'bg-indigo-300 bg-opacity-25'
: 'hover:bg-indigo-300 hover:bg-opacity-25',
'p-4 flex items-center space-x-4',
]"
>
<div class="flex">
<toggle-play-button :media_id="listsMusic.id" />
</div>
<div class="flex flex-1 text-sm text-gray-light">
{{ listsMusic.name }}
</div>
<div class="text-sm text-gray-light">
<span v-show="!listsMusic.playing">{{listsMusic.time}}</span>
<span v-show="listsMusic.playing">{{seek}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState } from "vuex";
import TogglePlayButton from "@/Shared/Misc/TogglePlayButton";
export default {
components: {
TogglePlayButton
},
data() {
return {
};
},
created(){
//console.log('loaded - now');
},
computed: {
//...mapGetters(["playing"]),
...mapState({
seek: (state) => state.player.seek,
currentSong: (state) => state.player.currentSong,
listsMusics: (state) => state.player.playlist,
}),
},
methods: {
...mapActions([
"toggleAudio",
"skipToIndexByMusic",
]),
toggleAudioLocal(music){
if (this.currentSong?.id === music.id) {
this.toggleAudio();
return;
}
this.skipToIndexByMusic(music);
},
},
};
</script>

25
resources/js/app.js vendored Normal file
View File

@@ -0,0 +1,25 @@
import { createApp, h } from 'vue'
import store from './store'
import { createInertiaApp, Link } from '@inertiajs/inertia-vue3'
import { InertiaProgress as progress } from '@inertiajs/progress'
progress.init({
color: '#673ab7',
})
createInertiaApp({
id: 'app',
resolve: name => import(`@/Pages/${name}`),
setup({ el, app, props, plugin }) {
createApp({ render: () => h(app, props) })
.mixin({
methods: {
route: window.route,
}
})
.use(store)
.use(plugin)
.component('InertiaLink', Link)
.mount(el)
},
})

24
resources/js/includes/helper.js vendored Normal file
View File

@@ -0,0 +1,24 @@
export default {
formatTime(time) {
var minutes = Math.floor(time / 60) || 0;
var seconds = Math.round((time - minutes * 60) || 0);
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
},
declOfNum (n, titles) {
return titles[n % 10 === 1 && n % 100 !== 11 ?
0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2];
},
declNumPosts(number){
const array_word = ['публикация', 'публикации', 'публикаций']
return this.declOfNum(number, array_word);
},
declNumReaders(number){
const array_word = ['публикация', 'публикации', 'публикаций']
return this.declOfNum(number, array_word);
},
declNumSubs(number){
const array_word = ['подписчик', 'подписчика', 'подписчиков']
return this.declOfNum(number, array_word);
}
};

6
resources/js/store/index.js vendored Normal file
View File

@@ -0,0 +1,6 @@
import { createStore } from 'vuex';
import modules from './modules';
export default createStore({
modules,
});

18
resources/js/store/modules/index.js vendored Normal file
View File

@@ -0,0 +1,18 @@
import { camelCase } from 'lodash';
const requireModule = require.context(
'.', false, /\.js$/,
);
const modules = {};
requireModule.keys().forEach((fileName) => {
if (fileName === './index.js' || fileName === './dummy.js') {
return;
}
const moduleConfig = requireModule(fileName);
const moduleName = camelCase(fileName.replace(/(\.\/|\.js)/g, ''));
modules[moduleName] = moduleConfig.default || moduleConfig;
});
export default modules;

273
resources/js/store/modules/player.js vendored Normal file
View File

@@ -0,0 +1,273 @@
import { Howl, Howler } from 'howler';
import axios from 'axios'
import helper from '@/includes/helper';
export default {
state: {
currentSong: {},
sound: {},
seek: '0:00',
duration: '0:00',
playerProgress: '0%',
playlist: [],
current_playlist: [],
my_playlist: [],
history_playlist: [],
playlist_id: 0,
history_group: [],
index: 0,
volume: 0.5,
tab: 'now',
local_current_playlist: JSON.parse(window.localStorage.getItem('local_current_playlist')),
local_current_playlist_song: JSON.parse(window.localStorage.getItem('local_current_playlist_song')),
local_current_playlist_id: parseInt(window.localStorage.getItem('local_current_playlist_id'), 10),
},
getters: {
playing: (state) => {
if (state.sound.playing) {
return state.sound.playing();
}
return false;
},
count_playlist: (state) => {
return state.playlist.length
},
volume_step: (state) => {
if (localStorage.volume_player) {
return localStorage.volume_player;
}
return state.volume
},
tab_now: (state) => {
return state.tab === 'now'
},
},
mutations: {
saveStorageCurrentPlaylist(state, [music, playlist, playlist_id]){
state.local_current_playlist = playlist;
state.local_current_playlist_song = music;
state.local_current_playlist_id = playlist_id;
window.localStorage.setItem('local_current_playlist', JSON.stringify(playlist));
window.localStorage.setItem('local_current_playlist_song', JSON.stringify(music));
window.localStorage.setItem('local_current_playlist_id', playlist_id);
},
clearPlaylist(state){
//state.playlist = [];
},
replaceTabName(state, payload){
state.tab = payload;
if(payload === 'now'){
state.playlist_id = state.local_current_playlist_id;
}else{
state.playlist_id = 0;
}
},
replacePlaylist(state, payload){
state.playlist = payload;
},
saveMyPlaylist(state, payload){
state.my_playlist = payload;
},
onlyPlay(state){
if (state.sound instanceof Howl) {
state.currentSong.playing = true;
state.sound.play();
}
},
onlyStop(state){
if (state.sound instanceof Howl) {
state.currentSong.playing = false;
state.sound.pause();
}
},
togglePlayMusic(state){
if (state.sound instanceof Howl) {
if (state.sound.playing()) {
state.currentSong.playing = false;
state.sound.pause();
} else {
state.currentSong.playing = true;
state.sound.play();
}
}
},
initVolume(state){
Howler.volume(state.volume);
},
updateVolume(state, payload) {
state.volume = payload;
localStorage.volume_player = payload;
if (state.sound instanceof Howl) {
Howler.volume(payload);
}
},
updatePosition(state) {
state.seek = helper.formatTime(state.sound.seek());
state.duration = helper.formatTime(state.sound.duration());
state.playerProgress = `${(state.sound.seek() / state.sound.duration()) * 100}%`;
},
currentPlaylistLoad(state, [music, playlist, playlist_id]){
playlist.forEach((track) => {
track.playing = false;
});
music.playing = true;
state.playlist = playlist;
state.playlist_id = playlist_id;
state.index = playlist.findIndex(track => track.id === music.id);
state.current_playlist = playlist;
},
howlReplace(state, [howl, music]){
if (state.sound instanceof Howl) {
state.sound.unload();
}
state.sound = howl;
state.currentSong = music;
state.index = state.playlist.findIndex(track => track.id === music.id);
},
},
actions: {
tabName({state, commit}, payload){
commit('replaceTabName', payload)
if(payload === 'loaded'){
if(state.my_playlist.length){
commit('replacePlaylist', state.my_playlist);
}
}
if(payload === 'now'){
if(state.current_playlist.length){
commit('replacePlaylist', state.current_playlist);
}
}
},
initLoadedPlaylist({state, commit}){
if(state.my_playlist.length > 0){
return;
}
return new Promise(resolve => {
commit('clearPlaylist');
axios.get(`/loaded-playlist`).then(response => response.data)
.then(playlist => {
commit('saveMyPlaylist', playlist);
commit('replacePlaylist', playlist);
commit('initVolume');
resolve(playlist)
})
.catch(() => {
//commit(mutationTypes.getArticleFailure)
})
})
},
async loadExsitPlaylist({ state, commit, dispatch }) {
if(state.local_current_playlist_id){
dispatch('instanceHowl', state.local_current_playlist_song);
commit('currentPlaylistLoad', [
state.local_current_playlist_song,
state.local_current_playlist,
state.local_current_playlist_id
]);
}
},
async skipToIndexByMusic({ state, commit, dispatch }, payload) {
commit('onlyStop');
dispatch('instanceHowl', payload);
commit('onlyPlay');
if(state.tab === 'now'){
commit('saveStorageCurrentPlaylist', [payload, state.playlist, state.playlist_id])
}
},
async newCurrentPlaylist({ commit, dispatch }, [music, playlist, playlist_id]){
commit('replaceTabName', 'now')
commit('onlyStop');
dispatch('instanceHowl', music);
commit('currentPlaylistLoad', [music, playlist, playlist_id]);
commit('initVolume');
commit('onlyPlay');
commit('saveStorageCurrentPlaylist', [music, playlist, playlist_id])
},
async instanceHowl({dispatch, commit}, payload){
let objectHowl = {};
objectHowl = new Howl({
src: [payload.url],
html5: true,
onend: () => {
dispatch('skipTrack', 'next');
}
});
objectHowl.on('play', () => {
requestAnimationFrame(() => {
dispatch('progress');
});
});
commit('howlReplace', [objectHowl, payload]);
},
async skipTrack({ state, dispatch }, payload) {
if (!state.playlist.length) {
return;
}
let index = 0;
if (payload === "next") {
index = state.index + 1
if (index >= state.playlist.length) {
index = 0
}
} else {
index = state.index - 1
if (index < 0) {
index = state.playlist.length - 1
}
}
dispatch('skipToIndexByMusic', state.playlist[index]);
},
async changeVolume({ commit }, payload) {
commit('updateVolume', payload);
},
async toggleAudio({ state, commit }) {
if (!state.sound.playing) {
return;
}
commit('togglePlayMusic');
},
progress({ commit, state, dispatch }) {
commit('updatePosition');
if (state.sound.playing()) {
requestAnimationFrame(() => {
dispatch('progress');
});
}
},
updateSeek({ state, dispatch }, payload) {
if (!state.sound.playing) {
return;
}
const { x, width } = payload.currentTarget.getBoundingClientRect();
// Document = 2000, Timeline = 1000, Click = 500, Distance = 500
const clickX = payload.clientX - x;
const percentage = clickX / width;
const seconds = state.sound.duration() * percentage;
state.sound.seek(seconds);
state.sound.once('seek', () => {
dispatch('progress');
});
},
},
};

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'These credentials do not match our records.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Previous',
'next' => 'Next &raquo;',
];

View File

@@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Passwords must be at least eight characters and match the confirmation.',
'reset' => 'Your password has been reset!',
'sent' => 'We have e-mailed your password reset link!',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that e-mail address.",
];

View File

@@ -0,0 +1,149 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_equals' => 'The :attribute must be a date equal to :date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'email' => 'The :attribute must be a valid email address.',
'exists' => 'The selected :attribute is invalid.',
'file' => 'The :attribute must be a file.',
'filled' => 'The :attribute field must have a value.',
'gt' => [
'numeric' => 'The :attribute must be greater than :value.',
'file' => 'The :attribute must be greater than :value kilobytes.',
'string' => 'The :attribute must be greater than :value characters.',
'array' => 'The :attribute must have more than :value items.',
],
'gte' => [
'numeric' => 'The :attribute must be greater than or equal :value.',
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
'string' => 'The :attribute must be greater than or equal :value characters.',
'array' => 'The :attribute must have :value items or more.',
],
'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'ipv4' => 'The :attribute must be a valid IPv4 address.',
'ipv6' => 'The :attribute must be a valid IPv6 address.',
'json' => 'The :attribute must be a valid JSON string.',
'lt' => [
'numeric' => 'The :attribute must be less than :value.',
'file' => 'The :attribute must be less than :value kilobytes.',
'string' => 'The :attribute must be less than :value characters.',
'array' => 'The :attribute must have less than :value items.',
],
'lte' => [
'numeric' => 'The :attribute must be less than or equal :value.',
'file' => 'The :attribute must be less than or equal :value kilobytes.',
'string' => 'The :attribute must be less than or equal :value characters.',
'array' => 'The :attribute must not have more than :value items.',
],
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'mimetypes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute format is invalid.',
'numeric' => 'The :attribute must be a number.',
'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values are present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'starts_with' => 'The :attribute must start with one of the following: :values',
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
'url' => 'The :attribute format is invalid.',
'uuid' => 'The :attribute must be a valid UUID.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/
'attributes' => [],
];

1151
resources/lang/ru.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'reset' => 'Ваш пароль был сброшен.',
'sent' => 'На указанный адрес электронной почты, была отправлена ссылка для сброса пароля.',
'token' => 'Ошибочный код сброса пароля.',
'user' => "Не удалось найти пользователя с указанным электронным адресом.",
"throttle" => "Слишком много попыток входа. Пожалуйста, попробуйте ещё раз через :seconds секунд.",
"throttled" => "Пожалуйста, подождите перед повторной попыткой.",
];

426
resources/lang/vendor/nova/en.json vendored Normal file
View File

@@ -0,0 +1,426 @@
{
"Actions": "Actions",
"Details": "Details",
"If you did not request a password reset, no further action is required.": "If you did not request a password reset, no further action is required.",
"Reset Password": "Reset Password",
"Sorry! You are not authorized to perform this action.": "Sorry! You are not authorized to perform this action.",
"You are receiving this email because we received a password reset request for your account.": "You are receiving this email because we received a password reset request for your account.",
"Confirm Password": "Confirm Password",
"Dashboard": "Dashboard",
"Email Address": "Email Address",
"Forgot Your Password?": "Forgot Your Password?",
"Forgot your password?": "Forgot your password?",
"Login": "Login",
"Logout": "Logout",
"Password": "Password",
"Remember Me": "Remember Me",
"Resources": "Resources",
"Send Password Reset Link": "Send Password Reset Link",
"Welcome Back!": "Welcome Back!",
"Delete Resource": "Delete Resource",
"Delete": "Delete",
"Detach Resource": "Detach Resource",
"Detach": "Detach",
"Detach Selected": "Detach Selected",
"Delete Selected": "Delete Selected",
"Force Delete Selected": "Force Delete Selected",
"Restore Selected": "Restore Selected",
"Restore Resource": "Restore Resource",
"Restore": "Restore",
"Force Delete Resource": "Force Delete Resource",
"Force Delete": "Force Delete",
"The :resource was created!": "The :resource was created!",
"Are you sure you want to delete this resource?": "Are you sure you want to delete this resource?",
"Are you sure you want to delete the selected resources?": "Are you sure you want to delete the selected resources?",
"Are you sure you want to detach this resource?": "Are you sure you want to detach this resource?",
"Are you sure you want to detach the selected resources?": "Are you sure you want to detach the selected resources?",
"Are you sure you want to force delete this resource?": "Are you sure you want to force delete this resource?",
"Are you sure you want to force delete the selected resources?": "Are you sure you want to force delete the selected resources?",
"Are you sure you want to restore this resource?": "Are you sure you want to restore this resource?",
"Are you sure you want to restore the selected resources?": "Are you sure you want to restore the selected resources?",
"No :resource matched the given criteria.": "No :resource matched the given criteria.",
"Another user has updated this resource since this page was loaded. Please refresh the page and try again.": "Another user has updated this resource since this page was loaded. Please refresh the page and try again.",
"Are you sure you want to delete this file?": "Are you sure you want to delete this file?",
"Are you sure you want to run this action?": "Are you sure you want to run this action?",
"Attach": "Attach",
"Attach & Attach Another": "Attach & Attach Another",
"Cancel": "Cancel",
"Choose": "Choose",
"Choose File": "Choose File",
"Choose Type": "Choose Type",
"Choose an option": "Choose an option",
"Click to choose": "Click to choose",
"Reset Filters": "Reset Filters",
"Create": "Create",
"Create & Add Another": "Create & Add Another",
"Delete File": "Delete File",
"Edit": "Edit",
"Edit Attached": "Edit Attached",
"Go Home": "Go Home",
"Hold Up!": "Hold Up!",
"Lens": "Lens",
"New": "New",
"Next": "Next",
"Only Trashed": "Only Trashed",
"Per Page": "Per Page",
"Preview": "Preview",
"Previous": "Previous",
"No Data": "No Data",
"No Current Data": "No Current Data",
"No Prior Data": "No Prior Data",
"No Increase": "No Increase",
"No Results Found.": "No Results Found.",
"Run Action": "Run Action",
"Select Action": "Select Action",
"Search": "Search",
"Press / to search": "Press / to search",
"Select All": "Select All",
"Select All Matching": "Select All Matching",
"Something went wrong.": "Something went wrong.",
"The action ran successfully!": "The action ran successfully!",
"The government won't let us show you what's behind these doors": "The government won't let us show you what's behind these doors",
"This image": "This image",
"Update": "Update",
"Update & Continue Editing": "Update & Continue Editing",
"View": "View",
"We're lost in space. The page you were trying to view does not exist.": "We're lost in space. The page you were trying to view does not exist.",
"Show Content": "Show Content",
"Hide Content": "Hide Content",
"Whoops": "Whoops",
"Whoops!": "Whoops!",
"With Trashed": "With Trashed",
"Trashed": "Trashed",
"Write": "Write",
"could not be found.": "could not be found.",
"total": "total",
"January": "January",
"February": "February",
"March": "March",
"April": "April",
"May": "May",
"June": "June",
"July": "July",
"August": "August",
"September": "September",
"October": "October",
"November": "November",
"December": "December",
"Afghanistan": "Afghanistan",
"Aland Islands": "Åland Islands",
"Albania": "Albania",
"Algeria": "Algeria",
"American Samoa": "American Samoa",
"Andorra": "Andorra",
"Angola": "Angola",
"Anguilla": "Anguilla",
"Antarctica": "Antarctica",
"Antigua And Barbuda": "Antigua and Barbuda",
"Argentina": "Argentina",
"Armenia": "Armenia",
"Aruba": "Aruba",
"Australia": "Australia",
"Austria": "Austria",
"Azerbaijan": "Azerbaijan",
"Bahamas": "Bahamas",
"Bahrain": "Bahrain",
"Bangladesh": "Bangladesh",
"Barbados": "Barbados",
"Belarus": "Belarus",
"Belgium": "Belgium",
"Belize": "Belize",
"Benin": "Benin",
"Bermuda": "Bermuda",
"Bhutan": "Bhutan",
"Bolivia": "Bolivia",
"Bonaire, Sint Eustatius and Saba": "Bonaire, Sint Eustatius and Saba",
"Bosnia And Herzegovina": "Bosnia and Herzegovina",
"Botswana": "Botswana",
"Bouvet Island": "Bouvet Island",
"Brazil": "Brazil",
"British Indian Ocean Territory": "British Indian Ocean Territory",
"Brunei Darussalam": "Brunei",
"Bulgaria": "Bulgaria",
"Burkina Faso": "Burkina Faso",
"Burundi": "Burundi",
"Cambodia": "Cambodia",
"Cameroon": "Cameroon",
"Canada": "Canada",
"Cape Verde": "Cape Verde",
"Cayman Islands": "Cayman Islands",
"Central African Republic": "Central African Republic",
"Chad": "Chad",
"Chile": "Chile",
"China": "China",
"Christmas Island": "Christmas Island",
"Cocos (Keeling) Islands": "Cocos (Keeling) Islands",
"Colombia": "Colombia",
"Comoros": "Comoros",
"Congo": "Congo",
"Congo, Democratic Republic": "Congo, Democratic Republic",
"Cook Islands": "Cook Islands",
"Costa Rica": "Costa Rica",
"Cote D'Ivoire": "Côte d'Ivoire",
"Croatia": "Croatia",
"Cuba": "Cuba",
"Curaçao": "Curaçao",
"Cyprus": "Cyprus",
"Czech Republic": "Czechia",
"Denmark": "Denmark",
"Djibouti": "Djibouti",
"Dominica": "Dominica",
"Dominican Republic": "Dominican Republic",
"Ecuador": "Ecuador",
"Egypt": "Egypt",
"El Salvador": "El Salvador",
"Equatorial Guinea": "Equatorial Guinea",
"Eritrea": "Eritrea",
"Estonia": "Estonia",
"Ethiopia": "Ethiopia",
"Falkland Islands (Malvinas)": "Falkland Islands (Malvinas)",
"Faroe Islands": "Faroe Islands",
"Fiji": "Fiji",
"Finland": "Finland",
"France": "France",
"French Guiana": "French Guiana",
"French Polynesia": "French Polynesia",
"French Southern Territories": "French Southern Territories",
"Gabon": "Gabon",
"Gambia": "Gambia",
"Georgia": "Georgia",
"Germany": "Germany",
"Ghana": "Ghana",
"Gibraltar": "Gibraltar",
"Greece": "Greece",
"Greenland": "Greenland",
"Grenada": "Grenada",
"Guadeloupe": "Guadeloupe",
"Guam": "Guam",
"Guatemala": "Guatemala",
"Guernsey": "Guernsey",
"Guinea": "Guinea",
"Guinea-Bissau": "Guinea-Bissau",
"Guyana": "Guyana",
"Haiti": "Haiti",
"Heard Island & Mcdonald Islands": "Heard Island and McDonald Islands",
"Holy See (Vatican City State)": "Vatican City",
"Honduras": "Honduras",
"Hong Kong": "Hong Kong",
"Hungary": "Hungary",
"Iceland": "Iceland",
"India": "India",
"Indonesia": "Indonesia",
"Iran, Islamic Republic Of": "Iran",
"Iraq": "Iraq",
"Ireland": "Ireland",
"Isle Of Man": "Isle of Man",
"Israel": "Israel",
"Italy": "Italy",
"Jamaica": "Jamaica",
"Japan": "Japan",
"Jersey": "Jersey",
"Jordan": "Jordan",
"Kazakhstan": "Kazakhstan",
"Kenya": "Kenya",
"Kiribati": "Kiribati",
"Korea, Democratic People's Republic of": "North Korea",
"Korea": "South Korea",
"Kosovo": "Kosovo",
"Kuwait": "Kuwait",
"Kyrgyzstan": "Kyrgyzstan",
"Lao People's Democratic Republic": "Laos",
"Latvia": "Latvia",
"Lebanon": "Lebanon",
"Lesotho": "Lesotho",
"Liberia": "Liberia",
"Libyan Arab Jamahiriya": "Libya",
"Liechtenstein": "Liechtenstein",
"Lithuania": "Lithuania",
"Luxembourg": "Luxembourg",
"Macao": "Macao",
"Macedonia": "North Macedonia",
"Madagascar": "Madagascar",
"Malawi": "Malawi",
"Malaysia": "Malaysia",
"Maldives": "Maldives",
"Mali": "Mali",
"Malta": "Malta",
"Marshall Islands": "Marshall Islands",
"Martinique": "Martinique",
"Mauritania": "Mauritania",
"Mauritius": "Mauritius",
"Mayotte": "Mayotte",
"Mexico": "Mexico",
"Micronesia, Federated States Of": "Micronesia",
"Moldova": "Moldova",
"Monaco": "Monaco",
"Mongolia": "Mongolia",
"Montenegro": "Montenegro",
"Montserrat": "Montserrat",
"Morocco": "Morocco",
"Mozambique": "Mozambique",
"Myanmar": "Myanmar",
"Namibia": "Namibia",
"Nauru": "Nauru",
"Nepal": "Nepal",
"Netherlands": "Netherlands",
"New Caledonia": "New Caledonia",
"New Zealand": "New Zealand",
"Nicaragua": "Nicaragua",
"Niger": "Niger",
"Nigeria": "Nigeria",
"Niue": "Niue",
"Norfolk Island": "Norfolk Island",
"Northern Mariana Islands": "Northern Mariana Islands",
"Norway": "Norway",
"Oman": "Oman",
"Pakistan": "Pakistan",
"Palau": "Palau",
"Palestinian Territory, Occupied": "Palestinian Territories",
"Panama": "Panama",
"Papua New Guinea": "Papua New Guinea",
"Paraguay": "Paraguay",
"Peru": "Peru",
"Philippines": "Philippines",
"Pitcairn": "Pitcairn Islands",
"Poland": "Poland",
"Portugal": "Portugal",
"Puerto Rico": "Puerto Rico",
"Qatar": "Qatar",
"Reunion": "Réunion",
"Romania": "Romania",
"Russian Federation": "Russia",
"Rwanda": "Rwanda",
"Saint Barthelemy": "St. Barthélemy",
"Saint Helena": "St. Helena",
"Saint Kitts And Nevis": "St. Kitts and Nevis",
"Saint Lucia": "St. Lucia",
"Saint Martin": "St. Martin",
"Saint Pierre And Miquelon": "St. Pierre and Miquelon",
"Saint Vincent And Grenadines": "St. Vincent and Grenadines",
"Samoa": "Samoa",
"San Marino": "San Marino",
"Sao Tome And Principe": "São Tomé and Príncipe",
"Saudi Arabia": "Saudi Arabia",
"Senegal": "Senegal",
"Serbia": "Serbia",
"Seychelles": "Seychelles",
"Sierra Leone": "Sierra Leone",
"Singapore": "Singapore",
"Sint Maarten (Dutch part)": "Sint Maarten",
"Slovakia": "Slovakia",
"Slovenia": "Slovenia",
"Solomon Islands": "Solomon Islands",
"Somalia": "Somalia",
"South Africa": "South Africa",
"South Georgia And Sandwich Isl.": "South Georgia and South Sandwich Islands",
"South Sudan": "South Sudan",
"Spain": "Spain",
"Sri Lanka": "Sri Lanka",
"Sudan": "Sudan",
"Suriname": "Suriname",
"Svalbard And Jan Mayen": "Svalbard and Jan Mayen",
"Swaziland": "Eswatini",
"Sweden": "Sweden",
"Switzerland": "Switzerland",
"Syrian Arab Republic": "Syria",
"Taiwan": "Taiwan",
"Tajikistan": "Tajikistan",
"Tanzania": "Tanzania",
"Thailand": "Thailand",
"Timor-Leste": "Timor-Leste",
"Togo": "Togo",
"Tokelau": "Tokelau",
"Tonga": "Tonga",
"Trinidad And Tobago": "Trinidad and Tobago",
"Tunisia": "Tunisia",
"Turkey": "Turkey",
"Turkmenistan": "Turkmenistan",
"Turks And Caicos Islands": "Turks and Caicos Islands",
"Tuvalu": "Tuvalu",
"Uganda": "Uganda",
"Ukraine": "Ukraine",
"United Arab Emirates": "United Arab Emirates",
"United Kingdom": "United Kingdom",
"United States": "United States",
"United States Outlying Islands": "U.S. Outlying Islands",
"Uruguay": "Uruguay",
"Uzbekistan": "Uzbekistan",
"Vanuatu": "Vanuatu",
"Venezuela": "Venezuela",
"Viet Nam": "Vietnam",
"Virgin Islands, British": "British Virgin Islands",
"Virgin Islands, U.S.": "U.S. Virgin Islands",
"Wallis And Futuna": "Wallis and Futuna",
"Western Sahara": "Western Sahara",
"Yemen": "Yemen",
"Zambia": "Zambia",
"Zimbabwe": "Zimbabwe",
"Yes": "Yes",
"No": "No",
"Action Name": "Name",
"Action Initiated By": "Initiated By",
"Action Target": "Target",
"Action Status": "Status",
"Action Happened At": "Happened At",
"resource": "resource",
"resources": "resources",
"Choose date": "Choose date",
"The :resource was updated!": "The :resource was updated!",
"The resource was updated!": "The resource was updated!",
"The :resource was deleted!": "The :resource was deleted!",
"The :resource was restored!": "The :resource was restored!",
"Increase": "Increase",
"Constant": "Constant",
"Decrease": "Decrease",
"Reset Password Notification": "Reset Password Notification",
"Nova User": "Nova User",
"of": "of",
"no file selected": "no file selected",
"Sorry, your session has expired.": "Sorry, your session has expired.",
"Reload": "Reload",
"Key": "Key",
"Value": "Value",
"Add row": "Add row",
"Attach :resource": "Attach :resource",
"Create :resource": "Create :resource",
"Choose :resource": "Choose :resource",
"New :resource": "New :resource",
"Edit :resource": "Edit :resource",
"Update :resource": "Update :resource",
"Start Polling": "Start Polling",
"Stop Polling": "Stop Polling",
"Choose :field": "Choose :field",
"Download": "Download",
"Action": "Action",
"Changes": "Changes",
"Original": "Original",
"This resource no longer exists": "This resource no longer exists",
":resource Details": ":resource Details",
"There are no available options for this resource.": "There are no available options for this resource.",
"All resources loaded.": "All resources loaded.",
"Load :perPage More": "Load :perPage More",
":amount Total": ":amount Total",
"Show All Fields": "Show All Fields",
"There was a problem submitting the form.": "There was a problem submitting the form.",
"There was a problem executing the action.": "There was a problem executing the action.",
"Do you really want to leave? You have unsaved changes.": "Do you really want to leave? You have unsaved changes.",
"*": "*",
"—": "—",
"The file was deleted!": "The file was deleted!",
"This file field is read-only.": "This file field is read-only.",
"No additional information...": "No additional information...",
"ID": "ID",
"30 Days": "30 Days",
"60 Days": "60 Days",
"90 Days": "90 Days",
"Today": "Today",
"Month To Date": "Month To Date",
"Quarter To Date": "Quarter To Date",
"Year To Date": "Year To Date",
"Customize": "Customize",
"Update :resource: :title": "Update :resource: :title",
"Update attached :resource: :title": "Update attached :resource: :title",
":resource Details: :title": ":resource Details: :title",
"The HasOne relationship has already been filled.": "The HasOne relationship has already been filled.",
"An error occured while uploading the file.": "An error occured while uploading the file."
}

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'attached' => 'This :attribute is already attached.',
'relatable' => 'This :attribute may not be associated with this resource.',
];

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>О компании - teeaseer</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="//fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
@php
$manifest = json_decode(file_get_contents(public_path('dist/manifest.json')), true);
@endphp
<link rel="stylesheet" href="/dist/{{ $manifest['resources/js/app.js']['css'][0] }}">
<style>
table {
border: 1px solid #dee2e6;
}
table {
width: 100%;
margin-bottom: 1rem;
color: #212529;
}
table {
border-collapse: collapse;
}
table thead td, table thead th {
border-bottom-width: 2px;
}
table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
}
table td, table th {
border: 1px solid #dee2e6;
}
table td, table th {
padding: 0.75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
ol{
list-style-type: decimal;
}
ul{
list-style-type: disc;
}
ol,ul{
list-style-position: inside;
}
ol li + li, ul li + li {
margin-top: .5em;
}
li ol, li ul{
margin-top: 1em;
margin-left: 2em;
}
.mlml2{
margin-left: 2em;
}
</style>
</head>
<body class="container mx-auto space-y-3 p-10">
<h1 class="text-center font-bold">Сайт teeaseer.com </h1>
<p>Сайт Teeaseer.com (Сайт) сайт в сети Интернет "Teeaseer.com" (домен http://teeaseer.com) включая все уровни указанного домена, включая его мобильную версию и как функционирующие на дату заключения настоящего Договора, так и запускаемые и вводимые в эксплуатацию в течение всего срока действия настоящего Договора), социальная сеть, администратором и владельцем которой является ООО «Тизер» ИНН 2462075237 КПП 246201001 ОГРН 1232400011414 зарегистрированный по по адресу: 660013, Красноярский край, город Красноярск, ул. Тамбовская, д. 5, стр 2, к 2, офис 301</p>
</body>
</html>

View File

@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>О компании - 4teaser</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="//fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
@php
$manifest = json_decode(file_get_contents(public_path('dist/manifest.json')), true);
@endphp
<link rel="stylesheet" href="/dist/{{ $manifest['resources/js/app.js']['css'][0] }}">
<style>
table {
border: 1px solid #dee2e6;
}
table {
width: 100%;
margin-bottom: 1rem;
color: #212529;
}
table {
border-collapse: collapse;
}
table thead td, table thead th {
border-bottom-width: 2px;
}
table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
}
table td, table th {
border: 1px solid #dee2e6;
}
table td, table th {
padding: 0.75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
ol{
list-style-type: decimal;
}
ul{
list-style-type: disc;
}
ol,ul{
list-style-position: inside;
}
ol li + li, ul li + li {
margin-top: .5em;
}
li ol, li ul{
margin-top: 1em;
margin-left: 2em;
}
.mlml2{
margin-left: 2em;
}
</style>
</head>
<body class="container mx-auto space-y-3 p-10">
<h1 class="text-center font-bold">Сервис 4teaser.com предоставляет компания ООО Синтез-К.</h1>
<p>ОГРН 1172468020658</p>
<p>ИНН 2466180271</p>
<p>КПП 246601001</p>
<p>Юридический адрес <br>
660049, Красноярский край, г.Красноярск, ул. Карла Маркса, д. 44А, помещение. 12</p>
</body>
</html>

View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Cookies - teeaseer</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="//fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
@php
$manifest = json_decode(file_get_contents(public_path('dist/manifest.json')), true);
@endphp
<link rel="stylesheet" href="/dist/{{ $manifest['resources/js/app.js']['css'][0] }}">
<style>
table {
border: 1px solid #dee2e6;
}
table {
width: 100%;
margin-bottom: 1rem;
color: #212529;
}
table {
border-collapse: collapse;
}
table thead td, table thead th {
border-bottom-width: 2px;
}
table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
}
table td, table th {
border: 1px solid #dee2e6;
}
table td, table th {
padding: 0.75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
ol{
list-style-type: decimal;
}
ul{
list-style-type: disc;
}
ol,ul{
list-style-position: inside;
}
ol li + li, ul li + li {
margin-top: .5em;
}
li ol, li ul{
margin-top: 1em;
margin-left: 2em;
}
.mlml2{
margin-left: 2em;
}
h2,h3{
font-weight: bold;
}
</style>
</head>
<body class="container mx-auto space-y-3 p-10">
<h1 class="text-center"><strong>ПОЛИТИКА ИСПОЛЬЗОВАНИЯ ФАЙЛОВ </strong><strong>COOKIE</strong> </h1>
<p>teeaseer</p>
&nbsp;
<p>Документ опубликован ООО «Тизер» ИНН 2462075237 КПП 246201001 ОГРН 1232400011414 зарегистрированный по по адресу: 660013, Красноярский край, город Красноярск, ул. Тамбовская, д. 5, стр 2, к 2, офис 301, далее «мы», «наш» или «нас», с целью ознакомления пользователей нашего веб-сайта с нашей политикой использования файлов cookie (куки).</p>
<p>Мы верим в ясность и открытость сбора и использования нами относящихся к вам данных. В целях прозрачности мы изложили в настоящей Политике использования файлов cookie подробную информацию о том, как и когда мы используем файлы cookie.</p>
<h2>Как мы используем cookie, теги и другие подобные технологии</h2>
<p>Пожалуйста, внимательно ознакомьтесь с данной Политикой использования файлов cookie. Данная политика описывает наши подходы к обработке информации, связанные с использованием нашего веб-сайта https://teeaseer.com/ и всех наших онлайн-продуктов и услуг (далее вместе именуемые «веб-сайт»).</p>
<h2>Файлы cookie</h2>
<p>Файл cookie представляет собой небольшой текстовый файл, включающий уникальный идентификатор, который посылается веб-сервером на ваш компьютер, мобильный телефон или другое устройство, подключенное к Интернету, когда вы посещаете сайт или используете мобильное приложение. Файлы cookie широко используются для эффективной работы сайтов и сбора информации о сетевых предпочтениях пользователей. Для наглядности эта Политика описывает работу с файлами cookie, но мы можем использовать другие подобные технологии таким же образом.</p>
<h3>Как мы используем файлы cookie?</h3>
<p>Мы используем файлы cookie для записи информации о сеансе и предоставлении вам наших услуг. Мы используем эту информацию для принятия решений о способах улучшения услуг, которые мы вам предлагаем, путем упрощения просмотра нашего веб-сайта, предоставления более персонализированного сервиса и адаптации рекомендаций и рекламы, которые вы видите на нашем веб-сайте. Также мы используем ее для улучшения нашего собственного анализа, который помогает нам разрабатывать и совершенствовать наш веб-сайт.</p>
<p><strong>C На нашем веб-сайте мы можем использовать все или некоторые из следующих категорий файлов cookie:</strong></p>
<p>Cookie, необходимые для работы веб-сайта.Эти файлы cookie являются необходимыми для работы различных частей нашего веб-сайта. Они позволяют вам перемещаться по нашему веб-сайту, а нам позволяют распознавать вас на веб-сайте, чтобы мы могли предоставить запрашиваемую вами услугу, например, запомнить ваши логин и пароль для входа.</p>
<p>Функциональные файлы cookie. Эти файлы cookie помогают нам настраивать контент нашего веб-сайта на основе ваших предпочтений. Они запоминают сделанный вами выбор, ваш язык, а также страну, в которой вы находились во время посещения нашего веб-сайта. Информация, собранная этими cookie, может быть анонимизирована, и они не могут отслеживать посещение вами других сайтов.</p>
<p>Статистические файлы cookie. Эти файлы cookie собирают информацию о том, как вы используете наш веб-сайт, чтобы помочь нам улучшить навигацию и помочь исправить технические проблемы и ошибки. Например, мы используем эти файлы cookie, чтобы лучше понять, каким образом вы переходите на наш веб-сайт, какие страницы просматриваете или используете, а также увидеть те области, где мы можем что-то улучшить. Информация, хранящаяся в этих файлах cookie, никогда не отображает личные данные, по которым может быть установлена ваша личность.</p>
<p>Cookie для таргетирования рекламы. Эти файлы cookie собирают информацию о том, какие сайты вы посещаете в Интернете и какими темами вы там интересуетесь. С их помощью мы можем добиться того, чтобы реклама и контент, который мы предоставляем, больше соответствовали вашим предпочтениям и интересам. Они также используются для ограничения количества просмотров рекламного объявления или конкретного контента, а также для оценки эффективности рекламной или маркетинговой кампании. Эти файлы cookie обычно размещаются сторонними рекламными сетями. Они запоминают сайты, которые вы посещаете, и эта информация предоставляется другим сторонам, например, рекламодателям.</p>
<p>Мы можем обращаться к сторонним сервисам, таким как Google Analytics, Яндекс.Метрика, CloudFlare, AddThis, которые действуют от нашего имени для обеспечения безопасного поиска и просмотра информации, улучшения качества взаимодействия с пользователями, отслеживания и анализа пользования нашим веб-сайтом за счет использования cookie, пиксельных тегов / веб-маяков и прочих подобных технологий. Эти сторонние сервисы собирают информацию о посещении нашего веб-сайта, делятся ею с нами, оценивают и анализируют эффективность наших рекламных объявлений, отслеживают использование страниц, помогают нам настраивать наши рекомендации и рекламу, а также отслеживать использование наших рекомендаций и рекламных объявлений.</p>
<h2>Как мне отказаться от использования cookie?</h2>
<p>В любое время вы можете запретить использование cookie в вашем браузере. Чтобы получить инструкции по блокировке, удалению или отключению файлов cookie, пожалуйста, используйте средства помощи и поддержки вашего браузера. Обратите внимание, что, удалив наши файлы cookie или отключив возможность загружать файлы cookie в будущем, вы можете не получить доступ к определенным областям или функциям нашего веб-сайта.</p>
<p>Пожалуйста, ознакомьтесь со следующими ссылками для получения информации об управлении и блокировании файлов cookie в зависимости от вашего браузера(a) Explorer: https://windows.microsoft.com/en-gb/internet-explorer/delete-manage-cookies#ie=ie-11.(b) Firefox: https://support.mozilla.org/en-US/kb/enable-and-disable-cookies-website-preferences.(c) Chrome: https://support.google.com/chrome/answer/95647?hl=en(Safari: https://support.apple.com/kb/PH19214?locale=en_GB</p>
<p>Вы можете запретить применение сторонних сетей отслеживания cookie, используя следующие инструменты: Кликнитесюда, чтобы отказаться от использования Google Analytics Кликните сюда, чтобы отказаться от использования Яндекс.Метрика Кликните сюда, чтобы отказаться от использования AddThis</p>
<p>Общую информацию и ресурсы для подобных отказов вы можете найти на сайте youronlinechoices.eu.</p>
<h2>Изменения, вносимые в настоящую Политику</h2>
<p>Время от времени мы можем вносить изменения в настоящую Политику использования файлов cookie и/или обновлять ее. Если данная Политика использования файлов cookie каким-либо образом изменится, мы опубликуем обновленную версию на этой странице. Мы рекомендуем вам регулярно просматривать эту страницу, чтобы всегда быть в курсе наших методов обработки информации и любых изменений в них. Любые изменения в данной Политике использования файлов cookie вступают в силу после публикации на этой странице.</p>
<h3>Контактная информация</h3>
<p>B Если у вас есть замечания или вопросы относительно данной политики и использования нами файлов cookie, пожалуйста, свяжитесь с нами по адресу support@teeaseer.com.</p>
</body>
</html>

View File

@@ -0,0 +1,13 @@
@component('mail::message')
# Сообщение с формы
Тема: {{$data->title}}
Сообщение: {{$data->body}}
ФИО: {{$data->userFullName}}
Телефон: {{$data->userPhone}}
Email: {{$data->userEmail}}
Ссылка на профиль: {{$data->profileUrl}}
Спасибо,
{{ config('app.name') }}
@endcomponent

View File

@@ -0,0 +1,9 @@
@component('mail::message')
# Зарегистрировался новый пользователь
{{$user->first_name}}
{{$user->email}}
Спасибо,
{{ config('app.name') }}
@endcomponent

View File

@@ -0,0 +1,233 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Публичная оферта на оказание услуг - Пользовательское соглашение teeaseer</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="//fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
@php
$manifest = json_decode(file_get_contents(public_path('dist/manifest.json')), true);
@endphp
<link rel="stylesheet" href="/dist/{{ $manifest['resources/js/app.js']['css'][0] }}">
<style>
table {
border: 1px solid #dee2e6;
}
table {
width: 100%;
margin-bottom: 1rem;
color: #212529;
}
table {
border-collapse: collapse;
}
table thead td, table thead th {
border-bottom-width: 2px;
}
table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
}
table td, table th {
border: 1px solid #dee2e6;
}
table td, table th {
padding: 0.75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
ol{
list-style-type: decimal;
}
ul{
list-style-type: disc;
}
ol,ul{
list-style-position: inside;
}
ol li + li, ul li + li {
margin-top: .5em;
}
li ol, li ul{
margin-top: 1em;
margin-left: 2em;
}
</style>
</head>
<body class="container mx-auto space-y-3 p-10">
<h1 style="text-align: center;"><strong>ПУБЛИЧНАЯ ОФЕРТА на оказание услуг</strong></h1>
<p>Пользовательское соглашение teeaseer</p>
<p>1.1. Сайт teeaseer.com (Сайт) сайт в сети Интернет "teeaseer.com " (доменhttp://teeaseer.com) включая все уровни указанного домена, включая его мобильную версию и как функционирующие на дату заключения настоящего Договора, так и запускаемые и вводимые в эксплуатацию в течение всего срока действия настоящего Договора), социальная сеть, администратором и владельцем которой является ООО «Тизер» ИНН 2462075237 КПП 246201001 ОГРН 1232400011414 зарегистрированный по по адресу: 660013, Красноярский край, город Красноярск, ул. Тамбовская, д. 5, стр 2, к 2, офис 301</p>
<p>Настоящее Пользовательское соглашение (далее также «Пользовательское соглашение» и/или «Соглашение») регулирует отношения по использованию Сервиса «teeaseer» (далее «Сервис») и общие условия оказания услуг между ООО «Тизер» ИНН 2462075237 которое является юридическим лицом, созданным на территории Российской Федерации и в соответствии с законодательством Российской Федерации, с одной стороны, и физическим лицом, принявшим условия настоящего Соглашения путём его Акцепта с другой стороны, далее при совместном упоминании именуемые «Стороны», а по отдельности «Сторона».</p>
<p>Настоящее Соглашение и отношения Сторон, возникшие из настоящего Соглашения, регулируются законодательством Российской Федерации.</p>
<p>1. Термины и определения, используемые в настоящем Соглашении</p>
<p>Акцепт Соглашения факт любого использования (в том числе без осуществления регистрации/авторизации на Сервисе) Сервиса Пользователем, автоматически признающий Пользователя принявшим безоговорочно и в целом условия настоящего Соглашения и иных документов, размещенных на Сервисе.</p>
<p>Контент результат интеллектуальной деятельности и/или приравненные к ним средства индивидуализации, в том числе видео, аудио, звуковые записи, фото, текст, изображения, исполнения, графика, и другие материалы, размещаемые Пользователем на Сервисе в соответствии с требованиями настоящего Соглашения, законодательства Российской Федерации и также документами, размещенными на Сервисе.</p>
<p>Сервис интернет-сайт teeaseer.com на которых Пользователи могут разместить, удалить, находить и просматривать Контент, оставлять комментарии, пользоваться Услугами и Платными Услугами.</p>
<p>Лица младше 18 лет могут пользоваться Сервисом только с разрешения законного представителя, акцептовавшего настоящее Соглашение. Законный представитель Пользователя младше 18 лет, разрешая такому Пользователю пользоваться Сервисом, обязуется соблюдать условия Соглашения и нести ответственность за действия, которые совершает в Сервисе несовершеннолетний Пользователь.</p>
<p>Правообладатель физическое или юридическое лицо, обладающее исключительным правом на результат интеллектуальной деятельности или на средство индивидуализации либо имеющее право на использование таких результатов интеллектуальной деятельности или средства индивидуализации на основании лицензионного договора.</p>
<p>Устройства персональные компьютеры, смартфоны, планшеты и иные устройства, с помощью которых можно получить доступ к Сервису посредством сети Интернет.</p>
<p>Услуга предоставление Владельцем Сервиса Пользователю возможности без оплаты просматривать, размещать, обрабатывать и удалять Контент, использовать бесплатные материалы Владельца Сервиса и/или Правообладателей (например, стикеры, графику, фонограммы, AR эффекты и сервисы и т.д.) (далее «Материалы»), а также обмениваться сообщениями, комментариями на Сервисе в соответствии с правилами, ограничениями и техническими требованиями, указанными в настоящем Соглашении и на Сервисе.</p>
<p>Учетная запись личный кабинет Пользователя.</p>
<p>Платная Услуга предоставление Владельцем Сервиса Пользователю дополнительных услуг за указанную в Сервисе плату, в том числе предоставление возможности в течение определенного периода времени использовать дополнительные Материалы Владельца Сервиса и Правообладателей совместно с Контентом такого Пользователя на Сервисе или, в случае получения специального разрешения от Владельца Сервиса, и на других сервисах, приложениях для Устройств и интернет-сайтах в соответствии с правилами, ограничениями и техническими требованиями, указанными в настоящем Соглашении и на Сервисе. Пользователь не получает каких-либо прав на Материалы и/или на производные произведения, если такие произведения будут созданы с использованием Материалов. Оплачивая Платную Услугу, Пользователь понимает, что список доступных Пользователю дополнительных услуг, дополнительных Материалов может меняться, в том числе в течение оплаченного срока оказания Платной Услуги.</p>
<p>Авторизация процесс проверки Владельцем Сервиса прав Пользователя на доступ к Учетной записи.</p>
<p>2. Предмет Соглашения</p>
<p>2.1. Владелец Сервиса предоставляет Пользователям Услуги и Платные Услуги непосредственно на Сервисе.</p>
<p>2.2. Для использования Сервиса Пользователь обязан принять, совершив Акцепт, и соблюдать настоящее Соглашение. С момента Акцепта Соглашения Пользователем настоящее Соглашение считается заключённым с Пользователем, и Пользователь приобретает права и обязанности, предусмотренные настоящим Соглашением.</p>
<p>2.3. Изменение настоящего Соглашения совершается путём размещения Владельцем Сервиса изменений настоящего Соглашения или новой редакции настоящего Соглашения в интерфейсе Сервиса. Пользователь обязуется самостоятельно отслеживать изменения в Соглашении. Совершение Пользователем действий, направленных на получение Услуг и Платных Услуг, после изменения условий Соглашения является подтверждением согласия Пользователя с новой редакцией Соглашения.</p>
<p>2.4. Фактический доступ Пользователя к Сервису посредством Сервиса, фактическое использование Пользователем Сервиса и Контента, возможно только на Устройствах, на которых установлено необходимое и достаточное программное обеспечение, отвечающее техническим требованиям, указанным в разделе 10 Соглашения, и которое имеет техническую и фактическую возможность доступа к сети Интернет.</p>
<p>2.5. Сервис относится к информационной продукции для детей, достигших возраста двенадцати лет (12+).</p>
<p>3. Регистрация на Сервисе</p>
<p>3.1. Просмотр общедоступного Контента (как указано в п. 4.1.2 ниже) других Пользователей Сервиса доступен без регистрации / Авторизации. Иные Услуги или Платные Услуги доступны Пользователю после прохождения Пользователем процедуры регистрации на Сервисе посредством создания Учетной записи, в том числе с помощью и по правилам сервисов третьих лиц, с указанием всех необходимых и достоверных данных, запрашиваемых в регистрационной форме. В случае изменения указанных в Учетной записи сведений, Пользователь обязан незамедлительно внести изменения в Учетной записи посредством соответствующего функционала в личном кабинете.</p>
<p>3.2. Пароль от Учетной записи является конфиденциальным, Пользователь обязан хранить пароль в тайне и не раскрывать его третьим лицам. В том случае, если третьи лица могли получить доступ к паролю или получили его, необходимо установить новый пароль и обратиться в службу поддержки, для проверки, был ли осуществлен несанкционированный доступ к Учетной записи, и необходимости принятия мер.</p>
<p>3.3. Пользователь принимает на себя полную ответственность перед Сервисом и третьими лицами за действия, которые происходят с помощью его Учетной записи.</p>
<p>3.4. Владелец Сервиса не несет ответственности за размещаемую Пользователем в Учетной записи информацию, а также за Контент, загруженный Пользователем с помощью Учетной записи, и не осуществляет контроль доступа к данной информации других Пользователей.</p>
<p>3.5. Удаление Учетной записи: Пользователь может инициировать удаление Учетной записи нажав на кнопку «Удалить аккаунт» на странице «Удаление аккаунта» в разделе «Настройки аккаунта». После нажатия на кнопку «Удалить аккаунт» автоматически прекращается сеанс использования Пользователем Сервиса в качестве зарегистрированного Пользователя, после чего можно воспользоваться лишь Услугами Сервиса, доступными Пользователям без регистрации.</p>
<p>3.6. Восстановление Учетной записи: при попытке Пользователя авторизоваться под своей удаленной Учетной записью, Сервис сообщит, что «Аккаунт заблокирован» с причиной блокировки: «удаление аккаунта», а также предложит восстановить Учетную запись посредством кнопки «Восстановить аккаунт». При нажатии на кнопку «Восстановить аккаунт» Пользователю предлагается перейти в Telegram-чат для направления сообщения технической поддержке Сервиса с просьбой восстановить Учетную запись. В качестве альтернативы, Пользователь может связаться с технической поддержкой по электронной почте: support@ritm.media. Техническая поддержка передает модератору Сервиса сообщение с просьбой Пользователя восстановить Учетную запись. После завершения процедуры восстановления Учетной записи Пользователю поступит соответствующее уведомление, после чего можно авторизоваться на Сервисе под своей Учетной записью.</p>
<p>Восстановление Учетной записи возможно в течение 30 (тридцати) календарных дней после удаления Учетной записи согласно п. 3.5. настоящего Соглашения.</p>
<p>4. Права и обязанности Пользователя</p>
<p>4.1. Пользователь имеет право:</p>
<p>4.1.1. Размещать, обрабатывать и удалять, а также просматривать Контент на Сервисе, обмениваться сообщениями, комментариями на Сервисе, а также пользоваться иными Услугами и/или Платными Услугами Владельца Сервиса в соответствии с условиями Соглашения и действующего законодательства Российской Федерации. Размещая Контент на Сервисе, Пользователь обнародует Контент, в том числе свое изображение, и разрешает доступ к такому Контенту для всех пользователей сети Интернет, если иное не указано Пользователем с помощью встроенных возможностей Сервиса, как это указано в п.4.1.2. Соглашения, а также Пользователь даёт разрешение всем Пользователям Сервиса использовать его Контент в порядке, установленном в п. 4.1.3. Соглашения, если иное не установлено Пользователем с помощью встроенных возможностей Сервиса. Пользователь понимает, что Контент и любые материалы, размещенные им на Сервисе, могут попадать в выдачи поисковых систем (Яндекс, Google и т.п.) даже после удаления Учетной записи с Сервиса. Владелец Сервиса не несет ответственности за индексацию или переиндексацию страниц поисковыми системами.</p>
<p>4.1.2. Устанавливать доступность своего Контента с использованием настроек Учетной записи или при публикации Контента делать Контент общедоступным для всех пользователей сети Интернет или предоставлять доступ лишь определенным Пользователям.</p>
<p>4.1.3. Все Пользователи Сервиса могут свободно использовать Контент полностью или любую часть Контента, созданного другим Пользователем, включая использование отдельно звука/аудиоряда, изображения/видеоряда из Контента и их синхронизацию с другими материалами/Контентом, если соответствующие ограничения на использование Контента не установлены таким Пользователем в порядке п. 4.1.1. Соглашения, для создания своего производного Контента.</p>
<p>4.1.4. При условии оплаты, пользоваться Платными Услугами Владельца Сервиса в течение определенного срока.</p>
<p>4.1.5. Использовать Контент, созданный с помощью функционала Сервиса, на сторонних сервисах/площадках только с сохранением логотипа Сервиса в таком Контенте, если иное использование такого Контента прямо не разрешено Соглашением и/или не доступно соответствующим функционалом Сервиса.</p>
<p>4.1.6. Отчуждать третьим лицам права на Контент, размещенный на Сервисе, созданный без помощи функционала Сервиса, при этом прекратив размещение от своего имени такого Контента на Сервисе, если договорённости об ином не достигнуты между Пользователем Сервиса и такими третьими лицами.</p>
<p>4.1.7. Обратиться с жалобой к Владельцу Сервиса на его решение об ограничении доступа к Контенту/материалу Пользователя в порядке мониторинга Владельцем Сервиса информации на Сервисе, распространяемой с нарушением закона, либо рассмотрения обращений Пользователей. Жалоба направляется по электронному адресу: teeaseer@bk.ru, либо в техническую поддержку Сервиса через Telegram-чат. Владелец Сервиса направляет Пользователю ответ на жалобу в течение 3 (Трёх) дней со дня ее поступления. В случае несогласия Пользователя с ответом Владельца Сервиса, Пользователь вправе обратиться с заявлением в уполномоченные государственные органы согласно действующему законодательству.</p>
<p>4.2. Пользователь обязан:</p>
<p>4.2.1. Не использовать Материалы, в том числе дополнительные, в целях доработки/обработки Контента для его размещения на сторонних сервисах и/или передачи прав на такой доработанный/обработанный Контент третьим лицам, если иное не разрешено настоящим Соглашением.</p>
<p>4.2.2. Обеспечивать соблюдение прав третьих лиц, включая авторские, смежные, иные интеллектуальные права авторов и Правообладателей соответствующих результатов интеллектуальной деятельности, а также других требований законодательства РФ при производстве, размещении Контента, в том числе, не использовать при создании, размещении Контента любые объекты интеллектуальных прав, если в отношении них не заключены соответствующие договоры с Правообладателями.</p>
<p>Если Пользователь не имеет прав на Контент, то он не имеет права размещать его на Сервисе.</p>
<p>В том случае, если Пользователь передал исключительные права на результаты интеллектуальной деятельности (их часть) третьим лицам, он обязуется не размещать их на Сервисе, если между Пользователем и такими лицами не достигнуты договоренности об ином. Все вопросы и связанные с ними споры по обладанию правами на соответствующие объекты интеллектуальной собственности Пользователь разрешает самостоятельно и за свой счет.</p>
<p>4.2.3. Не загружать, не хранить, не публиковать, не распространять и не предоставлять доступ или иным образом использовать любые комментарии, сообщения или Контент/материалы (в том числе ссылки на аналогичные материалы), которые являются заведомо ложной информацией, запрещены законодательством Российской Федерации, нормами морали и нравственности, а также «Правилами teeaseer.com, либо нарушают права и интересы каких-либо граждан, организаций, их честь, достоинство и деловую репутацию.</p>
<p>Помимо установленных в настоящем пункте запретов и ограничений Пользователям запрещено распространение каких-либо материалов и информации на Сервисе, связанных в том числе с:</p>
<p>- порнографическими изображениями несовершеннолетних и/или объявлениями о привлечении несовершеннолетних в качестве исполнителей для участия в зрелищных мероприятиях порнографического характера;</p>
<p>- способами, методами разработки, изготовлением и использованием наркотических средств, психотропных веществ и их прекурсоров, новых потенциально опасных психоактивных веществ, местах их приобретения, способах и местах культивирования наркосодержащих растений;</p>
<p>- совершением самоубийства, а также призывами к совершению самоубийства;</p>
<p>- совершением уголовно наказуемых деяний и других противоправных нарушений (включая, но не ограничиваясь: склонение или вовлечение в противоправные действия несовершеннолетних; оскорбление человеческого достоинства, общественной нравственности; неуважение к государству, официальным государственным символам, Конституции или органам государственной власти Российской Федерации и др.);</p>
<p>- разглашением сведений, составляющих государственную или иную специально охраняемую законом тайну;</p>
<p>- публичными призывами к осуществлению террористической/экстремисткой деятельности и/или публичного оправдания терроризма, других экстремистских материалов, организаций;</p>
<p>- пропагандой порнографии, культа насилия и жестокости;</p>
<p>- дискриминацией, ущемлением конкретного гражданина или отдельных категорий граждан по признакам пола, возраста, расовой или национальной принадлежности, языка, отношения к религии, профессии, места жительства и работы, а также в связи с их политическими убеждениями;</p>
<p>- призывами к массовым беспорядкам и участием в публичных мероприятиях, проводимых с нарушением установленного законом порядка;</p>
<p>- пропагандой нетрадиционных сексуальных отношений и (или) предпочтений, педофилии, желания сменить биологический пол;</p>
<p>- распространением недостоверной информации (в том числе под видом достоверной), включая, но не ограничиваясь:</p>
<p>а) общественно значимой информации, которая создает угрозу создания помех функционированию или прекращения функционирования объектов жизнеобеспечения, транспортной или социальной инфраструктуры, кредитных организаций, объектов энергетики, промышленности или связи;</p>
<p>б) информации от иностранной или международной неправительственной организации, деятельность которой признана нежелательной на территории Российской Федерации.</p>
<p>4.2.4. При размещении на Сервисе или в Контенте фотографий или видео с изображением третьих лиц получить согласие указанных лиц на обнародование и использование их изображений, если необходимость получения такого согласия установлена действующим законодательством Российской Федерации.</p>
<p>4.2.5. Не размещать на Сервисе, не передавать посредством функционала Сервиса Контент, комментарии и сообщения, содержащие информацию агитационного характера.</p>
<p>В случаях размещения Пользователем на Сервисе какой-либо информации агитационного характера (включая случаи распространения Пользователем агитационной информации, созданной или принадлежащей другим гражданам, иным третьим лицам), Пользователь обязуется соблюдать требования Федерального закона «Об основных гарантиях избирательных прав и права на участие в референдуме граждан Российской Федерации», либо иные применимые законы Российской Федерации о референдумах, выборах, распространении агитационных материалов.</p>
<p>4.2.6. Не указывать данные третьих лиц (в том числе имена, псевдонимы, названия аккаунтов в социальных сетях и т.д.) с намерением выдать себя за другого человека.</p>
<p>4.2.7. Не использовать Сервис для регистрации информационной или рекламной страницы юридического лица, иной организации и/или сообщества без разрешения такого лица.</p>
<p>4.2.8. Не осуществлять посредством Сервиса рассылки спама.</p>
<p>4.2.9. Не использовать Сервис для размещения/распространения Контента, содержащего вирусы или другие компьютерные коды, файлы или программы, предназначенные для нарушения, уничтожения либо ограничения функциональности любого компьютерного или телекоммуникационного оборудования или программ, для осуществления несанкционированного доступа, а также размещения ссылок на вышеуказанную информацию.</p>
<p>4.2.10. Самостоятельно оценивать содержание размещаемого/отправляемого Контента на соответствие требованиям действующего законодательства Российской Федерации и Соглашения.</p>
<p>4.2.11. Не использовать Сервис для сбора, хранения и распространения персональных данных других лиц, а также для размещения ссылок на адреса электронной почты, Интернет-сайтов (url), аккаунтов в социальных сетях и мессенджерах, номеров телефонов как собственных, так и других Пользователей и третьих лиц.</p>
<p>4.2.12. Не нарушать нормальной работы Сервиса.</p>
<p>4.2.13. В течение 3 (Трёх) календарных дней с момента получения соответствующего запроса Владельца Сервиса предоставлять Владельцу Сервиса в электронном формате документы, подтверждающие наличие у Пользователя всех необходимых прав на размещение Контента на Сервисе;</p>
<p>4.2.14. Не использовать Сервис для осуществления просветительской деятельности в случае, если она не соответствует требованиям Федерального закона «Об образовании в Российской Федерации»;</p>
<p>4.2.15. Не использовать Сервис для распространения информации об азартных играх и лотереях в нарушение требований Федеральных законов «О государственном регулировании деятельности по организации и проведению азартных игр» и «О лотереях»;</p>
<p>4.2.16. Не использовать Сервис для продажи алкогольной продукции, спиртосодержащей пищевой продукции, этилового спирта или спиртосодержащей продукции, розничная продажа которой ограничена или запрещена по действующему законодательству Российской Федерации;</p>
<p>4.2.17. Ознакомиться с Соглашением до начала использования Сервиса;</p>
<p>4.2.18. При использовании для регистрации на Сервисе сервисов третьих лиц принять условия использования соответствующих сервисов, указанные в них.</p>
<p>5. Права и обязанности Владельца Сервиса</p>
<p>5.1. Владелец Сервиса имеет право:</p>
<p>5.1.1. Распоряжаться и пользоваться полученным по настоящему Соглашению правом на Контент как самостоятельно, так и разрешать использование третьим лицам и другим Пользователям без выплаты вознаграждения Пользователю.</p>
<p>5.1.2. Запрашивать у Пользователя документы, подтверждающие наличие у него всех необходимых прав на размещение Контента на Сервисе.</p>
<p>5.1.3. В одностороннем порядке в любое время по своему усмотрению заблокировать Учетную запись Пользователя, в том числе, если Пользователь не соблюдает любое из положений настоящего Соглашения, или если действия, которые осуществляются с использованием Учетной записи Пользователя, могут причинить ущерб или ухудшить качество услуг, или ущемить, или нарушить права третьих лиц (граждан или организаций), или нарушают какие-либо применимые законы или правила настоящего Соглашения, или соответствуют возможным причинам блокировки, в том числе указанным в «Правилах teeaseer.com </p>
<p>5.1.4. Определять структуру и наполнение Сервиса, разрешать и ограничивать доступ к Сервису в соответствии с настоящим Соглашением и законодательством Российской Федерации.</p>
<p>5.1.5. Владелец Сервиса осуществляет мониторинг Контента на Сервисе (в автоматическом и ручном режиме, включая рассмотрение обращений Пользователей через электронную форму на Сервисе) с целью выявить информацию, распространяемую с нарушением действующего законодательства Российской Федерации, требований настоящего Соглашения, «Правил teeaseer.com», и может ограничивать доступ к любому Контенту/материалам, сообщений Пользователей и третьих лиц, без уведомления Пользователя о принятых Владельцем Сервиса мерах по ограничению доступа к Контенту/материалу, либо с уведомлением, если это предусмотрено нормами действующего законодательства.</p>
<p>Владелец Сервиса также вправе включать или отключать любые функциональные блоки Сервиса, перемещать любой Контент без предупреждения Пользователя.</p>
<p>5.1.6. По своему собственному усмотрению, по любой причине, а также в случае нарушения Пользователем настоящего Соглашения, любых иных документов, размещенных на Сервисе, или законодательства Российской Федерации Владелец Сервиса вправе приостанавливать, ограничивать или прекращать доступ такого Пользователя ко всем или к любому из разделов Сервиса в одностороннем порядке, а также блокировать возможность использования Сервиса (блокировать IP-адреса) для Пользователя в любое время, без объяснения причин, с предварительным уведомлением или без такового, не отвечая за любые убытки, которые могут быть причинены Пользователю таким действием, в случаи нарушения правил пользования владелец сервиса вправе блокирывать вывод срелств с учетной записи пользователя..</p>
<p>5.1.7. Проводить стимулирующие маркетинговые мероприятия разного характера с целью мотивации Пользователей, привлечения новых пользователей и повышения рейтинга Сервиса.</p>
<p>5.1.8. По своему собственному усмотрению изменять или удалять любую публикуемую Владельцем Сервиса на Сервисе информацию, полностью или частично, и любые элементы и составные части Сервиса. При этом Стороны соглашаются, что Владелец Сервиса не отвечает за любой вред, который может быть причинен Пользователю такими действиями.</p>
<p>5.1.9. Устанавливать любые ограничения в использовании Сервиса, в любое время изменять настоящее Соглашение в одностороннем порядке, без получения согласия Пользователя.</p>
<p>5.1.10. Осуществлять рассылки Пользователям сообщений, в т.ч. посредством сетей электросвязи, содержащих организационно-техническую или иную информацию о возможностях Сервиса, а также информационные материалы Владельца Сервиса.</p>
<p>5.1.11. Воспроизводить Контент на Устройствах Пользователей для осуществления целей, предусмотренных в настоящем Соглашении.</p>
<p>5.1.12. Размещать на Сервисе рекламу, в том числе совместно с Контентом и на странице Пользователя. Владелец Сервиса вправе разрешить размещение рекламы любым третьим лицам.</p>
<p>5.1.13. Предоставить данные Пользователя любой третьей стороне, которая обоснованно утверждает, что Контент Пользователя, размещенный или загруженный им на Сервис, представляет собой нарушение их прав интеллектуальной собственности или их права на неприкосновенность частной жизни, если при этом не нарушаются права Пользователя в части обработки его персональных данных.</p>
<p>5.1.14. Размещать в Контенте Пользователей или сопровождать Контент комментариями, предисловием, Материалами, водяными знаками, предупреждениями и т.д., добавлять в Контент рекламные материалы, перерабатывать Контент и создавать на его основе производные произведения в целях обеспечения Владельцем Сервиса функционирования Сервиса в объеме, определяемом функционалом и архитектурой Сервиса, и отображения Контента в промо материалах и рекламе Владельца Сервиса, выполнения требований законодательства и т.д. без выплаты Пользователю каких-либо вознаграждений, на что Пользователь дает свое согласие.</p>
<p>5.2. Владелец Сервиса обязан:</p>
<p>5.2.1. Поддерживать работоспособность Сервиса и его наполнение, осуществлять текущее управление разделами Сервиса, обеспечивать своевременное устранение ошибок работы Сервиса.</p>
<p>5.2.2. Поддерживать работоспособность на Сервисе электронной формы для направления Пользователями обращений Владельцу Сервиса о распространении информации, нарушающей действующее законодательство Российской Федерации, настоящее Соглашение, Правила teeaseer.com. Пользователь может направить указанное обращение через электронную форму, нажав на кнопку «Пожаловаться» при воспроизведении Контента на Сервисе.</p>
<p>5.2.3. Ежегодно размещать отчет о результатах мониторинга информации на Сервисе, а также рассмотрения обращений Пользователей, поданных Владельцу Сервиса с использованием электронной формы на Сервисе через кнопку «Пожаловаться», если это предусмотрено требованиям действующего законодательства Российской Федерации для Владельца Сервиса.</p>
<p>5.2.4. Информировать Пользователей об изменениях в тексте настоящего Соглашения согласно требованиям действующего законодательства Российской Федерации.</p>
<p>5.2.5. В случаях невозможности самостоятельной оценки Владельцем Сервиса степени соответствия Контента/материала, выявленного в процессе мониторинга Контента или по результатам рассмотрения обращений Пользователей через электронную форму, ограничивать доступ к Контенту/материалам и не позднее суток с момента выявления такой информации направить ее в уполномоченные государственные органы.</p>
<p>6. Финансовые условия</p>
<p>6.1. Пользователь имеет право без взимания платы загружать на Сервис Контент с помощью своей Учетной записи, а также использовать Материалы, доступные для бесплатного использования.</p>
<p>6.2. Пользователь имеет право пользоваться Платными Услугами. Пользователь вносит оплату за пользование Платными Услугами посредством платежных систем третьих лиц на условиях, которые регулируются Пользовательским соглашением между Пользователем и указанными лицами, на свой лицевой счет, привязанный к Учетной записи. Владелец Сервиса самостоятельно осуществляет расчеты с Правообладателями за использование Пользователями дополнительных Материалов в рамках Платных Услуг, списывая необходимую сумму за выбранную Пользователем Платную Услугу.</p>
<p>6.3. Стоимость Платных Услуг указана в Сервисе и может различаться для одной и той же Платной Услуги в зависимости от Устройства Пользователя, продолжительности подписки на такую Платную Услугу, страны Пользователя и иных условий.</p>
<p>6.4. Все платежи, осуществляемые Пользователями в адрес Владельца Сервиса в рамках настоящего Соглашения, включают налог на в размере, установленном действующим законодательством РФ, если применимо.</p>
<p>6.5. Все платежи, осуществляемые Пользователями в адрес Владельца Сервиса, не включают в себя стоимость Интернета или трафика данных и регулируются согласно соглашению между Пользователем и Интернет-провайдером или оператором мобильной связи.</p>
<p>6.6. При нажатии кнопки «Оплатить» Пользователь безоговорочно соглашается со стоимостью Платной Услуги на данном Устройстве и не имеет возражений против возможных различий со стоимостью приобретения аналогичных Услуг на другом Устройстве.</p>
<p>6.7. Владелец Сервиса не несет ответственности перед Пользователем в случае непоступления денежных средств на расчетный счет Владельца Сервиса по причинам, не зависящим от Владельца Сервиса, включая, но не ограничиваясь: сбои в программном обеспечении или поломку оборудования банков, операторов связи, платежных систем и иных платежных посредников, которые обеспечивают прием платежей от Пользователей и их перечисление Владельцу Сервиса.</p>
<p>6.8. Пользователь признает и соглашается, что Владелец Сервиса не обязан оказывать Платные Услуги до момента поступления денежных средств на расчетный счет Владельца Сервиса.</p>
<p>6.9. Стороны согласились, что при оказании Услуг по настоящему Соглашению счета-фактуры не составляются, согласно пп.1 п.3 ст. 169 Налогового кодекса Российской Федерации.</p>
<p>6.10. Если оплаченные зарегистрированным Пользователем Услуги не были предоставлены по вине Владельца Сервиса в течение 30 (тридцати) календарных дней с даты их оплаты по причине существенных технических неполадок на Сервисе, Владелец Сервиса на основании письменного заявления Пользователя, направленного по почтовому адресу Владельца Сервиса, указанному на Сервисе, возвращает Пользователю оплаченную им сумму. Для осуществления возврата денежных средств Пользователь вместе с заявлением должен предоставить документы, подтверждающие факт оплаты, до окончания срока пользования оплаченных Услуг.</p>
<p>7. Интеллектуальная собственность</p>
<p>7.1. Пользователь предоставляет Владельцу Сервиса простую (неисключительную) лицензию на право использования Контента с момента фактической загрузки/размещения Контента на Сервисе, в том числе, право на использование своего исполнения в полном объеме (в том числе отдельное использование звука и изображения), в целях обеспечения Владельцем Сервиса функционирования Сервиса в объеме, определяемом функционалом и архитектурой Сервиса, и отображения Контента в промо материалах и рекламе Владельца Сервиса, любыми способами, в том числе указанными в статьях 1270, 1317 Гражданского кодекса Российской Федерации, без ограничения по территории использования на срок размещения Контента на Сервисе с правом передачи любым третьим лицам, без выплаты Пользователю вознаграждения (безвозмездно). Владелец Сервиса вправе включать Контент, а равно фрагменты Контента, в состав любых промоматериалов или рекламы Владельца Сервиса, размещаемой как на Сервисе, так и по другим каналам продвижения (по выбору Владельца Сервиса). Окончание срока размещения Контента на Сервисе и/или срока действия исключительного права не влечет за собой необходимость изъятия из оборота промо материалов или рекламы Владельца Сервиса с использованным в них Контентом (в том числе их удаление из сети Интернет).</p>
<p>В случае, если Контент создан совместно несколькими Пользователями посредством функционала Сервиса, включая «коллабы», «реюзы» и/или иной производный Контент, каждый из них осознает и соглашается с тем, что размещая такой Контент на Сервисе, он разрешает другим Пользователям использование своего Контента согласно п. 4.1.3. Соглашения, а также предоставляет Владельцу Сервиса простую (неисключительную) лицензию с момента загрузки на Сервис на весь срок действия исключительного права на Контент, а равно на производный Контент, для использования всеми способами, в том числе установленными ст. 1270, 1317 Гражданского кодекса Российской Федерации, без ограничения по территории использования и без выплаты Пользователю вознаграждения (безвозмездно).</p>
<p>Владелец Сервиса не несет ответственности за возможные споры между Пользователями, которые создали совместно производный Контент посредством функционала Сервиса.</p>
<p>Удаление Учетной записи Пользователя не влечет удаления Владельцем Сервиса Контента, который вошёл в состав производного Контента (включая «коллабы», «реюзы», иной производный Контент).</p>
<p>7.2. Пользователь осознает и соглашается с тем, что, загружая Контент на Сервис, Пользователь отказывается от получения от Владельца Сервиса вознаграждения за Контент (например, вы не можете претендовать на Контент, который был загружен Владельцем Сервиса на иные платформы/сервисы для монетизации).</p>
<p>7.3. Размещая Контент на Сервисе, Пользователь дает свое согласие на обнародование его изображений, голоса, в том числе, зафиксированных в Контенте, и на дальнейшее их использование в любой форме, любым не противоречащим закону способом, в том числе, на перевод в электронную и цифровую форму, выделение (частично или полностью) звука/аудио, изображения/видеоряда из Контента Пользователя, синхронизацию с другими материалами, а также изменение, сокращение, дополнение, комментирование, редактирование, перемонтаж и иную переработку, в том числе, в целях создания профайлов, анонсирования и рекламирования, показа на любых телеканалах и доведение до всеобщего сведения, в т.ч. в сети Интернет, как Владельцем Сервиса, так и третьими лицами только по соглашениям с Владельцем Сервиса, без выплаты Пользователю вознаграждения.</p>
<p>Размещая Контент на Сервисе, Пользователь дает свое согласие Владельцу Сервиса и третьим лицам использовать Контент без указания имени или ника(псевдонима) Пользователя (анонимно).</p>
<p>7.4. Пользователь понимает и согласен с тем, что Владелец Сервиса не несет ответственности за действия Правообладателей Контента или Материалов по исполнении ими своих обязательств перед третьими лицами.</p>
<p>7.5. Все используемые и размещенные на Сервисе результаты интеллектуальной деятельности, а также сам Сервис являются интеллектуальной собственностью их законных Правообладателей и охраняются законодательством об интеллектуальной собственности Российской Федерации, а также соответствующими международными правовыми конвенциями. Загрузка на Сервис результатов интеллектуальной деятельности без разрешения Правообладателя таких результатов интеллектуальной деятельности, а также любое использование элементов визуального оформления Сервиса (товарных знаков, символики, текстов, графических изображений и других объектов) без разрешения Владельца Сервиса, если иное использование не разрешается настоящим Соглашением, является незаконным и может послужить причиной для судебного разбирательства и привлечения нарушителей к гражданско-правовой, административной и (или) уголовной ответственности в соответствии с законодательством Российской Федерации.</p>
<p>7.6. Никакой результат интеллектуальной деятельности, размещенный на Сервисе, не может быть скопирован (воспроизведен), переработан, распространен, отображен во фрейме, опубликован, скачан, передан, продан или иным способом использован целиком или по частям, без предварительного разрешения Владельца Сервиса или законного Правообладателя соответствующего результата интеллектуальной деятельности, кроме случаев, когда Владелец Сервиса или Правообладатель явным образом выразил свое согласие на свободное использование материала любым лицом.</p>
<p>7.7. Доступ к результатам интеллектуальной деятельности, размещенным на Сервисе, предоставляется Владельцем Сервиса исключительно для личного некоммерческого использования Пользователями в целях ознакомления с ними исключительно посредством Сервиса, без права на воспроизведение (в том числе копирование/загрузку в память электронных устройств) распространение, передачу, трансляцию, демонстрацию, продажу, модификацию лицензирование или использование любым образом для любых целей, а также без права на иное использование указанных результатов интеллектуальной деятельности, не указанное в настоящем Соглашении, целиком или по частям и т.п.</p>
<p>7.8. Любое использование Сервиса или результатов интеллектуальной деятельности, размещенных на нем, кроме разрешенного в Соглашении, или, в случае явно выраженного согласия Владельца Сервиса, автора или Правообладателя на такое использование, без предварительного письменного разрешения Владельца Сервиса или автора (Правообладателя) категорически запрещено.</p>
<p>7.9. Владелец Сервиса оставляет за собой право в любое время удалять с Сервиса любые результаты интеллектуальной деятельности, размещенные на нем, либо Контент, который содержит интеллектуальную собственность других лиц, без уведомления Пользователя по обоснованным заявлениям Правообладателей.</p>
<p>7.10. Применительно к защите интеллектуальных прав в связи с Контентом Владелец Сервиса выступает в роли информационного посредника (владелец информационного ресурса в сети Интернет, на котором аудиовизуальные произведения размещаются преимущественно пользователями сети Интернет, и который не выбирает получателя этой информации, не влияет на целостность такой передаваемой информации и, ввиду специфики статуса Информационного посредника, не несет ответственность за действия третьих лиц, допускающих нарушения действующего законодательства Российской Федерации), и в соответствии со ст. 1253.1 Гражданского Кодекса Российской Федерации и ст. 15.7 Федерального закона от 27.07.2006 N 149-ФЗ «Об информации, информационных технологиях и о защите информации» принимает меры по пресечению соответствующих нарушений по заявлениям Правообладателей.</p>
<p>8. Ограничение ответственности Владельца Сервиса</p>
<p>8.1. Владелец Сервиса не несет ответственности за любую информацию, размещенную Пользователем и/или третьими лицами, в том числе за Контент/материалы, сообщения и комментарии пользователей на Сервисе и на сайтах третьих лиц, к которым Пользователи получили доступ через Сервис, включая, в том числе, рекламные материалы, любые мнения или утверждения, выраженные на сайтах третьих лиц или в их материалах. Размещенные на Сервисе ссылки или руководства по скачиванию файлов и/или установке программ третьих лиц, ссылки на любой сайт, продукт, услугу, любую информацию не означают поддержку или одобрение этих действий со стороны Владельца Сервиса.</p>
<p>Если Пользователь решил покинуть Сервис и перейти на сайты третьих лиц или использовать, или установить программы третьих лиц, он делает это на свой риск, и с этого момента условия настоящего Соглашения более не распространяются на Пользователя. Владелец Сервиса не несет ответственности за услуги (товары), предлагаемые третьими лицами на Сервисе.</p>
<p>Пользователь понимает и согласен с тем, что Контент на Сервисе отображается в том виде, в котором он был представлен соответствующими Правообладателями на серверах третьих лиц. Пользователь согласен с тем, что Владелец Сервиса не несет никакой ответственности ни по каким договорам между Пользователем и третьими лицами.</p>
<p>8.2. В случае возникновения нежелательных последствий, понесенных Пользователем в результате пользования Сервисом, Владелец Сервиса обязуется рассматривать обращения Пользователей и принимать меры для устранения таких последствий в соответствии с условиями настоящего Соглашения и законодательством Российской Федерации.</p>
<p>8.3. Владелец Сервиса обеспечивает работу Сервиса, однако не несет ответственность за их бесперебойную работу, или за причинение любых убытков, которые возникли или могут возникнуть при пользовании Сервисом, в том числе и вследствие любых действий Владельца Сервиса, не имеющих прямой цели причинения вреда Пользователю.</p>
<p>8.4. Владелец Сервиса не несет ответственности за неисполнение либо ненадлежащее исполнение своих обязательств вследствие сбоев в телекоммуникационных и энергетических сетях третьих лиц, действий вредоносных программ, а также недобросовестных действий третьих лиц, направленных на несанкционированный доступ и (или) выведение из строя программных и (или) аппаратных средств Сервиса.</p>
<p>8.5. Владелец Сервиса не несет ответственности за некорректное функционирование Сервиса, сбои и перерывы в работе Сервиса, повреждение или утерю данных, содержащихся на Сервисе, если они были вызваны обстоятельствами непреодолимой силы, в том числе в случае пожаров, эпидемий, чрезвычайных погодных условий, перебоев подачи электроэнергии, распространения вирусных компьютерных программ, а также если такие обстоятельства были вызваны умышленными незаконными действиями третьих лиц.</p>
<p>8.6. Если какой-то Контент нарушает права третьих лиц или действующее законодательство Российской Федерации, то Пользователи могут обратиться в службу поддержки Владельца Сервиса посредством соответствующего функционала Сервиса, нажав кнопку «Поддержка», либо «Пожаловаться» в Сервисе.</p>
<p>Если какой-то контент нарушает авторские права, Правообладатель может оставить жалобу по электронному адресу: support@ritm.media, либо в техническую поддержку Сервиса через Telegram-чат, нажав на кнопку «Поддержка».</p>
<p>8.7. Функциональный блок «Открытые комнаты»: Владелец Сервиса предоставляет Пользователям техническую возможность создавать на Сервисе свои цифровые комнаты для целей общения, совместного творчества (далее «Открытая комната»/ «Комната»).</p>
<p>Владелец Сервиса предоставляет Пользователям возможность размещать свои сообщения, Контент/материалы, а также получать возможность доступа к сообщениям, Контенту/материалам других Пользователей на витринах Открытых комнат и внутри Комнат.</p>
<p>Пользователи подтверждают, что любая деятельность под их Учетными записями в Открытых комнатах расценивается как инициированная Пользователем самостоятельно, т.е. Владелец Сервиса не несет ответственности за размещаемую Пользователями информации, но принимает разумные меры для: а). блокировки размещенной Пользователями информации, запрещенной законодательством Российской Федерации, Правилами YAPPY, настоящим Соглашением б). блокировки Контента/материалов, которые обоснованно нарушают права Правообладателей, либо третьих лиц по соответствующим заявлениям, жалобам.</p>
<p>9. Данные Пользователей</p>
<p>9.1. Просмотр Контента других Пользователей Сервиса не требует от Пользователя предоставления каких-либо данных. Полный доступ к Сервису, его Услугам, в том числе Платным Услугам предоставляется Пользователю после регистрации, а также последующей Авторизации Пользователя на Сервисе. Регистрация, а также последующая Авторизация на Сервисе требует предоставления Пользователем номера мобильного телефона. Дальнейшее использование Сервиса может потребовать указания возраста Пользователя, а также предоставления, уникального на платформе ника (название канала) и имени Пользователя, что не является персональными данными. Сервис не требует предоставления персональных данных (таких как: ФИО полностью, адрес проживания, сведения о семейном положении, электронная почта), в связи с чем при использовании Сервиса Пользователь обязуется не вводить такие, а также иные персональные данные. Любая информация, содержащая признаки наличия в них персональных данных системой, приниматься не будет. Тем не менее, в случае если по какой-либо причине Пользователь использовал свои персональные данные, и они были приняты Сервисом, считается, что тем самым Пользователь предоставил Сервису согласие на обработку своих персональных данных (включая право осуществить их передачу третьим лицам). Сервис выполнит все требования законодательства Российской Федерации о персональных данных в связи с их обработкой.</p>
<p>9.2. Пользователь осознает и принимает, что Сервис собирает и обрабатывает информацию о ваших настройках и предпочтениях (в том числе, используя файлы cookies), а также информацию об Устройстве, с которого вы получаете доступ к Сервису.</p>
<p>Информация, которую Владелец Сервиса получает посредством такой информации, помогает предоставлять Пользователю Услуги в наиболее удобном для Пользователя виде, а также производит аутентификацию Пользователя на Сервисе, что дает возможность автоматического входа в Учетную запись при посещении Пользователем Сервиса.</p>
<p>9.3. Пользователь имеет право отключить cookie в настройках безопасности браузера. При этом соответствующие настройки необходимо применить во всех браузерах, которыми пользуется Пользователь (на компьютере и в телефоне). Отказ от использования файлов cookie или блокировка файлов cookie может привести к недоступности некоторых или всех функций и/или разделов Сервиса, а также может повлиять на возможность полноценного использования Пользователем Сервиса.</p>
<p>10. Технические требования</p>
<p>10.1. Для получения доступа к Сервису Пользователю требуется Устройство с установленной на нем операционной системой и программными приложениями для взаимодействия с глобальной сетью Интернет, сертифицированное компанией производителем Устройств в Российской Федерации.</p>
<p>10.2. Сервис рассчитан на взаимодействие только с официальным, лицензионным и не модифицированным программным обеспечением.</p>
<p>10.3. Устройство должно удовлетворять следующим требованиям:</p>
<p>а) Устройство должно быть подключено к глобальной сети Интернет на скорости не менее 1Мб/с;</p>
<p>б) Версия прошивки на Устройствах, функционирующих на операционной системе iOS, должна быть не ниже 12;</p>
<p>в) Версия прошивки на Устройствах, функционирующих на операционной системе Android, должна быть не ниже 10.</p>
<p>10.4. Пользователь соглашается с тем, что скорость доступа к Сервису и/или просмотру Контента, скорость создания или переработки Контента в глобальной сети Интернет может меняться в силу загруженности канала Пользователя трафиком от других ресурсов или по иным, не зависящим от Владельца Сервиса причинам. Владелец Сервиса не несет ответственности за то, что в конкретное время, в конкретном месте Пользователь не смог получить доступ к Сервису и/или просмотру Контента по причине низкой скорости доступа.</p>
<p>10.5. Пользователь соглашается с тем, что если Устройство Пользователя не соответствует техническим требованиям Владельца Сервиса, то он не сможет получить доступ к Сервису и/или Сервис может работать не корректно, даже в случае оплаты Платных Услуг.</p>
<p>10.6. Пользователь обязан следовать указанному Сервисом алгоритму для установки и обновления, использовать, а также выбирать на свое усмотрение и использовать антивирусные программы для защиты Устройств при использовании Сервиса. Сервис не несет ответственности за возможные вирусы или сбои, а также вредоносный контент, доступ к которому Пользователь получил на Сервисе.</p>
<p>11. Заключительные положения</p>
<p>11.1. Настоящее Соглашение регулируется и толкуется в соответствии с законодательством Российской Федерации.</p>
<p>11.2. Если по тем или иным причинам одно или несколько положений настоящего Соглашения является недействительным или не имеющим юридической силы, это не оказывает влияния на действительность или применимость остальных положений Соглашения.</p>
<p>12. Порядок рассмотрения обращений Пользователей</p>
<p>12.1. По всем вопросам и претензиям Пользователи и/или Правообладатели могут обращаться по электронному адресу teeaseer@bk.ru, либо в техническую поддержку Сервиса через Telegram-чат. Обращение Пользователя будет рассмотрено Владельцем Сервиса и предоставлен ответ в срок, не превышающий 30 (Тридцати) календарных дней со дня поступления соответствующего обращения, за исключением сроков, установленных в п. 4.1.7. настоящего Соглашения.</p>
<p>12.2. Для направления юридически значимых сообщений нужно использовать электронную почту teeaseer@bk.ru</p>
<p>Дата публикации: 01.05.2023</p>
</body>
</html>

View File

@@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Условия конфиденциальности - 4teaser</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="//fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
@php
$manifest = json_decode(file_get_contents(public_path('dist/manifest.json')), true);
@endphp
<link rel="stylesheet" href="/dist/{{ $manifest['resources/js/app.js']['css'][0] }}">
<style>
table {
border: 1px solid #dee2e6;
}
table {
width: 100%;
margin-bottom: 1rem;
color: #212529;
}
table {
border-collapse: collapse;
}
table thead td, table thead th {
border-bottom-width: 2px;
}
table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
}
table td, table th {
border: 1px solid #dee2e6;
}
table td, table th {
padding: 0.75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
ol{
list-style-type: decimal;
}
ul{
list-style-type: disc;
}
ol,ul{
list-style-position: inside;
}
ol li + li, ul li + li {
margin-top: .5em;
}
li ol, li ul{
margin-top: 1em;
margin-left: 2em;
}
</style>
</head>
<body class="container mx-auto space-y-3 p-10">
<h1 style="text-align: center;"><strong>ПОЛИТИКА КОНФИДЕНЦИАЛЬНОСТИ В ОТНОШЕНИИ ПОЛЬЗОВАТЕЛЕЙ ИЗ СТРАН, НЕ ВХОДЯЩИХ В ЕС</strong></h1>
<ol>
<li>О компании</li>
<li>Мы ИП Изместьев Филипп Евгеньевич (ОГРНИП 322246800057489, ИНН 246213118344) </li>
<li>Настоящая Политика конфиденциальности устанавливает процедуру сбора и использования вашей персональной информации при использовании нашего сайта<a href="https://4teaser.com">https://4teaser.com</a>(далее «Сайт») или использовании нашего онлайн-сервиса Тизер (далее «Услуги Тизер»), предлагаемого компанией Синтез-К. по адресу https://4teaser.com, а также предоставляемый вам выбор в связи с использованием нами вашей персональной информации (далее «Политика конфиденциальности»).
Сайт и Сервис Тизер в дальнейшем совместно именуются «Платформа Тизер».
Настоящую Политику конфиденциальности следует рассматривать вместе с нашими условиями, доступными по адресу: <a href="https://4teaser.com/app/offer/user">https://4teaser.com/app/offer/user</a> (далее «Условия»), и нашей Политикой в отношении файлов cookie (доступной в сети Интернет по адресу: <a href="https://4teaser.com/offer/cookie">https://4teaser.com/offer/cookie</a> ).
В случае возникновения каких-либо противоречий между настоящей Политикой конфиденциальности и Условиями, преимущественную силу будет иметь настоящая Политика конфиденциальности.</li>
<li>О настоящей Политике конфиденциальности
<ol>
<li>Предоставляя Платформу Тизер и действуя разумно и добросовестно, мы считаем, что вы:
(a) имеете все необходимые права для регистрации на и использования Платформы Тизер;
(b) предоставляете правдивую информацию о себе в объеме, необходимом для использования Платформы Тизер;
(c) понимаете, что, публикуя вашу персональную информацию, вы в явной форме делаете такую информацию общедоступной, и данная информация может стать доступной для других пользователей Платформы Тизер и пользователей сети Интернет, а также копироваться и распространяться ими;
(d) понимаете, что некоторые виды информации, передаваемой вами другим пользователям Платформы Тизер, не могут быть удалены вами или нами;
(e) осведомлены о настоящей Политике конфиденциальности и принимаете настоящую Политику конфиденциальности.</li>
<li>Мы не проверяем полученную от вас пользовательскую информацию за исключением случаев, когда такая проверка необходима для того, чтобы мы могли выполнить свои обязательства перед вами.</li>
</ol>
</li>
<li>Информация, которую мы собираем о вас
<ol>
<li>В целях реализации соглашения между вами и нами и предоставления вам доступа к использованию Платформы Тизер, мы будем совершенствовать, разрабатывать и внедрять новые функции для нашей Платформы Тизер, а также расширять доступный функционал Платформы Тизер. Для достижения этих целей и в соответствии с применимым законодательством мы будем собирать, хранить, накапливать, систематизировать, извлекать, сравнивать, использовать и дополнять ваши данные. Мы также будем получать и передавать эти данные и результат автоматической обработки нами этих данных нашим аффилированным лицам и партнерам, как указано в таблице ниже и в пункте 4 настоящей Политики конфиденциальности.</li>
<li>Ниже мы более подробно опишем информацию, которую мы можем собирать при использовании Платформы Тизер, то, почему мы собираем и обрабатываем ее, а также юридические основания для этого.</li>
</ol>
</li>
</ol>
<table>
<thead>
<tr>
<td></td>
<td ><strong>Собираемая информация</strong></td>
<td ><strong>Цель</strong></td>
<td><strong>Юридическое основание</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Данные, предоставляемые вами при регистрации в Платформе Тизер: данные, полученные от третьих лиц в случае входа через сторонние социальные сети или службы аутентификации (такие как, среди прочих, Facebook, Google, YouTube), включая ваше имя пользователя социальной сети и адрес электронной почты, ваше имя пользователя, созданное вами в процессе регистрации</td>
<td>Мы используем эту информацию для контроля и администрирования предоставляемой вам Платформы Тизер. Мы используем эти данные, чтобы мы могли выполнять свои обязательства перед вами в рамках Платформы Тизер (например, в случаях, когда вы запрашиваете восстановление своей учетной записи). См. пункт 8.3 настоящей Политики конфиденциальности для получения дополнительной информации.</td>
<td>Законные интересы
Исполнение нашего договора с вами</td>
</tr>
<tr>
<td>2</td>
<td>Дополнительные данные, предоставляемые вами при редактировании вашей страницы пользователя на https://4teaser.com или специальной странице сервиса путем добавления вашего имени, фамилии, номера мобильного телефона, адреса электронной почты, имени пользователя, страны.</td>
<td>Мы используем эту информацию для предоставления вам нашей Платформы Тизер, управления Платформой Тизер и ее администрирования, а также в качестве дополнительной информации для проверки вашей учетной записи для предотвращения злоупотреблений и ущемления ваших прав или прав других лиц.
Мы также используем эту информацию для предоставления вам обновлений и информации о наших продуктах и выбранных продуктах третьих лиц и о Платформе Тизер, которые, по нашему мнению, могут вас заинтересовать.</td>
<td>Законные интересы
Исполнение нашего договора с вами</td>
</tr>
<tr>
<td>3</td>
<td>Дополнительные данные, полученные при получении вами доступа к Платформе Тизер, включая информацию в отношении технического взаимодействия с Платформой Тизер, такую как ваш IP-адрес, время регистрации в Платформе Тизер, время вашего последнего посещения Платформы Тизер, идентификаторы устройства, настройки страны и языка.</td>
<td>Мы используем ваши данные для внутреннего контроля, чтобы постоянно улучшать содержание Платформы Тизер и веб-страниц, оптимизировать удобство пользования, понимать любые ошибки, с которыми вы можете столкнуться при использовании Платформы Тизер, уведомлять вас об изменениях в Платформе Тизер и персонализировать использование нашей Платформы Тизер.</td>
<td>Законные интересы</td>
</tr>
<tr>
<td>4</td>
<td>Информация, которая автоматически поступает в момент доступа к Платформе Тизер с использованием файлов cookie.</td>
<td>Ознакомьтесь с нашей политикой в отношении файлов cookie, в которой указаны используемые нами типы файлов cookie и для чего мы их используем.</td>
<td>Согласие</td>
</tr>
<tr>
<td>5</td>
<td>Информация, созданная вами при использовании Платформы Тизер (включая Пользовательский контент). Эта информация может быть доступна всем зрителям Контента Автора, у которого размещен Пользовательский контент.</td>
<td>Мы используем эту информацию для контроля и администрирования Платформы Тизер, включая предоставление вам Платформы Тизер.</td>
<td>Законные интересы</td>
</tr>
<tr>
<td>6</td>
<td>Информация, созданная вами при размещении запросов в нашу Службу поддержки.</td>
<td>Мы используем эту информацию для подтверждения вашей личности и выполнения вашего запроса в службу поддержки.
Мы также можем использовать эти данные для расследования любых жалоб, поступивших от вашего имени, и повышения эффективности вашего обслуживания.</td>
<td>Законные интересы
Исполнение нашего договора с вами</td>
</tr>
<tr>
<td>7</td>
<td>Информация, полученная в результате использования вами функций оплаты на Сайте (например, первые и последние четыре цифры номера вашей карты, необходимые для опции сопоставления этих данных с идентификационным номером пользователя).</td>
<td>Мы используем эту информацию для контроля и администрирования Сайта, включая предоставление вам наших Сервисов Сайта.
Мы также можем использовать эти данные для расследования любых жалоб, поступивших от вашего имени, и повышения эффективности вашего обслуживания.</td>
<td>Законные интересы
Исполнение нашего договора с вами</td>
</tr>
<tr>
<td>8</td>
<td>Данные, собранные через третьих лиц, если вы решите предоставить такие данные через сторонние социальные сети или службы аутентификации (такие как, помимо прочих, Facebook, Google, YouTube), когда вы входите с использованием таких социальных сетей и/или служб или привязываете такие социальные сети и/или службы к нашей Платформе Тизер, включая идентификатор вашей социальной сети (такой как Google ID), идентификатор магазина приложений, имя пользователя, адрес электронной почты и список друзей, список подписчиков, список трансляций, название канала, описание канала, URL канала, аватар или изображение профиля, ключ трансляции.</td>
<td>Мы используем эту информацию для контроля и администрирования предоставляемой вам Платформы Тизер.</td>
<td>Законные интересы
Исполнение нашего договора с вами</td>
</tr>
</tbody>
</table>
<ol start="4">
<li>Наши законные интересы включают: (1) поддержание и администрирование Платформы Тизер; (2) предоставление вам Платформы Тизер; (3) улучшение контента Платформы Тизер и веб-страниц; (4) обработку данных, которые были явно опубликованы вами; (5) обеспечение надлежащей защиты вашей учетной записи; и (6) соблюдение любых договорных, правовых или нормативных обязательств в соответствии с любым применимым законодательством.</li>
<li>Ваша персональная информация также может быть обработана, если это требуется правоохранительным или регулирующим органом или учреждением, или для защиты от судебных исков или подачи судебных исков.
Мы не будем удалять персональную информацию, если она имеет отношение к расследованию или спору. Она будет храниться до тех пор, пока эти вопросы не будут полностью решены и/или в течение срока, который требуется и/или допустим согласно применимому/соответствующему законодательству.</li>
<li>Вы можете отозвать свое согласие на отправку вам маркетинговой информации, изменив настройки конфиденциальности своей учетной записи. Возможность отказаться от подписки также будет включена в каждое электронное письмо, отправленное вам нами или нашими выбранными сторонними партнерами.</li>
<li>Обратите внимание: если вы не хотите, чтобы мы обрабатывали конфиденциальные и специальные категории данных о вас (включая данные, касающиеся вашего здоровья, расового или этнического происхождения, политических убеждений, религиозных или философских убеждений, половой жизни и вашей сексуальной ориентации), вам не следует размещать эту информацию или передавать эти данные на Платформе Тизер.
После предоставления вами этих данных они станут доступными пользователям веб-сайтов (включая мобильные версии), где размещены эти данные, и нам станет трудно удалить эти данные.</li>
<li>Обратите внимание, что, если вы отзываете свое согласие на обработку или не предоставляете данные, которые нам требуются для обслуживания и администрирования Платформы Тизер, вы не сможете получить доступ к Платформе Тизер и пользоваться ей.</li>
<li>Если мы намереваемся обрабатывать ваши данные в каких-либо иных целях, помимо тех, которые указаны в настоящей Политике конфиденциальности, мы предоставим вам подробную информацию об этой дополнительной цели до того, как мы начнем обработку.</li>
</ol>
<ol start="3">
<li>Обмен данными
<ol>
<li>Ваше имя пользователя может быть доступно всем зрителям вашего Контента Автора в сети Интернет при использовании вами Платформы Тизер. Мы принимаем технические и организационные меры для обеспечения безопасности ваших данных. Примите к сведению, что, публикуя вашу персональную информацию, вы явно сделали эту информацию общедоступной, и эта информация может стать доступной для других пользователей Сервиса и пользователей сети Интернет, и копироваться и/или распространяться такими пользователями. Как только вы передадите эти данные другим пользователям, вы не сможете их удалить.</li>
<li>Мы можем делиться вашими данными с нашими аффилированными лицами. Иногда нам также может потребоваться предоставить ваши данные третьему лицу для предоставления вам Платформы Тизер или для управления Платформой Тизер, например, если вы решите поделиться своими данными с другими социальными сетями.</li>
</ol>
</li>
<li>Настройки конфиденциальности
<ol>
<li>Платформа Тизер может содержать ссылки на сайты, управляемые третьими лицами. Мы не несем ответственности за конфиденциальность ваших данных, когда вы получаете доступ к этим ссылкам или взаимодействуете со сторонними Платформами Тизер, и вам следует убедиться, что вы ознакомились с соответствующим заявлением о конфиденциальности третьего лица, которое будет регулировать ваши права в области защиты данных.</li>
<li>Если вы собираетесь привязать вашу учетную запись YouTube или Google к Платформе Тизер с использованием сервисов YouTube API, вы можете проверить и, при необходимости, изменить ваши настройки конфиденциальности YouTube на странице настроек безопасности Google по адресу https://security.google.com/settings/security/permissions до подключения или привязывания их к нашему сайту или Сервису. Дополнительную информацию о конфиденциальности YouTube и Google можно найти по адресу https://policies.google.com/, а Политику конфиденциальности Google по адресу http://www.google.com/policies/privacy.</li>
<li>Мы не несем ответственности за действия третьих лиц, которые в результате использования вами сети Интернет или Платформы Тизер получают доступ к вашей информации в соответствии с выбранным вами уровнем конфиденциальности.</li>
<li>Мы не несем ответственности за последствия использования информации, которая в силу характера Платформы Тизер доступна любому пользователю сети Интернет. Мы просим вас ответственно подходить к выбору вашей информации, размещаемой в Платформе Тизер.</li>
</ol>
</li>
<li>Передача информации между странами
<ol>
<li>Мы можем передавать и хранить на наших серверах или в базах данных некоторую вашу персональную информацию в разных странах мира.</li>
</ol>
</li>
<li>Периоды хранения
<ol>
<li>Мы будем хранить вашу персональную информацию в течение всего времени, необходимого для достижения целей, для которых эти данные были собраны, в зависимости от юридического основания, на котором эти данные были получены, и/или от того, требуют ли дополнительные правовые/нормативные обязательства сохранения вашей персональной информации в течение срока, который обязателен и/или допустим согласно применимому/соответствующему законодательству.</li>
<li>Вы можете удалить свои персональные данные, удалив данные из вашей учетной записи или прислав нам электронное письмо по адресу support@4teaser.com.</li>
<li>Мы можем удалить вашу учетную запись или информацию, которую вы публикуете, в соответствии с Условиями.</li>
</ol>
</li>
<li>Ваши права
<ol>
<li>При определенных обстоятельствах вы имеете следующие права в отношении вашей персональной информации:
(a) Право доступа к вашей персональной информации.
(b) Право на исправление вашей персональной информации: вы можете потребовать, чтобы мы обновили, заблокировали или удалили ваши персональные данные, если данные являются неполными, устаревшими, неправильными, незаконно полученными или больше не имеют отношения к цели обработки.
(c) Право ограничивать использование вашей персональной информации.
(d) Право требовать, чтобы ваша персональная информация была стерта, если:
<ul>
<li>ее обработка больше не требуется в связи с целями, для которых она был собрана или обработана другим способом;</li>
<li>вы отзываете свое согласие относительно обработки при условии согласия;</li>
<li>вы обоснованно выступаете против обработки;</li>
<li>такая информация была обработана незаконно; или</li>
<li>это обязательно согласно законодательству.</li>
</ul>
</li>
</ol>
</li>
</ol>
(e) Право на возражение против обработки вашей персональной информации.
(f) Право на переносимость данных (при определенных обстоятельствах).
(g) Право не являться предметом автоматизированного решения.
(h) Право на подачу жалобы в надзорный орган.
(i) Для обработки, основанной на вашем согласии - право отозвать это согласие в любое время.
(j) Вы можете иметь другие права в соответствии с законодательством вашей страны проживания, включая право определять инструкции, касающиеся результатов обработки ваших персональных данных после вашей смерти.
<ol start="2">
<li>Вы также имеете право самостоятельно удалять персональную информацию из вашей учетной записи и вносить изменения и исправления в вашу информацию, при условии, что такие изменения и исправления содержат актуальную и достоверную информацию. Вы также можете просмотреть обзор информации о вас, которую мы храним.</li>
<li>При желании воспользоваться данными правами, пожалуйста, свяжитесь со Службой поддержки по адресу support@teaser.com или направьте нам свой письменный запрос по адресу: 660049, Красноярский край, г.Красноярск, ул. Карла Маркса, д. 44А, помещение. 12. Мы постараемся ответить вам в течение срока, установленного действующим законодательством. Нам потребуется подтвердить вашу личность, прежде чем мы сможем раскрыть вам любые персональные данные.</li>
<li>В случае предоставления вами доступа Платформе Тизер к вашей учетной записи YouTube (например, в случае регистрации в Платформе Тизер через учетную запись социальной сети YouTube) вы можете отменить такой доступ Платформе Тизер к вашей учетной записи YouTube через страницу настроек безопасности Google по адресу <a href="https://security.google.com/settings/security/permissions">https://security.google.com/settings/security/permissions</a>.</li>
</ol>
<ol start="8">
<li>Меры безопасности
<ol>
<li>Мы принимаем технические, организационные и юридические меры, включая, где это возможно, шифрование, чтобы обеспечить защиту ваших персональных данных от несанкционированного или случайного доступа, удаления, изменения, блокировки, копирования и распространения.</li>
<li>Доступ к Платформе Тизер авторизуется при использовании соответствующей социальной сетью вашего логина (адреса электронной почты или номера мобильного телефона) и пароля. Вы несете ответственность за сохранение конфиденциальности этой информации. Вы не должны передавать свои учетные данные третьим лицам, и мы рекомендуем вам принять меры для обеспечения конфиденциальности этой информации.</li>
</ol>
</li>
<li>Внесение изменений в настоящую Политику
<ol>
<li>В любой соответствующий момент времени мы можем изменять и/или обновлять настоящую Политику конфиденциальности. Если настоящая Политика конфиденциальности изменится, мы опубликуем обновленную версию на этой странице. Мы будем хранить предыдущие версии настоящей Политики конфиденциальности в нашем архиве документации. Мы рекомендуем вам регулярно просматривать эту страницу, чтобы всегда быть в курсе нашей практики обращения с информацией и любых изменений в ней.</li>
</ol>
</li>
<li>Связаться с нами
<ol>
<li>В случае возникновения любых вопросов вы можете отправить обращение в Службу поддержки по адресу: support@4teaser.com или письменный запрос по адресу: 660049, Красноярский край, г.Красноярск, ул. Карла Маркса, д. 44А, помещение. 12.. Пожалуйста, ссылайтесь на настоящую Политику конфиденциальности, чтобы мы смогли эффективно обработать ваш запрос. Мы постараемся ответить вам в течение срока, установленного действующим законодательством.</li>
<li>Вся полученная нами от вас корреспонденция (письменные или электронные запросы) классифицируется как информация с ограниченным доступом, и она не может быть разглашена без вашего письменного согласия. Персональные данные и другая информация о вас не могут быть использованы без вашего согласия для каких-либо целей, кроме как для ответа на запрос, за исключением случаев, прямо предусмотренных законом.</li>
</ol>
</li>
</ol>
</body>
</html>

View File

@@ -0,0 +1,442 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Условия оплаты - 4teaser</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="//fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
@php
$manifest = json_decode(file_get_contents(public_path('dist/manifest.json')), true);
@endphp
<link rel="stylesheet" href="/dist/{{ $manifest['resources/js/app.js']['css'][0] }}">
<style>
table {
border: 1px solid #dee2e6;
}
table {
width: 100%;
margin-bottom: 1rem;
color: #212529;
}
table {
border-collapse: collapse;
}
table thead td, table thead th {
border-bottom-width: 2px;
}
table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
}
table td, table th {
border: 1px solid #dee2e6;
}
table td, table th {
padding: 0.75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
ol{
list-style-type: decimal;
}
ul{
list-style-type: disc;
}
ol,ul{
list-style-position: inside;
}
ol li + li, ul li + li {
margin-top: .5em;
}
li ol, li ul{
margin-top: 1em;
margin-left: 2em;
}
.mlml2{
margin-left: 2em;
}
</style>
</head>
<body class="container mx-auto space-y-3 p-10">
<h1 class="text-center"><strong>УСЛОВИЯ ОПЛАТЫ</strong></h1>
<p>Все термины с заглавной буквы имеют значение, указанное в <u>Условиях Предоставления Услуг</u>, если иное прямо не указано в настоящем документе.</p>
<ol>
<li><strong>ОБЩИЕ УСЛОВИЯ</strong>
<ol>
<li>Компания будет собирать Вознаграждение Автора и/или Донаты от Пользователей и перечислять их Авторам после вычета суммы Агентского Вознаграждения (как указано в Таблице 1). Компания будет предпринимать действия для осуществления таких переводов на ежедневной основе, но не может гарантировать это. Автор обязан выбрать валюту и платежный способ из доступных на Платформе Тизер вариантов, который будет впоследствии использоваться в качестве валюты по умолчанию (<strong>«Основная валюта»</strong>) и платежного метода по умолчанию («<strong>Основной платежный метод</strong>») для получения Вознаграждения Автора и/или Донатов. Когда Автор выбирает платежный способ, он/она должен предоставить Компании действительную информацию, запрашиваемую на Платформе Тизер или запрашиваемую Компанией. В случае, если Вознаграждение Автора и/или Донаты получены в валюте, отличной от Основной валюты, они будут сконвертированы, отражены и выплачены Автору в Основной валюте по курсу Центрального Банка Российской Федерации на день его получения Компанией.</li>
<li>Если Автор выбирает платежный метод, который не позволяет получить полную сумму Вознаграждения Автора и/или Донатов из-за ограничений, установленных применимым поставщиком платежных услуг, тогда Автор должен выбрать дополнительный или альтернативный способ оплаты, если такая возможность предоставлена Платформой Тизер, или Компания имеет право перечислять Вознаграждение Автора и/или Донаты, причитающиеся к выплате Автору, на ежедневной основе до тех пор, пока не будет выплачена полная сумма Вознаграждения Автора и/или Донатов. Если Автор выбирает платежный метод, который не позволяет получать Вознаграждение Автора и/или Донаты в Основной валюте из-за ограничений применимого платежного провайдера, тогда Вознаграждение Автора и/или Донаты будут перечислены в разрешенной провайдером валюте по курсу Центрального Банка Российской Федерации (<u><a href="http://www.cbr.ru/">http://www.cbr.ru/</a></u>) на день перечисления Вознаграждения Автора и/или Донатов Компанией.</li>
<li>Компания настоящим информирует Пользователей и Авторов, что перечисление Донатов не является фактом оплаты каких-либо услуг Авторов. Донаты и Вознаграждение Автора являются добровольными платежами, Пользователи самостоятельно определяют их размер в пределах, доступных в интерфейсах Платформы Тизер. Вознаграждение Автора или Донаты не могут быть возвращены Пользователю после перечисления Автору. Пользователь вправе обратиться с жалобой на факт перечисления Донатов или Вознаграждения Автора, при этом Компания оставляет за собой право автоматически отказать Пользователю в жалобе, если такая жалоба была подана по истечении календарных суток, в течение которых был совершен платеж. В ином случае Компания оставляет за собой право руководствоваться п.1.4 настоящих Условий оплаты.</li>
<li>Компания вправе отложить на необходимый срок (но в любом случае не более чем на 90 дней) и/или отменить любой сбор Вознаграждения Автора и/или Донатов от Пользователя и/или последующее их перечисление Автору с целью предотвращения незаконной деятельности или мошеннических действий, оценки рисков, безопасности или расследования. В том случае, если Вознаграждение Автора и/или Донаты превышают максимальный размер, установленный Условиями использования, Компания отложит выплату такого Вознаграждения Автора и/или Донатов на срок не менее 5 (пяти) рабочих дней с целью, указанной выше.</li>
<li>Компания вправе вычитать или удерживать любые налоги, в отношении которых у Компании существует обусловленная законом обязанность по вычету или удержанию, из любых сумм, подлежащих оплате Автору по Агентскому Договору. Время от времени Компания может запрашивать у вас налоговую информацию, и вы должны предоставить ее Компании.</li>
<li>Начиная с первого календарного дня, следующего за днем присвоения Автору Статуса Неактивного Автора, стоимость услуг по поддержанию Учетной записи на Платформе Тизер составляет 10 (десять) рублей 00 копеек РФ за 1 (один) календарный день. В случае, если Основной валютой являются не рубли, то указанная выше сумма будет составлять 0 Евро 13 центов, если Основная валюта Евро, и 0 долларов США 15 центов, если Основная валюта доллары США.</li>
<li><strong>«Статус Неактивного Автора»</strong>- статус Автора, устанавливаемый Компанией, в случае если Автор в течение более чем трех календарных месяцев либо не использовал его/ее Учетную Запись, либо не выбрал платежный способ, который используется по умолчанию Компанией для перечисления денежных средств Автору.</li>
<li>Соглашение автоматически расторгается в случае если Автору присвоен Статус Неактивного Автора, и сумма Вознаграждения Автора и/или Донатов, подлежащая уплате Автору, равна нулю.</li>
</ol>
</li>
<li><strong>ОБЩЕЕ АГЕНТСКОЕ ВОЗНАГРАЖДЕНИЕ</strong>
<ol>
<li>Раздел 2 применяется только к Вознаграждению Автора и Донатам, перечисляемым вне VK Donut, OK Donations и MY.GAMES Boost, как описано в Условиях Предоставления Услуг.</li>
<li>Сумма Агентского Вознаграждения за услуги должна рассчитывается в зависимости от платежного способа, который был использован Пользователем для перечисления Вознаграждения Автора и/или Донатов, и суммы Вознаграждения Автора и/или Донатов в соответствии с Таблицей 1:</li>
</ol>
</li>
</ol>
<p>Таблица 1</p>
<table>
<tbody>
<tr>
<td rowspan="2">Платежный способ</td>
<td colspan="2">Агентское Вознаграждение для пользователей, зарегистрировавшихся как Авторы на Платформе Тизер</td>
</tr>
<tr>
<td>до 02 февраля 2022 г.</td>
<td>c 03 февраля 2022 г.</td>
</tr>
<tr>
<td>Банковские карты</td>
<td>7%</td>
<td>10%</td>
</tr>
<tr>
<td>QIWI Wallet</td>
<td>7%</td>
<td>10%</td>
</tr>
<tr>
<td>PayPal</td>
<td>7%</td>
<td>10%</td>
</tr>
<tr>
<td>ЮMoney</td>
<td>7%</td>
<td>10%</td>
</tr>
<tr>
<td>Apple Pay</td>
<td>7%</td>
<td>10%</td>
</tr>
</tbody>
</table>
<ol start="3" class="mlml2">
<li></li>
<li>Автор вправе выбрать следующие доступные платежные способы для получения Вознаграждения Автора и/или Донатов в соответствии с настоящими Условиями Оплаты при условии, что обязательство компании по перечислению Вознаграждения Автора и/или Донатов считается исполненным с момента зачисления средств на соответствующий счет платежной системы Автора. С Автора взимается комиссия за перевод Вознаграждения Автора и/или Донатов, как указано в Таблице 2 ниже.</li>
</ol>
<p>Таблица 2</p>
<table>
<tbody>
<tr>
<td>Платежный метод</td>
<td>Комиссия от суммы Вознаграждения Автора и/или Донатов</td>
</tr>
<tr>
<td>QIWI Wallet</td>
<td>2%</td>
</tr>
<tr>
<td>WebMoney (WMR, WMZ, WME)</td>
<td>1,5%</td>
</tr>
<tr>
<td>Банковские карты *</td>
<td>2,3% + 25 рублей</td>
</tr>
<tr>
<td>Банковские карты (бета)**</td>
<td>1,7%</td>
</tr>
<tr>
<td>Банковские карты (USD/EUR)***</td>
<td>1 USD/EUR</td>
</tr>
<tr>
<td>Банковские карты Украины (Рубли)****</td>
<td>1 USD</td>
</tr>
<tr>
<td>PayPal</td>
<td>2,5%</td>
</tr>
<tr>
<td>ЮMoney</td>
<td>2,7%</td>
</tr>
<tr>
<td>VK Pay</td>
<td>0%</td>
</tr>
</tbody>
</table>
<p>*Ограничения для банковских карт:</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 60000 рублей. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 600 000 рублей.</li>
</ul>
<p>**Ограничения для банковских карт (бета):</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 100000 рублей. Комиссия за единоразовый перевод на банковскую карту Вознаграждения Автора и/или Донатов не может быть меньше 30 рублей. Совокупное количество переводов на банковские карты не может превышать 50 штук. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 1 500 000 рублей.</li>
</ul>
<p>***Ограничения для банковских карт (USD/EUR).</p>
<p>В процессе перевода сумма Вознаграждения Автора и/или Донатов будет конвертирована в USD/EUR. Курс конвертации определяется соответствующим платежным партнером. Сумма единоразового перевода на банковские карты не может быть меньше 10 USD и не может превышать 2 000 USD/EUR.</p>
<ul>
<li>Перевод на банковскую карту Visa.
<ul>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 50000 USD/EUR в день, а совокупное количество переводов не может превышать 30 штук в день.</li>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 100000 USD/EUR в неделю, а совокупное количество переводов не может превышать 50 штук в неделю.</li>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 200000 USD/EUR в месяц, а совокупное количество переводов не может превышать 150 штук в месяц.</li>
</ul>
</li>
<li>Перевод на банковскую карту MasterCard.
<ul>
<li>Совокупная сумма Вознаграждения Автора и/или Донатов не может превышать 50000 USD/EUR в месяц.</li>
</ul>
</li>
</ul>
<p>****Ограничения для банковских Украины (Рубли).</p>
<p>В процессе перевода сумма Вознаграждения Автора и/или Донатов будет конвертирована в USD. Курс конвертации определяется соответствующим платежным партнером. Сумма единоразового перевода на банковские карты не может быть меньше 800 рублей и не может превышать 13 500 рублей.</p>
<ul>
<li>Перевод на банковскую карту Visa.
<ul>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 50000 USD в день, а совокупное количество переводов не может превышать 30 штук в день.</li>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 100000 USD в неделю, а совокупное количество переводов не может превышать 50 штук в неделю.</li>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 200000 USD в месяц, а совокупное количество переводов не может превышать 150 штук в месяц.</li>
</ul>
</li>
<li>Перевод на банковскую карту MasterCard.
<ul>
<li>Совокупная сумма Вознаграждения Автора и/или Донатов не может превышать 50000 USD в месяц.</li>
</ul>
</li>
</ul>
&nbsp;
<ol start="3">
<li><strong>АГЕНТСКОЕ ВОЗНАГРАЖДЕНИЕ ДЛЯ VK DONUT</strong>
<ol>
<li>Раздел 3 применяется только к Вознаграждению Автора и Донатам, перечисляемым с использованием VK Donut, как описано в Условиях Предоставления Услуг, и процент Агентского вознаграждения включает в себя расходы Компании, понесенные при выполнении и поддержке интеграции определенных Услуг Тизер для каждого из Пользователей и Авторов в VK Donut.
<li>В случае если перечисление Вознаграждения Автора было произведено либо (i) по истечении первых шести (6) последовательных месяцев с даты регистрации такого Автора в VK Donut, и такой Автор был зарегистрирован на Платформе Тизер через VK Donut до 31 декабря 2020 года; либо (ii) в пользу Автора, зарегистрированного на Платформе Тизер через VK Donut после 31 декабря 2020 года, сумма Агентского вознаграждения рассчитывается в зависимости от способа оплаты, который был использован Пользователем для перечисления Вознаграждения Автора и/или Донатов, и суммы Вознаграждения Автора и/или Донатов в соответствии с Таблицей 3: </li>
</ol>
</li>
</ol>
<p>Таблица 3</p>
<table>
<tbody>
<tr>
<td>Платежный способ</td>
<td>Агентское Вознаграждение</td>
</tr>
<tr>
<td>Банковские карты</td>
<td>10%</td>
</tr>
<tr>
<td>VK Pay</td>
<td>10%</td>
</tr>
</tbody>
</table>
<ol start="3" class="mlml2">
<li></li>
<li>Автор, использующий VK Donut, вправе выбрать следующие доступные платежные способы для получения Вознаграждения Автора и/или Донатов в соответствии с настоящими Условиями Оплаты при условии, что обязательство компании по перечислению Вознаграждения Автора и/или Донатов считается исполненным с момента зачисления средств на соответствующий счет платежной системы Автора. С Автора взимается комиссия за перевод Вознаграждения Автора и/или Донатов, как указано в Таблице 4 ниже</li>
</ol>
<p>Таблица 4</p>
<table>
<tbody>
<tr>
<td>Платежный метод</td>
<td>Комиссия от суммы Вознаграждения Автора и/или Донатов</td>
</tr>
<tr>
<td>Банковские карты*</td>
<td>2,3% + 25 рублей</td>
</tr>
<tr>
<td>Банковские карты (бета)**</td>
<td>1,7%</td>
</tr>
<tr>
<td>Банковские карты Украины (Рубли)***</td>
<td>1 USD</td>
</tr>
<tr>
<td>VK Pay</td>
<td>0%</td>
</tr>
</tbody>
</table>
<ol start="5" class="mlml2">
<p>*Ограничения для банковских карт:</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 60000 рублей. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 600 000 рублей.</li>
</ul>
<p>**Ограничения для банковских карт (бета):</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 100000 рублей. Комиссия за единоразовый перевод на банковскую карту Вознаграждения Автора и/или Донатов не может быть меньше 30 рублей. Совокупное количество переводов на банковские карты не может превышать 50 штук. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 1 500 000 рублей.</li>
</ul>
<p>***Ограничения для банковских Украины (Рубли).</p>
<p> В процессе перевода сумма Вознаграждения Автора и/или Донатов будет конвертирована в USD. Курс конвертации определяется соответствующим платежным партнером. Сумма единоразового перевода на банковские карты не может быть меньше 800 рублей и не может превышать 13 500 рублей.</p>
<ul>
<li>Перевод на банковскую карту Visa.
<ul>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 50000 USD в день, а совокупное количество переводов не может превышать 30 штук в день.</li>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 100000 USD в неделю, а совокупное количество переводов не может превышать 50 штук в неделю.</li>
<li>Совокупная сумма переведённых Вознаграждения Автора и/или Донатов не может превышать 200000 USD в месяц, а совокупное количество переводов не может превышать 150 штук в месяц.</li>
</ul>
</li>
<li>Перевод на банковскую карту MasterCard.
<ul>
<li>Совокупная сумма Вознаграждения Автора и/или Донатов не может превышать 50000 USD в месяц.</li>
</ul>
</li>
</ul>
&nbsp;
<ol start="4">
<li><strong>АГЕНТСКОЕ ВОЗНАГРАЖДЕНИЕ ДЛЯ OK DONATIONS</strong>
<ol>
<li>Раздел 4 применяется только к Вознаграждению Автора и Донатам, перечисляемым с использованием OK Donations, как описано в Условиях Предоставления Услуг, и процент Агентского вознаграждения включает в себя расходы Компании, понесенные при выполнении и поддержке интеграции определенных Услуг Тизер для каждого из Пользователей и Авторов в OK Donations.</li>
<li>Сумма Агентского вознаграждения рассчитывается в зависимости от способа оплаты, который был использован Пользователем для перечисления Вознаграждения Автора и/или Донатов, и суммы Вознаграждения Автора и/или Донатов в соответствии с Таблицей 5:</li>
</ol>
</li>
</ol>
<p>Таблица 5</p>
<table>
<tbody>
<tr>
<td>Платежный способ</td>
<td>Агентское Вознаграждение</td>
</tr>
<tr>
<td>Банковские карты</td>
<td>5%</td>
</tr>
</tbody>
</table>
<ol start="3" class="mlml2">
<li></li>
<li>Автор, использующий OK Donations, вправе выбрать следующие доступные платежные способы для получения Вознаграждения Автора и/или Донатов в соответствии с настоящими Условиями Оплаты при условии, что обязательство компании по перечислению Вознаграждения Автора и/или Донатов считается исполненным с момента зачисления средств на соответствующий счет платежной системы Автора. С Автора взимается комиссия за перевод Вознаграждения Автора и/или Донатов, как указано в Таблице 6 ниже</li>
</ol>
<p>Таблица 6</p>
<table>
<tbody>
<tr>
<td>Платежный метод</td>
<td>% Вознаграждения Автора и/или Донатов</td>
</tr>
<tr>
<td>Банковские карты*</td>
<td>2,3% + 25 рублей</td>
</tr>
<tr>
<td>Банковские карты (бета)**</td>
<td>1,7%</td>
</tr>
<tr>
<td>QIWI</td>
<td>2%</td>
</tr>
</tbody>
</table>
<p>*Ограничения для банковских карт:</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 60000 рублей. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 600 000 рублей.</li>
</ul>
<p>**Ограничения для банковских карт (бета):</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 100000 рублей. Комиссия за единоразовый перевод на банковскую карту Вознаграждения Автора и/или Донатов не может быть меньше 30 рублей. Совокупное количество переводов на банковские карты не может превышать 50 штук. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 1 500 000 рублей.</li>
</ul>
&nbsp;
<ol start="5">
<li><strong>АГЕНТСКОЕ ВОЗНАГРАЖДЕНИЕ ДЛЯ </strong><strong>MY</strong><strong>.</strong><strong>GAMES</strong> <strong>BOOST</strong>
<ol>
<li>Раздел 5 применяется только к Вознаграждению Автора и Донатам, перечисляемым с использованием MY.GAMES Boost, как описано в Условиях Предоставления Услуг, и процент Агентского вознаграждения включает в себя расходы Компании, понесенные при выполнении и поддержке интеграции определенных Услуг Тизер для каждого из Пользователей и Авторов в MY.GAMES Boost.</li>
<li>Сумма Агентского вознаграждения рассчитывается в зависимости от способа оплаты, который был использован Пользователем для перечисления Вознаграждения Автора и/или Донатов, и суммы Вознаграждения Автора и/или Донатов в соответствии с Таблицей 7:</li>
</ol>
</li>
</ol>
<p>Таблица 7</p>
<table>
<tbody>
<tr>
<td>Платежный способ</td>
<td>Агентское Вознаграждение</td>
</tr>
<tr>
<td>Банковские карты</td>
<td>7%</td>
</tr>
<tr>
<td>VK Pay</td>
<td>7%</td>
</tr>
</tbody>
</table>
<ol start="3" class="mlml2">
<li></li>
<li>Автор, использующий MY.GAMES Boost, вправе выбрать следующие доступные платежные способы для получения Вознаграждения Автора и/или Донатов в соответствии с настоящими Условиями Оплаты при условии, что обязательство компании по перечислению Вознаграждения Автора и/или Донатов считается исполненным с момента зачисления средств на соответствующий счет платежной системы Автора. С Автора взимается комиссия за перевод Вознаграждения Автора и/или Донатов, как указано в Таблице 8 ниже</li>
</ol>
<p>Таблица 8</p>
<table>
<tbody>
<tr>
<td>Платежный метод</td>
<td>% Вознаграждения Автора и/или Донатов</td>
</tr>
<tr>
<td>Банковские карты*</td>
<td>2,3% + 25 рублей</td>
</tr>
<tr>
<td>Банковские карты (бета)**</td>
<td>1,7%</td>
</tr>
<tr>
<td>VK Pay</td>
<td>0%</td>
</tr>
<tr>
<td>QIWI Wallet</td>
<td>2%</td>
</tr>
<tr>
<td>WebMoney (WMR, WMZ, WME)</td>
<td>1,5%</td>
</tr>
<tr>
<td>PayPal</td>
<td>2,5%</td>
</tr>
</tbody>
</table>
<p>*Ограничения для банковских карт:</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 60000 рублей. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 600 000 рублей.</li>
</ul>
<p>**Ограничения для банковских карт (бета):</p>
<ul>
<li>Переводы на банковские карты. Сумма единоразового перевода на банковские карты не может быть меньше 150 рублей и не может превышать 100000 рублей. Комиссия за единоразовый перевод на банковскую карту Вознаграждения Автора и/или Донатов не может быть меньше 30 рублей. Совокупное количество переводов на банковские карты не может превышать 50 штук. Совокупная сумма Вознаграждения Автора и/или Донатов за 1 месяц не может превышать 1 500 000 рублей.</li>
</ul>
<div class="mt-10">
<em>Только версия данного документа на английском языке имеет юридическую силу. Любые переводы данного документа на другие языки предоставлены только для вашего удобства.</em>
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More