import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; import 'training_detail_screen.dart'; class SearchTab extends StatefulWidget { const SearchTab({super.key}); @override State createState() => _SearchTabState(); } class _SearchTabState extends State { final TextEditingController _searchController = TextEditingController(); final List _categories = [ 'Aufwärmen & Mobilisation', 'Wurf- & Torabschluss', 'Torwarttraining', 'Athletik', 'Pass', 'Koordination', ]; String? _selectedCategory; String _searchTerm = ''; bool _isTrainer = false; bool _trainerChecked = false; Set _favorites = {}; @override void initState() { super.initState(); _searchController.addListener(() { setState(() { _searchTerm = _searchController.text.trim(); }); }); _checkIfTrainer(); _loadFavorites(); } Future _checkIfTrainer() async { final user = FirebaseAuth.instance.currentUser; if (user == null) return; final doc = await FirebaseFirestore.instance.collection('User').doc(user.uid).get(); setState(() { _isTrainer = doc.data()?['role'] == 'trainer'; _trainerChecked = true; }); } Future _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) { setState(() { _favorites = Set.from(data['favorites']); }); } } void _showCreateTrainingDialog() { showDialog( context: context, builder: (context) => _CreateTrainingDialog(categories: _categories), ).then((_) => setState(() {})); // Refresh nach Hinzufügen } Future _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]), }); } await _loadFavorites(); // Aktualisiere die Favoriten nach dem Toggle } @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ SliverAppBar( floating: true, title: TextField( controller: _searchController, decoration: InputDecoration( hintText: 'Suche nach Training...', border: InputBorder.none, prefixIcon: const Icon(Icons.search), suffixIcon: IconButton( icon: const Icon(Icons.clear), onPressed: () => _searchController.clear(), ), ), ), actions: [ if (_trainerChecked && _isTrainer) IconButton( icon: const Icon(Icons.add), tooltip: 'Neues Training erstellen', onPressed: _showCreateTrainingDialog, ), ], ), SliverPadding( padding: const EdgeInsets.all(16.0), sliver: SliverToBoxAdapter( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Kategorien', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), Wrap( spacing: 8, runSpacing: 8, children: _categories.map((category) { return FilterChip( label: Text(category), selected: _selectedCategory == category, onSelected: (bool selected) { setState(() { _selectedCategory = selected ? category : null; }); }, ); }).toList(), ), ], ), ), ), if (_searchTerm.isNotEmpty || _selectedCategory != null) SliverPadding( padding: const EdgeInsets.all(16.0), sliver: FutureBuilder( future: FirebaseFirestore.instance.collection('Training').get(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const SliverToBoxAdapter( child: Center(child: CircularProgressIndicator())); } if (!snapshot.hasData || snapshot.data!.docs.isEmpty) { return const SliverToBoxAdapter( child: Center(child: Text('Keine Trainings gefunden.'))); } final docs = snapshot.data!.docs.where((doc) { final data = doc.data() as Map; final title = (data['title'] ?? '').toString().toLowerCase(); final description = (data['description'] ?? '').toString().toLowerCase(); final category = (data['category'] ?? '').toString(); final matchesSearch = _searchTerm.isEmpty || title.contains(_searchTerm.toLowerCase()) || description.contains(_searchTerm.toLowerCase()); final matchesCategory = _selectedCategory == null || category == _selectedCategory; return matchesSearch && matchesCategory; }).toList(); if (docs.isEmpty) { return const SliverToBoxAdapter( child: Center(child: Text('Keine Trainings gefunden.'))); } return SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 16, crossAxisSpacing: 16, childAspectRatio: 0.75, ), delegate: SliverChildBuilderDelegate((context, index) { final data = docs[index].data() as Map; final isFavorite = _favorites.contains(docs[index].id); return Card( clipBehavior: Clip.antiAlias, child: InkWell( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => TrainingDetailScreen(trainingId: docs[index].id), ), ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: (data['picture'] is String && data['picture'] != '') ? Image.network( data['picture'], width: double.infinity, fit: BoxFit.cover, ) : Container( color: Colors.grey[300], child: const Center( child: Icon(Icons.fitness_center, size: 40), ), ), ), Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( data['title'] ?? '-', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), const SizedBox(height: 4), Text( data['description'] ?? '-', maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( color: Colors.grey[600], fontSize: 13, ), ), const SizedBox(height: 4), Text( '${data['duration'] ?? '-'} Minuten', style: TextStyle( color: Colors.grey[600], fontSize: 13, ), ), const SizedBox(height: 4), Row( children: [ const Icon(Icons.star, size: 16, color: Colors.amber), const SizedBox(width: 4), Text('${data['rating overall'] ?? '-'}'), ], ), const SizedBox(height: 4), Text('Level: ${data['year'] ?? '-'}'), const SizedBox(height: 4), Align( alignment: Alignment.bottomRight, child: IconButton( icon: Icon( isFavorite ? Icons.favorite : Icons.favorite_border, color: isFavorite ? Colors.red : null, ), onPressed: () => _toggleFavorite(docs[index].id, isFavorite), ), ), ], ), ), ], ), ), ); }, childCount: docs.length), ); }, ), ), ], ), ); } @override void dispose() { _searchController.dispose(); super.dispose(); } } class _CreateTrainingDialog extends StatefulWidget { final List categories; const _CreateTrainingDialog({required this.categories}); @override State<_CreateTrainingDialog> createState() => _CreateTrainingDialogState(); } class _CreateTrainingDialogState extends State<_CreateTrainingDialog> { final _formKey = GlobalKey(); String? _category; String? _title; String? _description; int? _duration; String? _year; bool _loading = false; File? _imageFile; final _picker = ImagePicker(); Future _pickImage() async { final pickedFile = await _picker.pickImage(source: ImageSource.gallery); if (pickedFile != null) { setState(() { _imageFile = File(pickedFile.path); }); } } Future _uploadImage() async { if (_imageFile == null) return null; final storageRef = FirebaseStorage.instance .ref() .child('training_images') .child('${DateTime.now().millisecondsSinceEpoch}.jpg'); try { final uploadTask = await storageRef.putFile(_imageFile!); return await uploadTask.ref.getDownloadURL(); } catch (e) { print('Error uploading image: $e'); return null; } } @override Widget build(BuildContext context) { return AlertDialog( title: const Text('Neues Training erstellen'), content: SingleChildScrollView( child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ if (_imageFile != null) Container( height: 200, width: double.infinity, margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( image: DecorationImage( image: FileImage(_imageFile!), fit: BoxFit.cover, ), ), ), ElevatedButton.icon( onPressed: _pickImage, icon: const Icon(Icons.image), label: Text(_imageFile == null ? 'Bild auswählen' : 'Bild ändern'), ), const SizedBox(height: 16), DropdownButtonFormField( value: _category, items: widget.categories .map((cat) => DropdownMenuItem(value: cat, child: Text(cat))) .toList(), onChanged: (v) => setState(() => _category = v), decoration: const InputDecoration(labelText: 'Kategorie'), validator: (v) => v == null ? 'Kategorie wählen' : null, ), TextFormField( decoration: const InputDecoration(labelText: 'Titel'), onChanged: (v) => _title = v, validator: (v) => v == null || v.isEmpty ? 'Titel angeben' : null, ), TextFormField( decoration: const InputDecoration(labelText: 'Beschreibung'), onChanged: (v) => _description = v, validator: (v) => v == null || v.isEmpty ? 'Beschreibung angeben' : null, maxLines: 2, ), TextFormField( decoration: const InputDecoration(labelText: 'Dauer (Minuten)'), keyboardType: TextInputType.number, onChanged: (v) => _duration = int.tryParse(v), validator: (v) => v == null || int.tryParse(v) == null ? 'Zahl angeben' : null, ), TextFormField( decoration: const InputDecoration(labelText: 'Schwierigkeitslevel'), onChanged: (v) => _year = v, validator: (v) => v == null || v.isEmpty ? 'Level angeben' : null, ), ], ), ), ), actions: [ TextButton( onPressed: _loading ? null : () => Navigator.pop(context), child: const Text('Abbrechen'), ), ElevatedButton( onPressed: _loading ? null : () async { if (_formKey.currentState!.validate()) { setState(() => _loading = true); try { final imageUrl = await _uploadImage(); await FirebaseFirestore.instance.collection('Training').add({ 'category': _category, 'title': _title, 'description': _description, 'duration': _duration, 'picture': imageUrl, 'rating overall': 0.0, 'year': _year, 'ratings': [], // Array für einzelne Bewertungen }); Navigator.pop(context); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Fehler beim Erstellen: $e')), ); } finally { setState(() => _loading = false); } } }, child: _loading ? const CircularProgressIndicator() : const Text('Erstellen'), ), ], ); } }