import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../controllers/authentication/auth_controller.dart'; import '../authentication/verification_view.dart'; class Login_view extends StatelessWidget { Login_view({super.key}); final TextEditingController phoneController = TextEditingController(); // Fix: RxString mirrors the field so Obx rebuilds on every keystroke/clear final RxString phoneValue = ''.obs; final RxBool isAgreed = false.obs; @override Widget build(BuildContext context) { Size screenSize = MediaQuery.of(context).size; return Scaffold( backgroundColor: Colors.white, body: Stack( children: [ // Top curved purple background Positioned( top: 0, left: 0, right: 0, child: CustomPaint( size: Size(screenSize.width, screenSize.height * 0.52), painter: _TopCurvePainter(), ), ), // Decorative circles Positioned( top: screenSize.height * 0.04, right: -30, child: Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.06), ), ), ), Positioned( top: screenSize.height * 0.10, left: -20, child: Container( width: 80, height: 80, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.06), ), ), ), SafeArea( child: SingleChildScrollView( physics: const ClampingScrollPhysics(), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header area Padding( padding: EdgeInsets.symmetric( horizontal: screenSize.width * 0.06, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: screenSize.height * 0.03), // Logo / brand chip SizedBox(height: screenSize.height * 0.02), const Text( "Groceries & More,\nDelivered in Minutes!", style: TextStyle( color: Colors.white, fontWeight: FontWeight.w800, fontSize: 26, height: 1.25, letterSpacing: -0.5, ), ), SizedBox(height: screenSize.height * 0.008), const Text( "Sign in to enjoy lightning-fast delivery!", style: TextStyle( color: Colors.white70, fontSize: 14, height: 1.4, ), ), ], ), ), // Image — right-aligned, overlapping curve Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Image.asset( "assets/images/loginImage.png", height: screenSize.height * 0.30, fit: BoxFit.contain, ), ], ), // White card form area Container( margin: EdgeInsets.symmetric( horizontal: screenSize.width * 0.05), padding: EdgeInsets.symmetric( horizontal: screenSize.width * 0.05, vertical: screenSize.height * 0.03, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: const Color(0xFF662582).withOpacity(0.08), blurRadius: 30, offset: const Offset(0, 8), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "Login or Signup", style: TextStyle( color: Color(0xFF1A1A2E), fontWeight: FontWeight.w800, fontSize: 20, letterSpacing: -0.3, ), ), const SizedBox(height: 4), const Text( "Enter your mobile number to continue", style: TextStyle( color: Color(0xFF9CA3AF), fontSize: 13, ), ), SizedBox(height: screenSize.height * 0.025), // Phone input TextFormField( controller: phoneController, maxLength: 10, onChanged: (value) { phoneValue.value = value; // Fix: keep Rx in sync if (value.length == 10) { FocusScope.of(context).unfocus(); } }, decoration: InputDecoration( labelText: "Mobile Number", hintText: "Enter 10-digit number", counterText: "", labelStyle: const TextStyle( color: Color(0xFF662582), fontSize: 13), hintStyle: const TextStyle(color: Color(0xFFD1D5DB)), prefixIcon: Container( width: screenSize.width * 0.2, padding: const EdgeInsets.symmetric(horizontal: 12), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( "+91", style: TextStyle( color: Color(0xFF662582), fontWeight: FontWeight.w600, fontSize: 15, ), ), const SizedBox(width: 8), Container( width: 1, height: 20, color: const Color(0xFFE5E7EB), ), ], ), ), // filled: true, // fillColor: const Color(0xFFF9F5FF), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide( color: Color(0xFFE9D5FF), width: 1.2), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide( color: Color(0xFFE9D5FF), width: 1.2), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide( color: Color(0xFF662582), width: 1.8), ), ), style: const TextStyle( color: Color(0xFF1A1A2E), fontWeight: FontWeight.w500, fontSize: 16, letterSpacing: 1, ), cursorColor: const Color(0xFF662582), keyboardType: TextInputType.phone, ), SizedBox(height: screenSize.height * 0.02), // Agree checkbox row Obx(() => GestureDetector( onTap: () => isAgreed.value = !isAgreed.value, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ AnimatedContainer( duration: const Duration(milliseconds: 200), width: 20, height: 20, decoration: BoxDecoration( color: isAgreed.value ? const Color(0xFF662582) : Colors.white, borderRadius: BorderRadius.circular(5), border: Border.all( color: isAgreed.value ? const Color(0xFF662582) : const Color(0xFFD1D5DB), width: 1.5, ), ), child: isAgreed.value ? const Icon(Icons.check, size: 13, color: Colors.white) : null, ), const SizedBox(width: 10), Expanded( child: RichText( text: TextSpan( style: const TextStyle( color: Color(0xFF6B7280), fontSize: 12.5, ), children: [ const TextSpan( text: "I agree to the "), TextSpan( text: "Terms & Privacy Policy", style: const TextStyle( color: Color(0xFF662582), fontWeight: FontWeight.w600, ), recognizer: TapGestureRecognizer() ..onTap = () { Get.to(() => WebViewScreen( url: "https://nearle.in/privacy", title: "Terms & Privacy Policy", )); }, ), ], ), ), ), ], ), )), SizedBox(height: screenSize.height * 0.025), // Continue button SizedBox( width: double.infinity, height: 52, child: Obx(() { final authController = Get.find(); final phone = phoneValue.value.trim(); // Fix: reactive read bool isValidMobile(String phone) { return RegExp(r'^[6-9]\d{9}$').hasMatch(phone); } final bool isPhoneValid = isValidMobile(phone); final bool canProceed = isPhoneValid && isAgreed.value && !authController.isLoading.value; return ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF662582), foregroundColor: Colors.white, disabledBackgroundColor: const Color(0xFFD8B4FE), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), elevation: 0, ), onPressed: canProceed ? () => authController.signIn(context, phone) : null, child: authController.isLoading.value ? const SizedBox( width: 22, height: 22, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white), ), ) : const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Continue", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, letterSpacing: 0.3, ), ), SizedBox(width: 8), Icon(Icons.arrow_forward_rounded, size: 18), ], ), ); }), ), ], ), ), SizedBox(height: screenSize.height * 0.04), ], ), ), ), ], ), ); } } // ── Custom painter for top curved purple background ────────────────────────── class _TopCurvePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..shader = const LinearGradient( colors: [Color(0xFF8B2FC9), Color(0xFF662582)], begin: Alignment.topRight, end: Alignment.bottomLeft, ).createShader(Rect.fromLTWH(0, 0, size.width, size.height)); final path = Path(); path.lineTo(0, size.height * 0.85); path.quadraticBezierTo( size.width * 0.25, size.height * 1.0, size.width * 0.5, size.height * 0.92, ); path.quadraticBezierTo( size.width * 0.75, size.height * 0.84, size.width, size.height * 0.94, ); path.lineTo(size.width, 0); path.close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(_TopCurvePainter oldDelegate) => false; } // ── WebView screen (unchanged) ──────────────────────────────────────────────── class WebViewScreen extends StatefulWidget { final String url; final String title; const WebViewScreen({ super.key, required this.url, required this.title, }); @override State createState() => _WebViewScreenState(); } class _WebViewScreenState extends State { late final WebViewController controller; @override void initState() { super.initState(); controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..loadRequest(Uri.parse(widget.url)); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), backgroundColor: Colors.white, foregroundColor: Colors.black, ), body: WebViewWidget(controller: controller), ); } }