import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { Filter, Search, TrendingUp, TrendingDown, Calendar, RefreshCw, AlertCircle, X, } from "lucide-react"; import { apiClient } from "../lib/api"; import { formatCurrency, formatDate } from "../lib/utils"; import LoadingSpinner from "./LoadingSpinner"; import type { Account, Transaction } from "../types/api"; export default function TransactionsList() { const [searchTerm, setSearchTerm] = useState(""); const [selectedAccount, setSelectedAccount] = useState(""); const [startDate, setStartDate] = useState(""); const [endDate, setEndDate] = useState(""); const [showFilters, setShowFilters] = useState(false); const { data: accounts } = useQuery({ queryKey: ["accounts"], queryFn: apiClient.getAccounts, }); const { data: transactions, isLoading: transactionsLoading, error: transactionsError, refetch: refetchTransactions, } = useQuery({ queryKey: ["transactions", selectedAccount, startDate, endDate], queryFn: () => apiClient.getTransactions({ accountId: selectedAccount || undefined, startDate: startDate || undefined, endDate: endDate || undefined, }), }); const filteredTransactions = (transactions || []).filter((transaction) => { // Additional validation (API client should have already filtered out invalid ones) if (!transaction || !transaction.account_id) { console.warn( "Invalid transaction found after API filtering:", transaction, ); return false; } const description = transaction.description || ""; const creditorName = transaction.creditor_name || ""; const debtorName = transaction.debtor_name || ""; const reference = transaction.reference || ""; const matchesSearch = searchTerm === "" || description.toLowerCase().includes(searchTerm.toLowerCase()) || creditorName.toLowerCase().includes(searchTerm.toLowerCase()) || debtorName.toLowerCase().includes(searchTerm.toLowerCase()) || reference.toLowerCase().includes(searchTerm.toLowerCase()); return matchesSearch; }); const clearFilters = () => { setSearchTerm(""); setSelectedAccount(""); setStartDate(""); setEndDate(""); }; const hasActiveFilters = searchTerm || selectedAccount || startDate || endDate; if (transactionsLoading) { return (
); } if (transactionsError) { return (

Failed to load transactions

Unable to fetch transactions from the Leggen API.

); } return (
{/* Filters */}

Transactions

{hasActiveFilters && ( )}
{showFilters && (
{/* Search */}
setSearchTerm(e.target.value)} placeholder="Description, name, reference..." className="pl-10 pr-3 py-2 w-full border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
{/* Account Filter */}
{/* Start Date */}
setStartDate(e.target.value)} className="pl-10 pr-3 py-2 w-full border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
{/* End Date */}
setEndDate(e.target.value)} className="pl-10 pr-3 py-2 w-full border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
)} {/* Results Summary */}

Showing {filteredTransactions.length} transaction {filteredTransactions.length !== 1 ? "s" : ""} {selectedAccount && accounts && ( for {accounts.find((acc) => acc.id === selectedAccount)?.name} )}

{/* Transactions List */} {filteredTransactions.length === 0 ? (

No transactions found

{hasActiveFilters ? "Try adjusting your filters to see more results." : "No transactions are available for the selected criteria."}

) : (
{filteredTransactions.map((transaction) => { const account = accounts?.find( (acc) => acc.id === transaction.account_id, ); const isPositive = transaction.amount > 0; return (
{isPositive ? ( ) : ( )}

{transaction.description}

{account && (

{account.name || "Unnamed Account"} •{" "} {account.institution_id}

)} {(transaction.creditor_name || transaction.debtor_name) && (

{isPositive ? "From: " : "To: "} {transaction.creditor_name || transaction.debtor_name}

)} {transaction.reference && (

Ref: {transaction.reference}

)} {transaction.internal_transaction_id && (

ID: {transaction.internal_transaction_id}

)}

{isPositive ? "+" : ""} {formatCurrency(transaction.amount, transaction.currency)}

{transaction.date ? formatDate(transaction.date) : "No date"}

{transaction.booking_date && transaction.booking_date !== transaction.date && (

Booked: {formatDate(transaction.booking_date)}

)}
); })}
)}
); }