import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import '../../../../common/theme/theme.dart'; import '../../../components/button/button.dart'; import '../../../components/spacer/spacer.dart'; import 'widgets/email_field.dart'; import 'widgets/password_field.dart'; @RoutePage() class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State with TickerProviderStateMixin { final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); bool _isLoading = false; late AnimationController _fadeController; late AnimationController _slideController; late Animation _fadeAnimation; late Animation _slideAnimation; @override void initState() { super.initState(); _fadeController = AnimationController( duration: const Duration(milliseconds: 1500), vsync: this, ); _slideController = AnimationController( duration: const Duration(milliseconds: 1200), vsync: this, ); _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), ); _slideAnimation = Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), ); _emailController.text = 'test@example.com'; _passwordController.text = 'password'; _fadeController.forward(); _slideController.forward(); } @override void dispose() { _fadeController.dispose(); _slideController.dispose(); _emailController.dispose(); _passwordController.dispose(); super.dispose(); } Future _handleLogin() async { if (_formKey.currentState!.validate()) { setState(() { _isLoading = true; }); // Simulasi proses login await Future.delayed(const Duration(seconds: 2)); setState(() { _isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: AppColor.primaryGradient, ), ), child: SafeArea( child: Center( child: SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: AppValue.padding), child: FadeTransition( opacity: _fadeAnimation, child: SlideTransition( position: _slideAnimation, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ _buildLogo(), SpaceHeight(48), _buildLoginCard(), SpaceHeight(24), _buildFooter(), ], ), ), ), ), ), ), ), ); } Widget _buildLogo() { return Column( children: [ Text( 'Welcome Back', style: AppStyle.h1.copyWith( fontWeight: FontWeight.bold, color: AppColor.white, ), ), const SpaceHeight(8), Text( 'Sign in to your account', style: AppStyle.lg.copyWith(color: AppColor.textLight), ), ], ); } Widget _buildLoginCard() { return Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), decoration: BoxDecoration( color: AppColor.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: AppColor.black.withOpacity(0.1), blurRadius: 30, offset: const Offset(0, 15), ), ], ), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ LoginEmailField(controller: _emailController), const SpaceHeight(24), LoginPasswordField(controller: _passwordController), const SpaceHeight(16), _buildForgetPassword(), const SpaceHeight(32), _buildLoginButton(), ], ), ), ); } Widget _buildForgetPassword() { return Align( alignment: Alignment.centerRight, child: GestureDetector( onTap: () {}, child: Text( 'Forgot Password?', style: AppStyle.md.copyWith( color: AppColor.primary, fontWeight: FontWeight.w600, ), ), ), ); } Widget _buildLoginButton() { return AppElevatedButton( text: 'Sign In', isLoading: _isLoading, onPressed: _isLoading ? null : _handleLogin, ); } Widget _buildFooter() { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Don't have an account? ", style: AppStyle.md.copyWith(color: AppColor.textLight), ), GestureDetector( onTap: () {}, child: Text( 'Sign Up', style: AppStyle.md.copyWith( color: AppColor.white, fontWeight: FontWeight.bold, ), ), ), ], ); } }