import 'package:flutter/material.dart'; import 'package:inou_app/design/inou_theme.dart'; import 'package:inou_app/design/inou_text.dart'; import 'package:inou_app/design/widgets/widgets.dart'; /// Signup page with step-by-step flow class SignupPage extends StatefulWidget { const SignupPage({super.key}); @override State createState() => _SignupPageState(); } class _SignupPageState extends State { final _formKey = GlobalKey(); final _nameController = TextEditingController(); final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _confirmPasswordController = TextEditingController(); bool _isLoading = false; bool _obscurePassword = true; bool _obscureConfirm = true; bool _acceptedTerms = false; // Additional profile info DateTime? _dateOfBirth; String? _sex; @override void dispose() { _nameController.dispose(); _emailController.dispose(); _passwordController.dispose(); _confirmPasswordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return InouAuthFlowPage( child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Create your account', style: InouText.sectionTitle.copyWith(fontWeight: FontWeight.w600), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( 'Start understanding your health better', style: InouText.body.copyWith( color: InouTheme.textMuted, ), textAlign: TextAlign.center, ), const SizedBox(height: 32), // Name field InouTextField( label: 'Full name', controller: _nameController, placeholder: 'Your name', autofillHints: const [AutofillHints.name], validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your name'; } return null; }, ), const SizedBox(height: 16), // Email field InouTextField( label: 'Email', controller: _emailController, placeholder: 'you@example.com', keyboardType: TextInputType.emailAddress, autofillHints: const [AutofillHints.email], validator: (value) { if (value == null || value.isEmpty) { return 'Please enter your email'; } if (!value.contains('@')) { return 'Please enter a valid email'; } return null; }, ), const SizedBox(height: 16), // Date of birth _buildDateOfBirthField(), const SizedBox(height: 16), // Sex selection InouRadioGroup( label: 'Biological sex', hint: 'Used for accurate medical context', value: _sex, options: const [ InouRadioOption(value: 'male', label: 'Male'), InouRadioOption(value: 'female', label: 'Female'), ], onChanged: (value) { setState(() => _sex = value); }, ), const SizedBox(height: 16), // Password field InouTextField( label: 'Password', controller: _passwordController, placeholder: 'At least 8 characters', obscureText: _obscurePassword, autofillHints: const [AutofillHints.newPassword], suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_off : Icons.visibility, color: InouTheme.textMuted, size: 20, ), onPressed: () { setState(() => _obscurePassword = !_obscurePassword); }, ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter a password'; } if (value.length < 8) { return 'Password must be at least 8 characters'; } return null; }, ), const SizedBox(height: 16), // Confirm password field InouTextField( label: 'Confirm password', controller: _confirmPasswordController, placeholder: 'Re-enter your password', obscureText: _obscureConfirm, autofillHints: const [AutofillHints.newPassword], suffixIcon: IconButton( icon: Icon( _obscureConfirm ? Icons.visibility_off : Icons.visibility, color: InouTheme.textMuted, size: 20, ), onPressed: () { setState(() => _obscureConfirm = !_obscureConfirm); }, ), validator: (value) { if (value == null || value.isEmpty) { return 'Please confirm your password'; } if (value != _passwordController.text) { return 'Passwords do not match'; } return null; }, ), const SizedBox(height: 20), // Terms acceptance InouCheckbox( value: _acceptedTerms, onChanged: (value) { setState(() => _acceptedTerms = value ?? false); }, child: RichText( text: TextSpan( style: InouText.bodySmall.copyWith(color: InouTheme.text), children: [ const TextSpan(text: 'I agree to the '), TextSpan( text: 'Terms of Service', style: TextStyle(color: InouTheme.accent), // TODO: Make tappable ), const TextSpan(text: ' and '), TextSpan( text: 'Privacy Policy', style: TextStyle(color: InouTheme.accent), ), ], ), ), ), const SizedBox(height: 24), // Sign up button InouButton( text: _isLoading ? 'Creating account...' : 'Create account', onPressed: (_isLoading || !_acceptedTerms) ? null : _handleSignup, ), const SizedBox(height: 24), // Login link Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Already have an account? ', style: InouText.body.copyWith( color: InouTheme.textMuted, ), ), TextButton( onPressed: () => Navigator.pushReplacementNamed(context, '/login'), style: TextButton.styleFrom( padding: EdgeInsets.zero, minimumSize: Size.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), child: Text( 'Sign in', style: InouText.body.copyWith( color: InouTheme.accent, fontWeight: FontWeight.w600, ), ), ), ], ), ], ), ), ); } Widget _buildDateOfBirthField() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Date of birth', style: InouText.label, ), const SizedBox(height: 4), Text( 'Used for accurate medical context', style: InouText.bodySmall.copyWith(color: InouTheme.textMuted), ), const SizedBox(height: 8), InkWell( onTap: _selectDateOfBirth, borderRadius: InouTheme.borderRadiusMd, child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), decoration: BoxDecoration( color: InouTheme.bgCard, borderRadius: InouTheme.borderRadiusMd, border: Border.all(color: InouTheme.border), ), child: Row( children: [ Expanded( child: Text( _dateOfBirth != null ? '${_dateOfBirth!.month}/${_dateOfBirth!.day}/${_dateOfBirth!.year}' : 'Select date', style: InouText.body.copyWith( color: _dateOfBirth != null ? InouTheme.text : InouTheme.textMuted, ), ), ), Icon( Icons.calendar_today, size: 20, color: InouTheme.textMuted, ), ], ), ), ), ], ); } Future _selectDateOfBirth() async { final now = DateTime.now(); final picked = await showDatePicker( context: context, initialDate: _dateOfBirth ?? DateTime(now.year - 30), firstDate: DateTime(1900), lastDate: now, builder: (context, child) { return Theme( data: Theme.of(context).copyWith( colorScheme: ColorScheme.light( primary: InouTheme.accent, onPrimary: Colors.white, surface: InouTheme.bgCard, onSurface: InouTheme.text, ), ), child: child!, ); }, ); if (picked != null) { setState(() => _dateOfBirth = picked); } } Future _handleSignup() async { if (!_formKey.currentState!.validate()) return; if (_dateOfBirth == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('Please select your date of birth'), backgroundColor: InouTheme.danger, behavior: SnackBarBehavior.floating, ), ); return; } if (_sex == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('Please select your biological sex'), backgroundColor: InouTheme.danger, behavior: SnackBarBehavior.floating, ), ); return; } setState(() => _isLoading = true); try { // TODO: Implement actual signup await Future.delayed(const Duration(seconds: 1)); if (mounted) { // Navigate to email verification or dashboard Navigator.pushNamedAndRemoveUntil( context, '/dashboard', (route) => false, ); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Signup failed: ${e.toString()}'), backgroundColor: InouTheme.danger, behavior: SnackBarBehavior.floating, ), ); } } finally { if (mounted) { setState(() => _isLoading = false); } } } }