Files
web-frontend/app/pages/clients/index.vue
2026-04-03 19:23:08 +07:00

128 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { useQuery } from '@vue/apollo-composable';
import {
RegistrationRequestsDocument,
type RegistrationRequestsQuery,
} from '~/composables/graphql/generated';
definePageMeta({
middleware: ['manager-only'],
});
type ClientCard = RegistrationRequestsQuery['registrationRequests'][number];
const clientsQuery = useQuery(RegistrationRequestsDocument, {
status: null,
});
const search = ref('');
function statusLabel(status: ClientCard['status']) {
if (status === 'APPROVED') {
return 'Активен';
}
if (status === 'REJECTED') {
return 'Отклонен';
}
return 'На проверке';
}
function statusClass(status: ClientCard['status']) {
if (status === 'APPROVED') {
return 'badge badge-success border-0';
}
if (status === 'REJECTED') {
return 'badge badge-error border-0';
}
return 'badge badge-warning border-0';
}
const filteredClients = computed(() => {
const items = clientsQuery.result.value?.registrationRequests ?? [];
const query = search.value.trim().toLowerCase();
return items.filter((item) => {
if (!query) {
return true;
}
return [
item.companyName,
item.contactName,
item.email,
item.inn || '',
]
.join(' ')
.toLowerCase()
.includes(query);
});
});
</script>
<template>
<section class="space-y-6">
<div class="flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
<div class="manager-hero">
<p class="manager-eyebrow">Клиенты</p>
<h1 class="manager-title">Карточки клиентов без лишней нагрузки</h1>
<p class="manager-copy">Список заявок и клиентов, с которыми менеджер уже работает.</p>
</div>
<NuxtLink to="/clients/invite" class="btn btn-primary border-0">
Пригласить клиента
</NuxtLink>
</div>
<div class="surface-card rounded-3xl p-4 md:p-5">
<div class="grid gap-3 md:grid-cols-[1fr_auto] md:items-end">
<label class="form-control">
<span class="label-text">Search</span>
<input
v-model="search"
type="text"
class="input manager-field w-full"
placeholder="Компания, контакт, email или ИНН"
>
</label>
<div class="manager-mini-card text-sm text-[#123824] md:w-56">
Всего карточек: <span class="font-semibold">{{ filteredClients.length }}</span>
</div>
</div>
</div>
<div v-if="clientsQuery.loading.value" class="manager-empty-state">
Загружаем клиентов...
</div>
<div v-else-if="filteredClients.length === 0" class="manager-empty-state">
По текущему запросу карточки клиентов не найдены.
</div>
<div v-else class="grid gap-4 lg:grid-cols-2 xl:grid-cols-3">
<NuxtLink
v-for="client in filteredClients"
:key="client.id"
:to="`/clients/${client.id}`"
class="surface-card rounded-3xl p-5"
>
<div class="flex items-start justify-between gap-3">
<div class="space-y-1">
<h2 class="text-lg font-bold text-[#123824]">{{ client.companyName }}</h2>
<p class="text-sm text-[#466653]">{{ client.contactName }}</p>
</div>
<span :class="statusClass(client.status)">{{ statusLabel(client.status) }}</span>
</div>
<div class="mt-4 space-y-2 text-sm text-[#355947]">
<p>{{ client.email }}</p>
<p v-if="client.inn">ИНН: {{ client.inn }}</p>
<p>{{ new Date(client.createdAt).toLocaleDateString() }}</p>
</div>
<p v-if="client.rejectionReason" class="mt-4 text-sm text-[#a34a34]">
{{ client.rejectionReason }}
</p>
</NuxtLink>
</div>
</section>
</template>