|
3 | 3 | <div class="flex flex-row gap-2.5 items-center"> |
4 | 4 | <SectionTitle title="Партнеры" /> |
5 | 5 | <CounterBadge :value="filteredPartners.length" /> |
| 6 | + <CounterBadge :value="`${new Intl.NumberFormat().format(totalBalance)} ₽`" /> |
6 | 7 | </div> |
7 | 8 |
|
8 | 9 | <div class="grid grid-cols-1 gap-2.5 items-center"> |
|
16 | 17 | }" |
17 | 18 | class="motion-preset-slide-down" |
18 | 19 | /> |
| 20 | + |
| 21 | + <USelect |
| 22 | + v-model="sortedBy" |
| 23 | + size="xl" |
| 24 | + trailing-icon="i-lucide-arrow-down-wide-narrow" |
| 25 | + :ui="{ |
| 26 | + base: 'rounded-lg text-lg/5 font-bold ring-0', |
| 27 | + }" |
| 28 | + :items="[ |
| 29 | + { label: 'По фамилии (возрастание)', value: 'nameAsc' }, |
| 30 | + { label: 'По балансу (возрастание)', value: 'balanceAsc' }, |
| 31 | + { label: 'По балансу (убывание)', value: 'balanceDesc' }, |
| 32 | + ]" |
| 33 | + class="motion-preset-slide-down" |
| 34 | + /> |
| 35 | + |
| 36 | + <USelect |
| 37 | + v-model="filteredBy" |
| 38 | + size="xl" |
| 39 | + trailing-icon="i-lucide-funnel" |
| 40 | + :ui="{ |
| 41 | + base: 'rounded-lg text-lg/5 font-bold ring-0', |
| 42 | + }" |
| 43 | + :items="[ |
| 44 | + { label: 'Все', value: 'all' }, |
| 45 | + { label: 'Только должники', value: 'negativeBalance' }, |
| 46 | + ]" |
| 47 | + class="motion-preset-slide-up" |
| 48 | + /> |
19 | 49 | </div> |
20 | 50 |
|
21 | 51 | <div class="grid grid-cols-2 gap-2.5 items-start"> |
|
32 | 62 | </template> |
33 | 63 |
|
34 | 64 | <script setup lang="ts"> |
| 65 | +import type { PartnerWithData } from '~/stores/partner' |
| 66 | +
|
35 | 67 | const partnerStore = usePartnerStore() |
36 | 68 |
|
| 69 | +const totalBalance = computed(() => partnerStore.partners.reduce((acc, partner) => acc + partner.balance, 0)) |
| 70 | +
|
| 71 | +const sortedBy = ref<'nameAsc' | 'balanceAsc' | 'balanceDesc'>('nameAsc') |
| 72 | +
|
| 73 | +function sortByNameAsc(a: PartnerWithData, b: PartnerWithData): number { |
| 74 | + return a.legalEntity?.name?.localeCompare(b.legalEntity?.name ?? '') ?? 0 |
| 75 | +} |
| 76 | +
|
| 77 | +function sortByBalanceAsc(a: PartnerWithData, b: PartnerWithData) { |
| 78 | + return a.balance - b.balance |
| 79 | +} |
| 80 | +
|
| 81 | +function sortByBalanceDesc(a: PartnerWithData, b: PartnerWithData) { |
| 82 | + return b.balance - a.balance |
| 83 | +} |
| 84 | +
|
| 85 | +function chooseSortFunction() { |
| 86 | + switch (sortedBy.value) { |
| 87 | + case 'nameAsc': |
| 88 | + return sortByNameAsc |
| 89 | + case 'balanceAsc': |
| 90 | + return sortByBalanceAsc |
| 91 | + case 'balanceDesc': |
| 92 | + return sortByBalanceDesc |
| 93 | + } |
| 94 | +} |
| 95 | +
|
37 | 96 | const search = ref('') |
38 | 97 |
|
| 98 | +const filteredBy = ref<'all' | 'negativeBalance'>('all') |
| 99 | +
|
| 100 | +function filterByAll() { |
| 101 | + return true |
| 102 | +} |
| 103 | +
|
| 104 | +function filterByNegativeBalance(partner: PartnerWithData) { |
| 105 | + return partner.balance < 0 |
| 106 | +} |
| 107 | +
|
| 108 | +function chooseFilterFunction() { |
| 109 | + switch (filteredBy.value) { |
| 110 | + case 'all': |
| 111 | + return filterByAll |
| 112 | + case 'negativeBalance': |
| 113 | + return filterByNegativeBalance |
| 114 | + } |
| 115 | +} |
| 116 | +
|
39 | 117 | const filteredPartners = computed(() => { |
| 118 | + const sorted = partnerStore.partners.toSorted(chooseSortFunction()) |
| 119 | + const filtered = sorted.filter(chooseFilterFunction()) |
| 120 | +
|
40 | 121 | if (!search.value) { |
41 | 122 | // Show all |
42 | | - return partnerStore.partners |
| 123 | + return filtered |
43 | 124 | } |
44 | 125 |
|
45 | | - const filteredBySearch = partnerStore.partners.filter((partner) => { |
| 126 | + return filtered.filter((partner) => { |
46 | 127 | return partner.legalEntity?.name?.toLowerCase().includes(search.value.toLowerCase()) ?? false |
47 | 128 | }) |
48 | | -
|
49 | | - return filteredBySearch |
50 | 129 | }) |
51 | 130 | </script> |
0 commit comments