import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; // ── Couleurs custom ─────────────────────────────────────────────────────────── // Couleurs custom pour le thème vert sage (Light Theme) const kSurfaceBg = Color(0xFFEDF1E7); // Fond vert très clair (de l'image) const kSurfaceCard = Color(0xFFF6F9F6); // Fond de carte off-white const kSurfaceElevated = Color(0xFFCAD8C3); // Sage green pour les surfaces surélevées const kGreenAccent = Color(0xFF3B5238); // Vert sombre pour le texte et les accents const kGreenAccentDim = Color(0xFF556B52); const kRedAccent = Color(0xFFBA1A1A); // Rouge d'erreur Material 3 const kTextPrimary = Color(0xFF191D17); // Texte principal sombre const kTextSecondary = Color(0xFF43493E); // Texte secondaire gris-vert const kDivider = Color(0xFFDDE4D7); // Séparateurs clairs final ThemeData ynabTheme = ThemeData( useMaterial3: true, brightness: Brightness.light, colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFFCAD8C3), brightness: Brightness.light, surface: kSurfaceBg, primary: kGreenAccent, secondary: kGreenAccentDim, error: kRedAccent, onSurface: kTextPrimary, onSurfaceVariant: kTextSecondary, outline: kDivider, ), scaffoldBackgroundColor: kSurfaceBg, cardTheme: CardThemeData( color: kSurfaceCard, elevation: 0, // M3 utilise plutôt les tonalités et outline qu'une grosse élévation shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: kDivider, width: 1), ), clipBehavior: Clip.antiAlias, ), navigationBarTheme: NavigationBarThemeData( backgroundColor: kSurfaceCard, indicatorColor: const Color(0xFFCAD8C3), iconTheme: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return const IconThemeData(color: Color(0xFF191D17)); } return const IconThemeData(color: Color(0xFF43493E)); }), labelTextStyle: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return GoogleFonts.inter( color: const Color(0xFF191D17), fontSize: 12, fontWeight: FontWeight.w600, ); } return GoogleFonts.inter( color: const Color(0xFF43493E), fontSize: 12, ); }), ), appBarTheme: AppBarTheme( backgroundColor: kSurfaceBg, elevation: 0, scrolledUnderElevation: 1, centerTitle: false, titleTextStyle: GoogleFonts.inter( fontSize: 20, fontWeight: FontWeight.w600, color: kTextPrimary, ), iconTheme: const IconThemeData(color: kTextSecondary), ), textTheme: GoogleFonts.interTextTheme( ThemeData.light().textTheme.copyWith( headlineLarge: const TextStyle(color: kTextPrimary), headlineMedium: const TextStyle(color: kTextPrimary), headlineSmall: const TextStyle(color: kTextPrimary), titleLarge: const TextStyle(color: kTextPrimary), titleMedium: const TextStyle(color: kTextPrimary), titleSmall: const TextStyle(color: kTextPrimary), bodyLarge: const TextStyle(color: kTextPrimary), bodyMedium: const TextStyle(color: kTextPrimary, fontSize: 14), bodySmall: const TextStyle(color: kTextSecondary, fontSize: 12), labelLarge: const TextStyle(color: kTextPrimary), labelMedium: const TextStyle(color: kTextSecondary), labelSmall: const TextStyle(color: kTextSecondary), ), ), dividerTheme: const DividerThemeData(color: kDivider, thickness: 1), floatingActionButtonTheme: FloatingActionButtonThemeData( backgroundColor: const Color(0xFFCAD8C3), foregroundColor: kTextPrimary, elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: kSurfaceCard, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: kDivider), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: kGreenAccent, width: 1.5), ), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), ), bottomSheetTheme: const BottomSheetThemeData( backgroundColor: kSurfaceCard, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), ), sliderTheme: SliderThemeData( activeTrackColor: kGreenAccent, thumbColor: kGreenAccent, inactiveTrackColor: kDivider, overlayColor: kGreenAccent.withAlpha(30), ), dialogTheme: DialogThemeData( backgroundColor: kSurfaceCard, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), ), ); final ThemeData ynabDarkTheme = ThemeData( useMaterial3: true, brightness: Brightness.dark, colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFFCAD8C3), brightness: Brightness.dark, ), ); // Utils String formatCurrency(double amount) { final sign = amount < 0 ? '-' : ''; final abs = amount.abs(); final parts = abs.toStringAsFixed(2).split('.'); final intPart = parts[0]; final decPart = parts[1]; final buf = StringBuffer(); int count = 0; for (int i = intPart.length - 1; i >= 0; i--) { if (count > 0 && count % 3 == 0) buf.write(' '); buf.write(intPart[i]); count++; } final formatted = '${buf.toString().split('').reversed.join()},$decPart'; return '$sign$formatted €'; } String formatCurrencyShort(double amount) { final abs = amount.abs(); if (abs >= 1000000) return '${(abs / 1000000).toStringAsFixed(1)} M'; if (abs >= 1000) return '${(abs / 1000).toStringAsFixed(1)} k'; return '${abs.toStringAsFixed(2)} €'; }