diff --git a/lib/presentation/pages/home/widgets/header.dart b/lib/presentation/pages/home/widgets/header.dart index a98129e..b4882e9 100644 --- a/lib/presentation/pages/home/widgets/header.dart +++ b/lib/presentation/pages/home/widgets/header.dart @@ -4,9 +4,78 @@ import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../components/spacer/spacer.dart'; -class HomeHeader extends StatelessWidget { +class HomeHeader extends StatefulWidget { const HomeHeader({super.key}); + @override + State createState() => _HomeHeaderState(); +} + +class _HomeHeaderState extends State with TickerProviderStateMixin { + late AnimationController _backgroundAnimationController; + late AnimationController _pulseAnimationController; + late AnimationController _rotationAnimationController; + + late Animation _circleAnimation; + late Animation _pulseAnimation; + late Animation _rotationAnimation; + + @override + void initState() { + super.initState(); + + // Background animation controller for floating circles + _backgroundAnimationController = AnimationController( + duration: const Duration(seconds: 15), + vsync: this, + )..repeat(reverse: true); // Add reverse for smooth back-and-forth + + // Pulse animation for subtle breathing effect + _pulseAnimationController = AnimationController( + duration: const Duration(seconds: 6), + vsync: this, + )..repeat(reverse: true); + + // Rotation animation for decorative elements (keep this smooth) + _rotationAnimationController = AnimationController( + duration: const Duration(seconds: 45), + vsync: this, + )..repeat(); + + _circleAnimation = + Tween( + begin: 0.0, + end: 20.0, // Reduced movement range + ).animate( + CurvedAnimation( + parent: _backgroundAnimationController, + curve: Curves.easeInOutSine, // Smoother curve + ), + ); + + _pulseAnimation = Tween(begin: 0.08, end: 0.12).animate( + CurvedAnimation( + parent: _pulseAnimationController, + curve: Curves.easeInOutSine, // Smoother breathing effect + ), + ); + + _rotationAnimation = Tween(begin: 0.0, end: 2 * 3.14159).animate( + CurvedAnimation( + parent: _rotationAnimationController, + curve: Curves.linear, + ), + ); + } + + @override + void dispose() { + _backgroundAnimationController.dispose(); + _pulseAnimationController.dispose(); + _rotationAnimationController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Container( @@ -32,31 +101,148 @@ class HomeHeader extends StatelessWidget { ), child: Stack( children: [ - // Decorative circles - Positioned( - top: -50, - right: -50, - child: Container( - width: 150, - height: 150, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.1), - ), - ), + // Animated decorative circles + AnimatedBuilder( + animation: Listenable.merge([ + _backgroundAnimationController, + _pulseAnimationController, + ]), + builder: (context, child) { + return Stack( + children: [ + // Large floating circle + Positioned( + top: -50 + _circleAnimation.value, + right: -50 + (_circleAnimation.value * 0.5), + child: AnimatedBuilder( + animation: _pulseAnimationController, + builder: (context, child) { + return Container( + width: 150, + height: 150, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity( + _pulseAnimation.value, + ), + ), + ); + }, + ), + ), + + // Medium floating circle + Positioned( + top: 80 - (_circleAnimation.value * 0.3), + right: -20 + (_circleAnimation.value * 0.8), + child: AnimatedBuilder( + animation: _pulseAnimationController, + builder: (context, child) { + return Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity( + _pulseAnimation.value * 0.5, + ), + ), + ); + }, + ), + ), + + // Small floating circle + Positioned( + top: 150 + (_circleAnimation.value * 0.4), + right: 30 - (_circleAnimation.value * 0.2), + child: AnimatedBuilder( + animation: _pulseAnimationController, + builder: (context, child) { + return Container( + width: 40, + height: 40, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity( + _pulseAnimation.value * 0.7, + ), + ), + ); + }, + ), + ), + + // Left side decorative circles + Positioned( + top: 60 + (_circleAnimation.value * 0.6), + left: -30, + child: AnimatedBuilder( + animation: _pulseAnimationController, + builder: (context, child) { + return Container( + width: 100, + height: 100, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity( + _pulseAnimation.value * 0.3, + ), + ), + ); + }, + ), + ), + + Positioned( + bottom: 20 - (_circleAnimation.value * 0.5), + left: -20 + (_circleAnimation.value * 0.3), + child: AnimatedBuilder( + animation: _pulseAnimationController, + builder: (context, child) { + return Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity( + _pulseAnimation.value * 0.4, + ), + ), + ); + }, + ), + ), + ], + ); + }, ), - Positioned( - top: 80, - right: -20, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.05), - ), - ), + + // Rotating subtle gradient overlay + AnimatedBuilder( + animation: _rotationAnimationController, + builder: (context, child) { + return Transform.rotate( + angle: _rotationAnimation.value, + child: Container( + decoration: BoxDecoration( + gradient: RadialGradient( + center: const Alignment(0.8, -0.8), + radius: 1.5, + colors: [ + AppColor.white.withOpacity(0.05), + Colors.transparent, + AppColor.primary.withOpacity(0.1), + ], + stops: const [0.0, 0.6, 1.0], + ), + ), + ), + ); + }, ), + + // Content SafeArea(child: _buildContent(context)), ], ), @@ -84,115 +270,189 @@ class HomeHeader extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - // Top bar - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'AppSkel POS Owner', - style: AppStyle.lg.copyWith( - color: AppColor.white.withOpacity(0.9), - fontWeight: FontWeight.w600, - letterSpacing: 0.3, + // Top bar with subtle animation + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 800), + builder: (context, value, child) { + return Transform.translate( + offset: Offset(0, 20 * (1 - value)), + child: Opacity( + opacity: value, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'AppSkel POS Owner', + style: AppStyle.lg.copyWith( + color: AppColor.white.withOpacity(0.9), + fontWeight: FontWeight.w600, + letterSpacing: 0.3, + ), + ), + const SpaceHeight(2), + Text( + 'Manager', + style: AppStyle.sm.copyWith( + color: AppColor.textLight, + fontSize: 11, + fontWeight: FontWeight.w400, + ), + ), + ], + ), ), - ), - const SpaceHeight(2), - Text( - 'Manager', - style: AppStyle.sm.copyWith( - color: AppColor.textLight, - fontSize: 11, - fontWeight: FontWeight.w400, + // Animated notification icon + AnimatedBuilder( + animation: _pulseAnimationController, + builder: (context, child) { + return Transform.scale( + scale: 1.0 + (_pulseAnimation.value * 0.1), + child: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: AppColor.white.withOpacity(0.3), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: AppColor.white.withOpacity(0.1), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: const Icon( + Icons.notifications_none_rounded, + color: AppColor.white, + size: 20, + ), + ), + ); + }, ), - ), - ], - ), - ), - Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: AppColor.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(14), - border: Border.all( - color: AppColor.white.withOpacity(0.3), - width: 1, + ], ), ), - child: const Icon( - Icons.notifications_none_rounded, - color: AppColor.white, - size: 20, - ), - ), - ], + ); + }, ), const SpaceHeight(24), - // Greeting Section - Text( - '${greeting(context)},', - style: AppStyle.lg.copyWith( - color: AppColor.white, - fontWeight: FontWeight.w500, - ), - ), - const SpaceHeight(2), - Text( - 'Vira Vania! 👋', - style: AppStyle.h4.copyWith( - color: AppColor.white, - fontWeight: FontWeight.w800, - letterSpacing: -0.5, - ), - ), - const SpaceHeight(8), - Text( - context.lang.home_header_desc, - style: AppStyle.md.copyWith( - color: AppColor.white.withOpacity(0.85), - fontWeight: FontWeight.w400, - height: 1.3, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, + // Greeting Section with staggered animation + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 1000), + builder: (context, value, child) { + return Transform.translate( + offset: Offset(0, 30 * (1 - value)), + child: Opacity( + opacity: value, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${greeting(context)},', + style: AppStyle.lg.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w500, + ), + ), + const SpaceHeight(2), + Text( + 'Vira Vania! 👋', + style: AppStyle.h4.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w800, + letterSpacing: -0.5, + ), + ), + const SpaceHeight(8), + Text( + context.lang.home_header_desc, + style: AppStyle.md.copyWith( + color: AppColor.white.withOpacity(0.85), + fontWeight: FontWeight.w400, + height: 1.3, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + }, ), const SpaceHeight(16), - // Today's highlight - Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), - decoration: BoxDecoration( - color: AppColor.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: AppColor.white.withOpacity(0.3), - width: 1, - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.trending_up_rounded, - color: AppColor.white, - size: 14, - ), - const SizedBox(width: 6), - Text( - '${context.lang.sales_today} +25%', - style: AppStyle.sm.copyWith( - color: AppColor.white, - fontWeight: FontWeight.w600, + // Today's highlight with delayed animation + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 1200), + builder: (context, value, child) { + return Transform.translate( + offset: Offset(0, 20 * (1 - value)), + child: Opacity( + opacity: value, + child: AnimatedBuilder( + animation: _pulseAnimationController, + builder: (context, child) { + return Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: AppColor.white.withOpacity( + 0.2 + (_pulseAnimation.value * 0.05), + ), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: AppColor.white.withOpacity(0.3), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: AppColor.white.withOpacity(0.1), + blurRadius: 4 + (_pulseAnimation.value * 2), + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.trending_up_rounded, + color: AppColor.white, + size: 14, + ), + const SizedBox(width: 6), + Text( + '${context.lang.sales_today} +25%', + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ); + }, ), ), - ], - ), + ); + }, ), ], ),