Bugs in Trainingsplanung behoben
parent
9689d4b9ba
commit
ae6e2bd0ed
|
|
@ -3,6 +3,7 @@ import 'package:table_calendar/table_calendar.dart';
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'training_detail_screen.dart';
|
import 'training_detail_screen.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
const Map<String, Color> categoryColors = {
|
const Map<String, Color> categoryColors = {
|
||||||
'Aufwärmen & Mobilisation': Colors.deepOrange,
|
'Aufwärmen & Mobilisation': Colors.deepOrange,
|
||||||
|
|
@ -121,49 +122,107 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
|
|
||||||
for (var trainerDoc in trainersSnapshot.docs) {
|
for (var trainerDoc in trainersSnapshot.docs) {
|
||||||
final trainerData = trainerDoc.data() as Map<String, dynamic>;
|
final trainerData = trainerDoc.data() as Map<String, dynamic>;
|
||||||
|
final trainings = trainerData['trainings'] as Map<String, dynamic>? ?? {};
|
||||||
|
final cancelledTrainings = trainerData['cancelledTrainings'] as List<dynamic>? ?? [];
|
||||||
final trainingTimes = trainerData['trainingTimes'] as Map<String, dynamic>? ?? {};
|
final trainingTimes = trainerData['trainingTimes'] as Map<String, dynamic>? ?? {};
|
||||||
final trainingDurations = trainerData['trainingDurations'] as Map<String, dynamic>? ?? {};
|
final trainingDurations = trainerData['trainingDurations'] as Map<String, dynamic>? ?? {};
|
||||||
final cancelledTrainings = trainerData['cancelledTrainings'] as List<dynamic>? ?? [];
|
|
||||||
final trainingExercises = trainerData['trainingExercises'] as Map<String, dynamic>? ?? {};
|
|
||||||
|
|
||||||
// 1. Wochentagsbasierte Trainings (wie gehabt)
|
print('Lade Events:');
|
||||||
trainingTimes.forEach((day, timeStr) {
|
print('trainings: $trainings');
|
||||||
// Prüfe, ob der Key KEIN Datum ist (also ein Wochentag)
|
print('cancelledTrainings: $cancelledTrainings');
|
||||||
if (DateTime.tryParse(day) != null) return;
|
print('trainingTimes: $trainingTimes');
|
||||||
if (timeStr == null) return;
|
print('trainingDurations: $trainingDurations');
|
||||||
final duration = trainingDurations[day] as int? ?? 60;
|
|
||||||
final timeParts = (timeStr as String).split(':');
|
|
||||||
if (timeParts.length != 2) return;
|
|
||||||
final hour = int.tryParse(timeParts[0]) ?? 0;
|
|
||||||
final minute = int.tryParse(timeParts[1]) ?? 0;
|
|
||||||
|
|
||||||
final now = DateTime.now();
|
// Lade alle Trainings für das Datum
|
||||||
final daysUntilNext = _getDaysUntilNext(day, now.weekday);
|
trainings.forEach((dateString, trainingsList) {
|
||||||
final eventDate = DateTime(now.year, now.month, now.day + daysUntilNext, hour, minute);
|
final date = DateTime.tryParse(dateString);
|
||||||
|
if (date == null) return;
|
||||||
for (var i = 0; i < 52; i++) {
|
|
||||||
final date = eventDate.add(Duration(days: i * 7));
|
|
||||||
final normalizedDate = DateTime(date.year, date.month, date.day);
|
final normalizedDate = DateTime(date.year, date.month, date.day);
|
||||||
final dateString = normalizedDate.toIso8601String();
|
final list = List<Map<String, dynamic>>.from(trainingsList);
|
||||||
final isCancelled = cancelledTrainings.any((cancelled) {
|
for (final training in list) {
|
||||||
if (cancelled is Map<String, dynamic>) {
|
final timeStr = training['time'] as String? ?? '00:00';
|
||||||
final cancelledDate = DateTime.parse(cancelled['date'] as String);
|
final duration = training['duration'] as int? ?? 60;
|
||||||
return isSameDay(cancelledDate, normalizedDate);
|
final exercises = training['exercises'] as List<dynamic>? ?? [];
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
// NEU: Prüfe, ob es ein datumsspezifisches Training für diesen Tag gibt
|
|
||||||
final hasDateSpecific = trainingTimes.containsKey(dateString);
|
|
||||||
if (!isCancelled || hasDateSpecific) {
|
|
||||||
// Wenn es ein datumsspezifisches Training gibt, blende das wochentagsbasierte Training aus
|
|
||||||
if (isCancelled && hasDateSpecific) continue;
|
|
||||||
final exercises = trainingExercises[dateString] as List<dynamic>? ?? [];
|
|
||||||
final totalExerciseDuration = exercises.fold<int>(0, (sum, exercise) {
|
final totalExerciseDuration = exercises.fold<int>(0, (sum, exercise) {
|
||||||
if (exercise is Map<String, dynamic>) {
|
if (exercise is Map<String, dynamic>) {
|
||||||
return sum + (exercise['duration'] as int? ?? 0);
|
return sum + (exercise['duration'] as int? ?? 0);
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final event = {
|
||||||
|
'trainerName': trainerData['name'] ?? 'Unbekannter Trainer',
|
||||||
|
'time': timeStr,
|
||||||
|
'duration': duration,
|
||||||
|
'trainerId': trainerDoc.id,
|
||||||
|
'isCurrentUser': trainerDoc.id == _currentUserId,
|
||||||
|
'day': dateString,
|
||||||
|
'date': dateString,
|
||||||
|
'exercises': exercises,
|
||||||
|
'remainingTime': duration - totalExerciseDuration,
|
||||||
|
'club': trainerData['club'] ?? 'Kein Verein',
|
||||||
|
'id': training['id'],
|
||||||
|
};
|
||||||
|
if (events.containsKey(normalizedDate)) {
|
||||||
|
events[normalizedDate]!.add(event);
|
||||||
|
} else {
|
||||||
|
events[normalizedDate] = [event];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Füge regelmäßige Trainings hinzu
|
||||||
|
final now = DateTime.now();
|
||||||
|
final yearStart = DateTime(now.year, 1, 1);
|
||||||
|
final yearEnd = DateTime(now.year + 1, 1, 1);
|
||||||
|
final weekdays = {
|
||||||
|
'Montag': 1,
|
||||||
|
'Dienstag': 2,
|
||||||
|
'Mittwoch': 3,
|
||||||
|
'Donnerstag': 4,
|
||||||
|
'Freitag': 5,
|
||||||
|
'Samstag': 6,
|
||||||
|
'Sonntag': 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Erstelle eine Set von gecancelten Daten für schnelleren Zugriff
|
||||||
|
final cancelledDates = cancelledTrainings
|
||||||
|
.where((cancelled) => cancelled is Map<String, dynamic>)
|
||||||
|
.map((cancelled) => DateTime.parse((cancelled as Map<String, dynamic>)['date'] as String))
|
||||||
|
.toSet();
|
||||||
|
|
||||||
|
print('Gecancelte Daten: $cancelledDates');
|
||||||
|
|
||||||
|
trainingTimes.forEach((day, timeStr) {
|
||||||
|
if (timeStr == null) return;
|
||||||
|
final timeParts = (timeStr as String).split(':');
|
||||||
|
if (timeParts.length != 2) return;
|
||||||
|
|
||||||
|
final hour = int.tryParse(timeParts[0]) ?? 0;
|
||||||
|
final minute = int.tryParse(timeParts[1]) ?? 0;
|
||||||
|
final duration = trainingDurations[day] ?? 60;
|
||||||
|
final targetWeekday = weekdays[day] ?? 1;
|
||||||
|
|
||||||
|
// Finde das erste gewünschte Wochentags-Datum ab Jahresanfang
|
||||||
|
DateTime firstDate = yearStart;
|
||||||
|
while (firstDate.weekday != targetWeekday) {
|
||||||
|
firstDate = firstDate.add(const Duration(days: 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generiere Trainings für das gesamte Jahr
|
||||||
|
while (firstDate.isBefore(yearEnd)) {
|
||||||
|
final normalizedDate = DateTime(firstDate.year, firstDate.month, firstDate.day);
|
||||||
|
final dateString = normalizedDate.toIso8601String();
|
||||||
|
|
||||||
|
// Prüfe, ob das Training für dieses Datum gecancelt ist
|
||||||
|
final isCancelled = cancelledDates.any((cancelledDate) =>
|
||||||
|
isSameDay(cancelledDate, normalizedDate)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Prüfe, ob bereits ein spezifisches Training für dieses Datum existiert
|
||||||
|
final hasSpecificTraining = trainings.containsKey(dateString);
|
||||||
|
|
||||||
|
if (!isCancelled && !hasSpecificTraining) {
|
||||||
final event = {
|
final event = {
|
||||||
'trainerName': trainerData['name'] ?? 'Unbekannter Trainer',
|
'trainerName': trainerData['name'] ?? 'Unbekannter Trainer',
|
||||||
'time': timeStr,
|
'time': timeStr,
|
||||||
|
|
@ -172,9 +231,10 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
'isCurrentUser': trainerDoc.id == _currentUserId,
|
'isCurrentUser': trainerDoc.id == _currentUserId,
|
||||||
'day': day,
|
'day': day,
|
||||||
'date': dateString,
|
'date': dateString,
|
||||||
'exercises': exercises,
|
'exercises': [],
|
||||||
'remainingTime': duration - totalExerciseDuration,
|
'remainingTime': duration,
|
||||||
'club': trainerData['club'] ?? 'Kein Verein',
|
'club': trainerData['club'] ?? 'Kein Verein',
|
||||||
|
'id': 'weekly_${day}_${dateString}',
|
||||||
};
|
};
|
||||||
if (events.containsKey(normalizedDate)) {
|
if (events.containsKey(normalizedDate)) {
|
||||||
events[normalizedDate]!.add(event);
|
events[normalizedDate]!.add(event);
|
||||||
|
|
@ -182,47 +242,7 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
events[normalizedDate] = [event];
|
events[normalizedDate] = [event];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
firstDate = firstDate.add(const Duration(days: 7));
|
||||||
});
|
|
||||||
|
|
||||||
// 2. Datumsspezifische Trainings (NEU)
|
|
||||||
trainingTimes.forEach((key, timeStr) {
|
|
||||||
// Prüfe, ob der Key ein Datum ist
|
|
||||||
final date = DateTime.tryParse(key);
|
|
||||||
if (date == null) return;
|
|
||||||
if (timeStr == null) return;
|
|
||||||
final duration = trainingDurations[key] as int? ?? 60;
|
|
||||||
final timeParts = (timeStr as String).split(':');
|
|
||||||
if (timeParts.length != 2) return;
|
|
||||||
final hour = int.tryParse(timeParts[0]) ?? 0;
|
|
||||||
final minute = int.tryParse(timeParts[1]) ?? 0;
|
|
||||||
final normalizedDate = DateTime(date.year, date.month, date.day);
|
|
||||||
final dateString = normalizedDate.toIso8601String();
|
|
||||||
// Für datumsspezifische Trainings: cancelledTrainings ignorieren!
|
|
||||||
// Event immer erzeugen
|
|
||||||
final exercises = trainingExercises[dateString] as List<dynamic>? ?? [];
|
|
||||||
final totalExerciseDuration = exercises.fold<int>(0, (sum, exercise) {
|
|
||||||
if (exercise is Map<String, dynamic>) {
|
|
||||||
return sum + (exercise['duration'] as int? ?? 0);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
});
|
|
||||||
final event = {
|
|
||||||
'trainerName': trainerData['name'] ?? 'Unbekannter Trainer',
|
|
||||||
'time': timeStr,
|
|
||||||
'duration': duration,
|
|
||||||
'trainerId': trainerDoc.id,
|
|
||||||
'isCurrentUser': trainerDoc.id == _currentUserId,
|
|
||||||
'day': key,
|
|
||||||
'date': dateString,
|
|
||||||
'exercises': exercises,
|
|
||||||
'remainingTime': duration - totalExerciseDuration,
|
|
||||||
'club': trainerData['club'] ?? 'Kein Verein',
|
|
||||||
};
|
|
||||||
if (events.containsKey(normalizedDate)) {
|
|
||||||
events[normalizedDate]!.add(event);
|
|
||||||
} else {
|
|
||||||
events[normalizedDate] = [event];
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -300,49 +320,106 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
|
|
||||||
Future<void> _deleteTraining(Map<String, dynamic> event) async {
|
Future<void> _deleteTraining(Map<String, dynamic> event) async {
|
||||||
if (_userRole != 'trainer' || !event['isCurrentUser']) return;
|
if (_userRole != 'trainer' || !event['isCurrentUser']) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final userDoc = await FirebaseFirestore.instance
|
final userDoc = await FirebaseFirestore.instance.collection('User').doc(_currentUserId).get();
|
||||||
.collection('User')
|
|
||||||
.doc(_currentUserId)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
if (!userDoc.exists) return;
|
if (!userDoc.exists) return;
|
||||||
|
|
||||||
final data = userDoc.data() as Map<String, dynamic>;
|
final data = userDoc.data() as Map<String, dynamic>;
|
||||||
|
final trainings = Map<String, dynamic>.from(data['trainings'] ?? {});
|
||||||
|
final dateString = event['date'] as String;
|
||||||
|
final trainingId = event['id'] as String?;
|
||||||
final cancelledTrainings = List<Map<String, dynamic>>.from(data['cancelledTrainings'] ?? []);
|
final cancelledTrainings = List<Map<String, dynamic>>.from(data['cancelledTrainings'] ?? []);
|
||||||
final trainingTimes = Map<String, dynamic>.from(data['trainingTimes'] ?? {});
|
|
||||||
final trainingDurations = Map<String, dynamic>.from(data['trainingDurations'] ?? {});
|
|
||||||
final trainingExercises = Map<String, dynamic>.from(data['trainingExercises'] ?? {});
|
|
||||||
|
|
||||||
// Stelle sicher, dass das Datum im richtigen Format gespeichert wird
|
print('Lösche Training:');
|
||||||
final date = DateTime.parse(event['date']);
|
print('dateString: $dateString');
|
||||||
final normalizedDateString = DateTime(date.year, date.month, date.day).toIso8601String();
|
print('trainingId: $trainingId');
|
||||||
|
print('Vorher - trainings: $trainings');
|
||||||
// Entferne ALLE Einträge für das Datum
|
print('Vorher - cancelledTrainings: $cancelledTrainings');
|
||||||
trainingTimes.remove(normalizedDateString);
|
|
||||||
trainingDurations.remove(normalizedDateString);
|
|
||||||
trainingExercises.remove(normalizedDateString);
|
|
||||||
|
|
||||||
|
// Wenn es sich um ein regelmäßiges Training handelt (ID beginnt mit 'weekly_')
|
||||||
|
if (trainingId != null && trainingId.startsWith('weekly_')) {
|
||||||
|
// Füge das Datum zu cancelledTrainings hinzu, wenn es noch nicht existiert
|
||||||
|
if (!cancelledTrainings.any((cancelled) =>
|
||||||
|
cancelled is Map<String, dynamic> &&
|
||||||
|
cancelled['date'] == dateString
|
||||||
|
)) {
|
||||||
cancelledTrainings.add({
|
cancelledTrainings.add({
|
||||||
'date': normalizedDateString,
|
'date': dateString,
|
||||||
'day': event['day'],
|
|
||||||
'time': event['time'],
|
|
||||||
'duration': event['duration'],
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Für spezifische Trainings: Entferne das Training aus der Liste
|
||||||
|
if (trainings.containsKey(dateString)) {
|
||||||
|
final trainingsList = List<Map<String, dynamic>>.from(trainings[dateString]);
|
||||||
|
trainingsList.removeWhere((t) => t['id'] == trainingId);
|
||||||
|
|
||||||
await FirebaseFirestore.instance
|
if (trainingsList.isEmpty) {
|
||||||
.collection('User')
|
trainings.remove(dateString);
|
||||||
.doc(_currentUserId)
|
} else {
|
||||||
.update({
|
trainings[dateString] = trainingsList;
|
||||||
'cancelledTrainings': cancelledTrainings,
|
}
|
||||||
'trainingTimes': trainingTimes,
|
}
|
||||||
'trainingDurations': trainingDurations,
|
|
||||||
'trainingExercises': trainingExercises,
|
// Entferne den Eintrag aus cancelledTrainings nur, wenn es sich um ein spezifisches Training handelt
|
||||||
|
// und kein regelmäßiges Training an diesem Tag stattfindet
|
||||||
|
final weekdays = {
|
||||||
|
'Montag': 1,
|
||||||
|
'Dienstag': 2,
|
||||||
|
'Mittwoch': 3,
|
||||||
|
'Donnerstag': 4,
|
||||||
|
'Freitag': 5,
|
||||||
|
'Samstag': 6,
|
||||||
|
'Sonntag': 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
final date = DateTime.parse(dateString);
|
||||||
|
final weekday = date.weekday;
|
||||||
|
final weekdayName = weekdays.entries.firstWhere((entry) => entry.value == weekday).key;
|
||||||
|
final trainingTimes = data['trainingTimes'] as Map<String, dynamic>? ?? {};
|
||||||
|
|
||||||
|
// Wenn an diesem Tag kein regelmäßiges Training stattfindet, entferne den Eintrag aus cancelledTrainings
|
||||||
|
if (!trainingTimes.containsKey(weekdayName)) {
|
||||||
|
cancelledTrainings.removeWhere((cancelled) =>
|
||||||
|
cancelled is Map<String, dynamic> &&
|
||||||
|
cancelled.containsKey('date') &&
|
||||||
|
cancelled['date'] == dateString
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print('Nachher - trainings: $trainings');
|
||||||
|
print('Nachher - cancelledTrainings: $cancelledTrainings');
|
||||||
|
|
||||||
|
// Aktualisiere die Datenbank
|
||||||
|
final updates = <String, dynamic>{};
|
||||||
|
|
||||||
|
// Aktualisiere trainings nur, wenn es nicht leer ist
|
||||||
|
if (trainings.isNotEmpty) {
|
||||||
|
updates['trainings'] = trainings;
|
||||||
|
} else {
|
||||||
|
updates['trainings'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aktualisiere cancelledTrainings nur, wenn es nicht leer ist
|
||||||
|
if (cancelledTrainings.isNotEmpty) {
|
||||||
|
updates['cancelledTrainings'] = cancelledTrainings;
|
||||||
|
} else {
|
||||||
|
updates['cancelledTrainings'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Führe die Aktualisierung durch
|
||||||
|
await FirebaseFirestore.instance.collection('User').doc(_currentUserId).update(updates);
|
||||||
|
|
||||||
|
// Aktualisiere die UI sofort
|
||||||
|
setState(() {
|
||||||
|
final normalizedDate = DateTime.parse(dateString);
|
||||||
|
if (_events.containsKey(normalizedDate)) {
|
||||||
|
_events[normalizedDate]!.removeWhere((e) => e['id'] == trainingId);
|
||||||
|
if (_events[normalizedDate]!.isEmpty) {
|
||||||
|
_events.remove(normalizedDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await _loadEvents();
|
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Training wurde gelöscht')),
|
const SnackBar(content: Text('Training wurde gelöscht')),
|
||||||
|
|
@ -590,10 +667,17 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
date: _selectedDay!,
|
date: _selectedDay!,
|
||||||
initialTime: event['time'],
|
initialTime: event['time'],
|
||||||
initialDuration: event['duration'],
|
initialDuration: event['duration'],
|
||||||
|
trainingId: event['id'],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
await _addOrEditTraining(_selectedDay!, result['time'], result['duration'], isException: true);
|
await _addOrEditTraining(
|
||||||
|
_selectedDay!,
|
||||||
|
result['time'],
|
||||||
|
result['duration'],
|
||||||
|
isException: true,
|
||||||
|
trainingId: result['trainingId'],
|
||||||
|
);
|
||||||
await _loadEvents();
|
await _loadEvents();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -736,52 +820,124 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _addOrEditTraining(DateTime date, String time, int duration, {bool isException = false}) async {
|
Future<void> _addOrEditTraining(DateTime date, String time, int duration, {bool isException = false, String? trainingId}) async {
|
||||||
// Trainingsdatum als String
|
|
||||||
final dateString = DateTime(date.year, date.month, date.day).toIso8601String();
|
final dateString = DateTime(date.year, date.month, date.day).toIso8601String();
|
||||||
final userDoc = await FirebaseFirestore.instance.collection('User').doc(_currentUserId).get();
|
final userDoc = await FirebaseFirestore.instance.collection('User').doc(_currentUserId).get();
|
||||||
final data = userDoc.data() ?? {};
|
final data = userDoc.data() ?? {};
|
||||||
final trainingExercises = Map<String, dynamic>.from(data['trainingExercises'] ?? {});
|
final trainings = Map<String, dynamic>.from(data['trainings'] ?? {});
|
||||||
final trainingTimes = Map<String, dynamic>.from(data['trainingTimes'] ?? {});
|
final uuid = const Uuid();
|
||||||
final trainingDurations = Map<String, dynamic>.from(data['trainingDurations'] ?? {});
|
|
||||||
|
|
||||||
// Entferne nur das Training für das konkrete Datum
|
|
||||||
trainingExercises.remove(dateString);
|
|
||||||
trainingTimes.remove(dateString);
|
|
||||||
trainingDurations.remove(dateString);
|
|
||||||
|
|
||||||
// Neues Training speichern (nur mit Datum als Key)
|
|
||||||
trainingExercises[dateString] = [];
|
|
||||||
trainingTimes[dateString] = time;
|
|
||||||
trainingDurations[dateString] = duration;
|
|
||||||
|
|
||||||
// cancelledTrainings bereinigen und ggf. Eintrag hinzufügen, wenn an diesem Tag ein wochentagsbasiertes Training existiert
|
|
||||||
final cancelledTrainings = List<Map<String, dynamic>>.from(data['cancelledTrainings'] ?? []);
|
final cancelledTrainings = List<Map<String, dynamic>>.from(data['cancelledTrainings'] ?? []);
|
||||||
|
final trainingTimes = data['trainingTimes'] as Map<String, dynamic>? ?? {};
|
||||||
|
|
||||||
|
print('Füge/Bearbeite Training:');
|
||||||
|
print('dateString: $dateString');
|
||||||
|
print('trainingId: $trainingId');
|
||||||
|
print('Vorher - trainings: $trainings');
|
||||||
|
print('Vorher - cancelledTrainings: $cancelledTrainings');
|
||||||
|
|
||||||
|
// Trainingsliste für das Datum holen oder neu anlegen
|
||||||
|
final trainingsList = List<Map<String, dynamic>>.from(trainings[dateString] ?? []);
|
||||||
|
|
||||||
|
if (trainingId != null) {
|
||||||
|
// Bearbeiten: Training mit ID ersetzen
|
||||||
|
final idx = trainingsList.indexWhere((t) => t['id'] == trainingId);
|
||||||
|
if (idx != -1) {
|
||||||
|
trainingsList[idx] = {
|
||||||
|
'id': trainingId,
|
||||||
|
'time': time,
|
||||||
|
'duration': duration,
|
||||||
|
'exercises': trainingsList[idx]['exercises'] ?? [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Hinzufügen: neues Training-Objekt anfügen
|
||||||
|
trainingsList.add({
|
||||||
|
'id': uuid.v4(),
|
||||||
|
'time': time,
|
||||||
|
'duration': duration,
|
||||||
|
'exercises': [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
trainings[dateString] = trainingsList;
|
||||||
|
|
||||||
|
// Prüfe, ob an diesem Tag ein regelmäßiges Training stattfindet
|
||||||
|
final weekdays = {
|
||||||
|
'Montag': 1,
|
||||||
|
'Dienstag': 2,
|
||||||
|
'Mittwoch': 3,
|
||||||
|
'Donnerstag': 4,
|
||||||
|
'Freitag': 5,
|
||||||
|
'Samstag': 6,
|
||||||
|
'Sonntag': 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
final weekday = date.weekday;
|
||||||
|
final weekdayName = weekdays.entries.firstWhere((entry) => entry.value == weekday).key;
|
||||||
|
|
||||||
|
// Wenn an diesem Tag ein regelmäßiges Training stattfindet, füge es zu cancelledTrainings hinzu
|
||||||
|
if (trainingTimes.containsKey(weekdayName)) {
|
||||||
|
if (!cancelledTrainings.any((cancelled) =>
|
||||||
|
cancelled is Map<String, dynamic> &&
|
||||||
|
cancelled['date'] == dateString
|
||||||
|
)) {
|
||||||
|
cancelledTrainings.add({
|
||||||
|
'date': dateString,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Wenn kein regelmäßiges Training stattfindet, entferne den Eintrag aus cancelledTrainings
|
||||||
cancelledTrainings.removeWhere((cancelled) =>
|
cancelledTrainings.removeWhere((cancelled) =>
|
||||||
cancelled is Map<String, dynamic> &&
|
cancelled is Map<String, dynamic> &&
|
||||||
cancelled.containsKey('date') &&
|
cancelled.containsKey('date') &&
|
||||||
cancelled['date'] == dateString
|
cancelled['date'] == dateString
|
||||||
);
|
);
|
||||||
|
|
||||||
// Prüfe, ob für diesen Tag ein wochentagsbasiertes Training existiert und ob es eine Ausnahme ist
|
|
||||||
final weekdayNames = [
|
|
||||||
'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'
|
|
||||||
];
|
|
||||||
final weekdayKey = weekdayNames[date.weekday - 1];
|
|
||||||
if (isException && trainingTimes.containsKey(weekdayKey)) {
|
|
||||||
cancelledTrainings.add({
|
|
||||||
'date': dateString,
|
|
||||||
'day': weekdayKey,
|
|
||||||
'time': trainingTimes[weekdayKey],
|
|
||||||
'duration': trainingDurations[weekdayKey] ?? 60,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await FirebaseFirestore.instance.collection('User').doc(_currentUserId).update({
|
print('Nachher - trainings: $trainings');
|
||||||
'trainingExercises': trainingExercises,
|
print('Nachher - cancelledTrainings: $cancelledTrainings');
|
||||||
'trainingTimes': trainingTimes,
|
|
||||||
'trainingDurations': trainingDurations,
|
// Aktualisiere die Datenbank
|
||||||
'cancelledTrainings': cancelledTrainings,
|
final updates = <String, dynamic>{};
|
||||||
|
|
||||||
|
// Aktualisiere trainings nur, wenn es nicht leer ist
|
||||||
|
if (trainings.isNotEmpty) {
|
||||||
|
updates['trainings'] = trainings;
|
||||||
|
} else {
|
||||||
|
updates['trainings'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aktualisiere cancelledTrainings nur, wenn es nicht leer ist
|
||||||
|
if (cancelledTrainings.isNotEmpty) {
|
||||||
|
updates['cancelledTrainings'] = cancelledTrainings;
|
||||||
|
} else {
|
||||||
|
updates['cancelledTrainings'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Führe die Aktualisierung durch
|
||||||
|
await FirebaseFirestore.instance.collection('User').doc(_currentUserId).update(updates);
|
||||||
|
|
||||||
|
// Aktualisiere die UI sofort
|
||||||
|
setState(() {
|
||||||
|
final normalizedDate = DateTime(date.year, date.month, date.day);
|
||||||
|
final event = {
|
||||||
|
'trainerName': data['name'] ?? 'Unbekannter Trainer',
|
||||||
|
'time': time,
|
||||||
|
'duration': duration,
|
||||||
|
'trainerId': _currentUserId,
|
||||||
|
'isCurrentUser': true,
|
||||||
|
'day': dateString,
|
||||||
|
'date': dateString,
|
||||||
|
'exercises': [],
|
||||||
|
'remainingTime': duration,
|
||||||
|
'club': data['club'] ?? 'Kein Verein',
|
||||||
|
'id': trainingId ?? uuid.v4(),
|
||||||
|
};
|
||||||
|
if (_events.containsKey(normalizedDate)) {
|
||||||
|
_events[normalizedDate]!.add(event);
|
||||||
|
} else {
|
||||||
|
_events[normalizedDate] = [event];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -791,7 +947,13 @@ class _TrainingEditDialog extends StatefulWidget {
|
||||||
final DateTime date;
|
final DateTime date;
|
||||||
final String? initialTime;
|
final String? initialTime;
|
||||||
final int? initialDuration;
|
final int? initialDuration;
|
||||||
const _TrainingEditDialog({required this.date, this.initialTime, this.initialDuration});
|
final String? trainingId;
|
||||||
|
const _TrainingEditDialog({
|
||||||
|
required this.date,
|
||||||
|
this.initialTime,
|
||||||
|
this.initialDuration,
|
||||||
|
this.trainingId,
|
||||||
|
});
|
||||||
@override
|
@override
|
||||||
State<_TrainingEditDialog> createState() => _TrainingEditDialogState();
|
State<_TrainingEditDialog> createState() => _TrainingEditDialogState();
|
||||||
}
|
}
|
||||||
|
|
@ -863,7 +1025,11 @@ class _TrainingEditDialogState extends State<_TrainingEditDialog> {
|
||||||
onPressed: _selectedTime != null
|
onPressed: _selectedTime != null
|
||||||
? () {
|
? () {
|
||||||
final timeString = _selectedTime!.hour.toString().padLeft(2, '0') + ':' + _selectedTime!.minute.toString().padLeft(2, '0');
|
final timeString = _selectedTime!.hour.toString().padLeft(2, '0') + ':' + _selectedTime!.minute.toString().padLeft(2, '0');
|
||||||
Navigator.pop(context, {'time': timeString, 'duration': _duration});
|
Navigator.pop(context, {
|
||||||
|
'time': timeString,
|
||||||
|
'duration': _duration,
|
||||||
|
'trainingId': widget.trainingId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: const Text('Speichern'),
|
child: const Text('Speichern'),
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.4+2"
|
version: "0.3.4+2"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.6"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -201,6 +209,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.9.7"
|
version: "3.9.7"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
@ -437,6 +453,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.1"
|
version: "1.10.1"
|
||||||
|
sprintf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sprintf
|
||||||
|
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -493,6 +517,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
|
uuid:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ dependencies:
|
||||||
firebase_storage: ^11.5.6
|
firebase_storage: ^11.5.6
|
||||||
image_picker: ^1.0.7
|
image_picker: ^1.0.7
|
||||||
provider: ^6.1.1
|
provider: ^6.1.1
|
||||||
|
uuid: ^4.2.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue