Initial commit
This commit is contained in:
235
lib/providers/program_provider.dart
Normal file
235
lib/providers/program_provider.dart
Normal file
@@ -0,0 +1,235 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:trainhub_flutter/database/database.dart';
|
||||
|
||||
class ProgramProvider extends ChangeNotifier {
|
||||
final AppDatabase database;
|
||||
|
||||
List<Program> _programs = [];
|
||||
Program? _activeProgram;
|
||||
List<ProgramWeek> _activeWeeks = [];
|
||||
List<ProgramWorkout> _activeWorkouts = [];
|
||||
|
||||
List<Program> get programs => _programs;
|
||||
Program? get activeProgram => _activeProgram;
|
||||
List<ProgramWeek> get activeWeeks => _activeWeeks;
|
||||
List<ProgramWorkout> get activeWorkouts => _activeWorkouts;
|
||||
|
||||
ProgramProvider(this.database) {
|
||||
_loadPrograms();
|
||||
}
|
||||
|
||||
Future<void> _loadPrograms() async {
|
||||
_programs =
|
||||
await (database.select(database.programs)..orderBy([
|
||||
(t) => OrderingTerm(
|
||||
expression: t.createdAt,
|
||||
mode: OrderingMode.desc,
|
||||
),
|
||||
]))
|
||||
.get();
|
||||
|
||||
// Auto-select most recent if none selected, or re-verify active one
|
||||
if (_activeProgram == null && _programs.isNotEmpty) {
|
||||
await loadProgram(_programs.first.id);
|
||||
} else if (_activeProgram != null) {
|
||||
// Refresh active program data
|
||||
await loadProgram(_activeProgram!.id);
|
||||
} else {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> loadProgram(String id) async {
|
||||
final program = await (database.select(
|
||||
database.programs,
|
||||
)..where((t) => t.id.equals(id))).getSingleOrNull();
|
||||
if (program != null) {
|
||||
_activeProgram = program;
|
||||
await _loadProgramDetails(id);
|
||||
} else {
|
||||
_activeProgram = null;
|
||||
_activeWeeks = [];
|
||||
_activeWorkouts = [];
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadProgramDetails(String programId) async {
|
||||
_activeWeeks =
|
||||
await (database.select(database.programWeeks)
|
||||
..where((t) => t.programId.equals(programId))
|
||||
..orderBy([(t) => OrderingTerm(expression: t.position)]))
|
||||
.get();
|
||||
|
||||
_activeWorkouts = await (database.select(
|
||||
database.programWorkouts,
|
||||
)..where((t) => t.programId.equals(programId))).get();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// --- Program Actions ---
|
||||
|
||||
Future<void> createProgram(String name) async {
|
||||
final id = DateTime.now().toIso8601String();
|
||||
await database
|
||||
.into(database.programs)
|
||||
.insert(
|
||||
ProgramsCompanion.insert(
|
||||
id: id,
|
||||
name: name,
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
),
|
||||
);
|
||||
await _loadPrograms();
|
||||
await loadProgram(id);
|
||||
}
|
||||
|
||||
Future<void> deleteProgram(String id) async {
|
||||
await (database.delete(
|
||||
database.programs,
|
||||
)..where((t) => t.id.equals(id))).go();
|
||||
if (_activeProgram?.id == id) {
|
||||
_activeProgram = null;
|
||||
}
|
||||
await _loadPrograms();
|
||||
}
|
||||
|
||||
Future<void> duplicateProgram(String sourceId) async {
|
||||
final sourceProgram = await (database.select(
|
||||
database.programs,
|
||||
)..where((t) => t.id.equals(sourceId))).getSingle();
|
||||
|
||||
final newId = DateTime.now().toIso8601String();
|
||||
await database
|
||||
.into(database.programs)
|
||||
.insert(
|
||||
ProgramsCompanion.insert(
|
||||
id: newId,
|
||||
name: '${sourceProgram.name} (Copy)',
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
),
|
||||
);
|
||||
|
||||
// Duplicate Weeks and Workouts
|
||||
// Note: implementing deep copy logic
|
||||
final weeks = await (database.select(
|
||||
database.programWeeks,
|
||||
)..where((t) => t.programId.equals(sourceId))).get();
|
||||
final workouts = await (database.select(
|
||||
database.programWorkouts,
|
||||
)..where((t) => t.programId.equals(sourceId))).get();
|
||||
|
||||
for (var week in weeks) {
|
||||
final newWeekId = '${newId}_${week.position}'; // Simple ID gen
|
||||
await database
|
||||
.into(database.programWeeks)
|
||||
.insert(
|
||||
ProgramWeeksCompanion.insert(
|
||||
id: newWeekId,
|
||||
programId: newId,
|
||||
position: week.position,
|
||||
notes: Value(week.notes),
|
||||
),
|
||||
);
|
||||
|
||||
final weekWorkouts = workouts.where((w) => w.weekId == week.id);
|
||||
for (var workout in weekWorkouts) {
|
||||
final newWorkoutId =
|
||||
DateTime.now().toIso8601String() + workout.id; // ensure uniqueness
|
||||
await database
|
||||
.into(database.programWorkouts)
|
||||
.insert(
|
||||
ProgramWorkoutsCompanion.insert(
|
||||
id: newWorkoutId,
|
||||
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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await _loadPrograms();
|
||||
await loadProgram(newId);
|
||||
}
|
||||
|
||||
// --- Week Actions ---
|
||||
|
||||
Future<void> addWeek() async {
|
||||
if (_activeProgram == null) return;
|
||||
final nextPosition = _activeWeeks.isEmpty
|
||||
? 1
|
||||
: _activeWeeks.last.position + 1;
|
||||
final id = DateTime.now().toIso8601String();
|
||||
|
||||
await database
|
||||
.into(database.programWeeks)
|
||||
.insert(
|
||||
ProgramWeeksCompanion.insert(
|
||||
id: id,
|
||||
programId: _activeProgram!.id,
|
||||
position: nextPosition,
|
||||
),
|
||||
);
|
||||
await _loadProgramDetails(_activeProgram!.id);
|
||||
}
|
||||
|
||||
Future<void> deleteWeek(String id) async {
|
||||
if (_activeProgram == null) return;
|
||||
await (database.delete(
|
||||
database.programWeeks,
|
||||
)..where((t) => t.id.equals(id))).go();
|
||||
await _loadProgramDetails(_activeProgram!.id);
|
||||
}
|
||||
|
||||
Future<void> updateWeekNote(String weekId, String note) async {
|
||||
await (database.update(database.programWeeks)
|
||||
..where((t) => t.id.equals(weekId)))
|
||||
.write(ProgramWeeksCompanion(notes: Value(note)));
|
||||
if (_activeProgram != null) await _loadProgramDetails(_activeProgram!.id);
|
||||
}
|
||||
|
||||
// --- Workout Actions ---
|
||||
|
||||
Future<void> addWorkout(ProgramWorkoutsCompanion workout) async {
|
||||
await database.into(database.programWorkouts).insert(workout);
|
||||
if (_activeProgram != null) await _loadProgramDetails(_activeProgram!.id);
|
||||
}
|
||||
|
||||
Future<void> updateWorkout(ProgramWorkout workout) async {
|
||||
await (database.update(
|
||||
database.programWorkouts,
|
||||
)..where((t) => t.id.equals(workout.id))).write(
|
||||
ProgramWorkoutsCompanion(
|
||||
day: Value(workout.day),
|
||||
type: Value(workout.type),
|
||||
refId: Value(workout.refId),
|
||||
name: Value(workout.name),
|
||||
description: Value(workout.description),
|
||||
completed: Value(workout.completed),
|
||||
weekId: Value(workout.weekId),
|
||||
),
|
||||
);
|
||||
if (_activeProgram != null) await _loadProgramDetails(_activeProgram!.id);
|
||||
}
|
||||
|
||||
Future<void> deleteWorkout(String id) async {
|
||||
await (database.delete(
|
||||
database.programWorkouts,
|
||||
)..where((t) => t.id.equals(id))).go();
|
||||
if (_activeProgram != null) await _loadProgramDetails(_activeProgram!.id);
|
||||
}
|
||||
|
||||
Future<void> toggleWorkoutComplete(String id, bool currentStatus) async {
|
||||
await (database.update(database.programWorkouts)
|
||||
..where((t) => t.id.equals(id)))
|
||||
.write(ProgramWorkoutsCompanion(completed: Value(!currentStatus)));
|
||||
if (_activeProgram != null) await _loadProgramDetails(_activeProgram!.id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user