import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; // --- placeholder imports --- // These are assumed to exist from your original code. // Make sure to have these files and controllers properly set up in your project. import 'package:Intaleq/controller/auth/login_controller.dart'; import '../../controller/auth/otp_controller.dart'; // Assumed to be PhoneAuthHelper import '../../controller/local/phone_intel/intl_phone_field.dart'; // --- end of placeholder imports --- /// A visually revamped authentication screen with a glassmorphism effect. /// It provides a consistent and beautiful UI for all authentication steps. /// /// A hidden feature for testers is included: a long-press on the logo /// will open a dialog for email/password login, suitable for app reviews. class AuthScreen extends StatelessWidget { final String title; final String subtitle; final Widget form; const AuthScreen({ super.key, required this.title, required this.subtitle, required this.form, }); /// Shows a dialog for testers to log in using email and password. /// This is triggered by a long-press on the logo or the explicit tester button. void _showTesterLoginDialog( BuildContext context, LoginController controller) { final testerEmailController = TextEditingController(); final testerPasswordController = TextEditingController(); final testerFormKey = GlobalKey(); showDialog( context: context, barrierDismissible: true, builder: (BuildContext dialogContext) { return BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: AlertDialog( backgroundColor: const Color(0xFF162232).withOpacity(0.85), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), title: const Text( 'App Tester Login', textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white), ), content: Form( key: testerFormKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ TextFormField( controller: testerEmailController, keyboardType: TextInputType.emailAddress, style: const TextStyle(color: Colors.white), decoration: InputDecoration( labelText: 'Email', labelStyle: TextStyle(color: Colors.white.withOpacity(0.7)), prefixIcon: Icon(Icons.email_outlined, color: Colors.white.withOpacity(0.7)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.3)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF00BFFF)), ), ), validator: (value) => value == null || !value.contains('@') ? 'Enter a valid email' : null, ), const SizedBox(height: 16), TextFormField( controller: testerPasswordController, obscureText: true, style: const TextStyle(color: Colors.white), decoration: InputDecoration( labelText: 'Password', labelStyle: TextStyle(color: Colors.white.withOpacity(0.7)), prefixIcon: Icon(Icons.lock_outline, color: Colors.white.withOpacity(0.7)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.3)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF00BFFF)), ), ), validator: (value) => value == null || value.isEmpty ? 'Enter a password' : null, ), ], ), ), actions: [ TextButton( child: const Text('Cancel', style: TextStyle(color: Colors.white70)), onPressed: () => Navigator.of(dialogContext).pop(), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF00BFFF), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: const Text('Login', style: TextStyle(color: Colors.black)), onPressed: () { if (testerFormKey.currentState!.validate()) { // Use the main controller to perform login controller.emailController.text = testerEmailController.text; controller.passwordController.text = testerPasswordController.text; controller.login(); Navigator.of(dialogContext).pop(); } }, ), ], ), ); }, ); } @override Widget build(BuildContext context) { // We still need the controller for the hidden tester login final loginController = Get.find(); return Scaffold( body: Container( // NEW: AI-inspired, brighter, and more dynamic color gradient decoration: const BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF00122E), Color(0xFF00285F)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: Stack( children: [ // Background shapes for a more dynamic feel Positioned( top: -100, left: -100, child: Container( width: 250, height: 250, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFF00BFFF).withOpacity(0.15), ), ), ), Positioned( bottom: -150, right: -100, child: Container( width: 350, height: 350, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFF00BFFF).withOpacity(0.1), ), ), ), Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // GestureDetector to handle long-press for tester login GestureDetector( onLongPress: () { _showTesterLoginDialog(context, loginController); }, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.1), border: Border.all( color: Colors.white.withOpacity(0.2), width: 2)), child: ClipRRect( borderRadius: BorderRadius.circular(50), child: Image.asset('assets/images/logo.gif', height: 100)), ), ), const SizedBox(height: 20), Text( title, textAlign: TextAlign.center, style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.white, shadows: [ Shadow( blurRadius: 10.0, color: Colors.black26, offset: Offset(2, 2)), ]), ), const SizedBox(height: 10), Text( subtitle, textAlign: TextAlign.center, style: TextStyle( fontSize: 16, color: Colors.white.withOpacity(0.8), ), ), const SizedBox(height: 30), // Glassmorphism Container for the form ClipRRect( borderRadius: BorderRadius.circular(25.0), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), child: Container( padding: const EdgeInsets.all(24.0), decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(25.0), border: Border.all( color: Colors.white.withOpacity(0.2), width: 1.5, ), ), child: form, // The form from the specific screen is placed here ), ), ), const SizedBox(height: 20), // A more distinct button for app testers Material( color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(12), child: InkWell( onTap: () => _showTesterLoginDialog(context, loginController), borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.symmetric( vertical: 10, horizontal: 16), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.admin_panel_settings_outlined, color: Colors.white.withOpacity(0.8)), const SizedBox(width: 8), Text( 'For App Reviewers / Testers', style: TextStyle( color: Colors.white.withOpacity(0.8), fontWeight: FontWeight.w600, ), ), ], ), ), ), ), ], ), ), ), ], ), ), ); } } // --- UI Screens --- // Note: These screens now use the new AuthScreen wrapper and have updated styling // for their form elements to match the new design. class PhoneNumberScreen extends StatefulWidget { const PhoneNumberScreen({super.key}); @override State createState() => _PhoneNumberScreenState(); } class _PhoneNumberScreenState extends State { final _phoneController = TextEditingController(); final _formKey = GlobalKey(); bool _isLoading = false; static String formatSyrianPhone(String phone) { // Remove spaces, symbols, +, -, () phone = phone.replaceAll(RegExp(r'[ \-\(\)\+]'), '').trim(); // Normalize 00963 → 963 if (phone.startsWith('00963')) { phone = phone.replaceFirst('00963', '963'); } // Normalize 0963 → 963 if (phone.startsWith('0963')) { phone = phone.replaceFirst('0963', '963'); } // NEW: Fix 96309xxxx → 9639xxxx if (phone.startsWith('96309')) { phone = '9639' + phone.substring(5); // remove the "0" after 963 } // If starts with 9630 → correct to 9639 if (phone.startsWith('9630')) { phone = '9639' + phone.substring(4); } // If already in correct format: 9639xxxxxxxx if (phone.startsWith('9639') && phone.length == 12) { return phone; } // If starts with 963 but missing the 9 if (phone.startsWith('963') && phone.length > 3) { // Ensure it begins with 9639 if (!phone.startsWith('9639')) { phone = '9639' + phone.substring(3); } return phone; } // If starts with 09xxxxxxxx → 9639xxxxxxxx if (phone.startsWith('09')) { return '963' + phone.substring(1); } // If 9xxxxxxxx (9 digits) if (phone.startsWith('9') && phone.length == 9) { return '963' + phone; } // If starts with incorrect 0xxxxxxx → assume Syrian and fix if (phone.startsWith('0') && phone.length == 10) { return '963' + phone.substring(1); } return phone; } void _submit() async { if (_formKey.currentState!.validate()) { setState(() => _isLoading = true); // PRODUCTION READY: Using the actual PhoneAuthHelper final rawPhone = _phoneController.text.trim().replaceFirst('+', ''); final success = await PhoneAuthHelper.sendOtp(rawPhone); if (success && mounted) { // Get.to(() => OtpVerificationScreen(phoneNumber: rawPhone)); await PhoneAuthHelper.verifyOtp( rawPhone, ); // For testing purposes, auto-verify with a dummy OTP } if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return AuthScreen( title: 'welcome to intaleq'.tr, subtitle: 'login or register subtitle'.tr, form: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( 'Enter your phone number'.tr, style: TextStyle(color: Colors.white.withOpacity(0.9), fontSize: 16), textAlign: TextAlign.center, ), const SizedBox(height: 20), IntlPhoneField( showCountryFlag: false, searchText: 'Search country'.tr, languageCode: 'ar', style: const TextStyle(color: Colors.white), dropdownTextStyle: const TextStyle(color: Colors.black87), decoration: InputDecoration( labelText: 'Phone Number'.tr, hintText: 'witout zero'.tr, labelStyle: TextStyle(color: Colors.white.withOpacity(0.7)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.3)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF00BFFF)), ), ), initialCountryCode: 'SY', onChanged: (phone) { _phoneController.text = phone.completeNumber; }, validator: (phone) { if (phone == null || phone.number.isEmpty) { return 'Please enter your phone number'.tr; } if (phone.number.startsWith('0')) { return 'Please enter the number without the leading 0'.tr; } if (phone.completeNumber.length < 10) { // Example validation return 'Phone number seems too short'.tr; } return null; }, ), const SizedBox(height: 24), _isLoading ? const CircularProgressIndicator(color: Colors.white) : SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF00BFFF), padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'send otp button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black), ), ), ), ], ), ), ); } } class OtpVerificationScreen extends StatefulWidget { final String phoneNumber; const OtpVerificationScreen({super.key, required this.phoneNumber}); @override State createState() => _OtpVerificationScreenState(); } class _OtpVerificationScreenState extends State { final _formKey = GlobalKey(); final _otpController = TextEditingController(); bool _isLoading = false; void _submit() async { if (_formKey.currentState!.validate()) { setState(() => _isLoading = true); // PRODUCTION READY: Using the actual PhoneAuthHelper // await PhoneAuthHelper.verifyOtp(widget.phoneNumber, _otpController.text); if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return AuthScreen( title: 'verify your number title'.tr, subtitle: 'otp sent subtitle'.trParams({'phoneNumber': widget.phoneNumber}), form: Column( mainAxisSize: MainAxisSize.min, children: [ Text( 'Enter the 5-digit code'.tr, style: TextStyle(color: Colors.white.withOpacity(0.9), fontSize: 16), textAlign: TextAlign.center, ), const SizedBox(height: 20), Form( key: _formKey, child: TextFormField( controller: _otpController, textAlign: TextAlign.center, keyboardType: TextInputType.number, maxLength: 5, style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.white, letterSpacing: 18, // Visually separates the digits ), decoration: InputDecoration( counterText: "", hintText: '-----', hintStyle: TextStyle( color: Colors.white.withOpacity(0.3), letterSpacing: 18, fontSize: 28), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric(vertical: 10), ), validator: (v) => v == null || v.length < 5 ? '' : null, ), ), const SizedBox(height: 30), _isLoading ? const CircularProgressIndicator(color: Colors.white) : SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF00BFFF), padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'verify and continue button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black), ), ), ), ], ), ); } } class RegistrationScreen extends StatefulWidget { final String phoneNumber; const RegistrationScreen({super.key, required this.phoneNumber}); @override State createState() => _RegistrationScreenState(); } class _RegistrationScreenState extends State { final _formKey = GlobalKey(); final _firstNameController = TextEditingController(); final _lastNameController = TextEditingController(); final _emailController = TextEditingController(); bool _isLoading = false; void _submit() async { if (_formKey.currentState!.validate()) { setState(() => _isLoading = true); // PRODUCTION READY: Using the actual PhoneAuthHelper await PhoneAuthHelper.registerUser( phoneNumber: widget.phoneNumber, firstName: _firstNameController.text.trim(), lastName: _lastNameController.text.trim(), email: _emailController.text.trim(), ); if (mounted) setState(() => _isLoading = false); } } // Helper to create styled text form fields Widget _buildTextFormField({ required TextEditingController controller, required String label, TextInputType keyboardType = TextInputType.text, String? Function(String?)? validator, }) { return TextFormField( controller: controller, style: const TextStyle(color: Colors.white), decoration: InputDecoration( labelText: label, labelStyle: TextStyle(color: Colors.white.withOpacity(0.7)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.3)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF00BFFF)), ), ), keyboardType: keyboardType, validator: validator, ); } @override Widget build(BuildContext context) { return AuthScreen( title: 'one last step title'.tr, subtitle: 'complete profile subtitle'.tr, form: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildTextFormField( controller: _firstNameController, label: 'first name label'.tr, validator: (v) => v!.isEmpty ? 'first name required'.tr : null, ), const SizedBox(height: 16), _buildTextFormField( controller: _lastNameController, label: 'last name label'.tr, validator: (v) => v!.isEmpty ? 'last name required'.tr : null, ), const SizedBox(height: 16), _buildTextFormField( controller: _emailController, label: 'email optional label'.tr, keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 24), _isLoading ? const CircularProgressIndicator(color: Colors.white) : SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF00BFFF), padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'complete registration button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black), ), ), ), ], ), ), ); } }