diff --git a/frontend/lib/screens/am/am_dashboard_screen.dart b/frontend/lib/screens/am/am_dashboard_screen.dart index f245013..5a2201e 100644 --- a/frontend/lib/screens/am/am_dashboard_screen.dart +++ b/frontend/lib/screens/am/am_dashboard_screen.dart @@ -1,11 +1,15 @@ import 'package:flutter/material.dart'; +import 'package:p_tits_pas/models/couple_garde.dart'; import 'package:p_tits_pas/models/user.dart'; import 'package:p_tits_pas/services/auth_service.dart'; +import 'package:p_tits_pas/services/couple_garde_service.dart'; +import 'package:p_tits_pas/widgets/quotidien/couple_selector_bandeau.dart'; import 'package:p_tits_pas/widgets/quotidien/quotidien_shell.dart'; import 'package:p_tits_pas/widgets/quotidien/quotidien_theme.dart'; +import 'package:p_tits_pas/screens/home/parent_screen/agenda_absences_stub.dart'; /// Dashboard assistante maternelle – coquille 3 colonnes quotidien (#169). -/// Colonne gauche : sélecteur de couple enfant–parent(s) (à venir #170). +/// Colonne gauche : sélecteur de couple enfant–parent(s) (#170). /// Métier cartes / blog / messagerie : tickets C/D/E. class AmDashboardScreen extends StatefulWidget { const AmDashboardScreen({super.key}); @@ -18,10 +22,16 @@ class _AmDashboardScreenState extends State { QuotidienNavSection _section = QuotidienNavSection.liaison; AppUser? _user; + List _couples = const []; + String? _selectedCoupleId; + bool _couplesLoading = true; + String? _couplesError; + @override void initState() { super.initState(); _loadUser(); + _loadCouples(); } Future _loadUser() async { @@ -29,6 +39,53 @@ class _AmDashboardScreenState extends State { if (mounted) setState(() => _user = user); } + Future _loadCouples() async { + setState(() { + _couplesLoading = true; + _couplesError = null; + }); + try { + // TODO: Pour l'instant on utilise le service générique de test (CoupleGardeService.getCouplesGarde). + // Dans le futur, l'API pour l'AM (enfants_accueillis) fournira la vraie liste. + final res = await CoupleGardeService.getCouplesGarde(); + if (!mounted) return; + setState(() { + _couples = res.couples; + _selectedCoupleId = res.coupleCourant?.id; + _couplesLoading = false; + }); + } catch (e) { + if (!mounted) return; + setState(() { + _couplesError = e.toString().replaceFirst('Exception: ', ''); + _couplesLoading = false; + }); + } + } + + Future _selectCouple(CoupleGarde couple) async { + if (couple.id == _selectedCoupleId) return; + setState(() => _selectedCoupleId = couple.id); + try { + final res = await CoupleGardeService.definirCoupleCourant(couple.id); + if (!mounted) return; + setState(() { + _couples = res.couples; + _selectedCoupleId = res.coupleCourant?.id ?? couple.id; + }); + } catch (e) { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + "Impossible de changer d'enfant : " + '${e.toString().replaceFirst('Exception: ', '')}', + ), + ), + ); + } + } + String get _displayName { final n = _user?.fullName.trim() ?? ''; if (n.isNotEmpty) return n; @@ -54,11 +111,13 @@ class _AmDashboardScreenState extends State { onSettingsTap: () => _soon('Paramètres'), // L'AM n'a pas de bouton "Recherche AM" dans le bandeau onSearchAmTap: null, - leftColumn: const QuotidienColumnPlaceholder( - title: 'Cartes', - subtitle: - 'Couple enfant–parent(s) et flux de cartes\n(à brancher — tickets #170 / #174).', - icon: Icons.style_outlined, + leftColumn: _LeftColumn( + couples: _couples, + selectedCoupleId: _selectedCoupleId, + loading: _couplesLoading, + error: _couplesError, + onRetry: _loadCouples, + onCoupleSelected: _selectCouple, ), centerColumn: const QuotidienColumnPlaceholder( title: 'Blog', @@ -72,10 +131,7 @@ class _AmDashboardScreenState extends State { 'Mess. Parents · Mess. RPE\n(à brancher — ticket #185).', icon: Icons.chat_bubble_outline, ), - agendaBody: const QuotidienStubPage( - title: 'Agenda', - message: 'Agenda — contenu à venir (stub #187).', - ), + agendaBody: AgendaAbsencesStub(placementId: _selectedCoupleId), contratBody: const QuotidienStubPage( title: 'Contrat', message: 'Contrat — contenu à venir (stub #187).', @@ -84,3 +140,51 @@ class _AmDashboardScreenState extends State { } } +class _LeftColumn extends StatelessWidget { + final List couples; + final String? selectedCoupleId; + final bool loading; + final String? error; + final VoidCallback onRetry; + final ValueChanged onCoupleSelected; + + const _LeftColumn({ + required this.couples, + required this.selectedCoupleId, + required this.loading, + required this.error, + required this.onRetry, + required this.onCoupleSelected, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + CoupleSelectorBandeau( + mode: CoupleBandeauMode.assistanteMaternelle, + couples: couples, + selectedCoupleId: selectedCoupleId, + loading: loading, + errorMessage: error, + onRetry: onRetry, + onCoupleSelected: onCoupleSelected, + ), + const SizedBox(height: 14), + const Expanded( + child: QuotidienColumnPlaceholder( + title: 'Cartes', + subtitle: + 'Absences, congés AM, sorties à valider\n(à brancher — ticket #174).', + icon: Icons.style_outlined, + ), + ), + ], + ), + ); + } +} + diff --git a/frontend/lib/widgets/quotidien/couple_selector_bandeau.dart b/frontend/lib/widgets/quotidien/couple_selector_bandeau.dart index b34aa00..963d8b3 100644 --- a/frontend/lib/widgets/quotidien/couple_selector_bandeau.dart +++ b/frontend/lib/widgets/quotidien/couple_selector_bandeau.dart @@ -135,6 +135,16 @@ class _CoupleCard extends StatelessWidget { @override Widget build(BuildContext context) { + // Parent mode: enfant | AM + // AM mode: enfant | parent(s) + final isParentMode = mode == CoupleBandeauMode.parent; + final fallbackRoleIcon = isParentMode ? Icons.volunteer_activism : Icons.person_outline; + final fallbackRoleName = isParentMode ? 'Nounou' : 'Parent'; + + // TODO: In AM mode, we should ideally display "parent1+parent2 empilés" or centered. + // For now, CoupleGarde only gives us `am` (which in AM mode might just represent one parent, or the system needs to feed both parents here). + // Assuming backend will populate `am` field with the parent data when called by AM. + return Container( height: 90, decoration: BoxDecoration( @@ -175,14 +185,8 @@ class _CoupleCard extends StatelessWidget { photoUrl: couple.am.photoUrl, name: (couple.am.prenom != null && couple.am.prenom!.isNotEmpty) ? couple.am.prenom! - : couple.am.displayName( - fallback: mode == CoupleBandeauMode.parent - ? 'Nounou' - : 'Parent', - ), - fallbackIcon: mode == CoupleBandeauMode.parent - ? Icons.volunteer_activism - : Icons.person_outline, + : couple.am.displayName(fallback: fallbackRoleName), + fallbackIcon: fallbackRoleIcon, ), ), ),