feat(frontend): Adapt RegisterChoiceScreen for mobile (Closes #83)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
MARTIN Julien 2026-02-07 17:43:17 +01:00
parent 0d88597bb6
commit 030ef81038
2 changed files with 231 additions and 138 deletions

View File

@ -1,19 +1,29 @@
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; // Pour la rotation du chevron
import '../../widgets/hover_relief_widget.dart'; // Import du widget générique import '../../widgets/choice_card_widget.dart'; // Import du nouveau widget
import '../../models/card_assets.dart'; // Import des enums de cartes import '../../widgets/custom_navigation_button.dart';
import '../../widgets/hover_relief_widget.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
// Screen for choosing between Parent and AM registration
class RegisterChoiceScreen extends StatelessWidget { class RegisterChoiceScreen extends StatelessWidget {
const RegisterChoiceScreen({super.key}); const RegisterChoiceScreen({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
return Scaffold( 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: [ children: [
// Fond papier // Fond papier
Positioned.fill( Positioned.fill(
@ -24,12 +34,19 @@ class RegisterChoiceScreen extends StatelessWidget {
), ),
), ),
// Bouton Retour (chevron gauche) // Bouton Retour (chevron gauche) - Desktop uniquement
if (!isMobile)
Positioned( Positioned(
top: 40, top: 40,
left: 40, left: 40,
child: IconButton( child: IconButton(
icon: Transform.flip(flipX: true, child: Image.asset('assets/images/chevron_right.png', height: 40)), icon: Transform.flip(
flipX: true,
child: Image.asset(
'assets/images/chevron_right.png',
height: 40
)
),
onPressed: () { onPressed: () {
if (context.canPop()) { if (context.canPop()) {
context.pop(); context.pop();
@ -41,8 +58,19 @@ class RegisterChoiceScreen extends StatelessWidget {
), ),
), ),
// Contenu principal en Row (Gauche / Droite) // Contenu principal
Padding( isMobile
? _buildMobileLayout(context, screenSize)
: _buildDesktopLayout(context, screenSize),
],
);
},
),
);
}
Widget _buildDesktopLayout(BuildContext context, Size screenSize) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: screenSize.width * 0.05), padding: EdgeInsets.symmetric(horizontal: screenSize.width * 0.05),
child: Row( child: Row(
children: [ children: [
@ -71,94 +99,72 @@ class RegisterChoiceScreen extends StatelessWidget {
child: Center( child: Center(
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: screenSize.height * 0.78, // Augmenté pour éviter l'overflow maxHeight: screenSize.height * 0.78,
), ),
child: AspectRatio( child: AspectRatio(
aspectRatio: 2 / 3, aspectRatio: 2 / 3,
child: Container( child: ChoiceCardWidget(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), isMobile: false,
decoration: BoxDecoration( onParentSelected: () => context.go('/parent-register-step1'),
image: DecorationImage( onAmSelected: () => context.go('/am-register-step1'),
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 _buildMobileLayout(BuildContext context, Size screenSize) {
Widget _buildChoiceButton({ return Center(
required BuildContext context, child: SingleChildScrollView(
required String iconPath, padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 20),
required String label, child: Column(
required VoidCallback onPressed, mainAxisAlignment: MainAxisAlignment.center,
}) {
// 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: [ 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),
),
),
const SizedBox(height: 15),
Text( Text(
label, 'Veuillez choisir votre\ntype de compte :',
style: GoogleFonts.merienda( style: GoogleFonts.merienda(
fontSize: 26, fontSize: 24,
fontWeight: FontWeight.w600, fontWeight: FontWeight.bold,
color: Colors.black.withOpacity(0.85), color: Colors.black87,
height: 1.3,
), ),
textAlign: TextAlign.center, 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,
),
),
),
], ],
),
),
); );
}
} }
// --- La classe HoverChoiceButton peut maintenant être supprimée si elle n'est plus utilisée ailleurs ---
// class HoverChoiceButton extends StatefulWidget { ... }
// class _HoverChoiceButtonState extends State<HoverChoiceButton> { ... }

View File

@ -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,
),
],
);
}
}