import "package:flutter/material.dart"; import "package:google_fonts/google_fonts.dart"; import "../demo_identity.dart"; import "../theme/ensup_colors.dart"; import "../models/materiel_item.dart"; import "../services/emprunt_service.dart"; import "../widgets/ensup_top_bar.dart"; import "../widgets/brand_corners.dart"; import "../widgets/etat_checklist.dart"; import "confirmation_screen.dart"; /// 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 _elements = widget.item.accessoires.isEmpty ? [widget.item.nom] : widget.item.accessoires; late final List _etats = List.filled( _elements.length, EtatChecklist.present, ); final TextEditingController _commentaireController = TextEditingController(); bool _envoiEnCours = false; @override void dispose() { _commentaireController.dispose(); super.dispose(); } Future _valider() async { setState(() => _envoiEnCours = true); final anomalies = []; for (var i = 0; i < _etats.length; i++) { if (_etats[i] == EtatChecklist.absent) { anomalies.add("${_elements[i]} absent au départ"); } else if (_etats[i] == EtatChecklist.deteriore) { anomalies.add("${_elements[i]} détérioré au départ"); } } final note = anomalies.isEmpty ? null : anomalies.join(", "); try { final emprunt = await EmpruntService.creerEmprunt( materielId: widget.item.id, commentaireDepart: _commentaireController.text, elements: _elements.asMap().entries.map((entry) { return { "nomElement": entry.value, "etat": _etatApi(_etats[entry.key]), "quantiteConstatee": _etats[entry.key] == EtatChecklist.absent ? 0 : 1, }; }).toList(), ); if (!mounted) { return; } Navigator.of(context).push( MaterialPageRoute( builder: (_) => ConfirmationScreen(emprunt: emprunt, note: note), ), ); } catch (error) { if (!mounted) { return; } ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(error.toString())), ); } finally { if (mounted) { setState(() => _envoiEnCours = false); } } } String _etatApi(EtatChecklist etat) { switch (etat) { case EtatChecklist.present: return "PRESENT"; case EtatChecklist.absent: return "ABSENT"; case EtatChecklist.deteriore: return "DETERIORE"; } } @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: DemoIdentity.campusTag, userName: DemoIdentity.userName, userInitials: DemoIdentity.userInitials, 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), ChecklistTableau( accessoires: _elements, etats: _etats, onChanged: (index, etat) => setState(() => _etats[index] = etat), ), ], ); } Widget _colonneDroite() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ChecklistInstructions( titre: "Instructions", texte: "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.", ), const SizedBox(height: 14), ChecklistCommentaire(controller: _commentaireController), const SizedBox(height: 14), SizedBox( width: double.infinity, child: FilledButton.icon( onPressed: _envoiEnCours ? null : _valider, icon: _envoiEnCours ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white), ) : const Icon(Icons.check, size: 18), label: Text( _envoiEnCours ? "Enregistrement..." : "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)), ), ), ), ], ); } }