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: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(
@ -24,12 +34,19 @@ class RegisterChoiceScreen extends StatelessWidget {
),
),
// Bouton Retour (chevron gauche)
// 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)),
icon: Transform.flip(
flipX: true,
child: Image.asset(
'assets/images/chevron_right.png',
height: 40
)
),
onPressed: () {
if (context.canPop()) {
context.pop();
@ -41,8 +58,19 @@ class RegisterChoiceScreen extends StatelessWidget {
),
),
// Contenu principal en Row (Gauche / Droite)
Padding(
// 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: [
@ -71,94 +99,72 @@ class RegisterChoiceScreen extends StatelessWidget {
child: Center(
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: screenSize.height * 0.78, // Augmenté pour éviter l'overflow
maxHeight: screenSize.height * 0.78,
),
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');
},
),
],
child: ChoiceCardWidget(
isMobile: false,
onParentSelected: () => context.go('/parent-register-step1'),
onAmSelected: () => 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,
Widget _buildMobileLayout(BuildContext context, Size screenSize) {
return Center(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
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(
label,
'Veuillez choisir votre\ntype de compte :',
style: GoogleFonts.merienda(
fontSize: 26,
fontWeight: FontWeight.w600,
color: Colors.black.withOpacity(0.85),
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,
),
),
),
],
),
),
);
}
// --- 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,
),
],
);
}
}