feat(ui): affichage du chrono de score dans le plan et l'historique (ticket #28)
Affiche le chrono du score chronométré sur workout_execution_screen.dart (plan de séance) et history_screen.dart (historique). flutter analyze propre, 77/77 tests verts, build APK debug validé. Dernier ticket du backlog — clôture aussi le ticket parent #18 (score chronométré). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -314,6 +314,22 @@ final class HistorySetDetail {
|
||||
final value = _formatScoreValue(result['actualScore'] as num);
|
||||
parts.add(unit == null ? 'Score $value' : 'Score $value $unit');
|
||||
}
|
||||
if (exercise['scoreEnabled'] == true &&
|
||||
_historyScoreInputMode(exercise, result) == ScoreInputMode.stopwatch &&
|
||||
result['actualScoreTimeMs'] != null) {
|
||||
final value = _formatScoreStopwatch(
|
||||
Duration(milliseconds: result['actualScoreTimeMs'] as int),
|
||||
);
|
||||
final target = _targetScoreTimeMsFromSnapshot(exercise, result);
|
||||
if (target == null) {
|
||||
parts.add('Temps réalisé : $value');
|
||||
} else {
|
||||
parts.add(
|
||||
'Temps réalisé : $value / objectif '
|
||||
'${_formatScoreStopwatchTarget(Duration(milliseconds: target))}',
|
||||
);
|
||||
}
|
||||
}
|
||||
return HistorySetDetail(
|
||||
setIndex: result['setIndex'] as int,
|
||||
summary: parts.isEmpty ? 'Aucune mesure saisie' : parts.join(' · '),
|
||||
@ -361,6 +377,9 @@ Map<String, dynamic> _resultFromDomain(WorkoutHistorySetResult result) {
|
||||
'actualTimeMs': result.actualTimeMs,
|
||||
'actualReps': result.actualReps,
|
||||
'actualScore': result.actualScore,
|
||||
'actualScoreTimeMs': result.actualScoreTimeMs,
|
||||
'scoreInputModeSnapshot': result.scoreInputModeSnapshot.name,
|
||||
'targetScoreTimeMsSnapshot': result.targetScoreTimeMsSnapshot,
|
||||
};
|
||||
}
|
||||
|
||||
@ -372,7 +391,11 @@ String _historySummary(WorkoutHistory history) {
|
||||
: (snapshot['results'] as List<dynamic>? ?? const [])
|
||||
.cast<Map<String, dynamic>>();
|
||||
final scoreCount = rawResults
|
||||
.where((result) => result['actualScore'] != null)
|
||||
.where(
|
||||
(result) =>
|
||||
result['actualScore'] != null ||
|
||||
result['actualScoreTimeMs'] != null,
|
||||
)
|
||||
.length;
|
||||
return '${rawResults.length} séries · $scoreCount score${scoreCount > 1 ? 's' : ''}';
|
||||
}
|
||||
@ -403,6 +426,47 @@ String _formatDurationMs(int milliseconds) {
|
||||
return '$minutes:$seconds';
|
||||
}
|
||||
|
||||
String _formatScoreStopwatch(Duration duration) {
|
||||
final totalTenths = (duration.inMilliseconds / 100).floor();
|
||||
final minutes = (totalTenths ~/ 600).toString().padLeft(2, '0');
|
||||
final seconds = ((totalTenths ~/ 10) % 60).toString().padLeft(2, '0');
|
||||
final tenths = totalTenths % 10;
|
||||
return '$minutes:$seconds.$tenths';
|
||||
}
|
||||
|
||||
String _formatScoreStopwatchTarget(Duration duration) {
|
||||
if (duration.inMilliseconds % 1000 == 0) {
|
||||
return _formatDurationMs(duration.inMilliseconds);
|
||||
}
|
||||
return _formatScoreStopwatch(duration);
|
||||
}
|
||||
|
||||
ScoreInputMode _scoreInputModeFromSnapshot(Object? value) {
|
||||
return switch (value) {
|
||||
'stopwatch' => ScoreInputMode.stopwatch,
|
||||
_ => ScoreInputMode.manual,
|
||||
};
|
||||
}
|
||||
|
||||
int? _targetScoreTimeMsFromSnapshot(
|
||||
Map<String, dynamic> exercise,
|
||||
Map<String, dynamic> result,
|
||||
) {
|
||||
return result['targetScoreTimeMsSnapshot'] as int? ??
|
||||
(exercise['targetScoreTimeMs'] as int?);
|
||||
}
|
||||
|
||||
ScoreInputMode _historyScoreInputMode(
|
||||
Map<String, dynamic> exercise,
|
||||
Map<String, dynamic> result,
|
||||
) {
|
||||
final resultMode = result['scoreInputModeSnapshot'];
|
||||
if (resultMode != null) {
|
||||
return _scoreInputModeFromSnapshot(resultMode);
|
||||
}
|
||||
return _scoreInputModeFromSnapshot(exercise['scoreInputModeSnapshot']);
|
||||
}
|
||||
|
||||
final class _CenteredMessage extends StatelessWidget {
|
||||
const _CenteredMessage({required this.title, this.message});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user