diff --git a/src/features/planner/CategoryTransactions.tsx b/src/features/planner/CategoryTransactions.tsx index d624a23..59fdd2d 100644 --- a/src/features/planner/CategoryTransactions.tsx +++ b/src/features/planner/CategoryTransactions.tsx @@ -3,7 +3,8 @@ import * as React from "react"; import Link from "next/link"; import { TextFieldRoot, TextFieldInput } from "@seed-design/react"; -import { Card } from "@/ds"; +import { Card, IconChip } from "@/ds"; +import { categoryStyle } from "@/ds/categoryStyle"; import { tugrik } from "@/ds/money"; import { useTransactions } from "@/api/hooks/reads"; import type { Txn } from "@/api/schemas"; @@ -36,12 +37,20 @@ export function CategoryTransactions({ category }: CategoryTransactionsProps) { }); const [search, setSearch] = React.useState(""); + // The backend's ?category= filter always appends a handful of unrelated + // "straggler" rows (recent uncategorized/other-category txns) to every + // result, which makes a low-activity category look like it shows the wrong + // transactions. Filter to the exact category client-side so the drill-down + // is trustworthy (empty categories correctly show empty). Case-insensitive. const rows: Txn[] = React.useMemo(() => { - const all = data ?? []; + const key = category.trim().toLowerCase(); + const inCategory = (data ?? []).filter((t) => (t.category ?? "").trim().toLowerCase() === key); const needle = search.trim().toLowerCase(); - if (!needle) return all; - return all.filter((t) => t.title.toLowerCase().includes(needle)); - }, [data, search]); + if (!needle) return inCategory; + return inCategory.filter((t) => t.title.toLowerCase().includes(needle)); + }, [data, category, search]); + + const cat = categoryStyle(category); return (