feat(#78): Migrer ParentRegisterStep3Screen (Enfants) vers infrastructure multi-modes

Adaptation responsive du formulaire "Informations Enfants" (Parent Step 3) :
- Desktop : Conservation du layout horizontal avec scroll et effets de fondu
- Mobile : Layout vertical avec cartes empilées
  - Header fixe
  - Bouton "+" carré (50px) centré à la fin de la liste
  - Boutons navigation intégrés au scroll
  - Cartes enfants adaptées (scale 0.9, polices réduites)
- Mise à jour DisplayConfig (mode optionnel par défaut)
- Mise à jour AppCustomCheckbox (paramètre fontSize)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-04 11:43:26 +01:00
co-authored by Cursor
parent bdecbc2c1d
commit eea94769bf
4 changed files with 223 additions and 44 deletions
@@ -7,6 +7,7 @@ class AppCustomCheckbox extends StatelessWidget {
final ValueChanged<bool> onChanged;
final double checkboxSize;
final double checkmarkSizeFactor;
final double fontSize;
const AppCustomCheckbox({
super.key,
@@ -15,6 +16,7 @@ class AppCustomCheckbox extends StatelessWidget {
required this.onChanged,
this.checkboxSize = 20.0,
this.checkmarkSizeFactor = 1.4,
this.fontSize = 16.0,
});
@override
@@ -51,7 +53,7 @@ class AppCustomCheckbox extends StatelessWidget {
Flexible(
child: Text(
label,
style: GoogleFonts.merienda(fontSize: 16),
style: GoogleFonts.merienda(fontSize: fontSize),
overflow: TextOverflow.ellipsis, // Gérer le texte long
),
),
+45 -24
View File
@@ -7,6 +7,7 @@ import '../models/card_assets.dart';
import 'custom_app_text_field.dart';
import 'app_custom_checkbox.dart';
import 'hover_relief_widget.dart';
import '../config/display_config.dart';
/// Widget pour afficher et éditer une carte enfant
/// Utilisé dans le workflow d'inscription des parents
@@ -87,6 +88,9 @@ class _ChildCardWidgetState extends State<ChildCardWidget> {
@override
Widget build(BuildContext context) {
final config = DisplayConfig.fromContext(context);
final scaleFactor = config.isMobile ? 0.9 : 1.1; // Réduire légèrement sur mobile
final File? currentChildImage = widget.childData.imageFile;
// Utiliser la couleur de la carte de childData pour l'ombre si besoin, ou directement pour le fond
final Color baseCardColorForShadow = widget.childData.cardColor == CardColorVertical.lavender
@@ -96,12 +100,12 @@ class _ChildCardWidgetState extends State<ChildCardWidget> {
final Color hoverPhotoShadow = baseCardColorForShadow.withAlpha(130);
return Container(
width: 345.0 * 1.1, // 379.5
height: 570.0 * 1.2, // 684.0
padding: const EdgeInsets.all(22.0 * 1.1), // 24.2
width: 345.0 * scaleFactor,
height: config.isMobile ? null : 570.0 * scaleFactor, // Hauteur auto sur mobile
padding: EdgeInsets.all(22.0 * scaleFactor),
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage(widget.childData.cardColor.path), fit: BoxFit.cover),
borderRadius: BorderRadius.circular(20 * 1.1), // 22
image: DecorationImage(image: AssetImage(widget.childData.cardColor.path), fit: BoxFit.fill),
borderRadius: BorderRadius.circular(20 * scaleFactor),
),
child: Stack(
children: [
@@ -114,43 +118,56 @@ class _ChildCardWidgetState extends State<ChildCardWidget> {
initialShadowColor: initialPhotoShadow,
hoverShadowColor: hoverPhotoShadow,
child: SizedBox(
height: 200.0,
width: 200.0,
height: 200.0 * (config.isMobile ? 0.8 : 1.0),
width: 200.0 * (config.isMobile ? 0.8 : 1.0),
child: Center(
child: Padding(
padding: const EdgeInsets.all(5.0 * 1.1), // 5.5
padding: EdgeInsets.all(5.0 * scaleFactor),
child: currentChildImage != null
? ClipRRect(borderRadius: BorderRadius.circular(10 * 1.1), child: kIsWeb ? Image.network(currentChildImage.path, fit: BoxFit.cover) : Image.file(currentChildImage, fit: BoxFit.cover))
? ClipRRect(borderRadius: BorderRadius.circular(10 * scaleFactor), child: kIsWeb ? Image.network(currentChildImage.path, fit: BoxFit.cover) : Image.file(currentChildImage, fit: BoxFit.cover))
: Image.asset('assets/images/photo.png', fit: BoxFit.contain),
),
),
),
),
const SizedBox(height: 12.0 * 1.1), // Augmenté pour plus d'espace après la photo
SizedBox(height: 12.0 * scaleFactor),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Enfant à naître ?', style: GoogleFonts.merienda(fontSize: 16 * 1.1, fontWeight: FontWeight.w600)),
Switch(value: widget.childData.isUnbornChild, onChanged: widget.onToggleIsUnborn, activeColor: Theme.of(context).primaryColor),
Text(
'Enfant à naître ?',
style: GoogleFonts.merienda(
fontSize: config.isMobile ? 14 : 16 * scaleFactor,
fontWeight: FontWeight.w600
)
),
Transform.scale(
scale: config.isMobile ? 0.8 : 1.0,
child: Switch(value: widget.childData.isUnbornChild, onChanged: widget.onToggleIsUnborn, activeColor: Theme.of(context).primaryColor),
),
],
),
const SizedBox(height: 9.0 * 1.1), // 9.9
SizedBox(height: 9.0 * scaleFactor),
CustomAppTextField(
controller: _firstNameController,
labelText: 'Prénom',
hintText: 'Facultatif si à naître',
isRequired: !widget.childData.isUnbornChild,
fieldHeight: 55.0 * 1.1, // 60.5
fieldHeight: config.isMobile ? 45.0 : 55.0 * scaleFactor,
labelFontSize: config.isMobile ? 14.0 : 22.0, // Police réduite mobile
inputFontSize: config.isMobile ? 14.0 : 20.0,
),
const SizedBox(height: 6.0 * 1.1), // 6.6
SizedBox(height: 6.0 * scaleFactor),
CustomAppTextField(
controller: _lastNameController,
labelText: 'Nom',
hintText: 'Nom de l\'enfant',
enabled: true,
fieldHeight: 55.0 * 1.1, // 60.5
fieldHeight: config.isMobile ? 45.0 : 55.0 * scaleFactor,
labelFontSize: config.isMobile ? 14.0 : 22.0,
inputFontSize: config.isMobile ? 14.0 : 20.0,
),
const SizedBox(height: 9.0 * 1.1), // 9.9
SizedBox(height: 9.0 * scaleFactor),
CustomAppTextField(
controller: _dobController,
labelText: widget.childData.isUnbornChild ? 'Date prévisionnelle de naissance' : 'Date de naissance',
@@ -158,9 +175,11 @@ class _ChildCardWidgetState extends State<ChildCardWidget> {
readOnly: true,
onTap: widget.onDateSelect,
suffixIcon: Icons.calendar_today,
fieldHeight: 55.0 * 1.1, // 60.5
fieldHeight: config.isMobile ? 45.0 : 55.0 * scaleFactor,
labelFontSize: config.isMobile ? 14.0 : 22.0,
inputFontSize: config.isMobile ? 14.0 : 20.0,
),
const SizedBox(height: 11.0 * 1.1), // 12.1
SizedBox(height: 11.0 * scaleFactor),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -168,14 +187,16 @@ class _ChildCardWidgetState extends State<ChildCardWidget> {
label: 'Consentement photo',
value: widget.childData.photoConsent,
onChanged: widget.onTogglePhotoConsent,
checkboxSize: 22.0 * 1.1, // 24.2
checkboxSize: config.isMobile ? 20.0 : 22.0 * scaleFactor,
fontSize: config.isMobile ? 13.0 : 16.0,
),
const SizedBox(height: 6.0 * 1.1), // 6.6
SizedBox(height: 6.0 * scaleFactor),
AppCustomCheckbox(
label: 'Naissance multiple',
value: widget.childData.multipleBirth,
onChanged: widget.onToggleMultipleBirth,
checkboxSize: 22.0 * 1.1, // 24.2
checkboxSize: config.isMobile ? 20.0 : 22.0 * scaleFactor,
fontSize: config.isMobile ? 13.0 : 16.0,
),
],
),
@@ -189,8 +210,8 @@ class _ChildCardWidgetState extends State<ChildCardWidget> {
customBorder: const CircleBorder(),
child: Image.asset(
'assets/images/red_cross2.png',
width: 36,
height: 36,
width: config.isMobile ? 30 : 36,
height: config.isMobile ? 30 : 36,
fit: BoxFit.contain,
),
),