diff --git a/lib/presentation/components/appbar/appbar.dart b/lib/presentation/components/appbar/appbar.dart new file mode 100644 index 0000000..51713e2 --- /dev/null +++ b/lib/presentation/components/appbar/appbar.dart @@ -0,0 +1,189 @@ +import 'package:flutter/material.dart'; +import 'dart:math' as math; + +import '../../../../common/theme/theme.dart'; +import '../../../common/painter/wave_painter.dart'; + +class CustomAppBar extends StatefulWidget { + final String title; + final bool isBack; + const CustomAppBar({super.key, required this.title, this.isBack = true}); + + @override + State createState() => _CustomAppBarState(); +} + +class _CustomAppBarState extends State + with TickerProviderStateMixin { + late AnimationController _particleController; + late AnimationController _waveController; + late AnimationController _breathController; + + late Animation _particleAnimation; + late Animation _waveAnimation; + late Animation _breathAnimation; + + @override + void initState() { + super.initState(); + + _particleController = AnimationController( + duration: const Duration(seconds: 8), + vsync: this, + )..repeat(); + + _waveController = AnimationController( + duration: const Duration(seconds: 6), + vsync: this, + )..repeat(); + + _breathController = AnimationController( + duration: const Duration(seconds: 4), + vsync: this, + )..repeat(reverse: true); + + _particleAnimation = Tween( + begin: 0.0, + end: 2 * math.pi, + ).animate(_particleController); + + _waveAnimation = Tween( + begin: 0.0, + end: 2 * math.pi, + ).animate(_waveController); + + _breathAnimation = Tween(begin: 0.8, end: 1.2).animate( + CurvedAnimation(parent: _breathController, curve: Curves.easeInOut), + ); + } + + @override + void dispose() { + _particleController.dispose(); + _waveController.dispose(); + _breathController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return FlexibleSpaceBar( + titlePadding: EdgeInsets.only(left: widget.isBack ? 50 : 20, bottom: 16), + title: Text( + widget.title, + style: AppStyle.xl.copyWith( + color: AppColor.textWhite, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + background: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + child: AnimatedBuilder( + animation: Listenable.merge([ + _particleController, + _waveController, + _breathController, + ]), + builder: (context, child) { + return Stack( + children: [ + // Animated background elements + _buildAnimatedBackground(context), + ], + ); + }, + ), + ), + ); + } + + Widget _buildAnimatedBackground(BuildContext context) { + final size = MediaQuery.of(context).size; + + return Stack( + children: [ + // Floating particles with orbital motion + ...List.generate(8, (index) { + final double radius = 40 + (index * 15); + final double angle = _particleAnimation.value + (index * 0.8); + final double centerX = size.width * 0.7; + final double centerY = 60; + + return Positioned( + left: centerX + math.cos(angle) * radius - 3, + top: centerY + math.sin(angle) * (radius * 0.5) - 3, + child: Transform.scale( + scale: _breathAnimation.value * 0.5, + child: Container( + width: 4 + (index % 3), + height: 4 + (index % 3), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.textWhite.withOpacity(0.6), + boxShadow: [ + BoxShadow( + color: AppColor.textWhite.withOpacity(0.3), + blurRadius: 6, + spreadRadius: 1, + ), + ], + ), + ), + ), + ); + }), + + // Wave patterns + Positioned.fill( + child: CustomPaint( + painter: WavePainter( + animation: _waveAnimation.value, + color: AppColor.textWhite.withOpacity(0.1), + ), + ), + ), + + // Sparkle effects + ...List.generate(4, (index) { + return Positioned( + left: (index * 90.0) % size.width, + top: 20 + (index * 25.0), + child: Transform.rotate( + angle: _particleAnimation.value * 2 + index, + child: Transform.scale( + scale: math.sin(_particleAnimation.value + index) * 0.5 + 1, + child: Icon( + Icons.auto_awesome, + size: 10 + (index % 3) * 3, + color: AppColor.textWhite.withOpacity(0.4), + ), + ), + ), + ); + }), + + // Gradient overlay for depth + Container( + decoration: BoxDecoration( + gradient: RadialGradient( + center: const Alignment(0.3, -0.2), + radius: 1.2, + colors: [ + Colors.transparent, + AppColor.primaryGradient.first.withOpacity(0.1), + Colors.transparent, + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/customer/customer_page.dart b/lib/presentation/pages/customer/customer_page.dart index f63d063..da89db4 100644 --- a/lib/presentation/pages/customer/customer_page.dart +++ b/lib/presentation/pages/customer/customer_page.dart @@ -1,11 +1,10 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; -import 'dart:math' as math; import '../../../common/theme/theme.dart'; +import '../../components/appbar/appbar.dart'; import '../../components/button/button.dart'; -import 'widgets/appbar.dart'; import 'widgets/customer_card.dart'; import 'widgets/customer_tile.dart'; @@ -102,27 +101,14 @@ class _CustomerPageState extends State ), ]; - // Animation - late AnimationController _rotationController; - late Animation _rotationAnimation; - @override initState() { super.initState(); - _rotationController = AnimationController( - duration: const Duration(seconds: 3), - vsync: this, - )..repeat(); - _rotationAnimation = Tween( - begin: 0, - end: 2 * math.pi, - ).animate(_rotationController); } @override void dispose() { _searchController.dispose(); - _rotationController.dispose(); super.dispose(); } @@ -151,9 +137,7 @@ class _CustomerPageState extends State floating: false, pinned: true, backgroundColor: AppColor.primary, - flexibleSpace: CustomerAppbar( - rotationAnimation: _rotationAnimation, - ), + flexibleSpace: CustomAppBar(title: 'Pelanggan'), actions: [ActionIconButton(onTap: () {}, icon: LineIcons.search)], ), diff --git a/lib/presentation/pages/finance/finance_page.dart b/lib/presentation/pages/finance/finance_page.dart index 8acbf22..b38a86d 100644 --- a/lib/presentation/pages/finance/finance_page.dart +++ b/lib/presentation/pages/finance/finance_page.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; import '../../../common/theme/theme.dart'; -import 'widgets/appbar.dart'; +import '../../components/appbar/appbar.dart'; import 'widgets/cash_flow.dart'; import 'widgets/category.dart'; import 'widgets/profit_loss.dart'; @@ -22,14 +22,10 @@ class _FinancePageState extends State late AnimationController _slideController; late AnimationController _fadeController; late AnimationController _scaleController; - late AnimationController _rotationController; - late AnimationController _floatingController; late Animation _slideAnimation; late Animation _fadeAnimation; late Animation _scaleAnimation; - late Animation rotationAnimation; - late Animation floatingAnimation; String selectedPeriod = 'Hari ini'; final List periods = [ @@ -43,16 +39,6 @@ class _FinancePageState extends State void initState() { super.initState(); - rotationAnimation = AnimationController( - duration: const Duration(seconds: 20), - vsync: this, - )..repeat(); - - floatingAnimation = AnimationController( - duration: const Duration(seconds: 3), - vsync: this, - )..repeat(reverse: true); - _slideController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, @@ -97,8 +83,6 @@ class _FinancePageState extends State _slideController.dispose(); _fadeController.dispose(); _scaleController.dispose(); - _rotationController.dispose(); - _floatingController.dispose(); super.dispose(); } @@ -115,10 +99,7 @@ class _FinancePageState extends State pinned: true, backgroundColor: AppColor.primary, elevation: 0, - flexibleSpace: FinanceAppbar( - rotationAnimation: rotationAnimation, - floatingAnimation: floatingAnimation, - ), + flexibleSpace: CustomAppBar(title: 'Keuangan'), ), // Header dengan filter periode diff --git a/lib/presentation/pages/finance/widgets/appbar.dart b/lib/presentation/pages/finance/widgets/appbar.dart deleted file mode 100644 index f37030f..0000000 --- a/lib/presentation/pages/finance/widgets/appbar.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../common/theme/theme.dart'; - -class FinanceAppbar extends StatelessWidget { - const FinanceAppbar({ - super.key, - required this.rotationAnimation, - required this.floatingAnimation, - }); - - final Animation rotationAnimation; - final Animation floatingAnimation; - - @override - Widget build(BuildContext context) { - return FlexibleSpaceBar( - titlePadding: const EdgeInsets.only(left: 50, bottom: 16), - title: Text( - 'Keuangan', - style: AppStyle.xl.copyWith( - color: AppColor.textWhite, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: AppColor.primaryGradient, - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - child: Stack( - children: [ - // Animated geometric shapes - Positioned( - right: -20, - top: -20, - child: AnimatedBuilder( - animation: Listenable.merge([ - rotationAnimation, - floatingAnimation, - ]), - builder: (context, child) { - return Transform.translate( - offset: Offset( - floatingAnimation.value * 10, - floatingAnimation.value * 15, - ), - child: Transform.rotate( - angle: rotationAnimation.value * 2 * 3.14159, - child: Container( - width: 120, - height: 120, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: RadialGradient( - colors: [ - AppColor.white.withOpacity(0.15), - AppColor.white.withOpacity(0.05), - ], - ), - boxShadow: [ - BoxShadow( - color: AppColor.white.withOpacity(0.1), - blurRadius: 20, - spreadRadius: 5, - ), - ], - ), - ), - ), - ); - }, - ), - ), - Positioned( - left: -30, - bottom: -30, - child: AnimatedBuilder( - animation: Listenable.merge([ - rotationAnimation, - floatingAnimation, - ]), - builder: (context, child) { - return Transform.translate( - offset: Offset( - -floatingAnimation.value * 8, - -floatingAnimation.value * 12, - ), - child: Transform.rotate( - angle: -rotationAnimation.value * 0.5 * 3.14159, - child: Container( - width: 100, - height: 100, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: RadialGradient( - colors: [ - AppColor.white.withOpacity(0.1), - AppColor.white.withOpacity(0.02), - ], - ), - ), - ), - ), - ); - }, - ), - ), - Positioned( - right: 80, - bottom: 30, - child: AnimatedBuilder( - animation: Listenable.merge([ - rotationAnimation, - floatingAnimation, - ]), - builder: (context, child) { - return Transform.translate( - offset: Offset( - floatingAnimation.value * 5, - -floatingAnimation.value * 8, - ), - child: Transform.rotate( - angle: -rotationAnimation.value * 0.3 * 3.14159, - child: Container( - width: 50, - height: 50, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - gradient: LinearGradient( - colors: [ - AppColor.white.withOpacity(0.12), - AppColor.white.withOpacity(0.04), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - ), - ), - ); - }, - ), - ), - // Additional floating elements - Positioned( - left: 60, - top: 80, - child: AnimatedBuilder( - animation: floatingAnimation, - builder: (context, child) { - return Transform.translate( - offset: Offset( - floatingAnimation.value * 3, - floatingAnimation.value * 6, - ), - child: Container( - width: 30, - height: 30, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.08), - ), - ), - ); - }, - ), - ), - Positioned( - right: 40, - top: 120, - child: AnimatedBuilder( - animation: floatingAnimation, - builder: (context, child) { - return Transform.translate( - offset: Offset( - -floatingAnimation.value * 4, - floatingAnimation.value * 7, - ), - child: Container( - width: 20, - height: 20, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6), - color: AppColor.white.withOpacity(0.06), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/pages/inventory/inventory_page.dart b/lib/presentation/pages/inventory/inventory_page.dart index f0004e7..16cd5c7 100644 --- a/lib/presentation/pages/inventory/inventory_page.dart +++ b/lib/presentation/pages/inventory/inventory_page.dart @@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import '../../../common/theme/theme.dart'; -import 'widgets/appbar.dart'; +import '../../components/appbar/appbar.dart'; import 'widgets/ingredient_tile.dart'; import 'widgets/product_tile.dart'; import 'widgets/stat_card.dart'; @@ -64,10 +64,8 @@ class _InventoryPageState extends State with TickerProviderStateMixin { late AnimationController _fadeAnimationController; late AnimationController _slideAnimationController; - late AnimationController _rotationAnimationController; late Animation _fadeAnimation; late Animation _slideAnimation; - late Animation rotationAnimation; late TabController _tabController; final List productItems = [ @@ -188,10 +186,6 @@ class _InventoryPageState extends State duration: const Duration(milliseconds: 800), vsync: this, ); - _rotationAnimationController = AnimationController( - duration: const Duration(seconds: 20), - vsync: this, - ); _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( @@ -208,21 +202,14 @@ class _InventoryPageState extends State ), ); - rotationAnimation = Tween( - begin: 0.0, - end: 2 * 3.14159, - ).animate(_rotationAnimationController); - _fadeAnimationController.forward(); _slideAnimationController.forward(); - _rotationAnimationController.repeat(); } @override void dispose() { _fadeAnimationController.dispose(); _slideAnimationController.dispose(); - _rotationAnimationController.dispose(); _tabController.dispose(); super.dispose(); } @@ -356,7 +343,7 @@ class _InventoryPageState extends State pinned: true, elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: InventoryAppBar(rotationAnimation: rotationAnimation), + flexibleSpace: CustomAppBar(title: 'Inventaris'), ); } diff --git a/lib/presentation/pages/inventory/widgets/appbar.dart b/lib/presentation/pages/inventory/widgets/appbar.dart deleted file mode 100644 index 6be4fe7..0000000 --- a/lib/presentation/pages/inventory/widgets/appbar.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../common/theme/theme.dart'; - -class InventoryAppBar extends StatelessWidget { - const InventoryAppBar({super.key, required this.rotationAnimation}); - - final Animation rotationAnimation; - - @override - Widget build(BuildContext context) { - return FlexibleSpaceBar( - titlePadding: const EdgeInsets.only(left: 50, bottom: 16), - title: Text( - 'Inventaris', - style: AppStyle.xl.copyWith( - color: AppColor.textWhite, - fontWeight: FontWeight.w600, - ), - ), - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: AppColor.primaryGradient, - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - child: Stack( - children: [ - Positioned( - right: -20, - top: -20, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: rotationAnimation.value, - child: Container( - width: 100, - height: 100, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.textWhite.withOpacity(0.1), - ), - ), - ); - }, - ), - ), - Positioned( - left: -30, - bottom: -30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.5, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.textWhite.withOpacity(0.05), - ), - ), - ); - }, - ), - ), - Positioned( - right: 80, - bottom: 30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.2, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: AppColor.textWhite.withOpacity(0.08), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/pages/product/product_page.dart b/lib/presentation/pages/product/product_page.dart index 8cce6f0..259d0ea 100644 --- a/lib/presentation/pages/product/product_page.dart +++ b/lib/presentation/pages/product/product_page.dart @@ -1,12 +1,10 @@ -import 'dart:math' as math; - 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/appbar/appbar.dart'; import '../../components/button/button.dart'; -import 'widgets/appbar.dart'; import 'widgets/category_delegate.dart'; import 'widgets/product_tile.dart'; @@ -26,10 +24,6 @@ class _ProductPageState extends State List categories = ['Semua', 'Makanan', 'Minuman', 'Snack', 'Dessert']; ViewType currentViewType = ViewType.grid; - // Animation - late AnimationController _rotationController; - late Animation _rotationAnimation; - // Sample product data List products = [ Product( @@ -135,19 +129,10 @@ class _ProductPageState extends State @override initState() { super.initState(); - _rotationController = AnimationController( - duration: const Duration(seconds: 3), - vsync: this, - )..repeat(); - _rotationAnimation = Tween( - begin: 0, - end: 2 * math.pi, - ).animate(_rotationController); } @override void dispose() { - _rotationController.dispose(); super.dispose(); } @@ -172,7 +157,7 @@ class _ProductPageState extends State floating: false, pinned: true, elevation: 0, - flexibleSpace: ProductAppbar(rotationAnimation: _rotationAnimation), + flexibleSpace: CustomAppBar(title: 'Produk'), actions: [ ActionIconButton(onTap: () {}, icon: LineIcons.search), ActionIconButton(onTap: _showAddProductDialog, icon: LineIcons.plus), diff --git a/lib/presentation/pages/product/widgets/appbar.dart b/lib/presentation/pages/product/widgets/appbar.dart deleted file mode 100644 index a81d162..0000000 --- a/lib/presentation/pages/product/widgets/appbar.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../common/theme/theme.dart'; - -class ProductAppbar extends StatelessWidget { - final Animation rotationAnimation; - const ProductAppbar({super.key, required this.rotationAnimation}); - - @override - Widget build(BuildContext context) { - return FlexibleSpaceBar( - titlePadding: const EdgeInsets.only(left: 50, bottom: 16), - title: Text( - 'Produk', - style: AppStyle.xl.copyWith( - color: AppColor.textWhite, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: AppColor.primaryGradient, - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - child: Stack( - children: [ - Positioned( - right: -20, - top: -20, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: rotationAnimation.value, - child: Container( - width: 100, - height: 100, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.1), - ), - ), - ); - }, - ), - ), - Positioned( - left: -30, - bottom: -30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.5, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.05), - ), - ), - ); - }, - ), - ), - Positioned( - right: 80, - bottom: 30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.2, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: AppColor.white.withOpacity(0.08), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/pages/purchase/purchase_page.dart b/lib/presentation/pages/purchase/purchase_page.dart index d5dbdd8..5775227 100644 --- a/lib/presentation/pages/purchase/purchase_page.dart +++ b/lib/presentation/pages/purchase/purchase_page.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; import '../../../common/theme/theme.dart'; -import 'widgets/appbar.dart'; +import '../../components/appbar/appbar.dart'; import 'widgets/purchase_tile.dart'; import 'widgets/stat_card.dart'; import 'widgets/status_chip.dart'; @@ -18,9 +18,7 @@ class PurchasePage extends StatefulWidget { class _PurchasePageState extends State with TickerProviderStateMixin { - late AnimationController rotationAnimation; late AnimationController cardAnimation; - late AnimationController floatingAnimation; String selectedFilter = 'Semua'; final List filterOptions = [ 'Semua', @@ -67,29 +65,18 @@ class _PurchasePageState extends State @override void initState() { super.initState(); - rotationAnimation = AnimationController( - duration: const Duration(seconds: 20), - vsync: this, - )..repeat(); cardAnimation = AnimationController( duration: const Duration(milliseconds: 1200), vsync: this, ); - floatingAnimation = AnimationController( - duration: const Duration(seconds: 3), - vsync: this, - )..repeat(reverse: true); - cardAnimation.forward(); } @override void dispose() { - rotationAnimation.dispose(); cardAnimation.dispose(); - floatingAnimation.dispose(); super.dispose(); } @@ -106,10 +93,7 @@ class _PurchasePageState extends State elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: PurchaseAppbar( - rotationAnimation: rotationAnimation, - floatingAnimation: floatingAnimation, - ), + flexibleSpace: CustomAppBar(title: 'Pembelian'), ), // Stats Cards diff --git a/lib/presentation/pages/purchase/widgets/appbar.dart b/lib/presentation/pages/purchase/widgets/appbar.dart deleted file mode 100644 index 0437c0d..0000000 --- a/lib/presentation/pages/purchase/widgets/appbar.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../common/theme/theme.dart'; - -class PurchaseAppbar extends StatelessWidget { - const PurchaseAppbar({ - super.key, - required this.rotationAnimation, - required this.floatingAnimation, - }); - - final AnimationController rotationAnimation; - final AnimationController floatingAnimation; - - @override - Widget build(BuildContext context) { - return FlexibleSpaceBar( - titlePadding: const EdgeInsets.only(left: 50, bottom: 16), - title: Text( - 'Pembelian', - style: AppStyle.xl.copyWith( - color: AppColor.textWhite, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: AppColor.primaryGradient, - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - child: Stack( - children: [ - // Animated geometric shapes with enhanced effects - Positioned( - right: -20, - top: -20, - child: AnimatedBuilder( - animation: Listenable.merge([ - rotationAnimation, - floatingAnimation, - ]), - builder: (context, child) { - return Transform.translate( - offset: Offset( - floatingAnimation.value * 10, - floatingAnimation.value * 15, - ), - child: Transform.rotate( - angle: rotationAnimation.value * 2 * 3.14159, - child: Container( - width: 120, - height: 120, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: RadialGradient( - colors: [ - AppColor.white.withOpacity(0.15), - AppColor.white.withOpacity(0.05), - ], - ), - boxShadow: [ - BoxShadow( - color: AppColor.white.withOpacity(0.1), - blurRadius: 20, - spreadRadius: 5, - ), - ], - ), - ), - ), - ); - }, - ), - ), - Positioned( - left: -30, - bottom: -30, - child: AnimatedBuilder( - animation: Listenable.merge([ - rotationAnimation, - floatingAnimation, - ]), - builder: (context, child) { - return Transform.translate( - offset: Offset( - -floatingAnimation.value * 8, - -floatingAnimation.value * 12, - ), - child: Transform.rotate( - angle: -rotationAnimation.value * 0.5 * 3.14159, - child: Container( - width: 100, - height: 100, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: RadialGradient( - colors: [ - AppColor.white.withOpacity(0.1), - AppColor.white.withOpacity(0.02), - ], - ), - ), - ), - ), - ); - }, - ), - ), - Positioned( - right: 80, - bottom: 30, - child: AnimatedBuilder( - animation: Listenable.merge([ - rotationAnimation, - floatingAnimation, - ]), - builder: (context, child) { - return Transform.translate( - offset: Offset( - floatingAnimation.value * 5, - -floatingAnimation.value * 8, - ), - child: Transform.rotate( - angle: -rotationAnimation.value * 0.3 * 3.14159, - child: Container( - width: 50, - height: 50, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - gradient: LinearGradient( - colors: [ - AppColor.white.withOpacity(0.12), - AppColor.white.withOpacity(0.04), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - ), - ), - ); - }, - ), - ), - // Additional floating elements - Positioned( - left: 60, - top: 80, - child: AnimatedBuilder( - animation: floatingAnimation, - builder: (context, child) { - return Transform.translate( - offset: Offset( - floatingAnimation.value * 3, - floatingAnimation.value * 6, - ), - child: Container( - width: 30, - height: 30, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.08), - ), - ), - ); - }, - ), - ), - Positioned( - right: 40, - top: 120, - child: AnimatedBuilder( - animation: floatingAnimation, - builder: (context, child) { - return Transform.translate( - offset: Offset( - -floatingAnimation.value * 4, - floatingAnimation.value * 7, - ), - child: Container( - width: 20, - height: 20, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6), - color: AppColor.white.withOpacity(0.06), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/pages/report/report_page.dart b/lib/presentation/pages/report/report_page.dart index 3884eb4..05510e4 100644 --- a/lib/presentation/pages/report/report_page.dart +++ b/lib/presentation/pages/report/report_page.dart @@ -4,9 +4,9 @@ import 'package:line_icons/line_icons.dart'; import 'dart:math' as math; import '../../../common/theme/theme.dart'; +import '../../components/appbar/appbar.dart'; import '../../components/button/button.dart'; import '../../components/spacer/spacer.dart'; -import 'widgets/appbar.dart'; import 'widgets/quick_stats.dart'; import 'widgets/report_action.dart'; import 'widgets/revenue_summary.dart'; @@ -80,14 +80,13 @@ class _ReportPageState extends State with TickerProviderStateMixin { backgroundColor: AppColor.background, body: CustomScrollView( slivers: [ - // Custom App Bar with Hero Effect SliverAppBar( expandedHeight: 120, floating: false, pinned: true, backgroundColor: AppColor.primary, centerTitle: false, - flexibleSpace: ReportAppBar(rotationAnimation: _rotationAnimation), + flexibleSpace: CustomAppBar(title: 'Laporan', isBack: false), actions: [ ActionIconButton(onTap: () {}, icon: LineIcons.download), ActionIconButton(onTap: () {}, icon: LineIcons.filter), diff --git a/lib/presentation/pages/report/widgets/appbar.dart b/lib/presentation/pages/report/widgets/appbar.dart deleted file mode 100644 index 09c34fa..0000000 --- a/lib/presentation/pages/report/widgets/appbar.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../common/theme/theme.dart'; - -class ReportAppBar extends StatelessWidget { - final Animation rotationAnimation; - const ReportAppBar({super.key, required this.rotationAnimation}); - - @override - Widget build(BuildContext context) { - return FlexibleSpaceBar( - titlePadding: const EdgeInsets.only(left: 20, bottom: 16), - title: Text( - 'Laporan Bisnis', - style: AppStyle.xl.copyWith( - color: AppColor.textWhite, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: AppColor.primaryGradient, - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - child: Stack( - children: [ - Positioned( - right: -20, - top: -20, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: rotationAnimation.value, - child: Container( - width: 100, - height: 100, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.1), - ), - ), - ); - }, - ), - ), - Positioned( - left: -30, - bottom: -30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.5, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.05), - ), - ), - ); - }, - ), - ), - Positioned( - right: 80, - bottom: 30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.2, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: AppColor.white.withOpacity(0.08), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/pages/sales/sales_page.dart b/lib/presentation/pages/sales/sales_page.dart index f3188cf..33d4368 100644 --- a/lib/presentation/pages/sales/sales_page.dart +++ b/lib/presentation/pages/sales/sales_page.dart @@ -2,8 +2,8 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import '../../../common/theme/theme.dart'; +import '../../components/appbar/appbar.dart'; import '../../components/spacer/spacer.dart'; -import 'widgets/appbar.dart'; import 'widgets/summary_card.dart'; // Data Models @@ -70,9 +70,6 @@ class SalesPage extends StatefulWidget { } class _SalesPageState extends State with TickerProviderStateMixin { - late AnimationController rotationAnimationController; - late Animation rotationAnimation; - late AnimationController slideAnimationController; late Animation slideAnimation; @@ -82,23 +79,6 @@ class _SalesPageState extends State with TickerProviderStateMixin { void initState() { super.initState(); - // Rotation Animation - rotationAnimationController = AnimationController( - duration: const Duration(seconds: 20), - vsync: this, - ); - rotationAnimation = - Tween( - begin: 0, - end: 6.28, // 2 * PI - ).animate( - CurvedAnimation( - parent: rotationAnimationController, - curve: Curves.linear, - ), - ); - rotationAnimationController.repeat(); - // Slide Animation slideAnimationController = AnimationController( duration: const Duration(milliseconds: 800), @@ -130,7 +110,6 @@ class _SalesPageState extends State with TickerProviderStateMixin { @override void dispose() { - rotationAnimationController.dispose(); slideAnimationController.dispose(); fadeAnimationController.dispose(); super.dispose(); @@ -187,7 +166,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { floating: false, pinned: true, backgroundColor: AppColor.primary, - flexibleSpace: SalesAppbar(rotationAnimation: rotationAnimation), + flexibleSpace: CustomAppBar(title: 'Penjualan'), ), // Date Range Header diff --git a/lib/presentation/pages/sales/widgets/appbar.dart b/lib/presentation/pages/sales/widgets/appbar.dart deleted file mode 100644 index 9dfbcf2..0000000 --- a/lib/presentation/pages/sales/widgets/appbar.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../common/theme/theme.dart'; - -class SalesAppbar extends StatelessWidget { - const SalesAppbar({super.key, required this.rotationAnimation}); - - final Animation rotationAnimation; - - @override - Widget build(BuildContext context) { - return FlexibleSpaceBar( - titlePadding: const EdgeInsets.only(left: 50, bottom: 16), - title: Text( - 'Penjualan', - style: AppStyle.xl.copyWith( - color: AppColor.textWhite, - fontWeight: FontWeight.w600, - ), - ), - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: AppColor.primaryGradient, - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - child: Stack( - children: [ - Positioned( - right: -20, - top: -20, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: rotationAnimation.value, - child: Container( - width: 100, - height: 100, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.1), - ), - ), - ); - }, - ), - ), - Positioned( - left: -30, - bottom: -30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.5, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.05), - ), - ), - ); - }, - ), - ), - Positioned( - right: 80, - bottom: 30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.2, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: AppColor.white.withOpacity(0.08), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/pages/schedule/schedule_page.dart b/lib/presentation/pages/schedule/schedule_page.dart index 481fdfb..89ae7bd 100644 --- a/lib/presentation/pages/schedule/schedule_page.dart +++ b/lib/presentation/pages/schedule/schedule_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:table_calendar/table_calendar.dart'; import '../../../common/theme/theme.dart'; +import '../../components/appbar/appbar.dart'; // Schedule model dengan optimasi class Schedule { @@ -212,107 +213,7 @@ class _SchedulePageState extends State floating: false, pinned: true, backgroundColor: AppColor.primary, - actions: [ - Container( - margin: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: AppColor.white.withOpacity(0.2), - borderRadius: BorderRadius.circular(12), - ), - child: IconButton( - onPressed: () => _showCalendarOptions(), - icon: Icon( - Icons.calendar_view_week, - color: AppColor.white, - size: 24, - ), - ), - ), - ], - flexibleSpace: FlexibleSpaceBar( - titlePadding: const EdgeInsets.only(left: 50, bottom: 16), - title: Text( - 'My Schedule', - style: TextStyle( - color: AppColor.white, - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - background: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [AppColor.primary, AppColor.primary.withOpacity(0.8)], - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - ), - ), - child: Stack( - children: [ - Positioned( - right: -20, - top: -20, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: rotationAnimation.value, - child: Container( - width: 100, - height: 100, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.1), - ), - ), - ); - }, - ), - ), - Positioned( - left: -30, - bottom: -30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.5, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.white.withOpacity(0.05), - ), - ), - ); - }, - ), - ), - Positioned( - right: 80, - bottom: 30, - child: AnimatedBuilder( - animation: rotationAnimation, - builder: (context, child) { - return Transform.rotate( - angle: -rotationAnimation.value * 0.2, - child: Container( - width: 40, - height: 40, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: AppColor.white.withOpacity(0.08), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ), + flexibleSpace: CustomAppBar(title: 'Jadwal'), ); } @@ -639,47 +540,6 @@ class _SchedulePageState extends State _slideController.forward(); } - void _showCalendarOptions() { - showModalBottomSheet( - context: context, - backgroundColor: Colors.transparent, - builder: (context) => Container( - decoration: BoxDecoration( - color: AppColor.white, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(24), - topRight: Radius.circular(24), - ), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - margin: const EdgeInsets.only(top: 12), - width: 40, - height: 4, - decoration: BoxDecoration( - color: AppColor.border, - borderRadius: BorderRadius.circular(2), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Text( - 'Calendar Options', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w700, - color: AppColor.textPrimary, - ), - ), - ), - ], - ), - ), - ); - } - void _showModernScheduleDetails(Schedule schedule) { showModalBottomSheet( context: context, diff --git a/lib/presentation/pages/transaction/transaction_page.dart b/lib/presentation/pages/transaction/transaction_page.dart index 7216c3c..f9ce760 100644 --- a/lib/presentation/pages/transaction/transaction_page.dart +++ b/lib/presentation/pages/transaction/transaction_page.dart @@ -1,13 +1,11 @@ -import 'dart:math' as math; - 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/appbar/appbar.dart'; import '../../components/button/button.dart'; import '../../components/spacer/spacer.dart'; -import 'widgets/appbar.dart'; import 'widgets/status_tile.dart'; import 'widgets/transaction_tile.dart'; @@ -23,10 +21,8 @@ class _TransactionPageState extends State with TickerProviderStateMixin { late AnimationController _fadeController; late AnimationController _slideController; - late AnimationController _rotationController; late Animation _fadeAnimation; late Animation _slideAnimation; - late Animation _rotationAnimation; // Filter state String selectedFilter = 'All'; @@ -51,11 +47,6 @@ class _TransactionPageState extends State vsync: this, ); - _rotationController = AnimationController( - duration: const Duration(seconds: 3), - vsync: this, - )..repeat(); - _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), ); @@ -65,11 +56,6 @@ class _TransactionPageState extends State CurvedAnimation(parent: _slideController, curve: Curves.elasticOut), ); - _rotationAnimation = Tween( - begin: 0, - end: 2 * math.pi, - ).animate(_rotationController); - _fadeController.forward(); _slideController.forward(); } @@ -78,7 +64,6 @@ class _TransactionPageState extends State void dispose() { _fadeController.dispose(); _slideController.dispose(); - _rotationController.dispose(); super.dispose(); } @@ -154,9 +139,7 @@ class _TransactionPageState extends State pinned: true, backgroundColor: AppColor.primary, centerTitle: false, - flexibleSpace: TransactionAppBar( - rotationAnimation: _rotationAnimation, - ), + flexibleSpace: CustomAppBar(title: 'Transaction', isBack: false), actions: [ ActionIconButton(onTap: () {}, icon: LineIcons.filter), SpaceWidth(8),