import 'package:flutter/material.dart'; /// Définition des couleurs d'accent disponibles pour la personnalisation. class AppAccentColor { final String id; final String name; final Color color; final Color lightColor; final Color darkColor; final IconData icon; const AppAccentColor({ required this.id, required this.name, required this.color, required this.lightColor, required this.darkColor, required this.icon, }); static const AppAccentColor blue = AppAccentColor( id: 'blue', name: 'Bleu Cobalt', color: Color(0xFF2563EB), lightColor: Color(0xFF60A5FA), darkColor: Color(0xFF1D4ED8), icon: Icons.lens, ); static const AppAccentColor red = AppAccentColor( id: 'red', name: 'Rouge Cible', color: Color(0xFFDC2626), lightColor: Color(0xFFF87171), darkColor: Color(0xFFB91C1C), icon: Icons.lens, ); static const AppAccentColor green = AppAccentColor( id: 'green', name: 'Vert Viseur', color: Color(0xFF10B981), lightColor: Color(0xFF34D399), darkColor: Color(0xFF059669), icon: Icons.lens, ); static const AppAccentColor orange = AppAccentColor( id: 'orange', name: 'Orange Ambre', color: Color(0xFFFF6D00), lightColor: Color(0xFFFF9E40), darkColor: Color(0xFFD84315), icon: Icons.lens, ); static const AppAccentColor purple = AppAccentColor( id: 'purple', name: 'Violet Cyber', color: Color(0xFF8B5CF6), lightColor: Color(0xFFA78BFA), darkColor: Color(0xFF6D28D9), icon: Icons.lens, ); static const AppAccentColor cyan = AppAccentColor( id: 'cyan', name: 'Cyan Néon', color: Color(0xFF06B6D4), lightColor: Color(0xFF67E8F9), darkColor: Color(0xFF0E7490), icon: Icons.lens, ); static const AppAccentColor gold = AppAccentColor( id: 'gold', name: 'Or Compétition', color: Color(0xFFF59E0B), lightColor: Color(0xFFFBBF24), darkColor: Color(0xFFD97706), icon: Icons.lens, ); static const List allAccents = [ blue, red, green, orange, purple, cyan, gold, ]; static AppAccentColor fromId(String? id) { return allAccents.firstWhere( (a) => a.id == id, orElse: () => blue, ); } } /// Système de design et thème de l'application Bully. class AppTheme { AppTheme._(); // Accents par défaut (compatibilité statique) static const Color primaryColor = Color(0xFF2563EB); static const Color primaryLight = Color(0xFF60A5FA); static const Color primaryDark = Color(0xFF1D4ED8); static const Color secondaryColor = Color(0xFF10B981); static const Color secondaryDark = Color(0xFF059669); static const Color accentBlue = Color(0xFF0EA5E9); static const Color accentGold = Color(0xFFFFB300); static const Color errorColor = Color(0xFFEF4444); static const Color warningColor = Color(0xFFF59E0B); static const Color successColor = Color(0xFF10B981); // Palette Thème Sombre (Standard Stand de Tir) static const Color darkBackground = Color(0xFF0D1219); static const Color darkSurface = Color(0xFF161E28); static const Color darkSurfaceElevated = Color(0xFF1E2836); static const Color darkSurfaceVariant = Color(0xFF253243); static const Color darkBorder = Color(0xFF2C3B4E); static const Color darkBorderLight = Color(0xFF3B4D65); static const Color darkTextPrimary = Color(0xFFF1F5F9); static const Color darkTextSecondary = Color(0xFF94A3B8); static const Color darkTextMuted = Color(0xFF64748B); // Palette Thème Clair static const Color lightBackground = Color(0xFFF8FAFC); static const Color lightSurface = Color(0xFFFFFFFF); static const Color lightSurfaceElevated = Color(0xFFFFFFFF); static const Color lightSurfaceVariant = Color(0xFFF1F5F9); static const Color lightBorder = Color(0xFFE2E8F0); static const Color lightTextPrimary = Color(0xFF0F172A); static const Color lightTextSecondary = Color(0xFF64748B); static const Color lightTextMuted = Color(0xFF94A3B8); // Compatibilité ascendante static const Color backgroundColor = lightBackground; static const Color surfaceColor = lightSurface; static const Color textPrimary = lightTextPrimary; static const Color textSecondary = lightTextSecondary; // Couleurs des impacts pour l'overlay static const Color impactColor = Color(0xFFFF3D00); static const Color impactOutlineColor = Color(0xFFFFFFFF); static const Color groupingCenterColor = Color(0xFF00E5FF); static const Color groupingCircleColor = Color(0x4D00E5FF); // Couleurs des zones de score cibles concentriques static const List zoneColors = [ Color(0xFFFFB300), // Zone 10 - Or Color(0xFFFFCA28), // Zone 9 Color(0xFFFF5722), // Zone 8 Color(0xFFFF7043), // Zone 7 Color(0xFF29B6F6), // Zone 6 Color(0xFF4FC3F7), // Zone 5 Color(0xFF66BB6A), // Zone 4 Color(0xFF81C784), // Zone 3 Color(0xFFFFFFFF), // Zone 2 Color(0xFFE0E0E0), // Zone 1 ]; static ThemeData get lightTheme => buildLightTheme(AppAccentColor.blue); static ThemeData get darkTheme => buildDarkTheme(AppAccentColor.blue); static ThemeData buildLightTheme(AppAccentColor accent) { final activePrimary = accent.color; return ThemeData( useMaterial3: true, brightness: Brightness.light, colorScheme: ColorScheme.light( primary: activePrimary, secondary: secondaryColor, surface: lightSurface, error: errorColor, onPrimary: Colors.white, onSecondary: Colors.white, onSurface: lightTextPrimary, onError: Colors.white, outline: lightBorder, ), scaffoldBackgroundColor: lightBackground, cardColor: lightSurface, appBarTheme: const AppBarTheme( elevation: 0, centerTitle: true, backgroundColor: lightSurface, foregroundColor: lightTextPrimary, surfaceTintColor: Colors.transparent, titleTextStyle: TextStyle( fontSize: 18, fontWeight: FontWeight.w700, color: lightTextPrimary, letterSpacing: 0.3, ), ), cardTheme: CardThemeData( elevation: 0, color: lightSurface, surfaceTintColor: Colors.transparent, margin: EdgeInsets.zero, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: const BorderSide(color: lightBorder, width: 1), ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( elevation: 0, backgroundColor: activePrimary, foregroundColor: Colors.white, minimumSize: const Size(double.infinity, 50), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), textStyle: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, letterSpacing: 0.2, ), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: lightTextPrimary, minimumSize: const Size(double.infinity, 50), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), side: const BorderSide(color: lightBorder, width: 1.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), textStyle: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, ), ), ), chipTheme: ChipThemeData( backgroundColor: lightSurfaceVariant, selectedColor: activePrimary.withValues(alpha: 0.15), labelStyle: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: lightTextPrimary, ), secondaryLabelStyle: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: activePrimary, ), side: const BorderSide(color: lightBorder, width: 1), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: lightSurfaceVariant, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: lightBorder), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: lightBorder), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: activePrimary, width: 1.8), ), labelStyle: const TextStyle(color: lightTextSecondary), hintStyle: const TextStyle(color: lightTextMuted), ), dividerTheme: const DividerThemeData( color: lightBorder, thickness: 1, space: 24, ), floatingActionButtonTheme: FloatingActionButtonThemeData( backgroundColor: activePrimary, foregroundColor: Colors.white, elevation: 3, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(16)), ), ), ); } static ThemeData buildDarkTheme(AppAccentColor accent) { final activePrimary = accent.color; return ThemeData( useMaterial3: true, brightness: Brightness.dark, colorScheme: ColorScheme.dark( primary: activePrimary, secondary: secondaryColor, surface: darkSurface, error: errorColor, onPrimary: Colors.white, onSecondary: Colors.white, onSurface: darkTextPrimary, onError: Colors.white, outline: darkBorder, ), scaffoldBackgroundColor: darkBackground, cardColor: darkSurface, appBarTheme: const AppBarTheme( elevation: 0, centerTitle: true, backgroundColor: darkBackground, foregroundColor: darkTextPrimary, surfaceTintColor: Colors.transparent, titleTextStyle: TextStyle( fontSize: 18, fontWeight: FontWeight.w700, color: darkTextPrimary, letterSpacing: 0.3, ), ), cardTheme: CardThemeData( elevation: 0, color: darkSurface, surfaceTintColor: Colors.transparent, margin: EdgeInsets.zero, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: const BorderSide(color: darkBorder, width: 1), ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( elevation: 0, backgroundColor: activePrimary, foregroundColor: Colors.white, minimumSize: const Size(double.infinity, 50), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), textStyle: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, letterSpacing: 0.2, ), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: darkTextPrimary, minimumSize: const Size(double.infinity, 50), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), side: const BorderSide(color: darkBorder, width: 1.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), textStyle: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, ), ), ), chipTheme: ChipThemeData( backgroundColor: darkSurfaceElevated, selectedColor: activePrimary.withValues(alpha: 0.2), labelStyle: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: darkTextPrimary, ), secondaryLabelStyle: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: activePrimary, ), side: const BorderSide(color: darkBorder, width: 1), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: darkSurfaceElevated, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: darkBorder), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: darkBorder), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: activePrimary, width: 1.8), ), labelStyle: const TextStyle(color: darkTextSecondary), hintStyle: const TextStyle(color: darkTextMuted), ), dividerTheme: const DividerThemeData( color: darkBorder, thickness: 1, space: 24, ), floatingActionButtonTheme: FloatingActionButtonThemeData( backgroundColor: activePrimary, foregroundColor: Colors.white, elevation: 3, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(16)), ), ), ); } }