201 lines
5.7 KiB
Dart
Raw Normal View History

2025-08-12 17:36:41 +07:00
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
2025-08-12 22:36:23 +07:00
import 'package:line_icons/line_icons.dart';
2025-08-12 17:36:41 +07:00
2025-08-12 20:44:27 +07:00
import '../../../common/theme/theme.dart';
2025-08-12 22:36:23 +07:00
import '../../components/button/button.dart';
2025-08-12 20:44:27 +07:00
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';
2025-08-12 17:36:41 +07:00
@RoutePage()
2025-08-12 20:44:27 +07:00
class HomePage extends StatefulWidget {
2025-08-12 17:36:41 +07:00
const HomePage({super.key});
2025-08-12 20:44:27 +07:00
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
late ScrollController _scrollController;
late AnimationController _headerAnimationController;
late AnimationController _contentAnimationController;
late AnimationController _appBarAnimationController;
late Animation<double> _appBarOpacityAnimation;
late Animation<Offset> _appBarSlideAnimation;
bool _showAppBar = false;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(_scrollListener);
_headerAnimationController = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: this,
);
_contentAnimationController = AnimationController(
duration: const Duration(milliseconds: 1200),
vsync: this,
);
// AppBar Animation Controller
_appBarAnimationController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
// AppBar Animations
_appBarOpacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _appBarAnimationController,
curve: Curves.easeInOut,
),
);
_appBarSlideAnimation =
Tween<Offset>(begin: const Offset(0.0, -1.0), end: Offset.zero).animate(
CurvedAnimation(
parent: _appBarAnimationController,
curve: Curves.easeOutCubic,
),
);
_startAnimations();
}
void _startAnimations() {
_headerAnimationController.forward();
Future.delayed(const Duration(milliseconds: 200), () {
_contentAnimationController.forward();
});
}
void _scrollListener() {
const double threshold = 200.0;
if (_scrollController.offset > threshold && !_showAppBar) {
setState(() {
_showAppBar = true;
});
_appBarAnimationController.forward();
} else if (_scrollController.offset <= threshold && _showAppBar) {
_appBarAnimationController.reverse().then((_) {
if (mounted) {
setState(() {
_showAppBar = false;
});
}
});
}
}
@override
void dispose() {
_scrollController.removeListener(_scrollListener);
_scrollController.dispose();
_headerAnimationController.dispose();
_contentAnimationController.dispose();
_appBarAnimationController.dispose();
super.dispose();
}
PreferredSizeWidget? _buildAnimatedAppBar() {
if (!_showAppBar) return null;
return PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: SlideTransition(
position: _appBarSlideAnimation,
child: FadeTransition(
opacity: _appBarOpacityAnimation,
child: AppBar(
title: const Text(
'AppSkel POS Owner',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 18,
letterSpacing: -0.5,
),
),
foregroundColor: AppColor.textPrimary,
elevation: 0,
2025-08-12 22:36:23 +07:00
scrolledUnderElevation: 0,
2025-08-12 20:44:27 +07:00
shadowColor: AppColor.primary.withOpacity(0.1),
2025-08-12 22:36:23 +07:00
actions: [ActionIconButton(onTap: () {}, icon: LineIcons.bell)],
2025-08-12 20:44:27 +07:00
),
),
),
);
}
2025-08-12 17:36:41 +07:00
@override
Widget build(BuildContext context) {
2025-08-12 20:44:27 +07:00
return Scaffold(
backgroundColor: AppColor.background,
appBar: _buildAnimatedAppBar(),
body: CustomScrollView(
controller: _scrollController,
physics: const BouncingScrollPhysics(),
slivers: [
// Enhanced Header
SliverToBoxAdapter(
child: 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),
],
),
),
);
},
),
),
],
),
);
2025-08-12 17:36:41 +07:00
}
}