feat: enhance category filter functionality to include child categories in selection and deselection; update transaction page to expand selected categories based on parent-child relationships
This commit is contained in:
@@ -87,21 +87,58 @@ export function CategoryFilterCombobox({
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a parent category
|
||||
const isParentCategory = parentCategories.some((p) => p.id === newValue);
|
||||
const childCategories = isParentCategory
|
||||
? childrenByParent[newValue] || []
|
||||
: [];
|
||||
|
||||
// Category selection - toggle
|
||||
let newSelection: string[];
|
||||
|
||||
if (isAll || isUncategorized) {
|
||||
// Start fresh with just this category
|
||||
// Start fresh with this category and its children (if parent)
|
||||
if (isParentCategory && childCategories.length > 0) {
|
||||
newSelection = [
|
||||
newValue,
|
||||
...childCategories.map((child) => child.id),
|
||||
];
|
||||
} else {
|
||||
newSelection = [newValue];
|
||||
}
|
||||
} else if (value.includes(newValue)) {
|
||||
// Remove category
|
||||
// Remove category and its children (if parent)
|
||||
if (isParentCategory && childCategories.length > 0) {
|
||||
const childIds = childCategories.map((child) => child.id);
|
||||
newSelection = value.filter(
|
||||
(v) => v !== newValue && !childIds.includes(v)
|
||||
);
|
||||
} else {
|
||||
newSelection = value.filter((v) => v !== newValue);
|
||||
}
|
||||
if (newSelection.length === 0) {
|
||||
newSelection = ["all"];
|
||||
}
|
||||
} else {
|
||||
// Add category
|
||||
// Add category and its children (if parent)
|
||||
if (isParentCategory && childCategories.length > 0) {
|
||||
const childIds = childCategories.map((child) => child.id);
|
||||
newSelection = [
|
||||
...value.filter((v) => !childIds.includes(v)), // Remove any existing children
|
||||
newValue,
|
||||
...childIds,
|
||||
];
|
||||
} else {
|
||||
// Check if this child's parent is already selected
|
||||
const category = categories.find((c) => c.id === newValue);
|
||||
if (category?.parentId && value.includes(category.parentId)) {
|
||||
// Parent is selected, so we're adding a child - keep parent
|
||||
newSelection = [...value, newValue];
|
||||
} else {
|
||||
// Regular add
|
||||
newSelection = [...value, newValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onChange(newSelection);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
useDuplicateIds,
|
||||
} from "@/lib/hooks";
|
||||
import type { TransactionsPaginatedParams } from "@/services/banking.service";
|
||||
import type { Category } from "@/lib/types";
|
||||
|
||||
type SortField = "date" | "amount" | "description";
|
||||
type SortOrder = "asc" | "desc";
|
||||
@@ -74,15 +75,35 @@ export function useTransactionsPage() {
|
||||
const categoryIdsParam = searchParams.get("categoryIds");
|
||||
const includeUncategorizedParam = searchParams.get("includeUncategorized");
|
||||
|
||||
if (categoryIdsParam) {
|
||||
if (categoryIdsParam && metadata) {
|
||||
const categoryIds = categoryIdsParam.split(",");
|
||||
setSelectedCategories(categoryIds);
|
||||
|
||||
// Expand parent categories to include their children
|
||||
const expandedCategoryIds = new Set<string>(categoryIds);
|
||||
|
||||
categoryIds.forEach((categoryId) => {
|
||||
// Check if this is a parent category
|
||||
const category = metadata.categories.find(
|
||||
(c: Category) => c.id === categoryId
|
||||
);
|
||||
if (category && category.parentId === null) {
|
||||
// Find all children of this parent
|
||||
const children = metadata.categories.filter(
|
||||
(c: Category) => c.parentId === categoryId
|
||||
);
|
||||
children.forEach((child: Category) => {
|
||||
expandedCategoryIds.add(child.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setSelectedCategories(Array.from(expandedCategoryIds));
|
||||
setPage(0);
|
||||
} else if (includeUncategorizedParam === "true") {
|
||||
setSelectedCategories(["uncategorized"]);
|
||||
setPage(0);
|
||||
}
|
||||
}, [searchParams]);
|
||||
}, [searchParams, metadata]);
|
||||
|
||||
// Calculate start date based on period
|
||||
const startDate = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user