import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'firebase_options.dart'; import 'screens/home_screen.dart'; import 'screens/notification_permission_screen.dart'; import 'screens/edit_profile_screen.dart'; import 'services/auth_service.dart'; import 'services/user_service.dart'; import 'services/app_lifecycle_service.dart'; final GlobalKey navigatorKey = GlobalKey(); void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // Initialize app lifecycle service AppLifecycleService.initialize(); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Wesal', theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'Roboto'), home: SplashScreen(), navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, ); } } class SplashScreen extends StatefulWidget { @override _SplashScreenState createState() => _SplashScreenState(); } class _SplashScreenState extends State { @override void initState() { super.initState(); _checkAuthenticationStatus(); } Future _checkAuthenticationStatus() async { await Future.delayed(Duration(milliseconds: 500)); final isLoggedIn = await AuthService.isLoggedIn(); if (isLoggedIn) { final userResult = await UserService.getCurrentUser(); if (userResult['success'] == true) { final userData = userResult['data']; // Check if user needs onboarding (activated = 0) if (userData['activated'] == 0) { Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => EditProfileScreen(userData: userData, isOnboarding: true), ), ); } else { // Start polling services now that user is logged in and going to main screen AppLifecycleService.startAllPolling(); Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => HomeScreen()), ); } } else { await AuthService.logout(); Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => LandingPage()), ); } } else { Navigator.of( context, ).pushReplacement(MaterialPageRoute(builder: (context) => LandingPage())); } } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFF32B0A5), Color(0xFF4600B9)], stops: [0.0, 0.5], ), ), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'وصال', style: TextStyle( fontSize: 160, fontWeight: FontWeight.w200, fontFamily: 'Blaka', color: Colors.white, shadows: [ Shadow( offset: Offset(2, 2), blurRadius: 4, color: Colors.black.withOpacity(0.3), ), ], ), ), SizedBox(height: 40), CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.white), ), ], ), ), ), ); } } class LandingPage extends StatefulWidget { @override _LandingPageState createState() => _LandingPageState(); } class _LandingPageState extends State { void _navigateDirectlyToLogin() { Navigator.of( context, ).push(MaterialPageRoute(builder: (context) => SignInPage())); } @override Widget build(BuildContext context) { return PopScope( canPop: false, // Prevent back navigation from landing page child: Scaffold( body: Stack( children: [ // Background gradient Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF32B0A5), // Teal Color(0xFF4600B9), // Purple ], stops: [0.0, 0.5], ), ), ), // Main content SafeArea( child: Column( children: [ Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Logo Container( padding: EdgeInsets.all(40), child: Text( 'وصال', style: TextStyle( fontSize: 160, fontWeight: FontWeight.w200, fontFamily: 'Blaka', color: Colors.white, shadows: [ Shadow( offset: Offset(2, 2), blurRadius: 4, color: Colors.black.withOpacity(0.3), ), ], ), ), ), SizedBox(height: 60), // Subtitle Text( 'Connections, Made\nEasier!', textAlign: TextAlign.center, style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600, color: Colors.white, height: 1.2, ), ), SizedBox(height: 80), // Get Started Button Container( width: 280, height: 56, child: ElevatedButton( onPressed: _navigateDirectlyToLogin, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF6A4C93), foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(28), ), elevation: 8, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Get Started', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, ), ), SizedBox(width: 8), Icon(Icons.arrow_forward, size: 20), ], ), ), ), SizedBox(height: 24), ], ), ), ), ], ), ), ], ), ), ); } } class SignInPage extends StatefulWidget { @override _SignInPageState createState() => _SignInPageState(); } class _SignInPageState extends State { final _formKey = GlobalKey(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); bool _isPasswordVisible = false; bool _isLoading = false; void _showHelpBottomSheet() { showModalBottomSheet( context: context, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), builder: (context) => Container( padding: EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(2), ), ), SizedBox(height: 24), Icon(Icons.contact_support, size: 48, color: Color(0xFF6A4C93)), SizedBox(height: 16), Text( 'Need Help?', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black87, ), ), SizedBox(height: 16), Text( 'For account creation or password reset, please contact ERP Management Group from your Aramco email address.', textAlign: TextAlign.center, style: TextStyle( fontSize: 16, color: Colors.grey[700], height: 1.4, ), ), SizedBox(height: 24), Container( width: double.infinity, child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF6A4C93), foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), padding: EdgeInsets.symmetric(vertical: 16), ), child: Text( 'Got It', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), ), ), SizedBox(height: 16), ], ), ), ); } @override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); } void _handleSignIn() async { if (_formKey.currentState!.validate()) { setState(() { _isLoading = true; }); final result = await AuthService.login( _emailController.text.trim(), _passwordController.text, ); setState(() { _isLoading = false; }); if (result['success'] == true) { final userResult = await UserService.getCurrentUser(forceRefresh: true); if (userResult['success'] == true) { final userData = userResult['data']; // Check if user needs onboarding (activated = 0) if (userData['activated'] == 0) { Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => EditProfileScreen(userData: userData, isOnboarding: true), ), ); } else { // Start polling services now that user is logged in AppLifecycleService.startAllPolling(); Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => NotificationPermissionScreen(), ), ); } } else { _showErrorAlert('Failed to load user data'); } } else { _showErrorAlert(result['message'] ?? 'Login failed'); } } } void _showErrorAlert(String message) { showDialog( context: context, builder: (context) => AlertDialog( title: Text('Login Failed'), content: Text(message), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text('OK', style: TextStyle(color: Color(0xFF6A4C93))), ), ], ), ); } @override Widget build(BuildContext context) { return PopScope( canPop: false, // Prevent back navigation from sign in page child: Scaffold( resizeToAvoidBottomInset: false, body: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFF32B0A5), Color(0xFF4600B9)], stops: [0.0, 0.5], ), ), child: SafeArea( child: Column( children: [ // App bar Padding( padding: EdgeInsets.all(16), child: Row( children: [ IconButton( onPressed: () => Navigator.of(context).pop(), icon: Icon(Icons.arrow_back, color: Colors.white), ), Text( 'Sign In', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, color: Colors.white, ), ), ], ), ), // Content Expanded( child: SingleChildScrollView( child: Container( margin: EdgeInsets.all(16), padding: EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 20, offset: Offset(0, 5), ), ], ), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SizedBox(height: 20), // Logo Center( child: Text( 'وصال', style: TextStyle( fontSize: 48, fontWeight: FontWeight.w200, fontFamily: 'Blaka', color: Color(0xFF6A4C93), ), ), ), SizedBox(height: 40), // Welcome text Text( 'Welcome Back!', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black87, ), textAlign: TextAlign.center, ), SizedBox(height: 8), Text( 'Sign in to socialize with your colleagues\nand transform your social life!', style: TextStyle( fontSize: 16, color: Colors.grey[600], ), textAlign: TextAlign.center, ), SizedBox(height: 40), // Email field TextFormField( controller: _emailController, keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email', prefixIcon: Icon(Icons.email_outlined), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: Color(0xFF6A4C93), ), ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your email'; } if (!value.contains('@')) { return 'Please enter a valid email'; } return null; }, ), SizedBox(height: 20), // Password field TextFormField( controller: _passwordController, obscureText: !_isPasswordVisible, decoration: InputDecoration( labelText: 'Password', prefixIcon: Icon(Icons.lock_outline), suffixIcon: IconButton( icon: Icon( _isPasswordVisible ? Icons.visibility_off : Icons.visibility, ), onPressed: () { setState(() { _isPasswordVisible = !_isPasswordVisible; }); }, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: Color(0xFF6A4C93), ), ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your password'; } if (value.length < 6) { return 'Password must be at least 6 characters'; } return null; }, ), SizedBox(height: 12), // Forgot password Align( alignment: Alignment.centerRight, child: TextButton( onPressed: _showHelpBottomSheet, child: Text( 'Forgot Password?', style: TextStyle( color: Color(0xFF6A4C93), fontWeight: FontWeight.w600, ), ), ), ), SizedBox(height: 30), // Sign in button Container( height: 56, child: ElevatedButton( onPressed: _isLoading ? null : _handleSignIn, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF6A4C93), foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 2, ), child: _isLoading ? CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( Colors.white, ), ) : Text( 'Sign In', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, ), ), ), ), SizedBox(height: 20), // Contact link for new accounts Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Don't have an account? ", style: TextStyle(color: Colors.grey[600]), ), GestureDetector( onTap: _showHelpBottomSheet, child: Text( 'Contact Support', style: TextStyle( color: Color(0xFF6A4C93), fontWeight: FontWeight.w600, ), ), ), ], ), SizedBox(height: 40), ], ), ), ), ), ), ], ), ), ), ), ); } }