Show only linked clients in bonus balances

This commit is contained in:
Ruslan Bakiev
2026-04-04 15:13:21 +07:00
parent 540418c1dc
commit 309d0e78db

View File

@@ -2,8 +2,10 @@
import { useQuery } from '@vue/apollo-composable'; import { useQuery } from '@vue/apollo-composable';
import { import {
ManagerBonusBalancesDocument, ManagerBonusBalancesDocument,
ManagerReferralLinksDocument,
ManagerWithdrawalRequestsDocument, ManagerWithdrawalRequestsDocument,
type ManagerBonusBalancesQuery, type ManagerBonusBalancesQuery,
type ManagerReferralLinksQuery,
type ManagerWithdrawalRequestsQuery, type ManagerWithdrawalRequestsQuery,
} from '~/composables/graphql/generated'; } from '~/composables/graphql/generated';
@@ -12,12 +14,14 @@ definePageMeta({
}); });
type BalanceItem = ManagerBonusBalancesQuery['managerBonusBalances'][number]; type BalanceItem = ManagerBonusBalancesQuery['managerBonusBalances'][number];
type ReferralLinkItem = ManagerReferralLinksQuery['managerReferralLinks'][number];
type WithdrawalItem = ManagerWithdrawalRequestsQuery['managerWithdrawalRequests'][number]; type WithdrawalItem = ManagerWithdrawalRequestsQuery['managerWithdrawalRequests'][number];
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const search = ref(''); const search = ref('');
const balancesQuery = useQuery(ManagerBonusBalancesDocument); const balancesQuery = useQuery(ManagerBonusBalancesDocument);
const referralLinksQuery = useQuery(ManagerReferralLinksDocument);
const withdrawalsQuery = useQuery(ManagerWithdrawalRequestsDocument, { const withdrawalsQuery = useQuery(ManagerWithdrawalRequestsDocument, {
status: 'PENDING', status: 'PENDING',
}); });
@@ -36,13 +40,28 @@ function setTab(tab: 'balances' | 'withdrawals') {
} }
const balances = computed<BalanceItem[]>(() => balancesQuery.result.value?.managerBonusBalances ?? []); const balances = computed<BalanceItem[]>(() => balancesQuery.result.value?.managerBonusBalances ?? []);
const referralLinks = computed<ReferralLinkItem[]>(() => referralLinksQuery.result.value?.managerReferralLinks ?? []);
const withdrawals = computed<WithdrawalItem[]>(() => withdrawalsQuery.result.value?.managerWithdrawalRequests ?? []); const withdrawals = computed<WithdrawalItem[]>(() => withdrawalsQuery.result.value?.managerWithdrawalRequests ?? []);
const referralLinksByReferrer = computed(() => {
const grouped = new Map<string, ReferralLinkItem[]>();
for (const link of referralLinks.value) {
const existing = grouped.get(link.referrerId) ?? [];
existing.push(link);
grouped.set(link.referrerId, existing);
}
return grouped;
});
const filteredBalances = computed(() => { const filteredBalances = computed(() => {
const query = search.value.trim().toLowerCase(); const query = search.value.trim().toLowerCase();
return balances.value.filter((item) => { return balances.value.filter((item) => {
if (item.balance <= 0) { const links = referralLinksByReferrer.value.get(item.userId);
if (!links?.length) {
return false; return false;
} }
@@ -55,6 +74,12 @@ const filteredBalances = computed(() => {
item.email, item.email,
item.companyName || '', item.companyName || '',
String(item.balance), String(item.balance),
...links.flatMap((link) => [
link.refereeName,
link.refereeEmail,
link.refereeCompanyName || '',
String(link.bonusPercent),
]),
] ]
.join(' ') .join(' ')
.toLowerCase() .toLowerCase()
@@ -90,7 +115,7 @@ const filteredWithdrawals = computed(() => {
<UiSectionSearchHero <UiSectionSearchHero
v-model="search" v-model="search"
title="Бонусы" title="Бонусы"
:search-placeholder="activeTab === 'balances' ? 'Пользователь, email или сумма' : 'Пользователь, сумма или статус'" :search-placeholder="activeTab === 'balances' ? 'Клиент, связанный клиент, email или процент' : 'Пользователь, сумма или статус'"
> >
<template #controls> <template #controls>
<NuxtLink to="/bonus-system/referrals/new" class="btn btn-primary border-0"> <NuxtLink to="/bonus-system/referrals/new" class="btn btn-primary border-0">
@@ -119,11 +144,11 @@ const filteredWithdrawals = computed(() => {
</UiSectionSearchHero> </UiSectionSearchHero>
<template v-if="activeTab === 'balances'"> <template v-if="activeTab === 'balances'">
<div v-if="balancesQuery.loading.value" class="manager-empty-state"> <div v-if="balancesQuery.loading.value || referralLinksQuery.loading.value" class="manager-empty-state">
Загружаем балансы... Загружаем балансы...
</div> </div>
<div v-else-if="filteredBalances.length === 0" class="manager-empty-state"> <div v-else-if="filteredBalances.length === 0" class="manager-empty-state">
Пользователей с ненулевым балансом сейчас нет. Бонусных связок пока нет.
</div> </div>
<div v-else class="grid gap-4 lg:grid-cols-2 xl:grid-cols-3"> <div v-else class="grid gap-4 lg:grid-cols-2 xl:grid-cols-3">
<article <article
@@ -139,6 +164,20 @@ const filteredWithdrawals = computed(() => {
<div class="mt-4 space-y-2 text-sm text-[#355947]"> <div class="mt-4 space-y-2 text-sm text-[#355947]">
<p>Баланс: <span class="font-semibold text-[#123824]">{{ item.balance }}</span></p> <p>Баланс: <span class="font-semibold text-[#123824]">{{ item.balance }}</span></p>
<p>Активных связок: <span class="font-semibold text-[#123824]">{{ referralLinksByReferrer.get(item.userId)?.length ?? 0 }}</span></p>
</div>
<div class="mt-4 space-y-2 rounded-2xl bg-[#f4faf6] p-4 text-sm text-[#355947]">
<p class="font-semibold text-[#123824]">Начисление идёт с заказов:</p>
<div
v-for="link in referralLinksByReferrer.get(item.userId) ?? []"
:key="link.id"
class="rounded-2xl bg-white px-3 py-2"
>
<p class="font-medium text-[#123824]">{{ link.refereeName }}</p>
<p>{{ link.refereeCompanyName || link.refereeEmail }}</p>
<p class="text-xs text-[#5c7b69]">Бонус: {{ link.bonusPercent }}%</p>
</div>
</div> </div>
</article> </article>
</div> </div>