Cooldown Added in Beneficiary
This commit is contained in:
90
lib/features/fund_transfer/screens/cooldown.dart
Normal file
90
lib/features/fund_transfer/screens/cooldown.dart
Normal file
@@ -0,0 +1,90 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CooldownTimer extends StatefulWidget {
|
||||
final DateTime createdAt;
|
||||
final VoidCallback onTimerFinish;
|
||||
|
||||
const CooldownTimer({
|
||||
Key? key,
|
||||
required this.createdAt,
|
||||
required this.onTimerFinish,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CooldownTimerState createState() => _CooldownTimerState();
|
||||
}
|
||||
|
||||
class _CooldownTimerState extends State<CooldownTimer> {
|
||||
late Timer _timer;
|
||||
late Duration _timeRemaining;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_updateRemainingTime();
|
||||
// Update the timer every second
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
_updateRemainingTime();
|
||||
});
|
||||
}
|
||||
|
||||
void _updateRemainingTime() {
|
||||
final cooldownEnd = widget.createdAt.add(const Duration(minutes: 60));
|
||||
final now = DateTime.now();
|
||||
|
||||
if (now.isAfter(cooldownEnd)) {
|
||||
_timeRemaining = Duration.zero;
|
||||
_timer.cancel();
|
||||
// Notify the parent widget that the timer is done
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
widget.onTimerFinish();
|
||||
});
|
||||
} else {
|
||||
_timeRemaining = cooldownEnd.difference(now);
|
||||
}
|
||||
// Trigger a rebuild
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
String _formatDuration(Duration duration) {
|
||||
final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
|
||||
final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
|
||||
return '$minutes:$seconds';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_timeRemaining == Duration.zero) {
|
||||
return const SizedBox.shrink(); // Or some other widget indicating it's enabled
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
'Enabled after:',
|
||||
style: TextStyle(
|
||||
color: Colors.red.shade700,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
_formatDuration(_timeRemaining),
|
||||
style: TextStyle(
|
||||
color: Colors.red.shade700,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/features/fund_transfer/screens/cooldown.dart';
|
||||
import 'package:kmobile/widgets/bank_logos.dart';
|
||||
import 'package:kmobile/data/models/beneficiary.dart';
|
||||
import 'package:kmobile/features/fund_transfer/screens/fund_transfer_amount_screen.dart';
|
||||
@@ -72,7 +73,8 @@ class _FundTransferBeneficiaryScreenState
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBeneficiaryList() {
|
||||
|
||||
Widget _buildBeneficiaryList() {
|
||||
if (_beneficiaries.isEmpty) {
|
||||
return Center(
|
||||
child: Text(AppLocalizations.of(context).noBeneficiaryFound));
|
||||
@@ -81,43 +83,79 @@ class _FundTransferBeneficiaryScreenState
|
||||
itemCount: _beneficiaries.length,
|
||||
itemBuilder: (context, index) {
|
||||
final beneficiary = _beneficiaries[index];
|
||||
return ListTile(
|
||||
leading: CircleAvatar(
|
||||
radius: 24,
|
||||
backgroundColor: Colors.transparent,
|
||||
child: getBankLogo(beneficiary.bankName, context),
|
||||
|
||||
// --- Cooldown Logic ---
|
||||
bool isCoolingDown = false;
|
||||
if (beneficiary.createdAt != null) {
|
||||
final sixtyMinutesAgo =
|
||||
DateTime.now().subtract(const Duration(minutes: 60));
|
||||
isCoolingDown = beneficiary.createdAt!.isAfter(sixtyMinutesAgo);
|
||||
}
|
||||
// --- End of Cooldown Logic ---
|
||||
|
||||
// By wrapping the ListTile in an Opacity widget, we can make it look
|
||||
// disabled while ensuring the onTap callback still works.
|
||||
return Opacity(
|
||||
opacity: isCoolingDown ? 0.5 : 1.0,
|
||||
child: ListTile(
|
||||
// REMOVED the 'enabled' property from here.
|
||||
leading: CircleAvatar(
|
||||
radius: 24,
|
||||
backgroundColor: Colors.transparent,
|
||||
child: getBankLogo(beneficiary.bankName, context),
|
||||
),
|
||||
title: Text(beneficiary.name),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(beneficiary.accountNo),
|
||||
if (beneficiary.bankName != null &&
|
||||
beneficiary.bankName!.isNotEmpty)
|
||||
Text(
|
||||
beneficiary.bankName!,
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
|
||||
),
|
||||
],
|
||||
),
|
||||
trailing: isCoolingDown
|
||||
? CooldownTimer(
|
||||
createdAt: beneficiary.createdAt!,
|
||||
onTimerFinish: () {
|
||||
setState(() {});
|
||||
},
|
||||
)
|
||||
: null,
|
||||
onTap: () {
|
||||
if (isCoolingDown) {
|
||||
// This will now execute correctly on tap
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text(
|
||||
'Beneficiary will be enabled after the cooldown period.'),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => FundTransferAmountScreen(
|
||||
debitAccountNo: widget.creditAccountNo,
|
||||
creditBeneficiary: beneficiary,
|
||||
remitterName: widget.remitterName,
|
||||
isOwnBank: widget.isOwnBank,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
title: Text(beneficiary.name),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(beneficiary.accountNo),
|
||||
if (beneficiary.bankName != null &&
|
||||
beneficiary.bankName!.isNotEmpty)
|
||||
Text(
|
||||
beneficiary.bankName!,
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => FundTransferAmountScreen(
|
||||
debitAccountNo: widget.creditAccountNo,
|
||||
creditBeneficiary: beneficiary,
|
||||
remitterName: widget.remitterName,
|
||||
isOwnBank: widget.isOwnBank,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
||||
Reference in New Issue
Block a user