import 'package:flutter/material.dart'; import 'package:em2rp/utils/colors.dart'; /// Dialog de succès avec animation de camion class PreparationSuccessDialog extends StatefulWidget { final bool isReturnMode; const PreparationSuccessDialog({ super.key, this.isReturnMode = false, }); @override State createState() => _PreparationSuccessDialogState(); } class _PreparationSuccessDialogState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _truckAnimation; late Animation _fadeAnimation; late Animation _scaleAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 2500), vsync: this, ); // Animation du camion qui part (translation) _truckAnimation = Tween( begin: 0.0, end: 1.5, ).animate(CurvedAnimation( parent: _controller, curve: const Interval(0.3, 1.0, curve: Curves.easeInBack), )); // Animation de fade out _fadeAnimation = Tween( begin: 1.0, end: 0.0, ).animate(CurvedAnimation( parent: _controller, curve: const Interval(0.7, 1.0, curve: Curves.easeOut), )); // Animation de scale pour le check _scaleAnimation = Tween( begin: 0.0, end: 1.0, ).animate(CurvedAnimation( parent: _controller, curve: const Interval(0.0, 0.3, curve: Curves.elasticOut), )); _controller.forward(); // Auto-fermer après l'animation Future.delayed(const Duration(milliseconds: 2500), () { if (mounted) { Navigator.of(context).pop(); } }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Dialog( backgroundColor: Colors.transparent, elevation: 0, child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Opacity( opacity: _fadeAnimation.value, child: Container( padding: const EdgeInsets.all(32), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Animation du check qui pop Transform.scale( scale: _scaleAnimation.value, child: Container( width: 80, height: 80, decoration: BoxDecoration( color: Colors.green, shape: BoxShape.circle, ), child: const Icon( Icons.check, color: Colors.white, size: 50, ), ), ), const SizedBox(height: 24), // Texte Text( widget.isReturnMode ? 'Retour validé !' : 'Préparation validée !', style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.green, ), textAlign: TextAlign.center, ), const SizedBox(height: 32), // Animation du camion avec pneus qui crissent SizedBox( height: 100, child: Stack( children: [ // Traces de pneus (lignes qui apparaissent) if (_truckAnimation.value > 0.1) Positioned( left: 0, right: MediaQuery.of(context).size.width * 0.3, bottom: 30, child: CustomPaint( painter: TireMarksPainter( progress: (_truckAnimation.value - 0.1).clamp(0.0, 1.0), ), ), ), // Camion qui part Positioned( left: MediaQuery.of(context).size.width * _truckAnimation.value - 100, bottom: 20, child: Transform.rotate( angle: _truckAnimation.value > 0.5 ? -0.1 : 0, child: const Icon( Icons.local_shipping, size: 60, color: AppColors.rouge, ), ), ), ], ), ), const SizedBox(height: 16), Text( widget.isReturnMode ? 'Le matériel est de retour au dépôt' : 'Le matériel est prêt pour l\'événement', style: TextStyle( fontSize: 14, color: Colors.grey.shade600, ), textAlign: TextAlign.center, ), ], ), ), ); }, ), ); } } /// Custom painter pour dessiner les traces de pneus class TireMarksPainter extends CustomPainter { final double progress; TireMarksPainter({required this.progress}); @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.grey.shade400 ..strokeWidth = 2 ..style = PaintingStyle.stroke; final dashWidth = 10.0; final dashSpace = 5.0; final maxWidth = size.width * progress; // Dessiner deux lignes de traces (pour les deux roues) for (var i = 0; i < 2; i++) { final y = i * 15.0; var startX = 0.0; while (startX < maxWidth) { final endX = (startX + dashWidth).clamp(0.0, maxWidth); canvas.drawLine( Offset(startX, y), Offset(endX, y), paint, ); startX += dashWidth + dashSpace; } } } @override bool shouldRepaint(TireMarksPainter oldDelegate) { return oldDelegate.progress != progress; } }