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(); // Brand Color for Logic (Cyan/Teal from the Arrow in the logo) const Color brandColor = Color(0xFF00E5FF); showDialog( context: context, barrierDismissible: true, builder: (BuildContext dialogContext) { return BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: AlertDialog( // Updated background to match new theme (Dark Purple/Indigo) backgroundColor: const Color(0xFF1A1A2E).withOpacity(0.90), 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), // Changed to Brand Cyan borderSide: const BorderSide(color: brandColor), ), ), 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), // Changed to Brand Cyan borderSide: const BorderSide(color: brandColor), ), ), 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: brandColor, // Updated Button Color shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: const Text('Login', style: TextStyle( color: Color(0xFF1A1A2E), fontWeight: FontWeight.bold)), 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 DESIGN: Deep Purple/Indigo Gradient to match the "N" body decoration: const BoxDecoration( gradient: LinearGradient( // Dark Indigo -> Deep Purple -> Dark Blue colors: [Color(0xFF2E1C59), Color(0xFF1A237E), Color(0xFF0D1117)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: Stack( children: [ // Background shapes updated to match the Logo accents // Shape 1: The Orange/Red Swoosh color Positioned( top: -80, left: -80, child: Container( width: 250, height: 250, decoration: BoxDecoration( shape: BoxShape.circle, // Orange/Red from the swoosh lines color: const Color(0xFFFF5722).withOpacity(0.12), boxShadow: [ BoxShadow( color: const Color(0xFFFF5722).withOpacity(0.2), blurRadius: 50, spreadRadius: 10, ) ]), ), ), // Shape 2: The Cyan/Teal Arrow color Positioned( bottom: -100, right: -80, child: Container( width: 350, height: 350, decoration: BoxDecoration( shape: BoxShape.circle, // Cyan/Teal from the arrow tip color: const Color(0xFF00E5FF).withOpacity(0.08), boxShadow: [ BoxShadow( color: const Color(0xFF00E5FF).withOpacity(0.15), blurRadius: 60, spreadRadius: 5, ) ]), ), ), 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.05), border: Border.all( // Gradient border for the logo container color: Colors.white.withOpacity(0.1), width: 1)), 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: 15.0, color: Color(0xFF000000), // Darker shadow offset: Offset(0, 4)), ]), ), const SizedBox(height: 10), Text( subtitle, textAlign: TextAlign.center, style: TextStyle( fontSize: 16, color: Colors.white.withOpacity(0.75), ), ), const SizedBox(height: 30), // Glassmorphism Container for the form ClipRRect( borderRadius: BorderRadius.circular(25.0), child: BackdropFilter( filter: ImageFilter.blur( sigmaX: 20, sigmaY: 20), // Increased blur child: Container( padding: const EdgeInsets.all(24.0), decoration: BoxDecoration( // Slightly darker tint for better contrast with Cyan inputs color: const Color(0xFF1A237E).withOpacity(0.2), borderRadius: BorderRadius.circular(25.0), border: Border.all( color: Colors.white.withOpacity(0.1), width: 1.0, ), ), 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.transparent, 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.5)), const SizedBox(width: 8), Text( 'For App Reviewers / Testers', style: TextStyle( color: Colors.white.withOpacity(0.5), fontWeight: FontWeight.w400, fontSize: 12), ), ], ), ), ), ), ], ), ), ), ], ), ), ); } } // --- 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; // Brand Color for Focus (Cyan/Teal) final Color _focusColor = const Color(0xFF00E5FF); 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 .white), // Changed to White for visibility on dark BG 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), // Updated to Logo Cyan borderSide: BorderSide(color: _focusColor, width: 2), ), ), 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( // Updated to Logo Cyan backgroundColor: _focusColor, padding: const EdgeInsets.symmetric(vertical: 16), elevation: 5, shadowColor: _focusColor.withOpacity(0.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'send otp button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, // Text is dark to contrast with bright Cyan color: Color(0xFF1A1A2E)), ), ), ), ], ), ), ); } } 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; // Brand Color final Color _brandColor = const Color(0xFF00E5FF); 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.1), letterSpacing: 18, fontSize: 28), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric(vertical: 10), // Add a subtle underline for the OTP area using brand color enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.white.withOpacity(0.2))), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: _brandColor)), ), 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: _brandColor, // Updated padding: const EdgeInsets.symmetric(vertical: 16), elevation: 5, shadowColor: _brandColor.withOpacity(0.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'verify and continue button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF1A1A2E)), ), ), ), ], ), ); } } 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; // Brand Color final Color _brandColor = const Color(0xFF00E5FF); 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), // Updated to Logo Cyan borderSide: BorderSide(color: _brandColor, width: 2), ), ), 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: _brandColor, // Updated padding: const EdgeInsets.symmetric(vertical: 16), elevation: 5, shadowColor: _brandColor.withOpacity(0.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'complete registration button'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF1A1A2E)), ), ), ), ], ), ), ); } }