From 030ef81038f891f80f0a587bdf46f86a2edad92e Mon Sep 17 00:00:00 2001 From: Julien Martin Date: Sat, 7 Feb 2026 17:43:17 +0100 Subject: [PATCH] feat(frontend): Adapt RegisterChoiceScreen for mobile (Closes #83) Co-authored-by: Cursor --- .../screens/auth/register_choice_screen.dart | 282 +++++++++--------- frontend/lib/widgets/choice_card_widget.dart | 87 ++++++ 2 files changed, 231 insertions(+), 138 deletions(-) create mode 100644 frontend/lib/widgets/choice_card_widget.dart diff --git a/frontend/lib/screens/auth/register_choice_screen.dart b/frontend/lib/screens/auth/register_choice_screen.dart index e80238b..301814c 100644 --- a/frontend/lib/screens/auth/register_choice_screen.dart +++ b/frontend/lib/screens/auth/register_choice_screen.dart @@ -1,164 +1,170 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'dart:math' as math; // Pour la rotation du chevron -import '../../widgets/hover_relief_widget.dart'; // Import du widget générique -import '../../models/card_assets.dart'; // Import des enums de cartes +import '../../widgets/choice_card_widget.dart'; // Import du nouveau widget +import '../../widgets/custom_navigation_button.dart'; +import '../../widgets/hover_relief_widget.dart'; import 'package:go_router/go_router.dart'; +// Screen for choosing between Parent and AM registration class RegisterChoiceScreen extends StatelessWidget { const RegisterChoiceScreen({super.key}); @override Widget build(BuildContext context) { - final screenSize = MediaQuery.of(context).size; - return Scaffold( - body: Stack( + body: LayoutBuilder( + builder: (context, constraints) { + final width = constraints.maxWidth; + final height = constraints.maxHeight; + final screenSize = Size(width, height); + + // Utilisation de la largeur disponible pour déterminer le mode + // C'est plus fiable que MediaQuery si le widget est contraint + final isMobile = width < 900; + + return Stack( + children: [ + // Fond papier + Positioned.fill( + child: Image.asset( + 'assets/images/paper2.png', + fit: BoxFit.cover, + repeat: ImageRepeat.repeat, + ), + ), + + // Bouton Retour (chevron gauche) - Desktop uniquement + if (!isMobile) + Positioned( + top: 40, + left: 40, + child: IconButton( + icon: Transform.flip( + flipX: true, + child: Image.asset( + 'assets/images/chevron_right.png', + height: 40 + ) + ), + onPressed: () { + if (context.canPop()) { + context.pop(); + } else { + context.go('/login'); + } + }, + tooltip: 'Retour', + ), + ), + + // Contenu principal + isMobile + ? _buildMobileLayout(context, screenSize) + : _buildDesktopLayout(context, screenSize), + ], + ); + }, + ), + ); + } + + Widget _buildDesktopLayout(BuildContext context, Size screenSize) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: screenSize.width * 0.05), + child: Row( children: [ - // Fond papier - Positioned.fill( - child: Image.asset( - 'assets/images/paper2.png', - fit: BoxFit.cover, - repeat: ImageRepeat.repeat, + // Partie Gauche: Texte d'instruction centré + Expanded( + flex: 1, + child: Center( + child: Text( + 'Veuillez choisir votre\ntype de compte :', + style: GoogleFonts.merienda( + fontSize: 36, + fontWeight: FontWeight.bold, + color: Colors.black87, + height: 1.5, + ), + textAlign: TextAlign.center, + ), ), ), - - // Bouton Retour (chevron gauche) - Positioned( - top: 40, - left: 40, - child: IconButton( - icon: Transform.flip(flipX: true, child: Image.asset('assets/images/chevron_right.png', height: 40)), - onPressed: () { - if (context.canPop()) { - context.pop(); - } else { - context.go('/login'); - } - }, - tooltip: 'Retour', - ), - ), - - // Contenu principal en Row (Gauche / Droite) - Padding( - padding: EdgeInsets.symmetric(horizontal: screenSize.width * 0.05), - child: Row( - children: [ - // Partie Gauche: Texte d'instruction centré - Expanded( - flex: 1, - child: Center( - child: Text( - 'Veuillez choisir votre\ntype de compte :', - style: GoogleFonts.merienda( - fontSize: 36, - fontWeight: FontWeight.bold, - color: Colors.black87, - height: 1.5, - ), - textAlign: TextAlign.center, - ), + // Espace entre les deux parties + SizedBox(width: screenSize.width * 0.05), + + // Partie Droite: Carte rose avec les boutons + Expanded( + flex: 1, + child: Center( + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: screenSize.height * 0.78, + ), + child: AspectRatio( + aspectRatio: 2 / 3, + child: ChoiceCardWidget( + isMobile: false, + onParentSelected: () => context.go('/parent-register-step1'), + onAmSelected: () => context.go('/am-register-step1'), ), ), - // Espace entre les deux parties - SizedBox(width: screenSize.width * 0.05), - - // Partie Droite: Carte rose avec les boutons - Expanded( - flex: 1, - child: Center( - child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: screenSize.height * 0.78, // Augmenté pour éviter l'overflow - ), - child: AspectRatio( - aspectRatio: 2 / 3, - child: Container( - padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage(CardColorVertical.pink.path), - fit: BoxFit.fill, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - // Bouton "Parents" avec HoverReliefWidget appliqué uniquement à l'image - _buildChoiceButton( - context: context, - iconPath: 'assets/images/icon_parents.png', - label: 'Parents', - onPressed: () { - context.go('/parent-register-step1'); - }, - ), - // Bouton "Assistante Maternelle" avec HoverReliefWidget appliqué uniquement à l'image - _buildChoiceButton( - context: context, - iconPath: 'assets/images/icon_assmat.png', - label: 'Assistante Maternelle', - onPressed: () { - context.go('/am-register-step1'); - }, - ), - ], - ), - ), - ), - ), - ), - ), - ], + ), ), ), ], ), ); } -} -// Nouvelle méthode helper pour construire les boutons de choix -Widget _buildChoiceButton({ - required BuildContext context, - required String iconPath, - required String label, - required VoidCallback onPressed, -}) { - // TODO: Déterminer la couleur de base de card_rose.png et ajuster ces couleurs d'ombre - final Color baseRoseColor = Colors.pink.shade300; // Placeholder - final Color initialShadow = baseRoseColor.withAlpha(90); // Rose plus foncé et transparent pour l'ombre initiale - final Color hoverShadow = baseRoseColor.withAlpha(130); // Rose encore plus foncé pour l'ombre au survol - - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - HoverReliefWidget( - onPressed: onPressed, - borderRadius: BorderRadius.circular(15.0), - initialShadowColor: initialShadow, // Ombre rose initiale - hoverShadowColor: hoverShadow, // Ombre rose au survol - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Image.asset(iconPath, height: 140), + Widget _buildMobileLayout(BuildContext context, Size screenSize) { + return Center( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Veuillez choisir votre\ntype de compte :', + style: GoogleFonts.merienda( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.black87, + height: 1.3, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 30), + // Carte rose verticale adaptative + ChoiceCardWidget( + isMobile: true, + onParentSelected: () => context.go('/parent-register-step1'), + onAmSelected: () => context.go('/am-register-step1'), + ), + const SizedBox(height: 30), + // Bouton Précédent + SizedBox( + width: double.infinity, + child: HoverReliefWidget( + child: CustomNavigationButton( + text: 'Précédent', + style: NavigationButtonStyle.purple, + onPressed: () { + if (context.canPop()) { + context.pop(); + } else { + context.go('/login'); + } + }, + width: double.infinity, + height: 50, + fontSize: 16, + ), + ), + ), + ], ), ), - const SizedBox(height: 15), - Text( - label, - style: GoogleFonts.merienda( - fontSize: 26, - fontWeight: FontWeight.w600, - color: Colors.black.withOpacity(0.85), - ), - textAlign: TextAlign.center, - ), - ], - ); + ); + } } - -// --- La classe HoverChoiceButton peut maintenant être supprimée si elle n'est plus utilisée ailleurs --- -// class HoverChoiceButton extends StatefulWidget { ... } -// class _HoverChoiceButtonState extends State { ... } \ No newline at end of file diff --git a/frontend/lib/widgets/choice_card_widget.dart b/frontend/lib/widgets/choice_card_widget.dart new file mode 100644 index 0000000..02041cb --- /dev/null +++ b/frontend/lib/widgets/choice_card_widget.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import '../models/card_assets.dart'; +import 'hover_relief_widget.dart'; + +// Widget for the registration choice card (Parent vs AM) +class ChoiceCardWidget extends StatelessWidget { + final VoidCallback onParentSelected; + final VoidCallback onAmSelected; + final bool isMobile; + + const ChoiceCardWidget({ + super.key, + required this.onParentSelected, + required this.onAmSelected, + this.isMobile = false, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(CardColorVertical.pink.path), + fit: BoxFit.fill, + ), + borderRadius: BorderRadius.circular(15), + ), + child: Column( + mainAxisAlignment: isMobile ? MainAxisAlignment.center : MainAxisAlignment.spaceEvenly, + children: [ + _buildChoiceButton( + iconPath: 'assets/images/icon_parents.png', + label: 'Parents', + onPressed: onParentSelected, + isMobile: isMobile, + ), + SizedBox(height: isMobile ? 30 : 0), + _buildChoiceButton( + iconPath: 'assets/images/icon_assmat.png', + label: 'Assistante Maternelle', + onPressed: onAmSelected, + isMobile: isMobile, + ), + ], + ), + ); + } + + Widget _buildChoiceButton({ + required String iconPath, + required String label, + required VoidCallback onPressed, + required bool isMobile, + }) { + final Color baseRoseColor = Colors.pink.shade300; + final Color initialShadow = baseRoseColor.withAlpha(90); + final Color hoverShadow = baseRoseColor.withAlpha(130); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + HoverReliefWidget( + onPressed: onPressed, + borderRadius: BorderRadius.circular(15.0), + initialShadowColor: initialShadow, + hoverShadowColor: hoverShadow, + child: Padding( + padding: EdgeInsets.all(isMobile ? 6.0 : 8.0), + child: Image.asset(iconPath, height: isMobile ? 100 : 140), + ), + ), + SizedBox(height: isMobile ? 10 : 15), + Text( + label, + style: GoogleFonts.merienda( + fontSize: isMobile ? 20 : 26, + fontWeight: FontWeight.w600, + color: Colors.black.withOpacity(0.85), + ), + textAlign: TextAlign.center, + ), + ], + ); + } +}