Branche Demande de congés sur la version 2 détourée. Co-authored-by: Cursor <cursoragent@cursor.com>
198 lines
5.7 KiB
Dart
198 lines
5.7 KiB
Dart
import 'package:p_tits_pas/models/card_assets.dart';
|
||
|
||
/// Statut d'une instance de carte (file d'attention) — contrat #194 / #173.
|
||
enum CarteStatut {
|
||
ouverte('ouverte'),
|
||
refusee('refusee'),
|
||
traitee('traitee');
|
||
|
||
final String apiValue;
|
||
const CarteStatut(this.apiValue);
|
||
|
||
static CarteStatut fromApi(String? raw) {
|
||
switch (raw) {
|
||
case 'refusee':
|
||
return CarteStatut.refusee;
|
||
case 'traitee':
|
||
return CarteStatut.traitee;
|
||
case 'ouverte':
|
||
default:
|
||
return CarteStatut.ouverte;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Mode de réponse attendu selon le type SYSTEM.
|
||
enum CarteResponseMode {
|
||
none('none'),
|
||
ack('ack'),
|
||
acceptRefuse('accept_refuse');
|
||
|
||
final String apiValue;
|
||
const CarteResponseMode(this.apiValue);
|
||
|
||
static CarteResponseMode fromApi(String? raw) {
|
||
switch (raw) {
|
||
case 'ack':
|
||
return CarteResponseMode.ack;
|
||
case 'accept_refuse':
|
||
return CarteResponseMode.acceptRefuse;
|
||
case 'none':
|
||
default:
|
||
return CarteResponseMode.none;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Bulle / carte de la file d'attention.
|
||
class CarteBulle {
|
||
final String id;
|
||
final String typeCode;
|
||
final String titre;
|
||
final String? couleur;
|
||
final String idPlacement;
|
||
final String? idAbsence;
|
||
final String operation;
|
||
final CarteStatut statut;
|
||
final Map<String, dynamic> payload;
|
||
final DateTime? purgeAt;
|
||
final String? creePar;
|
||
final bool isCreator;
|
||
final CarteResponseMode responseMode;
|
||
final String? lastRefuseComment;
|
||
final DateTime? creeLe;
|
||
final DateTime? modifieLe;
|
||
|
||
const CarteBulle({
|
||
required this.id,
|
||
required this.typeCode,
|
||
required this.titre,
|
||
this.couleur,
|
||
required this.idPlacement,
|
||
this.idAbsence,
|
||
this.operation = 'create',
|
||
required this.statut,
|
||
this.payload = const {},
|
||
this.purgeAt,
|
||
this.creePar,
|
||
this.isCreator = false,
|
||
this.responseMode = CarteResponseMode.none,
|
||
this.lastRefuseComment,
|
||
this.creeLe,
|
||
this.modifieLe,
|
||
});
|
||
|
||
String? get dateDebut => payload['date_debut']?.toString();
|
||
String? get dateFin => payload['date_fin']?.toString();
|
||
String? get motif => payload['motif']?.toString();
|
||
|
||
/// Libellé UI (sémantique produit) — pas le titre brut API.
|
||
String get titreAffiche {
|
||
switch (typeCode) {
|
||
case 'conge_am':
|
||
return 'Demande de congés';
|
||
case 'arret_maladie_am':
|
||
return 'Arrêt maladie';
|
||
case 'absence_enfant':
|
||
case 'absence_enfant_modif':
|
||
return 'Notification d’absence';
|
||
default:
|
||
return titre;
|
||
}
|
||
}
|
||
|
||
bool get isArretMaladie => typeCode == 'arret_maladie_am';
|
||
bool get isCongeAm => typeCode == 'conge_am';
|
||
|
||
/// Icône dessin (haut droite) selon le type de bulle.
|
||
String? get iconAsset {
|
||
switch (typeCode) {
|
||
case 'conge_am':
|
||
return 'assets/images/cartes/icon_carte_conges2.png';
|
||
case 'arret_maladie_am':
|
||
return 'assets/images/cartes/icon_carte_maladie.png';
|
||
case 'absence_enfant':
|
||
case 'absence_enfant_modif':
|
||
return 'assets/images/cartes/icon_carte_absence.png';
|
||
default:
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// Fin de période (jour inclus). Null si dates absentes / invalides.
|
||
DateTime? get dateFinJour {
|
||
final raw = dateFin;
|
||
if (raw == null || raw.isEmpty) return null;
|
||
final dt = DateTime.tryParse(raw);
|
||
if (dt == null) return null;
|
||
return DateTime(dt.year, dt.month, dt.day);
|
||
}
|
||
|
||
/// Vrai tant que la date de fin n’est pas dépassée (jour courant inclus).
|
||
bool get periodeEncoreActive {
|
||
final fin = dateFinJour;
|
||
if (fin == null) return true;
|
||
final today = DateTime.now();
|
||
final todayDay = DateTime(today.year, today.month, today.day);
|
||
return !todayDay.isAfter(fin);
|
||
}
|
||
|
||
/// Asset horizontal pastel (palette `assets/cards/` uniquement).
|
||
String get backgroundAsset {
|
||
final key = (couleur ?? '').trim().toLowerCase();
|
||
switch (key) {
|
||
case 'red':
|
||
return CardColorHorizontal.red.path;
|
||
case 'pink':
|
||
return CardColorHorizontal.pink.path;
|
||
case 'peach':
|
||
return CardColorHorizontal.peach.path;
|
||
case 'lime':
|
||
return CardColorHorizontal.lime.path;
|
||
case 'lavender':
|
||
return CardColorHorizontal.lavender.path;
|
||
case 'green':
|
||
return CardColorHorizontal.green.path;
|
||
case 'blue':
|
||
return CardColorHorizontal.blue.path;
|
||
default:
|
||
return CardColorHorizontal.peach.path;
|
||
}
|
||
}
|
||
|
||
/// Le destinataire peut répondre (pas le créateur, carte ouverte).
|
||
bool get peutRepondre =>
|
||
!isCreator &&
|
||
statut == CarteStatut.ouverte &&
|
||
responseMode != CarteResponseMode.none;
|
||
|
||
factory CarteBulle.fromJson(Map<String, dynamic> json) {
|
||
final rawPayload = json['payload'];
|
||
return CarteBulle(
|
||
id: (json['id'] ?? '').toString(),
|
||
typeCode: (json['type_code'] ?? '').toString(),
|
||
titre: (json['titre'] ?? json['type_code'] ?? 'Carte').toString(),
|
||
couleur: json['couleur']?.toString(),
|
||
idPlacement: (json['id_placement'] ?? '').toString(),
|
||
idAbsence: json['id_absence']?.toString(),
|
||
operation: (json['operation'] ?? 'create').toString(),
|
||
statut: CarteStatut.fromApi(json['statut']?.toString()),
|
||
payload: rawPayload is Map
|
||
? Map<String, dynamic>.from(rawPayload)
|
||
: const {},
|
||
purgeAt: _parseDate(json['purge_at']),
|
||
creePar: json['cree_par']?.toString(),
|
||
isCreator: json['is_creator'] == true,
|
||
responseMode: CarteResponseMode.fromApi(json['response_mode']?.toString()),
|
||
lastRefuseComment: json['last_refuse_comment']?.toString(),
|
||
creeLe: _parseDate(json['cree_le']),
|
||
modifieLe: _parseDate(json['modifie_le']),
|
||
);
|
||
}
|
||
|
||
static DateTime? _parseDate(dynamic v) {
|
||
if (v == null) return null;
|
||
return DateTime.tryParse(v.toString());
|
||
}
|
||
}
|