Initial commit
This commit is contained in:
152
lib/data/database/app_database.dart
Normal file
152
lib/data/database/app_database.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:trainhub_flutter/core/constants/app_constants.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/exercise_dao.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/training_plan_dao.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/program_dao.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/analysis_dao.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/chat_dao.dart';
|
||||
import 'dart:io';
|
||||
|
||||
part 'app_database.g.dart';
|
||||
|
||||
class Exercises extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get name => text()();
|
||||
TextColumn get instructions => text().nullable()();
|
||||
TextColumn get enrichment => text().nullable()();
|
||||
TextColumn get tags => text().nullable()();
|
||||
TextColumn get videoUrl => text().nullable()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class TrainingPlans extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get name => text()();
|
||||
TextColumn get sections => text().nullable()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class Programs extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get name => text()();
|
||||
TextColumn get createdAt => text()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class ProgramWeeks extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get programId =>
|
||||
text().references(Programs, #id, onDelete: KeyAction.cascade)();
|
||||
IntColumn get position => integer()();
|
||||
TextColumn get notes => text().nullable()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class ProgramWorkouts extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get weekId =>
|
||||
text().references(ProgramWeeks, #id, onDelete: KeyAction.cascade)();
|
||||
TextColumn get programId =>
|
||||
text().references(Programs, #id, onDelete: KeyAction.cascade)();
|
||||
TextColumn get day => text()();
|
||||
TextColumn get type => text()();
|
||||
TextColumn get refId => text().nullable()();
|
||||
TextColumn get name => text().nullable()();
|
||||
TextColumn get description => text().nullable()();
|
||||
BoolColumn get completed => boolean().withDefault(const Constant(false))();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class AnalysisSessions extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get name => text()();
|
||||
TextColumn get date => text()();
|
||||
TextColumn get videoPath => text().nullable()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class Annotations extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get sessionId =>
|
||||
text().references(AnalysisSessions, #id, onDelete: KeyAction.cascade)();
|
||||
RealColumn get startTime => real()();
|
||||
RealColumn get endTime => real()();
|
||||
TextColumn get name => text().nullable()();
|
||||
TextColumn get description => text().nullable()();
|
||||
TextColumn get color => text().nullable()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class ChatSessions extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get title => text().nullable()();
|
||||
TextColumn get createdAt => text()();
|
||||
TextColumn get updatedAt => text()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
class ChatMessages extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get sessionId =>
|
||||
text().references(ChatSessions, #id, onDelete: KeyAction.cascade)();
|
||||
TextColumn get role => text()();
|
||||
TextColumn get content => text()();
|
||||
TextColumn get createdAt => text()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
||||
|
||||
@DriftDatabase(
|
||||
tables: [
|
||||
Exercises,
|
||||
TrainingPlans,
|
||||
Programs,
|
||||
ProgramWeeks,
|
||||
ProgramWorkouts,
|
||||
AnalysisSessions,
|
||||
Annotations,
|
||||
ChatSessions,
|
||||
ChatMessages,
|
||||
],
|
||||
daos: [
|
||||
ExerciseDao,
|
||||
TrainingPlanDao,
|
||||
ProgramDao,
|
||||
AnalysisDao,
|
||||
ChatDao,
|
||||
],
|
||||
)
|
||||
class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase() : super(_openConnection());
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
}
|
||||
|
||||
LazyDatabase _openConnection() {
|
||||
return LazyDatabase(() async {
|
||||
final dbFolder = await getApplicationDocumentsDirectory();
|
||||
final file = File(p.join(dbFolder.path, AppConstants.databaseName));
|
||||
return NativeDatabase.createInBackground(file);
|
||||
});
|
||||
}
|
||||
6249
lib/data/database/app_database.g.dart
Normal file
6249
lib/data/database/app_database.g.dart
Normal file
File diff suppressed because it is too large
Load Diff
32
lib/data/database/daos/analysis_dao.dart
Normal file
32
lib/data/database/daos/analysis_dao.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
|
||||
part 'analysis_dao.g.dart';
|
||||
|
||||
@DriftAccessor(tables: [AnalysisSessions, Annotations])
|
||||
class AnalysisDao extends DatabaseAccessor<AppDatabase>
|
||||
with _$AnalysisDaoMixin {
|
||||
AnalysisDao(super.db);
|
||||
|
||||
Future<List<AnalysisSession>> getAllSessions() =>
|
||||
select(analysisSessions).get();
|
||||
|
||||
Future<AnalysisSession?> getSession(String id) =>
|
||||
(select(analysisSessions)..where((t) => t.id.equals(id)))
|
||||
.getSingleOrNull();
|
||||
|
||||
Future<void> insertSession(AnalysisSessionsCompanion entry) =>
|
||||
into(analysisSessions).insert(entry);
|
||||
|
||||
Future<void> deleteSession(String id) =>
|
||||
(delete(analysisSessions)..where((t) => t.id.equals(id))).go();
|
||||
|
||||
Future<List<Annotation>> getAnnotations(String sessionId) =>
|
||||
(select(annotations)..where((t) => t.sessionId.equals(sessionId))).get();
|
||||
|
||||
Future<void> insertAnnotation(AnnotationsCompanion entry) =>
|
||||
into(annotations).insert(entry);
|
||||
|
||||
Future<void> deleteAnnotation(String id) =>
|
||||
(delete(annotations)..where((t) => t.id.equals(id))).go();
|
||||
}
|
||||
10
lib/data/database/daos/analysis_dao.g.dart
Normal file
10
lib/data/database/daos/analysis_dao.g.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'analysis_dao.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
mixin _$AnalysisDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||
$AnalysisSessionsTable get analysisSessions =>
|
||||
attachedDatabase.analysisSessions;
|
||||
$AnnotationsTable get annotations => attachedDatabase.annotations;
|
||||
}
|
||||
43
lib/data/database/daos/chat_dao.dart
Normal file
43
lib/data/database/daos/chat_dao.dart
Normal file
@@ -0,0 +1,43 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
|
||||
part 'chat_dao.g.dart';
|
||||
|
||||
@DriftAccessor(tables: [ChatSessions, ChatMessages])
|
||||
class ChatDao extends DatabaseAccessor<AppDatabase> with _$ChatDaoMixin {
|
||||
ChatDao(super.db);
|
||||
|
||||
Future<List<ChatSession>> getAllSessions() =>
|
||||
(select(chatSessions)
|
||||
..orderBy([
|
||||
(t) => OrderingTerm(
|
||||
expression: t.createdAt, mode: OrderingMode.desc)
|
||||
]))
|
||||
.get();
|
||||
|
||||
Future<ChatSession?> getSession(String id) =>
|
||||
(select(chatSessions)..where((t) => t.id.equals(id)))
|
||||
.getSingleOrNull();
|
||||
|
||||
Future<void> insertSession(ChatSessionsCompanion entry) =>
|
||||
into(chatSessions).insert(entry);
|
||||
|
||||
Future<void> deleteSession(String id) =>
|
||||
(delete(chatSessions)..where((t) => t.id.equals(id))).go();
|
||||
|
||||
Future<void> updateSessionTitle(String id, String title) =>
|
||||
(update(chatSessions)..where((t) => t.id.equals(id)))
|
||||
.write(ChatSessionsCompanion(title: Value(title)));
|
||||
|
||||
Future<List<ChatMessage>> getMessages(String sessionId) =>
|
||||
(select(chatMessages)
|
||||
..where((t) => t.sessionId.equals(sessionId))
|
||||
..orderBy([
|
||||
(t) =>
|
||||
OrderingTerm(expression: t.createdAt, mode: OrderingMode.asc)
|
||||
]))
|
||||
.get();
|
||||
|
||||
Future<void> insertMessage(ChatMessagesCompanion entry) =>
|
||||
into(chatMessages).insert(entry);
|
||||
}
|
||||
9
lib/data/database/daos/chat_dao.g.dart
Normal file
9
lib/data/database/daos/chat_dao.g.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'chat_dao.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
mixin _$ChatDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||
$ChatSessionsTable get chatSessions => attachedDatabase.chatSessions;
|
||||
$ChatMessagesTable get chatMessages => attachedDatabase.chatMessages;
|
||||
}
|
||||
24
lib/data/database/daos/exercise_dao.dart
Normal file
24
lib/data/database/daos/exercise_dao.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
|
||||
part 'exercise_dao.g.dart';
|
||||
|
||||
@DriftAccessor(tables: [Exercises])
|
||||
class ExerciseDao extends DatabaseAccessor<AppDatabase>
|
||||
with _$ExerciseDaoMixin {
|
||||
ExerciseDao(super.db);
|
||||
|
||||
Future<List<Exercise>> getAllExercises() => select(exercises).get();
|
||||
|
||||
Future<Exercise> getExerciseById(String id) =>
|
||||
(select(exercises)..where((t) => t.id.equals(id))).getSingle();
|
||||
|
||||
Future<void> insertExercise(ExercisesCompanion entry) =>
|
||||
into(exercises).insert(entry);
|
||||
|
||||
Future<void> updateExercise(String id, ExercisesCompanion entry) =>
|
||||
(update(exercises)..where((t) => t.id.equals(id))).write(entry);
|
||||
|
||||
Future<void> deleteExercise(String id) =>
|
||||
(delete(exercises)..where((t) => t.id.equals(id))).go();
|
||||
}
|
||||
8
lib/data/database/daos/exercise_dao.g.dart
Normal file
8
lib/data/database/daos/exercise_dao.g.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'exercise_dao.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
mixin _$ExerciseDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||
$ExercisesTable get exercises => attachedDatabase.exercises;
|
||||
}
|
||||
60
lib/data/database/daos/program_dao.dart
Normal file
60
lib/data/database/daos/program_dao.dart
Normal file
@@ -0,0 +1,60 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
|
||||
part 'program_dao.g.dart';
|
||||
|
||||
@DriftAccessor(tables: [Programs, ProgramWeeks, ProgramWorkouts])
|
||||
class ProgramDao extends DatabaseAccessor<AppDatabase>
|
||||
with _$ProgramDaoMixin {
|
||||
ProgramDao(super.db);
|
||||
|
||||
Future<List<Program>> getAllPrograms() =>
|
||||
(select(programs)
|
||||
..orderBy([
|
||||
(t) =>
|
||||
OrderingTerm(expression: t.createdAt, mode: OrderingMode.desc)
|
||||
]))
|
||||
.get();
|
||||
|
||||
Future<Program?> getProgram(String id) =>
|
||||
(select(programs)..where((t) => t.id.equals(id))).getSingleOrNull();
|
||||
|
||||
Future<void> insertProgram(ProgramsCompanion entry) =>
|
||||
into(programs).insert(entry);
|
||||
|
||||
Future<void> deleteProgram(String id) =>
|
||||
(delete(programs)..where((t) => t.id.equals(id))).go();
|
||||
|
||||
Future<List<ProgramWeek>> getWeeks(String programId) =>
|
||||
(select(programWeeks)
|
||||
..where((t) => t.programId.equals(programId))
|
||||
..orderBy([(t) => OrderingTerm(expression: t.position)]))
|
||||
.get();
|
||||
|
||||
Future<void> insertWeek(ProgramWeeksCompanion entry) =>
|
||||
into(programWeeks).insert(entry);
|
||||
|
||||
Future<void> deleteWeek(String id) =>
|
||||
(delete(programWeeks)..where((t) => t.id.equals(id))).go();
|
||||
|
||||
Future<void> updateWeekNote(String weekId, String note) =>
|
||||
(update(programWeeks)..where((t) => t.id.equals(weekId)))
|
||||
.write(ProgramWeeksCompanion(notes: Value(note)));
|
||||
|
||||
Future<List<ProgramWorkout>> getWorkouts(String programId) =>
|
||||
(select(programWorkouts)..where((t) => t.programId.equals(programId)))
|
||||
.get();
|
||||
|
||||
Future<void> insertWorkout(ProgramWorkoutsCompanion entry) =>
|
||||
into(programWorkouts).insert(entry);
|
||||
|
||||
Future<void> updateWorkout(String id, ProgramWorkoutsCompanion entry) =>
|
||||
(update(programWorkouts)..where((t) => t.id.equals(id))).write(entry);
|
||||
|
||||
Future<void> deleteWorkout(String id) =>
|
||||
(delete(programWorkouts)..where((t) => t.id.equals(id))).go();
|
||||
|
||||
Future<void> toggleWorkoutComplete(String id, bool currentStatus) =>
|
||||
(update(programWorkouts)..where((t) => t.id.equals(id)))
|
||||
.write(ProgramWorkoutsCompanion(completed: Value(!currentStatus)));
|
||||
}
|
||||
10
lib/data/database/daos/program_dao.g.dart
Normal file
10
lib/data/database/daos/program_dao.g.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'program_dao.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
mixin _$ProgramDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||
$ProgramsTable get programs => attachedDatabase.programs;
|
||||
$ProgramWeeksTable get programWeeks => attachedDatabase.programWeeks;
|
||||
$ProgramWorkoutsTable get programWorkouts => attachedDatabase.programWorkouts;
|
||||
}
|
||||
24
lib/data/database/daos/training_plan_dao.dart
Normal file
24
lib/data/database/daos/training_plan_dao.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
|
||||
part 'training_plan_dao.g.dart';
|
||||
|
||||
@DriftAccessor(tables: [TrainingPlans])
|
||||
class TrainingPlanDao extends DatabaseAccessor<AppDatabase>
|
||||
with _$TrainingPlanDaoMixin {
|
||||
TrainingPlanDao(super.db);
|
||||
|
||||
Future<List<TrainingPlan>> getAllPlans() => select(trainingPlans).get();
|
||||
|
||||
Future<TrainingPlan> getPlanById(String id) =>
|
||||
(select(trainingPlans)..where((t) => t.id.equals(id))).getSingle();
|
||||
|
||||
Future<void> insertPlan(TrainingPlansCompanion entry) =>
|
||||
into(trainingPlans).insert(entry);
|
||||
|
||||
Future<void> updatePlan(String id, TrainingPlansCompanion entry) =>
|
||||
(update(trainingPlans)..where((t) => t.id.equals(id))).write(entry);
|
||||
|
||||
Future<void> deletePlan(String id) =>
|
||||
(delete(trainingPlans)..where((t) => t.id.equals(id))).go();
|
||||
}
|
||||
8
lib/data/database/daos/training_plan_dao.g.dart
Normal file
8
lib/data/database/daos/training_plan_dao.g.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'training_plan_dao.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
mixin _$TrainingPlanDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||
$TrainingPlansTable get trainingPlans => attachedDatabase.trainingPlans;
|
||||
}
|
||||
28
lib/data/mappers/analysis_mapper.dart
Normal file
28
lib/data/mappers/analysis_mapper.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/analysis_session.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/annotation.dart';
|
||||
|
||||
class AnalysisMapper {
|
||||
AnalysisMapper._();
|
||||
|
||||
static AnalysisSessionEntity sessionToEntity(AnalysisSession row) {
|
||||
return AnalysisSessionEntity(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
date: row.date,
|
||||
videoPath: row.videoPath,
|
||||
);
|
||||
}
|
||||
|
||||
static AnnotationEntity annotationToEntity(Annotation row) {
|
||||
return AnnotationEntity(
|
||||
id: row.id,
|
||||
sessionId: row.sessionId,
|
||||
startTime: row.startTime,
|
||||
endTime: row.endTime,
|
||||
name: row.name,
|
||||
description: row.description,
|
||||
color: row.color,
|
||||
);
|
||||
}
|
||||
}
|
||||
26
lib/data/mappers/chat_mapper.dart
Normal file
26
lib/data/mappers/chat_mapper.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/chat_session.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/chat_message.dart';
|
||||
|
||||
class ChatMapper {
|
||||
ChatMapper._();
|
||||
|
||||
static ChatSessionEntity sessionToEntity(ChatSession row) {
|
||||
return ChatSessionEntity(
|
||||
id: row.id,
|
||||
title: row.title,
|
||||
createdAt: row.createdAt,
|
||||
updatedAt: row.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
static ChatMessageEntity messageToEntity(ChatMessage row) {
|
||||
return ChatMessageEntity(
|
||||
id: row.id,
|
||||
sessionId: row.sessionId,
|
||||
role: row.role,
|
||||
content: row.content,
|
||||
createdAt: row.createdAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
39
lib/data/mappers/exercise_mapper.dart
Normal file
39
lib/data/mappers/exercise_mapper.dart
Normal file
@@ -0,0 +1,39 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/exercise.dart';
|
||||
|
||||
class ExerciseMapper {
|
||||
ExerciseMapper._();
|
||||
|
||||
static ExerciseEntity toEntity(Exercise row) {
|
||||
return ExerciseEntity(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
instructions: row.instructions,
|
||||
enrichment: row.enrichment,
|
||||
tags: row.tags,
|
||||
videoUrl: row.videoUrl,
|
||||
);
|
||||
}
|
||||
|
||||
static ExercisesCompanion toCompanion(ExerciseEntity entity) {
|
||||
return ExercisesCompanion(
|
||||
id: Value(entity.id),
|
||||
name: Value(entity.name),
|
||||
instructions: Value(entity.instructions),
|
||||
enrichment: Value(entity.enrichment),
|
||||
tags: Value(entity.tags),
|
||||
videoUrl: Value(entity.videoUrl),
|
||||
);
|
||||
}
|
||||
|
||||
static ExercisesCompanion toUpdateCompanion(ExerciseEntity entity) {
|
||||
return ExercisesCompanion(
|
||||
name: Value(entity.name),
|
||||
instructions: Value(entity.instructions),
|
||||
enrichment: Value(entity.enrichment),
|
||||
tags: Value(entity.tags),
|
||||
videoUrl: Value(entity.videoUrl),
|
||||
);
|
||||
}
|
||||
}
|
||||
68
lib/data/mappers/program_mapper.dart
Normal file
68
lib/data/mappers/program_mapper.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/program.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/program_week.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/program_workout.dart';
|
||||
|
||||
class ProgramMapper {
|
||||
ProgramMapper._();
|
||||
|
||||
static ProgramEntity toEntity(Program row) {
|
||||
return ProgramEntity(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
createdAt: row.createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
static ProgramWeekEntity weekToEntity(ProgramWeek row) {
|
||||
return ProgramWeekEntity(
|
||||
id: row.id,
|
||||
programId: row.programId,
|
||||
position: row.position,
|
||||
notes: row.notes,
|
||||
);
|
||||
}
|
||||
|
||||
static ProgramWorkoutEntity workoutToEntity(ProgramWorkout row) {
|
||||
return ProgramWorkoutEntity(
|
||||
id: row.id,
|
||||
weekId: row.weekId,
|
||||
programId: row.programId,
|
||||
day: row.day,
|
||||
type: row.type,
|
||||
refId: row.refId,
|
||||
name: row.name,
|
||||
description: row.description,
|
||||
completed: row.completed,
|
||||
);
|
||||
}
|
||||
|
||||
static ProgramWorkoutsCompanion workoutToCompanion(
|
||||
ProgramWorkoutEntity entity) {
|
||||
return ProgramWorkoutsCompanion(
|
||||
id: Value(entity.id),
|
||||
weekId: Value(entity.weekId),
|
||||
programId: Value(entity.programId),
|
||||
day: Value(entity.day),
|
||||
type: Value(entity.type),
|
||||
refId: Value(entity.refId),
|
||||
name: Value(entity.name),
|
||||
description: Value(entity.description),
|
||||
completed: Value(entity.completed),
|
||||
);
|
||||
}
|
||||
|
||||
static ProgramWorkoutsCompanion workoutToUpdateCompanion(
|
||||
ProgramWorkoutEntity entity) {
|
||||
return ProgramWorkoutsCompanion(
|
||||
day: Value(entity.day),
|
||||
type: Value(entity.type),
|
||||
refId: Value(entity.refId),
|
||||
name: Value(entity.name),
|
||||
description: Value(entity.description),
|
||||
completed: Value(entity.completed),
|
||||
weekId: Value(entity.weekId),
|
||||
);
|
||||
}
|
||||
}
|
||||
87
lib/data/mappers/training_plan_mapper.dart
Normal file
87
lib/data/mappers/training_plan_mapper.dart
Normal file
@@ -0,0 +1,87 @@
|
||||
import 'dart:convert';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/training_plan.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/training_section.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/training_exercise.dart';
|
||||
|
||||
class TrainingPlanMapper {
|
||||
TrainingPlanMapper._();
|
||||
|
||||
static TrainingPlanEntity toEntity(TrainingPlan row) {
|
||||
final List<dynamic> sectionsJson =
|
||||
row.sections != null && row.sections!.isNotEmpty
|
||||
? jsonDecode(row.sections!) as List
|
||||
: [];
|
||||
return TrainingPlanEntity(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
sections: sectionsJson
|
||||
.map((s) => _mapSection(s as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
static TrainingSectionEntity _mapSection(Map<String, dynamic> json) {
|
||||
final exercisesJson = json['exercises'] as List<dynamic>? ?? [];
|
||||
return TrainingSectionEntity(
|
||||
id: json['id'] as String? ?? '',
|
||||
name: json['name'] as String? ?? '',
|
||||
exercises: exercisesJson
|
||||
.map((e) => _mapExercise(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
static TrainingExerciseEntity _mapExercise(Map<String, dynamic> json) {
|
||||
return TrainingExerciseEntity(
|
||||
instanceId: json['instanceId'] as String? ?? '',
|
||||
exerciseId: json['exerciseId'] as String? ?? '',
|
||||
name: json['name'] as String? ?? '',
|
||||
sets: json['sets'] as int? ?? 3,
|
||||
value: json['value'] as int? ?? 10,
|
||||
isTime: json['isTime'] as bool? ?? false,
|
||||
rest: json['rest'] as int? ?? 60,
|
||||
);
|
||||
}
|
||||
|
||||
static String sectionsToJson(List<TrainingSectionEntity> sections) {
|
||||
return jsonEncode(sections.map((s) => _sectionToMap(s)).toList());
|
||||
}
|
||||
|
||||
static Map<String, dynamic> _sectionToMap(TrainingSectionEntity section) {
|
||||
return {
|
||||
'id': section.id,
|
||||
'name': section.name,
|
||||
'exercises': section.exercises.map((e) => _exerciseToMap(e)).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
static Map<String, dynamic> _exerciseToMap(TrainingExerciseEntity exercise) {
|
||||
return {
|
||||
'instanceId': exercise.instanceId,
|
||||
'exerciseId': exercise.exerciseId,
|
||||
'name': exercise.name,
|
||||
'sets': exercise.sets,
|
||||
'value': exercise.value,
|
||||
'isTime': exercise.isTime,
|
||||
'rest': exercise.rest,
|
||||
};
|
||||
}
|
||||
|
||||
static TrainingPlansCompanion toInsertCompanion(
|
||||
String id, String name) {
|
||||
return TrainingPlansCompanion.insert(
|
||||
id: id,
|
||||
name: name,
|
||||
sections: const Value('[]'),
|
||||
);
|
||||
}
|
||||
|
||||
static TrainingPlansCompanion toUpdateCompanion(TrainingPlanEntity entity) {
|
||||
return TrainingPlansCompanion(
|
||||
name: Value(entity.name),
|
||||
sections: Value(sectionsToJson(entity.sections)),
|
||||
);
|
||||
}
|
||||
}
|
||||
90
lib/data/repositories/analysis_repository_impl.dart
Normal file
90
lib/data/repositories/analysis_repository_impl.dart
Normal file
@@ -0,0 +1,90 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/core/utils/id_generator.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/analysis_dao.dart';
|
||||
import 'package:trainhub_flutter/data/mappers/analysis_mapper.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/analysis_session.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/annotation.dart';
|
||||
import 'package:trainhub_flutter/domain/repositories/analysis_repository.dart';
|
||||
|
||||
class AnalysisRepositoryImpl implements AnalysisRepository {
|
||||
final AnalysisDao _dao;
|
||||
|
||||
AnalysisRepositoryImpl(this._dao);
|
||||
|
||||
@override
|
||||
Future<List<AnalysisSessionEntity>> getAllSessions() async {
|
||||
final rows = await _dao.getAllSessions();
|
||||
return rows.map(AnalysisMapper.sessionToEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AnalysisSessionEntity?> getSession(String id) async {
|
||||
final row = await _dao.getSession(id);
|
||||
return row == null ? null : AnalysisMapper.sessionToEntity(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AnalysisSessionEntity> createSession(
|
||||
String name, String videoPath) async {
|
||||
final String id = IdGenerator.generate();
|
||||
await _dao.insertSession(
|
||||
AnalysisSessionsCompanion.insert(
|
||||
id: id,
|
||||
name: name,
|
||||
videoPath: Value(videoPath),
|
||||
date: DateTime.now().toIso8601String(),
|
||||
),
|
||||
);
|
||||
final row = await _dao.getSession(id);
|
||||
return AnalysisMapper.sessionToEntity(row!);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteSession(String id) async {
|
||||
await _dao.deleteSession(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<AnnotationEntity>> getAnnotations(String sessionId) async {
|
||||
final rows = await _dao.getAnnotations(sessionId);
|
||||
return rows.map(AnalysisMapper.annotationToEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AnnotationEntity> addAnnotation({
|
||||
required String sessionId,
|
||||
required String name,
|
||||
required String description,
|
||||
required double startTime,
|
||||
required double endTime,
|
||||
required String color,
|
||||
}) async {
|
||||
final String id = IdGenerator.generate();
|
||||
await _dao.insertAnnotation(
|
||||
AnnotationsCompanion.insert(
|
||||
id: id,
|
||||
sessionId: sessionId,
|
||||
name: Value(name),
|
||||
description: Value(description),
|
||||
startTime: startTime,
|
||||
endTime: endTime,
|
||||
color: Value(color),
|
||||
),
|
||||
);
|
||||
return AnnotationEntity(
|
||||
id: id,
|
||||
sessionId: sessionId,
|
||||
startTime: startTime,
|
||||
endTime: endTime,
|
||||
name: name,
|
||||
description: description,
|
||||
color: color,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteAnnotation(String id) async {
|
||||
await _dao.deleteAnnotation(id);
|
||||
}
|
||||
}
|
||||
84
lib/data/repositories/chat_repository_impl.dart
Normal file
84
lib/data/repositories/chat_repository_impl.dart
Normal file
@@ -0,0 +1,84 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/core/utils/id_generator.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/chat_dao.dart';
|
||||
import 'package:trainhub_flutter/data/mappers/chat_mapper.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/chat_session.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/chat_message.dart';
|
||||
import 'package:trainhub_flutter/domain/repositories/chat_repository.dart';
|
||||
|
||||
class ChatRepositoryImpl implements ChatRepository {
|
||||
final ChatDao _dao;
|
||||
|
||||
ChatRepositoryImpl(this._dao);
|
||||
|
||||
@override
|
||||
Future<List<ChatSessionEntity>> getAllSessions() async {
|
||||
final rows = await _dao.getAllSessions();
|
||||
return rows.map(ChatMapper.sessionToEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ChatSessionEntity?> getSession(String id) async {
|
||||
final row = await _dao.getSession(id);
|
||||
return row == null ? null : ChatMapper.sessionToEntity(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ChatSessionEntity> createSession() async {
|
||||
final String id = IdGenerator.generate();
|
||||
final String now = DateTime.now().toIso8601String();
|
||||
await _dao.insertSession(
|
||||
ChatSessionsCompanion.insert(
|
||||
id: id,
|
||||
title: const Value('New Chat'),
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
),
|
||||
);
|
||||
final row = await _dao.getSession(id);
|
||||
return ChatMapper.sessionToEntity(row!);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteSession(String id) async {
|
||||
await _dao.deleteSession(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ChatMessageEntity>> getMessages(String sessionId) async {
|
||||
final rows = await _dao.getMessages(sessionId);
|
||||
return rows.map(ChatMapper.messageToEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ChatMessageEntity> addMessage({
|
||||
required String sessionId,
|
||||
required String role,
|
||||
required String content,
|
||||
}) async {
|
||||
final String id = IdGenerator.generate();
|
||||
final String now = DateTime.now().toIso8601String();
|
||||
await _dao.insertMessage(
|
||||
ChatMessagesCompanion.insert(
|
||||
id: id,
|
||||
sessionId: sessionId,
|
||||
role: role,
|
||||
content: content,
|
||||
createdAt: now,
|
||||
),
|
||||
);
|
||||
return ChatMessageEntity(
|
||||
id: id,
|
||||
sessionId: sessionId,
|
||||
role: role,
|
||||
content: content,
|
||||
createdAt: now,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateSessionTitle(String sessionId, String title) async {
|
||||
await _dao.updateSessionTitle(sessionId, title);
|
||||
}
|
||||
}
|
||||
53
lib/data/repositories/exercise_repository_impl.dart
Normal file
53
lib/data/repositories/exercise_repository_impl.dart
Normal file
@@ -0,0 +1,53 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/core/utils/id_generator.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/exercise_dao.dart';
|
||||
import 'package:trainhub_flutter/data/mappers/exercise_mapper.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/exercise.dart';
|
||||
import 'package:trainhub_flutter/domain/repositories/exercise_repository.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
|
||||
class ExerciseRepositoryImpl implements ExerciseRepository {
|
||||
final ExerciseDao _dao;
|
||||
|
||||
ExerciseRepositoryImpl(this._dao);
|
||||
|
||||
@override
|
||||
Future<List<ExerciseEntity>> getAll() async {
|
||||
final rows = await _dao.getAllExercises();
|
||||
return rows.map(ExerciseMapper.toEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ExerciseEntity> create({
|
||||
required String name,
|
||||
String? instructions,
|
||||
String? tags,
|
||||
String? videoUrl,
|
||||
}) async {
|
||||
final String id = IdGenerator.generate();
|
||||
await _dao.insertExercise(
|
||||
ExercisesCompanion.insert(
|
||||
id: id,
|
||||
name: name,
|
||||
instructions: Value(instructions),
|
||||
tags: Value(tags),
|
||||
videoUrl: Value(videoUrl),
|
||||
),
|
||||
);
|
||||
final row = await _dao.getExerciseById(id);
|
||||
return ExerciseMapper.toEntity(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> update(ExerciseEntity exercise) async {
|
||||
await _dao.updateExercise(
|
||||
exercise.id,
|
||||
ExerciseMapper.toUpdateCompanion(exercise),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> delete(String id) async {
|
||||
await _dao.deleteExercise(id);
|
||||
}
|
||||
}
|
||||
151
lib/data/repositories/program_repository_impl.dart
Normal file
151
lib/data/repositories/program_repository_impl.dart
Normal file
@@ -0,0 +1,151 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/core/utils/id_generator.dart';
|
||||
import 'package:trainhub_flutter/data/database/app_database.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/program_dao.dart';
|
||||
import 'package:trainhub_flutter/data/mappers/program_mapper.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/program.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/program_week.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/program_workout.dart';
|
||||
import 'package:trainhub_flutter/domain/repositories/program_repository.dart';
|
||||
|
||||
class ProgramRepositoryImpl implements ProgramRepository {
|
||||
final ProgramDao _dao;
|
||||
|
||||
ProgramRepositoryImpl(this._dao);
|
||||
|
||||
@override
|
||||
Future<List<ProgramEntity>> getAllPrograms() async {
|
||||
final rows = await _dao.getAllPrograms();
|
||||
return rows.map(ProgramMapper.toEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ProgramEntity?> getProgram(String id) async {
|
||||
final row = await _dao.getProgram(id);
|
||||
return row == null ? null : ProgramMapper.toEntity(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ProgramWeekEntity>> getWeeks(String programId) async {
|
||||
final rows = await _dao.getWeeks(programId);
|
||||
return rows.map(ProgramMapper.weekToEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ProgramWorkoutEntity>> getWorkouts(String programId) async {
|
||||
final rows = await _dao.getWorkouts(programId);
|
||||
return rows.map(ProgramMapper.workoutToEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ProgramEntity> createProgram(String name) async {
|
||||
final String id = IdGenerator.generate();
|
||||
await _dao.insertProgram(
|
||||
ProgramsCompanion.insert(
|
||||
id: id,
|
||||
name: name,
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
),
|
||||
);
|
||||
final row = await _dao.getProgram(id);
|
||||
return ProgramMapper.toEntity(row!);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteProgram(String id) async {
|
||||
await _dao.deleteProgram(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> duplicateProgram(String sourceId) async {
|
||||
final sourceProgram = await _dao.getProgram(sourceId);
|
||||
if (sourceProgram == null) return;
|
||||
final String newId = IdGenerator.generate();
|
||||
await _dao.insertProgram(
|
||||
ProgramsCompanion.insert(
|
||||
id: newId,
|
||||
name: '${sourceProgram.name} (Copy)',
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
),
|
||||
);
|
||||
final weeks = await _dao.getWeeks(sourceId);
|
||||
final workouts = await _dao.getWorkouts(sourceId);
|
||||
for (final week in weeks) {
|
||||
final String newWeekId = IdGenerator.generate();
|
||||
await _dao.insertWeek(
|
||||
ProgramWeeksCompanion.insert(
|
||||
id: newWeekId,
|
||||
programId: newId,
|
||||
position: week.position,
|
||||
notes: Value(week.notes),
|
||||
),
|
||||
);
|
||||
final weekWorkouts = workouts.where((w) => w.weekId == week.id);
|
||||
for (final workout in weekWorkouts) {
|
||||
await _dao.insertWorkout(
|
||||
ProgramWorkoutsCompanion.insert(
|
||||
id: IdGenerator.generate(),
|
||||
weekId: newWeekId,
|
||||
programId: newId,
|
||||
day: workout.day,
|
||||
type: workout.type,
|
||||
refId: Value(workout.refId),
|
||||
name: Value(workout.name),
|
||||
description: Value(workout.description),
|
||||
completed: const Value(false),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ProgramWeekEntity> addWeek(String programId, int position) async {
|
||||
final String id = IdGenerator.generate();
|
||||
await _dao.insertWeek(
|
||||
ProgramWeeksCompanion.insert(
|
||||
id: id,
|
||||
programId: programId,
|
||||
position: position,
|
||||
),
|
||||
);
|
||||
final weeks = await _dao.getWeeks(programId);
|
||||
final week = weeks.firstWhere((w) => w.id == id);
|
||||
return ProgramMapper.weekToEntity(week);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteWeek(String id) async {
|
||||
await _dao.deleteWeek(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateWeekNote(String weekId, String note) async {
|
||||
await _dao.updateWeekNote(weekId, note);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ProgramWorkoutEntity> addWorkout(
|
||||
ProgramWorkoutEntity workout) async {
|
||||
await _dao.insertWorkout(ProgramMapper.workoutToCompanion(workout));
|
||||
return workout;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateWorkout(ProgramWorkoutEntity workout) async {
|
||||
await _dao.updateWorkout(
|
||||
workout.id,
|
||||
ProgramMapper.workoutToUpdateCompanion(workout),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteWorkout(String id) async {
|
||||
await _dao.deleteWorkout(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> toggleWorkoutComplete(String id, bool currentStatus) async {
|
||||
await _dao.toggleWorkoutComplete(id, currentStatus);
|
||||
}
|
||||
}
|
||||
40
lib/data/repositories/training_plan_repository_impl.dart
Normal file
40
lib/data/repositories/training_plan_repository_impl.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import 'package:trainhub_flutter/core/utils/id_generator.dart';
|
||||
import 'package:trainhub_flutter/data/database/daos/training_plan_dao.dart';
|
||||
import 'package:trainhub_flutter/data/mappers/training_plan_mapper.dart';
|
||||
import 'package:trainhub_flutter/domain/entities/training_plan.dart';
|
||||
import 'package:trainhub_flutter/domain/repositories/training_plan_repository.dart';
|
||||
|
||||
class TrainingPlanRepositoryImpl implements TrainingPlanRepository {
|
||||
final TrainingPlanDao _dao;
|
||||
|
||||
TrainingPlanRepositoryImpl(this._dao);
|
||||
|
||||
@override
|
||||
Future<List<TrainingPlanEntity>> getAll() async {
|
||||
final rows = await _dao.getAllPlans();
|
||||
return rows.map(TrainingPlanMapper.toEntity).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TrainingPlanEntity> getById(String id) async {
|
||||
final row = await _dao.getPlanById(id);
|
||||
return TrainingPlanMapper.toEntity(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TrainingPlanEntity> create(String name) async {
|
||||
final String id = IdGenerator.generate();
|
||||
await _dao.insertPlan(TrainingPlanMapper.toInsertCompanion(id, name));
|
||||
return getById(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> update(TrainingPlanEntity plan) async {
|
||||
await _dao.updatePlan(plan.id, TrainingPlanMapper.toUpdateCompanion(plan));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> delete(String id) async {
|
||||
await _dao.deletePlan(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user