import 'dart:async'; import 'package:audioplayers/audioplayers.dart'; 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; final String qrCodeData; const ReservationConfirmationPage({ super.key, required this.offer, required this.qrCodeData, }); @override State createState() => _ReservationConfirmationPageState(); } class _ReservationConfirmationPageState extends State { Timer? _timer; Duration _remaining = Duration.zero; final AudioPlayer _audioPlayer = AudioPlayer(); @override void initState() { super.initState(); _playSound(); _calculateRemainingTime(); _timer = Timer.periodic(const Duration(seconds: 1), (timer) { _calculateRemainingTime(); }); } void _playSound() async { try { await _audioPlayer.play(AssetSource('sounds/positive-notification-alert-351299.mp3')); } catch (e) { debugPrint("Error playing sound: $e"); } } 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(); _audioPlayer.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.rtl, child: Scaffold( backgroundColor: Colors.grey[50], appBar: _buildCustomAppBar(context), body: SingleChildScrollView( child: 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: [ const 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( '(${(100-widget.offer.finalPrice/widget.offer.originalPrice*100).toInt()}%)', 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: const Color.fromARGB(255, 157, 157, 155), ), const 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: const Color.fromARGB(255, 246, 246, 246), borderRadius: BorderRadius.circular(16), ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Column( children: [ Text( "مدت", style: TextStyle( color: AppColors.expiryReserve, fontSize: 15, ), ), SizedBox(height: 7), Text( "اعتبار", style: TextStyle( color: AppColors.expiryReserve, fontSize: 15, ), ), ], ), const SizedBox(width: 15), _buildTimeBlock(seconds, 'ثانیه'), const SizedBox(width: 10), _buildTimeBlock(minutes, 'دقیقه'), const SizedBox(width: 10), _buildTimeBlock(hours, 'ساعت'), if (_remaining.inDays > 0) ...[ const SizedBox(width: 10), _buildTimeBlock(days, 'روز'), ], ], ), const SizedBox(height: 20), const Text( "لطفا QR Code زیر رو به فروشنده نشون بده.", style: TextStyle(fontSize: 15), ), ], ), ); } Widget _buildTimeBlock(String value, String label) { return Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 5, ), decoration: BoxDecoration( border: Border.all(color: AppColors.countdownBorderRserve, width: 1.5), borderRadius: BorderRadius.circular(12), ), 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: const Color.fromARGB(255, 246, 246, 246), borderRadius: BorderRadius.circular(16), ), child: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: QrImageView( data: widget.qrCodeData, version: QrVersions.auto, size: 280.0, ), ), const SizedBox(height: 10), ], ), ), ); } }