diff --git a/frontend/lib/screens/auth/parent_register_step1_screen.dart b/frontend/lib/screens/auth/parent_register_step1_screen.dart index 5081264..d77f239 100644 --- a/frontend/lib/screens/auth/parent_register_step1_screen.dart +++ b/frontend/lib/screens/auth/parent_register_step1_screen.dart @@ -1,250 +1,65 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'dart:math' as math; // Pour la rotation du chevron -import '../../models/user_registration_data.dart'; // Import du modèle de données -import '../../utils/data_generator.dart'; // Import du générateur de données -import '../../widgets/custom_app_text_field.dart'; // Import du widget CustomAppTextField -import '../../models/card_assets.dart'; // Import des enums de cartes +import 'package:provider/provider.dart'; import 'package:go_router/go_router.dart'; -import 'package:provider/provider.dart'; // Importer Provider -class ParentRegisterStep1Screen extends StatefulWidget { +import '../../models/user_registration_data.dart'; +import '../../utils/data_generator.dart'; +import '../../widgets/personal_info_form_screen.dart'; +import '../../models/card_assets.dart'; + +class ParentRegisterStep1Screen extends StatelessWidget { const ParentRegisterStep1Screen({super.key}); - @override - State createState() => _ParentRegisterStep1ScreenState(); -} - -class _ParentRegisterStep1ScreenState extends State { - final _formKey = GlobalKey(); - // late UserRegistrationData _registrationData; // Supprimé, on utilisera le Provider - - // Contrôleurs pour les champs - final _lastNameController = TextEditingController(); - final _firstNameController = TextEditingController(); - final _phoneController = TextEditingController(); - final _emailController = TextEditingController(); - final _passwordController = TextEditingController(); - final _confirmPasswordController = TextEditingController(); - final _addressController = TextEditingController(); - final _postalCodeController = TextEditingController(); - final _cityController = TextEditingController(); - - @override - void initState() { - super.initState(); - // Récupérer les données existantes du Provider pour pré-remplir si l'utilisateur revient - final registrationDataFromProvider = Provider.of(context, listen: false); - _firstNameController.text = registrationDataFromProvider.parent1.firstName; - _lastNameController.text = registrationDataFromProvider.parent1.lastName; - _phoneController.text = registrationDataFromProvider.parent1.phone; - _emailController.text = registrationDataFromProvider.parent1.email; - _passwordController.text = registrationDataFromProvider.parent1.password; - _confirmPasswordController.text = registrationDataFromProvider.parent1.password; // Ou laisser vide pour reconfirmation - _addressController.text = registrationDataFromProvider.parent1.address; - _postalCodeController.text = registrationDataFromProvider.parent1.postalCode; - _cityController.text = registrationDataFromProvider.parent1.city; - - // Si les champs sont vides (première visite), générer des données - if (registrationDataFromProvider.parent1.firstName.isEmpty) { - _generateAndFillData(); - } - } - - void _generateAndFillData() { - final String genFirstName = DataGenerator.firstName(); - final String genLastName = DataGenerator.lastName(); - - _addressController.text = DataGenerator.address(); - _postalCodeController.text = DataGenerator.postalCode(); - _cityController.text = DataGenerator.city(); - - _firstNameController.text = genFirstName; - _lastNameController.text = genLastName; - _phoneController.text = DataGenerator.phone(); - _emailController.text = DataGenerator.email(genFirstName, genLastName); - _passwordController.text = DataGenerator.password(); - _confirmPasswordController.text = _passwordController.text; - } - - @override - void dispose() { - _lastNameController.dispose(); - _firstNameController.dispose(); - _phoneController.dispose(); - _emailController.dispose(); - _passwordController.dispose(); - _confirmPasswordController.dispose(); - _addressController.dispose(); - _postalCodeController.dispose(); - _cityController.dispose(); - super.dispose(); - } - - void _submitForm() { - if (_formKey.currentState?.validate() ?? false) { - final registrationData = Provider.of(context, listen: false); - registrationData.updateParent1( - ParentData( - firstName: _firstNameController.text, - lastName: _lastNameController.text, - address: _addressController.text, - postalCode: _postalCodeController.text, - city: _cityController.text, - phone: _phoneController.text, - email: _emailController.text, - password: _passwordController.text, // Sauvegarder le mot de passe - ) - ); - context.go('/parent-register-step2'); - } - } - @override Widget build(BuildContext context) { - final screenSize = MediaQuery.of(context).size; + final registrationData = Provider.of(context, listen: false); + final parent1 = registrationData.parent1; + + // Générer des données de test si vide + PersonalInfoData initialData; + if (parent1.firstName.isEmpty) { + final genFirstName = DataGenerator.firstName(); + final genLastName = DataGenerator.lastName(); + initialData = PersonalInfoData( + firstName: genFirstName, + lastName: genLastName, + phone: DataGenerator.phone(), + email: DataGenerator.email(genFirstName, genLastName), + address: DataGenerator.address(), + postalCode: DataGenerator.postalCode(), + city: DataGenerator.city(), + ); + } else { + initialData = PersonalInfoData( + firstName: parent1.firstName, + lastName: parent1.lastName, + phone: parent1.phone, + email: parent1.email, + address: parent1.address, + postalCode: parent1.postalCode, + city: parent1.city, + ); + } - return Scaffold( - body: Stack( - children: [ - // Fond papier - Positioned.fill( - child: Image.asset( - 'assets/images/paper2.png', - fit: BoxFit.cover, - repeat: ImageRepeat.repeat, - ), - ), - - // Contenu centré - Center( - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Indicateur d'étape (à rendre dynamique) - Text( - 'Étape 1/5', - style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54), - ), - const SizedBox(height: 10), - // Texte d'instruction - Text( - 'Informations du Parent Principal', - style: GoogleFonts.merienda( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.black87, - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 30), - - // Carte jaune contenant le formulaire - Container( - width: screenSize.width * 0.6, - padding: const EdgeInsets.symmetric(vertical: 50, horizontal: 50), - constraints: const BoxConstraints(minHeight: 570), - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage(CardColorHorizontal.peach.path), - fit: BoxFit.fill, - ), - ), - child: Form( - key: _formKey, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Votre nom de famille', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - Expanded(flex: 1, child: const SizedBox()), // Espace de 4% - Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Votre prénom', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - ], - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded(flex: 12, child: CustomAppTextField(controller: _phoneController, labelText: 'Téléphone', keyboardType: TextInputType.phone, hintText: 'Votre numéro de téléphone', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - Expanded(flex: 1, child: const SizedBox()), // Espace de 4% - Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Votre adresse e-mail', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - ], - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded(flex: 12, child: CustomAppTextField(controller: _passwordController, labelText: 'Mot de passe', obscureText: true, hintText: 'Créez votre mot de passe', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: (value) { - if (value == null || value.isEmpty) return 'Mot de passe requis'; - if (value.length < 6) return '6 caractères minimum'; - return null; - })), - Expanded(flex: 1, child: const SizedBox()), // Espace de 4% - Expanded(flex: 12, child: CustomAppTextField(controller: _confirmPasswordController, labelText: 'Confirmation', obscureText: true, hintText: 'Confirmez le mot de passe', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: (value) { - if (value == null || value.isEmpty) return 'Confirmation requise'; - if (value != _passwordController.text) return 'Ne correspond pas'; - return null; - })), - ], - ), - const SizedBox(height: 20), - CustomAppTextField( - controller: _addressController, - labelText: 'Adresse (N° et Rue)', - hintText: 'Numéro et nom de votre rue', - style: CustomAppTextFieldStyle.beige, - fieldWidth: double.infinity, - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded(flex: 1, child: CustomAppTextField(controller: _postalCodeController, labelText: 'Code Postal', keyboardType: TextInputType.number, hintText: 'Code postal', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - const SizedBox(width: 20), - Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Votre ville', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - ], - ), - ], - ), - ), - ), - ], - ), - ), - ), - - // Chevron de navigation gauche (Retour) - Positioned( - top: screenSize.height / 2 - 20, // Centré verticalement - left: 40, - child: IconButton( - icon: Transform( - alignment: Alignment.center, - transform: Matrix4.rotationY(math.pi), // Inverse horizontalement - child: Image.asset('assets/images/chevron_right.png', height: 40), - ), - onPressed: () { - if (context.canPop()) { - context.pop(); - } else { - context.go('/register-choice'); - } - }, - tooltip: 'Retour', - ), - ), - - // Chevron de navigation droit (Suivant) - Positioned( - top: screenSize.height / 2 - 20, // Centré verticalement - right: 40, - child: IconButton( - icon: Image.asset('assets/images/chevron_right.png', height: 40), - onPressed: _submitForm, // Appel de la fonction de soumission - tooltip: 'Suivant', - ), - ), - ], - ), + return PersonalInfoFormScreen( + stepText: 'Étape 1/5', + title: 'Informations du Parent Principal', + cardColor: CardColorHorizontal.peach, + initialData: initialData, + previousRoute: '/register-choice', + onSubmit: (data, {hasSecondPerson, sameAddress}) { + registrationData.updateParent1( + firstName: data.firstName, + lastName: data.lastName, + phone: data.phone, + email: data.email, + address: data.address, + postalCode: data.postalCode, + city: data.city, + password: '', + ); + context.go('/parent-register-step2'); + }, ); } -} \ No newline at end of file +} diff --git a/frontend/lib/screens/auth/parent_register_step2_screen.dart b/frontend/lib/screens/auth/parent_register_step2_screen.dart index 3151c8c..f4a7673 100644 --- a/frontend/lib/screens/auth/parent_register_step2_screen.dart +++ b/frontend/lib/screens/auth/parent_register_step2_screen.dart @@ -1,290 +1,90 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'dart:math' as math; // Pour la rotation du chevron -import '../../models/user_registration_data.dart'; // Import du modèle -import '../../utils/data_generator.dart'; // Import du générateur -import '../../widgets/custom_app_text_field.dart'; // Import du widget -import '../../models/card_assets.dart'; // Import des enums de cartes import 'package:provider/provider.dart'; -import 'package:go_router/go_router.dart'; // Importer GoRouter +import 'package:go_router/go_router.dart'; -class ParentRegisterStep2Screen extends StatefulWidget { - // final UserRegistrationData registrationData; // Supprimé +import '../../models/user_registration_data.dart'; +import '../../utils/data_generator.dart'; +import '../../widgets/personal_info_form_screen.dart'; +import '../../models/card_assets.dart'; - const ParentRegisterStep2Screen({super.key /*, required this.registrationData */}); // Modifié - - @override - _ParentRegisterStep2ScreenState createState() => - _ParentRegisterStep2ScreenState(); -} - -class _ParentRegisterStep2ScreenState extends State { - final _formKey = GlobalKey(); - // late UserRegistrationData _registrationData; // Supprimé - - bool _addParent2 = true; // Pour le test, on ajoute toujours le parent 2 - bool _sameAddressAsParent1 = false; // Peut être généré aléatoirement aussi - - // Contrôleurs pour les champs du parent 2 (restauration CP et Ville) - final _lastNameController = TextEditingController(); - final _firstNameController = TextEditingController(); - final _phoneController = TextEditingController(); - final _emailController = TextEditingController(); - final _passwordController = TextEditingController(); - final _confirmPasswordController = TextEditingController(); - final _addressController = TextEditingController(); // Rue seule - final _postalCodeController = TextEditingController(); // Restauré - final _cityController = TextEditingController(); // Restauré - - @override - void initState() { - super.initState(); - // On ne récupère plus _registrationData ici - // Mais on peut récupérer les données initiales pour les contrôleurs si nécessaire - final initialData = Provider.of(context, listen: false); - _addParent2 = initialData.parent2 != null; - if (_addParent2) { - _fillParent2Data(initialData.parent2!, initialData.parent1); - } else { - _generateAndFillParent2Data(initialData.parent1); // Ou générer si pas de données - } - } - - // Modifié pour prendre les données parent1 - void _generateAndFillParent2Data(ParentData parent1Data) { - final String genFirstName = DataGenerator.firstName(); - final String genLastName = DataGenerator.lastName(); - _firstNameController.text = genFirstName; - _lastNameController.text = genLastName; - _phoneController.text = DataGenerator.phone(); - _emailController.text = DataGenerator.email(genFirstName, genLastName); - _passwordController.text = DataGenerator.password(); - _confirmPasswordController.text = _passwordController.text; - - _sameAddressAsParent1 = DataGenerator.boolean(); - if (!_sameAddressAsParent1) { - // Générer adresse, CP, Ville séparément - _addressController.text = DataGenerator.address(); - _postalCodeController.text = DataGenerator.postalCode(); - _cityController.text = DataGenerator.city(); - } else { - // Vider les champs si même adresse (seront désactivés) - _addressController.text = parent1Data.address; - _postalCodeController.text = parent1Data.postalCode; - _cityController.text = parent1Data.city; - } - } - - // Nouvelle fonction pour remplir depuis les données existantes - void _fillParent2Data(ParentData parent2Data, ParentData parent1Data) { - _firstNameController.text = parent2Data.firstName; - _lastNameController.text = parent2Data.lastName; - _phoneController.text = parent2Data.phone; - _emailController.text = parent2Data.email; - _passwordController.text = parent2Data.password; // Attention à la sécurité - _confirmPasswordController.text = parent2Data.password; - - _sameAddressAsParent1 = (parent2Data.address == parent1Data.address && - parent2Data.postalCode == parent1Data.postalCode && - parent2Data.city == parent1Data.city); - - _addressController.text = parent2Data.address; - _postalCodeController.text = parent2Data.postalCode; - _cityController.text = parent2Data.city; - } - - @override - void dispose() { - _lastNameController.dispose(); - _firstNameController.dispose(); - _phoneController.dispose(); - _emailController.dispose(); - _passwordController.dispose(); - _confirmPasswordController.dispose(); - _addressController.dispose(); - _postalCodeController.dispose(); - _cityController.dispose(); - super.dispose(); - } - - bool get _parent2FieldsEnabled => _addParent2; - bool get _addressFieldsEnabled => _addParent2 && !_sameAddressAsParent1; +class ParentRegisterStep2Screen extends StatelessWidget { + const ParentRegisterStep2Screen({super.key}); @override Widget build(BuildContext context) { final registrationData = Provider.of(context, listen: false); - final parent1Data = registrationData.parent1; - final screenSize = MediaQuery.of(context).size; + final parent1 = registrationData.parent1; + final parent2 = registrationData.parent2; + + bool hasParent2 = parent2 != null; + bool sameAddress = false; + + // Générer des données de test si vide + PersonalInfoData initialData; + if (parent2 == null || parent2.firstName.isEmpty) { + final genFirstName = DataGenerator.firstName(); + final genLastName = DataGenerator.lastName(); + sameAddress = DataGenerator.boolean(); + + initialData = PersonalInfoData( + firstName: genFirstName, + lastName: genLastName, + phone: DataGenerator.phone(), + email: DataGenerator.email(genFirstName, genLastName), + address: sameAddress ? parent1.address : DataGenerator.address(), + postalCode: sameAddress ? parent1.postalCode : DataGenerator.postalCode(), + city: sameAddress ? parent1.city : DataGenerator.city(), + ); + } else { + sameAddress = (parent2.address == parent1.address && + parent2.postalCode == parent1.postalCode && + parent2.city == parent1.city); + initialData = PersonalInfoData( + firstName: parent2.firstName, + lastName: parent2.lastName, + phone: parent2.phone, + email: parent2.email, + address: parent2.address, + postalCode: parent2.postalCode, + city: parent2.city, + ); + } - return Scaffold( - body: Stack( - children: [ - Positioned.fill( - child: Image.asset('assets/images/paper2.png', fit: BoxFit.cover, repeat: ImageRepeat.repeat), - ), - Center( - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('Étape 2/5', style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54)), - const SizedBox(height: 10), - Text( - 'Informations du Deuxième Parent (Optionnel)', - style: GoogleFonts.merienda(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black87), - textAlign: TextAlign.center, - ), - const SizedBox(height: 30), - Container( - width: screenSize.width * 0.6, - padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 50), - decoration: BoxDecoration( - image: DecorationImage(image: AssetImage(CardColorHorizontal.blue.path), fit: BoxFit.fill), - ), - child: Form( - key: _formKey, - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - flex: 12, - child: Row(children: [ - const Icon(Icons.person_add_alt_1, size: 20), const SizedBox(width: 8), - Flexible(child: Text('Ajouter Parent 2 ?', style: GoogleFonts.merienda(fontWeight: FontWeight.bold), overflow: TextOverflow.ellipsis)), - const Spacer(), - Switch(value: _addParent2, onChanged: (val) => setState(() { - _addParent2 = val ?? false; - if (_addParent2) _generateAndFillParent2Data(parent1Data); else _clearParent2Fields(); - }), activeColor: Theme.of(context).primaryColor), - ]), - ), - Expanded(flex: 1, child: const SizedBox()), - Expanded( - flex: 12, - child: Row(children: [ - Icon(Icons.home_work_outlined, size: 20, color: _addParent2 ? null : Colors.grey), - const SizedBox(width: 8), - Flexible(child: Text('Même Adresse ?', style: GoogleFonts.merienda(color: _addParent2 ? null : Colors.grey), overflow: TextOverflow.ellipsis)), - const Spacer(), - Switch(value: _sameAddressAsParent1, onChanged: _addParent2 ? (val) => setState(() { - _sameAddressAsParent1 = val ?? false; - if (_sameAddressAsParent1) { - _addressController.text = parent1Data.address; - _postalCodeController.text = parent1Data.postalCode; - _cityController.text = parent1Data.city; - } else { - _addressController.text = DataGenerator.address(); - _postalCodeController.text = DataGenerator.postalCode(); - _cityController.text = DataGenerator.city(); - } - }) : null, activeColor: Theme.of(context).primaryColor), - ]), - ), - ]), - const SizedBox(height: 25), - Row( - children: [ - Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Nom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - Expanded(flex: 1, child: const SizedBox()), // Espace de 4% - Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Prénom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - ], - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded(flex: 12, child: CustomAppTextField(controller: _phoneController, labelText: 'Téléphone', keyboardType: TextInputType.phone, hintText: 'Son téléphone', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - Expanded(flex: 1, child: const SizedBox()), // Espace de 4% - Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Son email', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - ], - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded(flex: 12, child: CustomAppTextField(controller: _passwordController, labelText: 'Mot de passe', obscureText: true, hintText: 'Son mot de passe', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: _addParent2 ? (v) => (v == null || v.isEmpty ? 'Requis' : (v.length < 6 ? '6 car. min' : null)) : null)), - Expanded(flex: 1, child: const SizedBox()), // Espace de 4% - Expanded(flex: 12, child: CustomAppTextField(controller: _confirmPasswordController, labelText: 'Confirmation', obscureText: true, hintText: 'Confirmer mot de passe', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, validator: _addParent2 ? (v) => (v == null || v.isEmpty ? 'Requis' : (v != _passwordController.text ? 'Différent' : null)) : null)), - ], - ), - const SizedBox(height: 20), - CustomAppTextField(controller: _addressController, labelText: 'Adresse (N° et Rue)', hintText: 'Son numéro et nom de rue', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity), - const SizedBox(height: 20), - Row( - children: [ - Expanded(flex: 1, child: CustomAppTextField(controller: _postalCodeController, labelText: 'Code Postal', keyboardType: TextInputType.number, hintText: 'Son code postal', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - const SizedBox(width: 20), - Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Sa ville', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity)), - ], - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - Positioned( - top: screenSize.height / 2 - 20, - left: 40, - child: IconButton( - icon: Transform(alignment: Alignment.center, transform: Matrix4.rotationY(math.pi), child: Image.asset('assets/images/chevron_right.png', height: 40)), - onPressed: () { - if (context.canPop()) { - context.pop(); - } else { - context.go('/parent-register-step1'); - } - }, - tooltip: 'Retour', - ), - ), - Positioned( - top: screenSize.height / 2 - 20, - right: 40, - child: IconButton( - icon: Image.asset('assets/images/chevron_right.png', height: 40), - onPressed: () { - if (!_addParent2 || (_formKey.currentState?.validate() ?? false)) { - if (_addParent2) { - registrationData.updateParent2( - ParentData( - firstName: _firstNameController.text, - lastName: _lastNameController.text, - address: _sameAddressAsParent1 ? parent1Data.address : _addressController.text, - postalCode: _sameAddressAsParent1 ? parent1Data.postalCode : _postalCodeController.text, - city: _sameAddressAsParent1 ? parent1Data.city : _cityController.text, - phone: _phoneController.text, - email: _emailController.text, - password: _passwordController.text, - ) - ); - } else { - registrationData.updateParent2(null); - } - context.go('/parent-register-step3'); - } - }, - tooltip: 'Suivant', - ), - ), - ], - ), + // Adresse de référence pour "même adresse" + final referenceAddress = PersonalInfoData( + address: parent1.address, + postalCode: parent1.postalCode, + city: parent1.city, + ); + + return PersonalInfoFormScreen( + stepText: 'Étape 2/5', + title: 'Deuxième Parent', + cardColor: CardColorHorizontal.blue, + initialData: initialData, + previousRoute: '/parent-register-step1', + showSecondPersonToggle: true, + initialHasSecondPerson: hasParent2, + showSameAddressCheckbox: true, + initialSameAddress: sameAddress, + referenceAddressData: referenceAddress, + onSubmit: (data, {hasSecondPerson, sameAddress}) { + if (hasSecondPerson == true) { + registrationData.updateParent2( + firstName: data.firstName, + lastName: data.lastName, + phone: data.phone, + email: data.email, + address: data.address, + postalCode: data.postalCode, + city: data.city, + password: '', + ); + } else { + registrationData.removeParent2(); + } + context.go('/parent-register-step3'); + }, ); } - - void _clearParent2Fields() { - _formKey.currentState?.reset(); - _lastNameController.clear(); _firstNameController.clear(); _phoneController.clear(); - _emailController.clear(); _passwordController.clear(); _confirmPasswordController.clear(); - _addressController.clear(); - _postalCodeController.clear(); - _cityController.clear(); - _sameAddressAsParent1 = false; - setState(() {}); - } -} \ No newline at end of file +} diff --git a/frontend/lib/screens/auth/parent_register_step4_screen.dart b/frontend/lib/screens/auth/parent_register_step4_screen.dart index 5b1b42a..10ae74d 100644 --- a/frontend/lib/screens/auth/parent_register_step4_screen.dart +++ b/frontend/lib/screens/auth/parent_register_step4_screen.dart @@ -1,247 +1,42 @@ import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:p_tits_pas/widgets/custom_decorated_text_field.dart'; // Import du nouveau widget -import 'dart:math' as math; // Pour la rotation du chevron -import 'package:p_tits_pas/widgets/app_custom_checkbox.dart'; // Import de la checkbox personnalisée -// import 'package:p_tits_pas/models/placeholder_registration_data.dart'; // Remplacé -import '../../models/user_registration_data.dart'; // Import du vrai modèle -import '../../utils/data_generator.dart'; // Import du générateur -import '../../models/card_assets.dart'; // Import des enums de cartes -import 'package:provider/provider.dart'; // Assurer l'import +import 'package:provider/provider.dart'; import 'package:go_router/go_router.dart'; -class ParentRegisterStep4Screen extends StatefulWidget { - // final UserRegistrationData registrationData; // Supprimé +import '../../models/user_registration_data.dart'; +import '../../widgets/presentation_form_screen.dart'; +import '../../models/card_assets.dart'; +import '../../utils/data_generator.dart'; - const ParentRegisterStep4Screen({super.key /*, required this.registrationData */}); // Modifié - - @override - _ParentRegisterStep4ScreenState createState() => - _ParentRegisterStep4ScreenState(); -} - -class _ParentRegisterStep4ScreenState extends State { - // late UserRegistrationData _registrationData; // Supprimé - final _motivationController = TextEditingController(); - bool _cguAccepted = true; // Pour le test, CGU acceptées par défaut - final _bankNameController = TextEditingController(); - final _ibanController = TextEditingController(); - final _bicController = TextEditingController(); - final _attestationController = TextEditingController(); - bool _consentQuotientFamilial = false; - - @override - void initState() { - super.initState(); - final registrationData = Provider.of(context, listen: false); - // _registrationData = registrationData; // Supprimé - _motivationController.text = registrationData.motivationText.isNotEmpty ? registrationData.motivationText : DataGenerator.motivation(); - _bankNameController.text = registrationData.bankDetails?.bankName ?? ''; - _ibanController.text = registrationData.bankDetails?.iban ?? ''; - _bicController.text = registrationData.bankDetails?.bic ?? ''; - _attestationController.text = registrationData.attestationCafNumber; - _consentQuotientFamilial = registrationData.consentQuotientFamilial; - _cguAccepted = registrationData.cguAccepted; - } - - @override - void dispose() { - _motivationController.dispose(); - _bankNameController.dispose(); - _ibanController.dispose(); - _bicController.dispose(); - _attestationController.dispose(); - super.dispose(); - } - - void _showCGUModal() { - // Un long texte Lorem Ipsum pour simuler les CGU - const String loremIpsumText = ''' -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit. - -Ut velit mauris, egestas sed, gravida nec, ornare ut, mi. Aenean ut orci vel massa suscipit pulvinar. Nulla sollicitudin. Fusce varius, ligula non tempus aliquam, nunc turpis ullamcorper nibh, in tempus sapien eros vitae ligula. Pellentesque rhoncus nunc et augue. Integer id felis. Curabitur aliquet pellentesque diam. Integer quis metus vitae elit lobortis egestas. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi vel erat non mauris convallis vehicula. Nulla et sapien. Integer tortor tellus, aliquam faucibus, convallis id, congue eu, quam. Mauris ullamcorper felis vitae erat. Proin feugiat, augue non elementum posuere, metus purus iaculis lectus, et tristique ligula justo vitae magna. - -Aliquam convallis sollicitudin purus. Praesent aliquam, enim at fermentum mollis, ligula massa adipiscing nisl, ac euismod nibh nisl eu lectus. Fusce vulputate sem at sapien. Vivamus leo. Aliquam euismod libero eu enim. Nulla nec felis sed leo placerat imperdiet. Aenean suscipit nulla in justo. Suspendisse cursus rutrum augue. Nulla tincidunt tincidunt mi. Curabitur iaculis, lorem vel rhoncus faucibus, felis magna fermentum augue, et ultricies lacus lorem varius purus. Curabitur eu amet. - -Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit. - -Ut velit mauris, egestas sed, gravida nec, ornare ut, mi. Aenean ut orci vel massa suscipit pulvinar. Nulla sollicitudin. Fusce varius, ligula non tempus aliquam, nunc turpis ullamcorper nibh, in tempus sapien eros vitae ligula. Pellentesque rhoncus nunc et augue. Integer id felis. Curabitur aliquet pellentesque diam. Integer quis metus vitae elit lobortis egestas. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi vel erat non mauris convallis vehicula. Nulla et sapien. Integer tortor tellus, aliquam faucibus, convallis id, congue eu, quam. Mauris ullamcorper felis vitae erat. Proin feugiat, augue non elementum posuere, metus purus iaculis lectus, et tristique ligula justo vitae magna. Etiam et felis dolor. - -Praesent aliquam, enim at fermentum mollis, ligula massa adipiscing nisl, ac euismod nibh nisl eu lectus. Fusce vulputate sem at sapien. Vivamus leo. Aliquam euismod libero eu enim. Nulla nec felis sed leo placerat imperdiet. Aenean suscipit nulla in justo. Suspendisse cursus rutrum augue. Nulla tincidunt tincidunt mi. Curabitur iaculis, lorem vel rhoncus faucibus, felis magna fermentum augue, et ultricies lacus lorem varius purus. Curabitur eu amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. - -Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. -'''; - - showDialog( - context: context, - barrierDismissible: false, // L'utilisateur doit utiliser le bouton - builder: (BuildContext dialogContext) { - return AlertDialog( - title: Text( - 'Conditions Générales d\'Utilisation', - style: GoogleFonts.merienda(fontWeight: FontWeight.bold), - ), - content: SizedBox( - width: MediaQuery.of(dialogContext).size.width * 0.7, // 70% de la largeur de l'écran - height: MediaQuery.of(dialogContext).size.height * 0.6, // 60% de la hauteur de l'écran - child: SingleChildScrollView( - child: Text( - loremIpsumText, - style: GoogleFonts.merienda(fontSize: 13), - textAlign: TextAlign.justify, - ), - ), - ), - actionsPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), - actionsAlignment: MainAxisAlignment.center, - actions: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(dialogContext).primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15), - ), - child: Text( - 'Valider et Accepter', - style: GoogleFonts.merienda(fontSize: 15, color: Colors.white, fontWeight: FontWeight.bold), - ), - onPressed: () { - Navigator.of(dialogContext).pop(); // Ferme la modale - setState(() { - _cguAccepted = true; // Met à jour l'état - }); - }, - ), - ], - ); - }, - ); - } +class ParentRegisterStep4Screen extends StatelessWidget { + const ParentRegisterStep4Screen({super.key}); @override Widget build(BuildContext context) { - final registrationData = Provider.of(context, listen: false); // listen:false car on met à jour - final screenSize = MediaQuery.of(context).size; - final cardWidth = screenSize.width * 0.6; // Largeur de la carte (60% de l'écran) - final double imageAspectRatio = 2.0; // Ratio corrigé (1024/512 = 2.0) - final cardHeight = cardWidth / imageAspectRatio; + final registrationData = Provider.of(context, listen: false); + + // Générer un texte de test si vide + String initialText = registrationData.motivationText; + bool initialCgu = registrationData.cguAccepted; + + if (initialText.isEmpty) { + initialText = DataGenerator.motivation(); + initialCgu = true; + } - return Scaffold( - body: Stack( - children: [ - Positioned.fill( - child: Image.asset('assets/images/paper2.png', fit: BoxFit.cover, repeat: ImageRepeat.repeat), - ), - Center( - child: SingleChildScrollView( - padding: const EdgeInsets.symmetric(vertical: 40.0, horizontal: 50.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - 'Étape 4/5', - style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54), - ), - const SizedBox(height: 20), - Text( - 'Motivation de votre demande', - style: GoogleFonts.merienda(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.black87), - textAlign: TextAlign.center, - ), - const SizedBox(height: 30), - Container( - width: cardWidth, - height: cardHeight, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage(CardColorHorizontal.green.path), - fit: BoxFit.fill, - ), - ), - child: Padding( - padding: const EdgeInsets.all(40.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: CustomDecoratedTextField( - controller: _motivationController, - hintText: 'Écrivez ici pour motiver votre demande...', - fieldHeight: cardHeight * 0.6, - maxLines: 10, - expandDynamically: true, - fontSize: 18.0, - ), - ), - const SizedBox(height: 20), - GestureDetector( - onTap: () { - if (!_cguAccepted) { - _showCGUModal(); - } - }, - child: AppCustomCheckbox( - label: 'J\'accepte les conditions générales d\'utilisation', - value: _cguAccepted, - onChanged: (newValue) { - if (!_cguAccepted) { - _showCGUModal(); - } else { - setState(() => _cguAccepted = false); - } - }, - ), - ), - ], - ), - ), - ), - ], - ), - ), - ), - // Chevrons de navigation - Positioned( - top: screenSize.height / 2 - 20, - left: 40, - child: IconButton( - icon: Transform(alignment: Alignment.center, transform: Matrix4.rotationY(math.pi), child: Image.asset('assets/images/chevron_right.png', height: 40)), - onPressed: () { - if (context.canPop()) { - context.pop(); - } else { - context.go('/parent-register-step3'); - } - }, - tooltip: 'Retour', - ), - ), - Positioned( - top: screenSize.height / 2 - 20, - right: 40, - child: IconButton( - icon: Image.asset('assets/images/chevron_right.png', height: 40), - onPressed: _cguAccepted - ? () { - registrationData.updateMotivation(_motivationController.text); - registrationData.acceptCGU(_cguAccepted); - registrationData.updateFinancialInfo( - bankDetails: BankDetails( - bankName: _bankNameController.text, - iban: _ibanController.text, - bic: _bicController.text, - ), - attestationCafNumber: _attestationController.text, - consentQuotientFamilial: _consentQuotientFamilial, - ); - context.go('/parent-register-step5'); - } - : null, - tooltip: 'Suivant', - ), - ), - ], - ), + return PresentationFormScreen( + stepText: 'Étape 4/5', + title: 'Motivation de votre demande', + cardColor: CardColorHorizontal.green, + textFieldHint: 'Écrivez ici pour motiver votre demande...', + initialText: initialText, + initialCguAccepted: initialCgu, + previousRoute: '/parent-register-step3', + onSubmit: (text, cguAccepted) { + registrationData.updateMotivation(text); + registrationData.acceptCGU(cguAccepted); + // Les infos financières peuvent être gérées ailleurs si nécessaire + context.go('/parent-register-step5'); + }, ); } -} \ No newline at end of file +}