Kategorien horizontal
parent
4e966656d3
commit
e01a0203d1
|
@ -499,103 +499,36 @@ 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;
|
||||||
|
|
||||||
print('=== DEBUG: Starting _deleteTraining ===');
|
|
||||||
print('DEBUG: Event to delete: $event');
|
|
||||||
print('DEBUG: Training ID: ${event['id']}');
|
|
||||||
print('DEBUG: Date: ${event['date']}');
|
|
||||||
print('DEBUG: Is weekly training: ${event['id']?.toString().startsWith('weekly_')}');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final userDoc = await FirebaseFirestore.instance.collection('User').doc(_currentUserId).get();
|
final userDoc = await FirebaseFirestore.instance.collection('User').doc(_currentUserId).get();
|
||||||
if (!userDoc.exists) {
|
if (!userDoc.exists) return;
|
||||||
print('DEBUG: User document does not exist');
|
|
||||||
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 trainings = Map<String, dynamic>.from(data['trainings'] ?? {});
|
||||||
final dateString = event['date'] as String;
|
final dateString = event['date'] as String;
|
||||||
final trainingId = event['id'] 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'] ?? []);
|
||||||
|
|
||||||
print('DEBUG: Current trainings in DB: $trainings');
|
|
||||||
print('DEBUG: Current cancelledTrainings in DB: $cancelledTrainings');
|
|
||||||
|
|
||||||
// Wenn es sich um ein regelmäßiges Training handelt (ID beginnt mit 'weekly_')
|
// Wenn es sich um ein regelmäßiges Training handelt (ID beginnt mit 'weekly_')
|
||||||
if (trainingId != null && trainingId.startsWith('weekly_')) {
|
if (trainingId != null && trainingId.startsWith('weekly_')) {
|
||||||
print('DEBUG: Processing weekly training deletion');
|
// Füge das Datum zu cancelledTrainings hinzu, wenn es noch nicht existiert
|
||||||
|
if (!cancelledTrainings.any((cancelled) =>
|
||||||
// Für regelmäßige Trainings: Lösche alle Trainings dieser Serie
|
//cancelled is Map<String, dynamic> &&
|
||||||
final weekdays = {
|
cancelled['date'] == dateString
|
||||||
'Montag': 1,
|
)) {
|
||||||
'Dienstag': 2,
|
cancelledTrainings.add({
|
||||||
'Mittwoch': 3,
|
'date': dateString,
|
||||||
'Donnerstag': 4,
|
});
|
||||||
'Freitag': 5,
|
}
|
||||||
'Samstag': 6,
|
|
||||||
'Sonntag': 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
final date = DateTime.parse(dateString);
|
|
||||||
final weekday = date.weekday;
|
|
||||||
|
|
||||||
print('DEBUG: Weekday to delete: $weekday');
|
|
||||||
|
|
||||||
// Lösche alle Trainings an diesem Wochentag
|
|
||||||
trainings.forEach((dateStr, trainingsList) {
|
|
||||||
final trainingDate = DateTime.tryParse(dateStr);
|
|
||||||
if (trainingDate != null && trainingDate.weekday == weekday) {
|
|
||||||
print('DEBUG: Checking date $dateStr (weekday: ${trainingDate.weekday})');
|
|
||||||
final list = List<Map<String, dynamic>>.from(trainingsList);
|
|
||||||
print('DEBUG: Trainings on this date before deletion: $list');
|
|
||||||
|
|
||||||
final beforeCount = list.length;
|
|
||||||
list.removeWhere((t) => t['id'] == trainingId);
|
|
||||||
final afterCount = list.length;
|
|
||||||
|
|
||||||
print('DEBUG: Removed ${beforeCount - afterCount} trainings with ID $trainingId');
|
|
||||||
|
|
||||||
if (list.isEmpty) {
|
|
||||||
trainings.remove(dateStr);
|
|
||||||
print('DEBUG: Removed empty date $dateStr from trainings');
|
|
||||||
} else {
|
|
||||||
trainings[dateStr] = list;
|
|
||||||
print('DEBUG: Updated trainings for date $dateStr: $list');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Entferne alle cancelledTrainings für diesen Wochentag
|
|
||||||
final beforeCancelledCount = cancelledTrainings.length;
|
|
||||||
cancelledTrainings.removeWhere((cancelled) =>
|
|
||||||
cancelled.containsKey('date') &&
|
|
||||||
DateTime.parse(cancelled['date'] as String).weekday == weekday
|
|
||||||
);
|
|
||||||
final afterCancelledCount = cancelledTrainings.length;
|
|
||||||
|
|
||||||
print('DEBUG: Removed ${beforeCancelledCount - afterCancelledCount} cancelled trainings for weekday $weekday');
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
print('DEBUG: Processing specific training deletion');
|
// Für spezifische Trainings: Entferne das Training aus der Liste
|
||||||
|
|
||||||
// Für spezifische Trainings: Entferne nur das Training an diesem Tag
|
|
||||||
if (trainings.containsKey(dateString)) {
|
if (trainings.containsKey(dateString)) {
|
||||||
final trainingsList = List<Map<String, dynamic>>.from(trainings[dateString]);
|
final trainingsList = List<Map<String, dynamic>>.from(trainings[dateString]);
|
||||||
print('DEBUG: Trainings on date $dateString before deletion: $trainingsList');
|
|
||||||
|
|
||||||
final beforeCount = trainingsList.length;
|
|
||||||
trainingsList.removeWhere((t) => t['id'] == trainingId);
|
trainingsList.removeWhere((t) => t['id'] == trainingId);
|
||||||
final afterCount = trainingsList.length;
|
|
||||||
|
|
||||||
print('DEBUG: Removed ${beforeCount - afterCount} trainings with ID $trainingId');
|
|
||||||
|
|
||||||
if (trainingsList.isEmpty) {
|
if (trainingsList.isEmpty) {
|
||||||
trainings.remove(dateString);
|
trainings.remove(dateString);
|
||||||
print('DEBUG: Removed empty date $dateString from trainings');
|
|
||||||
} else {
|
} else {
|
||||||
trainings[dateString] = trainingsList;
|
trainings[dateString] = trainingsList;
|
||||||
print('DEBUG: Updated trainings for date $dateString: $trainingsList');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,107 +549,45 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
final weekdayName = weekdays.entries.firstWhere((entry) => entry.value == weekday).key;
|
final weekdayName = weekdays.entries.firstWhere((entry) => entry.value == weekday).key;
|
||||||
final trainingTimes = data['trainingTimes'] as Map<String, dynamic>? ?? {};
|
final trainingTimes = data['trainingTimes'] as Map<String, dynamic>? ?? {};
|
||||||
|
|
||||||
print('DEBUG: Weekday name: $weekdayName');
|
|
||||||
print('DEBUG: Training times: $trainingTimes');
|
|
||||||
print('DEBUG: Has regular training on this weekday: ${trainingTimes.containsKey(weekdayName)}');
|
|
||||||
|
|
||||||
// Wenn an diesem Tag kein regelmäßiges Training stattfindet, entferne den Eintrag aus cancelledTrainings
|
// Wenn an diesem Tag kein regelmäßiges Training stattfindet, entferne den Eintrag aus cancelledTrainings
|
||||||
if (!trainingTimes.containsKey(weekdayName)) {
|
if (!trainingTimes.containsKey(weekdayName)) {
|
||||||
final beforeCancelledCount = cancelledTrainings.length;
|
|
||||||
cancelledTrainings.removeWhere((cancelled) =>
|
cancelledTrainings.removeWhere((cancelled) =>
|
||||||
|
//cancelled is Map<String, dynamic> &&
|
||||||
cancelled.containsKey('date') &&
|
cancelled.containsKey('date') &&
|
||||||
cancelled['date'] == dateString
|
cancelled['date'] == dateString
|
||||||
);
|
);
|
||||||
final afterCancelledCount = cancelledTrainings.length;
|
|
||||||
|
|
||||||
print('DEBUG: Removed ${beforeCancelledCount - afterCancelledCount} cancelled trainings for date $dateString');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print('DEBUG: Final trainings after deletion: $trainings');
|
|
||||||
print('DEBUG: Final cancelledTrainings after deletion: $cancelledTrainings');
|
|
||||||
|
|
||||||
// Aktualisiere die Datenbank
|
// Aktualisiere die Datenbank
|
||||||
final updates = <String, dynamic>{};
|
final updates = <String, dynamic>{};
|
||||||
|
|
||||||
// Aktualisiere trainings nur, wenn es nicht leer ist
|
// Aktualisiere trainings nur, wenn es nicht leer ist
|
||||||
if (trainings.isNotEmpty) {
|
if (trainings.isNotEmpty) {
|
||||||
updates['trainings'] = trainings;
|
updates['trainings'] = trainings;
|
||||||
print('DEBUG: Will update trainings in DB');
|
|
||||||
} else {
|
} else {
|
||||||
updates['trainings'] = null;
|
updates['trainings'] = null;
|
||||||
print('DEBUG: Will set trainings to null in DB');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aktualisiere cancelledTrainings nur, wenn es nicht leer ist
|
// Aktualisiere cancelledTrainings nur, wenn es nicht leer ist
|
||||||
if (cancelledTrainings.isNotEmpty) {
|
if (cancelledTrainings.isNotEmpty) {
|
||||||
updates['cancelledTrainings'] = cancelledTrainings;
|
updates['cancelledTrainings'] = cancelledTrainings;
|
||||||
print('DEBUG: Will update cancelledTrainings in DB');
|
|
||||||
} else {
|
} else {
|
||||||
updates['cancelledTrainings'] = null;
|
updates['cancelledTrainings'] = null;
|
||||||
print('DEBUG: Will set cancelledTrainings to null in DB');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print('DEBUG: Final updates to DB: $updates');
|
|
||||||
|
|
||||||
// Führe die Aktualisierung durch
|
// Führe die Aktualisierung durch
|
||||||
await FirebaseFirestore.instance.collection('User').doc(_currentUserId).update(updates);
|
await FirebaseFirestore.instance.collection('User').doc(_currentUserId).update(updates);
|
||||||
print('DEBUG: Database update completed successfully');
|
|
||||||
|
|
||||||
// Aktualisiere die UI sofort
|
// Aktualisiere die UI sofort
|
||||||
setState(() {
|
setState(() {
|
||||||
print('DEBUG: Updating UI...');
|
final normalizedDate = DateTime.parse(dateString);
|
||||||
|
if (_events.containsKey(normalizedDate)) {
|
||||||
// Für regelmäßige Trainings: Entferne alle Events an diesem Wochentag
|
_events[normalizedDate]!.removeWhere((e) => e['id'] == trainingId);
|
||||||
if (trainingId != null && trainingId.startsWith('weekly_')) {
|
if (_events[normalizedDate]!.isEmpty) {
|
||||||
final date = DateTime.parse(dateString);
|
_events.remove(normalizedDate);
|
||||||
final weekday = date.weekday;
|
|
||||||
|
|
||||||
print('DEBUG: Removing events from UI for weekday $weekday');
|
|
||||||
|
|
||||||
_events.forEach((eventDate, eventList) {
|
|
||||||
if (eventDate.weekday == weekday) {
|
|
||||||
print('DEBUG: Checking event date $eventDate (weekday: ${eventDate.weekday})');
|
|
||||||
print('DEBUG: Events before removal: $eventList');
|
|
||||||
|
|
||||||
final beforeCount = eventList.length;
|
|
||||||
eventList.removeWhere((e) => e['id'] == trainingId);
|
|
||||||
final afterCount = eventList.length;
|
|
||||||
|
|
||||||
print('DEBUG: Removed ${beforeCount - afterCount} events with ID $trainingId');
|
|
||||||
print('DEBUG: Events after removal: $eventList');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Entferne leere Event-Listen
|
|
||||||
final beforeEmptyCount = _events.length;
|
|
||||||
_events.removeWhere((date, events) => events.isEmpty);
|
|
||||||
final afterEmptyCount = _events.length;
|
|
||||||
|
|
||||||
print('DEBUG: Removed ${beforeEmptyCount - afterEmptyCount} empty event lists');
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Für spezifische Trainings: Entferne nur das Event an diesem Tag
|
|
||||||
final normalizedDate = DateTime.parse(dateString);
|
|
||||||
if (_events.containsKey(normalizedDate)) {
|
|
||||||
print('DEBUG: Removing specific event from UI for date $normalizedDate');
|
|
||||||
print('DEBUG: Events before removal: ${_events[normalizedDate]}');
|
|
||||||
|
|
||||||
final beforeCount = _events[normalizedDate]!.length;
|
|
||||||
_events[normalizedDate]!.removeWhere((e) => e['id'] == trainingId);
|
|
||||||
final afterCount = _events[normalizedDate]!.length;
|
|
||||||
|
|
||||||
print('DEBUG: Removed ${beforeCount - afterCount} events with ID $trainingId');
|
|
||||||
print('DEBUG: Events after removal: ${_events[normalizedDate]}');
|
|
||||||
|
|
||||||
if (_events[normalizedDate]!.isEmpty) {
|
|
||||||
_events.remove(normalizedDate);
|
|
||||||
print('DEBUG: Removed empty date $normalizedDate from events');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print('DEBUG: UI update completed');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
@ -724,11 +595,7 @@ class _CalendarTabState extends State<CalendarTab> {
|
||||||
const SnackBar(content: Text('Training wurde gelöscht')),
|
const SnackBar(content: Text('Training wurde gelöscht')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
print('=== DEBUG: _deleteTraining completed successfully ===');
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('DEBUG: Error in _deleteTraining: $e');
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Fehler beim Löschen des Trainings')),
|
const SnackBar(content: Text('Fehler beim Löschen des Trainings')),
|
||||||
|
|
|
@ -48,6 +48,38 @@ class _FavoritesTabState extends State<FavoritesTab> {
|
||||||
_selectedCategory = widget.categoryFilter;
|
_selectedCategory = widget.categoryFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loads the user's favorite exercises from Firestore.
|
||||||
|
Future<Set<String>> _loadFavorites() async {
|
||||||
|
final user = FirebaseAuth.instance.currentUser;
|
||||||
|
if (user == null) return {};
|
||||||
|
|
||||||
|
final doc = await FirebaseFirestore.instance.collection('User').doc(user.uid).get();
|
||||||
|
final data = doc.data();
|
||||||
|
if (data != null && data['favorites'] != null) {
|
||||||
|
return Set<String>.from(data['favorites']);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Toggles the favorite status of an exercise for the current user.
|
||||||
|
Future<void> _toggleFavorite(String trainingId, bool isFavorite) async {
|
||||||
|
final user = FirebaseAuth.instance.currentUser;
|
||||||
|
if (user == null) return;
|
||||||
|
|
||||||
|
if (isFavorite) {
|
||||||
|
await FirebaseFirestore.instance.collection('User').doc(user.uid).update({
|
||||||
|
'favorites': FieldValue.arrayRemove([trainingId]),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await FirebaseFirestore.instance.collection('User').doc(user.uid).update({
|
||||||
|
'favorites': FieldValue.arrayUnion([trainingId]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh the favorites list
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
/// Opens the filter modal for advanced filtering (duration, level, rating).
|
/// Opens the filter modal for advanced filtering (duration, level, rating).
|
||||||
void _openFilterModal() async {
|
void _openFilterModal() async {
|
||||||
_tempMinDuration = _minDuration;
|
_tempMinDuration = _minDuration;
|
||||||
|
@ -196,7 +228,7 @@ class _FavoritesTabState extends State<FavoritesTab> {
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'Kategorien',
|
'Kategorien',
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
// Filter button opens the modal with advanced filters
|
// Filter button opens the modal with advanced filters
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
|
@ -210,50 +242,64 @@ class _FavoritesTabState extends State<FavoritesTab> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 12),
|
||||||
// Category filter chips
|
// Horizontal scrollable category chips
|
||||||
Wrap(
|
SizedBox(
|
||||||
alignment: WrapAlignment.center,
|
height: 40,
|
||||||
spacing: 8,
|
child: ListView(
|
||||||
runSpacing: 8,
|
scrollDirection: Axis.horizontal,
|
||||||
children: [
|
children: [
|
||||||
FilterChip(
|
// "Alle" chip
|
||||||
label: const Text('Alle'),
|
Padding(
|
||||||
selected: _selectedCategory == null,
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
onSelected: (selected) {
|
child: FilterChip(
|
||||||
setState(() => _selectedCategory = null);
|
label: const Text('Alle'),
|
||||||
},
|
selected: _selectedCategory == null,
|
||||||
),
|
onSelected: (selected) {
|
||||||
..._categories.map((cat) => FilterChip(
|
setState(() {
|
||||||
label: Text(cat),
|
_selectedCategory = null;
|
||||||
selected: _selectedCategory == cat,
|
});
|
||||||
onSelected: (selected) {
|
},
|
||||||
setState(() => _selectedCategory = selected ? cat : null);
|
),
|
||||||
},
|
),
|
||||||
)),
|
// Category chips
|
||||||
],
|
..._categories.map((category) => Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: FilterChip(
|
||||||
|
label: Text(category),
|
||||||
|
selected: _selectedCategory == category,
|
||||||
|
onSelected: (selected) {
|
||||||
|
setState(() {
|
||||||
|
_selectedCategory = selected ? category : null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)).toList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// Favorites list
|
||||||
Expanded(
|
Expanded(
|
||||||
child: StreamBuilder<DocumentSnapshot>(
|
child: FutureBuilder<Set<String>>(
|
||||||
stream: FirebaseFirestore.instance.collection('User').doc(user.uid).snapshots(),
|
future: _loadFavorites(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
if (!snapshot.hasData || !snapshot.data!.exists) {
|
|
||||||
return const Center(child: Text('Keine Favoriten gefunden'));
|
if (snapshot.hasError) {
|
||||||
|
return Center(child: Text('Fehler: ${snapshot.error}'));
|
||||||
}
|
}
|
||||||
final data = snapshot.data!.data() as Map<String, dynamic>;
|
|
||||||
final allFavorites = List<String>.from(data['favorites'] ?? []);
|
final allFavorites = snapshot.data ?? {};
|
||||||
|
|
||||||
if (allFavorites.isEmpty) {
|
if (allFavorites.isEmpty) {
|
||||||
return const Center(child: Text('Keine Favoriten gefunden'));
|
return const Center(child: Text('Keine Favoriten gefunden'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all favorite exercise documents at once
|
|
||||||
return FutureBuilder<List<DocumentSnapshot>>(
|
return FutureBuilder<List<DocumentSnapshot>>(
|
||||||
future: Future.wait(allFavorites.map((id) =>
|
future: Future.wait(allFavorites.map((id) =>
|
||||||
FirebaseFirestore.instance.collection('Training').doc(id).get()
|
FirebaseFirestore.instance.collection('Training').doc(id).get()
|
||||||
|
|
|
@ -249,14 +249,9 @@ class _SearchTabState extends State<SearchTab> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Übungen'),
|
title: const Text('Suche'),
|
||||||
actions: [
|
actions: [
|
||||||
if (widget.selectMode)
|
if (_isTrainer && _trainerChecked)
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.close),
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
),
|
|
||||||
if (_isTrainer && !widget.selectMode)
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
onPressed: () => _showCreateTrainingDialog(context),
|
onPressed: () => _showCreateTrainingDialog(context),
|
||||||
|
@ -265,34 +260,21 @@ class _SearchTabState extends State<SearchTab> {
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
// Search input field.
|
// Search bar
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
hintText: 'Suche nach Übungen...',
|
labelText: 'Suche nach Übungen...',
|
||||||
prefixIcon: const Icon(Icons.search),
|
prefixIcon: Icon(Icons.search),
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(),
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.selectMode && widget.remainingTime != null)
|
// Category filter chips
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: Text(
|
|
||||||
'Verbleibende Zeit: ${widget.remainingTime} Minuten',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.grey,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Category filter chips and filter button only (no direct filter UI here)
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
@ -301,8 +283,9 @@ class _SearchTabState extends State<SearchTab> {
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'Kategorien',
|
'Kategorien',
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
|
// Filter button opens the modal with advanced filters
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
onPressed: _openFilterModal,
|
onPressed: _openFilterModal,
|
||||||
icon: const Icon(Icons.filter_list),
|
icon: const Icon(Icons.filter_list),
|
||||||
|
@ -314,26 +297,47 @@ class _SearchTabState extends State<SearchTab> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 12),
|
||||||
Wrap(
|
// Horizontal scrollable category chips
|
||||||
spacing: 8,
|
SizedBox(
|
||||||
runSpacing: 8,
|
height: 40,
|
||||||
children: _categories.map((category) {
|
child: ListView(
|
||||||
return FilterChip(
|
scrollDirection: Axis.horizontal,
|
||||||
label: Text(category),
|
children: [
|
||||||
selected: _selectedCategory == category,
|
// "Alle" chip
|
||||||
onSelected: (bool selected) {
|
Padding(
|
||||||
setState(() {
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
_selectedCategory = selected ? category : null;
|
child: FilterChip(
|
||||||
});
|
label: const Text('Alle'),
|
||||||
},
|
selected: _selectedCategory == null,
|
||||||
);
|
onSelected: (selected) {
|
||||||
}).toList(),
|
setState(() {
|
||||||
|
_selectedCategory = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Category chips
|
||||||
|
..._categories.map((category) => Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: FilterChip(
|
||||||
|
label: Text(category),
|
||||||
|
selected: _selectedCategory == category,
|
||||||
|
onSelected: (selected) {
|
||||||
|
setState(() {
|
||||||
|
_selectedCategory = selected ? category : null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)).toList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Exercise grid view.
|
const SizedBox(height: 16),
|
||||||
|
// Exercise list
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FutureBuilder<QuerySnapshot>(
|
child: FutureBuilder<QuerySnapshot>(
|
||||||
future: FirebaseFirestore.instance.collection('Training').get(),
|
future: FirebaseFirestore.instance.collection('Training').get(),
|
||||||
|
|
Loading…
Reference in New Issue