import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:qpay/models/responsive_policy.dart'; import 'package:qpay/screens/confirm/confirm_controller.dart'; import 'package:skeletonizer/skeletonizer.dart'; class ConfirmScreen extends StatefulWidget { const ConfirmScreen({super.key}); @override State createState() => _ConfirmScreenState(); } class _ConfirmScreenState extends State with TickerProviderStateMixin { late ConfirmController controller; late Animation _fadeAnimation; late Animation _slideAnimation; late AnimationController _controller; final _formKey = GlobalKey(); @override void initState() { super.initState(); controller = ConfirmController(context); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 800), ); _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.0, 0.5, curve: Curves.easeOut), ), ); _slideAnimation = Tween( begin: const Offset(0, 0.1), end: Offset.zero, ).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.0, 0.5, curve: Curves.easeOut), ), ); _controller.forward(); } @override void dispose() { _controller.dispose(); controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: context.canPop() ? IconButton( onPressed: () { context.pop(); }, icon: const Icon(Icons.arrow_back), ) : SizedBox.shrink(), title: const Text( 'Confirm Payment', style: TextStyle(color: Colors.black87), ), ), body: ListenableBuilder( listenable: controller, builder: (context, child) { return SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(20.0), child: FadeTransition( opacity: _fadeAnimation, child: SlideTransition( position: _slideAnimation, child: Form( key: _formKey, child: Center( child: LayoutBuilder( builder: (context, constraints) { return SizedBox( width: double.parse(constraints.maxWidth > ResponsivePolicy.md ? ResponsivePolicy.md.toString() : constraints.maxWidth.toString()), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: EdgeInsets.all(15), decoration: BoxDecoration( border: Border.all( color: Theme.of( context, ).colorScheme.primary.withOpacity(0.3), ), borderRadius: BorderRadius.circular(10), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( decoration: BoxDecoration( border: Border( bottom: BorderSide( width: 1.0, color: Theme.of(context).colorScheme.primary, ), ), ), padding: EdgeInsets.only( bottom: 4.0, ), // Adjust spacing child: Text( "PROVIDER DETAILS", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ...controller .transactionController .model .confirmationData["additionalData"] .map((data) { return Column( children: [ const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( data["name"] ?? "", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), Text( data["value"] ?? "", style: TextStyle(fontSize: 16), ), ], ), ], ); }) .toList(), const SizedBox(height: 30), Container( decoration: BoxDecoration( border: Border( bottom: BorderSide( width: 1.0, color: Theme.of(context).colorScheme.primary, ), ), ), padding: EdgeInsets.only( bottom: 4.0, ), // Adjust spacing child: Text( "TRANSACTIONS DETAILS", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Amount", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), Text( controller .transactionController .model .confirmationData["amount"] .toString(), style: TextStyle(fontSize: 16), ), ], ), const SizedBox(height: 10), if (controller .transactionController .model .confirmationData["charge"] != 0) Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Our Charge", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), Text( controller .transactionController .model .confirmationData["charge"] .toString(), style: TextStyle(fontSize: 16), ), ], ), const SizedBox(height: 10), ], ), if (controller .transactionController .model .confirmationData["gatewayCharge"] != 0) Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Gateway Charge", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), Text( controller .transactionController .model .confirmationData["gatewayCharge"] .toString(), style: TextStyle(fontSize: 16), ), ], ), const SizedBox(height: 10), ], ), if (controller .transactionController .model .confirmationData["tax"] != 0) Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Tax", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), Text( controller .transactionController .model .confirmationData["tax"] .toString(), style: TextStyle(fontSize: 16), ), ], ), const SizedBox(height: 10), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Total Amount", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), Text( controller .transactionController .model .confirmationData["totalAmount"] .toString(), style: TextStyle(fontSize: 16), ), ], ), const SizedBox(height: 5), Text( "NB: Your payment provider may charge additional fees.", style: TextStyle( fontSize: 11, color: Colors.red, ), ), ], ), ), const SizedBox(height: 20), _buildPaymentProcessorButton(), const SizedBox(height: 20), Center( child: OutlinedButton( child: Text('Cancel'), onPressed: () { context.go('/'); }, ), ), ], ), ); } ), ), ), ), ), ), ); }, ), ); } Widget _buildPaymentProcessorButton() { return Skeletonizer( enabled: controller.model.isLoading, child: SlideTransition( position: _slideAnimation, child: Container( decoration: BoxDecoration( border: Border.all(color: Colors.black87.withAlpha(20)), borderRadius: BorderRadius.circular(12), gradient: LinearGradient( colors: [ Theme.of(context).colorScheme.primary.withValues(alpha: 0.1), Theme.of(context).colorScheme.tertiary.withValues(alpha: 0.05), ], stops: const [0.3, 0.7], begin: Alignment.topRight, end: Alignment.bottomLeft, ), ), child: InkWell( customBorder: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), onTap: () async { if (controller.model.isLoading) return; await controller.doTransaction(); }, child: ListTile( leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Theme.of( context, ).colorScheme.primary.withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Image( image: AssetImage( "assets/${controller.transactionController.model.selectedPaymentProcessor.image}", ), ), ), title: Text( controller .transactionController .model .selectedPaymentProcessor .name, style: TextStyle(fontWeight: FontWeight.bold), ), subtitle: Text( controller .transactionController .model .selectedPaymentProcessor .description, style: TextStyle(fontWeight: FontWeight.normal, fontSize: 10), ), trailing: Icon( Icons.chevron_right, color: Theme.of( context, ).colorScheme.secondary.withValues(alpha: 0.7), ), ), ), ), ), ); } }