import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; import '../../../common/theme/theme.dart'; import '../../components/button/button.dart'; import '../../components/spacer/spacer.dart'; import 'widgets/activity.dart'; import 'widgets/feature.dart'; import 'widgets/header.dart'; import 'widgets/performance.dart'; import 'widgets/stats.dart'; import 'widgets/task.dart'; @RoutePage() class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State with TickerProviderStateMixin { late AnimationController _headerAnimationController; late AnimationController _contentAnimationController; @override void initState() { super.initState(); _headerAnimationController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, ); _contentAnimationController = AnimationController( duration: const Duration(milliseconds: 1200), vsync: this, ); _startAnimations(); } void _startAnimations() { _headerAnimationController.forward(); Future.delayed(const Duration(milliseconds: 200), () { _contentAnimationController.forward(); }); } @override void dispose() { _headerAnimationController.dispose(); _contentAnimationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, body: CustomScrollView( physics: const BouncingScrollPhysics(parent: ClampingScrollPhysics()), slivers: [ // SliverAppBar with HomeHeader as background SliverAppBar( expandedHeight: 260, // Adjust based on HomeHeader height floating: true, pinned: true, snap: true, elevation: 0, scrolledUnderElevation: 8, backgroundColor: AppColor.primary, surfaceTintColor: Colors.transparent, flexibleSpace: LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { // Calculate collapse progress (0.0 = expanded, 1.0 = collapsed) final double expandedHeight = 200; final double collapsedHeight = kToolbarHeight + MediaQuery.of(context).padding.top; final double currentHeight = constraints.maxHeight; double collapseProgress = 1.0 - ((currentHeight - collapsedHeight) / (expandedHeight - collapsedHeight)); collapseProgress = collapseProgress.clamp(0.0, 1.0); return FlexibleSpaceBar( title: Opacity( opacity: collapseProgress, // Title muncul saat collapse child: Row( children: [ Expanded( child: Text( 'AppSkel POS Owner', style: AppStyle.xl.copyWith( fontWeight: FontWeight.w700, fontSize: 18, letterSpacing: -0.5, color: AppColor.white, ), ), ), ActionIconButton(onTap: () {}, icon: LineIcons.bell), ], ), ), titlePadding: const EdgeInsets.only( left: 20, right: 12, bottom: 16, ), background: AnimatedBuilder( animation: _headerAnimationController, builder: (context, child) { return Transform.translate( offset: Offset( 0, 50 * (1 - _headerAnimationController.value), ), child: Opacity( opacity: _headerAnimationController.value, child: HomeHeader(), ), ); }, ), ); }, ), ), // Main Content SliverToBoxAdapter( child: AnimatedBuilder( animation: _contentAnimationController, builder: (context, child) { return Transform.translate( offset: Offset( 0, 30 * (1 - _contentAnimationController.value), ), child: Opacity( opacity: _contentAnimationController.value, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ HomeFeature(), HomeStats(), HomeTask(), HomeActivity(), HomePerformance(), const SpaceHeight(40), ], ), ), ); }, ), ), ], ), ); } }