feat(statistiques): implémentation backend statistiques de progression (ticket #82)

Lots B1+B2+B3 : schéma/domaine, requêtes d'agrégation et ports/use cases pour les statistiques de progression, avec tests associés.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 08:35:47 +02:00
parent fdb301f746
commit 520f227e82
8 changed files with 1538 additions and 7 deletions

View File

@ -212,6 +212,10 @@ final class _FakeBootstrap implements AppDependencies {
repository: _FakeWorkoutHistoryRepository(),
clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
),
progressionStatsUseCase = ProgressionStatsUseCase(
repository: _FakeProgressionStatsRepository(),
clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)),
),
exercisePerformanceReferenceUseCase = ExercisePerformanceReferenceUseCase(
repository: _FakeExercisePerformanceReferenceRepository(),
);
@ -249,6 +253,9 @@ final class _FakeBootstrap implements AppDependencies {
@override
final WorkoutHistoryUseCases workoutHistoryUseCases;
@override
final ProgressionStatsUseCase progressionStatsUseCase;
@override
final ExercisePerformanceReferenceUseCase exercisePerformanceReferenceUseCase;
}
@ -711,6 +718,56 @@ final class _FakeWorkoutHistoryRepository implements WorkoutHistoryRepository {
Future<void> saveStepResult(WorkoutHistoryStepResult result) async {}
}
final class _FakeProgressionStatsRepository
implements ProgressionStatsRepository {
@override
Future<ProgressionGlobalStatsData> readGlobalStats(
ProgressionDateRange range,
) async {
return const ProgressionGlobalStatsData(
completedSessionCount: 0,
totalActiveMs: 0,
activeWeekStarts: [],
hasAnyCompletedHistory: false,
);
}
@override
Future<List<ProgressionExerciseOptionData>> listExerciseOptions(
ProgressionDateRange range,
) async {
return const [];
}
@override
Future<List<ProgressionMeasureOptionData>> listMeasureOptions({
required ProgressionDateRange range,
required String exerciseKey,
}) async {
return const [];
}
@override
Future<ProgressionExerciseSeriesData> readExerciseSeries({
required ProgressionDateRange range,
required String exerciseKey,
required ProgressionMeasure measure,
}) async {
return ProgressionExerciseSeriesData(
exerciseKey: exerciseKey,
exerciseNameSnapshot: exerciseKey,
measure: ProgressionMeasureOptionData(
measure: measure,
label: 'Score',
lowerIsBetter: false,
),
points: const [],
hasAnyAllTimeData: false,
hasAnyCompletedExerciseResult: false,
);
}
}
final class _FakeExercisePerformanceReferenceRepository
implements ExercisePerformanceReferenceRepository {
@override