From 8ff429a363c7e1e046fdc3aa6d6518cdaad80635 Mon Sep 17 00:00:00 2001 From: Ermolz <00ermzahar@gmail.com> Date: Wed, 24 Jun 2026 17:35:46 +0300 Subject: [PATCH 1/5] Add Currencies sheet, per-currency summary, and currency filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Entity: @entities/currency Introduced a first-class `Currency` type with fields `id`, `code`, `name`, `symbol`, `decimalDigits`, `isDefault`, `isEnabled`. Added `getDefaultCurrencies()` — a seed list of 10 currencies (UAH, USD, EUR, RUB, PLN, GBP, CHF, CAD, TRY, JPY) used only for initial sheet population and as an offline fallback. The sheet remains the source of truth; adding a new currency there requires no code change. ## Feature: @features/manage-currencies New feature following the same pattern as manage-categories / manage-containers: - `currency-row.mapper.ts` — `mapCurrencyToRow` / `mapRowToCurrency` with tolerant parsing: blank `decimalDigits` defaults to 2, booleans are case-insensitive (`true` / `TRUE` / `1`), missing name/symbol fall back to the code itself. - `manage-currencies.service.ts` — `readCurrencies()` reads the Currencies sheet when Google is connected; falls back to defaults when the sheet is missing or the user is offline. - `useCurrencies()` — React hook that seeds state with defaults immediately so the UI is never empty on first render. - `CurrencySelect` — replaces every free-text currency `` with a `` in `ManageContainersModal` with `` for consistency. ## calculateTransactionSummary (TASK-5) Rewrote to return `CurrencySummary[]` grouped by currency code instead of a single `TransactionSummary` object. Uses a `Map` so amounts of different currencies are never added together. 100 USD + 100 UAH now correctly produces two separate entries. Insertion order of first appearance is preserved. ## DashboardPage (TASK-6) Removed `activeTransactions[0]?.currency` fallback that labelled a mixed-currency sum with the first transaction's currency. The three summary cards (Income / Expense / Balance) now render a `