feat(frontend): Ajout champ genre obligatoire + Clean Code Step3
- Ajout champ gender (H/F) dans ChildData avec sélecteur radio - Correction indicateur étape: 3/5 → 3/6 - Suppression commentaires inutiles et code obsolète - Suppression print() pour gestion silencieuse des erreurs - Ajout méthode gender() dans DataGenerator Ticket #38
This commit is contained in:
parent
1bbdab03d0
commit
aee061f9bd
@ -28,22 +28,24 @@ class ParentData {
|
|||||||
class ChildData {
|
class ChildData {
|
||||||
String firstName;
|
String firstName;
|
||||||
String lastName;
|
String lastName;
|
||||||
String dob; // Date de naissance ou prévisionnelle
|
String dob;
|
||||||
|
String gender;
|
||||||
bool photoConsent;
|
bool photoConsent;
|
||||||
bool multipleBirth;
|
bool multipleBirth;
|
||||||
bool isUnbornChild;
|
bool isUnbornChild;
|
||||||
File? imageFile;
|
File? imageFile;
|
||||||
CardColorVertical cardColor; // Nouveau champ pour la couleur de la carte
|
CardColorVertical cardColor;
|
||||||
|
|
||||||
ChildData({
|
ChildData({
|
||||||
this.firstName = '',
|
this.firstName = '',
|
||||||
this.lastName = '',
|
this.lastName = '',
|
||||||
this.dob = '',
|
this.dob = '',
|
||||||
|
this.gender = 'F',
|
||||||
this.photoConsent = false,
|
this.photoConsent = false,
|
||||||
this.multipleBirth = false,
|
this.multipleBirth = false,
|
||||||
this.isUnbornChild = false,
|
this.isUnbornChild = false,
|
||||||
this.imageFile,
|
this.imageFile,
|
||||||
required this.cardColor, // Rendre requis dans le constructeur
|
required this.cardColor,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,16 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'dart:math' as math; // Pour la rotation du chevron
|
import 'dart:math' as math;
|
||||||
import 'package:flutter/gestures.dart'; // Pour PointerDeviceKind
|
import 'package:flutter/gestures.dart';
|
||||||
import '../../widgets/hover_relief_widget.dart'; // Import du nouveau widget
|
import '../../widgets/hover_relief_widget.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
// import 'package:image_cropper/image_cropper.dart'; // Supprimé
|
import 'dart:io' show File, Platform;
|
||||||
import 'dart:io' show File, Platform; // Ajout de Platform
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb; // Import pour kIsWeb
|
import '../../widgets/custom_app_text_field.dart';
|
||||||
import '../../widgets/custom_app_text_field.dart'; // Import du nouveau widget TextField
|
import '../../widgets/app_custom_checkbox.dart';
|
||||||
import '../../widgets/app_custom_checkbox.dart'; // Import du nouveau widget Checkbox
|
import '../../models/user_registration_data.dart';
|
||||||
import '../../models/user_registration_data.dart'; // Import du modèle de données
|
import '../../utils/data_generator.dart';
|
||||||
import '../../utils/data_generator.dart'; // Import du générateur
|
import '../../models/card_assets.dart';
|
||||||
import '../../models/card_assets.dart'; // Import des enums de cartes
|
|
||||||
|
|
||||||
// La classe _ChildFormData est supprimée car on utilise ChildData du modèle
|
|
||||||
|
|
||||||
class ParentRegisterStep3Screen extends StatefulWidget {
|
class ParentRegisterStep3Screen extends StatefulWidget {
|
||||||
final UserRegistrationData registrationData; // Accepte les données
|
final UserRegistrationData registrationData; // Accepte les données
|
||||||
@ -25,16 +22,15 @@ class ParentRegisterStep3Screen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
||||||
late UserRegistrationData _registrationData; // Stocke l'état complet
|
late UserRegistrationData _registrationData;
|
||||||
final ScrollController _scrollController = ScrollController(); // Pour le défilement horizontal
|
final ScrollController _scrollController = ScrollController();
|
||||||
bool _isScrollable = false;
|
bool _isScrollable = false;
|
||||||
bool _showLeftFade = false;
|
bool _showLeftFade = false;
|
||||||
bool _showRightFade = false;
|
bool _showRightFade = false;
|
||||||
static const double _fadeExtent = 0.05; // Pourcentage de fondu
|
static const double _fadeExtent = 0.05;
|
||||||
|
|
||||||
// Liste ordonnée des couleurs de cartes pour les enfants
|
|
||||||
static const List<CardColorVertical> _childCardColors = [
|
static const List<CardColorVertical> _childCardColors = [
|
||||||
CardColorVertical.lavender, // Premier enfant toujours lavande
|
CardColorVertical.lavender,
|
||||||
CardColorVertical.pink,
|
CardColorVertical.pink,
|
||||||
CardColorVertical.peach,
|
CardColorVertical.peach,
|
||||||
CardColorVertical.lime,
|
CardColorVertical.lime,
|
||||||
@ -43,11 +39,7 @@ class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
|||||||
CardColorVertical.blue,
|
CardColorVertical.blue,
|
||||||
];
|
];
|
||||||
|
|
||||||
// Garder une trace des couleurs déjà utilisées
|
final Set<CardColorVertical> _usedColors = {};
|
||||||
final Set<CardColorVertical> _usedColors = {};
|
|
||||||
|
|
||||||
// Utilisation de GlobalKey pour les cartes enfants si validation complexe future
|
|
||||||
// Map<int, GlobalKey<FormState>> _childFormKeys = {};
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -101,6 +93,7 @@ class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
|||||||
lastName: _registrationData.parent1.lastName,
|
lastName: _registrationData.parent1.lastName,
|
||||||
firstName: DataGenerator.firstName(),
|
firstName: DataGenerator.firstName(),
|
||||||
dob: DataGenerator.dob(isUnborn: isUnborn),
|
dob: DataGenerator.dob(isUnborn: isUnborn),
|
||||||
|
gender: DataGenerator.gender(),
|
||||||
isUnbornChild: isUnborn,
|
isUnbornChild: isUnborn,
|
||||||
photoConsent: DataGenerator.boolean(),
|
photoConsent: DataGenerator.boolean(),
|
||||||
multipleBirth: DataGenerator.boolean(),
|
multipleBirth: DataGenerator.boolean(),
|
||||||
@ -138,8 +131,10 @@ class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
|||||||
_registrationData.children[childIndex].imageFile = File(pickedFile.path);
|
_registrationData.children[childIndex].imageFile = File(pickedFile.path);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) { print("Erreur image: $e"); }
|
} catch (e) {
|
||||||
|
// Gestion silencieuse de l'erreur
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _selectDate(BuildContext context, int childIndex) async {
|
Future<void> _selectDate(BuildContext context, int childIndex) async {
|
||||||
@ -194,7 +189,7 @@ class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text('Étape 3/5', style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54)),
|
Text('Étape 3/6', style: GoogleFonts.merienda(fontSize: 16, color: Colors.black54)),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
Text(
|
||||||
'Informations Enfants',
|
'Informations Enfants',
|
||||||
@ -228,18 +223,18 @@ class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 20.0),
|
padding: const EdgeInsets.only(right: 20.0),
|
||||||
child: _ChildCardWidget(
|
child: _ChildCardWidget(
|
||||||
key: ValueKey(_registrationData.children[index].hashCode), // Utiliser une clé basée sur les données
|
key: ValueKey(_registrationData.children[index].hashCode),
|
||||||
childData: _registrationData.children[index],
|
childData: _registrationData.children[index],
|
||||||
childIndex: index,
|
childIndex: index,
|
||||||
onPickImage: () => _pickImage(index),
|
onPickImage: () => _pickImage(index),
|
||||||
onDateSelect: () => _selectDate(context, index),
|
onDateSelect: () => _selectDate(context, index),
|
||||||
onFirstNameChanged: (value) => setState(() => _registrationData.children[index].firstName = value),
|
onFirstNameChanged: (value) => setState(() => _registrationData.children[index].firstName = value),
|
||||||
onLastNameChanged: (value) => setState(() => _registrationData.children[index].lastName = value),
|
onLastNameChanged: (value) => setState(() => _registrationData.children[index].lastName = value),
|
||||||
|
onGenderChanged: (value) => setState(() => _registrationData.children[index].gender = value),
|
||||||
onTogglePhotoConsent: (newValue) => setState(() => _registrationData.children[index].photoConsent = newValue),
|
onTogglePhotoConsent: (newValue) => setState(() => _registrationData.children[index].photoConsent = newValue),
|
||||||
onToggleMultipleBirth: (newValue) => setState(() => _registrationData.children[index].multipleBirth = newValue),
|
onToggleMultipleBirth: (newValue) => setState(() => _registrationData.children[index].multipleBirth = newValue),
|
||||||
onToggleIsUnborn: (newValue) => setState(() {
|
onToggleIsUnborn: (newValue) => setState(() {
|
||||||
_registrationData.children[index].isUnbornChild = newValue;
|
_registrationData.children[index].isUnbornChild = newValue;
|
||||||
// Générer une nouvelle date si on change le statut
|
|
||||||
_registrationData.children[index].dob = DataGenerator.dob(isUnborn: newValue);
|
_registrationData.children[index].dob = DataGenerator.dob(isUnborn: newValue);
|
||||||
}),
|
}),
|
||||||
onRemove: () => _removeChild(index),
|
onRemove: () => _removeChild(index),
|
||||||
@ -295,13 +290,14 @@ class _ParentRegisterStep3ScreenState extends State<ParentRegisterStep3Screen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Widget pour la carte enfant (adapté pour prendre ChildData et des callbacks)
|
// Widget pour la carte enfant (adapté pour prendre ChildData et des callbacks)
|
||||||
class _ChildCardWidget extends StatefulWidget { // Transformé en StatefulWidget pour gérer les contrôleurs internes
|
class _ChildCardWidget extends StatefulWidget {
|
||||||
final ChildData childData;
|
final ChildData childData;
|
||||||
final int childIndex;
|
final int childIndex;
|
||||||
final VoidCallback onPickImage;
|
final VoidCallback onPickImage;
|
||||||
final VoidCallback onDateSelect;
|
final VoidCallback onDateSelect;
|
||||||
final ValueChanged<String> onFirstNameChanged;
|
final ValueChanged<String> onFirstNameChanged;
|
||||||
final ValueChanged<String> onLastNameChanged;
|
final ValueChanged<String> onLastNameChanged;
|
||||||
|
final ValueChanged<String> onGenderChanged;
|
||||||
final ValueChanged<bool> onTogglePhotoConsent;
|
final ValueChanged<bool> onTogglePhotoConsent;
|
||||||
final ValueChanged<bool> onToggleMultipleBirth;
|
final ValueChanged<bool> onToggleMultipleBirth;
|
||||||
final ValueChanged<bool> onToggleIsUnborn;
|
final ValueChanged<bool> onToggleIsUnborn;
|
||||||
@ -316,6 +312,7 @@ class _ChildCardWidget extends StatefulWidget { // Transformé en StatefulWidget
|
|||||||
required this.onDateSelect,
|
required this.onDateSelect,
|
||||||
required this.onFirstNameChanged,
|
required this.onFirstNameChanged,
|
||||||
required this.onLastNameChanged,
|
required this.onLastNameChanged,
|
||||||
|
required this.onGenderChanged,
|
||||||
required this.onTogglePhotoConsent,
|
required this.onTogglePhotoConsent,
|
||||||
required this.onToggleMultipleBirth,
|
required this.onToggleMultipleBirth,
|
||||||
required this.onToggleIsUnborn,
|
required this.onToggleIsUnborn,
|
||||||
@ -436,6 +433,32 @@ class _ChildCardWidgetState extends State<_ChildCardWidget> {
|
|||||||
fieldHeight: 55.0 * 1.1, // 60.5
|
fieldHeight: 55.0 * 1.1, // 60.5
|
||||||
),
|
),
|
||||||
const SizedBox(height: 9.0 * 1.1), // 9.9
|
const SizedBox(height: 9.0 * 1.1), // 9.9
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Genre', style: GoogleFonts.merienda(fontSize: 16 * 1.1, fontWeight: FontWeight.w600)),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Radio<String>(
|
||||||
|
value: 'H',
|
||||||
|
groupValue: widget.childData.gender,
|
||||||
|
onChanged: (value) => widget.onGenderChanged(value!),
|
||||||
|
activeColor: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
Text('H', style: GoogleFonts.merienda(fontSize: 16 * 1.1)),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Radio<String>(
|
||||||
|
value: 'F',
|
||||||
|
groupValue: widget.childData.gender,
|
||||||
|
onChanged: (value) => widget.onGenderChanged(value!),
|
||||||
|
activeColor: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
Text('F', style: GoogleFonts.merienda(fontSize: 16 * 1.1)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 9.0 * 1.1), // 9.9
|
||||||
CustomAppTextField(
|
CustomAppTextField(
|
||||||
controller: _dobController,
|
controller: _dobController,
|
||||||
labelText: widget.childData.isUnbornChild ? 'Date prévisionnelle de naissance' : 'Date de naissance',
|
labelText: widget.childData.isUnbornChild ? 'Date prévisionnelle de naissance' : 'Date de naissance',
|
||||||
|
|||||||
@ -51,6 +51,8 @@ class DataGenerator {
|
|||||||
|
|
||||||
static bool boolean() => _random.nextBool();
|
static bool boolean() => _random.nextBool();
|
||||||
|
|
||||||
|
static String gender() => _random.nextBool() ? 'H' : 'F';
|
||||||
|
|
||||||
static String motivation() {
|
static String motivation() {
|
||||||
int count = _random.nextInt(3) + 2; // 2 à 4 phrases
|
int count = _random.nextInt(3) + 2; // 2 à 4 phrases
|
||||||
List<String> chosenSnippets = [];
|
List<String> chosenSnippets = [];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user