diff --git a/lib/main.dart b/lib/main.dart index d4ab18b..ae13015 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:kettlebell_tracker/providers/settings_provider.dart'; import 'package:kettlebell_tracker/screens/home_screen.dart'; import 'package:kettlebell_tracker/screens/settings_screen.dart'; import 'package:kettlebell_tracker/screens/training_screen.dart'; @@ -58,6 +59,14 @@ class _MainScreenState extends ConsumerState { }); } + @override + void initState() { + super.initState(); + Future.microtask(() { + ref.read(settingsProvider.notifier).loadSettings(); + }); + } + @override Widget build(BuildContext context) { final theme = Theme.of(context); diff --git a/lib/models/training_session.dart b/lib/models/training_session.dart index b9c9595..88c0de6 100644 --- a/lib/models/training_session.dart +++ b/lib/models/training_session.dart @@ -6,7 +6,8 @@ class TrainingSession { final double weightRight; final int repsPerSet; final int duration; // in seconds - final String notes; + final String program; + final int blockDay; TrainingSession({ this.id, @@ -16,7 +17,8 @@ class TrainingSession { required this.weightRight, required this.repsPerSet, required this.duration, - required this.notes, + required this.program, + required this.blockDay, }); // Convert a TrainingSession into a Map. The keys must correspond to the names of the @@ -30,7 +32,8 @@ class TrainingSession { 'weightRight': weightRight, 'repsPerSet': repsPerSet, 'duration': duration, - 'notes': notes, + 'program': program, + 'blockDay': blockDay, }; } @@ -44,12 +47,37 @@ class TrainingSession { weightRight: map['weightRight'], repsPerSet: map['repsPerSet'], duration: map['duration'], - notes: map['notes'], + program: map['program'] ?? 'giant_1.0', + blockDay: map['blockDay'] ?? 1, + ); + } + + TrainingSession copyWith({ + int? id, + DateTime? date, + int? sets, + double? weightLeft, + double? weightRight, + int? repsPerSet, + int? duration, + String? program, + int? blockDay, + }) { + return TrainingSession( + id: id ?? this.id, + date: date ?? this.date, + sets: sets ?? this.sets, + weightLeft: weightLeft ?? this.weightLeft, + weightRight: weightRight ?? this.weightRight, + repsPerSet: repsPerSet ?? this.repsPerSet, + duration: duration ?? this.duration, + program: program ?? this.program, + blockDay: blockDay ?? this.blockDay, ); } @override String toString() { - return 'TrainingSession{id: $id, date: $date, sets: $sets, notes: $notes}'; + return 'TrainingSession{id: $id, date: $date, sets: $sets}'; } } diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 4cfb85f..3be9ff6 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -1,37 +1,34 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class SettingsState { final int trainingTimeMinutes; final double weightLeft; final double weightRight; - final int repsPerSet; final int goalSets; - final String notes; + final String initialProgram; SettingsState({ this.trainingTimeMinutes = 20, this.weightLeft = 16.0, this.weightRight = 16.0, - this.repsPerSet = 5, this.goalSets = 5, - this.notes = "", + this.initialProgram = 'giant_1.0', }); SettingsState copyWith({ int? trainingTimeMinutes, double? weightLeft, double? weightRight, - int? repsPerSet, int? goalSets, - String? notes, + String? initialProgram, }) { return SettingsState( trainingTimeMinutes: trainingTimeMinutes ?? this.trainingTimeMinutes, weightLeft: weightLeft ?? this.weightLeft, weightRight: weightRight ?? this.weightRight, - repsPerSet: repsPerSet ?? this.repsPerSet, goalSets: goalSets ?? this.goalSets, - notes: notes ?? this.notes, + initialProgram: initialProgram ?? this.initialProgram, ); } } @@ -39,9 +36,30 @@ class SettingsState { class SettingsNotifier extends StateNotifier { SettingsNotifier() : super(SettingsState()); - void updateSettings(SettingsState newSettings) { + Future loadSettings() async { + final prefs = await SharedPreferences.getInstance(); + state = SettingsState( + trainingTimeMinutes: prefs.getInt('trainingTimeMinutes') ?? 20, + weightLeft: prefs.getDouble('weightLeft') ?? 16.0, + weightRight: prefs.getDouble('weightRight') ?? 16.0, + goalSets: prefs.getInt('goalSets') ?? 5, + initialProgram: prefs.getString('initialProgram') ?? 'giant_1.0', + ); + } + + Future saveSettings(SettingsState newSettings) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt('trainingTimeMinutes', newSettings.trainingTimeMinutes); + await prefs.setDouble('weightLeft', newSettings.weightLeft); + await prefs.setDouble('weightRight', newSettings.weightRight); + await prefs.setInt('goalSets', newSettings.goalSets); + await prefs.setString('initialProgram', newSettings.initialProgram); state = newSettings; } + + Future updateSettings(SettingsState newSettings) async { + await saveSettings(newSettings); + } } final settingsProvider = StateNotifierProvider( diff --git a/lib/providers/training_provider.dart b/lib/providers/training_provider.dart index dc71e42..58a95f5 100644 --- a/lib/providers/training_provider.dart +++ b/lib/providers/training_provider.dart @@ -16,6 +16,10 @@ class TrainingState { final double progress; final int secondsSinceLastSet; final DateTime? lastSetTimestamp; + final String currentProgram; + final int currentBlockDay; + final int currentReps; + final int totalTrainingDays; TrainingState({ this.isTrainingRunning = false, @@ -28,6 +32,10 @@ class TrainingState { this.progress = 0.0, this.secondsSinceLastSet = 0, this.lastSetTimestamp, + this.currentProgram = 'giant_1.0', + this.currentBlockDay = 1, + this.currentReps = 5, + this.totalTrainingDays = 0, }); TrainingState copyWith({ @@ -42,6 +50,10 @@ class TrainingState { int? secondsSinceLastSet, DateTime? lastSetTimestamp, bool clearLastSetTimestamp = false, + String? currentProgram, + int? currentBlockDay, + int? currentReps, + int? totalTrainingDays, }) { return TrainingState( isTrainingRunning: isTrainingRunning ?? this.isTrainingRunning, @@ -57,6 +69,10 @@ class TrainingState { lastSetTimestamp: clearLastSetTimestamp ? null : lastSetTimestamp ?? this.lastSetTimestamp, + currentProgram: currentProgram ?? this.currentProgram, + currentBlockDay: currentBlockDay ?? this.currentBlockDay, + currentReps: currentReps ?? this.currentReps, + totalTrainingDays: totalTrainingDays ?? this.totalTrainingDays, ); } } @@ -65,14 +81,71 @@ class TrainingNotifier extends StateNotifier { final Ref ref; TrainingNotifier(this.ref) : super(TrainingState()); - void startTraining(int minutes, int reps, int goal) { + void _updateProgram() { + int newTotalDays = state.totalTrainingDays + 1; + String newProgram = state.currentProgram; + int newDay = (state.currentBlockDay % 3) + 1; + int newReps = state.currentReps; + + if (newTotalDays > 0 && newTotalDays % 12 == 0) { + switch (state.currentProgram) { + case 'giant_1.0': + newProgram = 'giant_1.1'; + break; + case 'giant_1.1': + newProgram = 'giant_1.2'; + break; + case 'giant_1.2': + newProgram = 'ksk_1.0'; + break; + case 'ksk_1.0': + newProgram = 'ksk_1.1'; + break; + case 'ksk_1.1': + newProgram = 'ksk_1.2'; + break; + case 'ksk_1.2': + newProgram = 'giant_1.0'; + break; + default: + newProgram = 'giant_1.0'; + } + newDay = 1; + } + + if (newProgram == 'giant_1.0') { + newReps = [5, 6, 4][newDay - 1]; + } else if (newProgram == 'giant_1.1') { + newReps = [6, 8, 7][newDay - 1]; + } else if (newProgram == 'giant_1.2') { + newReps = [7, 9, 8][newDay - 1]; + } else if (newProgram == 'ksk_1.0') { + newReps = [5, 6, 4][newDay - 1]; + } else if (newProgram == 'ksk_1.1') { + newReps = [6, 8, 7][newDay - 1]; + } else if (newProgram == 'ksk_1.2') { + newReps = [7, 9, 8][newDay - 1]; + } else { + newReps = 5; + } + + state = state.copyWith( + currentProgram: newProgram, + currentBlockDay: newDay, + currentReps: newReps, + totalTrainingDays: newTotalDays, + ); + } + + void startTraining(int minutes, int goal) { + _updateProgram(); final duration = minutes * 60; - state = TrainingState( + state = state.copyWith( isTrainingRunning: true, initialDurationSeconds: duration, remainingSeconds: duration, - repsPerSet: reps, goalSets: goal, + repsPerSet: state.currentReps, ); } @@ -107,11 +180,19 @@ class TrainingNotifier extends StateNotifier { } Future finishTraining(TrainingSession session) async { - await DatabaseHelper().saveTraining(session); - await sendTrainingToBackend( - reps: session.repsPerSet, - rest: session.duration / session.sets, - sets: session.sets); + final updatedSession = session.copyWith( + program: state.currentProgram, + blockDay: state.currentBlockDay, + ); + await DatabaseHelper().saveTraining(updatedSession); + try { + await sendTrainingToBackend( + reps: session.repsPerSet, + rest: session.duration / session.sets, + sets: session.sets); + } catch (e) { + print("Error sending information to backend"); + } ref.refresh(historyProvider); resetTraining(); } diff --git a/lib/screens/history_screen.dart b/lib/screens/history_screen.dart index 4b2b3de..32b1351 100644 --- a/lib/screens/history_screen.dart +++ b/lib/screens/history_screen.dart @@ -86,11 +86,6 @@ class HistoryItemCard extends StatelessWidget { 'Reps pro Satz: ${session.repsPerSet}'), _buildInfoRow( Icons.timer, 'Dauer: ${formatDuration(session.duration)}'), - if (session.notes.isNotEmpty) ...[ - const SizedBox(height: 8), - _buildInfoRow(Icons.note, 'Notizen: ${session.notes}', - isNote: true), - ] ], ), ); diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 0b0ae67..9bee64f 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -18,9 +18,7 @@ class _SettingsScreenState extends ConsumerState { late TextEditingController _trainingTimeController; late TextEditingController _weightLeftController; late TextEditingController _weightRightController; - late TextEditingController _repsController; late TextEditingController _goalSetsController; - late TextEditingController _notesController; @override void initState() { @@ -35,13 +33,9 @@ class _SettingsScreenState extends ConsumerState { _weightRightController = TextEditingController( text: settings.weightRight.toString(), ); - _repsController = TextEditingController( - text: settings.repsPerSet.toString(), - ); _goalSetsController = TextEditingController( text: settings.goalSets.toString(), ); - _notesController = TextEditingController(text: settings.notes); } @override @@ -49,9 +43,7 @@ class _SettingsScreenState extends ConsumerState { _trainingTimeController.dispose(); _weightLeftController.dispose(); _weightRightController.dispose(); - _repsController.dispose(); _goalSetsController.dispose(); - _notesController.dispose(); super.dispose(); } @@ -61,9 +53,7 @@ class _SettingsScreenState extends ConsumerState { trainingTimeMinutes: int.parse(_trainingTimeController.text), weightLeft: double.parse(_weightLeftController.text), weightRight: double.parse(_weightRightController.text), - repsPerSet: int.parse(_repsController.text), goalSets: int.parse(_goalSetsController.text), - notes: _notesController.text, ); ref.read(settingsProvider.notifier).updateSettings(newSettings); ScaffoldMessenger.of(context).showSnackBar( @@ -123,12 +113,6 @@ class _SettingsScreenState extends ConsumerState { keyboardType: TextInputType.number, ), const SizedBox(height: 16), - CustomTextField( - controller: _repsController, - labelText: "Reps pro Satz", - icon: Icons.repeat, - keyboardType: TextInputType.number, - ), const SizedBox(height: 16), CustomTextField( controller: _goalSetsController, @@ -139,25 +123,6 @@ class _SettingsScreenState extends ConsumerState { ], ), ), - const SizedBox(height: 20), - CustomCard( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Zusätzliche Notizen", - style: Theme.of(context).textTheme.titleLarge, - ), - const SizedBox(height: 20), - CustomTextField( - controller: _notesController, - labelText: "Notizen für nächstes Training", - icon: Icons.note, - maxLines: 4, - ), - ], - ), - ), const SizedBox(height: 24), ElevatedButton.icon( onPressed: _saveSettings, diff --git a/lib/screens/training_screen.dart b/lib/screens/training_screen.dart index 88dd8b4..2f75c01 100644 --- a/lib/screens/training_screen.dart +++ b/lib/screens/training_screen.dart @@ -34,7 +34,6 @@ class _TrainingScreenState extends ConsumerState { final settings = ref.read(settingsProvider); ref.read(trainingProvider.notifier).startTraining( settings.trainingTimeMinutes, - settings.repsPerSet, settings.goalSets, ); @@ -82,9 +81,10 @@ class _TrainingScreenState extends ConsumerState { sets: state.setsDone, weightLeft: settings.weightLeft, weightRight: settings.weightRight, - repsPerSet: settings.repsPerSet, + repsPerSet: state.currentReps, duration: state.initialDurationSeconds - state.remainingSeconds, - notes: settings.notes, + program: state.currentProgram, + blockDay: state.currentBlockDay, ); ref.read(trainingProvider.notifier).finishTraining(session); @@ -121,7 +121,6 @@ class _TrainingScreenState extends ConsumerState { @override Widget build(BuildContext context) { final trainingState = ref.watch(trainingProvider); - final settings = ref.watch(settingsProvider); final bool isTrainingRunning = trainingState.isTrainingRunning; return Scaffold( @@ -129,47 +128,66 @@ class _TrainingScreenState extends ConsumerState { body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + // Header-Bereich mit Programm-Infos CustomCard( child: Column( children: [ Text( - 'Verbleibende Zeit: ${_formatDuration(trainingState.remainingSeconds)}', + '${trainingState.currentProgram.toUpperCase()}', style: const TextStyle( - fontSize: 26, + fontSize: 28, fontWeight: FontWeight.bold, color: AppTheme.oneDarkPrimary, ), ), - const SizedBox(height: 12), Text( - 'Sätze: ${trainingState.setsDone}', - style: const TextStyle( - fontSize: 24, - color: AppTheme.oneDarkYellow, - ), - ), - const SizedBox(height: 8), - Text( - 'Reps pro Satz: ${settings.repsPerSet}', + 'Block Tag: ${trainingState.currentBlockDay}', style: const TextStyle( fontSize: 20, color: AppTheme.oneDarkAccent, ), ), - const SizedBox(height: 12), Text( - 'Zeit seit letztem Satz: ${_formatDuration(trainingState.secondsSinceLastSet)}', + 'Reps pro Satz: ${trainingState.currentReps}', style: const TextStyle( - fontSize: 18, + fontSize: 22, + fontWeight: FontWeight.w500, + color: AppTheme.oneDarkYellow, + ), + ), + ], + ), + ), + const SizedBox(height: 18), + + // Timer und Fortschritt + CustomCard( + child: Column( + children: [ + const Text( + 'Verbleibende Zeit', + style: TextStyle( + fontSize: 16, color: AppTheme.oneDarkTextWeak, ), ), - const SizedBox(height: 20), + Text( + _formatDuration(trainingState.remainingSeconds), + style: const TextStyle( + fontSize: 40, + fontWeight: FontWeight.bold, + color: AppTheme.oneDarkPrimary, + ), + ), + const SizedBox(height: 10), LinearProgressIndicator( value: trainingState.progress, - minHeight: 10, - borderRadius: BorderRadius.circular(5), + minHeight: 12, + borderRadius: BorderRadius.circular(6), + color: AppTheme.oneDarkGreen, + backgroundColor: AppTheme.oneDarkTextWeak, ), const SizedBox(height: 8), Text( @@ -182,51 +200,58 @@ class _TrainingScreenState extends ConsumerState { ], ), ), - const SizedBox(height: 20), + const SizedBox(height: 18), + + // Aktions-Buttons Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton.icon( onPressed: isTrainingRunning ? null : _startTraining, - icon: const Icon(Icons.play_arrow), - label: const Text('Start'), + icon: const Icon(Icons.play_arrow, size: 28), + label: const Text('Start', style: TextStyle(fontSize: 18)), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.oneDarkGreen, - foregroundColor: AppTheme.oneDarkTextWeak, + foregroundColor: Colors.white, + minimumSize: const Size(110, 48), ), ), ElevatedButton.icon( onPressed: !isTrainingRunning ? null : _completeSet, - icon: const Icon(Icons.check_circle), - label: const Text('Satz'), + icon: const Icon(Icons.check_circle, size: 28), + label: const Text('Satz', style: TextStyle(fontSize: 18)), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.oneDarkPrimary, - foregroundColor: AppTheme.oneDarkTextWeak, + foregroundColor: Colors.white, + minimumSize: const Size(110, 48), ), ), ElevatedButton.icon( onPressed: !isTrainingRunning ? null : _finishTraining, - icon: const Icon(Icons.stop), - label: const Text('Beenden'), + icon: const Icon(Icons.stop, size: 28), + label: const Text('Beenden', style: TextStyle(fontSize: 18)), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.oneDarkRed, - foregroundColor: AppTheme.oneDarkTextWeak, + foregroundColor: Colors.white, + minimumSize: const Size(110, 48), ), ), ], ), - const SizedBox(height: 20), - const Divider(), + const SizedBox(height: 22), + + // Satz-Historie Text( "Satz-Historie", - style: Theme.of( - context, - ).textTheme.titleLarge?.copyWith(color: AppTheme.oneDarkAccent), + style: Theme.of(context).textTheme.titleLarge?.copyWith( + color: AppTheme.oneDarkAccent, + fontWeight: FontWeight.bold, + ), ), const SizedBox(height: 10), CustomCard( child: SizedBox( - height: 150, + height: 180, child: trainingState.setTimes.isEmpty ? const Center( child: Text( @@ -234,13 +259,25 @@ class _TrainingScreenState extends ConsumerState { style: TextStyle(color: AppTheme.oneDarkTextWeak), ), ) - : ListView.builder( + : ListView.separated( itemCount: trainingState.setTimes.length, + separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, index) { final setTime = trainingState.setTimes[index]; - return Center( - child: Text( - '#${index + 1} um ${DateFormat.Hms().format(setTime)} (${settings.repsPerSet} Reps)', + return ListTile( + leading: CircleAvatar( + backgroundColor: AppTheme.oneDarkGreen, + child: Text( + '${index + 1}', + style: const TextStyle(color: Colors.white), + ), + ), + title: Text( + 'um ${DateFormat.Hms().format(setTime)}', + style: const TextStyle(fontSize: 16), + ), + trailing: Text( + '${trainingState.currentReps} Reps', style: const TextStyle( fontSize: 16, color: AppTheme.oneDarkGreen, @@ -256,4 +293,156 @@ class _TrainingScreenState extends ConsumerState { ), ); } + + // @override + // Widget build(BuildContext context) { + // final trainingState = ref.watch(trainingProvider); + // final settings = ref.watch(settingsProvider); + // final bool isTrainingRunning = trainingState.isTrainingRunning; + // + // return Scaffold( + // appBar: AppBar(title: const Text('Aktuelles Training')), + // body: SingleChildScrollView( + // padding: const EdgeInsets.all(16.0), + // child: Column( + // children: [ + // CustomCard( + // child: Column( + // children: [ + // Text( + // 'Programm: ${trainingState.currentProgram.toUpperCase()}', + // style: const TextStyle( + // fontSize: 20, + // color: AppTheme.oneDarkYellow, + // ), + // ), + // Text( + // 'Block Tag: ${trainingState.currentBlockDay}', + // style: const TextStyle( + // fontSize: 18, + // color: AppTheme.oneDarkAccent, + // ), + // ), + // Text( + // 'Verbleibende Zeit: ${_formatDuration(trainingState.remainingSeconds)}', + // style: const TextStyle( + // fontSize: 26, + // fontWeight: FontWeight.bold, + // color: AppTheme.oneDarkPrimary, + // ), + // ), + // const SizedBox(height: 12), + // Text( + // 'Sätze: ${trainingState.setsDone}', + // style: const TextStyle( + // fontSize: 24, + // color: AppTheme.oneDarkYellow, + // ), + // ), + // const SizedBox(height: 8), + // Text( + // 'Reps pro Satz: ${trainingState.currentReps}', + // style: const TextStyle( + // fontSize: 20, + // color: AppTheme.oneDarkAccent, + // ), + // ), + // const SizedBox(height: 12), + // Text( + // 'Zeit seit letztem Satz: ${_formatDuration(trainingState.secondsSinceLastSet)}', + // style: const TextStyle( + // fontSize: 18, + // color: AppTheme.oneDarkTextWeak, + // ), + // ), + // const SizedBox(height: 20), + // LinearProgressIndicator( + // value: trainingState.progress, + // minHeight: 10, + // borderRadius: BorderRadius.circular(5), + // ), + // const SizedBox(height: 8), + // Text( + // 'Fortschritt: ${(trainingState.progress * 100).toStringAsFixed(0)}%', + // style: const TextStyle( + // fontSize: 16, + // color: AppTheme.oneDarkText, + // ), + // ), + // ], + // ), + // ), + // const SizedBox(height: 20), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, + // children: [ + // ElevatedButton.icon( + // onPressed: isTrainingRunning ? null : _startTraining, + // icon: const Icon(Icons.play_arrow), + // label: const Text('Start'), + // style: ElevatedButton.styleFrom( + // backgroundColor: AppTheme.oneDarkGreen, + // foregroundColor: AppTheme.oneDarkTextWeak, + // ), + // ), + // ElevatedButton.icon( + // onPressed: !isTrainingRunning ? null : _completeSet, + // icon: const Icon(Icons.check_circle), + // label: const Text('Satz'), + // style: ElevatedButton.styleFrom( + // backgroundColor: AppTheme.oneDarkPrimary, + // foregroundColor: AppTheme.oneDarkTextWeak, + // ), + // ), + // ElevatedButton.icon( + // onPressed: !isTrainingRunning ? null : _finishTraining, + // icon: const Icon(Icons.stop), + // label: const Text('Beenden'), + // style: ElevatedButton.styleFrom( + // backgroundColor: AppTheme.oneDarkRed, + // foregroundColor: AppTheme.oneDarkTextWeak, + // ), + // ), + // ], + // ), + // const SizedBox(height: 20), + // const Divider(), + // Text( + // "Satz-Historie", + // style: Theme.of( + // context, + // ).textTheme.titleLarge?.copyWith(color: AppTheme.oneDarkAccent), + // ), + // const SizedBox(height: 10), + // CustomCard( + // child: SizedBox( + // height: 150, + // child: trainingState.setTimes.isEmpty + // ? const Center( + // child: Text( + // "Noch keine Sätze in dieser Einheit.", + // style: TextStyle(color: AppTheme.oneDarkTextWeak), + // ), + // ) + // : ListView.builder( + // itemCount: trainingState.setTimes.length, + // itemBuilder: (context, index) { + // final setTime = trainingState.setTimes[index]; + // return Center( + // child: Text( + // '#${index + 1} um ${DateFormat.Hms().format(setTime)} (${trainingState.currentReps} Reps)', + // style: const TextStyle( + // fontSize: 16, + // color: AppTheme.oneDarkGreen, + // ), + // ), + // ); + // }, + // ), + // ), + // ), + // ], + // ), + // ), + // ); } diff --git a/lib/services/api_service.dart b/lib/services/api_service.dart index 63b47b6..50d804a 100644 --- a/lib/services/api_service.dart +++ b/lib/services/api_service.dart @@ -9,17 +9,19 @@ Future sendTrainingToBackend({ required int sets, }) async { final uuid = await DeviceIdService.getOrCreateUUID(); - final url = Uri.parse('http://192.169.178.43:8000/trainings/'); - final response = await http.post( - url, - headers: {'Content-Type': 'application/json'}, - body: jsonEncode({ - 'reps': reps, - 'rest': rest, - 'sets': sets, - 'uuid': uuid, - }), - ); + final url = Uri.parse('http://192.169.178.43:8080/trainings/'); + final response = await http + .post( + url, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'reps': reps, + 'rest': rest, + 'sets': sets, + 'uuid': uuid, + }), + ) + .timeout(const Duration(seconds: 5)); if (response.statusCode == 200) { print('Training erfolgreich an Backend gesendet.'); } else { diff --git a/lib/services/database_helper.dart b/lib/services/database_helper.dart index a2f98e5..8529283 100644 --- a/lib/services/database_helper.dart +++ b/lib/services/database_helper.dart @@ -20,7 +20,19 @@ class DatabaseHelper { final dbPath = await getDatabasesPath(); final path = join(dbPath, 'giant_training.db'); - return await openDatabase(path, version: 1, onCreate: _onCreate); + return await openDatabase( + path, + version: 2, // Version erhöhen! + onCreate: _onCreate, + onUpgrade: _onUpgrade, + ); + } + + void _onUpgrade(Database db, int oldVersion, int newVersion) async { + if (oldVersion < 2) { + await db.execute('ALTER TABLE training ADD COLUMN program TEXT'); + await db.execute('ALTER TABLE training ADD COLUMN blockDay INTEGER'); + } } // Create the database table @@ -34,7 +46,8 @@ class DatabaseHelper { weightRight REAL, repsPerSet INTEGER, duration INTEGER, - notes TEXT + program TEXT, + blockDay INTEGER ) '''); }