dark Theme and 18 other changes done

This commit is contained in:
2025-11-20 12:33:30 +05:30
parent fda5d075ff
commit 4fe6af4098
15 changed files with 484 additions and 339 deletions

View File

@@ -71,9 +71,9 @@ 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),
receiveTimeout: const Duration(seconds: 60), receiveTimeout: const Duration(seconds: 60),
headers: { headers: {

View File

@@ -236,8 +236,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
itemCount: 3, itemCount: 3,
itemBuilder: (_, __) => ListTile( itemBuilder: (_, __) => ListTile(
leading: Shimmer.fromColors( leading: Shimmer.fromColors(
baseColor: Colors.grey[300]!, baseColor: Theme.of(context).colorScheme.surfaceVariant,
highlightColor: Colors.grey[100]!, highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
child: CircleAvatar( child: CircleAvatar(
radius: 12, radius: 12,
backgroundColor: backgroundColor:
@@ -245,8 +245,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
), ),
), ),
title: Shimmer.fromColors( title: Shimmer.fromColors(
baseColor: Colors.grey[300]!, baseColor: Theme.of(context).colorScheme.surfaceVariant,
highlightColor: Colors.grey[100]!, highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
child: Container( child: Container(
height: 10, height: 10,
width: 100, width: 100,
@@ -255,8 +255,8 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
), ),
), ),
subtitle: Shimmer.fromColors( subtitle: Shimmer.fromColors(
baseColor: Colors.grey[300]!, baseColor: Theme.of(context).colorScheme.surfaceVariant,
highlightColor: Colors.grey[100]!, highlightColor: Theme.of(context).colorScheme.onSurfaceVariant,
child: Container( child: Container(
height: 8, height: 8,
width: 60, width: 60,
@@ -286,7 +286,7 @@ 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'
? Colors.green ? Theme.of(context).colorScheme.secondary
: Theme.of(context).colorScheme.error, : Theme.of(context).colorScheme.error,
), ),
title: Text( title: Text(
@@ -330,7 +330,7 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
); );
}, },
separatorBuilder: (context, index) { separatorBuilder: (context, index) {
return const Divider(); return Divider(color: Theme.of(context).dividerColor);
}, },
), ),
), ),

View File

