From c4d4261afcc4a8ce6a163bd57a028a2bbf0b228e Mon Sep 17 00:00:00 2001 From: Nilanjan Chakrabarti Date: Wed, 6 Aug 2025 17:26:25 +0530 Subject: [PATCH] Theme --- lib/app.dart | 363 ++++-------------- lib/config/theme_controller.dart | 28 ++ lib/config/theme_mode_controller.dart | 40 ++ lib/config/theme_type.dart | 6 + lib/config/themes.dart | 353 +++++------------ lib/di/injection.dart | 8 + .../screens/account_statement_screen.dart | 8 +- .../auth/controllers/theme_cubit.dart | 50 +++ .../auth/controllers/theme_state.dart | 27 ++ lib/features/auth/screens/login_screen.dart | 16 +- lib/features/auth/screens/mpin_screen.dart | 2 +- lib/features/auth/screens/welcome_screen.dart | 12 +- .../screens/add_beneficiary_screen.dart | 22 +- .../screens/manage_beneficiaries_screen.dart | 8 +- .../card/screens/block_card_screen.dart | 14 +- .../card_pin_change_details_screen.dart | 12 +- .../card/screens/card_pin_set_screen.dart | 10 +- .../dashboard/screens/dashboard_screen.dart | 55 +-- .../dashboard/widgets/account_card.dart | 12 +- .../enquiry/screens/enquiry_screen.dart | 8 +- .../fund_transfer_beneficiary_screen.dart | 6 +- .../screens/fund_transfer_screen.dart | 2 +- .../screens/payment_animation.dart | 241 +++++++++++- .../screens/transaction_pin_screen.dart | 4 +- .../screens/transaction_success_screen.dart | 14 +- .../preferences/color_theme_dialog.dart | 35 ++ .../preferences/preference_screen.dart | 54 ++- lib/features/profile/profile_screen.dart | 2 +- .../quick_pay_outside_bank_screen.dart | 28 +- .../screens/quick_pay_within_bank_screen.dart | 14 +- lib/main.dart | 4 +- pubspec.lock | 247 +----------- pubspec.yaml | 2 +- 33 files changed, 772 insertions(+), 935 deletions(-) create mode 100644 lib/config/theme_controller.dart create mode 100644 lib/config/theme_mode_controller.dart create mode 100644 lib/config/theme_type.dart create mode 100644 lib/features/auth/controllers/theme_cubit.dart create mode 100644 lib/features/auth/controllers/theme_state.dart create mode 100644 lib/features/profile/preferences/color_theme_dialog.dart diff --git a/lib/app.dart b/lib/app.dart index 2f789fd..32c3313 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -6,6 +6,10 @@ import 'package:kmobile/security/secure_storage.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import './l10n/app_localizations.dart'; import 'config/themes.dart'; +import 'config/theme_controller.dart'; +import 'config/theme_mode_controller.dart'; +import 'package:kmobile/features/auth/controllers/theme_cubit.dart'; +import 'package:kmobile/features/auth/controllers/theme_state.dart'; import 'config/routes.dart'; import 'di/injection.dart'; import 'features/auth/controllers/auth_cubit.dart'; @@ -17,7 +21,6 @@ import 'features/dashboard/screens/dashboard_screen.dart'; import 'features/auth/screens/mpin_screen.dart'; import 'package:local_auth/local_auth.dart'; import 'package:shared_preferences/shared_preferences.dart'; -//import 'package:flutter_neumorphic/flutter_neumorphic.dart'; class KMobile extends StatefulWidget { const KMobile({super.key}); @@ -32,42 +35,43 @@ class KMobile extends StatefulWidget { } class _KMobileState extends State { - bool _showSplash = false; - Locale? _locale; + bool showSplash = true; + Locale? _locale; + @override void initState() { super.initState(); - _loadLocale(); - // Simulate a splash screen delay + loadPreferences(); Future.delayed(const Duration(seconds: 2), () { setState(() { - _showSplash = false; + showSplash = false; }); }); } - Future _loadLocale() async{ - final prefs = await SharedPreferences.getInstance(); + Future loadPreferences() async { + final prefs = await SharedPreferences.getInstance(); + + // Load Locale final String? langCode = prefs.getString('locale'); if (langCode != null) { setState(() { _locale = Locale(langCode); }); } + } - void setLocale(Locale locale) { setState(() { _locale = locale; }); } - /* - @override +/* @override Widget build(BuildContext context) { - // Set status bar color + // Set status bar color SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( statusBarColor: Colors.transparent, @@ -75,8 +79,12 @@ class _KMobileState extends State { ), ); - if (_showSplash) { - return MaterialApp( + return MultiBlocProvider( + providers: [ + BlocProvider(create: (_) => getIt()), + BlocProvider(create: (_) => getIt()), + ], + child: MaterialApp( debugShowCheckedModeBanner: false, locale: _locale, supportedLocales: const [ @@ -89,69 +97,67 @@ class _KMobileState extends State { GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], - home: const SplashScreen(), - ); - } - - - - return MultiBlocProvider( - providers: [ - BlocProvider(create: (_) => getIt()), - ], - child: MaterialApp( title: 'kMobile', - // debugShowCheckedModeBanner: false, - theme: AppThemes.lightTheme, - // darkTheme: AppThemes.darkTheme, - themeMode: ThemeMode.system, // Use system theme by default + + // Dynamic Theme and ThemeMode + theme: AppThemes.getLightTheme(_themeController.currentTheme), + darkTheme: AppThemes.getDarkTheme(_themeController.currentTheme), + themeMode: _themeModeController.currentThemeMode, + onGenerateRoute: AppRoutes.generateRoute, initialRoute: AppRoutes.splash, - home: const AuthGate(), + home: showSplash ? const SplashScreen() : const AuthGate(), ), ); - } - */ - -@override + }*/ + + @override Widget build(BuildContext context) { - // Set status bar color - SystemChrome.setSystemUIOverlayStyle( - const SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - statusBarIconBrightness: Brightness.dark, - ), - ); +// Set status bar color and brightness +SystemChrome.setSystemUIOverlayStyle( +const SystemUiOverlayStyle( +statusBarColor: Colors.transparent, +statusBarIconBrightness: Brightness.dark, +), +); - return MultiBlocProvider( - providers: [ - BlocProvider(create: (_) => getIt()), - ], - child: MaterialApp( - debugShowCheckedModeBanner: false, - locale: _locale, // Dynamic locale - supportedLocales: const [ - Locale('en'), - Locale('hi'), - ], - localizationsDelegates: const [ - AppLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - title: 'kMobile', - theme: AppThemes.lightTheme, - // darkTheme: AppThemes.darkTheme, - themeMode: ThemeMode.system, - onGenerateRoute: AppRoutes.generateRoute, - initialRoute: AppRoutes.splash, - home: _showSplash ? const SplashScreen() : const AuthGate(), - ), - ); -} +return MultiBlocProvider( +providers: [ +BlocProvider(create: (_) => getIt()), +BlocProvider(create: (_) => getIt()), +], +child: BlocBuilder( +builder: (context, themeState) { +return MaterialApp( +debugShowCheckedModeBanner: false, +locale: _locale ?? const Locale('en'), +supportedLocales: const [ +Locale('en'), +Locale('hi'), +], +localizationsDelegates: const [ +AppLocalizations.delegate, +GlobalMaterialLocalizations.delegate, +GlobalWidgetsLocalizations.delegate, +GlobalCupertinoLocalizations.delegate, +], +title: 'kMobile', +//theme: themeState.lightTheme, +//theme: AppThemes.getLightTheme(themeState.themeType), +theme: themeState.lightTheme, +darkTheme: AppThemes.getDarkTheme(themeState.themeType), +themeMode: themeState.themeMode, +onGenerateRoute: AppRoutes.generateRoute, +initialRoute: AppRoutes.splash, +home: showSplash ? const SplashScreen() : const AuthGate(), +); +}, +), +); } + +} class AuthGate extends StatefulWidget { const AuthGate({super.key}); @@ -210,105 +216,6 @@ class _AuthGateState extends State { } } - /* @override - Widget build(BuildContext context) { - if (_checking) { - return const SplashScreen(); - } - if (_isLoggedIn) { - if (_hasMPin) { - if (_biometricEnabled) { - return FutureBuilder( - future: _tryBiometric(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const SplashScreen(); - } - if (snapshot.data == true) { - // Authenticated with biometrics, go to dashboard - return const NavigationScaffold(); - } - // If not authenticated or user dismissed, show mPIN screen - return MPinScreen( - mode: MPinMode.enter, - onCompleted: (_) { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (_) => const NavigationScaffold()), - ); - }, - ); - }, - ); - } else { - return MPinScreen( - mode: MPinMode.enter, - onCompleted: (_) { - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => const NavigationScaffold()), - ); - }, - ); - } - } else { - return MPinScreen( - mode: MPinMode.set, - onCompleted: (_) async { - final storage = getIt(); - final localAuth = LocalAuthentication(); - - // 1) Prompt user to opt‐in for biometric - final optIn = await showDialog( - context: context, - barrierDismissible: false, // force choice - builder: (ctx) => AlertDialog( - title: const Text('Enable Fingerprint Login?'), - content: const Text( - 'Would you like to enable fingerprint authentication for faster login?', - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(ctx).pop(false), - child: const Text('No'), - ), - TextButton( - onPressed: () => Navigator.of(ctx).pop(true), - child: const Text('Yes'), - ), - ], - ), - ); - - // 2) If opted in, perform biometric auth - if (optIn == true) { - final canCheck = await localAuth.canCheckBiometrics; - bool didAuth = false; - if (canCheck) { - didAuth = await localAuth.authenticate( - localizedReason: 'Authenticate to enable fingerprint login', - options: const AuthenticationOptions( - stickyAuth: true, - biometricOnly: true, - ), - ); - } - await storage.write( - 'biometric_enabled', didAuth ? 'true' : 'false'); - } else { - await storage.write('biometric_enabled', 'false'); - } - - // 3) Finally go to your main scaffold - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => const NavigationScaffold()), - ); - }, - ); - } - } - return const LoginScreen(); - } -}*/ @override Widget build(BuildContext context) { @@ -430,124 +337,6 @@ class _AuthGateState extends State { } } -/*@override - Widget build(BuildContext context) { - if (_checking) { - return const SplashScreen(); - } - - if (_isLoggedIn) { - if (_hasMPin) { - if (_biometricEnabled) { - return FutureBuilder( - future: _tryBiometric(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const SplashScreen(); - } - - if (snapshot.data == true) { - return const NavigationScaffold(); // Authenticated - } - - // Failed or dismissed biometric → Show MPIN - return MPinScreen( - mode: MPinMode.enter, - onCompleted: (_) { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (_) => const NavigationScaffold(), - ), - ); - }, - ); - }, - ); - } else { - return MPinScreen( - mode: MPinMode.enter, - onCompleted: (_) { - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => const NavigationScaffold()), - ); - }, - ); - } - } else { - return MPinScreen( - mode: MPinMode.set, - onCompleted: (_) async { - final storage = getIt(); - final localAuth = LocalAuthentication(); - final optin = await showDialog( - context: context, - barrierDismissible: false, - builder: (ctx) => AlertDialog( - title: Text( - AppLocalizations.of(context).enableFingerprintLogin, - ), - content: Text( - AppLocalizations.of(context).enableFingerprintMessage, - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(ctx).pop(false), - child: Text(AppLocalizations.of(context).no), - ), - TextButton( - onPressed: () => Navigator.of(ctx).pop(true), - child: Text(AppLocalizations.of(context).yes), - ), - ], - ), - ); - - if (optin == true) { - final canCheck = await localAuth.canCheckBiometrics; - bool didAuth = false; - - if (canCheck) { - didAuth = await localAuth.authenticate( - localizedReason: AppLocalizations.of( - context, - ).authenticateToEnable, - options: const AuthenticationOptions( - stickyAuth: true, - biometricOnly: true, - ), - ); - } - - await storage.write( - 'biometric_enabled', - didAuth ? 'true' : 'false', - ); - } else { - await storage.write('biometric_enabled', 'false'); - } - - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => const NavigationScaffold()), - ); - }, - ); - } - } - - // 🔻 Show Welcome screen before login if not logged in - if (_showWelcome) { - return WelcomeScreen( - onContinue: () { - setState(() { - _showWelcome = false; - }); - }, - ); - } - return const LoginScreen(); - } -}*/ - class NavigationScaffold extends StatefulWidget { const NavigationScaffold({super.key}); @@ -612,8 +401,8 @@ class _NavigationScaffoldState extends State { bottomNavigationBar: BottomNavigationBar( currentIndex: _selectedIndex, type: BottomNavigationBarType.fixed, - backgroundColor: const Color(0xFFE0F7FA), // Light blue background - selectedItemColor: Colors.blue[800], + backgroundColor: Theme.of(context).scaffoldBackgroundColor, // Light blue background + selectedItemColor: Theme.of(context).primaryColor, unselectedItemColor: Colors.black54, onTap: _onItemTapped, items: [ diff --git a/lib/config/theme_controller.dart b/lib/config/theme_controller.dart new file mode 100644 index 0000000..f595976 --- /dev/null +++ b/lib/config/theme_controller.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:kmobile/config/theme_type.dart'; + +class ThemeController with ChangeNotifier { +ThemeType _currentTheme = ThemeType.violet; + +ThemeType get currentTheme => _currentTheme; + +Future loadTheme() async { +final prefs = await SharedPreferences.getInstance(); +final savedTheme = prefs.getString('color_theme'); +if (savedTheme != null) { +_currentTheme = ThemeType.values.firstWhere( +(e) => e.name == savedTheme, +orElse: () => ThemeType.violet, +); +notifyListeners(); +} +} + +Future setTheme(ThemeType theme) async { +_currentTheme = theme; +notifyListeners(); +final prefs = await SharedPreferences.getInstance(); +await prefs.setString('color_theme', theme.name); +} +} \ No newline at end of file diff --git a/lib/config/theme_mode_controller.dart b/lib/config/theme_mode_controller.dart new file mode 100644 index 0000000..073de5b --- /dev/null +++ b/lib/config/theme_mode_controller.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class ThemeModeController with ChangeNotifier { +ThemeMode _currentThemeMode = ThemeMode.system; + +ThemeMode get currentThemeMode => _currentThemeMode; + +Future loadThemeMode() async { +final prefs = await SharedPreferences.getInstance(); +final savedMode = prefs.getString('theme_mode'); +if (savedMode != null) { +switch (savedMode) { +case 'light': +_currentThemeMode = ThemeMode.light; +break; +case 'dark': +_currentThemeMode = ThemeMode.dark; +break; +default: +_currentThemeMode = ThemeMode.system; +} +notifyListeners(); +} +} + +Future toggleThemeMode() async { +if (_currentThemeMode == ThemeMode.light) { +_currentThemeMode = ThemeMode.dark; +} else { +_currentThemeMode = ThemeMode.light; +} +notifyListeners(); +final prefs = await SharedPreferences.getInstance(); +await prefs.setString( +'theme_mode', +_currentThemeMode == ThemeMode.light ? 'light' : 'dark', +); +} +} diff --git a/lib/config/theme_type.dart b/lib/config/theme_type.dart new file mode 100644 index 0000000..ce458a8 --- /dev/null +++ b/lib/config/theme_type.dart @@ -0,0 +1,6 @@ +enum ThemeType { +violet, +green, +orange, +blue, +} \ No newline at end of file diff --git a/lib/config/themes.dart b/lib/config/themes.dart index 6230e60..6b24ee9 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -1,266 +1,95 @@ +/*class AppThemes { + static ThemeData getLightTheme(ThemeType type) { + switch (type) { + case ThemeType.green: + return ThemeData( + brightness: Brightness.light, + primarySwatch: Colors.green, + scaffoldBackgroundColor: Colors.white, + ); + case ThemeType.orange: + return ThemeData( + brightness: Brightness.light, + primarySwatch: Colors.orange, + scaffoldBackgroundColor: Colors.white, + ); + case ThemeType.blue: + return ThemeData( + brightness: Brightness.light, + primarySwatch: Colors.blue, + scaffoldBackgroundColor: Colors.white, + ); + case ThemeType.violet: + default: + return ThemeData( + brightness: Brightness.light, + primarySwatch: Colors.deepPurple, + scaffoldBackgroundColor: Colors.white, + ); + } + } + + static ThemeData getDarkTheme(ThemeType type) { + switch (type) { + case ThemeType.green: + return ThemeData( + brightness: Brightness.dark, + primarySwatch: Colors.green, + scaffoldBackgroundColor: Colors.black, + ); + case ThemeType.orange: + return ThemeData( + brightness: Brightness.dark, + primarySwatch: Colors.orange, + scaffoldBackgroundColor: Colors.black, + ); + case ThemeType.blue: + return ThemeData( + brightness: Brightness.dark, + primarySwatch: Colors.blue, + scaffoldBackgroundColor: Colors.black, + ); + case ThemeType.violet: + default: + return ThemeData( + brightness: Brightness.dark, + primarySwatch: Colors.deepPurple, + scaffoldBackgroundColor: Colors.black, + ); + } + } +}*/ + + import 'package:flutter/material.dart'; +import 'theme_type.dart'; class AppThemes { - // Private constructor to prevent instantiation - AppThemes._(); + static ThemeData getLightTheme(ThemeType type) { + switch (type) { + case ThemeType.green: + return ThemeData(primarySwatch: Colors.green); + case ThemeType.orange: + return ThemeData(primarySwatch: Colors.orange); + case ThemeType.blue: + return ThemeData(primarySwatch: Colors.blue); + case ThemeType.violet: + default: + return ThemeData(primarySwatch: Colors.deepPurple); + } + } - // Light theme colors - static const Color _primaryColorLight = Color(0xFF1E88E5); // Blue 600 - static const Color _secondaryColorLight = Color(0xFF26A69A); // Teal 400 - static const Color _errorColorLight = Color(0xFFE53935); // Red 600 - static const Color _surfaceColorLight = Colors.white; - - // Dark theme colors - static const Color _primaryColorDark = Color(0xFF42A5F5); // Blue 400 - static const Color _secondaryColorDark = Color(0xFF4DB6AC); // Teal 300 - static const Color _errorColorDark = Color(0xFFEF5350); // Red 400 - static const Color _surfaceColorDark = Color(0xFF1E1E1E); - - // Text themes - static const TextTheme _textThemeLight = TextTheme( - displayLarge: TextStyle( - fontSize: 96, - fontWeight: FontWeight.w300, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - displayMedium: TextStyle( - fontSize: 60, - fontWeight: FontWeight.w300, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - displaySmall: TextStyle( - fontSize: 48, - fontWeight: FontWeight.w400, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - headlineMedium: TextStyle( - fontSize: 34, - fontWeight: FontWeight.w400, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - headlineSmall: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w400, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - titleLarge: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - bodyLarge: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - bodyMedium: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w400, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - bodySmall: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w400, - color: Color(0xFF757575), - fontFamily: 'Rubik', - ), - labelLarge: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Color(0xFF212121), - fontFamily: 'Rubik', - ), - ); - - static final TextTheme _textThemeDark = _textThemeLight.copyWith( - displayLarge: _textThemeLight.displayLarge?.copyWith(color: Colors.white), - displayMedium: _textThemeLight.displayMedium?.copyWith(color: Colors.white), - displaySmall: _textThemeLight.displaySmall?.copyWith(color: Colors.white), - headlineMedium: - _textThemeLight.headlineMedium?.copyWith(color: Colors.white), - headlineSmall: _textThemeLight.headlineSmall?.copyWith(color: Colors.white), - titleLarge: _textThemeLight.titleLarge?.copyWith(color: Colors.white), - bodyLarge: _textThemeLight.bodyLarge?.copyWith(color: Colors.white), - bodyMedium: _textThemeLight.bodyMedium?.copyWith(color: Colors.white), - bodySmall: _textThemeLight.bodySmall?.copyWith(color: Colors.white70), - labelLarge: _textThemeLight.labelLarge?.copyWith(color: Colors.white), - ); - - // Light theme - static final ThemeData lightTheme = ThemeData( - useMaterial3: true, - fontFamily: 'Rubik', - colorScheme: const ColorScheme.light( - primary: _primaryColorLight, - secondary: _secondaryColorLight, - error: _errorColorLight, - surface: _surfaceColorLight, - onPrimary: Colors.white, - onSecondary: Colors.white, - onSurface: Colors.black87, - onError: Colors.white, - brightness: Brightness.light, - ), - textTheme: _textThemeLight, - appBarTheme: const AppBarTheme( - elevation: 0, - backgroundColor: _surfaceColorLight, - foregroundColor: Color(0xFF212121), - centerTitle: true, - ), - cardTheme: CardTheme( - //Earlier CardThemeData - elevation: 2, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - elevatedButtonTheme: ElevatedButtonThemeData( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: _primaryColorLight, - elevation: 2, - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - ), - outlinedButtonTheme: OutlinedButtonThemeData( - style: OutlinedButton.styleFrom( - foregroundColor: _primaryColorLight, - side: const BorderSide(color: _primaryColorLight), - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - ), - textButtonTheme: TextButtonThemeData( - style: TextButton.styleFrom( - foregroundColor: _primaryColorLight, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - ), - ), - inputDecorationTheme: InputDecorationTheme( - filled: true, - fillColor: Colors.grey[100], - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide(color: Colors.grey[300]!), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: _primaryColorLight, width: 2), - ), - errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: _errorColorLight, width: 2), - ), - labelStyle: const TextStyle(color: Colors.grey), - ), - bottomNavigationBarTheme: const BottomNavigationBarThemeData( - selectedItemColor: _primaryColorLight, - unselectedItemColor: Colors.grey, - ), - ); - - // Dark theme - static final ThemeData darkTheme = ThemeData( - fontFamily: 'Rubik', - useMaterial3: true, - colorScheme: const ColorScheme.dark( - primary: _primaryColorDark, - secondary: _secondaryColorDark, - error: _errorColorDark, - surface: _surfaceColorDark, - onPrimary: Colors.black, - onSecondary: Colors.black, - onSurface: Colors.white, - onError: Colors.black, - brightness: Brightness.dark, - ), - textTheme: _textThemeDark, - appBarTheme: const AppBarTheme( - elevation: 0, - backgroundColor: _surfaceColorDark, - foregroundColor: Colors.white, - centerTitle: true, - ), - cardTheme: CardTheme( - //Earlier was CardThemeData - elevation: 2, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - color: const Color(0xFF2C2C2C), - ), - elevatedButtonTheme: ElevatedButtonThemeData( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.black, - backgroundColor: _primaryColorDark, - elevation: 2, - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - ), - outlinedButtonTheme: OutlinedButtonThemeData( - style: OutlinedButton.styleFrom( - foregroundColor: _primaryColorDark, - side: const BorderSide(color: _primaryColorDark), - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - ), - textButtonTheme: TextButtonThemeData( - style: TextButton.styleFrom( - foregroundColor: _primaryColorDark, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - ), - ), - inputDecorationTheme: InputDecorationTheme( - filled: true, - fillColor: const Color(0xFF2A2A2A), - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: BorderSide.none, - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: Color(0xFF3A3A3A)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: _primaryColorDark, width: 2), - ), - errorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: _errorColorDark, width: 2), - ), - labelStyle: const TextStyle(color: Colors.grey), - ), - bottomNavigationBarTheme: const BottomNavigationBarThemeData( - selectedItemColor: _primaryColorDark, - unselectedItemColor: Colors.grey, - backgroundColor: _surfaceColorDark, - ), - ); -} + static ThemeData getDarkTheme(ThemeType type) { + switch (type) { + case ThemeType.green: + return ThemeData.dark().copyWith(primaryColor: Colors.green); + case ThemeType.orange: + return ThemeData.dark().copyWith(primaryColor: Colors.orange); + case ThemeType.blue: + return ThemeData.dark().copyWith(primaryColor: Colors.blue); + case ThemeType.violet: + default: + return ThemeData.dark().copyWith(primaryColor: Colors.deepPurple); + } + } +} \ No newline at end of file diff --git a/lib/di/injection.dart b/lib/di/injection.dart index ec7c3de..c30aca2 100644 --- a/lib/di/injection.dart +++ b/lib/di/injection.dart @@ -4,15 +4,22 @@ import 'package:kmobile/api/services/beneficiary_service.dart'; import 'package:kmobile/api/services/payment_service.dart'; import 'package:kmobile/api/services/user_service.dart'; import 'package:kmobile/data/repositories/transaction_repository.dart'; +import 'package:kmobile/features/auth/controllers/theme_cubit.dart'; import '../api/services/auth_service.dart'; import '../api/interceptors/auth_interceptor.dart'; import '../data/repositories/auth_repository.dart'; import '../features/auth/controllers/auth_cubit.dart'; import '../security/secure_storage.dart'; + final getIt = GetIt.instance; Future setupDependencies() async { + + //getIt.registerLazySingleton(() => ThemeController()); + //getIt.registerLazySingleton(() => ThemeModeController()); + getIt.registerLazySingleton(() => ThemeCubit()); + // Register Dio client getIt.registerSingleton(_createDioClient()); @@ -44,6 +51,7 @@ Future setupDependencies() async { // Register controllers/cubits getIt.registerFactory( () => AuthCubit(getIt(), getIt())); + } Dio _createDioClient() { diff --git a/lib/features/accounts/screens/account_statement_screen.dart b/lib/features/accounts/screens/account_statement_screen.dart index 955179c..b5aea59 100644 --- a/lib/features/accounts/screens/account_statement_screen.dart +++ b/lib/features/accounts/screens/account_statement_screen.dart @@ -191,7 +191,7 @@ class _AccountStatementScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, ), keyboardType: TextInputType.number, textInputAction: TextInputAction.next, @@ -206,7 +206,7 @@ class _AccountStatementScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, ), keyboardType: TextInputType.number, textInputAction: TextInputAction.done, @@ -220,9 +220,9 @@ class _AccountStatementScreen extends State { style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).primaryColor, ), - child: const Icon( + child: Icon( Symbols.arrow_forward, - color: Colors.white, + color: Theme.of(context).scaffoldBackgroundColor, size: 30, ), ), diff --git a/lib/features/auth/controllers/theme_cubit.dart b/lib/features/auth/controllers/theme_cubit.dart new file mode 100644 index 0000000..21f2f86 --- /dev/null +++ b/lib/features/auth/controllers/theme_cubit.dart @@ -0,0 +1,50 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; +import 'theme_state.dart'; +import 'package:kmobile/config/theme_type.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:kmobile/config/themes.dart'; + +class ThemeCubit extends Cubit { + ThemeCubit() + : super(ThemeState( + lightTheme: AppThemes.getLightTheme(ThemeType.violet), + themeMode: ThemeMode.light, + themeType: ThemeType.violet, + )) { + loadTheme(); + } + + Future loadTheme() async { + final prefs = await SharedPreferences.getInstance(); + final themeIndex = prefs.getInt('theme_type') ?? 0; + final isDark = prefs.getBool('is_dark_mode') ?? false; + + final type = ThemeType.values[themeIndex]; + emit(state.copyWith( + lightTheme: AppThemes.getLightTheme(type), + themeMode: isDark ? ThemeMode.dark : ThemeMode.light, + themeType: type, + )); + } + + Future changeTheme(ThemeType type) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt('theme_type', type.index); + + emit(state.copyWith( + lightTheme: AppThemes.getLightTheme(type), + themeType: type, + )); + } + + Future toggleDarkMode(bool isDark) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool('is_dark_mode', isDark); + + emit(state.copyWith( + themeMode: isDark ? ThemeMode.dark : ThemeMode.light, + )); + } +} + diff --git a/lib/features/auth/controllers/theme_state.dart b/lib/features/auth/controllers/theme_state.dart new file mode 100644 index 0000000..badda67 --- /dev/null +++ b/lib/features/auth/controllers/theme_state.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:kmobile/config/theme_type.dart'; + +class ThemeState { + final ThemeData lightTheme; + final ThemeMode themeMode; + final ThemeType themeType; + + ThemeState({ + required this.lightTheme, + required this.themeMode, + required this.themeType, + }); + + ThemeState copyWith({ + ThemeData? lightTheme, + ThemeMode? themeMode, + ThemeType? themeType, + }) { + return ThemeState( + lightTheme: lightTheme ?? this.lightTheme, + themeMode: themeMode ?? this.themeMode, + themeType: themeType ?? this.themeType, + ); + } + bool get isDarkMode => themeMode == ThemeMode.dark; +} \ No newline at end of file diff --git a/lib/features/auth/screens/login_screen.dart b/lib/features/auth/screens/login_screen.dart index 6bec0bb..769a666 100644 --- a/lib/features/auth/screens/login_screen.dart +++ b/lib/features/auth/screens/login_screen.dart @@ -108,10 +108,10 @@ class LoginScreenState extends State width: 150, height: 150, errorBuilder: (context, error, stackTrace) { - return const Icon( + return Icon( Icons.account_balance, size: 100, - color: Colors.blue, + color: Theme.of(context).primaryColor, ); }, ), @@ -123,7 +123,7 @@ class LoginScreenState extends State style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold, - color: Colors.blue, + color: Theme.of(context).primaryColor, ), ), const SizedBox(height: 48), @@ -136,7 +136,7 @@ class LoginScreenState extends State border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -166,7 +166,7 @@ class LoginScreenState extends State border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -202,8 +202,8 @@ class LoginScreenState extends State style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.white, - foregroundColor: Colors.blueAccent, + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + foregroundColor: Theme.of(context).primaryColorDark, side: const BorderSide(color: Colors.black, width: 1), elevation: 0, ), @@ -242,7 +242,7 @@ class LoginScreenState extends State style: OutlinedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.lightBlue[100], + backgroundColor: Theme.of(context).primaryColorLight, foregroundColor: Colors.black, ), child: Text(AppLocalizations.of(context).register), diff --git a/lib/features/auth/screens/mpin_screen.dart b/lib/features/auth/screens/mpin_screen.dart index 6942f54..d794519 100644 --- a/lib/features/auth/screens/mpin_screen.dart +++ b/lib/features/auth/screens/mpin_screen.dart @@ -197,7 +197,7 @@ class _MPinScreenState extends State { key == '<' ? '⌫' : key, style: TextStyle( fontSize: 20, - color: key == 'Enter' ? Colors.blue : Colors.black, + color: key == 'Enter' ? Theme.of(context).primaryColor : Colors.black, ), ), ), diff --git a/lib/features/auth/screens/welcome_screen.dart b/lib/features/auth/screens/welcome_screen.dart index 12afb69..b6ad571 100644 --- a/lib/features/auth/screens/welcome_screen.dart +++ b/lib/features/auth/screens/welcome_screen.dart @@ -43,10 +43,10 @@ class _WelcomeScreenState extends State { children: [ Text( AppLocalizations.of(context).kconnect, - style: const TextStyle( + style: TextStyle( fontSize: 36, fontWeight: FontWeight.bold, - color: Colors.white, + color: Theme.of(context).dialogBackgroundColor, letterSpacing: 1.5, ), ), @@ -54,9 +54,9 @@ class _WelcomeScreenState extends State { Text( AppLocalizations.of(context).kccBankFull, textAlign: TextAlign.center, - style: const TextStyle( + style: TextStyle( fontSize: 18, - color: Colors.white, + color: Theme.of(context).dialogBackgroundColor, letterSpacing: 1.2, ), ), @@ -65,12 +65,12 @@ class _WelcomeScreenState extends State { ), /// 🔹 Loading Spinner at Bottom - const Positioned( + Positioned( bottom: 40, left: 0, right: 0, child: Center( - child: CircularProgressIndicator(color: Colors.white), + child: CircularProgressIndicator(color: Theme.of(context).scaffoldBackgroundColor), ), ), ], diff --git a/lib/features/beneficiaries/screens/add_beneficiary_screen.dart b/lib/features/beneficiaries/screens/add_beneficiary_screen.dart index 0a0d61a..0301d62 100644 --- a/lib/features/beneficiaries/screens/add_beneficiary_screen.dart +++ b/lib/features/beneficiaries/screens/add_beneficiary_screen.dart @@ -49,7 +49,7 @@ class _AddBeneficiaryScreen extends State { Expanded( child: Text( AppLocalizations.of(context).beneficiaryAdded, - style: TextStyle(color: Colors.white), + style: TextStyle(color: Theme.of(context).dialogBackgroundColor), ), ), TextButton( @@ -176,7 +176,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -211,7 +211,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -247,7 +247,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).dialogBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -376,7 +376,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -425,7 +425,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, // disabled color + fillColor: Theme.of(context).dialogBackgroundColor, // disabled color enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -448,7 +448,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).dialogBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -470,7 +470,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -510,7 +510,7 @@ class _AddBeneficiaryScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -542,8 +542,8 @@ class _AddBeneficiaryScreen extends State { style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.blue[900], - foregroundColor: Colors.white, + backgroundColor: Theme.of(context).primaryColorDark, + foregroundColor: Theme.of(context).scaffoldBackgroundColor, ), child: Text(AppLocalizations.of(context).validateAndAdd), ), diff --git a/lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart b/lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart index 2f0b866..ef8563f 100644 --- a/lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart +++ b/lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart @@ -58,8 +58,8 @@ class _ManageBeneficiariesScreen extends State { itemBuilder: (context, index) { final beneficiary = beneficiaries[index]; return ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.blue, + leading: CircleAvatar( + backgroundColor: Theme.of(context).primaryColor, child: Text('A'), ), title: Text(beneficiary['name']!), @@ -85,8 +85,8 @@ class _ManageBeneficiariesScreen extends State { ), ); }, - backgroundColor: Colors.grey[300], - foregroundColor: Colors.blue[900], + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + foregroundColor: Theme.of(context).primaryColor, elevation: 5, child: const Icon(Icons.add), ), diff --git a/lib/features/card/screens/block_card_screen.dart b/lib/features/card/screens/block_card_screen.dart index 6d3ef64..56f6379 100644 --- a/lib/features/card/screens/block_card_screen.dart +++ b/lib/features/card/screens/block_card_screen.dart @@ -42,7 +42,7 @@ class _BlockCardScreen extends State { onPressed: () { // Just close the SnackBar }, - textColor: Colors.white, + textColor: Theme.of(context).dialogBackgroundColor, ), backgroundColor: Colors.black, behavior: SnackBarBehavior.floating, @@ -97,7 +97,7 @@ class _BlockCardScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -122,7 +122,7 @@ class _BlockCardScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -150,7 +150,7 @@ class _BlockCardScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -174,7 +174,7 @@ class _BlockCardScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -198,8 +198,8 @@ class _BlockCardScreen extends State { style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.blue[900], - foregroundColor: Colors.white, + backgroundColor: Theme.of(context).primaryColor, + foregroundColor: Theme.of(context).scaffoldBackgroundColor, ), child: Text(AppLocalizations.of(context).block), ), diff --git a/lib/features/card/screens/card_pin_change_details_screen.dart b/lib/features/card/screens/card_pin_change_details_screen.dart index 4a66a14..e5eaa3f 100644 --- a/lib/features/card/screens/card_pin_change_details_screen.dart +++ b/lib/features/card/screens/card_pin_change_details_screen.dart @@ -87,7 +87,7 @@ class _CardPinChangeDetailsScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -112,7 +112,7 @@ class _CardPinChangeDetailsScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -140,7 +140,7 @@ class _CardPinChangeDetailsScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -164,7 +164,7 @@ class _CardPinChangeDetailsScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -188,8 +188,8 @@ class _CardPinChangeDetailsScreen extends State { style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.blue[900], - foregroundColor: Colors.white, + backgroundColor: Theme.of(context).primaryColor, + foregroundColor: Theme.of(context).scaffoldBackgroundColor, ), child: Text(AppLocalizations.of(context).next), ), diff --git a/lib/features/card/screens/card_pin_set_screen.dart b/lib/features/card/screens/card_pin_set_screen.dart index ddb0a4b..3c92c32 100644 --- a/lib/features/card/screens/card_pin_set_screen.dart +++ b/lib/features/card/screens/card_pin_set_screen.dart @@ -25,7 +25,7 @@ class _CardPinSetScreen extends State { onPressed: () { // Just close the SnackBar }, - textColor: Colors.white, + textColor: Theme.of(context).dialogBackgroundColor, ), backgroundColor: Colors.black, behavior: SnackBarBehavior.floating, @@ -87,7 +87,7 @@ class _CardPinSetScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -116,7 +116,7 @@ class _CardPinSetScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -143,8 +143,8 @@ class _CardPinSetScreen extends State { style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.blue[900], - foregroundColor: Colors.white, + backgroundColor: Theme.of(context).primaryColor, + foregroundColor: Theme.of(context).scaffoldBackgroundColor, ), child: Text(AppLocalizations.of(context).submit), ), diff --git a/lib/features/dashboard/screens/dashboard_screen.dart b/lib/features/dashboard/screens/dashboard_screen.dart index fac3aec..38cb95b 100644 --- a/lib/features/dashboard/screens/dashboard_screen.dart +++ b/lib/features/dashboard/screens/dashboard_screen.dart @@ -93,9 +93,9 @@ class _DashboardScreenState extends State { Widget _buildBalanceShimmer() { return Shimmer.fromColors( - baseColor: Colors.white.withOpacity(0.7), - highlightColor: Colors.white.withOpacity(0.3), - child: Container(width: 100, height: 32, color: Colors.white), + baseColor: Theme.of(context).dialogBackgroundColor, + highlightColor: Theme.of(context).dialogBackgroundColor, + child: Container(width: 100, height: 32, color: Theme.of(context).scaffoldBackgroundColor), ); } @@ -197,9 +197,9 @@ class _DashboardScreenState extends State { } }, child: Scaffold( - backgroundColor: const Color(0xfff5f9fc), + backgroundColor: Theme.of(context).scaffoldBackgroundColor, appBar: AppBar( - backgroundColor: const Color(0xfff5f9fc), + backgroundColor:Theme.of(context).scaffoldBackgroundColor, automaticallyImplyLeading: false, title: Text( AppLocalizations.of(context).kMobile, @@ -208,6 +208,7 @@ class _DashboardScreenState extends State { fontWeight: FontWeight.w500, ), ), + centerTitle: true, actions: [ Padding( padding: const EdgeInsets.only(right: 10.0), @@ -265,7 +266,7 @@ class _DashboardScreenState extends State { "${AppLocalizations.of(context).hi} $firstName", style: GoogleFonts.montserrat().copyWith( fontSize: 25, - color: Theme.of(context).primaryColorDark, + color: Theme.of(context).primaryColor, fontWeight: FontWeight.w700, ), ), @@ -289,8 +290,8 @@ class _DashboardScreenState extends State { children: [ Text( "${AppLocalizations.of(context).accountNumber}: ", - style: const TextStyle( - color: Colors.white, + style: TextStyle( + color: Theme.of(context).dialogBackgroundColor, fontSize: 12, ), ), @@ -299,9 +300,9 @@ class _DashboardScreenState extends State { dropdownColor: Theme.of(context).primaryColor, underline: const SizedBox(), icon: const Icon(Icons.keyboard_arrow_down), - iconEnabledColor: Colors.white, - style: const TextStyle( - color: Colors.white, + iconEnabledColor:Theme.of(context).dialogBackgroundColor, + style: TextStyle( + color: Theme.of(context).dialogBackgroundColor, fontSize: 14, ), items: List.generate(users.length, (index) { @@ -309,8 +310,8 @@ class _DashboardScreenState extends State { value: index, child: Text( users[index].accountNo ?? 'N/A', - style: const TextStyle( - color: Colors.white, + style: TextStyle( + color: Theme.of(context).dialogBackgroundColor, fontSize: 14, ), ), @@ -346,17 +347,17 @@ class _DashboardScreenState extends State { const Spacer(), IconButton( icon: isRefreshing - ? const SizedBox( + ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( - color: Colors.white, + color: Theme.of(context).dialogBackgroundColor, strokeWidth: 2, ), ) - : const Icon( + : Icon( Icons.refresh, - color: Colors.white, + color: Theme.of(context).dialogBackgroundColor, ), onPressed: isRefreshing ? null @@ -367,8 +368,8 @@ class _DashboardScreenState extends State { ), Text( getFullAccountType(currAccount.accountType), - style: const TextStyle( - color: Colors.white, + style: TextStyle( + color: Theme.of(context).dialogBackgroundColor, fontSize: 16, ), ), @@ -376,10 +377,10 @@ class _DashboardScreenState extends State { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Text( + Text( "₹ ", style: TextStyle( - color: Colors.white, + color: Theme.of(context).dialogBackgroundColor, fontSize: 40, fontWeight: FontWeight.w700, ), @@ -391,8 +392,8 @@ class _DashboardScreenState extends State { ? currAccount.currentBalance ?? '0.00' : '********', - style: const TextStyle( - color: Colors.white, + style: TextStyle( + color: Theme.of(context).dialogBackgroundColor, fontSize: 40, fontWeight: FontWeight.w700, ), @@ -422,7 +423,7 @@ class _DashboardScreenState extends State { isVisible ? Symbols.visibility_lock : Symbols.visibility, - color: Colors.white, + color: Theme.of(context).scaffoldBackgroundColor, ), ), ], @@ -598,17 +599,17 @@ class _DashboardScreenState extends State { leading: Shimmer.fromColors( baseColor: Colors.grey[300]!, highlightColor: Colors.grey[100]!, - child: const CircleAvatar(radius: 12, backgroundColor: Colors.white), + child: CircleAvatar(radius: 12, backgroundColor: Theme.of(context).scaffoldBackgroundColor), ), title: Shimmer.fromColors( baseColor: Colors.grey[300]!, highlightColor: Colors.grey[100]!, - child: Container(height: 10, width: 100, color: Colors.white), + child: Container(height: 10, width: 100, color: Theme.of(context).scaffoldBackgroundColor), ), subtitle: Shimmer.fromColors( baseColor: Colors.grey[300]!, highlightColor: Colors.grey[100]!, - child: Container(height: 8, width: 60, color: Colors.white), + child: Container(height: 8, width: 60, color: Theme.of(context).scaffoldBackgroundColor), ), ); }); diff --git a/lib/features/dashboard/widgets/account_card.dart b/lib/features/dashboard/widgets/account_card.dart index 50bd935..0b746f8 100644 --- a/lib/features/dashboard/widgets/account_card.dart +++ b/lib/features/dashboard/widgets/account_card.dart @@ -39,8 +39,8 @@ class AccountCard extends StatelessWidget { children: [ Text( account.accountType, - style: const TextStyle( - color: Colors.white, + style: TextStyle( + color: Theme.of(context).scaffoldBackgroundColor, fontSize: 18, fontWeight: FontWeight.bold, ), @@ -49,20 +49,20 @@ class AccountCard extends StatelessWidget { account.accountType == 'Savings' ? Icons.savings : Icons.account_balance, - color: Colors.white, + color: Theme.of(context).scaffoldBackgroundColor, ), ], ), const SizedBox(height: 20), Text( account.accountNumber, - style: const TextStyle(color: Colors.white70, fontSize: 16), + style: TextStyle(color: Theme.of(context).dialogBackgroundColor, fontSize: 16), ), const SizedBox(height: 30), Text( '${account.currency} ${account.balance.toStringAsFixed(2)}', - style: const TextStyle( - color: Colors.white, + style: TextStyle( + color: Theme.of(context).scaffoldBackgroundColor, fontSize: 22, fontWeight: FontWeight.bold, ), diff --git a/lib/features/enquiry/screens/enquiry_screen.dart b/lib/features/enquiry/screens/enquiry_screen.dart index c0d01cb..2304f43 100644 --- a/lib/features/enquiry/screens/enquiry_screen.dart +++ b/lib/features/enquiry/screens/enquiry_screen.dart @@ -38,12 +38,12 @@ class _EnquiryScreen extends State { const SizedBox(height: 4), GestureDetector( onTap: () => _launchEmailAddress(email), - child: Text(email, style: const TextStyle(color: Colors.blue)), + child: Text(email, style: TextStyle(color: Theme.of(context).primaryColor)), ), const SizedBox(height: 4), GestureDetector( onTap: () => _launchPhoneNumber(phone), - child: Text(phone, style: const TextStyle(color: Colors.blue)), + child: Text(phone, style: TextStyle(color: Theme.of(context).scaffoldBackgroundColor)), ), ], ); @@ -92,9 +92,9 @@ class _EnquiryScreen extends State { style: TextStyle(color: Colors.grey), ), const SizedBox(height: 4), - const Text( + Text( "complaint@kccb.in", - style: TextStyle(color: Colors.blue), + style: TextStyle(color: Theme.of(context).primaryColor), ), SizedBox(height: 20), diff --git a/lib/features/fund_transfer/screens/fund_transfer_beneficiary_screen.dart b/lib/features/fund_transfer/screens/fund_transfer_beneficiary_screen.dart index 766ca95..8f47d00 100644 --- a/lib/features/fund_transfer/screens/fund_transfer_beneficiary_screen.dart +++ b/lib/features/fund_transfer/screens/fund_transfer_beneficiary_screen.dart @@ -60,8 +60,8 @@ class _FundTransferBeneficiaryScreen itemBuilder: (context, index) { final beneficiary = beneficiaries[index]; return ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.blue, + leading: CircleAvatar( + backgroundColor: Theme.of(context).primaryColor, child: Text('A'), ), title: Text(beneficiary['name']!), @@ -96,7 +96,7 @@ class _FundTransferBeneficiaryScreen ); }, backgroundColor: Colors.grey[300], - foregroundColor: Colors.blue[900], + foregroundColor: Theme.of(context).primaryColor, elevation: 5, child: const Icon(Icons.add), ), diff --git a/lib/features/fund_transfer/screens/fund_transfer_screen.dart b/lib/features/fund_transfer/screens/fund_transfer_screen.dart index 34b849f..dd4cbff 100644 --- a/lib/features/fund_transfer/screens/fund_transfer_screen.dart +++ b/lib/features/fund_transfer/screens/fund_transfer_screen.dart @@ -135,7 +135,7 @@ class _FundTransferScreen extends State { const Spacer(), Container( padding: const EdgeInsets.all(16.0), - color: Colors.white, + color: Theme.of(context).scaffoldBackgroundColor, child: GridView.count( crossAxisCount: 3, shrinkWrap: true, diff --git a/lib/features/fund_transfer/screens/payment_animation.dart b/lib/features/fund_transfer/screens/payment_animation.dart index b16c609..3ada32d 100644 --- a/lib/features/fund_transfer/screens/payment_animation.dart +++ b/lib/features/fund_transfer/screens/payment_animation.dart @@ -8,8 +8,9 @@ import 'package:lottie/lottie.dart'; import 'package:share_plus/share_plus.dart'; import 'package:path_provider/path_provider.dart'; import '../../../l10n/app_localizations.dart'; +import 'package:confetti/confetti.dart'; -class PaymentAnimationScreen extends StatefulWidget { +/*class PaymentAnimationScreen extends StatefulWidget { final Future paymentResponse; const PaymentAnimationScreen({super.key, required this.paymentResponse}); @@ -97,7 +98,7 @@ class _PaymentAnimationScreenState extends State { AppLocalizations.of( context, ).paymentSuccessful, - style: TextStyle( + style: const TextStyle( fontSize: 22, fontWeight: FontWeight.bold, color: Colors.green, @@ -133,7 +134,7 @@ class _PaymentAnimationScreenState extends State { children: [ Text( AppLocalizations.of(context).paymentFailed, - style: TextStyle( + style: const TextStyle( fontSize: 22, fontWeight: FontWeight.bold, color: Colors.red, @@ -223,4 +224,238 @@ class _PaymentAnimationScreenState extends State { ), ); } +}*/ + +class PaymentAnimationScreen extends StatefulWidget { + final Future paymentResponse; + + const PaymentAnimationScreen({super.key, required this.paymentResponse}); + + @override + State createState() => _PaymentAnimationScreenState(); +} + +class _PaymentAnimationScreenState extends State { + final GlobalKey _shareKey = GlobalKey(); + late ConfettiController _confettiController; + + @override + void initState() { + super.initState(); + _confettiController = ConfettiController(duration: const Duration(seconds: 2)); + } + + @override + void dispose() { + _confettiController.dispose(); + super.dispose(); + } + + Future _shareScreenshot() async { + try { + RenderRepaintBoundary boundary = + _shareKey.currentContext!.findRenderObject() as RenderRepaintBoundary; + ui.Image image = await boundary.toImage(pixelRatio: 3.0); + ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); + Uint8List pngBytes = byteData!.buffer.asUint8List(); + + final tempDir = await getTemporaryDirectory(); + final file = await File('${tempDir.path}/payment_result.png').create(); + await file.writeAsBytes(pngBytes); + + await Share.shareXFiles( + [XFile(file.path)], + text: AppLocalizations.of(context).paymentResult, + ); + } catch (e) { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + '${AppLocalizations.of(context).failedToShareScreenshot}: $e', + ), + ), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: FutureBuilder( + future: widget.paymentResponse, + builder: (context, snapshot) { + if (!snapshot.hasData) { + return Center( + child: Lottie.asset( + 'assets/animations/rupee.json', + width: 200, + height: 200, + repeat: true, + ), + ); + } + + final response = snapshot.data!; + final isSuccess = response.isSuccess; + + if (isSuccess) _confettiController.play(); + + return Stack( + children: [ + Align( + alignment: Alignment.topCenter, + child: ConfettiWidget( + confettiController: _confettiController, + blastDirectionality: BlastDirectionality.explosive, + emissionFrequency: 0.2, + numberOfParticles: 40, + gravity: 0.3, + maxBlastForce: 25, + minBlastForce: 10, + shouldLoop: false, + colors: const [ + Colors.green, + Colors.blue, + Colors.pink, + Colors.orange, + ], + ), + ), + Center( + child: RepaintBoundary( + key: _shareKey, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 80), + Lottie.asset( + isSuccess + ? 'assets/animations/done.json' + : 'assets/animations/error.json', + width: 200, + height: 200, + repeat: false, + ), + const SizedBox(height: 10), + isSuccess + ? Column( + children: [ + Text( + AppLocalizations.of(context).paymentSuccessful, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: Colors.green, + ), + ), + const SizedBox(height: 16), + if (response.amount != null) + Text( + '${AppLocalizations.of(context).amount}: ${response.amount} ${response.currency ?? ""}', + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w700, + fontFamily: 'Rubik', + ), + ), + if (response.creditedAccount != null) + Text( + '${AppLocalizations.of(context).creditedAccount}: ${response.creditedAccount}', + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + fontFamily: 'Rubik', + ), + ), + if (response.date != null) + Text( + "Date: ${response.date!.toLocal().toIso8601String()}", + style: const TextStyle(fontSize: 16), + ), + ], + ) + : Column( + children: [ + Text( + AppLocalizations.of(context).paymentFailed, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: Colors.red, + ), + ), + const SizedBox(height: 16), + if (response.errorMessage != null) + Text( + response.errorMessage!, + style: const TextStyle(fontSize: 16), + ), + ], + ), + const SizedBox(height: 40), + ], + ), + ), + ), + ), + Positioned( + left: 0, + right: 0, + bottom: 80, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton.icon( + onPressed: _shareScreenshot, + icon: Icon( + Icons.share_rounded, + color: Theme.of(context).primaryColor, + ), + label: Text( + AppLocalizations.of(context).share, + style: TextStyle(color: Theme.of(context).primaryColor), + ), + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12), + shape: RoundedRectangleBorder( + side: BorderSide(color: Theme.of(context).primaryColor, width: 1), + borderRadius: BorderRadius.circular(30), + ), + textStyle: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + ), + ElevatedButton.icon( + onPressed: () { + Navigator.of(context).popUntil((route) => route.isFirst); + }, + icon: const Icon(Icons.check), + label: Text(AppLocalizations.of(context).done), + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric(horizontal: 45, vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + textStyle: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + ], + ); + }, + ), + ); + } } diff --git a/lib/features/fund_transfer/screens/transaction_pin_screen.dart b/lib/features/fund_transfer/screens/transaction_pin_screen.dart index 4cbbd06..5d34ac7 100644 --- a/lib/features/fund_transfer/screens/transaction_pin_screen.dart +++ b/lib/features/fund_transfer/screens/transaction_pin_screen.dart @@ -73,8 +73,8 @@ class _TransactionPinScreen extends State { height: 20, decoration: BoxDecoration( shape: BoxShape.circle, - border: Border.all(color: Colors.blue, width: 2), - color: index < _pin.length ? Colors.blue : Colors.transparent, + border: Border.all(color: Theme.of(context).primaryColor, width: 2), + color: index < _pin.length ? Theme.of(context).primaryColor : Colors.transparent, ), ); }), diff --git a/lib/features/fund_transfer/screens/transaction_success_screen.dart b/lib/features/fund_transfer/screens/transaction_success_screen.dart index 7ff6a8b..c9f1a51 100644 --- a/lib/features/fund_transfer/screens/transaction_success_screen.dart +++ b/lib/features/fund_transfer/screens/transaction_success_screen.dart @@ -50,10 +50,10 @@ class _TransactionSuccessScreen extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - const CircleAvatar( + CircleAvatar( radius: 50, - backgroundColor: Colors.blue, - child: Icon(Icons.check, color: Colors.white, size: 60), + backgroundColor: Theme.of(context).primaryColor, + child: Icon(Icons.check, color: Theme.of(context).scaffoldBackgroundColor, size: 60), ), const SizedBox(height: 24), Text( @@ -92,8 +92,8 @@ class _TransactionSuccessScreen extends State { style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.white, - foregroundColor: Colors.blueAccent, + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + foregroundColor: Theme.of(context).primaryColorLight, side: const BorderSide(color: Colors.black, width: 1), elevation: 0, ), @@ -114,8 +114,8 @@ class _TransactionSuccessScreen extends State { style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), - backgroundColor: Colors.blue[900], - foregroundColor: Colors.white, + backgroundColor: Theme.of(context).primaryColorDark, + foregroundColor: Theme.of(context).scaffoldBackgroundColor, ), child: Text(AppLocalizations.of(context).done), ), diff --git a/lib/features/profile/preferences/color_theme_dialog.dart b/lib/features/profile/preferences/color_theme_dialog.dart new file mode 100644 index 0000000..a706d00 --- /dev/null +++ b/lib/features/profile/preferences/color_theme_dialog.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:kmobile/config/theme_type.dart'; +import 'package:kmobile/features/auth/controllers/theme_cubit.dart'; +import 'package:kmobile/features/auth/controllers/theme_state.dart'; + + +void showColorThemeDialog(BuildContext context) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text('Select Theme Color'), + content: BlocBuilder( + builder: (context, state) { + return Column( + mainAxisSize: MainAxisSize.min, + children: ThemeType.values.map((type) { + return RadioListTile( + value: type, + groupValue: state.themeType, + title: Text(type.name.toUpperCase()), + onChanged: (val) { + if (val != null) { + context.read().changeTheme(val); + Navigator.pop(context); + } + }, + ); + }).toList(), + ); + }, + ), + ), + ); +} \ No newline at end of file diff --git a/lib/features/profile/preferences/preference_screen.dart b/lib/features/profile/preferences/preference_screen.dart index 628da3e..4b82bf4 100644 --- a/lib/features/profile/preferences/preference_screen.dart +++ b/lib/features/profile/preferences/preference_screen.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; import 'language_dialog.dart'; +import 'color_theme_dialog.dart'; import '../../../l10n/app_localizations.dart'; +import 'package:kmobile/features/auth/controllers/theme_cubit.dart'; +import 'package:kmobile/features/auth/controllers/theme_state.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; class PreferenceScreen extends StatelessWidget { const PreferenceScreen({super.key}); @@ -11,22 +15,44 @@ class PreferenceScreen extends StatelessWidget { return Scaffold( appBar: AppBar( - title: Text(loc.preferences), // Localized "Preferences" + title: Text(loc.preferences), ), - body: ListView( - children: [ - ListTile( - leading: const Icon(Icons.language), - title: Text(loc.language), // Localized "Language" - onTap: () { - showDialog( - context: context, - builder: (context) => LanguageDialog(), - ); - }, + body: BlocBuilder( + builder: (context, state) { + return ListView( + children: [ + // Theme Mode Switch (Light/Dark) + ListTile( + leading: const Icon(Icons.brightness_6), + title: const Text("Theme Mode"), + trailing: Switch( + value: state.isDarkMode, + onChanged: (val) { + context.read().toggleDarkMode(val); + }, + ), + ), + //Color_Theme_Selection + ListTile( + leading: const Icon(Icons.color_lens), + title: const Text('Theme Color'), + onTap: () => showColorThemeDialog(context), ), - ], + // Language Selection + ListTile( + leading: const Icon(Icons.language), + title: Text(loc.language), + onTap: () { + showDialog( + context: context, + builder: (_) => const LanguageDialog(), // your custom language dialog + ); + }, + ), + ], + ); + }, ), ); } -} +} \ No newline at end of file diff --git a/lib/features/profile/profile_screen.dart b/lib/features/profile/profile_screen.dart index 15df270..bf018ae 100644 --- a/lib/features/profile/profile_screen.dart +++ b/lib/features/profile/profile_screen.dart @@ -21,7 +21,7 @@ class ProfileScreen extends StatelessWidget { onTap: () { Navigator.push( context, - MaterialPageRoute(builder: (_) => const PreferenceScreen()), + MaterialPageRoute(builder: (context) => const PreferenceScreen()), ); }, ), diff --git a/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart b/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart index 83c5a0c..0545423 100644 --- a/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart +++ b/lib/features/quick_pay/screens/quick_pay_outside_bank_screen.dart @@ -122,7 +122,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -152,7 +152,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -179,7 +179,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -204,7 +204,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -228,7 +228,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -255,7 +255,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -282,7 +282,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -320,7 +320,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -342,7 +342,7 @@ class _QuickPayOutsideBankScreen extends State { border: OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -382,9 +382,9 @@ class _QuickPayOutsideBankScreen extends State { Align( alignment: Alignment.center, child: SwipeButton.expand( - thumb: const Icon(Icons.arrow_forward, color: Colors.white), - activeThumbColor: Colors.blue[900], - activeTrackColor: Colors.blue.shade100, + thumb: Icon(Icons.arrow_forward, color: Theme.of(context).scaffoldBackgroundColor), + activeThumbColor: Theme.of(context).primaryColorDark, + activeTrackColor: Theme.of(context).primaryColorLight, borderRadius: BorderRadius.circular(30), height: 56, child: Text( @@ -438,10 +438,10 @@ class _QuickPayOutsideBankScreen extends State { margin: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(vertical: 5), decoration: BoxDecoration( - color: isSelected ? Colors.blue[200] : Colors.white, + color: isSelected ? Theme.of(context).primaryColor : Theme.of(context).scaffoldBackgroundColor, borderRadius: BorderRadius.circular(5), border: Border.all( - color: isSelected ? Colors.blue : Colors.grey, + color: isSelected ? Theme.of(context).primaryColor : Theme.of(context).scaffoldBackgroundColor, width: isSelected ? 0 : 1.2, ), ), diff --git a/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart b/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart index a4b172f..7b5ea79 100644 --- a/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart +++ b/lib/features/quick_pay/screens/quick_pay_within_bank_screen.dart @@ -129,7 +129,7 @@ class _QuickPayWithinBankScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, ), readOnly: true, controller: TextEditingController(text: widget.debitAccount), @@ -144,7 +144,7 @@ class _QuickPayWithinBankScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -183,7 +183,7 @@ class _QuickPayWithinBankScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -265,7 +265,7 @@ class _QuickPayWithinBankScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -312,7 +312,7 @@ class _QuickPayWithinBankScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).scaffoldBackgroundColor, enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), @@ -338,7 +338,7 @@ class _QuickPayWithinBankScreen extends State { Align( alignment: Alignment.center, child: SwipeButton.expand( - thumb: const Icon(Icons.arrow_forward, color: Colors.white), + thumb: Icon(Icons.arrow_forward, color: Theme.of(context).dialogBackgroundColor), activeThumbColor: Theme.of(context).primaryColor, activeTrackColor: Theme.of( context, @@ -461,7 +461,7 @@ class _QuickPayWithinBankScreen extends State { border: const OutlineInputBorder(), isDense: true, filled: true, - fillColor: Colors.white, + fillColor: Theme.of(context).dialogBackgroundColor, enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.black), ), diff --git a/lib/main.dart b/lib/main.dart index 9ba4cd8..fe59125 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:shimmer/main.dart'; import 'di/injection.dart'; import 'app.dart'; @@ -13,7 +14,6 @@ void main() async { ]); // Initialize dependencies - await setupDependencies(); - + await setupDependencies(); runApp(const KMobile()); } diff --git a/pubspec.lock b/pubspec.lock index 58834dc..832df6d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,27 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 - url: "https://pub.dev" - source: hosted - version: "72.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.2" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 - url: "https://pub.dev" - source: hosted - version: "6.7.0" archive: dependency: transitive description: @@ -62,70 +41,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" - build: - dependency: transitive - description: - name: build - sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - build_config: - dependency: transitive - description: - name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 - url: "https://pub.dev" - source: hosted - version: "1.1.1" - build_daemon: - dependency: transitive - description: - name: build_daemon - sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - build_runner: - dependency: "direct dev" - description: - name: build_runner - sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" - url: "https://pub.dev" - source: hosted - version: "2.4.13" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 - url: "https://pub.dev" - source: hosted - version: "7.3.2" - built_collection: - dependency: transitive - description: - name: built_collection - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.dev" - source: hosted - version: "5.1.1" - built_value: - dependency: transitive - description: - name: built_value - sha256: "0b1b12a0a549605e5f04476031cd0bc91ead1d7c8e830773a18ee54179b3cb62" - url: "https://pub.dev" - source: hosted - version: "8.11.0" chalkdart: dependency: transitive description: @@ -166,14 +81,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" - code_builder: - dependency: transitive - description: - name: code_builder - sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" - url: "https://pub.dev" - source: hosted - version: "4.10.1" collection: dependency: transitive description: @@ -182,14 +89,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" - convert: - dependency: transitive + confetti: + dependency: "direct main" description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + name: confetti + sha256: "979aafde2428c53947892c95eb244466c109c129b7eee9011f0a66caaca52267" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "0.7.0" cross_file: dependency: transitive description: @@ -214,14 +121,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" - dart_style: - dependency: transitive - description: - name: dart_style - sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" - url: "https://pub.dev" - source: hosted - version: "2.3.7" dio: dependency: "direct main" description: @@ -402,14 +301,6 @@ packages: description: flutter source: sdk version: "0.0.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" get_it: dependency: "direct main" description: @@ -434,14 +325,6 @@ packages: url: "https://pub.dev" source: hosted version: "6.2.1" - graphs: - dependency: transitive - description: - name: graphs - sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.dev" - source: hosted - version: "2.3.2" http: dependency: transitive description: @@ -450,14 +333,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" http_parser: dependency: transitive description: @@ -482,14 +357,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" js: dependency: transitive description: @@ -578,14 +445,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.11" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" lottie: dependency: "direct main" description: @@ -594,14 +453,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.7.0" - macros: - dependency: transitive - description: - name: macros - sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" - url: "https://pub.dev" - source: hosted - version: "0.1.2-main.4" matcher: dependency: transitive description: @@ -650,14 +501,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - package_config: - dependency: transitive - description: - name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" - source: hosted - version: "2.2.0" path: dependency: transitive description: @@ -746,14 +589,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - pool: - dependency: transitive - description: - name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.dev" - source: hosted - version: "1.5.1" provider: dependency: "direct main" description: @@ -762,22 +597,6 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.5" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" - url: "https://pub.dev" - source: hosted - version: "1.4.0" screenshot: dependency: "direct main" description: @@ -858,22 +677,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" - shelf: - dependency: transitive - description: - name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 - url: "https://pub.dev" - source: hosted - version: "1.4.1" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 - url: "https://pub.dev" - source: hosted - version: "2.0.1" shimmer: dependency: "direct main" description: @@ -919,14 +722,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.dev" - source: hosted - version: "2.1.1" string_scanner: dependency: transitive description: @@ -951,14 +746,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.2" - timing: - dependency: transitive - description: - name: timing - sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" - url: "https://pub.dev" - source: hosted - version: "1.0.2" typed_data: dependency: transitive description: @@ -1079,14 +866,6 @@ packages: url: "https://pub.dev" source: hosted version: "14.2.5" - watcher: - dependency: transitive - description: - name: watcher - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" - url: "https://pub.dev" - source: hosted - version: "1.1.2" web: dependency: transitive description: @@ -1095,22 +874,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index cad93ad..cc61e0a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,11 +58,11 @@ dependencies: shimmer: ^3.0.0 lottie: ^2.6.0 share_plus: ^7.2.1 + confetti: ^0.7.0 dev_dependencies: - build_runner: ^2.4.6 flutter_test: sdk: flutter