From 2c6fcd628c60d5b0bb1d3f36e7c2448c1c7c7cf9 Mon Sep 17 00:00:00 2001 From: ZProger Date: Mon, 24 Aug 2026 23:51:33 +0300 Subject: [PATCH] feat: add 4 default income categories, localize category display names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fresh installs (this app is published on GitHub) only got Salary, Freelance, Investments, Gifts, Other Income by default — adds Business Income, Rental Income, Benefits, and Item Sales, rounding out the 8-slot categorical palette. Only affects new databases (seeding is a one-time no-op once any category exists). Also fixes CategoryList.tsx (added last commit) to run category names through translateCategoryName() like every other category display in the app, and registers the new defaults' translation keys. Co-Authored-By: Claude Sonnet 5 --- backend/app/db/seed.py | 4 ++++ frontend/package.json | 2 +- .../src/components/categories/CategoryList.tsx | 3 ++- frontend/src/lib/categoryLabels.ts | 12 ++++++++---- frontend/src/lib/i18n.ts | 17 ++++++++++++----- frontend/src/lib/icons.tsx | 6 ++++++ 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/backend/app/db/seed.py b/backend/app/db/seed.py index fe93f35..20729cd 100644 --- a/backend/app/db/seed.py +++ b/backend/app/db/seed.py @@ -31,6 +31,10 @@ DEFAULT_INCOME_CATEGORIES = [ ("Freelance", "briefcase", "#1baf7a"), ("Investments", "trending-up", "#4a3aa7"), ("Gifts", "gift", "#e87ba4"), + ("Business Income", "building-2", "#eb6834"), + ("Rental Income", "key", "#eda100"), + ("Benefits", "hand-coins", "#008300"), + ("Item Sales", "tag", "#e34948"), ("Other Income", "plus-circle", "#898781"), ] diff --git a/frontend/package.json b/frontend/package.json index e328f11..5bac112 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "aurum-frontend", "private": true, - "version": "0.23.0", + "version": "0.23.1", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/categories/CategoryList.tsx b/frontend/src/components/categories/CategoryList.tsx index d1a5de7..eceac5a 100644 --- a/frontend/src/components/categories/CategoryList.tsx +++ b/frontend/src/components/categories/CategoryList.tsx @@ -1,4 +1,5 @@ import { Pencil, Trash2 } from "lucide-react"; +import { translateCategoryName } from "@/lib/categoryLabels"; import { getCategoryIcon } from "@/lib/icons"; import { useTranslation } from "@/lib/i18n"; import type { Category } from "@/types"; @@ -30,7 +31,7 @@ export function CategoryList({ items, onEdit, onDelete }: CategoryListProps) { - {category.name} + {translateCategoryName(category.name)} {category.is_default && ( {t("category.defaultBadge")} diff --git a/frontend/src/lib/categoryLabels.ts b/frontend/src/lib/categoryLabels.ts index 3b1381d..828163b 100644 --- a/frontend/src/lib/categoryLabels.ts +++ b/frontend/src/lib/categoryLabels.ts @@ -1,10 +1,10 @@ import { t, type TranslationKey } from "@/lib/i18n"; // Maps the exact seeded English category name (backend/app/db/seed.py) to -// its translation key. There's no category-management UI yet, so every -// category currently in the database is one of these — anything that -// doesn't match (a renamed default, or a future custom category) falls -// through unchanged. +// its translation key, so the fixed default set reads in the user's chosen +// language regardless of what the DB literally stores. Categories created +// through the category-management UI (CategoriesPage) aren't in this map — +// their name is whatever the user typed and is shown as-is. const DEFAULT_CATEGORY_KEYS: Record = { "Housing & Utilities": "category.housingUtilities", Groceries: "category.groceries", @@ -18,6 +18,10 @@ const DEFAULT_CATEGORY_KEYS: Record = { Freelance: "category.freelance", Investments: "category.investments", Gifts: "category.gifts", + "Business Income": "category.businessIncome", + "Rental Income": "category.rentalIncome", + Benefits: "category.benefits", + "Item Sales": "category.itemSales", "Other Income": "category.otherIncome", }; diff --git a/frontend/src/lib/i18n.ts b/frontend/src/lib/i18n.ts index 5b1a926..9a5df61 100644 --- a/frontend/src/lib/i18n.ts +++ b/frontend/src/lib/i18n.ts @@ -324,11 +324,10 @@ const ru = { "cashFlow.net": "Баланс", "cashFlow.noData": "Нет данных за выбранный период.", - // Default seeded categories (backend/app/db/seed.py) — there's no - // category-management UI yet, so every category currently in the - // database is one of these; translateCategoryName() matches on the exact - // seeded English name and falls through unchanged for anything else - // (a renamed default, or a future custom category). + // Default seeded categories (backend/app/db/seed.py) — translateCategoryName() + // matches on the exact seeded English name and falls through unchanged + // for anything else (a renamed default, or a custom category added via + // the category-management UI). "category.housingUtilities": "Жильё и коммуналка", "category.groceries": "Продукты", "category.diningOut": "Кафе и рестораны", @@ -341,6 +340,10 @@ const ru = { "category.freelance": "Фриланс", "category.investments": "Инвестиции", "category.gifts": "Подарки", + "category.businessIncome": "Доход от бизнеса", + "category.rentalIncome": "Сдача недвижимости", + "category.benefits": "Пособия и соцвыплаты", + "category.itemSales": "Продажа личных вещей", "category.otherIncome": "Прочий доход", "months.jan": "Янв", @@ -689,6 +692,10 @@ const en: Record = { "category.freelance": "Freelance", "category.investments": "Investments", "category.gifts": "Gifts", + "category.businessIncome": "Business Income", + "category.rentalIncome": "Rental Income", + "category.benefits": "Benefits", + "category.itemSales": "Item Sales", "category.otherIncome": "Other Income", "months.jan": "Jan", diff --git a/frontend/src/lib/icons.tsx b/frontend/src/lib/icons.tsx index d2e6970..75a6942 100644 --- a/frontend/src/lib/icons.tsx +++ b/frontend/src/lib/icons.tsx @@ -11,8 +11,10 @@ import { Gem, Gift, GraduationCap, + HandCoins, HeartPulse, Home, + Key, MoreHorizontal, Package, Plane, @@ -26,6 +28,7 @@ import { Smartphone, Sofa, Sparkles, + Tag, TrendingUp, Truck, Utensils, @@ -71,6 +74,9 @@ const ICON_MAP: Record = { smartphone: Smartphone, sofa: Sofa, sparkles: Sparkles, + tag: Tag, + "hand-coins": HandCoins, + key: Key, truck: Truck, // lucide-react dropped brand/trademarked glyphs (no "Youtube" icon) — a // generic video-camera icon is the closest available stand-in.