@@ -42,7 +42,9 @@ class TransactionDetailsScreen extends StatelessWidget {
isCredit isCredit
? Symbols.call_received ? Symbols.call_received
: Symbols.call_made, : Symbols.call_made,
color: isCredit ? Colors.green : Colors.red, color: isCredit
? Theme.of(context).colorScheme.secondary
: Theme.of(context).colorScheme.error,
size: 28, size: 28,
), ),
], ],
@@ -51,9 +53,9 @@ class TransactionDetailsScreen extends StatelessWidget {
// Date centered // Date centered
Text( Text(
transaction.date ?? "", transaction.date ?? "",
style: const TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: Colors.grey, color: Theme.of(context).textTheme.bodySmall?.color,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@@ -61,7 +63,7 @@ class TransactionDetailsScreen extends StatelessWidget {
), ),
), ),
), ),
const Divider(), Divider(color: Theme.of(context).dividerColor),
Expanded( Expanded(
flex: 5, flex: 5,
child: ListView( child: ListView(

View File

@@ -21,21 +21,47 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
var service = getIt<BeneficiaryService>(); var service = getIt<BeneficiaryService>();
bool _isLoading = true; bool _isLoading = true;
List<Beneficiary> _beneficiaries = []; List<Beneficiary> _beneficiaries = [];
List<Beneficiary> _filteredBeneficiaries = [];
final TextEditingController _searchController = TextEditingController();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_loadBeneficiaries(); _loadBeneficiaries();
_searchController.addListener(() {
_filterBeneficiaries(_searchController.text);
});
}
@override
void dispose() {
_searchController.dispose();
super.dispose();
} }
Future<void> _loadBeneficiaries() async { Future<void> _loadBeneficiaries() async {
final data = await service.fetchBeneficiaryList(); final data = await service.fetchBeneficiaryList();
setState(() { setState(() {
_beneficiaries = data; _beneficiaries = data;
_filteredBeneficiaries = data;
_isLoading = false; _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() { Widget _buildShimmerList() {
return ListView.builder( return ListView.builder(
itemCount: 6, itemCount: 6,
@@ -63,14 +89,14 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
} }
Widget _buildBeneficiaryList() { Widget _buildBeneficiaryList() {
if (_beneficiaries.isEmpty) { if (_filteredBeneficiaries.isEmpty) {
return Center( return Center(
child: Text(AppLocalizations.of(context).noBeneficiaryFound)); child: Text(AppLocalizations.of(context).noBeneficiaryFound));
} }
return ListView.builder( return ListView.builder(
itemCount: _beneficiaries.length, itemCount: _filteredBeneficiaries.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = _beneficiaries[index]; final item = _filteredBeneficiaries[index];
return ListTile( return ListTile(
leading: CircleAvatar( leading: CircleAvatar(
radius: 24, radius: 24,
@@ -111,7 +137,27 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
), ),
body: Stack( body: Stack(
children: [ 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( IgnorePointer(
child: Center( child: Center(
child: Opacity( child: Opacity(

View File

@@ -35,7 +35,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
onTap: () {}, onTap: () {},
disabled: true, // Add this disabled: true, // Add this
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
CardManagementTile( CardManagementTile(
icon: Symbols.remove_moderator, icon: Symbols.remove_moderator,
label: AppLocalizations.of(context).blockUnblockCard, label: AppLocalizations.of(context).blockUnblockCard,
@@ -49,7 +49,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
}, },
disabled: true, disabled: true,
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
CardManagementTile( CardManagementTile(
icon: Symbols.password_2, icon: Symbols.password_2,
label: AppLocalizations.of(context).changeCardPin, label: AppLocalizations.of(context).changeCardPin,
@@ -63,7 +63,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
}, },
disabled: true, disabled: true,
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
CardManagementTile( CardManagementTile(
icon: Symbols.payment_card, icon: Symbols.payment_card,
label: AppLocalizations.of(context).viewCardDeatils, label: AppLocalizations.of(context).viewCardDeatils,
@@ -77,7 +77,7 @@ class _CardManagementScreen extends State<CardManagementScreen> {
}, },
disabled: true, disabled: true,
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
], ],
), ),
IgnorePointer( IgnorePointer(

View File

@@ -18,7 +18,7 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
title: Text( title: Text(
AppLocalizations.of(context).chequeManagement, AppLocalizations.of(context).chequeManagement,
style: style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500), TextStyle(color: Theme.of(context).textTheme.titleLarge?.color, fontWeight: FontWeight.w500),
), ),
centerTitle: false, centerTitle: false,
), ),
@@ -32,7 +32,7 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
label: AppLocalizations.of(context).requestChequeBook, label: AppLocalizations.of(context).requestChequeBook,
onTap: () {}, onTap: () {},
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
ChequeManagementTile( ChequeManagementTile(
icon: Symbols.data_alert, icon: Symbols.data_alert,
label: AppLocalizations.of(context).enquiry, 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( ChequeManagementTile(
icon: Symbols.approval_delegation, icon: Symbols.approval_delegation,
label: AppLocalizations.of(context).chequeDeposit, label: AppLocalizations.of(context).chequeDeposit,
onTap: () {}, onTap: () {},
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
ChequeManagementTile( ChequeManagementTile(
icon: Symbols.front_hand, icon: Symbols.front_hand,
label: AppLocalizations.of(context).stopCheque, label: AppLocalizations.of(context).stopCheque,
onTap: () {}, onTap: () {},
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
ChequeManagementTile( ChequeManagementTile(
icon: Symbols.cancel_presentation, icon: Symbols.cancel_presentation,
label: AppLocalizations.of(context).revokeStop, label: AppLocalizations.of(context).revokeStop,
onTap: () {}, onTap: () {},
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
ChequeManagementTile( ChequeManagementTile(
icon: Symbols.payments, icon: Symbols.payments,
label: AppLocalizations.of(context).positivePay, label: AppLocalizations.of(context).positivePay,
onTap: () {}, onTap: () {},
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
], ],
), ),
IgnorePointer( IgnorePointer(

View File

@@ -28,11 +28,22 @@ class _FundTransferBeneficiaryScreenState
var service = getIt<BeneficiaryService>(); var service = getIt<BeneficiaryService>();
bool _isLoading = true; bool _isLoading = true;
List<Beneficiary> _beneficiaries = []; List<Beneficiary> _beneficiaries = [];
List<Beneficiary> _filteredBeneficiaries = [];
final TextEditingController _searchController = TextEditingController();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_loadBeneficiaries(); _loadBeneficiaries();
_searchController.addListener(() {
_filterBeneficiaries(_searchController.text);
});
}
@override
void dispose() {
_searchController.dispose();
super.dispose();
} }
Future<void> _loadBeneficiaries() async { Future<void> _loadBeneficiaries() async {
@@ -43,10 +54,25 @@ class _FundTransferBeneficiaryScreenState
? b.bankName!.toLowerCase().contains('kangra central') ? b.bankName!.toLowerCase().contains('kangra central')
: !b.bankName!.toLowerCase().contains('kangra central')) : !b.bankName!.toLowerCase().contains('kangra central'))
.toList(); .toList();
_filteredBeneficiaries = _beneficiaries;
_isLoading = false; _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() { Widget _buildShimmerList() {
return ListView.builder( return ListView.builder(
itemCount: 6, itemCount: 6,
@@ -74,14 +100,14 @@ class _FundTransferBeneficiaryScreenState
} }
Widget _buildBeneficiaryList() { Widget _buildBeneficiaryList() {
if (_beneficiaries.isEmpty) { if (_filteredBeneficiaries.isEmpty) {
return Center( return Center(
child: Text(AppLocalizations.of(context).noBeneficiaryFound)); child: Text(AppLocalizations.of(context).noBeneficiaryFound));
} }
return ListView.builder( return ListView.builder(
itemCount: _beneficiaries.length, itemCount: _filteredBeneficiaries.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final beneficiary = _beneficiaries[index]; final beneficiary = _filteredBeneficiaries[index];
// --- Cooldown Logic --- // --- Cooldown Logic ---
bool isCoolingDown = false; bool isCoolingDown = false;
@@ -162,7 +188,27 @@ class _FundTransferBeneficiaryScreenState
), ),
body: Stack( body: Stack(
children: [ 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( IgnorePointer(
child: Center( child: Center(
child: Opacity( child: Opacity(

View File

@@ -34,66 +34,73 @@ class FundTransferScreen extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return Stack( return Stack(
children: [ children: [
ListView( Padding(
children: [ padding: const EdgeInsets.symmetric(vertical: 16.0),
FundTransferManagementTile( child: Column(
icon: Symbols.person, crossAxisAlignment: CrossAxisAlignment.stretch,
// Restore localization for the label children: [
label: "Self Pay", Expanded(
onTap: () { child: FundTransferManagementTile(
// The accounts list is passed directly from the constructor icon: Symbols.person,
Navigator.push( label: "Self Pay",
context, onTap: () {
MaterialPageRoute( Navigator.push(
builder: (context) => FundTransferSelfAccountsScreen( context,
debitAccountNo: creditAccountNo, MaterialPageRoute(
remitterName: remitterName, builder: (context) =>
accounts: accounts, FundTransferSelfAccountsScreen(
), debitAccountNo: creditAccountNo,
), remitterName: remitterName,
); accounts: accounts,
}, ),
// Disable the tile if the state is not Authenticated ),
disable: state is! Authenticated, );
), },
const Divider(height: 1), disable: state is! Authenticated,
FundTransferManagementTile( ),
icon: Symbols.input_circle, ),
// Restore localization for the label const SizedBox(height: 16),
label: AppLocalizations.of(context).ownBank, Expanded(
onTap: () { child: FundTransferManagementTile(
Navigator.push( icon: Symbols.input_circle,
context, label: AppLocalizations.of(context).ownBank,
MaterialPageRoute( onTap: () {
builder: (context) => FundTransferBeneficiaryScreen( Navigator.push(
creditAccountNo: creditAccountNo, context,
remitterName: remitterName, MaterialPageRoute(
isOwnBank: true, 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: () { const SizedBox(height: 16),
Navigator.push( Expanded(
context, child: FundTransferManagementTile(
MaterialPageRoute( icon: Symbols.output_circle,
builder: (context) => FundTransferBeneficiaryScreen( label: AppLocalizations.of(context).outsideBank,
creditAccountNo: creditAccountNo, onTap: () {
remitterName: remitterName, Navigator.push(
isOwnBank: false, context,
), MaterialPageRoute(
), builder: (context) =>
); FundTransferBeneficiaryScreen(
}, creditAccountNo: creditAccountNo,
), remitterName: remitterName,
const Divider(height: 1), isOwnBank: false,
], ),
),
);
},
),
),
],
),
), ),
IgnorePointer( IgnorePointer(
child: Center( child: Center(
@@ -133,12 +140,44 @@ class FundTransferManagementTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( final theme = Theme.of(context);
leading: Icon(icon), return Card(
title: Text(label), margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
trailing: const Icon(Symbols.arrow_right, size: 20), shape: RoundedRectangleBorder(
onTap: onTap, borderRadius: BorderRadius.circular(12.0),
enabled: !disable, ),
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,
),
),
],
),
),
),
),
); );
} }
} }

View File

@@ -308,6 +308,8 @@ 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 isDarkMode = theme.brightness == Brightness.dark;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@@ -320,83 +322,75 @@ Widget build(BuildContext context) {
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
children: [ children: [
// ===== Profile Header ===== // ===== Profile Header =====
Container( Card(
padding: const EdgeInsets.all(16), child: Padding(
decoration: BoxDecoration( padding: const EdgeInsets.all(16.0),
color: Colors.white, child: Row(
borderRadius: BorderRadius.circular(16), children: [
boxShadow: [ // Avatar
BoxShadow( Container(
color: Colors.black.withOpacity(0.05), width: 56,
blurRadius: 8, height: 56,
offset: const Offset(0, 4), decoration: BoxDecoration(
), shape: BoxShape.circle,
], color: theme.colorScheme.surface,
), image: const DecorationImage(
child: Row( image: AssetImage('assets/images/logo.png'),
children: [ fit: BoxFit.cover,
// 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,
), ),
), ),
), 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: const TextStyle( fontWeight: FontWeight.w600,
fontSize: 18, ),
fontWeight: FontWeight.w600,
), ),
), const SizedBox(height: 4),
const SizedBox(height: 4), Text(
Text( widget.customerNo,
widget.customerNo, style: theme.textTheme.bodyMedium?.copyWith(
style: TextStyle( color:
fontSize: 14, theme.colorScheme.onSurface.withOpacity(0.7),
color: Colors.grey.shade600, ),
), ),
), ],
], ),
), ),
), // 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: Colors.blueGrey.shade700, ),
), ),
), ],
], ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// ===== Section: Settings ===== // ===== Section: Settings =====
const Text( Padding(
"Settings", padding: const EdgeInsets.symmetric(horizontal: 8.0),
style: TextStyle( child: Text(
fontSize: 13, "Settings",
fontWeight: FontWeight.w600, style: theme.textTheme.labelLarge?.copyWith(
letterSpacing: 0.2, fontWeight: FontWeight.w600,
letterSpacing: 0.2,
),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -439,18 +433,7 @@ Widget build(BuildContext context) {
); );
}, },
), ),
Container( Card(
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: SwitchListTile( child: SwitchListTile(
title: Text(loc.enableFingerprintLogin), title: Text(loc.enableFingerprintLogin),
value: _isBiometricEnabled, value: _isBiometricEnabled,
@@ -467,35 +450,27 @@ Widget build(BuildContext context) {
const Divider(height: 24), const Divider(height: 24),
// ===== Section: Security & App ===== // ===== Section: Security & App =====
Text( Padding(
loc.appVersion, padding: const EdgeInsets.symmetric(horizontal: 8.0),
style: const TextStyle( child: Text(
fontSize: 13, loc.appVersion,
fontWeight: FontWeight.w600, style: theme.textTheme.labelLarge?.copyWith(
letterSpacing: 0.2, fontWeight: FontWeight.w600,
letterSpacing: 0.2,
),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
// Fingerprint toggle inside a styled container // Fingerprint toggle inside a styled container
Container( Card(
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( child: ListTile(
leading: const Icon(Icons.smartphone), leading: const Icon(Icons.smartphone),
title: Text(loc.appVersion), title: Text(loc.appVersion),
trailing: FutureBuilder<String>( trailing: FutureBuilder<String>(
future: _getAppVersion(), future: _getAppVersion(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) { builder:
(BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.waiting) {
return const SizedBox( return const SizedBox(
width: 18, width: 18,
@@ -507,7 +482,6 @@ Widget build(BuildContext context) {
} else { } else {
return Text( return Text(
snapshot.data ?? "N/A", snapshot.data ?? "N/A",
selectionColor: const Color(0xFFFFFFFF),
); );
} }
}, },
@@ -524,12 +498,14 @@ Widget build(BuildContext context) {
const Divider(height: 24), const Divider(height: 24),
// ===== Section: Actions ===== // ===== Section: Actions =====
const Text( Padding(
"Exit", padding: const EdgeInsets.symmetric(horizontal: 8.0),
style: TextStyle( child: Text(
fontSize: 13, "Exit",
fontWeight: FontWeight.w600, style: theme.textTheme.labelLarge?.copyWith(
letterSpacing: 0.2, fontWeight: FontWeight.w600,
letterSpacing: 0.2,
),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@@ -608,6 +584,7 @@ Widget build(BuildContext context) {
); );
} }
} }
class _SectionTile extends StatelessWidget { class _SectionTile extends StatelessWidget {
const _SectionTile({ const _SectionTile({
required this.leadingIcon, required this.leadingIcon,
@@ -623,23 +600,16 @@ class _SectionTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( final theme = Theme.of(context);
return Card(
margin: const EdgeInsets.only(bottom: 10), 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( child: ListTile(
leading: Icon(leadingIcon), leading: Icon(leadingIcon, color: theme.colorScheme.onSurface),
title: Text(title), title: Text(title, style: theme.textTheme.bodyLarge),
trailing: trailChevron ? const Icon(Icons.chevron_right) : null, trailing: trailChevron
? Icon(Icons.chevron_right, color: theme.colorScheme.onSurface)
: null,
onTap: onTap, onTap: onTap,
contentPadding: contentPadding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 8), const EdgeInsets.symmetric(horizontal: 16, vertical: 8),

View File

@@ -40,7 +40,7 @@ class SecuritySettingsScreen extends StatelessWidget {
); );
}, },
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
ListTile( ListTile(
leading: const Icon(Icons.pin), leading: const Icon(Icons.pin),
title: Text(loc.changeMpin), title: Text(loc.changeMpin),
@@ -57,13 +57,13 @@ class SecuritySettingsScreen extends StatelessWidget {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text(loc.mpinChangedSuccessfully), 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( ListTile(
leading: const Icon(Icons.password), leading: const Icon(Icons.password),
title: const Text('Change TPIN'), title: const Text('Change TPIN'),

View File

@@ -23,39 +23,46 @@ class _QuickPayScreen extends State<QuickPayScreen> {
), ),
body: Stack( body: Stack(
children: [ children: [
ListView( Padding(
children: [ padding: const EdgeInsets.symmetric(vertical: 16.0),
QuickPayManagementTile( child: Column(
icon: Symbols.input_circle, crossAxisAlignment: CrossAxisAlignment.stretch,
label: AppLocalizations.of(context).ownBank, children: [
onTap: () { Expanded(
Navigator.push( child: QuickPayManagementTile(
context, icon: Symbols.input_circle,
MaterialPageRoute( label: AppLocalizations.of(context).ownBank,
builder: (context) => QuickPayWithinBankScreen( onTap: () {
debitAccount: widget.debitAccount, 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( const SizedBox(height: 16),
context, Expanded(
MaterialPageRoute( child: QuickPayManagementTile(
builder: (context) => QuickPayOutsideBankScreen( icon: Symbols.output_circle,
debitAccount: widget.debitAccount, label: AppLocalizations.of(context).outsideBank,
), onTap: () {
), Navigator.push(
); context,
}, MaterialPageRoute(
), builder: (context) => QuickPayOutsideBankScreen(
const Divider(height: 1), debitAccount: widget.debitAccount,
], ),
),
);
},
),
),
],
),
), ),
IgnorePointer( IgnorePointer(
child: Center( child: Center(
@@ -93,12 +100,42 @@ class QuickPayManagementTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( final theme = Theme.of(context);
leading: Icon(icon), return Card(
title: Text(label), margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
trailing: const Icon(Symbols.arrow_right, size: 20), shape: RoundedRectangleBorder(
onTap: onTap, borderRadius: BorderRadius.circular(12.0),
enabled: !disable, ),
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,
),
),
],
),
),
),
); );
} }
} }

View File

@@ -20,17 +20,17 @@
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildDetailRow("Branch Name", branch.branch_name), _buildDetailRow(context, "Branch Name", branch.branch_name),
_buildDetailRow("Branch Code", branch.branch_code), _buildDetailRow(context, "Branch Code", branch.branch_code),
_buildDetailRow("Zone", branch.zone), _buildDetailRow(context, "Zone", branch.zone),
_buildDetailRow("Tehsil", branch.tehsil), _buildDetailRow(context, "Tehsil", branch.tehsil),
_buildDetailRow("Block", branch.block), _buildDetailRow(context, "Block", branch.block),
_buildDetailRow("District", branch.distt_name), _buildDetailRow(context, "District", branch.distt_name),
_buildDetailRow("Pincode", branch.pincode), _buildDetailRow(context, "Pincode", branch.pincode),
// _buildDetailRow("Post Office", branch.post_office), // _buildDetailRow(context, "Post Office", branch.post_office),
// _buildDetailRow("Date of Opening", branch.date_of_opening), // _buildDetailRow(context, "Date of Opening", branch.date_of_opening),
// _buildDetailRow("Branch Type", branch.type_of_branch), // _buildDetailRow(context, "Branch Type", branch.type_of_branch),
_buildDetailRow("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),
@@ -58,46 +58,46 @@
); );
} }
Widget _buildDetailRow(String label, String value) { Widget _buildDetailRow(BuildContext context, String label, String value) {
return Padding( final theme = Theme.of(context);
padding: const EdgeInsets.symmetric(vertical: 8.0), return Padding(
child: Column( padding: const EdgeInsets.symmetric(vertical: 8.0),
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Text( children: [
label, Text(
style: TextStyle( label,
fontSize: 14, style: TextStyle(
color: Colors.grey[600], fontSize: 14,
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,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: theme.colorScheme.primary, // Indicate it's clickable
decoration: TextDecoration.underline,
),
),
)
: Text(
value, value,
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.blue, // Indicate it's clickable
decoration: TextDecoration.underline,
), ),
), ),
) Divider(height: 16, color: theme.dividerColor),
: Text( ],
value, ),
style: const TextStyle( );
fontSize: 16, }
fontWeight: FontWeight.w500,
),
),
const Divider(height: 16),
],
),
);
}
Future<void> _launchUrl(String urlString) async { Future<void> _launchUrl(String urlString) async {
final Uri url = Uri.parse(urlString); final Uri url = Uri.parse(urlString);
if (!await launchUrl(url)) { if (!await launchUrl(url)) {

View File

@@ -56,7 +56,12 @@ class BranchLocatorScreen extends StatefulWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( 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( body: Stack(
children: [ children: [

View File

@@ -54,7 +54,7 @@ class _ServiceScreen extends State<ServiceScreen> {
}, },
disabled: false, disabled: false,
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
ServiceManagementTile( ServiceManagementTile(
icon: Symbols.question_mark, icon: Symbols.question_mark,
label: AppLocalizations.of(context).faq, label: AppLocalizations.of(context).faq,
@@ -65,7 +65,7 @@ class _ServiceScreen extends State<ServiceScreen> {
}, },
disabled: false, disabled: false,
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
ServiceManagementTile( ServiceManagementTile(
icon: Symbols.location_pin, icon: Symbols.location_pin,
label: "ATM Locator", label: "ATM Locator",
@@ -77,7 +77,7 @@ class _ServiceScreen extends State<ServiceScreen> {
}, },
disabled: false, disabled: false,
), ),
const Divider(height: 1), Divider(height: 1, color: Theme.of(context).dividerColor),
], ],
), ),
IgnorePointer( IgnorePointer(

View File

@@ -69,10 +69,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.4.0"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
@@ -93,18 +93,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.1.2"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.18.0" version: "1.19.1"
confetti: confetti:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -181,10 +181,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.3"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@@ -385,10 +385,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: intl name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.19.0" version: "0.20.2"
jailbreak_root_detection: jailbreak_root_detection:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -417,26 +417,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.5" version: "11.0.2"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.5" version: "3.0.10"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_testing name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.2"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@@ -497,10 +497,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16+1" version: "0.12.17"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
@@ -521,10 +521,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.15.0" version: "1.16.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@@ -561,10 +561,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.0" version: "1.9.1"
path_parsing: path_parsing:
dependency: transitive dependency: transitive
description: description:
@@ -817,7 +817,7 @@ packages:
dependency: transitive dependency: transitive
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.99" version: "0.0.0"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@@ -838,18 +838,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.1" version: "1.12.1"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.4"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
@@ -870,10 +870,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.2" version: "0.7.6"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -982,10 +982,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.2.0"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description:
@@ -1043,5 +1043,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.5.0 <4.0.0" dart: ">=3.8.0-0 <4.0.0"
flutter: ">=3.24.0" flutter: ">=3.24.0"