Files
luminic-front/src/components/transactions/TransactionList.vue
Vladimir Voronin 106aa56214 events
2025-01-09 15:58:05 +03:00

173 lines
6.5 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 {computed, onMounted, onUnmounted, ref} from "vue";
import BudgetTransactionView from "@/components/budgets/BudgetTransactionView.vue";
import IconField from "primevue/iconfield";
import InputIcon from "primevue/inputicon";
import InputText from "primevue/inputtext";
import {getTransactions, getTransactionTypes} from "@/services/transactionService";
import {Transaction} from "@/models/Transaction";
import ProgressSpinner from "primevue/progressspinner";
import {getUsers} from "@/services/userService";
import Button from "primevue/button";
import { EventBus } from '@/utils/eventBus';
const loading = ref(false);
const searchText = ref("");
const transactions = ref<Transaction[]>([]);
const limit = 20; // Количество транзакций на одну загрузку
const offset = ref(0); // Начальное смещение
const allLoaded = ref(false); // Флаг для отслеживания окончания данных
// Функция для получения транзакций с параметрами limit и offset
const fetchTransactions = async (reload) => {
console.log("here")
console.log(allLoaded.value)
// if (loading.value || allLoaded.value) return; // Останавливаем загрузку, если уже загружается или данные загружены полностью
loading.value = true;
try {
console.log(reload);
const response = await getTransactions('INSTANT', null, null, selectedUserId.value ? selectedUserId.value : null, null, reload ? offset.value : limit, reload ? 0 : offset.value);
const newTransactions = response.data;
// Проверка на конец данных
if (newTransactions.length < limit) {
allLoaded.value = true; // Если данных меньше limit, значит, достигнут конец
}
// Добавляем новые транзакции к текущему списку
reload ? transactions.value = newTransactions : transactions.value.push(...newTransactions)
offset.value += limit; // Обновляем смещение для следующей загрузки
} catch (error) {
console.error("Error fetching transactions:", error);
}
loading.value = false;
};
const switchUserFilter = async (user) => {
if (selectedUserId.value == user.id) {
selectedUserId.value = null
} else if (selectedUserId.value == null) {
selectedUserId.value = user.id;
} else {
selectedUserId.value = user.id;
}
await getTransactions('INSTANT', null, null, selectedUserId.value, null, offset.value, 0)
.then(it => transactions.value = it.data)
}
const tgname = computed(() => {
if (window.Telegram.WebApp) {
const tg = window.Telegram.WebApp;
return tg.initDataUnsafe.user;
}
});
// Отфильтрованные транзакции по поисковому запросу
const filteredTransactions = computed(() => {
// Проверяем, есть ли текст поиска
const search = searchText.value.trim().toLowerCase();
if (!search) {
// Если текст поиска пуст, возвращаем все транзакции
return transactions.value;
}
// Проверяем наличие данных
if (!transactions.value || !Array.isArray(transactions.value)) {
console.warn("Transactions is not a valid array");
return [];
}
// Фильтруем транзакции по тексту поиска
return transactions.value.filter(transaction => {
return transaction.comment.toLowerCase().includes(search) ||
transaction.category.name.toLowerCase().includes(search);
});
});
// Обработчик прокрутки для ленивой загрузки
// const handleScroll = () => {
// const bottomReached = window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 2000;
// if (bottomReached && !loading.value) {
// fetchTransactions(); // Загружаем следующую страницу
// }
// };
const users = ref([])
const selectedUserId = ref(null)
const fetchUsers = async () => {
users.value = await getUsers();
}
const selectedTransactionType = ref(null)
const types = ref([])
onMounted(async () => {
EventBus.on('transactions-updated', fetchTransactions);
await fetchTransactions(); // Первоначальная загрузка данных
await fetchUsers();
await getTransactionTypes().then( it => types.value = it.data);
// window.addEventListener("scroll", handleScroll); // Добавляем обработчик прокрутки
});
onUnmounted( async () => {
EventBus.off('transactions-updated', fetchTransactions);
})
</script>
<template>
<div class="px-4 bg-gray-100 h-full">
<h2 class="text-4xl mb-6 font-bold">Transaction list</h2>
<div class="flex flex-col gap-2">
<IconField>
<InputIcon class="pi pi-search"/>
<InputText v-model="searchText" placeholder="Search"></InputText>
</IconField>
<div class="flex flex-row gap-2">
<!-- <span v-for="user in users">{{user.id}}</span>-->
<button v-for="user in users" @click="switchUserFilter(user)"
class="rounded-xl border p-1 bg-white border-gray-300 mb-2 min-w-fit px-2"
:class="selectedUserId == user.id ? '!bg-blue-100' : ''">
<p><span class="text-sm font-bold">{{ user.firstName }}</span></p>
</button>
<!-- <button v-for="type in types" class="rounded-xl border p-1 bg-white border-gray-300 mb-2 min-w-fit px-2">-->
<!-- <p><span class="text-sm font-bold">{{ type.name }}</span></p>-->
<!-- </button>-->
</div>
<div class="flex flex-col gap-2">
<BudgetTransactionView
v-for="transaction in filteredTransactions"
:key="transaction.id"
:transaction="transaction"
:is-list="true"
@transaction-updated="fetchTransactions(true)"
@delete-transaction="fetchTransactions(true)"
/>
<div class="flex items-center justify-center px-2 py-1 mb-5">
<Button @click="fetchTransactions(false)">Загрузить следующие...</Button>
</div>
<!-- Показать спиннер загрузки, если идет загрузка -->
<ProgressSpinner v-if="loading" class="mb-4" style="width: 50px; height: 50px;"
strokeWidth="8"
fill="transparent"
animationDuration=".5s"/>
</div>
</div>
</div>
</template>
<style scoped>
</style>