diff --git a/frontend/assets/images/flacon.png b/frontend/assets/images/flacon.png new file mode 100644 index 0000000..8c09209 Binary files /dev/null and b/frontend/assets/images/flacon.png differ diff --git a/frontend/assets/images/pansement.png b/frontend/assets/images/pansement.png new file mode 100644 index 0000000..b26ab83 Binary files /dev/null and b/frontend/assets/images/pansement.png differ diff --git a/frontend/assets/images/thermo_verre.png b/frontend/assets/images/thermo_verre.png new file mode 100644 index 0000000..69c353c Binary files /dev/null and b/frontend/assets/images/thermo_verre.png differ diff --git a/frontend/lib/models/carte_bulle.dart b/frontend/lib/models/carte_bulle.dart index 54e851e..10df0c9 100644 --- a/frontend/lib/models/carte_bulle.dart +++ b/frontend/lib/models/carte_bulle.dart @@ -110,11 +110,56 @@ class CarteBulle { String? get dateDebut => payload['date_debut']?.toString(); String? get dateFin => payload['date_fin']?.toString(); String? get motif => payload['motif']?.toString(); - - /// Helper pour extraire les informations de soin - String? get resumerSoin { + + /// Heure de relevé (payload soins), format API `HH:mm`. + String? get heureReleve => payload['heure_releve']?.toString(); + + /// Heure affichable `18h19` (depuis `heure_releve`). + String? get heureReleveAffichee { + final h = heureReleve?.trim(); + if (h == null || h.isEmpty) return null; + final parts = h.split(':'); + if (parts.length < 2) return h; + return '${parts[0]}h${parts[1]}'; + } + + /// Ligne détail soin (sans date/heure) — sous la ligne agenda. + String? get detailSoin { if (!isSoinEnfant) return null; - return payload['motif']?.toString(); + final st = payload['sous_type']?.toString(); + if (st == 'fievre') { + final t = payload['temperature_c']; + final med = payload['medicament_donne']?.toString().trim(); + String? temp; + if (t is num) { + temp = t.toStringAsFixed(1).replaceAll('.', ','); + } else if (t != null) { + temp = t.toString().replaceAll('.', ','); + } + if (temp == null || temp.isEmpty) return motif; + var s = '$temp °C'; + if (med != null && med.isNotEmpty) { + s += ' (Médicament : $med)'; + } + return s; + } + if (st == 'bobo') { + final nature = payload['bobo_nature']?.toString() ?? 'bobo'; + final desc = payload['description']?.toString().trim(); + if (desc != null && desc.isNotEmpty) { + return 'Bobo ($nature) : $desc'; + } + return 'Bobo ($nature)'; + } + if (st == 'medicament') { + final nom = payload['medicament_nom']?.toString().trim(); + final ctx = payload['contexte']?.toString().trim(); + final label = + (nom != null && nom.isNotEmpty) ? 'Médicament ($nom)' : 'Médicament'; + if (ctx != null && ctx.isNotEmpty) return '$label : $ctx'; + return label; + } + return motif; } /// Motif de refus : réponse API, sinon motif payload (co-parent / reload). @@ -174,9 +219,9 @@ class CarteBulle { return 'assets/images/sac_lapin.png'; case 'soin_enfant': final st = payload['sous_type']?.toString(); - if (st == 'fievre') return 'assets/images/thermo_croix.png'; - if (st == 'medicament') return 'assets/images/cuillere.png'; // Using generic fallback or specific if added later. Assuming thermo_croix or similar could work. - if (st == 'bobo') return 'assets/images/sac_lapin.png'; // Will adjust these later if better assets exist. Let's use generic ones for now, or null if no appropriate assets. + if (st == 'fievre') return 'assets/images/thermo_verre.png'; + if (st == 'bobo') return 'assets/images/pansement.png'; + if (st == 'medicament') return 'assets/images/flacon.png'; return null; default: return null; diff --git a/frontend/lib/widgets/quotidien/cartes_feed.dart b/frontend/lib/widgets/quotidien/cartes_feed.dart index 86fc0a1..0573d34 100644 --- a/frontend/lib/widgets/quotidien/cartes_feed.dart +++ b/frontend/lib/widgets/quotidien/cartes_feed.dart @@ -612,12 +612,15 @@ class _BulleTile extends StatelessWidget { } String _fmtPeriodeUneLigne() { - // Si c'est un soin_enfant en singleDay, on affiche juste "Le ..." ou un résumé si pertinent + // Soin : « Le 08 octobre 2026 à 18h19 » (détail en italique sous la ligne). if (card.isSoinEnfant) { - final resume = card.resumerSoin; - final jour = card.dateDebut != null ? 'Le ${_fmtLong(card.dateDebut)}' : ''; - if (resume != null) return '$jour\n$resume'; - return jour; + final jour = card.dateDebut != null + ? 'Le ${_fmtLong(card.dateDebut)}' + : ''; + final h = card.heureReleveAffichee; + if (jour.isEmpty) return h != null ? 'À $h' : ''; + if (h == null || h.isEmpty) return jour; + return '$jour à $h'; } final d1 = DateTime.tryParse(card.dateDebut ?? ''); @@ -723,8 +726,6 @@ class _BulleTile extends StatelessWidget { Expanded( child: Text( periode, - maxLines: 2, - overflow: TextOverflow.ellipsis, style: GoogleFonts.merienda( fontSize: 15, fontWeight: FontWeight.w600, @@ -736,14 +737,27 @@ class _BulleTile extends StatelessWidget { ], ), ], + if (card.isSoinEnfant && + (card.detailSoin?.trim().isNotEmpty ?? false)) ...[ + const SizedBox(height: 8), + Text( + card.detailSoin!, + softWrap: true, + style: GoogleFonts.merriweather( + fontSize: 13, + fontStyle: FontStyle.italic, + height: 1.35, + color: encre.ink, + ), + ), + ], if (card.isCongeAm && card.statut == CarteStatut.refusee && card.motifRefus != null) ...[ const SizedBox(height: 8), Text( 'Motif : ${card.motifRefus}', - maxLines: 4, - overflow: TextOverflow.ellipsis, + softWrap: true, style: GoogleFonts.merriweather( fontSize: 13, fontStyle: FontStyle.italic,