import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:p_tits_pas/widgets/app_footer.dart'; import 'package:p_tits_pas/widgets/quotidien/quotidien_bandeau.dart'; import 'package:p_tits_pas/widgets/quotidien/quotidien_theme.dart'; /// Coquille « Cahier de liaison » quotidien 3 colonnes + bandeau (#166). /// L’AM (#169) réutilise ce widget en injectant ses slots. class QuotidienShell extends StatelessWidget { final QuotidienNavSection selectedSection; final ValueChanged onSectionSelected; final String userDisplayName; final String? userEmail; final VoidCallback? onProfileTap; final VoidCallback? onSearchAmTap; final VoidCallback? onSettingsTap; final VoidCallback? onLogout; /// Colonne gauche (couple + cartes + actions). final Widget leftColumn; /// Colonne milieu (blog). final Widget centerColumn; /// Colonne droite (messagerie). final Widget rightColumn; /// Corps affiché hors Cahier de liaison (Agenda / Contrat stubs). final Widget? agendaBody; final Widget? contratBody; const QuotidienShell({ super.key, required this.selectedSection, required this.onSectionSelected, required this.userDisplayName, required this.leftColumn, required this.centerColumn, required this.rightColumn, this.userEmail, this.onProfileTap, this.onSearchAmTap, this.onSettingsTap, this.onLogout, this.agendaBody, this.contratBody, }); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: QuotidienTheme.ivory, body: Container( decoration: QuotidienTheme.paperBackground(), child: Column( children: [ QuotidienBandeau( selectedSection: selectedSection, onSectionSelected: onSectionSelected, userDisplayName: userDisplayName, userEmail: userEmail, onProfileTap: onProfileTap, onSearchAmTap: onSearchAmTap, onSettingsTap: onSettingsTap, onLogout: onLogout, ), const QuotidienPencilDivider(), Expanded(child: _bodyForSection(context)), const QuotidienPencilDivider(), const AppFooter(showTopBorder: false), ], ), ), ); } Widget _bodyForSection(BuildContext context) { switch (selectedSection) { case QuotidienNavSection.liaison: return _ThreeColumns( left: leftColumn, center: centerColumn, right: rightColumn, ); case QuotidienNavSection.agenda: return agendaBody ?? const QuotidienStubPage( title: 'Agenda', message: 'Page Agenda — à venir.', ); case QuotidienNavSection.contrat: return contratBody ?? const QuotidienStubPage( title: 'Contrat', message: 'Page Contrat — à venir.', ); } } } /// Trait « crayon gris » dessiné à la main : sépare bandeau / corps / footer /// (horizontal) et les 3 colonnes (vertical). Le PNG (2400×28) est étiré dans /// le sens du trait seulement : sur un trait, c'est invisible. class QuotidienPencilDivider extends StatelessWidget { final Axis axis; /// Épaisseur de la zone du trait (hauteur si horizontal, largeur sinon). final double thickness; final EdgeInsets padding; const QuotidienPencilDivider({ super.key, this.axis = Axis.horizontal, this.thickness = 14, this.padding = const EdgeInsets.symmetric(horizontal: 24), }); const QuotidienPencilDivider.vertical({ super.key, this.thickness = 14, this.padding = const EdgeInsets.symmetric(vertical: 16), }) : axis = Axis.vertical; @override Widget build(BuildContext context) { final horizontal = axis == Axis.horizontal; return Padding( padding: padding, child: SizedBox( width: horizontal ? double.infinity : thickness, height: horizontal ? thickness : double.infinity, child: Image.asset( horizontal ? QuotidienTheme.pencilLineAsset : QuotidienTheme.pencilLineVerticalAsset, fit: BoxFit.fill, filterQuality: FilterQuality.medium, ), ), ); } } class _ThreeColumns extends StatelessWidget { final Widget left; final Widget center; final Widget right; const _ThreeColumns({ required this.left, required this.center, required this.right, }); @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { final wide = constraints.maxWidth >= 900; if (!wide) { // Socle mobile temporaire (#188 = swipe dédié) : pile verticale. return ListView( padding: const EdgeInsets.fromLTRB(12, 4, 12, 12), children: [ _ColumnPanel(child: left), const QuotidienPencilDivider( padding: EdgeInsets.symmetric(horizontal: 32, vertical: 4), ), _ColumnPanel(child: center), const QuotidienPencilDivider( padding: EdgeInsets.symmetric(horizontal: 32, vertical: 4), ), _ColumnPanel(child: right), ], ); } return Padding( padding: const EdgeInsets.fromLTRB(16, 4, 16, 12), child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded(child: _ColumnPanel(child: left)), const QuotidienPencilDivider.vertical(), Expanded(child: _ColumnPanel(child: center)), const QuotidienPencilDivider.vertical(), Expanded(child: _ColumnPanel(child: right)), ], ), ); }, ); } } /// Panneau colonne (carte pastel semi-transparente). class _ColumnPanel extends StatelessWidget { final Widget child; const _ColumnPanel({required this.child}); @override Widget build(BuildContext context) { return Container( // Pas de bordure Material : la séparation est assurée par les traits // crayon, on garde juste un léger fond. decoration: BoxDecoration( color: QuotidienTheme.columnCardFill.withOpacity(0.82), borderRadius: BorderRadius.circular(16), ), clipBehavior: Clip.antiAlias, child: child, ); } } /// Placeholder de colonne métier (branchable par tickets C/D/E). class QuotidienColumnPlaceholder extends StatelessWidget { final String title; final String subtitle; final IconData icon; const QuotidienColumnPlaceholder({ super.key, required this.title, required this.subtitle, required this.icon, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ Icon(icon, color: QuotidienTheme.lavender, size: 22), const SizedBox(width: 8), Text( title, style: GoogleFonts.merienda( fontSize: 18, fontWeight: FontWeight.w600, color: QuotidienTheme.ink, ), ), ], ), const SizedBox(height: 12), Expanded( child: Center( child: Text( subtitle, textAlign: TextAlign.center, style: GoogleFonts.merriweather( fontSize: 13, color: QuotidienTheme.muted, height: 1.4, ), ), ), ), ], ), ); } } /// Stub pleine page (Agenda / Contrat) — contenu riche hors #166. class QuotidienStubPage extends StatelessWidget { final String title; final String message; const QuotidienStubPage({ super.key, required this.title, required this.message, }); @override Widget build(BuildContext context) { return Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Container( margin: const EdgeInsets.all(24), padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 32), decoration: BoxDecoration( color: Colors.white.withOpacity(0.85), borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey.shade300), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( title, style: GoogleFonts.merienda( fontSize: 22, fontWeight: FontWeight.w600, color: QuotidienTheme.ink, ), ), const SizedBox(height: 12), Text( message, textAlign: TextAlign.center, style: GoogleFonts.merriweather( fontSize: 14, color: QuotidienTheme.muted, ), ), ], ), ), ), ); } }