import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'dart:async'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late final Animation _alignAnimation; final List> _animations = []; final List> _alignListAnimations = []; late bool _enabled = true; late bool _loading = true; Timer? _loadingTimer; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 600), vsync: this, )..forward(); _alignAnimation = Tween( begin: Alignment.centerLeft, end: Alignment.center, ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut)); List tranListIndices = [0, 1]; for (int i = 0; i < tranListIndices.length; i++) { _alignListAnimations.add( Tween(begin: Offset(0, -0.25), end: Offset.zero).animate( CurvedAnimation( parent: _controller, curve: Interval(0.075 * i, 1.0, curve: Curves.easeOut), ), ), ); } List buttonIndices = [0, 1, 2]; for (int i = 0; i < buttonIndices.length; i++) { _animations.add( Tween(begin: Offset(-0.15, 0), end: Offset.zero).animate( CurvedAnimation( parent: _controller, curve: Interval(0.075 * i, 1.0, curve: Curves.easeOut), ), ), ); } // Simulate a delay to mimic loading state _loadingTimer = Timer(const Duration(seconds: 1), () { if (mounted) { setState(() { _loading = false; }); } }); } @override void dispose() { _loadingTimer?.cancel(); _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final VoidCallback? onPressed = _enabled ? () {} : null; return Scaffold( body: SafeArea( child: CustomScrollView( slivers: [ SliverAppBar( floating: true, title: const Text('QPay'), actions: [ IconButton( icon: const Icon(Icons.notifications_outlined), onPressed: () {}, ), ], ), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AlignTransition( alignment: _alignAnimation, child: Skeletonizer( enabled: _loading, child: Text( "USD 4.02", style: TextStyle( fontSize: 30, fontWeight: FontWeight.bold, ), ), ), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ SlideTransition( position: _animations[0], child: FilledButton( style: ButtonStyle( backgroundColor: WidgetStateProperty.all( Theme.of( context, ).colorScheme.primary.withValues(alpha: 0.9), ), padding: WidgetStateProperty.all( const EdgeInsets.symmetric( vertical: 17.5, horizontal: 30, ), ), ), onPressed: onPressed, child: Row( children: [ Icon(Icons.electric_bolt, color: Colors.white), const SizedBox(width: 8), const Text( 'Electricity', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ], ), ), ), SlideTransition( position: _animations[1], child: OutlinedButton( style: ButtonStyle( side: WidgetStateProperty.all( BorderSide( color: Theme.of(context).colorScheme.primary, ), ), foregroundColor: WidgetStateProperty.all( Theme.of(context).colorScheme.primary, ), padding: WidgetStateProperty.all( const EdgeInsets.symmetric( vertical: 17.5, horizontal: 30, ), ), ), onPressed: onPressed, child: Row( children: [ Icon(Icons.phone_android), const SizedBox(width: 8), const Text( 'Airtime', style: TextStyle(fontWeight: FontWeight.bold), ), ], ), ), ), SlideTransition( position: _animations[2], child: OutlinedButton( style: ButtonStyle( side: WidgetStateProperty.all( BorderSide( color: Theme.of(context).colorScheme.primary, ), ), padding: WidgetStateProperty.all( const EdgeInsets.symmetric( vertical: 17.5, horizontal: 30, ), ), ), onPressed: onPressed, child: Icon(Icons.add), ), ), ], ), const SizedBox(height: 30), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Recent Activity', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), GestureDetector( onTap: () { context.go('/history'); }, child: const Text( 'View All', style: TextStyle( fontSize: 18, fontWeight: FontWeight.normal, ), ), ), ], ), const SizedBox(height: 20), Skeletonizer( enabled: _loading, child: ListView( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), children: [ SlideTransition( position: _alignListAnimations[0], 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: Icon( Icons.electric_bolt, color: Theme.of(context).colorScheme.primary, ), ), title: Text( 'Electricity Bill', style: TextStyle(fontWeight: FontWeight.bold), ), subtitle: Text( 'Paid USD 50.00', style: TextStyle(fontWeight: FontWeight.normal), ), trailing: Text( '-USD 50.00', style: TextStyle( color: Colors.red, fontWeight: FontWeight.bold, ), ), ), ), SlideTransition( position: _alignListAnimations[1], 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: Icon( Icons.phone_android, color: Theme.of(context).colorScheme.primary, ), ), title: Text( 'Airtime Purchase', style: TextStyle(fontWeight: FontWeight.bold), ), subtitle: Text( 'Purchased USD 10.00', style: TextStyle(fontWeight: FontWeight.normal), ), trailing: Text( '-USD 10.00', style: TextStyle( color: Colors.red, fontWeight: FontWeight.bold, ), ), ), ), ], ), ), ], ), ), ), ], ), ), ); } }