feat(ui): écran Exécution de séance
Ajoute l'écran d'exécution de séance (presentation/workout_execution_screen.dart), avec les ajustements application/domaine/repositories nécessaires et la navigation depuis l'accueil et l'écran séance-modèle. flutter analyze propre, 15/15 tests verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -8,6 +8,8 @@ final class AppBootstrap {
|
||||
required this.mediaUseCases,
|
||||
required this.programUseCases,
|
||||
required this.workoutTemplateUseCases,
|
||||
required this.activeWorkoutSessionUseCases,
|
||||
required this.closeWorkoutSessionUseCase,
|
||||
});
|
||||
|
||||
final AppDatabase database;
|
||||
@ -15,6 +17,8 @@ final class AppBootstrap {
|
||||
final MediaUseCases mediaUseCases;
|
||||
final ProgramUseCases programUseCases;
|
||||
final WorkoutTemplateUseCases workoutTemplateUseCases;
|
||||
final ActiveWorkoutSessionUseCases activeWorkoutSessionUseCases;
|
||||
final CloseWorkoutSessionUseCase closeWorkoutSessionUseCase;
|
||||
|
||||
static Future<AppBootstrap> create() async {
|
||||
final database = AppDatabase.open();
|
||||
@ -23,6 +27,8 @@ final class AppBootstrap {
|
||||
final mediaRepository = DriftMediaAssetRepository(database);
|
||||
final programRepository = DriftProgramRepository(database);
|
||||
final templateRepository = DriftWorkoutTemplateRepository(database);
|
||||
final activeSessionRepository = DriftActiveSessionRepository(database);
|
||||
final historyRepository = DriftWorkoutHistoryRepository(database);
|
||||
final ids = LocalIdGenerator();
|
||||
const clock = SystemClock();
|
||||
const originDeviceId = 'local-device';
|
||||
@ -57,6 +63,20 @@ final class AppBootstrap {
|
||||
ids: ids,
|
||||
originDeviceId: originDeviceId,
|
||||
),
|
||||
activeWorkoutSessionUseCases: ActiveWorkoutSessionUseCases(
|
||||
sessionRepository: activeSessionRepository,
|
||||
templateRepository: templateRepository,
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
originDeviceId: originDeviceId,
|
||||
),
|
||||
closeWorkoutSessionUseCase: CloseWorkoutSessionUseCase(
|
||||
sessionRepository: activeSessionRepository,
|
||||
historyRepository: historyRepository,
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
originDeviceId: originDeviceId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -76,6 +76,7 @@ abstract interface class WorkoutTemplateRepository {
|
||||
|
||||
abstract interface class ActiveSessionRepository {
|
||||
Future<ActiveWorkoutSession?> findById(String id);
|
||||
Future<ActiveWorkoutSession?> findOpen();
|
||||
Future<void> save(ActiveWorkoutSession session);
|
||||
Future<void> saveSetResult(ActiveSetResult result);
|
||||
Future<void> saveRestState(ActiveRestState restState);
|
||||
|
||||
@ -590,6 +590,8 @@ final class ActiveWorkoutSessionUseCases {
|
||||
final IdGenerator ids;
|
||||
final String originDeviceId;
|
||||
|
||||
Future<ActiveWorkoutSession?> findOpen() => sessionRepository.findOpen();
|
||||
|
||||
Future<ActiveWorkoutSession> startFromTemplate(String templateId) async {
|
||||
final template = await templateRepository.findById(templateId);
|
||||
if (template == null) {
|
||||
@ -659,6 +661,97 @@ final class ActiveWorkoutSessionUseCases {
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<ActiveSetResult> recordCurrentSetResult({
|
||||
required String sessionId,
|
||||
required String programSnapshotId,
|
||||
required String exerciseSnapshotId,
|
||||
required int programIndex,
|
||||
required int exerciseIndex,
|
||||
required int setIndex,
|
||||
int? actualTimeMs,
|
||||
int? actualReps,
|
||||
double? actualScore,
|
||||
String? scoreLabelSnapshot,
|
||||
String? scoreUnitSnapshot,
|
||||
}) async {
|
||||
final now = clock.now();
|
||||
final result = ActiveSetResult(
|
||||
metadata: _newMetadata(ids, originDeviceId, now),
|
||||
activeWorkoutSessionId: sessionId,
|
||||
programSnapshotId: programSnapshotId,
|
||||
exerciseSnapshotId: exerciseSnapshotId,
|
||||
programIndex: programIndex,
|
||||
exerciseIndex: exerciseIndex,
|
||||
setIndex: setIndex,
|
||||
completedAt: now,
|
||||
actualTimeMs: actualTimeMs,
|
||||
actualReps: actualReps,
|
||||
actualScore: actualScore,
|
||||
scoreLabelSnapshot: scoreLabelSnapshot,
|
||||
scoreUnitSnapshot: scoreUnitSnapshot,
|
||||
);
|
||||
await sessionRepository.saveSetResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<ActiveWorkoutSession> updateProgress({
|
||||
required String sessionId,
|
||||
required int programIndex,
|
||||
required int exerciseIndex,
|
||||
required int setIndex,
|
||||
}) async {
|
||||
final session = await _requiredSession(sessionId);
|
||||
final updated = session.copyWith(
|
||||
currentProgramIndex: programIndex,
|
||||
currentExerciseIndex: exerciseIndex,
|
||||
currentSetIndex: setIndex,
|
||||
metadata: session.metadata.touch(clock.now()),
|
||||
);
|
||||
await sessionRepository.save(updated);
|
||||
return updated;
|
||||
}
|
||||
|
||||
Future<ActiveWorkoutSession> quitAndSave(String sessionId) async {
|
||||
final session = await _requiredSession(sessionId);
|
||||
final now = clock.now();
|
||||
final saved = session.copyWith(
|
||||
status: ActiveWorkoutStatus.savedExit,
|
||||
lastPersistedAt: now,
|
||||
elapsedActiveMs: session.elapsedActiveMillisecondsAt(now),
|
||||
metadata: session.metadata.touch(now),
|
||||
);
|
||||
await sessionRepository.save(saved);
|
||||
return saved;
|
||||
}
|
||||
|
||||
Future<ActiveWorkoutSession> abandon(String sessionId) async {
|
||||
final session = await _requiredSession(sessionId);
|
||||
final now = clock.now();
|
||||
final abandoned = session.copyWith(
|
||||
status: ActiveWorkoutStatus.abandoned,
|
||||
endedAt: now,
|
||||
lastPersistedAt: now,
|
||||
elapsedActiveMs: session.elapsedActiveMillisecondsAt(now),
|
||||
metadata: session.metadata.touch(now),
|
||||
);
|
||||
await sessionRepository.save(abandoned);
|
||||
return abandoned;
|
||||
}
|
||||
|
||||
Future<ActiveWorkoutSession> complete(String sessionId) async {
|
||||
final session = await _requiredSession(sessionId);
|
||||
final now = clock.now();
|
||||
final completed = session.copyWith(
|
||||
status: ActiveWorkoutStatus.completed,
|
||||
endedAt: now,
|
||||
lastPersistedAt: now,
|
||||
elapsedActiveMs: session.elapsedActiveMillisecondsAt(now),
|
||||
metadata: session.metadata.touch(now),
|
||||
);
|
||||
await sessionRepository.save(completed);
|
||||
return completed;
|
||||
}
|
||||
|
||||
Future<ActiveRestState> startRestAfterSet({
|
||||
required String sessionId,
|
||||
required int afterProgramIndex,
|
||||
|
||||
Reference in New Issue
Block a user