import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import '../providers/auth_provider.dart'; import 'auth_screen.dart'; class ResetPasswordScreen extends ConsumerStatefulWidget { final String email; const ResetPasswordScreen({super.key, required this.email}); @override ConsumerState createState() => _ResetPasswordScreenState(); } class _ResetPasswordScreenState extends ConsumerState { final otpController = TextEditingController(); final newPasswordController = TextEditingController(); final confirmPasswordController = TextEditingController(); bool _isLoading = false; bool _obscurePassword = true; bool _obscureConfirm = true; String? _errorMessage; @override void dispose() { otpController.dispose(); newPasswordController.dispose(); confirmPasswordController.dispose(); super.dispose(); } Future _resetPassword() async { final otp = otpController.text.trim(); final newPassword = newPasswordController.text; final confirmPassword = confirmPasswordController.text; if (otp.isEmpty || otp.length != 6) { setState(() => _errorMessage = 'Please enter a valid 6-digit OTP'); return; } if (newPassword.isEmpty || newPassword.length < 6) { setState(() => _errorMessage = 'Password must be at least 6 characters'); return; } if (newPassword != confirmPassword) { setState(() => _errorMessage = 'Passwords do not match'); return; } setState(() { _isLoading = true; _errorMessage = null; }); final success = await ref .read(authControllerProvider.notifier) .resetPassword(widget.email, otp, newPassword); if (mounted) { setState(() => _isLoading = false); if (success) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Password reset successfully! Please log in.'), backgroundColor: Color(0xFF6C63FF), ), ); Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (_) => const AuthScreen()), (route) => false, ); } else { setState( () => _errorMessage = 'Invalid OTP or reset failed. Please try again.', ); } } } InputDecoration _buildInputDecoration( String hint, { IconData? prefixIcon, Widget? suffixIcon, }) { return InputDecoration( hintText: hint, prefixIcon: prefixIcon != null ? Icon(prefixIcon, color: Colors.grey.shade500) : null, suffixIcon: suffixIcon, filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade300), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade300), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Theme.of(context).primaryColor, width: 2), ), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18), ); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () => FocusScope.of(context).unfocus(), child: Scaffold( backgroundColor: Colors.grey.shade50, appBar: AppBar( elevation: 0, backgroundColor: Colors.transparent, leading: Padding( padding: const EdgeInsets.only(left: 16.0), child: IconButton( onPressed: () => Navigator.pop(context), icon: const Icon(LucideIcons.chevronLeft, size: 28), color: Colors.black87, ), ), ), body: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 400), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( width: 80, height: 80, decoration: BoxDecoration( color: Theme.of(context).primaryColor.withOpacity(0.1), shape: BoxShape.circle, ), child: Center( child: Icon( LucideIcons.shieldCheck, size: 40, color: Theme.of(context).primaryColor, ), ), ), const SizedBox(height: 32), Text( 'Reset Password', style: Theme.of(context).textTheme.headlineMedium ?.copyWith( fontWeight: FontWeight.bold, color: Colors.black87, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( 'We\'ve sent a 6-digit code to\n${widget.email}', textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.grey.shade600, height: 1.5, ), ), const SizedBox(height: 40), // OTP Field TextField( controller: otpController, keyboardType: TextInputType.number, textInputAction: TextInputAction.next, maxLength: 6, style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 24, letterSpacing: 16, ), textAlign: TextAlign.center, decoration: InputDecoration( hintText: '000000', hintStyle: TextStyle( color: Colors.grey.shade300, letterSpacing: 16, ), counterText: '', filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 20, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade300), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade300), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: Theme.of(context).primaryColor, width: 2, ), ), ), ), const SizedBox(height: 24), // New Password TextField( controller: newPasswordController, obscureText: _obscurePassword, textInputAction: TextInputAction.next, style: const TextStyle(fontWeight: FontWeight.w500), decoration: _buildInputDecoration( 'New Password', prefixIcon: LucideIcons.lock, suffixIcon: IconButton( icon: Icon( _obscurePassword ? LucideIcons.eyeOff : LucideIcons.eye, color: Colors.grey.shade500, ), onPressed: () => setState( () => _obscurePassword = !_obscurePassword, ), ), ), ), const SizedBox(height: 16), // Confirm Password TextField( controller: confirmPasswordController, obscureText: _obscureConfirm, textInputAction: TextInputAction.done, onSubmitted: (_) => _resetPassword(), style: const TextStyle(fontWeight: FontWeight.w500), decoration: _buildInputDecoration( 'Confirm Password', prefixIcon: LucideIcons.lock, suffixIcon: IconButton( icon: Icon( _obscureConfirm ? LucideIcons.eyeOff : LucideIcons.eye, color: Colors.grey.shade500, ), onPressed: () => setState( () => _obscureConfirm = !_obscureConfirm, ), ), ), ), AnimatedSize( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, alignment: Alignment.topCenter, child: _errorMessage != null ? Padding( padding: const EdgeInsets.only(top: 16), child: Container( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), decoration: BoxDecoration( color: Colors.red.shade50, borderRadius: BorderRadius.circular(12), border: Border.all( color: Colors.red.shade200, ), ), child: Row( children: [ Icon( LucideIcons.alertCircle, color: Colors.red.shade400, size: 20, ), const SizedBox(width: 12), Expanded( child: Text( _errorMessage!, style: TextStyle( color: Colors.red.shade700, fontSize: 14, fontWeight: FontWeight.w500, ), ), ), ], ), ), ) : const SizedBox.shrink(), ), const SizedBox(height: 40), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _isLoading ? null : _resetPassword, style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).primaryColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 20), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), elevation: 2, ), child: _isLoading ? const SizedBox( width: 24, height: 24, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text( 'Reset Password', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), ), ), ), ], ), ), ), ), ), ), ); } }