feat(front): implement AM dashboard shell with 3 columns (#169)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-24 12:13:20 +02:00
co-authored by Cursor
parent 2380aa9826
commit 8b1b9e7917
2 changed files with 63 additions and 54 deletions
@@ -1,11 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:p_tits_pas/models/user.dart'; import 'package:p_tits_pas/models/user.dart';
import 'package:p_tits_pas/services/auth_service.dart'; import 'package:p_tits_pas/services/auth_service.dart';
import 'package:p_tits_pas/widgets/app_footer.dart'; import 'package:p_tits_pas/widgets/quotidien/quotidien_shell.dart';
import 'package:p_tits_pas/widgets/dashboard/dashboard_bandeau.dart'; import 'package:p_tits_pas/widgets/quotidien/quotidien_theme.dart';
/// Dashboard assistante maternelle – page blanche avec bandeau générique. /// Dashboard assistante maternelle – coquille 3 colonnes quotidien (#169).
/// Contenu détaillé à venir. /// Colonne gauche : sélecteur de couple enfant–parent(s) (à venir #170).
/// Métier cartes / blog / messagerie : tickets C/D/E.
class AmDashboardScreen extends StatefulWidget { class AmDashboardScreen extends StatefulWidget {
const AmDashboardScreen({super.key}); const AmDashboardScreen({super.key});
@@ -14,7 +15,7 @@ class AmDashboardScreen extends StatefulWidget {
} }
class _AmDashboardScreenState extends State<AmDashboardScreen> { class _AmDashboardScreenState extends State<AmDashboardScreen> {
int selectedTabIndex = 0; QuotidienNavSection _section = QuotidienNavSection.liaison;
AppUser? _user; AppUser? _user;
@override @override
@@ -28,51 +29,58 @@ class _AmDashboardScreenState extends State<AmDashboardScreen> {
if (mounted) setState(() => _user = user); if (mounted) setState(() => _user = user);
} }
String get _displayName {
final n = _user?.fullName.trim() ?? '';
if (n.isNotEmpty) return n;
final email = _user?.email.trim() ?? '';
if (email.isNotEmpty) return email.split('@').first;
return 'Assistante maternelle';
}
void _soon(String label) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('$label — à venir')),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return QuotidienShell(
appBar: PreferredSize( selectedSection: _section,
preferredSize: const Size.fromHeight(60.0), onSectionSelected: (s) => setState(() => _section = s),
child: DashboardBandeau( userDisplayName: _displayName,
tabItems: const [
DashboardTabItem(label: 'Mon tableau de bord'),
DashboardTabItem(label: 'Paramètres'),
],
selectedTabIndex: selectedTabIndex,
onTabSelected: (index) => setState(() => selectedTabIndex = index),
userDisplayName: _user?.fullName.isNotEmpty == true
? _user!.fullName
: 'Assistante maternelle',
userEmail: _user?.email, userEmail: _user?.email,
userRole: _user?.role, onProfileTap: () => _soon('Profil'),
onProfileTap: () { onSettingsTap: () => _soon('Paramètres'),
ScaffoldMessenger.of(context).showSnackBar( // L'AM n'a pas de bouton "Recherche AM" dans le bandeau
const SnackBar( onSearchAmTap: null,
content: Text('Modification du profil – à venir')), leftColumn: const QuotidienColumnPlaceholder(
); title: 'Cartes',
}, subtitle:
onSettingsTap: () { 'Couple enfant–parent(s) et flux de cartes\n(à brancher — tickets #170 / #174).',
ScaffoldMessenger.of(context).showSnackBar( icon: Icons.style_outlined,
const SnackBar(content: Text('Paramètres – à venir')),
);
},
onLogout: () {},
showLogoutConfirmation: true,
), ),
centerColumn: const QuotidienColumnPlaceholder(
title: 'Blog',
subtitle:
'Fil du quotidien (affichage par défaut)\n(à brancher — ticket #179).',
icon: Icons.auto_stories_outlined,
), ),
body: Column( rightColumn: const QuotidienColumnPlaceholder(
children: [ title: 'Messagerie',
Expanded( subtitle:
child: Center( 'Mess. Parents · Mess. RPE\n(à brancher — ticket #185).',
child: Text( icon: Icons.chat_bubble_outline,
'Dashboard AM – à venir',
style: Theme.of(context).textTheme.titleLarge,
), ),
agendaBody: const QuotidienStubPage(
title: 'Agenda',
message: 'Agenda — contenu à venir (stub #187).',
), ),
), contratBody: const QuotidienStubPage(
const AppFooter(), title: 'Contrat',
], message: 'Contrat — contenu à venir (stub #187).',
), ),
); );
} }
} }
@@ -183,6 +183,7 @@ class _UserMenu extends StatelessWidget {
title: Text('Profil'), title: Text('Profil'),
), ),
), ),
if (onSearchAmTap != null)
const PopupMenuItem( const PopupMenuItem(
value: 'search_am', value: 'search_am',
child: ListTile( child: ListTile(