// ignore_for_file: use_build_context_synchronously, deprecated_member_use, unused_import import 'package:flutter/material.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:http/http.dart' as http; import 'package:monarch/main_pages/HomePage/homepage.dart'; import 'package:monarch/main_pages/HomePage/Components/Voice/voice_dialog.dart'; import 'package:monarch/other_pages/enviroment.dart'; import 'dart:convert'; import 'dart:math' as math; import 'package:shared_preferences/shared_preferences.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State with TickerProviderStateMixin { final GoogleSignIn _googleSignIn = GoogleSignIn( scopes: [ 'email', 'profile', 'openid', 'https://www.googleapis.com/auth/gmail.readonly', ], serverClientId: Environment.serverClientId, ); bool _isLoading = false; late AnimationController _fadeController; late AnimationController _slideController; late AnimationController _scaleController; late AnimationController _rotationController; late Animation _fadeAnimation; late Animation _slideAnimation; late Animation _scaleAnimation; late Animation _rotationAnimation; @override void initState() { super.initState(); _initAnimations(); _startAnimations(); } void _initAnimations() { _fadeController = AnimationController( duration: const Duration(milliseconds: 1500), vsync: this, ); _slideController = AnimationController( duration: const Duration(milliseconds: 1200), vsync: this, ); _scaleController = AnimationController( duration: const Duration(milliseconds: 1000), vsync: this, ); _rotationController = AnimationController( duration: const Duration(seconds: 20), vsync: this, ); _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), ); _slideAnimation = Tween( begin: const Offset(0, 1), end: Offset.zero, ).animate( CurvedAnimation(parent: _slideController, curve: Curves.elasticOut), ); _scaleAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _scaleController, curve: Curves.elasticOut), ); _rotationAnimation = Tween( begin: 0.0, end: 2 * math.pi, ).animate(_rotationController); } void _startAnimations() { Future.delayed(const Duration(milliseconds: 300), () { _fadeController.forward(); }); Future.delayed(const Duration(milliseconds: 500), () { _slideController.forward(); }); Future.delayed(const Duration(milliseconds: 700), () { _scaleController.forward(); }); _rotationController.repeat(); } @override void dispose() { _fadeController.dispose(); _slideController.dispose(); _scaleController.dispose(); _rotationController.dispose(); super.dispose(); } Future _handleGoogleSignIn() async { setState(() => _isLoading = true); try { final GoogleSignInAccount? account = await _googleSignIn.signIn(); if (account == null) { setState(() => _isLoading = false); return; } final GoogleSignInAuthentication auth = await account.authentication; final String? idToken = auth.idToken; final String? accessToken = auth.accessToken; if (idToken == null || accessToken == null) { debugPrint("❌ Failed to get tokens"); return; } final uri = Uri.parse("${Environment.baseUrl}/auth/google/token"); final res = await http.post( uri, headers: {"Content-Type": "application/json"}, body: jsonEncode({"idToken": idToken}), ); if (res.statusCode == 200) { final data = jsonDecode(res.body); if (data['success'] == true) { final prefs = await SharedPreferences.getInstance(); prefs.setString('userId', data['user']['_id']); prefs.setString('accessToken', accessToken); Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) => FinTrackHomePage()), ); } else { debugPrint("❌ Login failed: ${data['error']}"); } } else { debugPrint("❌ Backend error: ${res.body}"); } } catch (e) { debugPrint("⚠ Google Sign-In error: $e"); } finally { setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; return Scaffold( body: Container( width: double.infinity, height: double.infinity, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF1DB584), // Your app's primary green Color(0xFF0FA968), Color(0xFF059649), ], stops: [0.0, 0.5, 1.0], ), ), child: Stack( children: [ // Animated Background Elements ...List.generate(6, (index) { return AnimatedBuilder( animation: _rotationController, builder: (context, child) { return Positioned( top: size.height * (0.1 + (index * 0.15)), left: size.width * (0.1 + (index * 0.12)), child: Transform.rotate( angle: _rotationAnimation.value + (index * 0.5), child: Container( width: 60 + (index * 10), height: 60 + (index * 10), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.05), border: Border.all( color: Colors.white.withOpacity(0.1), width: 2, ), ), ), ), ); }, ); }), // Floating Particles ...List.generate(12, (index) { return AnimatedBuilder( animation: _rotationController, builder: (context, child) { return Positioned( top: size.height * (0.2 + (index * 0.06)), right: size.width * (0.1 + (index * 0.05)), child: Transform.translate( offset: Offset( math.sin(_rotationAnimation.value + index) * 20, math.cos(_rotationAnimation.value + index) * 15, ), child: Container( width: 8 + (index % 3) * 4, height: 8 + (index % 3) * 4, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.3), boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.1), blurRadius: 10, spreadRadius: 2, ), ], ), ), ), ); }, ); }), // Main Content SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( children: [ const Spacer(), // Logo Section FadeTransition( opacity: _fadeAnimation, child: Column( children: [ ScaleTransition( scale: _scaleAnimation, child: Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 30, spreadRadius: 5, offset: const Offset(0, 10), ), ], ), child: const Icon( Icons.account_balance_wallet_rounded, size: 60, color: Color(0xFF1DB584), ), ), ), const SizedBox(height: 32), // App Title const Text( 'FinTrack', style: TextStyle( fontFamily: 'Inter', fontSize: 42, fontWeight: FontWeight.w800, color: Colors.white, letterSpacing: -1.5, ), ), const SizedBox(height: 12), // Subtitle Text( 'Your Smart Financial Companion', style: TextStyle( fontFamily: 'Inter', fontSize: 16, color: Colors.white.withOpacity(0.9), fontWeight: FontWeight.w400, letterSpacing: 0.3, ), ), ], ), ), const Spacer(), // Features Section SlideTransition( position: _slideAnimation, child: Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(24), border: Border.all( color: Colors.white.withOpacity(0.2), width: 1, ), ), child: Column( children: [ Row( children: [ _buildFeatureItem( Icons.trending_up_rounded, 'Track Expenses', ), const SizedBox(width: 24), _buildFeatureItem( Icons.insights_rounded, 'Smart Analytics', ), ], ), const SizedBox(height: 16), Row( children: [ _buildFeatureItem( Icons.security_rounded, 'Secure & Private', ), const SizedBox(width: 24), _buildFeatureItem( Icons.sync_rounded, 'Auto Sync', ), ], ), ], ), ), ), const SizedBox(height: 48), // Google Sign In Button SlideTransition( position: _slideAnimation, child: _isLoading ? Container( width: double.infinity, height: 60, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.15), blurRadius: 20, spreadRadius: 2, offset: const Offset(0, 8), ), ], ), child: const Center( child: SizedBox( width: 24, height: 24, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Color(0xFF1DB584), ), ), ), ), ) : Container( width: double.infinity, height: 60, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.15), blurRadius: 20, spreadRadius: 2, offset: const Offset(0, 8), ), ], ), child: Material( color: Colors.transparent, child: InkWell( onTap: _handleGoogleSignIn, borderRadius: BorderRadius.circular(30), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 24, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.network( 'https://developers.google.com/identity/images/g-logo.png', width: 24, height: 24, ), const SizedBox(width: 16), const Text( 'Continue with Google', style: TextStyle( fontFamily: 'Inter', fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFF1F2937), letterSpacing: 0.2, ), ), ], ), ), ), ), ), ), const SizedBox(height: 24), // Terms Text FadeTransition( opacity: _fadeAnimation, child: Text( 'By continuing, you agree to our Terms of Service\nand Privacy Policy', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'Inter', fontSize: 12, color: Colors.white.withOpacity(0.7), fontWeight: FontWeight.w400, height: 1.5, ), ), ), const SizedBox(height: 48), ], ), ), ), ], ), ), ); } Widget _buildFeatureItem(IconData icon, String text) { return Expanded( child: Row( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: Colors.white, size: 20), ), const SizedBox(width: 12), Expanded( child: Text( text, style: const TextStyle( fontFamily: 'Inter', color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500, ), ), ), ], ), ); } }