Files
AYS-Provider/lib/components/countdown_timer.dart
2026-02-16 17:03:38 +08:00

212 lines
5.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:handyman_provider_flutter/utils/configs.dart';
class CountdownTimer extends StatefulWidget {
final int userId;
final VoidCallback? onTimerComplete;
const CountdownTimer({
Key? key,
required this.userId,
this.onTimerComplete,
}) : super(key: key);
@override
_CountdownTimerState createState() => _CountdownTimerState();
}
class _CountdownTimerState extends State<CountdownTimer> {
Duration _remainingTime = Duration.zero;
bool _isTimerActive = false;
bool _canTryAgain = false;
@override
void initState() {
super.initState();
_loadTimerState();
}
Future<void> _loadTimerState() async {
try {
final prefs = await SharedPreferences.getInstance();
final rejectionTimeKey = 'rejection_time_${widget.userId}';
final rejectionTime = prefs.getInt(rejectionTimeKey);
if (rejectionTime != null) {
final rejectionDateTime = DateTime.fromMillisecondsSinceEpoch(rejectionTime);
final now = DateTime.now();
final timeSinceRejection = now.difference(rejectionDateTime);
// 5 seconds cooldown (for testing)
const cooldownDuration = Duration(seconds: 5);
if (timeSinceRejection >= cooldownDuration) {
// Cooldown period has passed
setState(() {
_canTryAgain = true;
_isTimerActive = false;
_remainingTime = Duration.zero;
});
widget.onTimerComplete?.call();
} else {
// Still in cooldown period
setState(() {
_canTryAgain = false;
_isTimerActive = true;
_remainingTime = cooldownDuration - timeSinceRejection;
});
_startTimer();
}
} else {
// No rejection time stored - user can try again immediately
setState(() {
_canTryAgain = true;
_isTimerActive = false;
_remainingTime = Duration.zero;
});
widget.onTimerComplete?.call();
}
} catch (e) {
print('🔍 [CountdownTimer] Error loading timer state: $e');
// Default to allowing try again if there's an error
setState(() {
_canTryAgain = true;
_isTimerActive = false;
_remainingTime = Duration.zero;
});
widget.onTimerComplete?.call();
}
}
Future<void> _startNewCooldown() async {
try {
final prefs = await SharedPreferences.getInstance();
final rejectionTimeKey = 'rejection_time_${widget.userId}';
final now = DateTime.now();
await prefs.setInt(rejectionTimeKey, now.millisecondsSinceEpoch);
setState(() {
_canTryAgain = false;
_isTimerActive = true;
_remainingTime = Duration(seconds: 5);
});
_startTimer();
print('🔍 [CountdownTimer] Started new 5-second cooldown for user ${widget.userId}');
} catch (e) {
print('🔍 [CountdownTimer] Error starting new cooldown: $e');
}
}
void _startTimer() {
if (!_isTimerActive) return;
Future.delayed(Duration(seconds: 1), () {
if (mounted && _isTimerActive) {
setState(() {
if (_remainingTime.inSeconds > 0) {
_remainingTime = Duration(seconds: _remainingTime.inSeconds - 1);
} else {
_canTryAgain = true;
_isTimerActive = false;
widget.onTimerComplete?.call();
}
});
if (_isTimerActive) {
_startTimer();
}
}
});
}
String _formatDuration(Duration duration) {
final days = duration.inDays;
final hours = duration.inHours % 24;
final minutes = duration.inMinutes % 60;
final seconds = duration.inSeconds % 60;
if (days > 0) {
return '${days}d ${hours}h ${minutes}m ${seconds}s';
} else if (hours > 0) {
return '${hours}h ${minutes}m ${seconds}s';
} else if (minutes > 0) {
return '${minutes}m ${seconds}s';
} else {
return '${seconds}s';
}
}
@override
Widget build(BuildContext context) {
if (_canTryAgain) {
return Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: secondaryColor,
border: Border.all(color: primaryColor.withOpacity(0.2)),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.check_circle, color: primaryColor, size: 20),
SizedBox(width: 8),
Text(
'You can now try again!',
style: TextStyle(
fontWeight: FontWeight.bold,
color: primaryColor,
),
),
],
),
);
}
return Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: secondaryColor,
border: Border.all(color: primaryColor.withOpacity(0.2)),
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.access_time, color: primaryColor, size: 20),
SizedBox(width: 8),
Text(
'Time Remaining:',
style: TextStyle(
fontWeight: FontWeight.w600,
color: primaryColor,
),
),
],
),
SizedBox(height: 8),
Text(
_formatDuration(_remainingTime),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: primaryColor,
),
),
],
),
);
}
@override
void dispose() {
_isTimerActive = false;
super.dispose();
}
}