From 99e23bf21d6c2e7b0f80b172afdcb1954fbd01bd Mon Sep 17 00:00:00 2001 From: Nilanjan Chakrabarti Date: Thu, 7 Aug 2025 18:12:31 +0530 Subject: [PATCH] IFSC Code Validation and Add Beneficiary Validation API integration --- lib/api/services/beneficiary_service.dart | 84 ++++++- lib/app.dart | 51 +--- lib/config/themes.dart | 2 +- lib/data/models/beneficiary.dart | 37 +++ lib/data/models/ifsc.dart | 32 +++ lib/di/injection.dart | 5 +- .../screens/account_statement_screen.dart | 8 +- .../auth/controllers/theme_cubit.dart | 60 +++-- .../auth/controllers/theme_state.dart | 65 +++-- .../screens/add_beneficiary_screen.dart | 235 ++++++------------ .../screens/beneficiary_result_page.dart | 19 ++ .../dashboard/screens/dashboard_screen.dart | 4 +- .../dashboard/widgets/account_card.dart | 2 +- .../screens/tpin_otp_screen.dart | 2 +- .../screens/tpin_set_screen.dart | 4 +- .../preferences/color_theme_dialog.dart | 50 +++- .../preferences/preference_screen.dart | 27 +- 17 files changed, 416 insertions(+), 271 deletions(-) create mode 100644 lib/data/models/beneficiary.dart create mode 100644 lib/data/models/ifsc.dart create mode 100644 lib/features/beneficiaries/screens/beneficiary_result_page.dart diff --git a/lib/api/services/beneficiary_service.dart b/lib/api/services/beneficiary_service.dart index cde8805..dcd2096 100644 --- a/lib/api/services/beneficiary_service.dart +++ b/lib/api/services/beneficiary_service.dart @@ -1,4 +1,6 @@ import 'package:dio/dio.dart'; +import 'package:kmobile/data/models/ifsc.dart'; +import 'package:kmobile/data/models/beneficiary.dart'; class BeneficiaryService { final Dio _dio; @@ -22,4 +24,84 @@ class BeneficiaryService { throw Exception('Unexpected error: ${e.toString()}'); } } -} \ No newline at end of file + + + Future validateIFSC(String ifscCode) async { + try { + final response = await _dio.get('/api/beneficiary/ifsc-details', queryParameters: { + "ifscCode": ifscCode + } + ); + + if (response.statusCode == 200) { + return ifsc.fromJson(response.data); + } + } on DioException catch (e) { + if (e.response?.statusCode == 404) { + print('Invalid IFSC code.'); + } else { + print('API error: ${e.message}'); + } + } catch (e) { + print('Unexpected error: $e'); + } + + return null; + +} + + // Send Data for Validation + Future sendForValidation(Beneficiary beneficiary) async { + try { + print(beneficiary.toJson()); + final response = await _dio.post( + '/api/beneficiary/add', + data: beneficiary.toJson(), + ); + + if (response.statusCode == 200) { + print("SENT FOR VALIDATION"); + } else { + print("VALIDATION REQUEST FAILED: ${response.statusCode}"); + } + } catch (e) { + print("ERROR IN SENDING REQUEST: $e"); + rethrow; + } + } + + // Poll to check if beneficiary is found + Future checkIfFound(String accountNo) async { + const int timeoutInSeconds = 30; + const int intervalInSeconds = 2; + const int maxTries = timeoutInSeconds ~/ intervalInSeconds; + + int attempts = 0; + + while (attempts < maxTries) { + try { + final response = await _dio.get( + '/api/beneficiary/check?', + queryParameters: { + 'accountNo': accountNo + } + ); + + if (response.statusCode == 200) { + print("FOUND"); + return true; + } else if (response.statusCode == 404) { + print("NOT FOUND"); + } + } catch (e) { + print("ERROR DURING STATUS: $e"); + } + attempts++; + } + + print("Beneficiary not found within timeout."); + return false; + } + +} + diff --git a/lib/app.dart b/lib/app.dart index 32c3313..d175a5c 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -69,48 +69,6 @@ class _KMobileState extends State { }); } -/* @override - Widget build(BuildContext context) { - // Set status bar color - SystemChrome.setSystemUIOverlayStyle( - const SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - statusBarIconBrightness: Brightness.dark, - ), - ); - - return MultiBlocProvider( - providers: [ - BlocProvider(create: (_) => getIt()), - BlocProvider(create: (_) => getIt()), - ], - child: MaterialApp( - debugShowCheckedModeBanner: false, - locale: _locale, - supportedLocales: const [ - Locale('en'), - Locale('hi'), - ], - localizationsDelegates: const [ - AppLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - title: 'kMobile', - - // Dynamic Theme and ThemeMode - theme: AppThemes.getLightTheme(_themeController.currentTheme), - darkTheme: AppThemes.getDarkTheme(_themeController.currentTheme), - themeMode: _themeModeController.currentThemeMode, - - onGenerateRoute: AppRoutes.generateRoute, - initialRoute: AppRoutes.splash, - home: showSplash ? const SplashScreen() : const AuthGate(), - ), - ); - }*/ - @override Widget build(BuildContext context) { // Set status bar color and brightness @@ -128,6 +86,8 @@ BlocProvider(create: (_) => getIt()), ], child: BlocBuilder( builder: (context, themeState) { + print('global theme state changed'); + print(themeState); return MaterialApp( debugShowCheckedModeBanner: false, locale: _locale ?? const Locale('en'), @@ -142,11 +102,10 @@ 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, +theme: themeState.getThemeData(), +// darkTheme: AppThemes.getDarkTheme(themeState.themeType), +themeMode: ThemeMode.system, onGenerateRoute: AppRoutes.generateRoute, initialRoute: AppRoutes.splash, home: showSplash ? const SplashScreen() : const AuthGate(), diff --git a/lib/config/themes.dart b/lib/config/themes.dart index 6b24ee9..ee35438 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -77,7 +77,7 @@ class AppThemes { default: return ThemeData(primarySwatch: Colors.deepPurple); } - } + } static ThemeData getDarkTheme(ThemeType type) { switch (type) { diff --git a/lib/data/models/beneficiary.dart b/lib/data/models/beneficiary.dart new file mode 100644 index 0000000..37a511a --- /dev/null +++ b/lib/data/models/beneficiary.dart @@ -0,0 +1,37 @@ +class Beneficiary { + final String accountNo; + final String accountType; + final String name; + final String ifscCode; + + + Beneficiary({ + required this.accountNo, + required this.accountType, + required this.name, + required this.ifscCode, + }); + + factory Beneficiary.fromJson(Map json) { + return Beneficiary( + accountNo: json['accountNo'] ?? '', + accountType: json['accountType'] ?? '', + name: json['name'] ?? '', + ifscCode: json['ifscCode'] ?? '', + ); + } + + Map toJson() { + return { + 'accountNo': accountNo, + 'accountType': accountType, + 'name': name, + 'ifscCode' : ifscCode, + }; + } + + @override + String toString() { + return 'Beneficiary(accountNo: $accountNo, accountType: $accountType, ifscCode: $ifscCode, name: $name)'; + } +} \ No newline at end of file diff --git a/lib/data/models/ifsc.dart b/lib/data/models/ifsc.dart new file mode 100644 index 0000000..c6102c9 --- /dev/null +++ b/lib/data/models/ifsc.dart @@ -0,0 +1,32 @@ +class ifsc { + final String ifscCode; + final String bankName; + final String branchName; + + ifsc({ + required this.ifscCode, + required this.bankName, + required this.branchName, + }); + + factory ifsc.fromJson(Map json) { + return ifsc( + ifscCode: json['ifsc_code'] ?? '', + bankName: json['bank_name'] ?? '', + branchName: json['branch_name'] ?? '', + ); + } + + Map toJson() { + return { + 'ifsc_code': ifscCode, + 'bank_name': bankName, + 'branch_name': branchName, + }; + } + + @override + String toString() { + return 'IFSC(ifscCode: $ifscCode, bankName: $bankName, branchName: $branchName)'; + } +} \ No newline at end of file diff --git a/lib/di/injection.dart b/lib/di/injection.dart index c30aca2..337236f 100644 --- a/lib/di/injection.dart +++ b/lib/di/injection.dart @@ -18,7 +18,7 @@ Future setupDependencies() async { //getIt.registerLazySingleton(() => ThemeController()); //getIt.registerLazySingleton(() => ThemeModeController()); - getIt.registerLazySingleton(() => ThemeCubit()); + getIt.registerSingleton( ThemeCubit()); // Register Dio client getIt.registerSingleton(_createDioClient()); @@ -58,7 +58,8 @@ Dio _createDioClient() { final dio = Dio( BaseOptions( baseUrl: - 'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080', + //'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080', + 'http://localhost:8081', connectTimeout: const Duration(seconds: 5), receiveTimeout: const Duration(seconds: 3), headers: { diff --git a/lib/features/accounts/screens/account_statement_screen.dart b/lib/features/accounts/screens/account_statement_screen.dart index b5aea59..f7b9630 100644 --- a/lib/features/accounts/screens/account_statement_screen.dart +++ b/lib/features/accounts/screens/account_statement_screen.dart @@ -250,9 +250,9 @@ class _AccountStatementScreen extends State { leading: Shimmer.fromColors( baseColor: Colors.grey[300]!, highlightColor: Colors.grey[100]!, - child: const CircleAvatar( + child: CircleAvatar( radius: 12, - backgroundColor: Colors.white, + backgroundColor: Theme.of(context).scaffoldBackgroundColor, ), ), title: Shimmer.fromColors( @@ -261,7 +261,7 @@ class _AccountStatementScreen extends State { child: Container( height: 10, width: 100, - color: Colors.white, + color: Theme.of(context).scaffoldBackgroundColor, ), ), subtitle: Shimmer.fromColors( @@ -270,7 +270,7 @@ class _AccountStatementScreen extends State { child: Container( height: 8, width: 60, - color: Colors.white, + color: Theme.of(context).scaffoldBackgroundColor, ), ), ), diff --git a/lib/features/auth/controllers/theme_cubit.dart b/lib/features/auth/controllers/theme_cubit.dart index 21f2f86..9141165 100644 --- a/lib/features/auth/controllers/theme_cubit.dart +++ b/lib/features/auth/controllers/theme_cubit.dart @@ -1,50 +1,60 @@ +import 'dart:developer'; + 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'; +// import 'package:kmobile/config/themes.dart'; class ThemeCubit extends Cubit { - ThemeCubit() - : super(ThemeState( - lightTheme: AppThemes.getLightTheme(ThemeType.violet), - themeMode: ThemeMode.light, - themeType: ThemeType.violet, - )) { + ThemeCubit(): super(ThemeViolet()) { 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 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, - )); + switch(type) { + case ThemeType.blue: + emit(ThemeBlue()); + case ThemeType.violet: + emit(ThemeViolet()); + default: + emit(ThemeViolet()); + } } 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, - )); + log("Mode Change"); + print("mode changed"); + switch(type) { + case ThemeType.blue: + emit(ThemeBlue()); + print('blue matched'); + break; + case ThemeType.violet: + emit(ThemeViolet()); + print('violet matched'); + break; + default: + emit(ThemeBlue()); + print('default macthed'); + } } - Future toggleDarkMode(bool isDark) async { - final prefs = await SharedPreferences.getInstance(); - await prefs.setBool('is_dark_mode', isDark); + // 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, - )); - } + // 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 index badda67..b188c72 100644 --- a/lib/features/auth/controllers/theme_state.dart +++ b/lib/features/auth/controllers/theme_state.dart @@ -1,27 +1,52 @@ +import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:kmobile/config/theme_type.dart'; +import 'package:kmobile/config/themes.dart'; -class ThemeState { - final ThemeData lightTheme; - final ThemeMode themeMode; - final ThemeType themeType; +// class ThemeState { +// final ThemeData lightTheme; +// final ThemeMode themeMode; +// final ThemeType themeType; - ThemeState({ - required this.lightTheme, - required this.themeMode, - required this.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, - ); +// 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; +// } + +abstract class ThemeState extends Equatable { + getThemeData(); + @override + List get props => []; +} + +class ThemeBlue extends ThemeState { + + @override + getThemeData() { + print('returning blue theme'); + return AppThemes.getLightTheme(ThemeType.blue); + } +} + +class ThemeViolet extends ThemeState { + @override + getThemeData() { + print('returning violet theme'); + return AppThemes.getLightTheme(ThemeType.violet); } - bool get isDarkMode => themeMode == ThemeMode.dark; } \ No newline at end of file diff --git a/lib/features/beneficiaries/screens/add_beneficiary_screen.dart b/lib/features/beneficiaries/screens/add_beneficiary_screen.dart index 0301d62..725cdb8 100644 --- a/lib/features/beneficiaries/screens/add_beneficiary_screen.dart +++ b/lib/features/beneficiaries/screens/add_beneficiary_screen.dart @@ -1,6 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:kmobile/api/services/beneficiary_service.dart'; +import 'package:kmobile/data/models/ifsc.dart'; +import 'package:kmobile/data/models/beneficiary.dart'; +import 'beneficiary_result_page.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; +import '../../../di/injection.dart'; import '../../../l10n/app_localizations.dart'; class AddBeneficiaryScreen extends StatefulWidget { @@ -21,7 +26,9 @@ class _AddBeneficiaryScreen extends State { final TextEditingController branchNameController = TextEditingController(); final TextEditingController ifscController = TextEditingController(); final TextEditingController phoneController = TextEditingController(); + + bool _isLoading2 = false; late String accountType; @override @@ -34,7 +41,7 @@ class _AddBeneficiaryScreen extends State { }); } - void _submitForm() { + /*void _submitForm() { if (_formKey.currentState!.validate()) { // Handle successful submission ScaffoldMessenger.of(context).showSnackBar( @@ -56,11 +63,11 @@ class _AddBeneficiaryScreen extends State { onPressed: () { // Navigate to Payment Screen or do something }, - style: TextButton.styleFrom(foregroundColor: Colors.blue[200]), + style: TextButton.styleFrom(foregroundColor: Theme.of(context).primaryColorLight), child: Text(AppLocalizations.of(context).payNow), ), IconButton( - icon: const Icon(Icons.close, color: Colors.white), + icon: Icon(Icons.close, color: Theme.of(context).scaffoldBackgroundColor), onPressed: () { ScaffoldMessenger.of(context).hideCurrentSnackBar(); }, @@ -70,58 +77,82 @@ class _AddBeneficiaryScreen extends State { ), ); } + }*/ + +ifsc? _ifscData; +bool _isLoading = false; + + void _validateIFSC() async { + var beneficiaryService = getIt(); + final ifsc = ifscController.text.trim().toUpperCase(); + if (ifsc.isEmpty) return; + setState(() { + _isLoading = true; + _ifscData = null; + }); + + final result = await beneficiaryService.validateIFSC(ifsc); + + setState(() { + _isLoading = false; + _ifscData = result; + }); + + if (result == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Invalid IFSC code')), + ); + bankNameController.clear(); + branchNameController.clear(); + } else { + print("Valid IFSC: ${result.bankName}, ${result.branchName}"); + bankNameController.text = result.bankName; + branchNameController.text = result.branchName; } + } - void _validateIFSC() async { - final ifsc = ifscController.text.trim().toUpperCase(); - // 🔹 Format check - final isValidFormat = RegExp(r'^[A-Z]{4}0[A-Z0-9]{6}$').hasMatch(ifsc); - if (!isValidFormat) { - bankNameController.clear(); - branchNameController.clear(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(AppLocalizations.of(context).invalidIfscFormat)), - ); - return; - } - await Future.delayed( - const Duration(seconds: 2), - ); //Mock delay for 2 sec to imitate api call - // 🔹 Mock IFSC lookup (you can replace this with API) - const mockIfscData = { - 'KCCB0001234': { - 'bank': 'Kangra Central Co-operative Bank', - 'branch': 'Dharamshala', - }, - 'SBIN0004567': { - 'bank': 'State Bank of India', - 'branch': 'Connaught Place', - }, - }; + String _selectedAccountType = 'Savings'; // default value - if (mockIfscData.containsKey(ifsc)) { - final data = mockIfscData[ifsc]!; - bankNameController.text = data['bank']!; - branchNameController.text = data['branch']!; - } else { - bankNameController.clear(); - branchNameController.clear(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(AppLocalizations.of(context).noIfscDetails)), + void validateAndAddBeneficiary() async { + setState(() { + _isLoading = true; + }); + + final beneficiary = Beneficiary( + accountNo: accountNumberController.text.trim(), + accountType: _selectedAccountType, + name: nameController.text.trim(), + ifscCode: ifscController.text.trim(), + ); + + var service = getIt(); + + try { + await service.sendForValidation(beneficiary); + bool isFound = await service.checkIfFound(beneficiary.accountNo); + + if (context.mounted) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BeneficiaryResultPage(isSuccess: isFound), + ), ); } + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("Something went wrong during validation.")), + ); + } finally { + if (mounted) { + setState(() { + _isLoading2 = false; + }); + } + } +} - /* - 🔸 Optional: Use real IFSC API like: - final response = await http.get(Uri.parse('https://ifsc.razorpay.com/$ifsc')); - if (response.statusCode == 200) { - final data = jsonDecode(response.body); - bankNameController.text = data['BANK']; - branchNameController.text = data['BRANCH']; - } - */ - } @override Widget build(BuildContext context) { @@ -263,110 +294,7 @@ class _AddBeneficiaryScreen extends State { ? AppLocalizations.of(context).nameRequired : null, ), - /*const SizedBox(height: 24), - TextFormField( - controller: bankNameController, - decoration: const InputDecoration( - labelText: 'Beneficiary Bank Name', - // prefixIcon: Icon(Icons.person), - border: OutlineInputBorder(), - isDense: true, - filled: true, - fillColor: Colors.white, - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black, width: 2), - ), - ), - textInputAction: TextInputAction.next, - validator: (value) => - value == null || value.isEmpty ? "Bank name is required" : null, - ), - const SizedBox(height: 24), - TextFormField( - controller: branchNameController, - decoration: const InputDecoration( - labelText: 'Branch Name', - // prefixIcon: Icon(Icons.person), - border: OutlineInputBorder(), - isDense: true, - filled: true, - fillColor: Colors.white, - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black, width: 2), - ), - ), - textInputAction: TextInputAction.next, - validator: (value) => - value == null || value.isEmpty ? "Branch name is required" : null, - ), - const SizedBox(height: 24), - Row( - children: [ - Expanded( - flex: 2, - child: TextFormField( - controller: ifscController, - decoration: const InputDecoration( - labelText: 'IFSC Code', - // prefixIcon: Icon(Icons.person), - border: OutlineInputBorder(), - isDense: true, - filled: true, - fillColor: Colors.white, - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black, width: 2), - ), - ), - textInputAction: TextInputAction.next, - validator: (value) => value == null || value.length < 5 - ? "Enter a valid IFSC" - : null, - ), - ), - const SizedBox(width: 16), - Expanded( - flex: 2, - child: DropdownButtonFormField( - value: accountType, - decoration: const InputDecoration( - labelText: 'Account Type', - // prefixIcon: Icon(Icons.person), - border: OutlineInputBorder(), - isDense: true, - filled: true, - fillColor: Colors.white, - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.black, width: 2), - ), - ), - - items: ['Savings', 'Current'] - .map((type) => DropdownMenuItem( - value: type, - child: Text(type), - )) - .toList(), - onChanged: (value) { - setState(() { - accountType = value!; - }); - }, - ), - ), - ], - ),*/ + const SizedBox(height: 24), // 🔹 IFSC Code Field TextFormField( @@ -538,7 +466,8 @@ class _AddBeneficiaryScreen extends State { child: SizedBox( width: 250, child: ElevatedButton( - onPressed: _submitForm, + onPressed: _isLoading2 ? null : + validateAndAddBeneficiary, style: ElevatedButton.styleFrom( shape: const StadiumBorder(), padding: const EdgeInsets.symmetric(vertical: 16), diff --git a/lib/features/beneficiaries/screens/beneficiary_result_page.dart b/lib/features/beneficiaries/screens/beneficiary_result_page.dart new file mode 100644 index 0000000..887a792 --- /dev/null +++ b/lib/features/beneficiaries/screens/beneficiary_result_page.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class BeneficiaryResultPage extends StatelessWidget { + final bool isSuccess; + + const BeneficiaryResultPage({super.key, required this.isSuccess}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Text( + isSuccess ? 'Beneficiary Added Successfully!' : 'Beneficiary Addition Failed!', + style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/dashboard/screens/dashboard_screen.dart b/lib/features/dashboard/screens/dashboard_screen.dart index 38cb95b..d191279 100644 --- a/lib/features/dashboard/screens/dashboard_screen.dart +++ b/lib/features/dashboard/screens/dashboard_screen.dart @@ -482,7 +482,7 @@ class _DashboardScreenState extends State { MaterialPageRoute( builder: (context) => const FundTransferBeneficiaryScreen())); - }, disable: true), + }, disable: false), _buildQuickLink(Symbols.server_person, AppLocalizations.of(context).accountInfo, () { Navigator.push( @@ -518,7 +518,7 @@ class _DashboardScreenState extends State { MaterialPageRoute( builder: (context) => const ManageBeneficiariesScreen())); - }, disable: true), + }, disable: false), _buildQuickLink(Symbols.support_agent, AppLocalizations.of(context).contactUs, () { Navigator.push( diff --git a/lib/features/dashboard/widgets/account_card.dart b/lib/features/dashboard/widgets/account_card.dart index 0b746f8..c0ac225 100644 --- a/lib/features/dashboard/widgets/account_card.dart +++ b/lib/features/dashboard/widgets/account_card.dart @@ -70,7 +70,7 @@ class AccountCard extends StatelessWidget { const SizedBox(height: 5), Text( AppLocalizations.of(context).availableBalance, - style: TextStyle(color: Colors.white70, fontSize: 12), + style: TextStyle(color: Theme.of(context).dialogBackgroundColor, fontSize: 12), ), ], ), diff --git a/lib/features/fund_transfer/screens/tpin_otp_screen.dart b/lib/features/fund_transfer/screens/tpin_otp_screen.dart index 01849df..03ad59d 100644 --- a/lib/features/fund_transfer/screens/tpin_otp_screen.dart +++ b/lib/features/fund_transfer/screens/tpin_otp_screen.dart @@ -106,7 +106,7 @@ class _TpinOtpScreenState extends State { decoration: InputDecoration( counterText: '', filled: true, - fillColor: Colors.blue[50], + fillColor: Theme.of(context).primaryColorLight, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( diff --git a/lib/features/fund_transfer/screens/tpin_set_screen.dart b/lib/features/fund_transfer/screens/tpin_set_screen.dart index 23e40e5..48c9dc0 100644 --- a/lib/features/fund_transfer/screens/tpin_set_screen.dart +++ b/lib/features/fund_transfer/screens/tpin_set_screen.dart @@ -172,7 +172,7 @@ class _TpinSetScreenState extends State { key == '<' ? '⌫' : key, style: TextStyle( fontSize: 20, - color: key == 'Enter' ? Colors.blue : Colors.black, + color: key == 'Enter' ? Theme.of(context).primaryColor : Colors.black, ), ), ), @@ -201,7 +201,7 @@ class _TpinSetScreenState extends State { child: Column( children: [ const Spacer(), - const Icon(Icons.lock_outline, size: 60, color: Colors.blue), + Icon(Icons.lock_outline, size: 60, color: Theme.of(context).primaryColor), const SizedBox(height: 20), Text( getTitle(), diff --git a/lib/features/profile/preferences/color_theme_dialog.dart b/lib/features/profile/preferences/color_theme_dialog.dart index a706d00..2addbae 100644 --- a/lib/features/profile/preferences/color_theme_dialog.dart +++ b/lib/features/profile/preferences/color_theme_dialog.dart @@ -5,7 +5,7 @@ import 'package:kmobile/features/auth/controllers/theme_cubit.dart'; import 'package:kmobile/features/auth/controllers/theme_state.dart'; -void showColorThemeDialog(BuildContext context) { +/*void showColorThemeDialog(BuildContext context) { showDialog( context: context, builder: (_) => AlertDialog( @@ -32,4 +32,50 @@ void showColorThemeDialog(BuildContext context) { ), ), ); -} \ No newline at end of file +}*/ + +class ColorThemeDialog extends StatelessWidget { + const ColorThemeDialog({super.key}); + + @override + Widget build(BuildContext context) { + return SimpleDialog( + title: const Text('Select Color Theme'), + children: [ + ListTile( + leading: const CircleAvatar(backgroundColor: Colors.deepPurple), + title: const Text('Violet'), + onTap: () { + context.read().changeTheme(ThemeType.violet); + Navigator.pop(context); + }, + ), + // ListTile( + // leading: const CircleAvatar(backgroundColor: Colors.green), + // title: const Text('Green'), + // onTap: () { + // context.read().changeTheme(ThemeType.green); + // Navigator.pop(context); + // }, + // ), + // ListTile( + // leading: const CircleAvatar(backgroundColor: Colors.orange), + // title: const Text('Orange'), + // onTap: () { + // context.read().changeTheme(ThemeType.orange); + // Navigator.pop(context); + // }, + // ), + ListTile( + leading: const CircleAvatar(backgroundColor: Colors.blue), + title: const Text('Blue'), + onTap: () { + context.read().changeTheme(ThemeType.blue); + Navigator.pop(context); + }, + ), + ], + ); + } +} + diff --git a/lib/features/profile/preferences/preference_screen.dart b/lib/features/profile/preferences/preference_screen.dart index 4b82bf4..58c8707 100644 --- a/lib/features/profile/preferences/preference_screen.dart +++ b/lib/features/profile/preferences/preference_screen.dart @@ -22,21 +22,26 @@ class PreferenceScreen extends StatelessWidget { 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); - }, - ), - ), + // 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), + onTap: () { + showDialog( + context: context, + builder: (_) => const ColorThemeDialog(), + ); + } ), // Language Selection ListTile(