import "package:flutter/material.dart"; import "package:google_fonts/google_fonts.dart"; import "../theme/ensup_colors.dart"; import "../models/materiel_item.dart"; import "../widgets/ensup_top_bar.dart"; import "../widgets/brand_corners.dart"; enum _Etat { present, absent, deteriore } /// Checklist de départ (RG11) : l'étudiant indique l'état de chaque accessoire /// attendu avant de confirmer l'emprunt. class ChecklistDepartScreen extends StatefulWidget { const ChecklistDepartScreen({super.key, required this.item}); final MaterielItem item; @override State createState() => _ChecklistDepartScreenState(); } class _ChecklistDepartScreenState extends State { late final List<_Etat> _etats = List<_Etat>.filled( widget.item.accessoires.length, _Etat.present, ); void _valider() { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Confirmation de l'emprunt — écran à venir")), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: EnsupColors.soft, body: Stack( children: [ Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 1280, maxHeight: 820), child: Container( margin: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: EnsupColors.text.withValues(alpha: 0.14), blurRadius: 60, offset: const Offset(0, 18), ), ], ), clipBehavior: Clip.antiAlias, child: Column( children: [ EnsupTopBar( brandText: "Checklist de départ", campusTag: "Paris · Ensitech", userName: "Lucas Martin", userInitials: "LM", onBack: () => Navigator.of(context).pop(), ), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 28), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded(flex: 3, child: _colonneGauche()), const SizedBox(width: 20), Expanded(flex: 2, child: _colonneDroite()), ], ), ), ), ], ), ), ), ), const Positioned.fill(child: BrandCorners()), ], ), ); } Widget _colonneGauche() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: EnsupColors.soft, borderRadius: BorderRadius.circular(12), border: Border.all(color: EnsupColors.cyan.withValues(alpha: 0.15), width: 1.5), ), child: Row( children: [ Container( width: 38, height: 38, decoration: BoxDecoration( color: EnsupColors.cyan.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(9), ), child: Icon(widget.item.icon, color: EnsupColors.cyan, size: 18), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.item.nom, style: GoogleFonts.darkerGrotesque(fontWeight: FontWeight.w800, fontSize: 16), ), Text( "Vérifiez chaque élément physiquement avant de valider", style: GoogleFonts.titilliumWeb(fontSize: 12, color: EnsupColors.muted), ), ], ), ), ], ), ), const SizedBox(height: 16), _entete(), for (var i = 0; i < widget.item.accessoires.length; i++) _ligne(i), ], ); } Widget _entete() { return Container( padding: const EdgeInsets.symmetric(vertical: 10), decoration: const BoxDecoration( border: Border(bottom: BorderSide(color: EnsupColors.line, width: 2)), ), child: Row( children: [ Expanded(child: _texteEntete("Élément")), _colonneEntete("Présent"), _colonneEntete("Absent"), _colonneEntete("Détérioré"), ], ), ); } Widget _texteEntete(String label) { return Text( label.toUpperCase(), style: GoogleFonts.darkerGrotesque( fontSize: 12, fontWeight: FontWeight.w700, color: EnsupColors.muted, letterSpacing: 0.6, ), ); } Widget _colonneEntete(String label) { return SizedBox(width: 72, child: Center(child: _texteEntete(label))); } Widget _ligne(int index) { return Container( padding: const EdgeInsets.symmetric(vertical: 10), decoration: const BoxDecoration( border: Border(bottom: BorderSide(color: EnsupColors.line)), ), child: Row( children: [ Expanded( child: Text( widget.item.accessoires[index], style: GoogleFonts.titilliumWeb(fontSize: 14, color: EnsupColors.text2), ), ), _caseEtat(index, _Etat.present), _caseEtat(index, _Etat.absent), _caseEtat(index, _Etat.deteriore), ], ), ); } Widget _caseEtat(int index, _Etat type) { return SizedBox( width: 72, child: Center( child: _EtatBox( type: type, selected: _etats[index] == type, onTap: () => setState(() => _etats[index] = type), ), ), ); } Widget _colonneDroite() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: EnsupColors.blue2.withValues(alpha: 0.05), borderRadius: BorderRadius.circular(10), border: Border.all(color: EnsupColors.blue2.withValues(alpha: 0.15), width: 1.5), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "INSTRUCTIONS", style: GoogleFonts.darkerGrotesque( fontSize: 12, fontWeight: FontWeight.w700, color: EnsupColors.muted, letterSpacing: 0.6, ), ), const SizedBox(height: 8), Text( "Vérifiez physiquement chaque élément du kit et indiquez son état : " "Présent, Absent ou Détérioré. Signalez tout élément manquant ou " "endommagé pour éviter tout litige au retour.", style: GoogleFonts.titilliumWeb( fontSize: 13, color: EnsupColors.text2, height: 1.6, ), ), ], ), ), const SizedBox(height: 14), TextField( maxLines: 4, style: GoogleFonts.titilliumWeb(fontSize: 13, color: EnsupColors.text), decoration: InputDecoration( hintText: "Commentaire ou observation optionnelle...", hintStyle: GoogleFonts.titilliumWeb(fontSize: 13, color: EnsupColors.muted), filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(9), borderSide: const BorderSide(color: EnsupColors.line, width: 1.5), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(9), borderSide: const BorderSide(color: EnsupColors.cyan, width: 1.5), ), ), ), const SizedBox(height: 14), SizedBox( width: double.infinity, child: FilledButton.icon( onPressed: _valider, icon: const Icon(Icons.check, size: 18), label: Text( "Valider la checklist et confirmer l'emprunt", textAlign: TextAlign.center, style: GoogleFonts.darkerGrotesque(fontWeight: FontWeight.w700, fontSize: 15), ), style: FilledButton.styleFrom( backgroundColor: EnsupColors.blue3, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), ), ), ), ], ); } } class _EtatBox extends StatelessWidget { const _EtatBox({required this.type, required this.selected, required this.onTap}); final _Etat type; final bool selected; final VoidCallback onTap; @override Widget build(BuildContext context) { var background = Colors.white; var border = EnsupColors.line; Widget? contenu; if (selected) { switch (type) { case _Etat.present: background = const Color(0xFFF0FDF4); border = const Color(0xFF86EFAC); contenu = const Icon(Icons.check, size: 16, color: Color(0xFF16A34A)); case _Etat.absent: background = const Color(0xFFFEF2F2); border = const Color(0xFFFCA5A5); contenu = const Icon(Icons.close, size: 16, color: EnsupColors.red); case _Etat.deteriore: background = const Color(0xFFFFFBEB); border = const Color(0xFFFDE68A); contenu = const Icon(Icons.priority_high, size: 16, color: Color(0xFFD97706)); } } return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(8), child: Container( width: 36, height: 36, decoration: BoxDecoration( color: background, borderRadius: BorderRadius.circular(8), border: Border.all(color: border, width: 2), ), child: contenu, ), ); } }