import "package:flutter/material.dart"; import "package:google_fonts/google_fonts.dart"; import "../theme/ensup_colors.dart"; /// État possible d'un élément de checklist (départ ou retour). enum EtatChecklist { present, absent, deteriore } /// Case cliquable colorée selon l'état sélectionné (vert / rouge / jaune). class EtatBox extends StatelessWidget { const EtatBox({ super.key, required this.type, required this.selected, required this.onTap, }); final EtatChecklist 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 EtatChecklist.present: background = const Color(0xFFF0FDF4); border = const Color(0xFF86EFAC); contenu = const Icon(Icons.check, size: 16, color: Color(0xFF16A34A)); case EtatChecklist.absent: background = const Color(0xFFFEF2F2); border = const Color(0xFFFCA5A5); contenu = const Icon(Icons.close, size: 16, color: EnsupColors.red); case EtatChecklist.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, ), ); } } /// Tableau de checklist : une ligne par accessoire avec les 3 états possibles. class ChecklistTableau extends StatelessWidget { const ChecklistTableau({ super.key, required this.accessoires, required this.etats, required this.onChanged, }); final List accessoires; final List etats; final void Function(int index, EtatChecklist etat) onChanged; @override Widget build(BuildContext context) { return Column( children: [ _entete(), for (var i = 0; i < 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, 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( accessoires[index], style: GoogleFonts.titilliumWeb(fontSize: 14, color: EnsupColors.text2), ), ), _case(index, EtatChecklist.present), _case(index, EtatChecklist.absent), _case(index, EtatChecklist.deteriore), ], ), ); } Widget _case(int index, EtatChecklist type) { return SizedBox( width: 72, child: Center( child: EtatBox( type: type, selected: etats[index] == type, onTap: () => onChanged(index, type), ), ), ); } } /// Encadré d'instructions / rappel à côté d'une checklist. class ChecklistInstructions extends StatelessWidget { const ChecklistInstructions({super.key, required this.titre, required this.texte}); final String titre; final String texte; @override Widget build(BuildContext context) { return 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( titre.toUpperCase(), style: GoogleFonts.darkerGrotesque( fontSize: 12, fontWeight: FontWeight.w700, color: EnsupColors.muted, letterSpacing: 0.6, ), ), const SizedBox(height: 8), Text( texte, style: GoogleFonts.titilliumWeb(fontSize: 13, color: EnsupColors.text2, height: 1.6), ), ], ), ); } } /// Zone de commentaire optionnel sous une checklist. class ChecklistCommentaire extends StatelessWidget { const ChecklistCommentaire({ super.key, this.controller, this.hint = "Commentaire ou observation optionnelle...", }); final TextEditingController? controller; final String hint; @override Widget build(BuildContext context) { return TextField( controller: controller, maxLines: 4, style: GoogleFonts.titilliumWeb(fontSize: 13, color: EnsupColors.text), decoration: InputDecoration( hintText: hint, 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), ), ), ); } }