import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; // --- افترض أن هذه المسارات موجودة في مشروعك --- import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/controller/auth/captin/phone_helper_controller.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../controller/local/phone_intel/intl_phone_field.dart'; import '../../../controller/local/phone_intel/phone_number.dart'; // import '../../../main.dart'; /// ---------------------------------------------------------------------------- /// 1. AUTH SCREEN WRAPPER /// (يحتوي على التصميم العام + اللوجيك الخفي للـ App Tester) /// ---------------------------------------------------------------------------- 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, }); // --- دالة إظهار نافذة دخول الفاحصين (Hidden Tester Dialog) --- void _showTesterLoginDialog(BuildContext context) { final controller = Get.put(LoginDriverController()); final emailController = TextEditingController(); final passwordController = TextEditingController(); final formKey = GlobalKey(); showGeneralDialog( context: context, barrierDismissible: true, barrierLabel: '', transitionDuration: const Duration(milliseconds: 300), pageBuilder: (ctx, anim1, anim2) => Container(), transitionBuilder: (ctx, anim1, anim2, child) { return ScaleTransition( scale: CurvedAnimation(parent: anim1, curve: Curves.easeOutBack), child: AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), backgroundColor: Colors.white, surfaceTintColor: Colors.white, title: Column( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppColor.primaryColor.withOpacity(0.1), shape: BoxShape.circle, ), child: const Icon(Icons.admin_panel_settings_rounded, color: AppColor.primaryColor, size: 30), ), const SizedBox(height: 10), const Text( 'Tester Access', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: AppColor.writeColor, ), ), ], ), content: Form( key: formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ TextFormField( controller: emailController, style: const TextStyle(color: AppColor.writeColor), decoration: InputDecoration( labelText: 'Tester Email', prefixIcon: const Icon(Icons.email_outlined, color: Colors.grey), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12)), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColor.primaryColor), ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), ), validator: (v) => v!.contains('@') ? null : 'Invalid Email', ), const SizedBox(height: 16), TextFormField( controller: passwordController, style: const TextStyle(color: AppColor.writeColor), obscureText: true, decoration: InputDecoration( labelText: 'Password', prefixIcon: const Icon(Icons.lock_outline, color: Colors.grey), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12)), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColor.primaryColor), ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), ), validator: (v) => v!.isEmpty ? 'Required' : null, ), ], ), ), actions: [ TextButton( onPressed: () => Get.back(), child: Text('Cancel', style: TextStyle(color: Colors.grey.shade600)), ), ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), elevation: 0, ), onPressed: () { if (formKey.currentState!.validate()) { controller.logintest( passwordController.text.trim(), emailController.text.trim(), ); Get.back(); } }, child: const Text('Login', style: TextStyle(color: Colors.white)), ), ], ), ); }, ); } @override Widget build(BuildContext context) { final Size size = MediaQuery.of(context).size; return Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: SizedBox( height: size.height, child: Stack( children: [ // 1. الخلفية العلوية (Blue Gradient Header) Container( height: size.height * 0.45, width: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: AppColor.gradientStartEnd, ), borderRadius: const BorderRadius.only( bottomRight: Radius.circular(60), bottomLeft: Radius.circular(0), ), ), child: Stack( children: [ // زخارف خلفية بسيطة Positioned( top: -40, left: -40, child: Container( width: 150, height: 150, decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), shape: BoxShape.circle, ), ), ), Positioned( bottom: 40, right: -20, child: Container( width: 100, height: 100, decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), shape: BoxShape.circle, ), ), ), // المحتوى (اللوجو والعناوين) SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // --- اللوجو مع الضغط المطول (Backdoor) --- GestureDetector( onLongPress: () { _showTesterLoginDialog(context); }, child: Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 10, spreadRadius: 2, ) ], ), child: ClipOval( child: Image.asset( 'assets/images/logo.gif', height: 80, width: 80, fit: BoxFit.cover, ), ), ), ), const SizedBox(height: 20), Text( title, textAlign: TextAlign.center, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white, letterSpacing: 1, ), ), const SizedBox(height: 8), Text( subtitle, textAlign: TextAlign.center, style: TextStyle( fontSize: 14, color: Colors.white.withOpacity(0.9), ), ), const SizedBox( height: 40), // مساحة لرفع المحتوى عن الكارت ], ), ), ), ], ), ), // 2. الفورم (White Floating Card) Positioned( top: size.height * 0.38, left: 20, right: 20, child: Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 30), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: AppColor.primaryColor.withOpacity(0.15), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: form, ), ), // 3. التذييل Positioned( bottom: 20, left: 0, right: 0, child: Center( child: Text( "Tripz Driver Egypt © 2026", style: TextStyle( color: Colors.grey.shade400, fontSize: 12, fontWeight: FontWeight.w500, ), ), ), ), ], ), ), ), ); } } /// ---------------------------------------------------------------------------- /// 2. PHONE NUMBER SCREEN /// (تحقق صارم جداً للأرقام المصرية + تنظيف الأصفار) /// ---------------------------------------------------------------------------- class PhoneNumberScreen extends StatefulWidget { const PhoneNumberScreen({super.key}); @override State createState() => _PhoneNumberScreenState(); } class _PhoneNumberScreenState extends State { final _formKey = GlobalKey(); // ignore: unused_field String _completePhoneNumber = ""; String _pureNumber = ""; // الرقم بدون كود الدولة bool _isLoading = false; void _submit() async { if (_formKey.currentState!.validate()) { setState(() => _isLoading = true); // --- منطق المعالجة (Strict Processing) --- // 1. تنظيف الرقم من أي صفر في البداية (Standardization) String cleanNumber = _pureNumber.startsWith('0') ? _pureNumber.substring(1) : _pureNumber; // 2. بناء الرقم الكامل ليكون +2010xxxxxxxxx String finalPhone = "+20$cleanNumber"; // 3. الإرسال final success = await PhoneAuthHelper.sendOtp(finalPhone); if (success && mounted) { setState(() => _isLoading = false); // ✅ [تصحيح]: الانتقال لصفحة الـ OTP بدلاً من استدعاء دالة verifyOtp Get.to(() => OtpVerificationScreen(phoneNumber: finalPhone)); } else { if (mounted) setState(() => _isLoading = false); } if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return AuthScreen( title: 'أهلاً بك كابتن'.tr, subtitle: 'سجل دخولك وابدأ رحلاتك في مصر'.tr, form: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'رقم الهاتف'.tr, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 15, color: AppColor.writeColor, ), ), const SizedBox(height: 10), Directionality( textDirection: TextDirection.ltr, child: IntlPhoneField( disableLengthCheck: true, // تفعيل التحقق اليدوي للصرامة showCountryFlag: true, flagsButtonPadding: const EdgeInsets.only(left: 10), dropdownIconPosition: IconPosition.trailing, dropdownIcon: const Icon(Icons.keyboard_arrow_down, color: AppColor.primaryColor), initialCountryCode: 'EG', // مصر افتراضياً languageCode: 'ar', // الدول بالعربية style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: AppColor.writeColor), decoration: InputDecoration( hintText: '010xxxxxxxxx', hintStyle: TextStyle(color: Colors.grey.shade300), filled: true, fillColor: Colors.grey.shade50, contentPadding: const EdgeInsets.symmetric(vertical: 16), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade200), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade200), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide( color: AppColor.primaryColor, width: 2), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Colors.redAccent), ), ), onChanged: (phone) { _completePhoneNumber = phone.completeNumber; _pureNumber = phone.number; }, // --- التحقق الصارم (Strict Validation) --- validator: (PhoneNumber? phone) { if (phone == null || phone.number.isEmpty) { return 'رقم الهاتف مطلوب'.tr; } // 1. التأكد أن الدولة مصر if (phone.countryISOCode != 'EG') { return 'التطبيق متاح حالياً في مصر فقط'.tr; } // 2. تنظيف الرقم من الرموز والمسافات String number = phone.number.replaceAll(RegExp(r'\D'), ''); // 3. حذف الصفر من البداية لتوحيد التحقق String cleanNumber = number.startsWith('0') ? number.substring(1) : number; // 4. التحقق من الطول (يجب أن يكون 10 أرقام صافية) if (cleanNumber.length != 10) { return 'الرقم يجب أن يكون 11 خانة (01xxxxxxxxx)'.tr; } // 5. التحقق من مفاتيح الشبكات (010, 011, 012, 015) List validPrefixes = ['10', '11', '12', '15']; bool isValidPrefix = validPrefixes .any((prefix) => cleanNumber.startsWith(prefix)); if (!isValidPrefix) { return 'يجب أن يبدأ الرقم بـ 010, 011, 012, أو 015'.tr; } return null; }, ), ), const SizedBox(height: 30), _isLoading ? const Center( child: CircularProgressIndicator(color: AppColor.primaryColor)) : SizedBox( width: double.infinity, height: 55, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, foregroundColor: Colors.white, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text( 'إرسال رمز التحقق'.tr, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold), ), ), ), ], ), ), ); } } /// ---------------------------------------------------------------------------- /// 3. OTP VERIFICATION SCREEN /// ---------------------------------------------------------------------------- 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); // ✅ [تصحيح]: تمرير الكود المدخل للدالة await PhoneAuthHelper.verifyOtp(widget.phoneNumber, _otpController.text); if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { return AuthScreen( title: 'تأكيد الرقم'.tr, subtitle: '${'تم إرسال الرمز إلى'.tr} ${widget.phoneNumber}', form: Column( children: [ Text( 'أدخل الرمز المكون من 5 أرقام'.tr, style: const TextStyle( fontSize: 14, color: Colors.grey, fontWeight: FontWeight.w600), ), const SizedBox(height: 20), Form( key: _formKey, child: Directionality( textDirection: TextDirection.ltr, child: TextFormField( controller: _otpController, keyboardType: TextInputType.number, maxLength: 5, textAlign: TextAlign.center, style: const TextStyle( fontSize: 32, fontWeight: FontWeight.bold, letterSpacing: 10, color: AppColor.primaryColor, ), decoration: InputDecoration( counterText: '', hintText: '•••••', hintStyle: TextStyle( color: Colors.grey.shade300, letterSpacing: 10, ), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.grey.shade300, width: 2), ), focusedBorder: const UnderlineInputBorder( borderSide: BorderSide(color: AppColor.primaryColor, width: 3), ), ), validator: (v) => (v == null || v.length < 5) ? '' : null, onChanged: (value) { if (value.length == 5) _submit(); }, ), ), ), const SizedBox(height: 40), _isLoading ? const Center( child: CircularProgressIndicator(color: AppColor.primaryColor)) : SizedBox( width: double.infinity, height: 55, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'تحقق الآن'.tr, style: const TextStyle( fontSize: 16, color: Colors.white, fontWeight: FontWeight.bold), ), ), ), ], ), ); } } /// ---------------------------------------------------------------------------- /// 4. REGISTRATION SCREEN /// ---------------------------------------------------------------------------- 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); // await PhoneAuthHelper.registerUser( // phoneNumber: widget.phoneNumber, // firstName: _firstNameController.text.trim(), // lastName: _lastNameController.text.trim(), // email: _emailController.text.trim(), // ); if (mounted) setState(() => _isLoading = false); } } Widget _buildField( TextEditingController controller, String label, IconData icon, {bool required = true}) { return TextFormField( controller: controller, style: const TextStyle(color: AppColor.writeColor), decoration: InputDecoration( labelText: label, labelStyle: TextStyle(color: Colors.grey.shade600), prefixIcon: Icon(icon, color: AppColor.primaryColor), border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade200), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: AppColor.primaryColor, width: 2), ), filled: true, fillColor: Colors.grey.shade50, ), validator: required ? (v) => v!.isEmpty ? '$label مطلوب'.tr : null : null, ); } @override Widget build(BuildContext context) { return AuthScreen( title: 'بيانات الحساب'.tr, subtitle: 'أكمل بياناتك لإنشاء حساب السائق'.tr, form: Form( key: _formKey, child: Column( children: [ _buildField( _firstNameController, 'الاسم الأول'.tr, Icons.person_outline), const SizedBox(height: 16), _buildField( _lastNameController, 'اسم العائلة'.tr, Icons.person_outline), const SizedBox(height: 16), _buildField(_emailController, 'البريد الإلكتروني (اختياري)'.tr, Icons.email_outlined, required: false), const SizedBox(height: 30), _isLoading ? const Center( child: CircularProgressIndicator(color: AppColor.primaryColor)) : SizedBox( width: double.infinity, height: 55, child: ElevatedButton( onPressed: _submit, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primaryColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: Text( 'إتمام التسجيل'.tr, style: const TextStyle( fontSize: 16, color: Colors.white, fontWeight: FontWeight.bold), ), ), ), ], ), ), ); } }