feat(balance): add i18n keys + CHANGELOG entry for snapshot editor
All checks were successful
PR Check / rust (push) Successful in 21m48s
PR Check / frontend (push) Successful in 2m19s

i18n FR/EN under balance.snapshot.* — page (titles, date label and
immutability notice, total, prefill, save/create/delete buttons),
editor (empty state), line (placeholder + a11y label), delete
(double-confirm modal copy). Five new error codes added to
balance.errors.* (snapshot_date_required, snapshot_date_taken,
snapshot_not_found, snapshot_value_invalid, snapshot_priced_unsupported).

Adds common.back so the SnapshotEditPage back arrow has a localized title.

CHANGELOG entries for #146 under [Unreleased] in both EN and FR.

Refs #146

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
le king fu 2026-04-25 14:49:41 -04:00
parent fdc6cc6c38
commit 8f5cc71707
4 changed files with 78 additions and 4 deletions

View file

@ -3,6 +3,7 @@
## [Non publié] ## [Non publié]
### Ajouté ### Ajouté
- **Bilan — éditeur de snapshot (type simple)** (route `/balance/snapshot`) : deuxième tranche de la feature *Bilan*. La nouvelle page permet de créer ou modifier un snapshot daté de votre patrimoine : choisissez une date (par défaut aujourd'hui), saisissez la valeur de chaque compte actif groupé par catégorie, puis enregistrez. Le mode est piloté par le paramètre `?date=` de l'URL — si un snapshot existe déjà à cette date, la page bascule automatiquement en mode édition (la contrainte UNIQUE sur `balance_snapshots.snapshot_date` garantit un snapshot par jour). La date d'un snapshot existant est immuable : pour la changer, supprimez puis recréez. Un bouton *Pré-remplir depuis le précédent* copie les valeurs du snapshot antérieur le plus récent (comptes simples uniquement — les comptes cotés seront pris en charge quand l'éditeur coté arrivera). Un bouton *Supprimer* affiche une modal de double confirmation qui exige de retaper la date du snapshot avant d'activer l'action destructive. Seules les valeurs de type simple sont acceptées à ce stade (`quantity` et `unit_price` sont laissés `NULL`) ; l'éditeur coté (quantité × prix unitaire + récupération de prix) arrivera dans une prochaine version. Nouveau hook `useSnapshotEditor` (`useReducer` couvrant tout le cycle de vie) et deux nouveaux composants `SnapshotEditor` + `SnapshotLineRow`. i18n FR/EN sous `balance.snapshot.*` (#146)
- **Bilan — fondations du schéma et page Comptes** (route `/balance/accounts`) : première tranche de la nouvelle feature *Bilan*. La migration SQL v9 introduit 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) avec 7 index et seede 7 catégories standard — Encaisse, CELI, REER, Fonds commun, Autre (type simple) + Action et Cryptomonnaie (type coté). La colonne `currency` est verrouillée à `CAD` via une contrainte CHECK au MVP — le support multi-devises arrivera plus tard. La nouvelle page expose deux onglets : *Comptes* (CRUD complet sur les comptes de l'utilisateur, archivage soft plutôt que suppression dure pour préserver les snapshots historiques) et *Catégories* (renommer une catégorie, créer des catégories de type simple, supprimer celles créées par l'utilisateur — les catégories standard sont protégées). Couverture i18n FR/EN complète sous `balance.*`. Snapshots, transferts, rendements et price-fetching premium arriveront dans les prochaines issues ; pour l'instant la route est accessible directement par URL (pas encore d'entrée sidebar) (#138) - **Bilan — fondations du schéma et page Comptes** (route `/balance/accounts`) : première tranche de la nouvelle feature *Bilan*. La migration SQL v9 introduit 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) avec 7 index et seede 7 catégories standard — Encaisse, CELI, REER, Fonds commun, Autre (type simple) + Action et Cryptomonnaie (type coté). La colonne `currency` est verrouillée à `CAD` via une contrainte CHECK au MVP — le support multi-devises arrivera plus tard. La nouvelle page expose deux onglets : *Comptes* (CRUD complet sur les comptes de l'utilisateur, archivage soft plutôt que suppression dure pour préserver les snapshots historiques) et *Catégories* (renommer une catégorie, créer des catégories de type simple, supprimer celles créées par l'utilisateur — les catégories standard sont protégées). Couverture i18n FR/EN complète sous `balance.*`. Snapshots, transferts, rendements et price-fetching premium arriveront dans les prochaines issues ; pour l'instant la route est accessible directement par URL (pas encore d'entrée sidebar) (#138)
### Corrigé ### Corrigé

View file

@ -3,6 +3,7 @@
## [Unreleased] ## [Unreleased]
### Added ### Added
- **Balance sheet — snapshot editor (simple kind)** (route `/balance/snapshot`): second slice of the *Bilan* feature. The new page lets you create or edit a dated snapshot of your balance: pick a date (defaulting to today), enter the value of each active account grouped by category, and save. The mode is driven by the `?date=` query parameter — when a snapshot already exists at that date the page automatically flips into edit mode (the underlying `balance_snapshots.snapshot_date` UNIQUE constraint guarantees one snapshot per day). The date of an existing snapshot is immutable: to change it, delete the snapshot and create a new one. A *Prefill from previous snapshot* button copies values from the most recent earlier snapshot (simple-kind accounts only — priced accounts will be handled when the priced editor lands in a later release). A *Delete* button surfaces a double-confirmation modal that requires retyping the snapshot date before the destructive action is enabled. Only simple-kind values are accepted at this stage (`quantity` and `unit_price` are kept `NULL`); the priced editor (quantity × unit price + price fetch) ships in a later release. New `useSnapshotEditor` hook (scoped `useReducer` covering the full lifecycle) and two new components `SnapshotEditor` + `SnapshotLineRow`. FR/EN i18n under `balance.snapshot.*` (#146)
- **Balance sheet — schema foundation and accounts page** (route `/balance/accounts`): first slice of the upcoming *Bilan* feature. New SQL migration v9 introduces 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) with 7 indexes and seeds 7 standard categories — Cash, TFSA, RRSP, Mutual Fund, Other (simple kind) plus Stock and Crypto (priced kind). The `currency` column is hardcoded to `CAD` via a CHECK constraint at the MVP — multi-currency support will come in a later release. The new accounts page exposes two tabs: *Accounts* (full CRUD over the user's holdings, soft-archive instead of hard delete to preserve historic snapshots) and *Categories* (rename any category, create simple-kind ones, delete user-created ones — seeded categories are protected). The full FR/EN i18n coverage uses keys under `balance.*`. Snapshots, transfers, returns and the price-fetching premium remain to ship in upcoming issues; for now the route is reachable directly via URL (no sidebar entry yet) (#138) - **Balance sheet — schema foundation and accounts page** (route `/balance/accounts`): first slice of the upcoming *Bilan* feature. New SQL migration v9 introduces 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) with 7 indexes and seeds 7 standard categories — Cash, TFSA, RRSP, Mutual Fund, Other (simple kind) plus Stock and Crypto (priced kind). The `currency` column is hardcoded to `CAD` via a CHECK constraint at the MVP — multi-currency support will come in a later release. The new accounts page exposes two tabs: *Accounts* (full CRUD over the user's holdings, soft-archive instead of hard delete to preserve historic snapshots) and *Categories* (rename any category, create simple-kind ones, delete user-created ones — seeded categories are protected). The full FR/EN i18n coverage uses keys under `balance.*`. Snapshots, transfers, returns and the price-fetching premium remain to ship in upcoming issues; for now the route is reachable directly via URL (no sidebar entry yet) (#138)
### Fixed ### Fixed

View file

@ -981,7 +981,8 @@
"darkMode": "Dark mode", "darkMode": "Dark mode",
"lightMode": "Light mode", "lightMode": "Light mode",
"close": "Close", "close": "Close",
"underConstruction": "Under construction" "underConstruction": "Under construction",
"back": "Back"
}, },
"license": { "license": {
"title": "License", "title": "License",
@ -1535,6 +1536,36 @@
"stock": "Stock", "stock": "Stock",
"crypto": "Crypto" "crypto": "Crypto"
}, },
"snapshot": {
"page": {
"newTitle": "New snapshot",
"editTitle": "Edit snapshot",
"dateLabel": "Snapshot date",
"dateImmutable": "An existing snapshot date cannot be changed. To change the date, delete this snapshot and create a new one.",
"total": "Entered total",
"noAccounts": "You need to create at least one balance account first.",
"goToAccounts": "Go to accounts",
"prefill": "Prefill from previous",
"prefillTooltip": "Copy values from the snapshot dated {{date}}",
"prefillNoPrevious": "No earlier snapshot available.",
"save": "Save",
"create": "Create snapshot",
"delete": "Delete this snapshot"
},
"editor": {
"empty": "No active accounts. Create an account before entering a snapshot."
},
"line": {
"valuePlaceholder": "0.00",
"valueLabel": "Value for {{account}}"
},
"delete": {
"title": "Delete this snapshot?",
"body": "This permanently deletes the snapshot dated {{date}} and all its lines. To confirm, retype the date below.",
"confirmLabel": "Retype the date {{date}} to confirm",
"confirm": "Delete permanently"
}
},
"errors": { "errors": {
"currency_unsupported": "Only CAD is supported at the MVP.", "currency_unsupported": "Only CAD is supported at the MVP.",
"category_seed_protected": "Standard categories cannot be deleted.", "category_seed_protected": "Standard categories cannot be deleted.",
@ -1542,7 +1573,12 @@
"category_not_found": "Category not found.", "category_not_found": "Category not found.",
"account_not_found": "Account not found.", "account_not_found": "Account not found.",
"name_required": "Name is required.", "name_required": "Name is required.",
"kind_invalid": "Invalid category kind." "kind_invalid": "Invalid category kind.",
"snapshot_date_required": "A date in YYYY-MM-DD format is required.",
"snapshot_date_taken": "A snapshot already exists at that date — edit it instead of creating a new one.",
"snapshot_not_found": "Snapshot not found.",
"snapshot_value_invalid": "An entered value is not a valid number.",
"snapshot_priced_unsupported": "Priced accounts (stocks/crypto) will be supported in a future release."
} }
} }
} }

