105 lines
2.8 KiB
Vue
105 lines
2.8 KiB
Vue
<script setup lang="ts">
|
|
import { useQuery } from '@vue/apollo-composable';
|
|
import { ManagerUsersDocument } from '~/composables/graphql/generated';
|
|
import { messengerConnectionAvatarSrc } from '~/composables/useMessengerConnectionPresentation';
|
|
|
|
definePageMeta({
|
|
middleware: ['manager-only'],
|
|
path: '/admin/orders/clients',
|
|
alias: ['/clients'],
|
|
});
|
|
|
|
const search = ref('');
|
|
const usersQuery = useQuery(ManagerUsersDocument);
|
|
|
|
const filteredUsers = computed(() => {
|
|
const items = usersQuery.result.value?.managerUsers ?? [];
|
|
const query = search.value.trim().toLowerCase();
|
|
|
|
return items.filter((item) => {
|
|
if (!query) {
|
|
return true;
|
|
}
|
|
|
|
return [
|
|
item.fullName,
|
|
item.email,
|
|
item.companyName || '',
|
|
]
|
|
.join(' ')
|
|
.toLowerCase()
|
|
.includes(query);
|
|
});
|
|
});
|
|
|
|
const {
|
|
canLoadMore: canLoadMoreUsers,
|
|
loadMore: loadMoreUsers,
|
|
loadMoreSentinel: loadMoreUsersSentinel,
|
|
remainingCount: remainingUsersCount,
|
|
visibleItems: visibleUsers,
|
|
} = useIncrementalList(filteredUsers, {
|
|
pageSize: 24,
|
|
resetKeys: [search],
|
|
});
|
|
|
|
function userInitials(fullName: string) {
|
|
const parts = fullName
|
|
.trim()
|
|
.split(/\s+/)
|
|
.filter(Boolean)
|
|
.slice(0, 2);
|
|
|
|
if (!parts.length) {
|
|
return 'FR';
|
|
}
|
|
|
|
return parts.map((part) => part[0]?.toUpperCase() ?? '').join('');
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<section class="space-y-6">
|
|
<UiSectionSearchHero
|
|
v-model="search"
|
|
title="Клиенты"
|
|
search-placeholder="Имя, компания или email"
|
|
>
|
|
<template #controls>
|
|
<NuxtLink to="/admin/orders/clients/invite" class="btn btn-primary border-0">
|
|
Пригласить
|
|
</NuxtLink>
|
|
</template>
|
|
</UiSectionSearchHero>
|
|
|
|
<div v-if="usersQuery.loading.value" class="manager-empty-state">
|
|
Загружаем пользователей...
|
|
</div>
|
|
<div v-else-if="filteredUsers.length === 0" class="manager-empty-state">
|
|
Пользователи по текущему запросу не найдены.
|
|
</div>
|
|
<div v-else class="space-y-4">
|
|
<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-6">
|
|
<UsersGridCard
|
|
v-for="user in visibleUsers"
|
|
:key="user.id"
|
|
:to="`/admin/orders/clients/${user.id}`"
|
|
:full-name="user.fullName"
|
|
:avatar-src="messengerConnectionAvatarSrc(user.telegramConnection)"
|
|
:initials="userInitials(user.fullName)"
|
|
/>
|
|
</div>
|
|
|
|
<div
|
|
v-if="canLoadMoreUsers"
|
|
ref="loadMoreUsersSentinel"
|
|
class="flex justify-center"
|
|
>
|
|
<button class="btn btn-outline border-[#d7e9de] bg-white" @click="loadMoreUsers">
|
|
Показать ещё {{ Math.min(remainingUsersCount, 24) }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|