diff --git a/frontend/lib/screens/auth/parent/parent_register_step1_screen.dart b/frontend/lib/screens/auth/parent/parent_register_step1_screen.dart new file mode 100644 index 0000000..194208a --- /dev/null +++ b/frontend/lib/screens/auth/parent/parent_register_step1_screen.dart @@ -0,0 +1,209 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'dart:math' as math; // Pour la rotation du chevron +import '../../../models/parent_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 + +class ParentRegisterStep1Screen extends StatefulWidget { + const ParentRegisterStep1Screen({super.key}); + + @override + State createState() => _ParentRegisterStep1ScreenState(); +} + +class _ParentRegisterStep1ScreenState extends State { + final _formKey = GlobalKey(); + late UserRegistrationData _registrationData; + + // Contrôleurs pour les champs (restauration CP et Ville) + final _lastNameController = TextEditingController(); + final _firstNameController = TextEditingController(); + final _phoneController = TextEditingController(); + final _emailController = TextEditingController(); + final _addressController = TextEditingController(); + final _postalCodeController = TextEditingController(); + final _cityController = TextEditingController(); + + @override + void initState() { + super.initState(); + _registrationData = UserRegistrationData(); + _generateAndFillData(); + } + + void _generateAndFillData() { + final String genFirstName = DataGenerator.firstName(); + final String genLastName = DataGenerator.lastName(); + + // Utilisation des méthodes publiques de DataGenerator + _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); + } + + @override + void dispose() { + _lastNameController.dispose(); + _firstNameController.dispose(); + _phoneController.dispose(); + _emailController.dispose(); + _addressController.dispose(); + _postalCodeController.dispose(); + _cityController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final screenSize = MediaQuery.of(context).size; + + 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 + Text( + 'Étape 1/6', + 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, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + const SizedBox(height: 10), + Row( + children: [ + Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Votre nom de famille', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + Expanded(flex: 1, child: const SizedBox()), + Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Votre prénom', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + ], + ), + const SizedBox(height: 32), + 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, labelFontSize: 22.0, inputFontSize: 20.0)), + Expanded(flex: 1, child: const SizedBox()), + Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Votre adresse e-mail', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + ], + ), + const SizedBox(height: 32), + CustomAppTextField( + controller: _addressController, + labelText: 'Adresse (N° et Rue)', + hintText: 'Numéro et nom de votre rue', + style: CustomAppTextFieldStyle.beige, + fieldWidth: double.infinity, + labelFontSize: 22.0, + inputFontSize: 20.0, + ), + const SizedBox(height: 32), + Row( + children: [ + Expanded(flex: 1, child: CustomAppTextField(controller: _postalCodeController, labelText: 'Code Postal', keyboardType: TextInputType.number, hintText: 'Code postal', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + const SizedBox(width: 20), + Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Votre ville', style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + ], + ), + const SizedBox(height: 10), + ], + ), + ), + ), + ], + ), + ), + ), + + // 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: () => Navigator.pop(context), // Retour à l'écran de choix + 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: () { + if (_formKey.currentState?.validate() ?? 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: '', // Pas de mot de passe à cette étape + ) + ); + Navigator.pushNamed(context, '/parent-register/step2', arguments: _registrationData); + } + }, + tooltip: 'Suivant', + ), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/frontend/lib/screens/auth/parent/parent_register_step2_screen.dart b/frontend/lib/screens/auth/parent/parent_register_step2_screen.dart new file mode 100644 index 0000000..219a519 --- /dev/null +++ b/frontend/lib/screens/auth/parent/parent_register_step2_screen.dart @@ -0,0 +1,244 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'dart:math' as math; // Pour la rotation du chevron +import '../../../models/parent_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 + +class ParentRegisterStep2Screen extends StatefulWidget { + final UserRegistrationData registrationData; // Accepte les données de l'étape 1 + + const ParentRegisterStep2Screen({super.key, required this.registrationData}); + + @override + State createState() => _ParentRegisterStep2ScreenState(); +} + +class _ParentRegisterStep2ScreenState extends State { + final _formKey = GlobalKey(); + late UserRegistrationData _registrationData; // Copie locale pour modification + + 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 + final _lastNameController = TextEditingController(); + final _firstNameController = TextEditingController(); + final _phoneController = TextEditingController(); + final _emailController = TextEditingController(); + final _addressController = TextEditingController(); + final _postalCodeController = TextEditingController(); + final _cityController = TextEditingController(); + + @override + void initState() { + super.initState(); + _registrationData = widget.registrationData; // Récupère les données de l'étape 1 + if (_addParent2) { + _generateAndFillParent2Data(); + } + } + + void _generateAndFillParent2Data() { + 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); + + _sameAddressAsParent1 = DataGenerator.boolean(); + if (!_sameAddressAsParent1) { + _addressController.text = DataGenerator.address(); + _postalCodeController.text = DataGenerator.postalCode(); + _cityController.text = DataGenerator.city(); + } else { + _addressController.clear(); + _postalCodeController.clear(); + _cityController.clear(); + } + } + + @override + void dispose() { + _lastNameController.dispose(); + _firstNameController.dispose(); + _phoneController.dispose(); + _emailController.dispose(); + _addressController.dispose(); + _postalCodeController.dispose(); + _cityController.dispose(); + super.dispose(); + } + + bool get _parent2FieldsEnabled => _addParent2; + bool get _addressFieldsEnabled => _addParent2 && !_sameAddressAsParent1; + + @override + Widget build(BuildContext context) { + final screenSize = MediaQuery.of(context).size; + + 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/6', 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, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + const SizedBox(height: 10), + 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(); 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 = _registrationData.parent1.address; + _postalCodeController.text = _registrationData.parent1.postalCode; + _cityController.text = _registrationData.parent1.city; + } else { + _addressController.text = DataGenerator.address(); + _postalCodeController.text = DataGenerator.postalCode(); + _cityController.text = DataGenerator.city(); + } + }) : null, activeColor: Theme.of(context).primaryColor), + ]), + ), + ]), + const SizedBox(height: 32), + Row( + children: [ + Expanded(flex: 12, child: CustomAppTextField(controller: _lastNameController, labelText: 'Nom', hintText: 'Nom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + Expanded(flex: 1, child: const SizedBox()), + Expanded(flex: 12, child: CustomAppTextField(controller: _firstNameController, labelText: 'Prénom', hintText: 'Prénom du parent 2', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + ], + ), + const SizedBox(height: 32), + 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, labelFontSize: 22.0, inputFontSize: 20.0)), + Expanded(flex: 1, child: const SizedBox()), + Expanded(flex: 12, child: CustomAppTextField(controller: _emailController, labelText: 'Email', keyboardType: TextInputType.emailAddress, hintText: 'Son email', enabled: _parent2FieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + ], + ), + const SizedBox(height: 32), + CustomAppTextField(controller: _addressController, labelText: 'Adresse (N° et Rue)', hintText: 'Son numéro et nom de rue', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0), + const SizedBox(height: 32), + 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, labelFontSize: 22.0, inputFontSize: 20.0)), + const SizedBox(width: 20), + Expanded(flex: 4, child: CustomAppTextField(controller: _cityController, labelText: 'Ville', hintText: 'Sa ville', enabled: _addressFieldsEnabled, style: CustomAppTextFieldStyle.beige, fieldWidth: double.infinity, labelFontSize: 22.0, inputFontSize: 20.0)), + ], + ), + const SizedBox(height: 10), + ], + ), + ), + ), + ), + ], + ), + ), + ), + 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: () => Navigator.pop(context), + 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 ? _registrationData.parent1.address : _addressController.text, + postalCode: _sameAddressAsParent1 ? _registrationData.parent1.postalCode : _postalCodeController.text, + city: _sameAddressAsParent1 ? _registrationData.parent1.city : _cityController.text, + phone: _phoneController.text, + email: _emailController.text, + password: '', // Pas de mot de passe à cette étape + ) + ); + } else { + _registrationData.updateParent2(null); + } + Navigator.pushNamed(context, '/parent-register/step3', arguments: _registrationData); + } + }, + tooltip: 'Suivant', + ), + ), + ], + ), + ); + } + + void _clearParent2Fields() { + _formKey.currentState?.reset(); + _lastNameController.clear(); + _firstNameController.clear(); + _phoneController.clear(); + _emailController.clear(); + _addressController.clear(); + _postalCodeController.clear(); + _cityController.clear(); + _sameAddressAsParent1 = false; + setState(() {}); + } +} \ No newline at end of file