feat: implement enhanced transaction filtering capabilities with support for account and category filters, improving data visibility and user interaction

This commit is contained in:
Julien Froidefond
2025-11-29 19:19:21 +01:00
parent 921ee4a5f0
commit 5195f4adad
5 changed files with 234 additions and 47 deletions

View File

@@ -33,25 +33,55 @@ export default function StatisticsPage() {
const [selectedAccounts, setSelectedAccounts] = useState<string[]>(["all"]);
const [selectedCategories, setSelectedCategories] = useState<string[]>(["all"]);
const stats = useMemo(() => {
if (!data) return null;
// Get start date based on period
const startDate = useMemo(() => {
const now = new Date();
let startDate: Date;
switch (period) {
case "3months":
startDate = new Date(now.getFullYear(), now.getMonth() - 3, 1);
break;
return new Date(now.getFullYear(), now.getMonth() - 3, 1);
case "6months":
startDate = new Date(now.getFullYear(), now.getMonth() - 6, 1);
break;
return new Date(now.getFullYear(), now.getMonth() - 6, 1);
case "12months":
startDate = new Date(now.getFullYear(), now.getMonth() - 12, 1);
break;
return new Date(now.getFullYear(), now.getMonth() - 12, 1);
default:
startDate = new Date(0);
return new Date(0);
}
}, [period]);
// Transactions filtered for account filter (by categories, period - not accounts)
const transactionsForAccountFilter = useMemo(() => {
if (!data) return [];
return data.transactions.filter(
(t) => new Date(t.date) >= startDate
).filter((t) => {
if (!selectedCategories.includes("all")) {
if (selectedCategories.includes("uncategorized")) {
return !t.categoryId;
} else {
return t.categoryId && selectedCategories.includes(t.categoryId);
}
}
return true;
});
}, [data, startDate, selectedCategories]);
// Transactions filtered for category filter (by accounts, period - not categories)
const transactionsForCategoryFilter = useMemo(() => {
if (!data) return [];
return data.transactions.filter(
(t) => new Date(t.date) >= startDate
).filter((t) => {
if (!selectedAccounts.includes("all")) {
return selectedAccounts.includes(t.accountId);
}
return true;
});
}, [data, startDate, selectedAccounts]);
const stats = useMemo(() => {
if (!data) return null;
let transactions = data.transactions.filter(
(t) => new Date(t.date) >= startDate
@@ -226,7 +256,7 @@ export default function StatisticsPage() {
perAccountBalanceData,
transactionCount: transactions.length,
};
}, [data, period, selectedAccounts, selectedCategories]);
}, [data, startDate, selectedAccounts, selectedCategories]);
const formatCurrency = (amount: number) => {
return new Intl.NumberFormat("fr-FR", {
@@ -255,6 +285,7 @@ export default function StatisticsPage() {
value={selectedAccounts}
onChange={setSelectedAccounts}
className="w-[200px]"
filteredTransactions={transactionsForAccountFilter}
/>
<CategoryFilterCombobox
@@ -262,6 +293,7 @@ export default function StatisticsPage() {
value={selectedCategories}
onChange={setSelectedCategories}
className="w-[220px]"
filteredTransactions={transactionsForCategoryFilter}
/>
<Select