diff --git a/.ideai/memory/MEMORY.md b/.ideai/memory/MEMORY.md index 098275b..584096c 100644 --- a/.ideai/memory/MEMORY.md +++ b/.ideai/memory/MEMORY.md @@ -11,3 +11,4 @@ - [gametime-architecture-score-chrono](gametime-architecture-score-chrono.md) — memory note gametime-architecture-score-chrono - [gametime-resume-plan-2026-07-18](gametime-resume-plan-2026-07-18.md) — memory note gametime-resume-plan-2026-07-18 - [gametime-ux-exercise-default-targets](gametime-ux-exercise-default-targets.md) — memory note gametime-ux-exercise-default-targets +- [gametime-ux-series-counter](gametime-ux-series-counter.md) — memory note gametime-ux-series-counter diff --git a/.ideai/memory/gametime-ux-series-counter.md b/.ideai/memory/gametime-ux-series-counter.md new file mode 100644 index 0000000..c31e5a5 --- /dev/null +++ b/.ideai/memory/gametime-ux-series-counter.md @@ -0,0 +1,19 @@ +--- +name: gametime-ux-series-counter +description: memory note gametime-ux-series-counter +metadata: + type: project +--- +# GameTime — Compteur de série plus visible (ticket #34, UX 2026-07-18) + +Sortir "Série X/Y" de la ligne "Programme · Exercice · Série" et en faire un bloc visuel principal proche de la série active. + +## Écran d'exécution +- Header discret conservé : temps écoulé + "Programme 1/2 · Exercice 3/8" (SANS le compteur de série qui est retiré de cette ligne). +- Juste au-dessus du nom de l'exercice, nouveau bloc visible : label "SÉRIE" (Archivo 600, 12-13px, texte secondaire, uppercase) + valeur "2 / 4" (Anton, 44-52px, couleur PRIMAIRE OR — pas crimson, le crimson reste réservé à l'accent/liseré). Bloc dans une petite carte plate (surface existante, liseré supérieur crimson 2px, rayon 6px cohérent avec la DA Court Blazer). + +## Écran Repos +Dans le texte "Ensuite : ", ajouter "Série 3 / 4" en Anton 28-32px or, pour préparer clairement à la prochaine série. + +## Ne pas casser +Les compteurs Programme/Exercice restent affichés mais discrets (juste allégés du compteur série qu'ils portaient). \ No newline at end of file diff --git a/.ideai/tickets/34/carnet.md b/.ideai/tickets/34/carnet.md index 7c186e9..0f0cd8f 100644 --- a/.ideai/tickets/34/carnet.md +++ b/.ideai/tickets/34/carnet.md @@ -1,6 +1,7 @@ --- issueRef: "#34" -version: 3 -updatedBy: {"kind":"user"} -updatedAt: 1784329283319 +version: 6 +updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"} +updatedAt: 1784363909962 --- +Décision UX consignée dans la mémoire "gametime-ux-series-counter" — lis-la en entier avant d'implémenter. Résumé : sortir "Série X/Y" de la ligne de progression existante, en faire un bloc visuel principal (Anton 44-52px, couleur or) juste au-dessus du nom de l'exercice, dans une petite carte avec liseré crimson. Même traitement allégé (Anton 28-32px or) pour "Série suivante" sur l'écran Repos. \ No newline at end of file diff --git a/.ideai/tickets/34/issue.md b/.ideai/tickets/34/issue.md index 532fad4..109a8f8 100644 --- a/.ideai/tickets/34/issue.md +++ b/.ideai/tickets/34/issue.md @@ -2,15 +2,15 @@ id: "a78c5f84-3d2e-40ae-b800-880de78f2035" number: 34 title: "Rendr ele compteur de série plus visible" -status: "open" +status: "closed" priority: "high" sprint: null links: [] agentRefs: [{"agentId":"57695b92-24d0-4876-837c-76116e70a6ae","role":"assigned"}] createdBy: {"kind":"user"} -updatedBy: {"kind":"user"} +updatedBy: {"kind":"agent","agent_id":"57695b92-24d0-4876-837c-76116e70a6ae"} createdAt: 1784329212434 -updatedAt: 1784329283319 -version: 3 +updatedAt: 1784363909962 +version: 6 --- Il faudrait que le compteur de série soit plus visible. Actuellement il est perdu avec le compteur de programme et le compteur d'exercice. J'aimerais qu'il soit plus visible, pour ça il faudrait le déplacer plus proche de notre série en cours et pourquoi pas le mettre plus gros/d'une autre couleur ? Laisser UX gérer ça \ No newline at end of file diff --git a/.ideai/tickets/index.json b/.ideai/tickets/index.json index 954ace3..ff62137 100644 --- a/.ideai/tickets/index.json +++ b/.ideai/tickets/index.json @@ -381,13 +381,13 @@ "issueRef": "#34", "path": "34", "title": "Rendr ele compteur de série plus visible", - "status": "open", + "status": "closed", "priority": "high", "sprint": null, "assignedAgentIds": [ "57695b92-24d0-4876-837c-76116e70a6ae" ], - "updatedAt": 1784329283319 + "updatedAt": 1784363909962 }, { "issueRef": "#35", diff --git a/lib/presentation/workout_execution_screen.dart b/lib/presentation/workout_execution_screen.dart index 3227627..5dec571 100644 --- a/lib/presentation/workout_execution_screen.dart +++ b/lib/presentation/workout_execution_screen.dart @@ -124,6 +124,11 @@ final class _WorkoutExecutionScreenState extends State { progressLabel: _plan.progressLabel(_position), ), const SizedBox(height: 24), + _SeriesCounterCard( + currentSet: _position.setIndex + 1, + totalSets: _exercise.setsCount, + ), + const SizedBox(height: 16), Text(_exercise.name, style: Theme.of(context).textTheme.headlineMedium), const SizedBox(height: 16), SetMeasureInput( @@ -168,10 +173,15 @@ final class _WorkoutExecutionScreenState extends State { ), if (next != null && nextExercise != null) ...[ const SizedBox(height: 24), + Text('Ensuite : ${nextExercise.name}', textAlign: TextAlign.center), + const SizedBox(height: 8), Text( - 'Ensuite : ${nextExercise.name} · ' - 'Série ${next.setIndex + 1}/${nextExercise.setsCount}', + 'Série ${next.setIndex + 1} / ${nextExercise.setsCount}', textAlign: TextAlign.center, + style: Theme.of(context).textTheme.displaySmall?.copyWith( + color: Theme.of(context).colorScheme.primary, + fontSize: 30, + ), ), ], const Spacer(), @@ -1304,10 +1314,8 @@ final class WorkoutExecutionPlan { String progressLabel(ExecutionPosition position) { final program = programAt(position); - final exercise = exerciseAt(position); return 'Programme ${position.programIndex + 1}/${programs.length} · ' - 'Exercice ${position.exerciseIndex + 1}/${program.exercises.length} · ' - 'Série ${position.setIndex + 1}/${exercise.setsCount}'; + 'Exercice ${position.exerciseIndex + 1}/${program.exercises.length}'; } } @@ -1463,6 +1471,42 @@ final class _Header extends StatelessWidget { } } +final class _SeriesCounterCard extends StatelessWidget { + const _SeriesCounterCard({required this.currentSet, required this.totalSets}); + + final int currentSet; + final int totalSets; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final tokens = courtBlazerTokensOf(context); + return CourtBlazerAccentPanel( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'SÉRIE', + style: theme.textTheme.labelSmall?.copyWith( + color: tokens.mutedText, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 6), + Text( + '$currentSet / $totalSets', + style: theme.textTheme.displayLarge?.copyWith( + color: theme.colorScheme.primary, + fontSize: 48, + ), + ), + ], + ), + ); + } +} + String _formatDuration(Duration duration) { final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); diff --git a/test/presentation/workout_execution_screen_test.dart b/test/presentation/workout_execution_screen_test.dart index 573e286..4586fd3 100644 --- a/test/presentation/workout_execution_screen_test.dart +++ b/test/presentation/workout_execution_screen_test.dart @@ -165,6 +165,7 @@ void main() { expect(find.text('Repos avant la prochaine série'), findsOneWidget); expect(find.text('00:45'), findsOneWidget); + expect(find.text('Série 2 / 2'), findsOneWidget); await tester.tap(find.text('+15 s')); await tester.pump(); @@ -181,6 +182,9 @@ void main() { testWidgets('la mesure temps enregistre une durée réelle de série', ( tester, ) async { + await tester.binding.setSurfaceSize(const Size(400, 1400)); + addTearDown(() => tester.binding.setSurfaceSize(null)); + final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12)); final repository = _FakeActiveSessionRepository(); final session = ActiveWorkoutSession( @@ -221,6 +225,9 @@ void main() { testWidgets( 'terminer la série 2 avec temps répétitions et score manuel avance', (tester) async { + await tester.binding.setSurfaceSize(const Size(400, 1400)); + addTearDown(() => tester.binding.setSurfaceSize(null)); + final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12)); final repository = _FakeActiveSessionRepository(); final session = ActiveWorkoutSession( @@ -256,10 +263,9 @@ void main() { ), ); - expect( - find.text('Programme 1/1 · Exercice 1/1 · Série 2/3'), - findsOneWidget, - ); + expect(find.text('Programme 1/1 · Exercice 1/1'), findsOneWidget); + expect(find.text('SÉRIE'), findsOneWidget); + expect(find.text('2 / 3'), findsOneWidget); expect(find.text('30 s'), findsOneWidget); for (var i = 0; i < 3; i++) { @@ -279,10 +285,8 @@ void main() { expect(repository.results.single.actualReps, 3); expect(repository.results.single.actualScore, 5); expect(repository.session?.currentSetIndex, 2); - expect( - find.text('Programme 1/1 · Exercice 1/1 · Série 3/3'), - findsOneWidget, - ); + expect(find.text('Programme 1/1 · Exercice 1/1'), findsOneWidget); + expect(find.text('3 / 3'), findsOneWidget); }, ); @@ -445,10 +449,8 @@ void main() { await tester.tap(find.byTooltip('Fermer')); await tester.pumpAndSettle(); - expect( - find.text('Programme 1/1 · Exercice 1/1 · Série 3/4'), - findsOneWidget, - ); + expect(find.text('Programme 1/1 · Exercice 1/1'), findsOneWidget); + expect(find.text('3 / 4'), findsOneWidget); }, ); @@ -493,10 +495,8 @@ void main() { expect(find.text('Plan de séance'), findsNothing); expect(find.text('Modifier la série'), findsNothing); - expect( - find.text('Programme 1/1 · Exercice 1/1 · Série 2/3'), - findsOneWidget, - ); + expect(find.text('Programme 1/1 · Exercice 1/1'), findsOneWidget); + expect(find.text('2 / 3'), findsOneWidget); }, ); }