205 lines
6.7 KiB
Vue
Executable File
205 lines
6.7 KiB
Vue
Executable File
<template>
|
||
<meta-head title="Подписчики"></meta-head>
|
||
|
||
<profile-header :is_leader="is_leader" :user="user"
|
||
:counts="counts" :limit-leader="limitLeader"
|
||
:auth-user-active-subscription="authUserActiveSubscription"
|
||
:package-completed="packageCompleted"
|
||
/>
|
||
<profile-menu :user="user" />
|
||
|
||
|
||
<div v-if="user.is_auth_user || (user.private === false || packageCompleted)" 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="">
|
||
<search-filter v-model="form.search" class="w-full max-w-3xl mr-4"
|
||
@reset="reset"
|
||
>
|
||
<div class="flex flex-col space-y-6">
|
||
<div class="flex items-center">
|
||
<input id="user-sub-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-sub-1" class="select-none ml-3 text-gray text-xs md:text-base">По подписчикам</label>
|
||
</div>
|
||
<div class="flex items-center">
|
||
<input id="user-sub-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-sub-2" class="select-none ml-3 text-gray text-xs md:text-base">Не по подписчикам</label>
|
||
</div>
|
||
</div>
|
||
</search-filter>
|
||
</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">
|
||
<InfinityScroll :node-element="lastNodeLement" :next-cursor="nextCursor"
|
||
@fromPagination="putFromPagination"
|
||
>
|
||
<div v-for="subscriber in userLists" :key="subscriber.id"
|
||
:ref="el => { if (el && subscriber.id === lastElementID) lastNodeLement = el }" class=" user-card relative"
|
||
>
|
||
<div v-if="user.is_auth_user && !subscriber.private" class="absolute inset-x-0 top-4 z-10 flex justify-center">
|
||
<toggle
|
||
:user_id="subscriber.id"
|
||
:enabled="subscriber.is_sub"
|
||
textin="Подписаться"
|
||
textout="Отписаться" @clicked="susbscribe"
|
||
/>
|
||
</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>
|
||
</InfinityScroll>
|
||
</div>
|
||
</div>
|
||
<div v-show="subscribers.length == 0">
|
||
<p class="mt-4 text-center md:text-2xl text-gray-light">
|
||
Пользователи не найдены
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div v-else class="mt-12 xl:container xl:mx-auto px-2 md:px-3 text-gray-light text-lg">
|
||
Аккаунт закрыт
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { ref } from 'vue'
|
||
import { Inertia } from '@inertiajs/inertia'
|
||
import pickBy from 'lodash/pickBy'
|
||
import throttle from 'lodash/throttle'
|
||
import mapValues from 'lodash/mapValues'
|
||
|
||
import Layout from '@/Shared/Layout.vue'
|
||
import MetaHead from '@/Shared/MetaHead.vue'
|
||
import ProfileHeader from '@/Shared/Partials/ProfileHeader.vue'
|
||
import ProfileMenu from '@/Shared/Partials/ProfileMenu.vue'
|
||
import UserAvatar from '@/Shared/Misc/UserAvatar.vue'
|
||
import UserBanner from '@/Shared/Misc/UserBanner.vue'
|
||
import Toggle from '@/Shared/Form/Toggle.vue'
|
||
import SearchFilter from '@/Shared/Form/SearchFilter.vue'
|
||
import InfinityScroll from '@/Shared/Misc/InfinityScroll.vue'
|
||
|
||
|
||
export default {
|
||
components: {
|
||
MetaHead,
|
||
Toggle,
|
||
UserAvatar,
|
||
UserBanner,
|
||
ProfileHeader,
|
||
ProfileMenu,
|
||
SearchFilter,
|
||
InfinityScroll,
|
||
},
|
||
layout: Layout,
|
||
props: {
|
||
nextCursor: String,
|
||
user: Object,
|
||
subscribers: Array,
|
||
counts: Object,
|
||
filters: Object,
|
||
is_leader: Boolean,
|
||
close_account: Boolean,
|
||
authUserActiveSubscription: Boolean,
|
||
limitLeader: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
packageCompleted: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
|
||
},
|
||
|
||
setup() {
|
||
const containerRef = ref(null)
|
||
return {
|
||
lastNodeLement: containerRef,
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
userLists: [],
|
||
form: {
|
||
search: this.filters.search,
|
||
sub: this.filters.sub,
|
||
},
|
||
}
|
||
},
|
||
|
||
computed: {
|
||
lastElementID() {
|
||
return this.userLists[this.userLists.length - 1]?.id
|
||
},
|
||
},
|
||
|
||
mounted() {
|
||
this.updateRequest()
|
||
},
|
||
|
||
watch: {
|
||
subscribers() {
|
||
this.updateRequest()
|
||
},
|
||
|
||
form: {
|
||
deep: true,
|
||
handler: throttle(function () {
|
||
const url = route('profile.subs', this.user.username)
|
||
Inertia.get(url, pickBy(this.form), {
|
||
preserveState: true,
|
||
preserveScroll: true,
|
||
})
|
||
}, 300),
|
||
},
|
||
},
|
||
|
||
methods: {
|
||
putFromPagination(lists) {
|
||
for (let list of lists) {
|
||
this.userLists.push(list)
|
||
}
|
||
},
|
||
|
||
updateRequest() {
|
||
this.userLists = this.subscribers
|
||
},
|
||
|
||
reset() {
|
||
this.form = mapValues(this.form, () => null)
|
||
},
|
||
susbscribe(user_id) {
|
||
Inertia.post(
|
||
route('users.subs', user_id),
|
||
{},
|
||
{ preserveScroll: true, preserveState: true }
|
||
)
|
||
},
|
||
},
|
||
}
|
||
</script>
|