mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 19:16:40 +07:00
fix: show full category path (parent · subcategory) everywhere, group filters by hierarchy
Транзакция на подкатегории показывала только её имя — непонятно было, что это подкатегория и к какой родительской категории она относится. Фильтры по категории в Транзакциях и Отчётах тоже перечисляли подкатегории наравне с родительскими, без иерархии. - categoryLabels.ts: categoryPath() и buildHierarchicalCategories() — общая логика, вынесенная из TransactionFormModal. - Список транзакций и «Последние транзакции» на Dashboard показывают счёт, затем родителя, затем подкатегорию. - Фильтр категорий в Транзакциях сгруппирован по типу (как в Отчётах); оба списка показывают подкатегорию с отступом под родителем.
This commit is contained in:
@@ -29,3 +29,43 @@ export function translateCategoryName(name: string): string {
|
||||
const key = DEFAULT_CATEGORY_KEYS[name];
|
||||
return key ? t(key) : name;
|
||||
}
|
||||
|
||||
/** A category's full path for display — "Groceries" alone reads as if it
|
||||
* were a top-level category even when it's actually a subcategory; showing
|
||||
* "Groceries · Sweets" makes the parent unambiguous everywhere a bare
|
||||
* category name used to be shown (transaction rows, filters). `categories`
|
||||
* is the full list (any kind, any order) to resolve the parent's own name
|
||||
* from `category.parent_id` — subcategories are one level deep only, so a
|
||||
* single lookup is enough. */
|
||||
export function categoryPath(
|
||||
category: { name: string; parent_id: number | null },
|
||||
categories: { id: number; name: string }[] | undefined
|
||||
): string {
|
||||
if (category.parent_id == null) return translateCategoryName(category.name);
|
||||
const parent = categories?.find((c) => c.id === category.parent_id);
|
||||
if (!parent) return translateCategoryName(category.name);
|
||||
return `${translateCategoryName(parent.name)} · ${translateCategoryName(category.name)}`;
|
||||
}
|
||||
|
||||
/** Orders a category list for display in a dropdown: alphabetical by
|
||||
* translated name, with each subcategory placed directly under its own
|
||||
* parent (not scattered by name) and flagged `indented` so callers can
|
||||
* prefix it visually (e.g. " ↳ "). Shared by every category picker
|
||||
* (TransactionFormModal, the Transactions/Reports filters) so they all
|
||||
* read the same way. */
|
||||
export function buildHierarchicalCategories<C extends { id: number; parent_id: number | null; name: string }>(
|
||||
categories: C[],
|
||||
language: string
|
||||
): (C & { indented: boolean })[] {
|
||||
const sorted = [...categories].sort((a, b) =>
|
||||
translateCategoryName(a.name).localeCompare(translateCategoryName(b.name), language)
|
||||
);
|
||||
const result: (C & { indented: boolean })[] = [];
|
||||
for (const parent of sorted.filter((category) => category.parent_id === null)) {
|
||||
result.push({ ...parent, indented: false });
|
||||
for (const child of sorted.filter((category) => category.parent_id === parent.id)) {
|
||||
result.push({ ...child, indented: true });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user