IFSC Code Validation and Add Beneficiary Validation API integration

This commit is contained in:
2025-08-07 18:12:31 +05:30
parent c4d4261afc
commit 99e23bf21d
17 changed files with 416 additions and 271 deletions

View File

@@ -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()}');
}
}
Future<ifsc?> 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<void> 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<bool> 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;
}
}

View File

@@ -69,48 +69,6 @@ class _KMobileState extends State<KMobile> {
});
}
/* @override
Widget build(BuildContext context) {
// Set status bar color
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
),
);
return MultiBlocProvider(
providers: [
BlocProvider<AuthCubit>(create: (_) => getIt<AuthCubit>()),
BlocProvider<ThemeCubit>(create: (_) => getIt<ThemeCubit>()),
],
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<ThemeCubit>(create: (_) => getIt<ThemeCubit>()),
],
child: BlocBuilder<ThemeCubit, ThemeState>(
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(),

View File

@@ -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<String, dynamic> json) {
return Beneficiary(
accountNo: json['accountNo'] ?? '',
accountType: json['accountType'] ?? '',
name: json['name'] ?? '',
ifscCode: json['ifscCode'] ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'accountNo': accountNo,
'accountType': accountType,
'name': name,
'ifscCode' : ifscCode,
};
}
@override
String toString() {
return 'Beneficiary(accountNo: $accountNo, accountType: $accountType, ifscCode: $ifscCode, name: $name)';
}
}

32
lib/data/models/ifsc.dart Normal file
View File

@@ -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<String, dynamic> json) {
return ifsc(
ifscCode: json['ifsc_code'] ?? '',
bankName: json['bank_name'] ?? '',
branchName: json['branch_name'] ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'ifsc_code': ifscCode,
'bank_name': bankName,
'branch_name': branchName,
};
}
@override
String toString() {
return 'IFSC(ifscCode: $ifscCode, bankName: $bankName, branchName: $branchName)';
}
}

View File

@@ -18,7 +18,7 @@ Future<void> setupDependencies() async {
//getIt.registerLazySingleton<ThemeController>(() => ThemeController());
//getIt.registerLazySingleton<ThemeModeController>(() => ThemeModeController());
getIt.registerLazySingleton<ThemeCubit>(() => ThemeCubit());
getIt.registerSingleton<ThemeCubit>( ThemeCubit());
// Register Dio client
getIt.registerSingleton<Dio>(_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: {

View File

@@ -250,9 +250,9 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
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<AccountStatementScreen> {
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<AccountStatementScreen> {
child: Container(
height: 8,
width: 60,
color: Colors.white,
color: Theme.of(context).scaffoldBackgroundColor,
),
),
),

View File

@@ -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<ThemeState> {
ThemeCubit()
: super(ThemeState(
lightTheme: AppThemes.getLightTheme(ThemeType.violet),
themeMode: ThemeMode.light,
themeType: ThemeType.violet,
)) {
ThemeCubit(): super(ThemeViolet()) {
loadTheme();
}
Future<void> 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<void> 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<void> 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,
));
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<void> 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,
// ));
// }
}

View File

@@ -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<Object?> 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;
}

View File

@@ -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 {
@@ -22,6 +27,8 @@ class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
final TextEditingController ifscController = TextEditingController();
final TextEditingController phoneController = TextEditingController();
bool _isLoading2 = false;
late String accountType;
@override
@@ -34,7 +41,7 @@ class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
});
}
void _submitForm() {
/*void _submitForm() {
if (_formKey.currentState!.validate()) {
// Handle successful submission
ScaffoldMessenger.of(context).showSnackBar(
@@ -56,11 +63,11 @@ class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
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<AddBeneficiaryScreen> {
),
);
}
}
}*/
ifsc? _ifscData;
bool _isLoading = false;
void _validateIFSC() async {
var beneficiaryService = getIt<BeneficiaryService>();
final ifsc = ifscController.text.trim().toUpperCase();
if (ifsc.isEmpty) return;
setState(() {
_isLoading = true;
_ifscData = null;
});
// 🔹 Format check
final isValidFormat = RegExp(r'^[A-Z]{4}0[A-Z0-9]{6}$').hasMatch(ifsc);
if (!isValidFormat) {
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();
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',
},
};
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)),
);
print("Valid IFSC: ${result.bankName}, ${result.branchName}");
bankNameController.text = result.bankName;
branchNameController.text = result.branchName;
}
}
/*
🔸 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'];
String _selectedAccountType = 'Savings'; // default value
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<BeneficiaryService>();
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;
});
}
}
}
@override
Widget build(BuildContext context) {
@@ -263,110 +294,7 @@ class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
? 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<String>(
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<AddBeneficiaryScreen> {
child: SizedBox(
width: 250,
child: ElevatedButton(
onPressed: _submitForm,
onPressed: _isLoading2 ? null :
validateAndAddBeneficiary,
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),

View File

@@ -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),
),
),
);
}
}

View File

@@ -482,7 +482,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
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<DashboardScreen> {
MaterialPageRoute(
builder: (context) =>
const ManageBeneficiariesScreen()));
}, disable: true),
}, disable: false),
_buildQuickLink(Symbols.support_agent,
AppLocalizations.of(context).contactUs, () {
Navigator.push(

View File

@@ -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),
),
],
),

View File

@@ -106,7 +106,7 @@ class _TpinOtpScreenState extends State<TpinOtpScreen> {
decoration: InputDecoration(
counterText: '',
filled: true,
fillColor: Colors.blue[50],
fillColor: Theme.of(context).primaryColorLight,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(

View File

@@ -172,7 +172,7 @@ class _TpinSetScreenState extends State<TpinSetScreen> {
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<TpinSetScreen> {
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(),

View File

@@ -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) {
),
),
);
}*/
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<ThemeCubit>().changeTheme(ThemeType.violet);
Navigator.pop(context);
},
),
// ListTile(
// leading: const CircleAvatar(backgroundColor: Colors.green),
// title: const Text('Green'),
// onTap: () {
// context.read<ThemeCubit>().changeTheme(ThemeType.green);
// Navigator.pop(context);
// },
// ),
// ListTile(
// leading: const CircleAvatar(backgroundColor: Colors.orange),
// title: const Text('Orange'),
// onTap: () {
// context.read<ThemeCubit>().changeTheme(ThemeType.orange);
// Navigator.pop(context);
// },
// ),
ListTile(
leading: const CircleAvatar(backgroundColor: Colors.blue),
title: const Text('Blue'),
onTap: () {
context.read<ThemeCubit>().changeTheme(ThemeType.blue);
Navigator.pop(context);
},
),
],
);
}
}

View File

@@ -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<ThemeCubit>().toggleDarkMode(val);
},
),
),
// ListTile(
// leading: const Icon(Icons.brightness_6),
// title: const Text("Theme Mode"),
// trailing: Switch(
// value: state.isDarkMode,
// onChanged: (val) {
// context.read<ThemeCubit>().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(