Последняя версия с сервера прошлого разработчика

This commit is contained in:
2025-07-10 04:35:51 +00:00
commit c731570032
1174 changed files with 134314 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
<template>
<div class="gradient-profile relative">
<user-banner class="h-56 xl:h-80 bg-indigo-200" :user="user"
size="hero"
/>
</div>
<messanger-modal ref="messangerModal" />
<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-[350px] 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>
<!-- self-center -->
<div class="mx-2 my-2 lg:mx-4 lg:my-4 self-center md:self-start 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> {{ countReaders }}
</inertia-link>
</div>
<div class="mt-4 text-gray-light text-sm min-h-[20px]">
{{ 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>
<div v-else>
<button v-if="$page.props.auth.user && (user.private === false || packageCompleted)" class="pt-2 default flex items-center text-white"
@click="openModalMessanger"
>
<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 mr-2"
><line x1="22" y1="2"
x2="11" y2="13"
></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
написать сообщение
</button>
<toggle
v-if="$page.props.auth.user && user.private === false"
:user_id="user.id"
class="mt-3"
:enabled="user.is_sub"
textin="Подписаться"
textout="Отписаться" @clicked="susbscribe"
/>
<div v-if="authUserActiveSubscription">
<toggle
v-if="user.is_sub && (user.private === false || packageCompleted)"
class="mt-3"
:user_id="user.id"
:enabled="is_leader"
:disabled="limitLeader === true && user.is_leader === false ? true : false"
textin="Сделать лидером"
textout="Убрать лидера" @clicked="leader"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import helper from '@/includes/helper'
import { Inertia } from '@inertiajs/inertia'
import UserAvatar from '@/Shared/Misc/UserAvatar.vue'
import UserBanner from '@/Shared/Misc/UserBanner.vue'
import Toggle from '@/Shared/Form/Toggle.vue'
import MessangerModal from '@/Shared/Messanger/MessangerModal.vue'
export default {
components: {
Toggle,
UserAvatar,
UserBanner,
MessangerModal,
},
props: {
user: Object,
counts: Object,
is_leader: Boolean,
authUserActiveSubscription: Boolean,
limitLeader: {
type: Boolean,
default: false
},
packageCompleted: {
type: Boolean,
default: false
},
},
computed: {
countPosts() {
return helper.declNumPosts(this.counts.feeds)
},
countSubs() {
return helper.declNumSubs(this.counts.subscribers)
},
countReaders() {
return helper.declNumReaders(this.counts.readers)
},
},
methods: {
openModalMessanger() {
this.$refs.messangerModal.openAction(this.user)
},
susbscribe(user_id) {
Inertia.post(
route('users.subs', user_id),
{},
{ preserveScroll: true, preserveState: true }
)
},
leader(user_id) {
Inertia.post(
route('users.leader', user_id),
{ vote: this.is_leader },
{ preserveScroll: true, preserveState: true }
)
},
},
}
</script>

View File

@@ -0,0 +1,98 @@
<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('videos.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('images.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('musics.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.vue'
export default {
components: {
DropdownMenu,
MenuItem,
MenuItems,
PhotographIcon,
MusicNoteIcon,
VideoCameraIcon,
},
props: {
user: Object,
},
}
</script>

View File

@@ -0,0 +1,153 @@
<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-3
"
>
<span class="text-xs text-gray-light">{{
comment.created_at_humans
}}</span>
<template v-if="$page.props.auth.user">
<span
class="
text-xs text-gray-light
font-semibold
hover:underline
cursor-pointer
"
@click="toAnswer(comment.id, comment.user.id, comment.user.username)"
>ответить</span>
<inertia-link
v-if="$page.props.auth.user.id !== comment.user?.id"
:href="route('complaint.reason.comment', comment.id)"
class="
text-xs text-orange
font-semibold
hover:underline
cursor-pointer
"
>
пожаловаться
</inertia-link>
<user-comment-remove v-if="$page.props.auth.user.id === comment.user.id || $page.props.auth.user.id === creator_id" :text="comment.children_count ? 'удалить ветку' : 'удалить'"
@remove="removeComment"
/>
</template>
</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>
<div v-if="comment.children_count && comment.closed_children_comments" class="test-box ml-14 mt-2 text-gray-light text-xs">
<button class="button-default" @click="showChildren">
--- Посмотреть ответы ({{ comment.children_count }})
</button>
</div>
<div v-if="comment.childrens" class="mt-2 space-y-3 ml-14 md:space-y-6">
<div v-for="children in comment.childrens" :key="children.id"
class="comment-line text-gray text-sm"
>
<user-comment-children :creator_id="creator_id" :comment="children"
@toAnswerChild="sendChild" @removeComment="removeCommentChildren"
/>
</div>
</div>
<div v-if="cursor" class="flex items-center justify-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="cursor-pointer text-white" @click="showChildren"
><circle cx="12" cy="12"
r="10"
></circle><line x1="12" y1="8"
x2="12" y2="16"
></line><line x1="8" y1="12"
x2="16" y2="12"
></line></svg>
</div>
</template>
<script>
import UserAvatar from '@/Shared/Misc/UserAvatar.vue'
import UserCommentChildren from '@/Shared/Partials/UserCommentChildren.vue'
import UserCommentRemove from './UserCommentRemove.vue'
import axios from 'axios'
export default {
components: {
UserAvatar,
UserCommentChildren,
UserCommentRemove,
},
props: {
comment: Object,
creator_id: Number,
},
emits: ['toAnswer', 'showChildren', 'removeCommentItem'],
data() {
return {
cursor: null,
}
},
methods: {
toAnswer(id, user_id, name) {
this.$emit('toAnswer', id, user_id, name)
},
sendChild(user_id, name){
this.toAnswer(this.comment.id, user_id, name)
},
showChildren(){
const that = this
axios.post(route('comments.children.show', this.comment.id), { cursor: this.cursor }).then(({ data }) => {
that.$emit('showChildren', that.comment.id, data.items)
that.cursor = data.nextCursor
})
},
removeComment() {
const that = this
axios.post(route('comments.remove', this.comment.id)).then(({ data }) => {
that.$emit('removeCommentItem', that.comment.id, data, null)
})
},
removeCommentChildren(id) {
const that = this
axios.post(route('comments.remove', id)).then(({ data }) => {
that.$emit('removeCommentItem', id, data, that.comment.id)
})
}
},
}
</script>

View File

@@ -0,0 +1,92 @@
<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>
<div v-show="comment.user.id != comment.answer_to.id">
<inertia-link :href="route('profile.user', comment.answer_to.username)" class="text-orange">
@{{ comment.answer_to.username }}
</inertia-link>
</div>
{{ 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>
<inertia-link
v-if="$page.props.auth.user.id !== comment.user.id"
:href="route('complaint.reason.comment', comment.id)"
class="
text-xs text-orange
font-semibold
hover:underline
cursor-pointer
"
>
пожаловаться
</inertia-link>
<span
class="
text-xs text-gray-light
font-semibold
hover:underline
cursor-pointer
"
@click="toAnswerChildren()"
>ответить</span>
<user-comment-remove v-if="$page.props.auth.user.id === comment.user.id || $page.props.auth.user.id === creator_id" @remove="removeComment" />
</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.vue'
import UserCommentRemove from './UserCommentRemove.vue'
export default {
components: {
UserAvatar,
UserCommentRemove
},
props: {
comment: Object,
creator_id: Number,
},
emits: ['toAnswerChild', 'removeComment'],
methods: {
toAnswerChildren() {
this.$emit('toAnswerChild', this.comment.user.id, this.comment.user.username)
},
removeComment() {
this.$emit('removeComment', this.comment.id)
}
},
}
</script>

View File

@@ -0,0 +1,37 @@
<script setup>
import { ref } from 'vue'
defineProps({
text: {
type: String,
default: ''
}
})
const emit = defineEmits({
'remove': null
})
const show = ref(false)
function showPopupRemove() {
show.value = !show.value
}
function remove() {
show.value = false
emit('remove')
}
</script>
<template>
<div class="relative inline-flex">
<div v-if="show" class=" absolute text-xs px-1 py-1 w-[130px] leading-none rounded bg-pink top-[-35px]">
<span class="cursor-pointer" @click="remove">Нажмите для подтверждения</span>
</div>
<span
class="text-xs text-red font-semibold hover:underline cursor-pointer"
@click="showPopupRemove"
>
{{ show ? 'отменить' : text }}
</span>
</div>
</template>