Skip to Content

Projet Niv. 4 — Dépenses

Le brief : le tracker de dépenses personnel — saisie en 3 secondes, catégories, budgets mensuels, graphiques, export CSV. Le projet DATA : votre SQL passe au niveau supérieur, et Drizzle entre en scène (le verdict du ch. 8.4 appliqué).

Ce que vous allez pratiquer

Le schéma multi-tables avec Drizzle (comptes, catégories, transactions, budgets — le seuil du ch. 8.4 est franchi), les agrégats sérieux (par mois, par catégorie, vs budget), victory-native pour les graphiques, l’export CSV (ch. 9.5), et le pavé numérique custom. Chapitres liés : 8.4, 8.3, 9.5, 4.5.

Les features

  1. La saisie éclair : ouvrir → pavé numérique custom → montant → catégorie (grille d’emojis) → fait. 3 secondes, PAS de formulaire.
  2. Catégories (CRUD, emoji, couleur) et comptes (espèces/carte — simple).
  3. Le mois en cours : total, par catégorie, la jauge vs budget (ProgressBar du kit !).
  4. Les graphiques : barres des 6 derniers mois, donut par catégorie (victory-native).
  5. Budgets mensuels par catégorie, avec l’alerte de dépassement (notification locale).
  6. Export CSV du mois/de l’année (fichier + share sheet).

L’architecture recommandée

  • Drizzle d’entrée (la grille du ch. 8.4 : 4+ tables, schéma évolutif → l’ORM gagne) :
// db/schema.ts — l'esquisse categories: { id, name, emoji, color } accounts: { id, name } transactions: { id, amountCents, categoryId, accountId, note?, spentAt } // ← CENTIMES budgets: { id, categoryId, monthKey /* '2026-07' */, limitCents }

Les centimes en INTEGER — la règle d’or de l’argent (jamais de flottants : 0.1+0.2 ≠ 0.3 ; l’affichage divise par 100 au dernier moment, dans une fonction formatEuros de lib/).

  • Les requêtes du dashboard : GROUP BY strftime('%Y-%m', …) pour les mois, la jointure budgets↔dépenses du mois (LEFT JOIN — les catégories sans budget existent), et le monthKey textuel qui esquive les pièges de fuseaux (le pattern du jour local, généralisé au mois).
  • Le pavé numérique custom : une grille de Pressable du kit (les claviers système sont trop lents pour la « saisie éclair ») — votre premier composant d’input original.
  • victory-native (XL, sur Skia) pour les deux graphiques — l’occasion d’évaluer une lib selon les critères du ch. 1.4 avant adoption.

Les jalons

  1. Schéma Drizzle + migrations générées + seed de démo (3 mois de données réalistes).
  2. La saisie éclair (pavé + grille de catégories) — chronométrez-la réellement.
  3. Le dashboard du mois (agrégats + jauges budgets).
  4. Les graphiques (6 mois + donut).
  5. Budgets + l’alerte de dépassement (déclenchée À LA SAISIE qui dépasse).
  6. Export CSV + share + APK.

Critères de réussite

  • La saisie d’une dépense prend < 5 s montre en main (le critère produit n°1)
  • 5 000 transactions seedées : dashboard et graphiques instantanés (agrégats en SQL, pas en JS)
  • 12,34 € + 45,67 € = 58,01 € EXACTEMENT (centimes entiers, pas de 58.009999)
  • Le CSV s’ouvre proprement dans un tableur (séparateur, encodage UTF-8 BOM pour Excel, montants avec virgule locale — les VRAIS détails d’un export)
  • Le mois bascule correctement le 1er (monthKey local)
  • APK + VOS dépenses réelles pendant un mois

Pièges connus

  • Le CSV français : Excel attend ; comme séparateur et une virgule décimale — l’option « séparateur » dans l’écran d’export est le vrai réglage utile (et le BOM UTF-8 pour les accents).
  • Le donut « autres » : au-delà de 6 catégories, regroupez — un donut à 14 tranches est illisible (le design de données fait partie du projet).
  • L’alerte budget : à la SAISIE (synchrone, fiable), pas par vérification périodique en arrière-plan (complexité sans bénéfice — Android limite le background de toute façon).

💡 L’upgrade : les transactions récurrentes (loyer le 1er — un champ recurrence + la matérialisation au premier lancement du mois : un vrai problème de conception), et le widget de saisie sur l’écran d’accueil (module natif — le boss final du hors-SDK).