import 'dart:async'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:proxibuy/core/config/app_colors.dart'; import 'package:proxibuy/core/gen/assets.gen.dart'; import 'package:proxibuy/data/models/offer_model.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:flutter_animate/flutter_animate.dart'; class ReservationConfirmationPage extends StatefulWidget { final OfferModel offer; const ReservationConfirmationPage({super.key, required this.offer}); @override State createState() => _ReservationConfirmationPageState(); } class _ReservationConfirmationPageState extends State { Timer? _timer; Duration _remaining = Duration.zero; @override void initState() { super.initState(); _calculateRemainingTime(); _timer = Timer.periodic(const Duration(seconds: 1), (timer) { _calculateRemainingTime(); }); } void _calculateRemainingTime() { final now = DateTime.now(); if (widget.offer.expiryTime.isAfter(now)) { if (mounted) { setState(() { _remaining = widget.offer.expiryTime.difference(now); }); } } else { if (mounted) { setState(() { _remaining = Duration.zero; }); } _timer?.cancel(); } } @override void dispose() { _timer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.rtl, child: Scaffold( backgroundColor: Colors.grey[50], appBar: _buildCustomAppBar(context), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 32.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // ✅ انیمیشن برای عنوان اصلی Text( 'تخفیف ${widget.offer.discountType} رزرو شد!', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black87, ), ).animate().fadeIn(delay: 300.ms, duration: 500.ms).slideY(begin: -0.2, end: 0), const SizedBox(height: 8), // ✅ انیمیشن برای خط جداکننده const Divider(thickness: 1.5) .animate() .fadeIn(delay: 400.ms) .scaleX(begin: 0, duration: 600.ms, curve: Curves.easeInOut), const SizedBox(height: 18), _buildOfferDetailsCard() .animate() .fadeIn(delay: 600.ms, duration: 500.ms) .slideX(begin: 0.5, end: 0, curve: Curves.easeOutCubic), const SizedBox(height: 18), _buildTimerCard() .animate() .fadeIn(delay: 800.ms, duration: 500.ms) .scale(begin: const Offset(0.8, 0.8), curve: Curves.easeOutBack), const SizedBox(height: 18), _buildQrCodeCard() .animate() .fadeIn(delay: 1000.ms, duration: 500.ms) .flipV(begin: -0.5, end: 0, curve: Curves.easeOut), ], ), ), ), ); } PreferredSizeWidget _buildCustomAppBar(BuildContext context) { return PreferredSize( preferredSize: const Size.fromHeight(70.0), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.vertical( bottom: Radius.circular(15), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Column( children: [ SizedBox(height: 15), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Row( children: [ const Text( 'رزرو شده', style: TextStyle( color: Colors.black, fontWeight: FontWeight.normal, fontSize: 16, ), ), IconButton( icon: SvgPicture.asset(Assets.icons.arrowLeft.path), onPressed: () => Navigator.of(context).pop(), ), ], ), ], ), ], ), ), ), ), ); } Widget _buildOfferDetailsCard() { return Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration(borderRadius: BorderRadius.circular(16)), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ ClipRRect( borderRadius: BorderRadius.circular(12), child: CachedNetworkImage( imageUrl: widget.offer.coverImageUrl, width: 110, height: 110, fit: BoxFit.cover, ), ), const SizedBox(width: 16), // جزئیات متنی Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text( widget.offer.title, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.normal, color: AppColors.hint, ), ), const SizedBox(height: 10), Row( children: [ SvgPicture.asset(Assets.icons.ticketDiscount.path), const SizedBox(width: 6), Text( '(${widget.offer.discount})', style: const TextStyle( fontSize: 16, color: AppColors.singleOfferType, fontWeight: FontWeight.normal, ), ), const SizedBox(width: 6), Text( widget.offer.originalPrice.toStringAsFixed(0), style: TextStyle( fontSize: 14, color: Colors.grey.shade600, decoration: TextDecoration.lineThrough, ), ), ], ), const SizedBox(height: 10), Row( children: [ SvgPicture.asset(Assets.icons.cardPos.path,height: 22,color: Color.fromARGB(255, 157, 157, 155),), SizedBox(width: 6,), Text( '${widget.offer.finalPrice.toStringAsFixed(0)} تومان', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.normal, color: AppColors.singleOfferType, ), ), ], ), const SizedBox(height: 10), ], ), ), ], ), ); } Widget _buildTimerCard() { if (_remaining.inSeconds <= 0) { return const Center( child: Text( 'مهلت این تخفیف به پایان رسیده است', style: TextStyle(color: AppColors.singleOfferType, fontSize: 16), ), ); } String days = _remaining.inDays.toString(); String hours = (_remaining.inHours % 24).toString(); String minutes = (_remaining.inMinutes % 60).toString(); String seconds = (_remaining.inSeconds % 60).toString(); return Container( padding: const EdgeInsets.symmetric(vertical: 20), decoration: BoxDecoration( color: Color.fromARGB(255, 246, 246, 246), borderRadius: BorderRadius.circular(16), ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Column( children: [ Text("مدت",style: TextStyle(color: AppColors.expiryReserve,fontSize: 15),), SizedBox(height: 7,), Text("اعتبار",style: TextStyle(color: AppColors.expiryReserve,fontSize: 15),), ], ), SizedBox(width: 25,), _buildTimeBlock(seconds, 'ثانیه'), SizedBox(width: 20,), _buildTimeBlock(minutes, 'دقیقه'), SizedBox(width: 20,), _buildTimeBlock(hours, 'ساعت'), SizedBox(width: 20,), if (_remaining.inDays > 0) _buildTimeBlock(days, 'روز'), ], ), SizedBox(height: 20 ,), Text("لطفا QR Code زیر رو به فروشنده نشون بده.",style: TextStyle(fontSize: 15),) ], ), ); } Widget _buildTimeBlock(String value, String label) { return Row( children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 3), decoration: BoxDecoration( border: Border.all(color: AppColors.countdownBorderRserve, width: 1.5), borderRadius: BorderRadius.circular(12), ), child: Padding( padding: const EdgeInsets.all(4.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( value, style: const TextStyle( fontSize: 20, fontFamily: 'Dana', fontWeight: FontWeight.bold, color: Colors.black, ), ), const SizedBox(height: 4), Text( label, style: const TextStyle( fontSize: 12, fontFamily: 'Dana', color: Colors.black, ), ), ], ), ), ), ], ); } Widget _buildQrCodeCard() { return Center( child: Container( width: 500, padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Color.fromARGB(255, 246, 246, 246), borderRadius: BorderRadius.circular(16), ), child: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: QrImageView( data: widget.offer.qrCodeData, version: QrVersions.auto, size: 280.0, ), ), SizedBox(height: 10,), Text(widget.offer.qrCodeData,style: TextStyle(fontWeight: FontWeight.bold,fontSize: 20),) ], ), ), ); } }