dark Theme and 18 other changes done
This commit is contained in:
@@ -71,9 +71,9 @@ Dio _createDioClient() {
|
||||
final dio = Dio(
|
||||
BaseOptions(
|
||||
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
|
||||
//'https://kccbmbnk.net', //prod small
|
||||
'https://kccbmbnk.net', //prod small
|
||||
connectTimeout: const Duration(seconds: 60),
|
||||
receiveTimeout: const Duration(seconds: 60),
|
||||
headers: {
|
||||
|
||||
@@ -236,8 +236,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
itemCount: 3,
|
||||
itemBuilder: (_, __) => ListTile(
|
||||
leading: Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
baseColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||
highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
child: CircleAvatar(
|
||||
radius: 12,
|
||||
backgroundColor:
|
||||
@@ -245,8 +245,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
),
|
||||
),
|
||||
title: Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
baseColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||
highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
child: Container(
|
||||
height: 10,
|
||||
width: 100,
|
||||
@@ -255,8 +255,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
),
|
||||
),
|
||||
subtitle: Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
baseColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||
highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
child: Container(
|
||||
height: 8,
|
||||
width: 60,
|
||||
@@ -286,7 +286,7 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
? Symbols.call_received
|
||||
: Symbols.call_made,
|
||||
color: tx.type == 'CR'
|
||||
? Colors.green
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
title: Text(
|
||||
@@ -330,7 +330,7 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const Divider();
|
||||
return Divider(color: Theme.of(context).dividerColor);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -42,7 +42,9 @@ class TransactionDetailsScreen extends StatelessWidget {
|
||||
isCredit
|
||||
? Symbols.call_received
|
||||
: Symbols.call_made,
|
||||
color: isCredit ? Colors.green : Colors.red,
|
||||
color: isCredit
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: Theme.of(context).colorScheme.error,
|
||||
size: 28,
|
||||
),
|
||||
],
|
||||
@@ -51,9 +53,9 @@ class TransactionDetailsScreen extends StatelessWidget {
|
||||
// Date centered
|
||||
Text(
|
||||
transaction.date ?? "",
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.grey,
|
||||
color: Theme.of(context).textTheme.bodySmall?.color,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
@@ -61,7 +63,7 @@ class TransactionDetailsScreen extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
Divider(color: Theme.of(context).dividerColor),
|
||||
Expanded(
|
||||
flex: 5,
|
||||
child: ListView(
|
||||
|
||||
@@ -21,21 +21,47 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
|
||||
var service = getIt<BeneficiaryService>();
|
||||
bool _isLoading = true;
|
||||
List<Beneficiary> _beneficiaries = [];
|
||||
List<Beneficiary> _filteredBeneficiaries = [];
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadBeneficiaries();
|
||||
_searchController.addListener(() {
|
||||
_filterBeneficiaries(_searchController.text);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _loadBeneficiaries() async {
|
||||
final data = await service.fetchBeneficiaryList();
|
||||
setState(() {
|
||||
_beneficiaries = data;
|
||||
_filteredBeneficiaries = data;
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
void _filterBeneficiaries(String query) {
|
||||
setState(() {
|
||||
if (query.isEmpty) {
|
||||
_filteredBeneficiaries = _beneficiaries;
|
||||
} else {
|
||||
_filteredBeneficiaries = _beneficiaries.where((beneficiary) {
|
||||
final lowerQuery = query.toLowerCase();
|
||||
return beneficiary.name.toLowerCase().contains(lowerQuery) ||
|
||||
beneficiary.accountNo.toLowerCase().contains(lowerQuery);
|
||||
}).toList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildShimmerList() {
|
||||
return ListView.builder(
|
||||
itemCount: 6,
|
||||
@@ -63,14 +89,14 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
|
||||
}
|
||||
|
||||
Widget _buildBeneficiaryList() {
|
||||
if (_beneficiaries.isEmpty) {
|
||||
if (_filteredBeneficiaries.isEmpty) {
|
||||
return Center(
|
||||
child: Text(AppLocalizations.of(context).noBeneficiaryFound));
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: _beneficiaries.length,
|
||||
itemCount: _filteredBeneficiaries.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = _beneficiaries[index];
|
||||
final item = _filteredBeneficiaries[index];
|
||||
return ListTile(
|
||||
leading: CircleAvatar(
|
||||
radius: 24,
|
||||
@@ -111,7 +137,27 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
_isLoading ? _buildShimmerList() : _buildBeneficiaryList(),
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: TextField(
|
||||
controller: _searchController,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search by name or account number",
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child:
|
||||
_isLoading ? _buildShimmerList() : _buildBeneficiaryList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
IgnorePointer(
|
||||
child: Center(
|
||||
child: Opacity(
|
||||
|
||||
@@ -35,7 +35,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
|
||||
onTap: () {},
|
||||
disabled: true, // Add this
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
CardManagementTile(
|
||||
icon: Symbols.remove_moderator,
|
||||
label: AppLocalizations.of(context).blockUnblockCard,
|
||||
@@ -49,7 +49,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
|
||||
},
|
||||
disabled: true,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
CardManagementTile(
|
||||
icon: Symbols.password_2,
|
||||
label: AppLocalizations.of(context).changeCardPin,
|
||||
@@ -63,7 +63,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
|
||||
},
|
||||
disabled: true,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
CardManagementTile(
|
||||
icon: Symbols.payment_card,
|
||||
label: AppLocalizations.of(context).viewCardDeatils,
|
||||
@@ -77,7 +77,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
|
||||
},
|
||||
disabled: true,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
],
|
||||
),
|
||||
IgnorePointer(
|
||||
|
||||
@@ -18,7 +18,7 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
||||
title: Text(
|
||||
AppLocalizations.of(context).chequeManagement,
|
||||
style:
|
||||
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
|
||||
TextStyle(color: Theme.of(context).textTheme.titleLarge?.color, fontWeight: FontWeight.w500),
|
||||
),
|
||||
centerTitle: false,
|
||||
),
|
||||
@@ -32,7 +32,7 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
||||
label: AppLocalizations.of(context).requestChequeBook,
|
||||
onTap: () {},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.data_alert,
|
||||
label: AppLocalizations.of(context).enquiry,
|
||||
@@ -44,31 +44,31 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.approval_delegation,
|
||||
label: AppLocalizations.of(context).chequeDeposit,
|
||||
onTap: () {},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.front_hand,
|
||||
label: AppLocalizations.of(context).stopCheque,
|
||||
onTap: () {},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.cancel_presentation,
|
||||
label: AppLocalizations.of(context).revokeStop,
|
||||
onTap: () {},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.payments,
|
||||
label: AppLocalizations.of(context).positivePay,
|
||||
onTap: () {},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
],
|
||||
),
|
||||
IgnorePointer(
|
||||
|
||||
@@ -28,11 +28,22 @@ class _FundTransferBeneficiaryScreenState
|
||||
var service = getIt<BeneficiaryService>();
|
||||
bool _isLoading = true;
|
||||
List<Beneficiary> _beneficiaries = [];
|
||||
List<Beneficiary> _filteredBeneficiaries = [];
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadBeneficiaries();
|
||||
_searchController.addListener(() {
|
||||
_filterBeneficiaries(_searchController.text);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _loadBeneficiaries() async {
|
||||
@@ -43,10 +54,25 @@ class _FundTransferBeneficiaryScreenState
|
||||
? b.bankName!.toLowerCase().contains('kangra central')
|
||||
: !b.bankName!.toLowerCase().contains('kangra central'))
|
||||
.toList();
|
||||
_filteredBeneficiaries = _beneficiaries;
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
void _filterBeneficiaries(String query) {
|
||||
setState(() {
|
||||
if (query.isEmpty) {
|
||||
_filteredBeneficiaries = _beneficiaries;
|
||||
} else {
|
||||
_filteredBeneficiaries = _beneficiaries.where((beneficiary) {
|
||||
final lowerQuery = query.toLowerCase();
|
||||
return beneficiary.name.toLowerCase().contains(lowerQuery) ||
|
||||
beneficiary.accountNo.toLowerCase().contains(lowerQuery);
|
||||
}).toList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildShimmerList() {
|
||||
return ListView.builder(
|
||||
itemCount: 6,
|
||||
@@ -74,14 +100,14 @@ class _FundTransferBeneficiaryScreenState
|
||||
}
|
||||
|
||||
Widget _buildBeneficiaryList() {
|
||||
if (_beneficiaries.isEmpty) {
|
||||
if (_filteredBeneficiaries.isEmpty) {
|
||||
return Center(
|
||||
child: Text(AppLocalizations.of(context).noBeneficiaryFound));
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: _beneficiaries.length,
|
||||
itemCount: _filteredBeneficiaries.length,
|
||||
itemBuilder: (context, index) {
|
||||
final beneficiary = _beneficiaries[index];
|
||||
final beneficiary = _filteredBeneficiaries[index];
|
||||
|
||||
// --- Cooldown Logic ---
|
||||
bool isCoolingDown = false;
|
||||
@@ -162,7 +188,27 @@ class _FundTransferBeneficiaryScreenState
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
_isLoading ? _buildShimmerList() : _buildBeneficiaryList(),
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: TextField(
|
||||
controller: _searchController,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search by name or account number",
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child:
|
||||
_isLoading ? _buildShimmerList() : _buildBeneficiaryList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
IgnorePointer(
|
||||
child: Center(
|
||||
child: Opacity(
|
||||
|
||||
@@ -34,66 +34,73 @@ class FundTransferScreen extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
return Stack(
|
||||
children: [
|
||||
ListView(
|
||||
children: [
|
||||
FundTransferManagementTile(
|
||||
icon: Symbols.person,
|
||||
// Restore localization for the label
|
||||
label: "Self Pay",
|
||||
onTap: () {
|
||||
// The accounts list is passed directly from the constructor
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => FundTransferSelfAccountsScreen(
|
||||
debitAccountNo: creditAccountNo,
|
||||
remitterName: remitterName,
|
||||
accounts: accounts,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
// Disable the tile if the state is not Authenticated
|
||||
disable: state is! Authenticated,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
FundTransferManagementTile(
|
||||
icon: Symbols.input_circle,
|
||||
// Restore localization for the label
|
||||
label: AppLocalizations.of(context).ownBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => FundTransferBeneficiaryScreen(
|
||||
creditAccountNo: creditAccountNo,
|
||||
remitterName: remitterName,
|
||||
isOwnBank: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
FundTransferManagementTile(
|
||||
icon: Symbols.output_circle,
|
||||
// Restore localization for the label
|
||||
label: AppLocalizations.of(context).outsideBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => FundTransferBeneficiaryScreen(
|
||||
creditAccountNo: creditAccountNo,
|
||||
remitterName: remitterName,
|
||||
isOwnBank: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
],
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: FundTransferManagementTile(
|
||||
icon: Symbols.person,
|
||||
label: "Self Pay",
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
FundTransferSelfAccountsScreen(
|
||||
debitAccountNo: creditAccountNo,
|
||||
remitterName: remitterName,
|
||||
accounts: accounts,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
disable: state is! Authenticated,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Expanded(
|
||||
child: FundTransferManagementTile(
|
||||
icon: Symbols.input_circle,
|
||||
label: AppLocalizations.of(context).ownBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
FundTransferBeneficiaryScreen(
|
||||
creditAccountNo: creditAccountNo,
|
||||
remitterName: remitterName,
|
||||
isOwnBank: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Expanded(
|
||||
child: FundTransferManagementTile(
|
||||
icon: Symbols.output_circle,
|
||||
label: AppLocalizations.of(context).outsideBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
FundTransferBeneficiaryScreen(
|
||||
creditAccountNo: creditAccountNo,
|
||||
remitterName: remitterName,
|
||||
isOwnBank: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IgnorePointer(
|
||||
child: Center(
|
||||
@@ -133,12 +140,44 @@ class FundTransferManagementTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Icon(icon),
|
||||
title: Text(label),
|
||||
trailing: const Icon(Symbols.arrow_right, size: 20),
|
||||
onTap: onTap,
|
||||
enabled: !disable,
|
||||
final theme = Theme.of(context);
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
elevation: 4, // Add some elevation for better visual separation
|
||||
child: InkWell(
|
||||
onTap: disable ? null : onTap, // Disable InkWell if the tile is disabled
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
size: 48, // Make icon larger
|
||||
color:
|
||||
disable ? theme.disabledColor : theme.colorScheme.primary,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
label,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: disable
|
||||
? theme.disabledColor
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,6 +308,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context);
|
||||
final theme = Theme.of(context);
|
||||
final isDarkMode = theme.brightness == Brightness.dark;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -320,83 +322,75 @@ Widget build(BuildContext context) {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
children: [
|
||||
// ===== Profile Header =====
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Avatar
|
||||
Container(
|
||||
width: 56,
|
||||
height: 56,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.grey.shade200,
|
||||
image: const DecorationImage(
|
||||
image: AssetImage('assets/images/logo.png'),
|
||||
fit: BoxFit.cover,
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
children: [
|
||||
// Avatar
|
||||
Container(
|
||||
width: 56,
|
||||
height: 56,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: theme.colorScheme.surface,
|
||||
image: const DecorationImage(
|
||||
image: AssetImage('assets/images/logo.png'),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
// Name + mobile
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
// If you want to show the user's name instead, replace below.
|
||||
widget.customerName,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
const SizedBox(width: 12),
|
||||
// Name + mobile
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
// If you want to show the user's name instead, replace below.
|
||||
widget.customerName,
|
||||
style: theme.textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
widget.customerNo,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade600,
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
widget.customerNo,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color:
|
||||
theme.colorScheme.onSurface.withOpacity(0.7),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Edit/Profile button (optional)
|
||||
TextButton.icon(
|
||||
onPressed: () {
|
||||
// TODO: Navigate to edit profile if required
|
||||
},
|
||||
icon: const Icon(Icons.edit, size: 18),
|
||||
label: const Text("Edit"),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Colors.blueGrey.shade700,
|
||||
// Edit/Profile button (optional)
|
||||
TextButton.icon(
|
||||
onPressed: () {
|
||||
// TODO: Navigate to edit profile if required
|
||||
},
|
||||
icon: const Icon(Icons.edit, size: 18),
|
||||
label: const Text("Edit"),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// ===== Section: Settings =====
|
||||
const Text(
|
||||
"Settings",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.2,
|
||||
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),
|
||||
@@ -439,18 +433,7 @@ Widget build(BuildContext context) {
|
||||
);
|
||||
},
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
Card(
|
||||
child: SwitchListTile(
|
||||
title: Text(loc.enableFingerprintLogin),
|
||||
value: _isBiometricEnabled,
|
||||
@@ -467,35 +450,27 @@ Widget build(BuildContext context) {
|
||||
const Divider(height: 24),
|
||||
|
||||
// ===== Section: Security & App =====
|
||||
Text(
|
||||
loc.appVersion,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.2,
|
||||
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
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
Card(
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.smartphone),
|
||||
title: Text(loc.appVersion),
|
||||
trailing: FutureBuilder<String>(
|
||||
future: _getAppVersion(),
|
||||
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||
builder:
|
||||
(BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const SizedBox(
|
||||
width: 18,
|
||||
@@ -507,7 +482,6 @@ Widget build(BuildContext context) {
|
||||
} else {
|
||||
return Text(
|
||||
snapshot.data ?? "N/A",
|
||||
selectionColor: const Color(0xFFFFFFFF),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -524,12 +498,14 @@ Widget build(BuildContext context) {
|
||||
const Divider(height: 24),
|
||||
|
||||
// ===== Section: Actions =====
|
||||
const Text(
|
||||
"Exit",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.2,
|
||||
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),
|
||||
@@ -608,6 +584,7 @@ Widget build(BuildContext context) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SectionTile extends StatelessWidget {
|
||||
const _SectionTile({
|
||||
required this.leadingIcon,
|
||||
@@ -623,23 +600,16 @@ class _SectionTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ListTile(
|
||||
leading: Icon(leadingIcon),
|
||||
title: Text(title),
|
||||
trailing: trailChevron ? const Icon(Icons.chevron_right) : null,
|
||||
leading: Icon(leadingIcon, color: theme.colorScheme.onSurface),
|
||||
title: Text(title, style: theme.textTheme.bodyLarge),
|
||||
trailing: trailChevron
|
||||
? Icon(Icons.chevron_right, color: theme.colorScheme.onSurface)
|
||||
: null,
|
||||
onTap: onTap,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
|
||||
@@ -40,7 +40,7 @@ class SecuritySettingsScreen extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.pin),
|
||||
title: Text(loc.changeMpin),
|
||||
@@ -57,13 +57,13 @@ class SecuritySettingsScreen extends StatelessWidget {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(loc.mpinChangedSuccessfully),
|
||||
backgroundColor: Colors.green,
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.password),
|
||||
title: const Text('Change TPIN'),
|
||||
|
||||
@@ -23,39 +23,46 @@ class _QuickPayScreen extends State<QuickPayScreen> {
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
ListView(
|
||||
children: [
|
||||
QuickPayManagementTile(
|
||||
icon: Symbols.input_circle,
|
||||
label: AppLocalizations.of(context).ownBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => QuickPayWithinBankScreen(
|
||||
debitAccount: widget.debitAccount,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
QuickPayManagementTile(
|
||||
icon: Symbols.output_circle,
|
||||
label: AppLocalizations.of(context).outsideBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => QuickPayOutsideBankScreen(
|
||||
debitAccount: widget.debitAccount,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
],
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: QuickPayManagementTile(
|
||||
icon: Symbols.input_circle,
|
||||
label: AppLocalizations.of(context).ownBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => QuickPayWithinBankScreen(
|
||||
debitAccount: widget.debitAccount,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Expanded(
|
||||
child: QuickPayManagementTile(
|
||||
icon: Symbols.output_circle,
|
||||
label: AppLocalizations.of(context).outsideBank,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => QuickPayOutsideBankScreen(
|
||||
debitAccount: widget.debitAccount,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IgnorePointer(
|
||||
child: Center(
|
||||
@@ -93,12 +100,42 @@ class QuickPayManagementTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Icon(icon),
|
||||
title: Text(label),
|
||||
trailing: const Icon(Symbols.arrow_right, size: 20),
|
||||
onTap: onTap,
|
||||
enabled: !disable,
|
||||
final theme = Theme.of(context);
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
elevation: 4, // Add some elevation for better visual separation
|
||||
child: InkWell(
|
||||
onTap: disable ? null : onTap, // Disable InkWell if the tile is disabled
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 36.0, horizontal: 16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
size: 64, // Make icon larger for two cards
|
||||
color:
|
||||
disable ? theme.disabledColor : theme.colorScheme.primary,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
label,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: disable
|
||||
? theme.disabledColor
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,17 @@
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildDetailRow("Branch Name", branch.branch_name),
|
||||
_buildDetailRow("Branch Code", branch.branch_code),
|
||||
_buildDetailRow("Zone", branch.zone),
|
||||
_buildDetailRow("Tehsil", branch.tehsil),
|
||||
_buildDetailRow("Block", branch.block),
|
||||
_buildDetailRow("District", branch.distt_name),
|
||||
_buildDetailRow("Pincode", branch.pincode),
|
||||
// _buildDetailRow("Post Office", branch.post_office),
|
||||
// _buildDetailRow("Date of Opening", branch.date_of_opening),
|
||||
// _buildDetailRow("Branch Type", branch.type_of_branch),
|
||||
_buildDetailRow("Telephone No.", branch.telephone_no),
|
||||
_buildDetailRow(context, "Branch Name", branch.branch_name),
|
||||
_buildDetailRow(context, "Branch Code", branch.branch_code),
|
||||
_buildDetailRow(context, "Zone", branch.zone),
|
||||
_buildDetailRow(context, "Tehsil", branch.tehsil),
|
||||
_buildDetailRow(context, "Block", branch.block),
|
||||
_buildDetailRow(context, "District", branch.distt_name),
|
||||
_buildDetailRow(context, "Pincode", branch.pincode),
|
||||
// _buildDetailRow(context, "Post Office", branch.post_office),
|
||||
// _buildDetailRow(context, "Date of Opening", branch.date_of_opening),
|
||||
// _buildDetailRow(context, "Branch Type", branch.type_of_branch),
|
||||
_buildDetailRow(context, "Telephone No.", branch.telephone_no),
|
||||
// _buildDetailRow("RTGS Account No.", branch.rtgs_acct_no),
|
||||
// _buildDetailRow("RBI Code 1", branch.rbi_code_1),
|
||||
// _buildDetailRow("RBI Code 2", branch.rbi_code_2),
|
||||
@@ -58,46 +58,46 @@
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDetailRow(String label, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[600],
|
||||
Widget _buildDetailRow(BuildContext context, String label, String value) {
|
||||
final theme = Theme.of(context);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: theme.textTheme.bodySmall?.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
label == "Telephone No."
|
||||
? InkWell(
|
||||
onTap: () => _launchUrl('tel:$value'),
|
||||
child: Text(
|
||||
const SizedBox(height: 4),
|
||||
label == "Telephone No."
|
||||
? InkWell(
|
||||
onTap: () => _launchUrl('tel:$value'),
|
||||
child: Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: theme.colorScheme.primary, // Indicate it's clickable
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
value,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.blue, // Indicate it's clickable
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
value,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const Divider(height: 16),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Divider(height: 16, color: theme.dividerColor),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Future<void> _launchUrl(String urlString) async {
|
||||
final Uri url = Uri.parse(urlString);
|
||||
if (!await launchUrl(url)) {
|
||||
|
||||
@@ -56,7 +56,12 @@ class BranchLocatorScreen extends StatefulWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Branch Locator"),
|
||||
title: Text(
|
||||
"Branch Locator",
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
|
||||
@@ -54,7 +54,7 @@ class _ServiceScreen extends State<ServiceScreen> {
|
||||
},
|
||||
disabled: false,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ServiceManagementTile(
|
||||
icon: Symbols.question_mark,
|
||||
label: AppLocalizations.of(context).faq,
|
||||
@@ -65,7 +65,7 @@ class _ServiceScreen extends State<ServiceScreen> {
|
||||
},
|
||||
disabled: false,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ServiceManagementTile(
|
||||
icon: Symbols.location_pin,
|
||||
label: "ATM Locator",
|
||||
@@ -77,7 +77,7 @@ class _ServiceScreen extends State<ServiceScreen> {
|
||||
},
|
||||
disabled: false,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
],
|
||||
),
|
||||
IgnorePointer(
|
||||
|
||||
Reference in New Issue
Block a user