diff --git a/trainerbox/lib/main.dart b/trainerbox/lib/main.dart index cce94d1..382a10d 100644 --- a/trainerbox/lib/main.dart +++ b/trainerbox/lib/main.dart @@ -1,6 +1,9 @@ +// main.dart +// Einstiegspunkt der App und globale Konfigurationen import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'firebase_options.dart'; +import 'screens/home_screen.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -24,289 +27,3 @@ class MyApp extends StatelessWidget { ); } } - -class HomeScreen extends StatefulWidget { - const HomeScreen({super.key}); - - @override - State createState() => _HomeScreenState(); -} - -class _HomeScreenState extends State { - final PageController _pageController = PageController(); - int _currentPage = 0; - - @override - void initState() { - super.initState(); - _pageController.addListener(() { - setState(() { - _currentPage = _pageController.page?.round() ?? 0; - }); - }); - } - - @override - void dispose() { - _pageController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SafeArea( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Center( - child: Text( - 'Hallo Trainer!', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - color: Colors.pink, - ), - ), - ), - const SizedBox(height: 20), - Container( - height: 200, - width: double.infinity, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - image: const DecorationImage( - image: AssetImage('images/training_bg.jpg'), - fit: BoxFit.cover, - colorFilter: ColorFilter.mode( - Colors.black26, - BlendMode.darken, - ), - ), - ), - child: const Center( - child: Text( - 'Dein nächstes Training', - style: TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(height: 20), - const Text( - 'Favoriten', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - SizedBox( - height: 100, - child: ListView( - scrollDirection: Axis.horizontal, - children: const [ - CategoryCircle( - title: 'Kondition', - icon: Icons.directions_run, - ), - CategoryCircle(title: 'Wurf', icon: Icons.sports_handball), - CategoryCircle( - title: 'Passen', - icon: Icons.sports_volleyball, - ), - CategoryCircle( - title: 'Torhüter', - icon: Icons.sports_soccer, - ), - ], - ), - ), - const SizedBox(height: 20), - const Text( - 'Vorschläge', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - SizedBox( - height: 180, - child: Stack( - alignment: Alignment.center, - children: [ - PageView( - controller: _pageController, - children: const [ - ExerciseCard( - title: 'Wurf', - category: 'Wurf', - icon: Icons.sports_handball, - ), - ExerciseCard( - title: 'Doppelpass', - category: 'Passen', - icon: Icons.sports_volleyball, - ), - ExerciseCard( - title: 'Torhüter Training', - category: 'Torhüter', - icon: Icons.sports_soccer, - ), - ], - ), - // Left Arrow - if (_currentPage > 0) - Positioned( - left: 0, - child: IconButton( - icon: Icon( - Icons.arrow_back_ios, - size: 40, - color: Theme.of(context).colorScheme.primary, - ), - onPressed: () { - _pageController.previousPage( - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - ); - }, - ), - ), - // Right Arrow - if (_currentPage < 2) - Positioned( - right: 0, - child: IconButton( - icon: Icon( - Icons.arrow_forward_ios, - size: 40, - color: Theme.of(context).colorScheme.primary, - ), - onPressed: () { - _pageController.nextPage( - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - ); - }, - ), - ), - ], - ), - ), - ], - ), - ), - ), - bottomNavigationBar: BottomNavigationBar( - type: BottomNavigationBarType.fixed, - items: const [ - BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), - BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Suche'), - BottomNavigationBarItem( - icon: Icon(Icons.favorite_border), - label: 'Favoriten', - ), - BottomNavigationBarItem( - icon: Icon(Icons.calendar_today), - label: 'Kalender', - ), - BottomNavigationBarItem( - icon: Icon(Icons.person_outline), - label: 'Profil', - ), - ], - ), - ); - } -} - -class CategoryCircle extends StatelessWidget { - final String title; - final IconData icon; - - const CategoryCircle({super.key, required this.title, required this.icon}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(right: 16.0), - child: Column( - children: [ - Container( - width: 70, - height: 70, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - shape: BoxShape.circle, - ), - child: Icon( - icon, - color: Theme.of(context).colorScheme.primary, - size: 35, - ), - ), - const SizedBox(height: 8), - Text( - title, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ), - ], - ), - ); - } -} - -class ExerciseCard extends StatelessWidget { - final String title; - final String category; - final IconData icon; - - const ExerciseCard({ - super.key, - required this.title, - required this.category, - required this.icon, - }); - - @override - Widget build(BuildContext context) { - return Card( - margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - child: Container( - width: double.infinity, - height: 180, - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(icon, size: 60, color: Theme.of(context).colorScheme.primary), - const SizedBox(height: 16), - Text( - title, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - const SizedBox(height: 8), - Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - ), - child: Text( - category, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/trainerbox/lib/models/exercise.dart b/trainerbox/lib/models/exercise.dart new file mode 100644 index 0000000..c2556a7 --- /dev/null +++ b/trainerbox/lib/models/exercise.dart @@ -0,0 +1,16 @@ +// models/exercise.dart +// Datenmodell für eine Trainingsübung + +import 'package:flutter/material.dart'; + +class Exercise { + final String title; // Name der Übung + final String category; // Kategorie der Übung + final IconData icon; // Icon zur Darstellung + + Exercise({ + required this.title, + required this.category, + required this.icon, + }); +} \ No newline at end of file diff --git a/trainerbox/lib/screens/calendar_tab.dart b/trainerbox/lib/screens/calendar_tab.dart new file mode 100644 index 0000000..8ba8019 --- /dev/null +++ b/trainerbox/lib/screens/calendar_tab.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class CalendarTab extends StatelessWidget { + const CalendarTab({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Center( + child: Text( + 'Kalender', + style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold), + ), + ), + ); + } +} \ No newline at end of file diff --git a/trainerbox/lib/screens/favorites_tab.dart b/trainerbox/lib/screens/favorites_tab.dart new file mode 100644 index 0000000..6a64259 --- /dev/null +++ b/trainerbox/lib/screens/favorites_tab.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class FavoritesTab extends StatelessWidget { + const FavoritesTab({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Center( + child: Text( + 'Favoriten', + style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold), + ), + ), + ); + } +} \ No newline at end of file diff --git a/trainerbox/lib/screens/home_screen.dart b/trainerbox/lib/screens/home_screen.dart new file mode 100644 index 0000000..59ae37b --- /dev/null +++ b/trainerbox/lib/screens/home_screen.dart @@ -0,0 +1,61 @@ +// screens/home_screen.dart +// Enthält die BottomNavigationBar-Logik und Navigation zwischen den Hauptscreens +import 'package:flutter/material.dart'; +import 'home_tab.dart'; +import 'search_tab.dart'; +import 'favorites_tab.dart'; +import 'calendar_tab.dart'; +import 'profile_tab.dart'; + +class HomeScreen extends StatefulWidget { + const HomeScreen({super.key}); + + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + int _selectedIndex = 0; + + final List _screens = const [ + HomeTab(), + SearchTab(), + FavoritesTab(), + CalendarTab(), + ProfileTab(), + ]; + + void _onItemTapped(int index) { + setState(() { + _selectedIndex = index; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: _screens[_selectedIndex], + bottomNavigationBar: BottomNavigationBar( + type: BottomNavigationBarType.fixed, + currentIndex: _selectedIndex, + onTap: _onItemTapped, + items: const [ + BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), + BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Suche'), + BottomNavigationBarItem( + icon: Icon(Icons.favorite_border), + label: 'Favoriten', + ), + BottomNavigationBarItem( + icon: Icon(Icons.calendar_today), + label: 'Kalender', + ), + BottomNavigationBarItem( + icon: Icon(Icons.person_outline), + label: 'Profil', + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/trainerbox/lib/screens/home_tab.dart b/trainerbox/lib/screens/home_tab.dart new file mode 100644 index 0000000..6a9b7f9 --- /dev/null +++ b/trainerbox/lib/screens/home_tab.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import '../widgets/category_circle.dart'; +import '../widgets/exercise_card.dart'; + +class HomeTab extends StatelessWidget { + const HomeTab({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // Begrüßung + const Center( + child: Text( + 'Hallo Trainer!', + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + color: Colors.pink, + ), + ), + ), + const SizedBox(height: 20), + // Bild mit Titel + Container( + height: 200, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + image: const DecorationImage( + image: AssetImage('images/training_bg.jpg'), + fit: BoxFit.cover, + colorFilter: ColorFilter.mode( + Colors.black26, + BlendMode.darken, + ), + ), + ), + child: Center( + child: Text( + 'Dein nächstes Training', + style: TextStyle( + color: Colors.blueAccent, + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + const SizedBox(height: 20), + // Favoriten Kategorien + const Text( + 'Favoriten', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + SizedBox( + height: 100, + child: ListView( + scrollDirection: Axis.horizontal, + children: const [ + CategoryCircle( + title: 'Kondition', + icon: Icons.directions_run, + ), + CategoryCircle(title: 'Wurf', icon: Icons.sports_handball), + CategoryCircle( + title: 'Passen', + icon: Icons.sports_volleyball, + ), + CategoryCircle( + title: 'Torhüter', + icon: Icons.sports_soccer, + ), + ], + ), + ), + const SizedBox(height: 20), + // Vorschläge + const Text( + 'Vorschläge', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + SizedBox( + height: 180, + child: Stack( + alignment: Alignment.center, + children: [ + PageView( + children: const [ + ExerciseCard( + title: 'Wurf', + category: 'Wurf', + icon: Icons.sports_handball, + ), + ExerciseCard( + title: 'Doppelpass', + category: 'Passen', + icon: Icons.sports_volleyball, + ), + ExerciseCard( + title: 'Torhüter Training', + category: 'Torhüter', + icon: Icons.sports_soccer, + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/trainerbox/lib/screens/profile_tab.dart b/trainerbox/lib/screens/profile_tab.dart new file mode 100644 index 0000000..6b71be2 --- /dev/null +++ b/trainerbox/lib/screens/profile_tab.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class ProfileTab extends StatelessWidget { + const ProfileTab({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Center( + child: Text( + 'Profil', + style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold), + ), + ), + ); + } +} \ No newline at end of file diff --git a/trainerbox/lib/screens/search_tab.dart b/trainerbox/lib/screens/search_tab.dart new file mode 100644 index 0000000..17d3f5b --- /dev/null +++ b/trainerbox/lib/screens/search_tab.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class SearchTab extends StatelessWidget { + const SearchTab({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Center( + child: Text( + 'Suche', + style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold), + ), + ), + ); + } +} \ No newline at end of file diff --git a/trainerbox/lib/widgets/category_circle.dart b/trainerbox/lib/widgets/category_circle.dart new file mode 100644 index 0000000..9e7b56f --- /dev/null +++ b/trainerbox/lib/widgets/category_circle.dart @@ -0,0 +1,41 @@ +// widgets/category_circle.dart +// Widget für eine runde Kategorie-Ansicht +import 'package:flutter/material.dart'; + +class CategoryCircle extends StatelessWidget { + final String title; + final IconData icon; + + const CategoryCircle({super.key, required this.title, required this.icon}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(right: 16.0), + child: Column( + children: [ + // Kreis mit Icon + Container( + width: 70, + height: 70, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + shape: BoxShape.circle, + ), + child: Icon( + icon, + color: Theme.of(context).colorScheme.primary, + size: 35, + ), + ), + const SizedBox(height: 8), + // Titel unter dem Kreis + Text( + title, + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/trainerbox/lib/widgets/exercise_card.dart b/trainerbox/lib/widgets/exercise_card.dart new file mode 100644 index 0000000..2628c8b --- /dev/null +++ b/trainerbox/lib/widgets/exercise_card.dart @@ -0,0 +1,60 @@ +// widgets/exercise_card.dart +// Widget für eine Trainingskarten-Ansicht +import 'package:flutter/material.dart'; + +class ExerciseCard extends StatelessWidget { + final String title; + final String category; + final IconData icon; + + const ExerciseCard({ + super.key, + required this.title, + required this.category, + required this.icon, + }); + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + child: Container( + width: double.infinity, + height: 180, + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Icon für die Übung + Icon(icon, size: 60, color: Theme.of(context).colorScheme.primary), + const SizedBox(height: 16), + // Titel der Übung + Text( + title, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + const SizedBox(height: 8), + // Kategorie-Badge + Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + ), + child: Text( + category, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ), + ); + } +} \ No newline at end of file