MIF_E31222656/lib/widgets/session_expired_dialog.dart

182 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
import 'package:tugas_akhir_supabase/services/session_manager.dart';
class SessionExpiredDialog extends StatelessWidget {
const SessionExpiredDialog({super.key});
@override
Widget build(BuildContext context) {
// Ensure we have a MaterialLocalizations
if (Localizations.of<MaterialLocalizations>(
context,
MaterialLocalizations,
) ==
null) {
// If no MaterialLocalizations, return a simpler dialog
return AlertDialog(
title: const Text('Sesi Berakhir'),
content: const Text('Sesi Anda telah berakhir. Silakan login kembali.'),
actions: [
TextButton(
onPressed: () => _handleLoginRedirect(context),
child: const Text('Login'),
),
],
);
}
return Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
elevation: 0,
backgroundColor: Colors.transparent,
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 5,
blurRadius: 15,
offset: const Offset(0, 3),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Use a try-catch for the Lottie animation in case it fails
_buildSessionExpiredAnimation(),
const SizedBox(height: 20),
const Text(
'Sesi Anda Telah Berakhir',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF056839),
),
),
const SizedBox(height: 15),
Text(
'Untuk keamanan akun Anda, sesi telah berakhir karena tidak ada aktivitas selama ${SessionManager.getSessionTimeout()} menit atau sesi Anda telah habis masa berlakunya.',
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 12, color: Colors.black87),
),
const SizedBox(height: 10),
const Text(
'Silahkan login kembali untuk melanjutkan menggunakan aplikasi.',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 12, color: Colors.black54),
),
const SizedBox(height: 25),
ElevatedButton(
onPressed: () => _handleLoginRedirect(context),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF056839),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 40,
vertical: 15,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
elevation: 2,
),
child: const Text(
'Login Kembali',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
],
),
),
);
}
Widget _buildSessionExpiredAnimation() {
try {
// Gunakan asset yang aman dan tersedia, daripada yang mungkin hilang
return Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0xFFF5F5F5),
shape: BoxShape.circle,
),
child: const Icon(
Icons.timer_off_outlined,
size: 60,
color: Color(0xFF056839),
),
);
// Kode ini dinonaktifkan karena asset file tidak tersedia di Web
// dan menyebabkan error di awal aplikasi
/*
return Lottie.asset(
'assets/animations/session_expired.json',
width: 150,
height: 150,
repeat: true,
fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) {
// Fallback if animation file doesn't exist
return Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0xFFF5F5F5),
shape: BoxShape.circle,
),
child: const Icon(
Icons.timer_off_outlined,
size: 60,
color: Color(0xFF056839),
),
);
},
);
*/
} catch (e) {
// Fallback if Lottie animation fails
return Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0xFFF5F5F5),
shape: BoxShape.circle,
),
child: const Icon(
Icons.timer_off_outlined,
size: 60,
color: Color(0xFF056839),
),
);
}
}
Future<void> _handleLoginRedirect(BuildContext context) async {
try {
// Clear session data properly
await SessionManager.clearSession();
if (!context.mounted) return;
// Use rootNavigator to ensure we get out of any nested navigators
Navigator.of(
context,
rootNavigator: true,
).pushNamedAndRemoveUntil('/login', (route) => false);
} catch (e) {
debugPrint('Session: Error during login redirect: $e');
// Try a different approach if the first fails
if (context.mounted) {
Navigator.of(context).pushReplacementNamed('/login');
}
}
}
}