import 'package:flutter/material.dart'; import '../utils/app_colors.dart'; import '../widgets/custom_text_field.dart'; import '../widgets/custom_button.dart'; import '../services/auth_service.dart'; import '../services/firestore_service.dart'; import 'dashboard_screen.dart'; import 'package:firebase_auth/firebase_auth.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({Key? key}) : super(key: key); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State with TickerProviderStateMixin { final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _authService = AuthService(); final _firestoreService = FirestoreService(); bool _isLoading = false; late AnimationController _animationController; late AnimationController _pulseAnimationController; late Animation _fadeAnimation; late Animation _slideAnimation; late Animation _scaleAnimation; late Animation _pulseAnimation; @override void initState() { super.initState(); // Initialize animation controllers _animationController = AnimationController( duration: const Duration(milliseconds: 1500), vsync: this, ); _pulseAnimationController = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this, ); // Initialize animations _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _animationController, curve: Curves.easeInOut), ); _slideAnimation = Tween( begin: const Offset(0, 0.5), end: Offset.zero, ).animate( CurvedAnimation(parent: _animationController, curve: Curves.elasticOut), ); _scaleAnimation = Tween(begin: 0.8, end: 1.0).animate( CurvedAnimation(parent: _animationController, curve: Curves.elasticOut), ); _pulseAnimation = Tween(begin: 1.0, end: 1.1).animate( CurvedAnimation( parent: _pulseAnimationController, curve: Curves.easeInOut, ), ); // Start animations _animationController.forward(); _pulseAnimationController.repeat(reverse: true); } @override void dispose() { _animationController.dispose(); _pulseAnimationController.dispose(); _emailController.dispose(); _passwordController.dispose(); super.dispose(); } String? _validateEmail(String? value) { if (value == null || value.isEmpty) { return 'Email tidak boleh kosong'; } if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) { return 'Format email tidak valid'; } return null; } String? _validatePassword(String? value) { if (value == null || value.isEmpty) { return 'Password tidak boleh kosong'; } if (value.length < 6) { return 'Password minimal 6 karakter'; } return null; } void _handleLogin() async { if (_formKey.currentState!.validate()) { setState(() { _isLoading = true; }); try { // Login dengan Firebase UserCredential? result = await _authService.signInWithEmailAndPassword( email: _emailController.text.trim(), password: _passwordController.text.trim(), ); if (result?.user != null) { // Cek apakah user profile sudah ada di Firestore var userProfile = await _firestoreService.getUserProfile( result!.user!.uid, ); if (userProfile == null) { // Buat profile baru jika belum ada await _firestoreService.createUserProfile( uid: result.user!.uid, email: result.user!.email!, displayName: result.user!.displayName, photoURL: result.user!.photoURL, ); } // Tampilkan pesan sukses ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Login berhasil!'), backgroundColor: AppColors.accentGreen, ), ); // TODO: Navigate to home screen Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const DashboardScreen()), ); } } catch (e) { // Tampilkan error message ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString()), backgroundColor: AppColors.textError, ), ); } finally { setState(() { _isLoading = false; }); } } } @override Widget build(BuildContext context) { final screenHeight = MediaQuery.of(context).size.height; final screenWidth = MediaQuery.of(context).size.width; return Scaffold( body: Container( width: screenWidth, height: screenHeight, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppColors.backgroundLight, AppColors.backgroundWhite, Color(0xFFFFF8F0), ], ), ), child: SafeArea( child: FadeTransition( opacity: _fadeAnimation, child: SlideTransition( position: _slideAnimation, child: ScaleTransition( scale: _scaleAnimation, child: SingleChildScrollView( padding: EdgeInsets.symmetric( horizontal: screenWidth * 0.08, vertical: 16, ), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox(height: screenHeight * 0.05), // Logo and App Title _buildHeader(), SizedBox(height: screenHeight * 0.06), // Login Form _buildLoginForm(), SizedBox(height: screenHeight * 0.04), // Login Button CustomButton( text: 'Masuk', onPressed: _handleLogin, isLoading: _isLoading, width: double.infinity, height: 54, icon: Icons.login, ), SizedBox(height: screenHeight * 0.04), // Footer _buildFooter(), ], ), ), ), ), ), ), ), ), ); } Widget _buildHeader() { return Column( children: [ // Fire Detection Logo with animated pulse AnimatedBuilder( animation: _pulseAnimation, builder: (context, child) { return Transform.scale( scale: _pulseAnimation.value, child: Container( width: 110, height: 110, decoration: BoxDecoration( shape: BoxShape.circle, gradient: AppColors.primaryGradient, boxShadow: [ BoxShadow( color: AppColors.primaryRed.withOpacity(0.4), blurRadius: 25, offset: const Offset(0, 10), ), BoxShadow( color: AppColors.primaryOrange.withOpacity(0.3), blurRadius: 40, offset: const Offset(0, 15), ), ], ), child: const Icon( Icons.local_fire_department, size: 55, color: AppColors.textLight, ), ), ); }, ), const SizedBox(height: 20), // App Title const Text( 'Fire Detection', style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: AppColors.textPrimary, letterSpacing: 1.2, ), ), const SizedBox(height: 8), // Subtitle const Text( 'Sistem Deteksi Kebakaran Otomatis', style: TextStyle( fontSize: 14, color: AppColors.textSecondary, fontWeight: FontWeight.w400, ), ), ], ); } Widget _buildLoginForm() { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: AppColors.backgroundWhite, borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: AppColors.secondaryGray.withOpacity(0.08), blurRadius: 25, offset: const Offset(0, 10), ), BoxShadow( color: AppColors.primaryRed.withOpacity(0.05), blurRadius: 30, offset: const Offset(0, 20), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Masuk ke Akun Anda', style: TextStyle( fontSize: 22, fontWeight: FontWeight.w600, color: AppColors.textPrimary, ), ), const SizedBox(height: 6), const Text( 'Silakan masukkan email dan password Anda', style: TextStyle(fontSize: 13, color: AppColors.textSecondary), ), const SizedBox(height: 24), // Email Field CustomTextField( hintText: 'Masukkan email Anda', labelText: 'Email', prefixIcon: Icons.email_outlined, controller: _emailController, validator: _validateEmail, keyboardType: TextInputType.emailAddress, ), // Password Field CustomTextField( hintText: 'Masukkan password Anda', labelText: 'Password', prefixIcon: Icons.lock_outline, controller: _passwordController, validator: _validatePassword, obscureText: true, ), ], ), ); } Widget _buildFooter() { return Column( children: [ // Row( // mainAxisAlignment: MainAxisAlignment.center, // children: [ // const Text( // 'Belum punya akun? ', // style: TextStyle(color: AppColors.textSecondary, fontSize: 14), // ), // TextButton( // onPressed: () { // // Navigate to register page // }, // child: const Text( // 'Daftar Sekarang', // style: TextStyle( // color: AppColors.primaryRed, // fontSize: 14, // fontWeight: FontWeight.w600, // ), // ), // ), // ], // ), const SizedBox(height: 16), // Version Info const Text( 'Version 1.0.0', style: TextStyle(color: AppColors.textSecondary, fontSize: 12), ), const SizedBox(height: 4), // Copyright const Text( '© 2025 Fire Detection System', style: TextStyle(color: AppColors.textSecondary, fontSize: 12), ), ], ); } }