feat: custom appbar
This commit is contained in:
parent
d334bb8f17
commit
d73cd1a574
189
lib/presentation/components/appbar/appbar.dart
Normal file
189
lib/presentation/components/appbar/appbar.dart
Normal file
@ -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<CustomAppBar> createState() => _CustomAppBarState();
|
||||
}
|
||||
|
||||
class _CustomAppBarState extends State<CustomAppBar>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _particleController;
|
||||
late AnimationController _waveController;
|
||||
late AnimationController _breathController;
|
||||
|
||||
late Animation<double> _particleAnimation;
|
||||
late Animation<double> _waveAnimation;
|
||||
late Animation<double> _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<double>(
|
||||
begin: 0.0,
|
||||
end: 2 * math.pi,
|
||||
).animate(_particleController);
|
||||
|
||||
_waveAnimation = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 2 * math.pi,
|
||||
).animate(_waveController);
|
||||
|
||||
_breathAnimation = Tween<double>(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,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<CustomerPage>
|
||||
),
|
||||
];
|
||||
|
||||
// Animation
|
||||
late AnimationController _rotationController;
|
||||
late Animation<double> _rotationAnimation;
|
||||
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
_rotationController = AnimationController(
|
||||
duration: const Duration(seconds: 3),
|
||||
vsync: this,
|
||||
)..repeat();
|
||||
_rotationAnimation = Tween<double>(
|
||||
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<CustomerPage>
|
||||
floating: false,
|
||||
pinned: true,
|
||||
backgroundColor: AppColor.primary,
|
||||
flexibleSpace: CustomerAppbar(
|
||||
rotationAnimation: _rotationAnimation,
|
||||
),
|
||||
flexibleSpace: CustomAppBar(title: 'Pelanggan'),
|
||||
actions: [ActionIconButton(onTap: () {}, icon: LineIcons.search)],
|
||||
),
|
||||
|
||||
|
||||
@ -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<FinancePage>
|
||||
late AnimationController _slideController;
|
||||
late AnimationController _fadeController;
|
||||
late AnimationController _scaleController;
|
||||
late AnimationController _rotationController;
|
||||
late AnimationController _floatingController;
|
||||
|
||||
late Animation<Offset> _slideAnimation;
|
||||
late Animation<double> _fadeAnimation;
|
||||
late Animation<double> _scaleAnimation;
|
||||
late Animation<double> rotationAnimation;
|
||||
late Animation<double> floatingAnimation;
|
||||
|
||||
String selectedPeriod = 'Hari ini';
|
||||
final List<String> periods = [
|
||||
@ -43,16 +39,6 @@ class _FinancePageState extends State<FinancePage>
|
||||
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<FinancePage>
|
||||
_slideController.dispose();
|
||||
_fadeController.dispose();
|
||||
_scaleController.dispose();
|
||||
_rotationController.dispose();
|
||||
_floatingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -115,10 +99,7 @@ class _FinancePageState extends State<FinancePage>
|
||||
pinned: true,
|
||||
backgroundColor: AppColor.primary,
|
||||
elevation: 0,
|
||||
flexibleSpace: FinanceAppbar(
|
||||
rotationAnimation: rotationAnimation,
|
||||
floatingAnimation: floatingAnimation,
|
||||
),
|
||||
flexibleSpace: CustomAppBar(title: 'Keuangan'),
|
||||
),
|
||||
|
||||
// Header dengan filter periode
|
||||
|
||||
@ -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<double> rotationAnimation;
|
||||
final Animation<double> 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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<InventoryPage>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _fadeAnimationController;
|
||||
late AnimationController _slideAnimationController;
|
||||
late AnimationController _rotationAnimationController;
|
||||
late Animation<double> _fadeAnimation;
|
||||
late Animation<Offset> _slideAnimation;
|
||||
late Animation<double> rotationAnimation;
|
||||
late TabController _tabController;
|
||||
|
||||
final List<ProductItem> productItems = [
|
||||
@ -188,10 +186,6 @@ class _InventoryPageState extends State<InventoryPage>
|
||||
duration: const Duration(milliseconds: 800),
|
||||
vsync: this,
|
||||
);
|
||||
_rotationAnimationController = AnimationController(
|
||||
duration: const Duration(seconds: 20),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(
|
||||
@ -208,21 +202,14 @@ class _InventoryPageState extends State<InventoryPage>
|
||||
),
|
||||
);
|
||||
|
||||
rotationAnimation = Tween<double>(
|
||||
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<InventoryPage>
|
||||
pinned: true,
|
||||
elevation: 0,
|
||||
backgroundColor: AppColor.primary,
|
||||
flexibleSpace: InventoryAppBar(rotationAnimation: rotationAnimation),
|
||||
flexibleSpace: CustomAppBar(title: 'Inventaris'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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<double> 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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<ProductPage>
|
||||
List<String> categories = ['Semua', 'Makanan', 'Minuman', 'Snack', 'Dessert'];
|
||||
ViewType currentViewType = ViewType.grid;
|
||||
|
||||
// Animation
|
||||
late AnimationController _rotationController;
|
||||
late Animation<double> _rotationAnimation;
|
||||
|
||||
// Sample product data
|
||||
List<Product> products = [
|
||||
Product(
|
||||
@ -135,19 +129,10 @@ class _ProductPageState extends State<ProductPage>
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
_rotationController = AnimationController(
|
||||
duration: const Duration(seconds: 3),
|
||||
vsync: this,
|
||||
)..repeat();
|
||||
_rotationAnimation = Tween<double>(
|
||||
begin: 0,
|
||||
end: 2 * math.pi,
|
||||
).animate(_rotationController);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_rotationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -172,7 +157,7 @@ class _ProductPageState extends State<ProductPage>
|
||||
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),
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../common/theme/theme.dart';
|
||||
|
||||
class ProductAppbar extends StatelessWidget {
|
||||
final Animation<double> 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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<PurchasePage>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController rotationAnimation;
|
||||
late AnimationController cardAnimation;
|
||||
late AnimationController floatingAnimation;
|
||||
String selectedFilter = 'Semua';
|
||||
final List<String> filterOptions = [
|
||||
'Semua',
|
||||
@ -67,29 +65,18 @@ class _PurchasePageState extends State<PurchasePage>
|
||||
@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<PurchasePage>
|
||||
elevation: 0,
|
||||
backgroundColor: AppColor.primary,
|
||||
|
||||
flexibleSpace: PurchaseAppbar(
|
||||
rotationAnimation: rotationAnimation,
|
||||
floatingAnimation: floatingAnimation,
|
||||
),
|
||||
flexibleSpace: CustomAppBar(title: 'Pembelian'),
|
||||
),
|
||||
|
||||
// Stats Cards
|
||||
|
||||
@ -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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<ReportPage> 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),
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../common/theme/theme.dart';
|
||||
|
||||
class ReportAppBar extends StatelessWidget {
|
||||
final Animation<double> 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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<SalesPage> with TickerProviderStateMixin {
|
||||
late AnimationController rotationAnimationController;
|
||||
late Animation<double> rotationAnimation;
|
||||
|
||||
late AnimationController slideAnimationController;
|
||||
late Animation<Offset> slideAnimation;
|
||||
|
||||
@ -82,23 +79,6 @@ class _SalesPageState extends State<SalesPage> with TickerProviderStateMixin {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// Rotation Animation
|
||||
rotationAnimationController = AnimationController(
|
||||
duration: const Duration(seconds: 20),
|
||||
vsync: this,
|
||||
);
|
||||
rotationAnimation =
|
||||
Tween<double>(
|
||||
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<SalesPage> with TickerProviderStateMixin {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
rotationAnimationController.dispose();
|
||||
slideAnimationController.dispose();
|
||||
fadeAnimationController.dispose();
|
||||
super.dispose();
|
||||
@ -187,7 +166,7 @@ class _SalesPageState extends State<SalesPage> with TickerProviderStateMixin {
|
||||
floating: false,
|
||||
pinned: true,
|
||||
backgroundColor: AppColor.primary,
|
||||
flexibleSpace: SalesAppbar(rotationAnimation: rotationAnimation),
|
||||
flexibleSpace: CustomAppBar(title: 'Penjualan'),
|
||||
),
|
||||
|
||||
// Date Range Header
|
||||
|
||||
@ -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<double> 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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<SchedulePage>
|
||||
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<SchedulePage>
|
||||
_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,
|
||||
|
||||
@ -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<TransactionPage>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _fadeController;
|
||||
late AnimationController _slideController;
|
||||
late AnimationController _rotationController;
|
||||
late Animation<double> _fadeAnimation;
|
||||
late Animation<Offset> _slideAnimation;
|
||||
late Animation<double> _rotationAnimation;
|
||||
|
||||
// Filter state
|
||||
String selectedFilter = 'All';
|
||||
@ -51,11 +47,6 @@ class _TransactionPageState extends State<TransactionPage>
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_rotationController = AnimationController(
|
||||
duration: const Duration(seconds: 3),
|
||||
vsync: this,
|
||||
)..repeat();
|
||||
|
||||
_fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut),
|
||||
);
|
||||
@ -65,11 +56,6 @@ class _TransactionPageState extends State<TransactionPage>
|
||||
CurvedAnimation(parent: _slideController, curve: Curves.elasticOut),
|
||||
);
|
||||
|
||||
_rotationAnimation = Tween<double>(
|
||||
begin: 0,
|
||||
end: 2 * math.pi,
|
||||
).animate(_rotationController);
|
||||
|
||||
_fadeController.forward();
|
||||
_slideController.forward();
|
||||
}
|
||||
@ -78,7 +64,6 @@ class _TransactionPageState extends State<TransactionPage>
|
||||
void dispose() {
|
||||
_fadeController.dispose();
|
||||
_slideController.dispose();
|
||||
_rotationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -154,9 +139,7 @@ class _TransactionPageState extends State<TransactionPage>
|
||||
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),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user