import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:real_estate_mobile/core/constants/app_colors.dart'; import 'package:real_estate_mobile/features/agents/data/models/agent_type.dart'; import 'package:real_estate_mobile/features/agents/presentation/providers/agents_provider.dart'; import 'package:real_estate_mobile/features/auth/presentation/providers/auth_provider.dart'; import 'package:real_estate_mobile/features/auth/presentation/widgets/auth_text_field.dart'; import 'package:real_estate_mobile/features/auth/presentation/widgets/or_divider.dart'; import 'package:real_estate_mobile/features/auth/presentation/widgets/role_toggle.dart'; import 'package:real_estate_mobile/features/auth/presentation/widgets/social_login_buttons.dart'; import 'package:go_router/go_router.dart'; class SignupScreen extends ConsumerStatefulWidget { const SignupScreen({super.key}); @override ConsumerState createState() => _SignupScreenState(); } class _SignupScreenState extends ConsumerState { final _nameController = TextEditingController(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); String _selectedRole = 'USER'; bool _obscurePassword = true; List _agentTypes = []; String? _selectedAgentTypeId; bool _loadingAgentTypes = false; @override void initState() { super.initState(); _fetchAgentTypes(); } @override void dispose() { _nameController.dispose(); _emailController.dispose(); _passwordController.dispose(); super.dispose(); } Future _fetchAgentTypes() async { setState(() => _loadingAgentTypes = true); try { final repo = ref.read(agentsRepositoryProvider); final types = await repo.getAgentTypes(); if (mounted) { setState(() { _agentTypes = types; _loadingAgentTypes = false; }); } } catch (_) { if (mounted) setState(() => _loadingAgentTypes = false); } } String? _validateLocally() { if (_nameController.text.trim().isEmpty) { return 'Please enter your name'; } if (_emailController.text.trim().isEmpty) { return 'Please enter your email'; } if (_passwordController.text.isEmpty) { return 'Please enter a password'; } if (_selectedRole == 'AGENT' && (_selectedAgentTypeId == null || _selectedAgentTypeId!.isEmpty)) { return 'Please select an agent type'; } return null; } void _handleSignup() { final localError = _validateLocally(); if (localError != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(localError), behavior: SnackBarBehavior.floating, ), ); return; } ref.read(authProvider.notifier).register( name: _nameController.text.trim(), email: _emailController.text.trim(), password: _passwordController.text, role: _selectedRole, agentTypeId: _selectedRole == 'AGENT' ? _selectedAgentTypeId : null, ); } @override Widget build(BuildContext context) { final authState = ref.watch(authProvider); return Scaffold( body: Container( width: double.infinity, height: double.infinity, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [AppColors.gradientStart, AppColors.gradientEnd], ), ), child: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24), child: authState.registrationSuccess ? _buildSuccessContent(authState) : _buildFormContent(authState), ), ), ), ); } Widget _buildSuccessContent(AuthState authState) { return Padding( padding: const EdgeInsets.only(top: 80), child: Container( padding: const EdgeInsets.all(32), decoration: BoxDecoration( color: AppColors.white, borderRadius: BorderRadius.circular(20), ), child: Column( children: [ const Icon( Icons.check_circle_outline, size: 64, color: AppColors.success, ), const SizedBox(height: 24), const Text( 'Check Your Email', style: TextStyle( fontFamily: 'Fractul', fontSize: 24, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), const SizedBox(height: 12), Text( 'We\'ve sent a verification link to ', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w300, color: AppColors.primaryDark.withValues(alpha: 0.7), ), ), Text( authState.registeredEmail, textAlign: TextAlign.center, style: const TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w600, color: AppColors.primaryDark, ), ), const SizedBox(height: 4), Text( 'Please check your inbox and click the link to verify your account before logging in.', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w300, color: AppColors.primaryDark.withValues(alpha: 0.7), ), ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { ref.read(authProvider.notifier).reset(); context.go('/login'); }, child: const Text('Go to Login'), ), ), const SizedBox(height: 16), Text( 'Didn\'t receive the email? Check your spam folder or contact support.', textAlign: TextAlign.center, style: TextStyle( fontFamily: 'Fractul', fontSize: 12, fontWeight: FontWeight.w300, color: AppColors.primaryDark.withValues(alpha: 0.5), ), ), ], ), ), ); } Widget _buildFormContent(AuthState authState) { final isLoading = authState.status == AuthStatus.loading; return Column( children: [ const SizedBox(height: 40), // Logo Image.asset( 'assets/icons/logo.png', width: 143, height: 41, ), const SizedBox(height: 24), // Title const Text( 'Sign Up', style: TextStyle( fontFamily: 'Fractul', fontSize: 30, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), const SizedBox(height: 24), // Role toggle RoleToggle( selectedRole: _selectedRole, onChanged: (role) => setState(() { _selectedRole = role; if (role != 'AGENT') _selectedAgentTypeId = null; }), ), const SizedBox(height: 20), // Error banner if (authState.errorMessage != null && authState.fieldErrors.isEmpty) ...[ Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: AppColors.errorBg, border: Border.all(color: AppColors.errorBorder), borderRadius: BorderRadius.circular(20), ), child: Text( authState.errorMessage!, style: const TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w300, color: AppColors.error, ), ), ), const SizedBox(height: 16), ], // Name field AuthTextField( hintText: 'Name', controller: _nameController, keyboardType: TextInputType.name, errorText: authState.getFieldError('firstName'), ), const SizedBox(height: 16), // Email field AuthTextField( hintText: 'Email', controller: _emailController, keyboardType: TextInputType.emailAddress, errorText: authState.getFieldError('email'), ), const SizedBox(height: 16), // Password field AuthTextField( hintText: 'Password', controller: _passwordController, obscureText: _obscurePassword, textInputAction: TextInputAction.done, errorText: authState.getFieldError('password'), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_off : Icons.visibility, color: AppColors.hintText, size: 22, ), onPressed: () => setState(() => _obscurePassword = !_obscurePassword), ), ), Padding( padding: const EdgeInsets.only(top: 8, left: 8), child: Align( alignment: Alignment.centerLeft, child: Text( 'Min 8 chars, 1 uppercase, 1 lowercase, 1 number, 1 special character', style: TextStyle( fontFamily: 'Fractul', fontSize: 12, fontWeight: FontWeight.w300, color: AppColors.primaryDark.withValues(alpha: 0.6), ), ), ), ), // Agent type selector (only when AGENT role is selected) if (_selectedRole == 'AGENT') ...[ const SizedBox(height: 16), Container( height: 50, decoration: BoxDecoration( color: AppColors.white, borderRadius: BorderRadius.circular(20), ), padding: const EdgeInsets.symmetric(horizontal: 16), child: _loadingAgentTypes ? const Center( child: SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: AppColors.accentOrange, ), ), ) : DropdownButtonHideUnderline( child: DropdownButton( value: _selectedAgentTypeId, hint: Text( 'Select Agent Type', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w300, color: AppColors.primaryDark.withValues(alpha: 0.5), ), ), isExpanded: true, icon: const Icon( Icons.keyboard_arrow_down, color: AppColors.primaryDark, size: 22, ), style: const TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), items: _agentTypes .map((type) => DropdownMenuItem( value: type.id, child: Text(type.name), )) .toList(), onChanged: (value) => setState(() => _selectedAgentTypeId = value), ), ), ), if (authState.getFieldError('agentTypeId') != null) Padding( padding: const EdgeInsets.only(top: 6, left: 12), child: Text( authState.getFieldError('agentTypeId')!, style: const TextStyle( fontFamily: 'Fractul', fontSize: 12, color: AppColors.error, ), ), ), ], const SizedBox(height: 24), // Sign Up button SizedBox( width: double.infinity, child: ElevatedButton( onPressed: isLoading ? null : _handleSignup, child: isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, color: AppColors.primaryDark, ), ) : const Text('Sign Up'), ), ), const SizedBox(height: 24), // Already have account Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'Already Have An Account ? ', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w300, color: AppColors.primaryDark, ), ), GestureDetector( onTap: () => context.go('/login'), child: const Text( 'Login', style: TextStyle( fontFamily: 'Fractul', fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.primaryDark, ), ), ), ], ), const SizedBox(height: 24), // Or divider const OrDivider(), const SizedBox(height: 24), // Social login buttons (signup mode with role and agent type) SocialLoginButtons( mode: 'signup', role: _selectedRole, agentTypeId: _selectedAgentTypeId, ), const SizedBox(height: 40), ], ); } }