Files
mobile/lib/features/wash/domain/wash_progress.dart
T

115 lines
3.3 KiB
Dart

/// Progression d'un lavage en cours.
class WashProgress {
const WashProgress({
required this.percent,
required this.phaseLabel,
this.phase,
this.estimatedEndAt,
this.remainingSeconds,
});
final int percent;
final String phaseLabel;
final String? phase;
final DateTime? estimatedEndAt;
final int? remainingSeconds;
String get remainingLabel {
if (remainingSeconds == null) return '';
final s = remainingSeconds!;
if (s <= 0) return 'Bientôt terminé';
if (s < 60) return '$s s restantes';
final min = (s / 60).ceil();
return '$min min restantes';
}
factory WashProgress.fromJson(Map<String, dynamic>? json) {
if (json == null) {
return const WashProgress(percent: 0, phaseLabel: 'En cours');
}
return WashProgress(
percent: json['percent'] as int? ?? 0,
phase: json['phase'] as String?,
phaseLabel: json['phase_label'] as String? ?? 'En cours',
estimatedEndAt: json['estimated_end_at'] != null
? DateTime.tryParse(json['estimated_end_at'] as String)
: null,
remainingSeconds: json['remaining_seconds'] as int?,
);
}
/// Calcul local si pas de données API (rafraîchissement chaque seconde).
factory WashProgress.compute({
required DateTime? startedAt,
required DateTime? estimatedEndAt,
required int? durationMinutes,
required String? machineType,
required String status,
}) {
if (status == 'pending_start') {
return const WashProgress(percent: 0, phaseLabel: 'En attente de démarrage', phase: 'pending');
}
final now = DateTime.now();
final end = estimatedEndAt ??
(startedAt != null && durationMinutes != null
? startedAt.add(Duration(minutes: durationMinutes))
: null);
if (startedAt == null || end == null) {
return const WashProgress(percent: 5, phaseLabel: 'Démarrage…', phase: 'lock');
}
final total = end.difference(startedAt).inSeconds.clamp(1, 999999);
final elapsed = now.difference(startedAt).inSeconds.clamp(0, total);
final percent = ((elapsed / total) * 100).round().clamp(0, 99);
final remaining = end.difference(now).inSeconds.clamp(0, total);
return WashProgress(
percent: percent,
phaseLabel: _phaseLabel(percent, machineType),
phase: _phase(percent, machineType),
estimatedEndAt: end,
remainingSeconds: remaining,
);
}
static String _phase(int percent, String? type) {
final isDryer = type?.startsWith('dryer') ?? false;
if (percent < 5) return 'lock';
if (isDryer) {
if (percent < 15) return 'heat';
if (percent < 85) return 'dry';
return 'finish';
}
if (percent < 15) return 'fill';
if (percent < 55) return 'wash';
if (percent < 75) return 'rinse';
if (percent < 90) return 'spin';
return 'finish';
}
static String _phaseLabel(int percent, String? type) {
switch (_phase(percent, type)) {
case 'lock':
return 'Verrouillage';
case 'heat':
return 'Préchauffage';
case 'dry':
return 'Séchage';
case 'fill':
return 'Remplissage';
case 'wash':
return 'Lavage';
case 'rinse':
return 'Rinçage';
case 'spin':
return 'Essorage';
case 'finish':
return 'Finition';
default:
return 'En cours';
}
}
}