View file

@ -981,7 +981,8 @@
"darkMode": "Mode sombre", "darkMode": "Mode sombre",
"lightMode": "Mode clair", "lightMode": "Mode clair",
"close": "Fermer", "close": "Fermer",
"underConstruction": "En construction" "underConstruction": "En construction",
"back": "Retour"
}, },
"license": { "license": {
"title": "Licence", "title": "Licence",
@ -1535,6 +1536,36 @@
"stock": "Action", "stock": "Action",
"crypto": "Cryptomonnaie" "crypto": "Cryptomonnaie"
}, },
"snapshot": {
"page": {
"newTitle": "Nouveau snapshot",
"editTitle": "Modifier le snapshot",
"dateLabel": "Date du snapshot",
"dateImmutable": "La date d'un snapshot existant ne peut pas être modifiée. Pour changer la date, supprimez ce snapshot et créez-en un nouveau.",
"total": "Total saisi",
"noAccounts": "Vous devez d'abord créer au moins un compte de bilan.",
"goToAccounts": "Aller aux comptes",
"prefill": "Pré-remplir depuis le précédent",
"prefillTooltip": "Copier les valeurs du snapshot du {{date}}",
"prefillNoPrevious": "Aucun snapshot antérieur disponible.",
"save": "Enregistrer",
"create": "Créer le snapshot",
"delete": "Supprimer ce snapshot"
},
"editor": {
"empty": "Aucun compte actif. Créez un compte avant de saisir un snapshot."
},
"line": {
"valuePlaceholder": "0,00",
"valueLabel": "Valeur pour {{account}}"
},
"delete": {
"title": "Supprimer ce snapshot ?",
"body": "Cette action supprime définitivement le snapshot du {{date}} et toutes ses lignes. Pour confirmer, retapez la date ci-dessous.",
"confirmLabel": "Retapez la date {{date}} pour confirmer",
"confirm": "Supprimer définitivement"
}
},
"errors": { "errors": {
"currency_unsupported": "Seul le CAD est supporté au MVP.", "currency_unsupported": "Seul le CAD est supporté au MVP.",
"category_seed_protected": "Les catégories standard ne peuvent pas être supprimées.", "category_seed_protected": "Les catégories standard ne peuvent pas être supprimées.",
@ -1542,7 +1573,12 @@
"category_not_found": "Catégorie introuvable.", "category_not_found": "Catégorie introuvable.",
"account_not_found": "Compte introuvable.", "account_not_found": "Compte introuvable.",
"name_required": "Le nom est obligatoire.", "name_required": "Le nom est obligatoire.",
"kind_invalid": "Type de catégorie invalide." "kind_invalid": "Type de catégorie invalide.",
"snapshot_date_required": "Une date au format AAAA-MM-JJ est obligatoire.",
"snapshot_date_taken": "Un snapshot existe déjà à cette date — modifiez-le au lieu d'en créer un nouveau.",
"snapshot_not_found": "Snapshot introuvable.",
"snapshot_value_invalid": "Une valeur saisie n'est pas un nombre valide.",
"snapshot_priced_unsupported": "Les comptes cotés (actions/crypto) seront supportés dans une prochaine version."
} }
} }
} }