chore(wip): consolidation intermédiaire multi-tickets (sprints Statistiques, UI, Bug resolution, Serveur-client)

Regroupe l'état de travail en cours réalisé dans un même worktree sur
plusieurs tickets/sprints (#85, #136, #145, #155-160, #162-164),
mélangeant des tickets QA et inProgress. Ne constitue pas une feature
terminée : commit de sauvegarde avant triage/split par ticket en
branches feature/* dédiées. Exclut les dossiers d'environnement de
build locaux et le heap dump parasite (.gitignore mis à jour).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 16:48:54 +02:00
parent 58272e354a
commit 917777e18b
279 changed files with 13546 additions and 674 deletions

View File

@ -110,7 +110,7 @@ class ShareInboxItems extends Table {
@override
List<String> get customConstraints => [
"CHECK (resource_type IN ('program', 'workoutTemplate'))",
"CHECK (resource_type IN ('program', 'workoutTemplate', 'pack'))",
"CHECK (status IN ('pending', 'accepted', 'declined', 'revoked'))",
];
}
@ -138,7 +138,7 @@ class PendingShareActions extends Table {
List<String> get customConstraints => [
"CHECK (action_type IN ('send', 'accept', 'decline', 'revoke'))",
'CHECK (resource_type IS NULL OR resource_type IN '
"('program', 'workoutTemplate'))",
"('program', 'workoutTemplate', 'pack'))",
"CHECK (status IN ('pending', 'succeeded', 'failed'))",
];
}
@ -750,14 +750,94 @@ class WorkoutHistories extends SyncableTable {
IntColumn get totalActiveMs => integer()();
BoolColumn get completed => boolean()();
TextColumn get historySnapshotJson => text().withLength(min: 1)();
IntColumn get minHeartRateBpm => integer().nullable()();
RealColumn get averageHeartRateBpm => real().nullable()();
IntColumn get maxHeartRateBpm => integer().nullable()();
RealColumn get totalDistanceMeters => real().nullable()();
RealColumn get totalCaloriesKcal => real().nullable()();
@override
List<String> get customConstraints => [
'CHECK (total_active_ms >= 0)',
'CHECK (min_heart_rate_bpm IS NULL OR min_heart_rate_bpm > 0)',
'CHECK (average_heart_rate_bpm IS NULL OR average_heart_rate_bpm > 0)',
'CHECK (max_heart_rate_bpm IS NULL OR max_heart_rate_bpm > 0)',
'CHECK (total_distance_meters IS NULL OR total_distance_meters >= 0)',
'CHECK (total_calories_kcal IS NULL OR total_calories_kcal >= 0)',
];
}
class WorkoutTelemetrySamples extends Table {
@override
String get tableName => 'workout_telemetry_samples';
TextColumn get id => text()();
TextColumn get sessionId => text().withLength(min: 1)();
DateTimeColumn get capturedAt => dateTime()();
IntColumn get programIndex => integer().nullable()();
IntColumn get exerciseIndex => integer().nullable()();
IntColumn get setIndex => integer().nullable()();
IntColumn get passageIndex => integer().nullable()();
IntColumn get stepIndex => integer().nullable()();
TextColumn get programSnapshotId => text().nullable()();
TextColumn get exerciseSnapshotId => text().nullable()();
TextColumn get stepSnapshotId => text().nullable()();
IntColumn get heartRateBpm => integer().nullable()();
RealColumn get distanceMeters => real().nullable()();
RealColumn get caloriesKcal => real().nullable()();
@override
Set<Column> get primaryKey => {id};
@override
List<String> get customConstraints => [
'CHECK (program_index IS NULL OR program_index >= 0)',
'CHECK (exercise_index IS NULL OR exercise_index >= 0)',
'CHECK (set_index IS NULL OR set_index >= 0)',
'CHECK (passage_index IS NULL OR passage_index >= 0)',
'CHECK (step_index IS NULL OR step_index >= 0)',
'CHECK (heart_rate_bpm IS NULL OR heart_rate_bpm > 0)',
'CHECK (distance_meters IS NULL OR distance_meters >= 0)',
'CHECK (calories_kcal IS NULL OR calories_kcal >= 0)',
'CHECK (heart_rate_bpm IS NOT NULL OR distance_meters IS NOT NULL OR '
'calories_kcal IS NOT NULL)',
];
}
class WorkoutTelemetryAggregates extends Table {
@override
String get tableName => 'workout_telemetry_aggregates';
TextColumn get sessionId => text().withLength(min: 1)();
TextColumn get scope => text()();
IntColumn get programIndex => integer().nullable()();
IntColumn get exerciseIndex => integer().nullable()();
IntColumn get setIndex => integer().nullable()();
IntColumn get passageIndex => integer().nullable()();
IntColumn get stepIndex => integer().nullable()();
IntColumn get sampleCount => integer()();
IntColumn get minHeartRateBpm => integer().nullable()();
RealColumn get averageHeartRateBpm => real().nullable()();
IntColumn get maxHeartRateBpm => integer().nullable()();
RealColumn get totalDistanceMeters => real().nullable()();
RealColumn get totalCaloriesKcal => real().nullable()();
@override
List<String> get customConstraints => [
"CHECK (scope IN ('session', 'exercise', 'set', 'step'))",
'CHECK (program_index IS NULL OR program_index >= 0)',
'CHECK (exercise_index IS NULL OR exercise_index >= 0)',
'CHECK (set_index IS NULL OR set_index >= 0)',
'CHECK (passage_index IS NULL OR passage_index >= 0)',
'CHECK (step_index IS NULL OR step_index >= 0)',
'CHECK (sample_count >= 0)',
'CHECK (min_heart_rate_bpm IS NULL OR min_heart_rate_bpm > 0)',
'CHECK (average_heart_rate_bpm IS NULL OR average_heart_rate_bpm > 0)',
'CHECK (max_heart_rate_bpm IS NULL OR max_heart_rate_bpm > 0)',
'CHECK (total_distance_meters IS NULL OR total_distance_meters >= 0)',
'CHECK (total_calories_kcal IS NULL OR total_calories_kcal >= 0)',
'UNIQUE (session_id, scope, program_index, exercise_index, set_index, '
'passage_index, step_index)',
];
}