feat(ui): écran Historique des séances
Ajoute l'écran d'historique des séances (presentation/history_screen.dart), avec les ajustements application/domaine/repositories nécessaires et la navigation depuis l'accueil. Complète le dernier écran du périmètre UI. flutter analyze propre, 18/18 tests verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -428,6 +428,52 @@ final class DriftWorkoutHistoryRepository implements WorkoutHistoryRepository {
|
||||
|
||||
final db.AppDatabase database;
|
||||
|
||||
@override
|
||||
Future<domain.WorkoutHistory?> findById(String id) async {
|
||||
final row =
|
||||
await (database.select(
|
||||
database.workoutHistories,
|
||||
)..where((table) => table.id.equals(id) & table.deletedAt.isNull()))
|
||||
.getSingleOrNull();
|
||||
if (row == null) {
|
||||
return null;
|
||||
}
|
||||
final results =
|
||||
await (database.select(database.workoutHistorySetResults)
|
||||
..where(
|
||||
(table) =>
|
||||
table.workoutHistoryId.equals(id) &
|
||||
table.deletedAt.isNull(),
|
||||
)
|
||||
..orderBy([
|
||||
(table) => OrderingTerm.asc(table.programIndex),
|
||||
(table) => OrderingTerm.asc(table.exerciseIndex),
|
||||
(table) => OrderingTerm.asc(table.setIndex),
|
||||
]))
|
||||
.get();
|
||||
return _workoutHistoryFromRow(
|
||||
row,
|
||||
results.map(_workoutHistorySetResultFromRow).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<domain.WorkoutHistory>> listActive() async {
|
||||
final rows =
|
||||
await (database.select(database.workoutHistories)
|
||||
..where((table) => table.deletedAt.isNull())
|
||||
..orderBy([(table) => OrderingTerm.desc(table.startedAt)]))
|
||||
.get();
|
||||
final histories = <domain.WorkoutHistory>[];
|
||||
for (final row in rows) {
|
||||
final history = await findById(row.id);
|
||||
if (history != null) {
|
||||
histories.add(history);
|
||||
}
|
||||
}
|
||||
return histories;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save(domain.WorkoutHistory history) async {
|
||||
await database
|
||||
@ -444,6 +490,28 @@ final class DriftWorkoutHistoryRepository implements WorkoutHistoryRepository {
|
||||
.into(database.workoutHistorySetResults)
|
||||
.insertOnConflictUpdate(_workoutHistorySetResultCompanion(result));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> delete(String id, DateTime deletedAt) async {
|
||||
await database.transaction(() async {
|
||||
await (database.update(
|
||||
database.workoutHistories,
|
||||
)..where((table) => table.id.equals(id))).write(
|
||||
db.WorkoutHistoriesCompanion(
|
||||
deletedAt: Value(deletedAt),
|
||||
updatedAt: Value(deletedAt),
|
||||
),
|
||||
);
|
||||
await (database.update(
|
||||
database.workoutHistorySetResults,
|
||||
)..where((table) => table.workoutHistoryId.equals(id))).write(
|
||||
db.WorkoutHistorySetResultsCompanion(
|
||||
deletedAt: Value(deletedAt),
|
||||
updatedAt: Value(deletedAt),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
domain.EntityMetadata _metadataFromRow(dynamic row) {
|
||||
@ -986,6 +1054,53 @@ db.WorkoutHistorySetResultsCompanion _workoutHistorySetResultCompanion(
|
||||
);
|
||||
}
|
||||
|
||||
domain.WorkoutHistory _workoutHistoryFromRow(
|
||||
db.WorkoutHistory row,
|
||||
List<domain.WorkoutHistorySetResult> results,
|
||||
) {
|
||||
return domain.WorkoutHistory(
|
||||
metadata: _metadataFromRow(row),
|
||||
sourceWorkoutTemplateId: row.sourceWorkoutTemplateId,
|
||||
sourceActiveWorkoutSessionId: row.sourceActiveWorkoutSessionId,
|
||||
nameSnapshot: row.nameSnapshot,
|
||||
startedAt: row.startedAt,
|
||||
endedAt: row.endedAt,
|
||||
totalActiveMs: row.totalActiveMs,
|
||||
completed: row.completed,
|
||||
historySnapshotJson: row.historySnapshotJson,
|
||||
results: results,
|
||||
);
|
||||
}
|
||||
|
||||
domain.WorkoutHistorySetResult _workoutHistorySetResultFromRow(
|
||||
db.WorkoutHistorySetResult row,
|
||||
) {
|
||||
return domain.WorkoutHistorySetResult(
|
||||
metadata: _metadataFromRow(row),
|
||||
workoutHistoryId: row.workoutHistoryId,
|
||||
programSnapshotId: row.programSnapshotId,
|
||||
exerciseSnapshotId: row.exerciseSnapshotId,
|
||||
programIndex: row.programIndex,
|
||||
exerciseIndex: row.exerciseIndex,
|
||||
setIndex: row.setIndex,
|
||||
programNameSnapshot: row.programNameSnapshot,
|
||||
exerciseNameSnapshot: row.exerciseNameSnapshot,
|
||||
timeEnabledSnapshot: row.timeEnabledSnapshot,
|
||||
repsEnabledSnapshot: row.repsEnabledSnapshot,
|
||||
scoreEnabledSnapshot: row.scoreEnabledSnapshot,
|
||||
targetTimeSecondsSnapshot: row.targetTimeSecondsSnapshot,
|
||||
targetRepsSnapshot: row.targetRepsSnapshot,
|
||||
targetScoreSnapshot: row.targetScoreSnapshot,
|
||||
actualTimeMs: row.actualTimeMs,
|
||||
actualReps: row.actualReps,
|
||||
actualScore: row.actualScore,
|
||||
scoreLabelSnapshot: row.scoreLabelSnapshot,
|
||||
scoreUnitSnapshot: row.scoreUnitSnapshot,
|
||||
startedAt: row.startedAt,
|
||||
completedAt: row.completedAt,
|
||||
);
|
||||
}
|
||||
|
||||
String _syncStateToDb(domain.SyncState state) => switch (state) {
|
||||
domain.SyncState.localOnly => 'localOnly',
|
||||
domain.SyncState.dirty => 'dirty',
|
||||
|
||||
Reference in New Issue
Block a user