Code Formatted
This commit is contained in:
@@ -1,47 +1,47 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
class Branch{
|
class Branch {
|
||||||
final String branch_code;
|
final String branch_code;
|
||||||
final String branch_name;
|
final String branch_name;
|
||||||
final String zone;
|
final String zone;
|
||||||
final String tehsil;
|
final String tehsil;
|
||||||
final String block;
|
final String block;
|
||||||
final String block_code;
|
final String block_code;
|
||||||
final String distt_name;
|
final String distt_name;
|
||||||
final String distt_code_slbc;
|
final String distt_code_slbc;
|
||||||
final String date_of_opening;
|
final String date_of_opening;
|
||||||
final String rbi_code_1;
|
final String rbi_code_1;
|
||||||
final String rbi_code_2;
|
final String rbi_code_2;
|
||||||
final String telephone_no;
|
final String telephone_no;
|
||||||
final String type_of_branch;
|
final String type_of_branch;
|
||||||
final String rtgs_acct_no;
|
final String rtgs_acct_no;
|
||||||
final String br_lattitude;
|
final String br_lattitude;
|
||||||
final String br_longitude;
|
final String br_longitude;
|
||||||
final String pincode;
|
final String pincode;
|
||||||
final String post_office;
|
final String post_office;
|
||||||
|
|
||||||
Branch({
|
Branch({
|
||||||
required this.branch_code,
|
required this.branch_code,
|
||||||
required this.branch_name,
|
required this.branch_name,
|
||||||
required this.zone,
|
required this.zone,
|
||||||
required this.tehsil,
|
required this.tehsil,
|
||||||
required this.block,
|
required this.block,
|
||||||
required this.block_code,
|
required this.block_code,
|
||||||
required this.distt_name,
|
required this.distt_name,
|
||||||
required this.distt_code_slbc,
|
required this.distt_code_slbc,
|
||||||
required this.date_of_opening,
|
required this.date_of_opening,
|
||||||
required this.rbi_code_1,
|
required this.rbi_code_1,
|
||||||
required this.rbi_code_2,
|
required this.rbi_code_2,
|
||||||
required this.telephone_no,
|
required this.telephone_no,
|
||||||
required this.type_of_branch,
|
required this.type_of_branch,
|
||||||
required this.rtgs_acct_no,
|
required this.rtgs_acct_no,
|
||||||
required this.br_lattitude,
|
required this.br_lattitude,
|
||||||
required this.br_longitude,
|
required this.br_longitude,
|
||||||
required this.pincode,
|
required this.pincode,
|
||||||
required this.post_office,
|
required this.post_office,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Branch.fromJson(Map<String, dynamic> json) {
|
factory Branch.fromJson(Map<String, dynamic> json) {
|
||||||
return Branch(
|
return Branch(
|
||||||
branch_code: json['branch_code'] ?? json['branch_code'] ?? '',
|
branch_code: json['branch_code'] ?? json['branch_code'] ?? '',
|
||||||
branch_name: json['branch_name'] ?? json['branch_name'] ?? '',
|
branch_name: json['branch_name'] ?? json['branch_name'] ?? '',
|
||||||
@@ -60,33 +60,32 @@ factory Branch.fromJson(Map<String, dynamic> json) {
|
|||||||
br_lattitude: json['br_lattitude'] ?? json['br_lattitude'] ?? '',
|
br_lattitude: json['br_lattitude'] ?? json['br_lattitude'] ?? '',
|
||||||
br_longitude: json['br_longitude'] ?? json['br_longitude'] ?? '',
|
br_longitude: json['br_longitude'] ?? json['br_longitude'] ?? '',
|
||||||
pincode: json['pincode'] ?? json['pincode'] ?? '',
|
pincode: json['pincode'] ?? json['pincode'] ?? '',
|
||||||
post_office: json['post_office'] ?? json['post_office'] ?? '',
|
post_office: json['post_office'] ?? json['post_office'] ?? '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<Branch> listFromJson(List<dynamic> jsonList) {
|
static List<Branch> listFromJson(List<dynamic> jsonList) {
|
||||||
final beneficiaryList = jsonList
|
final beneficiaryList =
|
||||||
.map((beneficiary) => Branch.fromJson(beneficiary))
|
jsonList.map((beneficiary) => Branch.fromJson(beneficiary)).toList();
|
||||||
.toList();
|
|
||||||
return beneficiaryList;
|
return beneficiaryList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Atm {
|
class Atm {
|
||||||
final String name;
|
final String name;
|
||||||
|
|
||||||
Atm({required this.name});
|
Atm({required this.name});
|
||||||
|
|
||||||
factory Atm.fromJson(Map<String, dynamic> json) {
|
factory Atm.fromJson(Map<String, dynamic> json) {
|
||||||
return Atm(
|
return Atm(
|
||||||
name: json['name'] ?? '', // Assuming the API returns a 'name' field
|
name: json['name'] ?? '', // Assuming the API returns a 'name' field
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<Atm> listFromJson(List<dynamic> jsonList) {
|
static List<Atm> listFromJson(List<dynamic> jsonList) {
|
||||||
return jsonList.map((atm) => Atm.fromJson(atm)).toList();
|
return jsonList.map((atm) => Atm.fromJson(atm)).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BranchService {
|
class BranchService {
|
||||||
final Dio _dio;
|
final Dio _dio;
|
||||||
@@ -113,7 +112,7 @@ class BranchService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Atm>> fetchAtmList() async {
|
Future<List<Atm>> fetchAtmList() async {
|
||||||
try {
|
try {
|
||||||
final response = await _dio.get(
|
final response = await _dio.get(
|
||||||
"/api/atm",
|
"/api/atm",
|
||||||
@@ -134,4 +133,4 @@ class BranchService {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ Dio _createDioClient() {
|
|||||||
final dio = Dio(
|
final dio = Dio(
|
||||||
BaseOptions(
|
BaseOptions(
|
||||||
baseUrl:
|
baseUrl:
|
||||||
'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080', //test
|
'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080', //test
|
||||||
//'http://lb-kccb-mobile-banking-app-848675342.ap-south-1.elb.amazonaws.com', //prod
|
//'http://lb-kccb-mobile-banking-app-848675342.ap-south-1.elb.amazonaws.com', //prod
|
||||||
//'https://kccbmbnk.net', //prod small
|
//'https://kccbmbnk.net', //prod small
|
||||||
connectTimeout: const Duration(seconds: 60),
|
connectTimeout: const Duration(seconds: 60),
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
|||||||
? fromDate!.add(const Duration(days: 183))
|
? fromDate!.add(const Duration(days: 183))
|
||||||
: now;
|
: now;
|
||||||
final initialToDate = toDate ?? now;
|
final initialToDate = toDate ?? now;
|
||||||
final clampedInitialToDate = initialToDate.isBefore(fromDate!) ? fromDate! : initialToDate;
|
final clampedInitialToDate =
|
||||||
|
initialToDate.isBefore(fromDate!) ? fromDate! : initialToDate;
|
||||||
final picked = await showDatePicker(
|
final picked = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: clampedInitialToDate,
|
initialDate: clampedInitialToDate,
|
||||||
@@ -238,8 +239,11 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
|||||||
itemCount: 3,
|
itemCount: 3,
|
||||||
itemBuilder: (_, __) => ListTile(
|
itemBuilder: (_, __) => ListTile(
|
||||||
leading: Shimmer.fromColors(
|
leading: Shimmer.fromColors(
|
||||||
baseColor: Theme.of(context).colorScheme.surfaceVariant,
|
baseColor:
|
||||||
highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
Theme.of(context).colorScheme.surfaceVariant,
|
||||||
|
highlightColor: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurfaceVariant,
|
||||||
child: CircleAvatar(
|
child: CircleAvatar(
|
||||||
radius: 12,
|
radius: 12,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
@@ -247,8 +251,11 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Shimmer.fromColors(
|
title: Shimmer.fromColors(
|
||||||
baseColor: Theme.of(context).colorScheme.surfaceVariant,
|
baseColor:
|
||||||
highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
Theme.of(context).colorScheme.surfaceVariant,
|
||||||
|
highlightColor: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurfaceVariant,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 10,
|
height: 10,
|
||||||
width: 100,
|
width: 100,
|
||||||
@@ -257,8 +264,11 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
subtitle: Shimmer.fromColors(
|
subtitle: Shimmer.fromColors(
|
||||||
baseColor: Theme.of(context).colorScheme.surfaceVariant,
|
baseColor:
|
||||||
highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
Theme.of(context).colorScheme.surfaceVariant,
|
||||||
|
highlightColor: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurfaceVariant,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 8,
|
height: 8,
|
||||||
width: 60,
|
width: 60,
|
||||||
@@ -288,7 +298,9 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
|||||||
? Symbols.call_received
|
? Symbols.call_received
|
||||||
: Symbols.call_made,
|
: Symbols.call_made,
|
||||||
color: tx.type == 'CR'
|
color: tx.type == 'CR'
|
||||||
? Theme.of(context).colorScheme.secondary
|
? Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondary
|
||||||
: Theme.of(context).colorScheme.error,
|
: Theme.of(context).colorScheme.error,
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
@@ -332,7 +344,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) {
|
separatorBuilder: (context, index) {
|
||||||
return Divider(color: Theme.of(context).dividerColor);
|
return Divider(
|
||||||
|
color: Theme.of(context).dividerColor);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ class _AllAccountsScreenState extends State<AllAccountsScreen> {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final user = widget.users[index];
|
final user = widget.users[index];
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
child: _buildAccountCard(user),
|
child: _buildAccountCard(user),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ class BeneficiaryDetailsScreen extends StatelessWidget {
|
|||||||
_showSuccessDialog(context);
|
_showSuccessDialog(context);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('${AppLocalizations.of(context).failedToDeleteBeneficiary} : $e')),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'${AppLocalizations.of(context).failedToDeleteBeneficiary} : $e')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +35,8 @@ class BeneficiaryDetailsScreen extends StatelessWidget {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text(AppLocalizations.of(context).success),
|
title: Text(AppLocalizations.of(context).success),
|
||||||
content: Text(AppLocalizations.of(context).beneficiaryDeletedSuccessfully),
|
content:
|
||||||
|
Text(AppLocalizations.of(context).beneficiaryDeletedSuccessfully),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(AppLocalizations.of(context).ok),
|
child: Text(AppLocalizations.of(context).ok),
|
||||||
@@ -53,8 +56,8 @@ class BeneficiaryDetailsScreen extends StatelessWidget {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text(AppLocalizations.of(context).deleteBeneficiary),
|
title: Text(AppLocalizations.of(context).deleteBeneficiary),
|
||||||
content:
|
content: Text(AppLocalizations.of(context)
|
||||||
Text(AppLocalizations.of(context).areYouSureYouWantToDeleteThisBeneficiary),
|
.areYouSureYouWantToDeleteThisBeneficiary),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(AppLocalizations.of(context).cancel),
|
child: Text(AppLocalizations.of(context).cancel),
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
AppLocalizations.of(context).chequeManagement,
|
AppLocalizations.of(context).chequeManagement,
|
||||||
style:
|
style: TextStyle(
|
||||||
TextStyle(color: Theme.of(context).textTheme.titleLarge?.color, fontWeight: FontWeight.w500),
|
color: Theme.of(context).textTheme.titleLarge?.color,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -125,143 +125,144 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
child: Transform.translate(
|
child: Transform.translate(
|
||||||
offset: isSelected ? const Offset(10.0, 0.0) : Offset.zero,
|
offset: isSelected ? const Offset(10.0, 0.0) : Offset.zero,
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 2),
|
margin: const EdgeInsets.symmetric(horizontal: 2),
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 18,
|
horizontal: 18,
|
||||||
vertical: 10,
|
vertical: 10,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF01A04C),
|
color: const Color(0xFF01A04C),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// Top section with account type and number (no refresh button here)
|
// Top section with account type and number (no refresh button here)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
getFullAccountType(user.accountType),
|
|
||||||
style: TextStyle(
|
|
||||||
color: theme.colorScheme.onPrimary,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
user.accountNo ?? 'N/A',
|
|
||||||
style: TextStyle(
|
|
||||||
color: theme.colorScheme.onPrimary,
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isSelected) // Show logo only if card is selected
|
|
||||||
CircleAvatar(
|
|
||||||
radius: 20,
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(2.0),
|
|
||||||
child: ClipOval(
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/logo.png',
|
|
||||||
width: 30,
|
|
||||||
height: 30,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
// Bottom section with balance and combined toggle/refresh
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
if (isRefreshing && isSelected)
|
|
||||||
Expanded(child: _buildBalanceShimmer())
|
|
||||||
else
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FittedBox(
|
child: Column(
|
||||||
fit: BoxFit.scaleDown,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
alignment: Alignment.centerLeft,
|
children: [
|
||||||
child: Row(
|
Text(
|
||||||
children: [
|
getFullAccountType(user.accountType),
|
||||||
Text(
|
style: TextStyle(
|
||||||
"₹ ",
|
color: theme.colorScheme.onPrimary,
|
||||||
style: TextStyle(
|
fontSize: 16,
|
||||||
color: theme.colorScheme.onPrimary,
|
fontWeight: FontWeight.w700,
|
||||||
fontSize: 40,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Text(
|
),
|
||||||
isCardVisible
|
Text(
|
||||||
? user.currentBalance ?? '0.00'
|
user.accountNo ?? 'N/A',
|
||||||
: '*****',
|
style: TextStyle(
|
||||||
style: TextStyle(
|
color: theme.colorScheme.onPrimary,
|
||||||
color: theme.colorScheme.onPrimary,
|
fontSize: 14,
|
||||||
fontSize: 40,
|
fontWeight: FontWeight.w700,
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10), // A steady space
|
if (isSelected) // Show logo only if card is selected
|
||||||
if (isSelected) // Only show toggle for selected card
|
CircleAvatar(
|
||||||
InkWell(
|
radius: 20,
|
||||||
onTap: () async {
|
backgroundColor: Colors.white,
|
||||||
if (isRefreshing) return; // Prevent taps while refreshing
|
child: Padding(
|
||||||
final accountNo = user.accountNo;
|
padding: const EdgeInsets.all(2.0),
|
||||||
if (accountNo == null) return;
|
child: ClipOval(
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/logo.png',
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
// Bottom section with balance and combined toggle/refresh
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (isRefreshing && isSelected)
|
||||||
|
Expanded(child: _buildBalanceShimmer())
|
||||||
|
else
|
||||||
|
Expanded(
|
||||||
|
child: FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"₹ ",
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme.colorScheme.onPrimary,
|
||||||
|
fontSize: 40,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
isCardVisible
|
||||||
|
? user.currentBalance ?? '0.00'
|
||||||
|
: '*****',
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme.colorScheme.onPrimary,
|
||||||
|
fontSize: 40,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10), // A steady space
|
||||||
|
if (isSelected) // Only show toggle for selected card
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
if (isRefreshing)
|
||||||
|
return; // Prevent taps while refreshing
|
||||||
|
final accountNo = user.accountNo;
|
||||||
|
if (accountNo == null) return;
|
||||||
|
|
||||||
final bool currentVisibility =
|
final bool currentVisibility =
|
||||||
_visibilityMap[accountNo] ?? false;
|
_visibilityMap[accountNo] ?? false;
|
||||||
|
|
||||||
if (!currentVisibility) {
|
if (!currentVisibility) {
|
||||||
// If hidden, refresh data and then show the balance
|
// If hidden, refresh data and then show the balance
|
||||||
await _refreshAccountData(context);
|
await _refreshAccountData(context);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_visibilityMap[accountNo] = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If visible, just hide it
|
||||||
setState(() {
|
setState(() {
|
||||||
_visibilityMap[accountNo] = true;
|
_visibilityMap[accountNo] = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
// If visible, just hide it
|
child: Padding(
|
||||||
setState(() {
|
padding: const EdgeInsets.all(8.0),
|
||||||
_visibilityMap[accountNo] = false;
|
child: Icon(
|
||||||
});
|
isCardVisible
|
||||||
}
|
? Symbols.visibility_lock
|
||||||
},
|
: Symbols.visibility,
|
||||||
child: Padding(
|
color: theme.scaffoldBackgroundColor,
|
||||||
padding: const EdgeInsets.all(8.0),
|
weight: 800,
|
||||||
child: Icon(
|
),
|
||||||
isCardVisible
|
|
||||||
? Symbols.visibility_lock
|
|
||||||
: Symbols.visibility,
|
|
||||||
color: theme.scaffoldBackgroundColor,
|
|
||||||
weight: 800,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
const Spacer(),
|
||||||
const Spacer(),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,8 +326,7 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
return Shimmer.fromColors(
|
return Shimmer.fromColors(
|
||||||
baseColor: theme.colorScheme.primary,
|
baseColor: theme.colorScheme.primary,
|
||||||
highlightColor: theme.colorScheme.onPrimary,
|
highlightColor: theme.colorScheme.onPrimary,
|
||||||
child: Container(
|
child: Container(height: 36, color: theme.scaffoldBackgroundColor),
|
||||||
height: 36, color: theme.scaffoldBackgroundColor),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,8 +445,8 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
final authState = context.read<AuthCubit>().state;
|
final authState = context.read<AuthCubit>().state;
|
||||||
String mobileNumberToPass = '';
|
String mobileNumberToPass = '';
|
||||||
String customerNo ='';
|
String customerNo = '';
|
||||||
String customerName = '';
|
String customerName = '';
|
||||||
if (authState is Authenticated) {
|
if (authState is Authenticated) {
|
||||||
if (selectedAccountIndex >= 0 &&
|
if (selectedAccountIndex >= 0 &&
|
||||||
selectedAccountIndex < authState.users.length) {
|
selectedAccountIndex < authState.users.length) {
|
||||||
@@ -454,7 +454,7 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
authState.users[selectedAccountIndex].mobileNo ?? '';
|
authState.users[selectedAccountIndex].mobileNo ?? '';
|
||||||
customerNo =
|
customerNo =
|
||||||
authState.users[selectedAccountIndex].cifNumber ?? '';
|
authState.users[selectedAccountIndex].cifNumber ?? '';
|
||||||
customerName=
|
customerName =
|
||||||
authState.users[selectedAccountIndex].name ?? '';
|
authState.users[selectedAccountIndex].name ?? '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,8 +462,10 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) => ProfileScreen(
|
||||||
ProfileScreen(mobileNumber: mobileNumberToPass, customerNo: customerNo, customerName: customerName),
|
mobileNumber: mobileNumberToPass,
|
||||||
|
customerNo: customerNo,
|
||||||
|
customerName: customerName),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -535,25 +537,31 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
|
|
||||||
// Account Info Cards
|
// Account Info Cards
|
||||||
ClipRect(
|
ClipRect(
|
||||||
child: SizedBox( // This SizedBox defines the height for the Stack
|
child: SizedBox(
|
||||||
|
// This SizedBox defines the height for the Stack
|
||||||
height: 160,
|
height: 160,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
// PageView part, painted underneath
|
// PageView part, painted underneath
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 48.0), // Space for tab (40) + gap (8)
|
padding: const EdgeInsets.only(
|
||||||
child: SizedBox( // Keep SizedBox for PageView height
|
left: 48.0), // Space for tab (40) + gap (8)
|
||||||
|
child: SizedBox(
|
||||||
|
// Keep SizedBox for PageView height
|
||||||
height: 160,
|
height: 160,
|
||||||
child: PageView.builder(
|
child: PageView.builder(
|
||||||
controller: _pageController,
|
controller: _pageController,
|
||||||
itemCount: users.length,
|
itemCount: users.length,
|
||||||
clipBehavior: Clip.none, // Keep this to show adjacent cards
|
clipBehavior: Clip
|
||||||
|
.none, // Keep this to show adjacent cards
|
||||||
padEnds: false,
|
padEnds: false,
|
||||||
onPageChanged: (int newIndex) async {
|
onPageChanged: (int newIndex) async {
|
||||||
if (newIndex == selectedAccountIndex) return;
|
if (newIndex == selectedAccountIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
// Hide the balance of the old card when scrolling away
|
// Hide the balance of the old card when scrolling away
|
||||||
final oldAccountNo = users[selectedAccountIndex].accountNo;
|
final oldAccountNo =
|
||||||
|
users[selectedAccountIndex].accountNo;
|
||||||
if (oldAccountNo != null) {
|
if (oldAccountNo != null) {
|
||||||
_visibilityMap[oldAccountNo] = false;
|
_visibilityMap[oldAccountNo] = false;
|
||||||
}
|
}
|
||||||
@@ -561,15 +569,17 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
setState(() {
|
setState(() {
|
||||||
selectedAccountIndex = newIndex;
|
selectedAccountIndex = newIndex;
|
||||||
});
|
});
|
||||||
|
|
||||||
await _loadTransactions(
|
await _loadTransactions(
|
||||||
users[newIndex].accountNo!,
|
users[newIndex].accountNo!,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final user = users[index];
|
final user = users[index];
|
||||||
final isSelected = index == selectedAccountIndex;
|
final isSelected =
|
||||||
return _buildAccountCard(user, isSelected);
|
index == selectedAccountIndex;
|
||||||
|
return _buildAccountCard(
|
||||||
|
user, isSelected);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -715,7 +725,6 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -777,9 +786,7 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
Icon(
|
Icon(
|
||||||
icon,
|
icon,
|
||||||
size: 30,
|
size: 30,
|
||||||
color: disable
|
color: disable ? theme.disabledColor : theme.colorScheme.primary,
|
||||||
? theme.disabledColor
|
|
||||||
: theme.colorScheme.primary,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
@@ -788,9 +795,8 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
style: theme.textTheme.titleMedium?.copyWith(
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: disable
|
color:
|
||||||
? theme.disabledColor
|
disable ? theme.disabledColor : theme.colorScheme.onSurface,
|
||||||
: theme.colorScheme.onSurface,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -799,4 +805,3 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,10 @@ class _EnquiryScreen extends State<EnquiryScreen> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => _launchPhoneNumber(phone),
|
onTap: () => _launchPhoneNumber(phone),
|
||||||
child: Text(phone,
|
child: Text(phone,
|
||||||
style:
|
style: TextStyle(
|
||||||
TextStyle(color: Theme.of(context).colorScheme.primary)), // Changed color for visibility
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primary)), // Changed color for visibility
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -91,14 +93,16 @@ class _EnquiryScreen extends State<EnquiryScreen> {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => _launchUrl("https://kccbhp.bank.in/complaint-form/"),
|
onTap: () =>
|
||||||
|
_launchUrl("https://kccbhp.bank.in/complaint-form/"),
|
||||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
Text(
|
Text(
|
||||||
"Complaint Form",
|
"Complaint Form",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 17,
|
fontSize: 17,
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
decoration: TextDecoration.underline, // Added underline for link clarity
|
decoration: TextDecoration
|
||||||
|
.underline, // Added underline for link clarity
|
||||||
decorationColor:
|
decorationColor:
|
||||||
Theme.of(context).colorScheme.primary,
|
Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
@@ -165,4 +169,4 @@ class _EnquiryScreen extends State<EnquiryScreen> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,7 +492,8 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
if (_isLoadingLimit) Text(AppLocalizations.of(context).fetchingDailyLimit),
|
if (_isLoadingLimit)
|
||||||
|
Text(AppLocalizations.of(context).fetchingDailyLimit),
|
||||||
if (!_isLoadingLimit && _limit != null)
|
if (!_isLoadingLimit && _limit != null)
|
||||||
Text(
|
Text(
|
||||||
'Remaining Daily Limit: ${_formatCurrency.format(_limit!.dailyLimit - _limit!.usedLimit)}',
|
'Remaining Daily Limit: ${_formatCurrency.format(_limit!.dailyLimit - _limit!.usedLimit)}',
|
||||||
|
|||||||
@@ -148,7 +148,8 @@ class FundTransferManagementTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
elevation: 4, // Add some elevation for better visual separation
|
elevation: 4, // Add some elevation for better visual separation
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: disable ? null : onTap, // Disable InkWell if the tile is disabled
|
onTap:
|
||||||
|
disable ? null : onTap, // Disable InkWell if the tile is disabled
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ class ProfileScreen extends StatefulWidget {
|
|||||||
final String mobileNumber;
|
final String mobileNumber;
|
||||||
final String customerNo;
|
final String customerNo;
|
||||||
final String customerName;
|
final String customerName;
|
||||||
const ProfileScreen({super.key, required this.mobileNumber, required this.customerNo, required this.customerName});
|
const ProfileScreen(
|
||||||
|
{super.key,
|
||||||
|
required this.mobileNumber,
|
||||||
|
required this.customerNo,
|
||||||
|
required this.customerName});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ProfileScreen> createState() => _ProfileScreenState();
|
State<ProfileScreen> createState() => _ProfileScreenState();
|
||||||
@@ -306,283 +310,283 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final loc = AppLocalizations.of(context);
|
final loc = AppLocalizations.of(context);
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final isDarkMode = theme.brightness == Brightness.dark;
|
final isDarkMode = theme.brightness == Brightness.dark;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(loc.profile),
|
title: Text(loc.profile),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
),
|
),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
ListView(
|
ListView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
children: [
|
children: [
|
||||||
// ===== Profile Header =====
|
// ===== Profile Header =====
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
// Avatar
|
// Avatar
|
||||||
Container(
|
Container(
|
||||||
width: 56,
|
width: 56,
|
||||||
height: 56,
|
height: 56,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: theme.colorScheme.surface,
|
color: theme.colorScheme.surface,
|
||||||
image: const DecorationImage(
|
image: const DecorationImage(
|
||||||
image: AssetImage('assets/images/logo.png'),
|
image: AssetImage('assets/images/logo.png'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 12),
|
||||||
const SizedBox(width: 12),
|
// Name + mobile
|
||||||
// Name + mobile
|
Expanded(
|
||||||
Expanded(
|
child: Column(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
Text(
|
||||||
Text(
|
// If you want to show the user's name instead, replace below.
|
||||||
// If you want to show the user's name instead, replace below.
|
widget.customerName,
|
||||||
widget.customerName,
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
style: theme.textTheme.titleLarge?.copyWith(
|
fontWeight: FontWeight.w600,
|
||||||
fontWeight: FontWeight.w600,
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 4),
|
||||||
const SizedBox(height: 4),
|
Text(
|
||||||
Text(
|
widget.customerNo,
|
||||||
widget.customerNo,
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
color: theme.colorScheme.onSurface
|
||||||
color:
|
.withOpacity(0.7),
|
||||||
theme.colorScheme.onSurface.withOpacity(0.7),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
// Edit/Profile button (optional)
|
||||||
// Edit/Profile button (optional)
|
TextButton.icon(
|
||||||
TextButton.icon(
|
onPressed: () {
|
||||||
onPressed: () {
|
// TODO: Navigate to edit profile if required
|
||||||
// TODO: Navigate to edit profile if required
|
},
|
||||||
},
|
icon: const Icon(Icons.edit, size: 18),
|
||||||
icon: const Icon(Icons.edit, size: 18),
|
label: const Text("Edit"),
|
||||||
label: const Text("Edit"),
|
style: TextButton.styleFrom(
|
||||||
style: TextButton.styleFrom(
|
foregroundColor: theme.colorScheme.onSurface,
|
||||||
foregroundColor: theme.colorScheme.onSurface,
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// ===== Section: Settings =====
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: Text(
|
|
||||||
"Settings",
|
|
||||||
style: theme.textTheme.labelLarge?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: 0.2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
|
|
||||||
_SectionTile(
|
|
||||||
leadingIcon: Icons.settings,
|
|
||||||
title: loc.preferences,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const PreferenceScreen(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_SectionTile(
|
|
||||||
leadingIcon: Icons.security,
|
|
||||||
title: loc.securitySettings,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => SecuritySettingsScreen(
|
|
||||||
mobileNumber: widget.mobileNumber,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_SectionTile(
|
|
||||||
leadingIcon: Icons.currency_rupee,
|
|
||||||
title: loc.dailylimit,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const DailyLimitScreen(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Card(
|
|
||||||
child: SwitchListTile(
|
|
||||||
title: Text(loc.enableFingerprintLogin),
|
|
||||||
value: _isBiometricEnabled,
|
|
||||||
onChanged: (bool value) {
|
|
||||||
_handleBiometricToggle(value);
|
|
||||||
},
|
|
||||||
secondary: const Icon(Icons.fingerprint),
|
|
||||||
contentPadding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
const Divider(height: 24),
|
|
||||||
|
|
||||||
// ===== Section: Security & App =====
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: Text(
|
|
||||||
loc.appVersion,
|
|
||||||
style: theme.textTheme.labelLarge?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: 0.2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
|
|
||||||
// Fingerprint toggle inside a styled container
|
|
||||||
Card(
|
|
||||||
child: ListTile(
|
|
||||||
leading: const Icon(Icons.smartphone),
|
|
||||||
title: Text(loc.appVersion),
|
|
||||||
trailing: FutureBuilder<String>(
|
|
||||||
future: _getAppVersion(),
|
|
||||||
builder:
|
|
||||||
(BuildContext context, AsyncSnapshot<String> snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return const SizedBox(
|
|
||||||
width: 18,
|
|
||||||
height: 18,
|
|
||||||
child: CircularProgressIndicator(strokeWidth: 2),
|
|
||||||
);
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Text(loc.error);
|
|
||||||
} else {
|
|
||||||
return Text(
|
|
||||||
snapshot.data ?? "N/A",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
contentPadding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
const Divider(height: 24),
|
|
||||||
|
|
||||||
// ===== Section: Actions =====
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: Text(
|
|
||||||
"Exit",
|
|
||||||
style: theme.textTheme.labelLarge?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: 0.2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
|
|
||||||
_SectionTile(
|
|
||||||
leadingIcon: Icons.exit_to_app,
|
|
||||||
title: loc.logout,
|
|
||||||
trailChevron: false, // action tile, no chevron
|
|
||||||
onTap: () async {
|
|
||||||
final shouldExit = await showDialog<bool>(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
title: Text(loc.logout),
|
|
||||||
content: Text(loc.logoutCheck),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
|
||||||
child: Text(loc.no),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
|
||||||
child: Text(loc.yes),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
),
|
||||||
|
|
||||||
if (shouldExit == true) {
|
const SizedBox(height: 16),
|
||||||
if (Platform.isAndroid) {
|
|
||||||
SystemNavigator.pop();
|
// ===== Section: Settings =====
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"Settings",
|
||||||
|
style: theme.textTheme.labelLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: 0.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
|
_SectionTile(
|
||||||
|
leadingIcon: Icons.settings,
|
||||||
|
title: loc.preferences,
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const PreferenceScreen(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_SectionTile(
|
||||||
|
leadingIcon: Icons.security,
|
||||||
|
title: loc.securitySettings,
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => SecuritySettingsScreen(
|
||||||
|
mobileNumber: widget.mobileNumber,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_SectionTile(
|
||||||
|
leadingIcon: Icons.currency_rupee,
|
||||||
|
title: loc.dailylimit,
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const DailyLimitScreen(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Card(
|
||||||
|
child: SwitchListTile(
|
||||||
|
title: Text(loc.enableFingerprintLogin),
|
||||||
|
value: _isBiometricEnabled,
|
||||||
|
onChanged: (bool value) {
|
||||||
|
_handleBiometricToggle(value);
|
||||||
|
},
|
||||||
|
secondary: const Icon(Icons.fingerprint),
|
||||||
|
contentPadding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const Divider(height: 24),
|
||||||
|
|
||||||
|
// ===== Section: Security & App =====
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Text(
|
||||||
|
loc.appVersion,
|
||||||
|
style: theme.textTheme.labelLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: 0.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
|
// Fingerprint toggle inside a styled container
|
||||||
|
Card(
|
||||||
|
child: ListTile(
|
||||||
|
leading: const Icon(Icons.smartphone),
|
||||||
|
title: Text(loc.appVersion),
|
||||||
|
trailing: FutureBuilder<String>(
|
||||||
|
future: _getAppVersion(),
|
||||||
|
builder:
|
||||||
|
(BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return const SizedBox(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
|
);
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Text(loc.error);
|
||||||
|
} else {
|
||||||
|
return Text(
|
||||||
|
snapshot.data ?? "N/A",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
contentPadding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const Divider(height: 24),
|
||||||
|
|
||||||
|
// ===== Section: Actions =====
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"Exit",
|
||||||
|
style: theme.textTheme.labelLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: 0.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
|
_SectionTile(
|
||||||
|
leadingIcon: Icons.exit_to_app,
|
||||||
|
title: loc.logout,
|
||||||
|
trailChevron: false, // action tile, no chevron
|
||||||
|
onTap: () async {
|
||||||
|
final shouldExit = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text(loc.logout),
|
||||||
|
content: Text(loc.logoutCheck),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
child: Text(loc.no),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
child: Text(loc.yes),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shouldExit == true) {
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
SystemNavigator.pop();
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
exit(0);
|
},
|
||||||
}
|
),
|
||||||
},
|
_SectionTile(
|
||||||
),
|
leadingIcon: Icons.logout,
|
||||||
_SectionTile(
|
title: loc.deregister,
|
||||||
leadingIcon: Icons.logout,
|
trailChevron: false,
|
||||||
title: loc.deregister,
|
onTap: () async {
|
||||||
trailChevron: false,
|
final shouldLogout = await showDialog<bool>(
|
||||||
onTap: () async {
|
context: context,
|
||||||
final shouldLogout = await showDialog<bool>(
|
builder: (_) => const LogoutDialog(),
|
||||||
context: context,
|
);
|
||||||
builder: (_) => const LogoutDialog(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (shouldLogout == true) {
|
if (shouldLogout == true) {
|
||||||
await _handleLogout(context);
|
await _handleLogout(context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
// ===== Watermark (kept subtle, no theme change) =====
|
// ===== Watermark (kept subtle, no theme change) =====
|
||||||
IgnorePointer(
|
IgnorePointer(
|
||||||
child: Positioned.fill(
|
child: Positioned.fill(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: 0.06,
|
opacity: 0.06,
|
||||||
child: ClipOval(
|
child: ClipOval(
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/logo.png',
|
'assets/images/logo.png',
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 200,
|
height: 200,
|
||||||
filterQuality: FilterQuality.medium,
|
filterQuality: FilterQuality.medium,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SectionTile extends StatelessWidget {
|
class _SectionTile extends StatelessWidget {
|
||||||
@@ -611,8 +615,7 @@ class _SectionTile extends StatelessWidget {
|
|||||||
? Icon(Icons.chevron_right, color: theme.colorScheme.onSurface)
|
? Icon(Icons.chevron_right, color: theme.colorScheme.onSurface)
|
||||||
: null,
|
: null,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
contentPadding:
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ class SecuritySettingsScreen extends StatelessWidget {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(loc.mpinChangedSuccessfully),
|
content: Text(loc.mpinChangedSuccessfully),
|
||||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.secondary,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ class QuickPayManagementTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
elevation: 4, // Add some elevation for better visual separation
|
elevation: 4, // Add some elevation for better visual separation
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: disable ? null : onTap, // Disable InkWell if the tile is disabled
|
onTap:
|
||||||
|
disable ? null : onTap, // Disable InkWell if the tile is disabled
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 36.0, horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(vertical: 36.0, horizontal: 16.0),
|
||||||
|
|||||||
@@ -15,10 +15,12 @@ class ATMLocatorScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _ATMLocatorScreenState extends State<ATMLocatorScreen> {
|
class _ATMLocatorScreenState extends State<ATMLocatorScreen> {
|
||||||
final TextEditingController _searchController = TextEditingController();
|
final TextEditingController _searchController = TextEditingController();
|
||||||
var service = getIt<BranchService>(); // Added: Instance of BranchService for API calls
|
var service =
|
||||||
|
getIt<BranchService>(); // Added: Instance of BranchService for API calls
|
||||||
bool _isLoading = true; // State variable to manage loading status
|
bool _isLoading = true; // State variable to manage loading status
|
||||||
List<Atm> _allAtms = []; // Changed: List to hold all fetched Atm objects
|
List<Atm> _allAtms = []; // Changed: List to hold all fetched Atm objects
|
||||||
List<Atm> _filteredAtms = []; // Changed: List to hold filtered Atm objects for display
|
List<Atm> _filteredAtms =
|
||||||
|
[]; // Changed: List to hold filtered Atm objects for display
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -28,7 +30,8 @@ class _ATMLocatorScreenState extends State<ATMLocatorScreen> {
|
|||||||
|
|
||||||
/// Fetches the list of ATMs from the API using BranchService.
|
/// Fetches the list of ATMs from the API using BranchService.
|
||||||
Future<void> _loadAtms() async {
|
Future<void> _loadAtms() async {
|
||||||
final data = await service.fetchAtmList(); // Call the new fetchAtmList method
|
final data =
|
||||||
|
await service.fetchAtmList(); // Call the new fetchAtmList method
|
||||||
setState(() {
|
setState(() {
|
||||||
_allAtms = data; // Update the list of all ATMs
|
_allAtms = data; // Update the list of all ATMs
|
||||||
_filteredAtms = data; // Initialize filtered list with all ATMs
|
_filteredAtms = data; // Initialize filtered list with all ATMs
|
||||||
@@ -37,14 +40,18 @@ class _ATMLocatorScreenState extends State<ATMLocatorScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Filters the list of ATMs based on the search query.
|
/// Filters the list of ATMs based on the search query.
|
||||||
void _filterAtms(String query) { // Changed: Renamed from _filterLocations
|
void _filterAtms(String query) {
|
||||||
|
// Changed: Renamed from _filterLocations
|
||||||
setState(() {
|
setState(() {
|
||||||
if (query.isEmpty) {
|
if (query.isEmpty) {
|
||||||
_filteredAtms = _allAtms; // If query is empty, show all ATMs
|
_filteredAtms = _allAtms; // If query is empty, show all ATMs
|
||||||
} else {
|
} else {
|
||||||
_filteredAtms = _allAtms.where((atm) { // Changed: Filter based on Atm object
|
_filteredAtms = _allAtms.where((atm) {
|
||||||
|
// Changed: Filter based on Atm object
|
||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
return atm.name.toLowerCase().contains(lowerQuery); // Filter by atm.name
|
return atm.name
|
||||||
|
.toLowerCase()
|
||||||
|
.contains(lowerQuery); // Filter by atm.name
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -64,7 +71,8 @@ class _ATMLocatorScreenState extends State<ATMLocatorScreen> {
|
|||||||
padding: const EdgeInsets.all(12.0),
|
padding: const EdgeInsets.all(12.0),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
onChanged: _filterAtms, // Updated: Call _filterAtms on text change
|
onChanged:
|
||||||
|
_filterAtms, // Updated: Call _filterAtms on text change
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Name/Address", // Hint text for the search bar
|
hintText: "Name/Address", // Hint text for the search bar
|
||||||
prefixIcon: const Icon(Icons.search), // Search icon
|
prefixIcon: const Icon(Icons.search), // Search icon
|
||||||
@@ -81,12 +89,16 @@ class _ATMLocatorScreenState extends State<ATMLocatorScreen> {
|
|||||||
? _buildShimmerList() // Display shimmer while loading
|
? _buildShimmerList() // Display shimmer while loading
|
||||||
: _filteredAtms.isEmpty
|
: _filteredAtms.isEmpty
|
||||||
? const Center(
|
? const Center(
|
||||||
child: Text("No matching ATMs found")) // Message if no ATMs found
|
child: Text(
|
||||||
|
"No matching ATMs found")) // Message if no ATMs found
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
itemCount: _filteredAtms.length, // Number of items in the filtered list
|
itemCount: _filteredAtms
|
||||||
|
.length, // Number of items in the filtered list
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final atm = _filteredAtms[index]; // Get the current Atm object
|
final atm = _filteredAtms[
|
||||||
return _buildAtmItem(atm); // Build the ATM list item
|
index]; // Get the current Atm object
|
||||||
|
return _buildAtmItem(
|
||||||
|
atm); // Build the ATM list item
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -111,9 +123,9 @@ class _ATMLocatorScreenState extends State<ATMLocatorScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Helper widget to build a single ATM list item.
|
/// Helper widget to build a single ATM list item.
|
||||||
Widget _buildAtmItem(Atm atm) { // Changed: Takes an Atm object
|
Widget _buildAtmItem(Atm atm) {
|
||||||
|
// Changed: Takes an Atm object
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
|||||||
@@ -1,107 +1,109 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:kmobile/api/services/branch_service.dart';
|
import 'package:kmobile/api/services/branch_service.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class BranchDetailsScreen extends StatelessWidget {
|
class BranchDetailsScreen extends StatelessWidget {
|
||||||
final Branch branch;
|
final Branch branch;
|
||||||
|
|
||||||
const BranchDetailsScreen({super.key, required this.branch});
|
const BranchDetailsScreen({super.key, required this.branch});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(branch.branch_name),
|
title: Text(branch.branch_name),
|
||||||
),
|
),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
SingleChildScrollView(
|
SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildDetailRow(context, "Branch Name", branch.branch_name),
|
_buildDetailRow(context, "Branch Name", branch.branch_name),
|
||||||
_buildDetailRow(context, "Branch Code", branch.branch_code),
|
_buildDetailRow(context, "Branch Code", branch.branch_code),
|
||||||
_buildDetailRow(context, "Zone", branch.zone),
|
_buildDetailRow(context, "Zone", branch.zone),
|
||||||
_buildDetailRow(context, "Tehsil", branch.tehsil),
|
_buildDetailRow(context, "Tehsil", branch.tehsil),
|
||||||
_buildDetailRow(context, "Block", branch.block),
|
_buildDetailRow(context, "Block", branch.block),
|
||||||
_buildDetailRow(context, "District", branch.distt_name),
|
_buildDetailRow(context, "District", branch.distt_name),
|
||||||
_buildDetailRow(context, "Pincode", branch.pincode),
|
_buildDetailRow(context, "Pincode", branch.pincode),
|
||||||
// _buildDetailRow(context, "Post Office", branch.post_office),
|
// _buildDetailRow(context, "Post Office", branch.post_office),
|
||||||
// _buildDetailRow(context, "Date of Opening", branch.date_of_opening),
|
// _buildDetailRow(context, "Date of Opening", branch.date_of_opening),
|
||||||
// _buildDetailRow(context, "Branch Type", branch.type_of_branch),
|
// _buildDetailRow(context, "Branch Type", branch.type_of_branch),
|
||||||
_buildDetailRow(context, "Telephone No.", branch.telephone_no),
|
_buildDetailRow(context, "Telephone No.", branch.telephone_no),
|
||||||
// _buildDetailRow("RTGS Account No.", branch.rtgs_acct_no),
|
// _buildDetailRow("RTGS Account No.", branch.rtgs_acct_no),
|
||||||
// _buildDetailRow("RBI Code 1", branch.rbi_code_1),
|
// _buildDetailRow("RBI Code 1", branch.rbi_code_1),
|
||||||
// _buildDetailRow("RBI Code 2", branch.rbi_code_2),
|
// _buildDetailRow("RBI Code 2", branch.rbi_code_2),
|
||||||
// _buildDetailRow("Latitude", branch.br_lattitude),
|
// _buildDetailRow("Latitude", branch.br_lattitude),
|
||||||
// _buildDetailRow("Longitude", branch.br_longitude),
|
// _buildDetailRow("Longitude", branch.br_longitude),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
IgnorePointer(
|
IgnorePointer(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: 0.07, // Reduced opacity
|
opacity: 0.07, // Reduced opacity
|
||||||
child: ClipOval(
|
child: ClipOval(
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/logo.png',
|
'assets/images/logo.png',
|
||||||
width: 200, // Adjust size as needed
|
width: 200, // Adjust size as needed
|
||||||
height: 200, // Adjust size as needed
|
height: 200, // Adjust size as needed
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDetailRow(BuildContext context, String label, String value) {
|
Widget _buildDetailRow(BuildContext context, String label, String value) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: theme.textTheme.bodySmall?.color,
|
color: theme.textTheme.bodySmall?.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
label == "Telephone No."
|
label == "Telephone No."
|
||||||
? InkWell(
|
? InkWell(
|
||||||
onTap: () => _launchUrl('tel:$value'),
|
onTap: () => _launchUrl('tel:$value'),
|
||||||
child: Text(
|
child: Text(
|
||||||
value,
|
value,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: theme.colorScheme.primary, // Indicate it's clickable
|
color:
|
||||||
decoration: TextDecoration.underline,
|
theme.colorScheme.primary, // Indicate it's clickable
|
||||||
),
|
decoration: TextDecoration.underline,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
: Text(
|
)
|
||||||
value,
|
: Text(
|
||||||
style: const TextStyle(
|
value,
|
||||||
fontSize: 16,
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontSize: 16,
|
||||||
),
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
Divider(height: 16, color: theme.dividerColor),
|
),
|
||||||
],
|
Divider(height: 16, color: theme.dividerColor),
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
}
|
);
|
||||||
Future<void> _launchUrl(String urlString) async {
|
}
|
||||||
final Uri url = Uri.parse(urlString);
|
|
||||||
if (!await launchUrl(url)) {
|
Future<void> _launchUrl(String urlString) async {
|
||||||
throw 'Could not launch $urlString';
|
final Uri url = Uri.parse(urlString);
|
||||||
}
|
if (!await launchUrl(url)) {
|
||||||
}
|
throw 'Could not launch $urlString';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import 'package:kmobile/di/injection.dart';
|
|||||||
import 'package:shimmer/shimmer.dart';
|
import 'package:shimmer/shimmer.dart';
|
||||||
import 'package:kmobile/features/service/screens/branch_details_screen.dart';
|
import 'package:kmobile/features/service/screens/branch_details_screen.dart';
|
||||||
|
|
||||||
|
|
||||||
class BranchLocatorScreen extends StatefulWidget {
|
class BranchLocatorScreen extends StatefulWidget {
|
||||||
const BranchLocatorScreen({super.key});
|
const BranchLocatorScreen({super.key});
|
||||||
|
|
||||||
@@ -15,52 +14,51 @@ class BranchLocatorScreen extends StatefulWidget {
|
|||||||
State<BranchLocatorScreen> createState() => _BranchLocatorScreenState();
|
State<BranchLocatorScreen> createState() => _BranchLocatorScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BranchLocatorScreenState extends State<BranchLocatorScreen> {
|
class _BranchLocatorScreenState extends State<BranchLocatorScreen> {
|
||||||
final TextEditingController _searchController = TextEditingController();
|
final TextEditingController _searchController = TextEditingController();
|
||||||
var service = getIt<BranchService>();
|
var service = getIt<BranchService>();
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
List<Branch> _allBranches = [];
|
List<Branch> _allBranches = [];
|
||||||
List<Branch> _filteredBranches = [];
|
List<Branch> _filteredBranches = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// _fetchAndSetLocations();
|
// _fetchAndSetLocations();
|
||||||
_loadBranches();
|
_loadBranches();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadBranches() async {
|
Future<void> _loadBranches() async {
|
||||||
final data = await service.fetchBranchList();
|
final data = await service.fetchBranchList();
|
||||||
setState(() {
|
setState(() {
|
||||||
_allBranches = data;
|
_allBranches = data;
|
||||||
_filteredBranches = data;
|
_filteredBranches = data;
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _filterBranches(String query) {
|
void _filterBranches(String query) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (query.isEmpty) {
|
if (query.isEmpty) {
|
||||||
_filteredBranches = _allBranches;
|
_filteredBranches = _allBranches;
|
||||||
} else {
|
} else {
|
||||||
_filteredBranches = _allBranches.where((branch) {
|
_filteredBranches = _allBranches.where((branch) {
|
||||||
final lowerQuery = query.toLowerCase();
|
final lowerQuery = query.toLowerCase();
|
||||||
return branch.branch_name.toLowerCase().contains(lowerQuery);
|
return branch.branch_name.toLowerCase().contains(lowerQuery);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
"Branch Locator",
|
"Branch Locator",
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
@@ -88,11 +86,13 @@ class BranchLocatorScreen extends StatefulWidget {
|
|||||||
? _buildShimmerList() // Changed to shimmer
|
? _buildShimmerList() // Changed to shimmer
|
||||||
: _filteredBranches.isEmpty
|
: _filteredBranches.isEmpty
|
||||||
? const Center(
|
? const Center(
|
||||||
child: Text("No matching branches found")) // Updated tex
|
child: Text(
|
||||||
|
"No matching branches found")) // Updated tex
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
itemCount: _filteredBranches.length,
|
itemCount: _filteredBranches.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final branch = _filteredBranches[index]; // Changed to
|
final branch =
|
||||||
|
_filteredBranches[index]; // Changed to
|
||||||
return _buildBranchItem(branch); // Updated
|
return _buildBranchItem(branch); // Updated
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -132,7 +132,7 @@ class BranchLocatorScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper widget to build a single branch item
|
// Helper widget to build a single branch item
|
||||||
|
|
||||||
Widget _buildBranchItem(Branch branch) {
|
Widget _buildBranchItem(Branch branch) {
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||||
@@ -155,7 +155,6 @@ class BranchLocatorScreen extends StatefulWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Shimmer loading list
|
// Shimmer loading list
|
||||||
Widget _buildShimmerList() {
|
Widget _buildShimmerList() {
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
|||||||
@@ -110,4 +110,4 @@ class _FaqsScreenState extends State<FaqsScreen> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,113 +1,113 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:kmobile/l10n/app_localizations.dart';
|
import 'package:kmobile/l10n/app_localizations.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
// Data model for a single Quick Link item
|
// Data model for a single Quick Link item
|
||||||
class QuickLink {
|
class QuickLink {
|
||||||
final String title;
|
final String title;
|
||||||
final String url;
|
final String url;
|
||||||
// The icon is no longer used in the UI but is kept in the model for potential future use.
|
// The icon is no longer used in the UI but is kept in the model for potential future use.
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
|
|
||||||
QuickLink({required this.title, required this.url, required this.icon});
|
QuickLink({required this.title, required this.url, required this.icon});
|
||||||
}
|
}
|
||||||
|
|
||||||
class QuickLinksScreen extends StatefulWidget {
|
class QuickLinksScreen extends StatefulWidget {
|
||||||
const QuickLinksScreen({super.key});
|
const QuickLinksScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<QuickLinksScreen> createState() => _QuickLinksScreenState();
|
State<QuickLinksScreen> createState() => _QuickLinksScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _QuickLinksScreenState extends State<QuickLinksScreen> {
|
class _QuickLinksScreenState extends State<QuickLinksScreen> {
|
||||||
// List of Quick Links
|
// List of Quick Links
|
||||||
final List<QuickLink> _quickLinks = [
|
final List<QuickLink> _quickLinks = [
|
||||||
QuickLink(
|
QuickLink(
|
||||||
title: "National Bank of Agriculture & Rural Development",
|
title: "National Bank of Agriculture & Rural Development",
|
||||||
url: "http://www.nabard.org/",
|
url: "http://www.nabard.org/",
|
||||||
icon: Icons.account_balance),
|
icon: Icons.account_balance),
|
||||||
QuickLink(
|
QuickLink(
|
||||||
title: "Reserve Bank of India",
|
title: "Reserve Bank of India",
|
||||||
url: "http://www.rbi.org.in/home.aspx",
|
url: "http://www.rbi.org.in/home.aspx",
|
||||||
icon: Icons.account_balance_wallet),
|
icon: Icons.account_balance_wallet),
|
||||||
QuickLink(
|
QuickLink(
|
||||||
title: "Indian Institute of Banking & Finance",
|
title: "Indian Institute of Banking & Finance",
|
||||||
url: "http://www.iibf.org.in/",
|
url: "http://www.iibf.org.in/",
|
||||||
icon: Icons.school),
|
icon: Icons.school),
|
||||||
QuickLink(
|
QuickLink(
|
||||||
title: "Indian Bank Association",
|
title: "Indian Bank Association",
|
||||||
url: "http://www.iba.org.in/",
|
url: "http://www.iba.org.in/",
|
||||||
icon: Icons.group_work),
|
icon: Icons.group_work),
|
||||||
QuickLink(
|
QuickLink(
|
||||||
title: "Ministry of Finance",
|
title: "Ministry of Finance",
|
||||||
url: "http://www.finmin.nic.in/",
|
url: "http://www.finmin.nic.in/",
|
||||||
icon: Icons.business),
|
icon: Icons.business),
|
||||||
QuickLink(
|
QuickLink(
|
||||||
title: "Securities Exchange Board of India",
|
title: "Securities Exchange Board of India",
|
||||||
url: "http://www.sebi.gov.in/",
|
url: "http://www.sebi.gov.in/",
|
||||||
icon: Icons.show_chart),
|
icon: Icons.show_chart),
|
||||||
QuickLink(
|
QuickLink(
|
||||||
title: "Insurance Regulatory & Development Authority",
|
title: "Insurance Regulatory & Development Authority",
|
||||||
url: "https://www.irdai.gov.in/",
|
url: "https://www.irdai.gov.in/",
|
||||||
icon: Icons.shield_outlined),
|
icon: Icons.shield_outlined),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Function to launch a URL
|
// Function to launch a URL
|
||||||
Future<void> _launchURL(String url, BuildContext context) async {
|
Future<void> _launchURL(String url, BuildContext context) async {
|
||||||
final Uri uri = Uri.parse(url);
|
final Uri uri = Uri.parse(url);
|
||||||
if (await canLaunchUrl(uri)) {
|
if (await canLaunchUrl(uri)) {
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Could not launch $url')),
|
SnackBar(content: Text('Could not launch $url')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(AppLocalizations.of(context).quickLinks),
|
title: Text(AppLocalizations.of(context).quickLinks),
|
||||||
),
|
),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
// Background logo
|
// Background logo
|
||||||
IgnorePointer(
|
IgnorePointer(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: 0.07,
|
opacity: 0.07,
|
||||||
child: ClipOval(
|
child: ClipOval(
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/logo.png',
|
'assets/images/logo.png',
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 200,
|
height: 200,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// UPDATED: List of Quick Links
|
// UPDATED: List of Quick Links
|
||||||
ListView.builder(
|
ListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
itemCount: _quickLinks.length,
|
itemCount: _quickLinks.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final link = _quickLinks[index];
|
final link = _quickLinks[index];
|
||||||
return Card(
|
return Card(
|
||||||
margin:
|
margin:
|
||||||
const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
|
const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(link.title),
|
title: Text(link.title),
|
||||||
trailing: const Icon(Icons.open_in_new, size: 20),
|
trailing: const Icon(Icons.open_in_new, size: 20),
|
||||||
onTap: () => _launchURL(link.url, context),
|
onTap: () => _launchURL(link.url, context),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ class _ServiceScreen extends State<ServiceScreen> {
|
|||||||
label: AppLocalizations.of(context).faq,
|
label: AppLocalizations.of(context).faq,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => const FaqsScreen()),
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const FaqsScreen()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@@ -120,7 +121,8 @@ class ServiceManagementTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
elevation: 4, // Add some elevation for better visual separation
|
elevation: 4, // Add some elevation for better visual separation
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: disabled ? null : onTap, // Disable InkWell if the tile is disabled
|
onTap:
|
||||||
|
disabled ? null : onTap, // Disable InkWell if the tile is disabled
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
|
||||||
@@ -130,7 +132,8 @@ class ServiceManagementTile extends StatelessWidget {
|
|||||||
Icon(
|
Icon(
|
||||||
icon,
|
icon,
|
||||||
size: 48, // Make icon larger
|
size: 48, // Make icon larger
|
||||||
color: disabled ? theme.disabledColor : theme.colorScheme.primary,
|
color:
|
||||||
|
disabled ? theme.disabledColor : theme.colorScheme.primary,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text(
|
Text(
|
||||||
@@ -138,7 +141,9 @@ class ServiceManagementTile extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: theme.textTheme.titleLarge?.copyWith(
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: disabled ? theme.disabledColor : theme.colorScheme.onSurface,
|
color: disabled
|
||||||
|
? theme.disabledColor
|
||||||
|
: theme.colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user