added 2 themes

This commit is contained in:
2026-03-12 11:45:59 +01:00
parent 0658b0cd5b
commit bd56d97b6d
6 changed files with 225 additions and 76 deletions

View File

@@ -77,3 +77,17 @@ Folgende Dateien wurden in diesem Prompt verändert:
- Show a placeholder in the carousel if no tournaments were found.<br><br>
Folgende Dateien wurden in diesem Prompt verändert:
- frontend_splatournament_manager/lib/widgets/my_tournaments_carousel.dart
- Add 2 more themes that change the colors of the application, one light and one dark.<br><br>
Folgende Dateien wurden in diesem Prompt verändert:
- frontend_splatournament_manager/lib/providers/theme_provider.dart
- frontend_splatournament_manager/lib/main.dart
- frontend_splatournament_manager/lib/widgets/theme_selector_widget.dart
- Make the background color of the tournament detail page semi-transparent and keep the title text legible.<br><br>
Folgende Dateien wurden in diesem Prompt verändert:
- frontend_splatournament_manager/lib/pages/tournament_detail_page.dart
- In the Teams view, fix the upper TabBar text so selected and non-selected labels are readable.<br><br>
Folgende Dateien wurden in diesem Prompt verändert:
- frontend_splatournament_manager/lib/pages/home_page.dart

View File

@@ -32,15 +32,9 @@ class SplatournamentApp extends StatelessWidget {
return MaterialApp.router(
title: 'Splatournament Manager',
routerConfig: routes,
themeMode: themeProvider.theme,
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.blue,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.deepPurple,
),
themeMode: themeProvider.themeMode,
theme: themeProvider.lightTheme,
darkTheme: themeProvider.darkTheme,
);
}
}

View File

@@ -17,7 +17,8 @@ class HomePage extends StatefulWidget {
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
int _selectedIndex = 0;
late TabController _tabController;
@@ -35,12 +36,23 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
@override
Widget build(BuildContext context) {
final appBarForeground =
Theme.of(context).appBarTheme.foregroundColor ??
Theme.of(context).colorScheme.onSurface;
return Scaffold(
appBar: AppBar(
title: Text(_selectedIndex == 0 ? "Tournaments" : "Teams"),
bottom: _selectedIndex == 1
? TabBar(
controller: _tabController,
labelColor: appBarForeground,
unselectedLabelColor: appBarForeground.withValues(alpha: 0.82),
indicatorColor: appBarForeground,
labelStyle: const TextStyle(fontWeight: FontWeight.w700),
unselectedLabelStyle: const TextStyle(
fontWeight: FontWeight.w500,
),
tabs: const [
Tab(text: 'All Teams'),
Tab(text: 'My Teams'),
@@ -101,10 +113,7 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
// Teams View with tabs
TabBarView(
controller: _tabController,
children: const [
TeamsListWidget(),
MyTeamsWidget(),
],
children: const [TeamsListWidget(), MyTeamsWidget()],
),
],
),
@@ -120,10 +129,7 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
icon: Icon(Icons.emoji_events),
label: 'Tournaments',
),
BottomNavigationBarItem(
icon: Icon(Icons.groups),
label: 'Teams',
),
BottomNavigationBarItem(icon: Icon(Icons.groups), label: 'Teams'),
],
),
floatingActionButton: FloatingActionButton(
@@ -138,9 +144,7 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CreateTeamPage(),
),
MaterialPageRoute(builder: (context) => const CreateTeamPage()),
);
}
},

View File

@@ -26,7 +26,11 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
if (teams.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('You are not a member of any team. Join or create a team first!')),
const SnackBar(
content: Text(
'You are not a member of any team. Join or create a team first!',
),
),
);
return;
}
@@ -87,25 +91,34 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to join: ${e.toString().replaceAll('Exception: ', '')}'),
content: Text(
'Failed to join: ${e.toString().replaceAll('Exception: ', '')}',
),
),
);
}
}
} catch (e) {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to load your teams: $e')),
);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('Failed to load your teams: $e')));
}
}
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final appBarBackground = colorScheme.surface.withValues(alpha: 0.78);
return Scaffold(
appBar: AppBar(
title: Text(widget.tournament.name, style: TextStyle(overflow: TextOverflow.ellipsis)),
backgroundColor: Theme.of(context).colorScheme.surface.withAlpha(180),
backgroundColor: appBarBackground,
foregroundColor: colorScheme.onSurface,
title: Text(
widget.tournament.name,
style: TextStyle(overflow: TextOverflow.ellipsis),
),
elevation: 3,
actions: [
IconButton(

View File

@@ -1,11 +1,50 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ThemeProvider extends ChangeNotifier {
static const String _themeKey = 'theme_mode';
ThemeMode _themeMode = ThemeMode.system;
enum AppThemeOption { lightBlue, darkPurple, lightMint, darkAmber, system }
ThemeMode get theme => _themeMode;
class ThemeProvider extends ChangeNotifier {
static const String _themeKey = 'theme_option';
AppThemeOption _selectedTheme = AppThemeOption.system;
AppThemeOption get selectedTheme => _selectedTheme;
ThemeMode get themeMode {
switch (_selectedTheme) {
case AppThemeOption.lightBlue:
case AppThemeOption.lightMint:
return ThemeMode.light;
case AppThemeOption.darkPurple:
case AppThemeOption.darkAmber:
return ThemeMode.dark;
case AppThemeOption.system:
return ThemeMode.system;
}
}
ThemeData get lightTheme {
switch (_selectedTheme) {
case AppThemeOption.lightMint:
return _mintLightTheme;
case AppThemeOption.lightBlue:
case AppThemeOption.darkPurple:
case AppThemeOption.darkAmber:
case AppThemeOption.system:
return _blueLightTheme;
}
}
ThemeData get darkTheme {
switch (_selectedTheme) {
case AppThemeOption.darkAmber:
return _amberDarkTheme;
case AppThemeOption.lightBlue:
case AppThemeOption.darkPurple:
case AppThemeOption.lightMint:
case AppThemeOption.system:
return _purpleDarkTheme;
}
}
ThemeProvider() {
_loadTheme();
@@ -14,38 +53,116 @@ class ThemeProvider extends ChangeNotifier {
Future<void> _loadTheme() async {
final prefs = await SharedPreferences.getInstance();
final themeName = prefs.getString(_themeKey) ?? 'system';
_themeMode = _themeFromString(themeName);
_selectedTheme = _themeFromString(themeName);
notifyListeners();
}
Future<void> setTheme(ThemeMode mode) async {
_themeMode = mode;
Future<void> setTheme(AppThemeOption option) async {
_selectedTheme = option;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_themeKey, _themeToString(mode));
await prefs.setString(_themeKey, _themeToString(option));
}
String _themeToString(ThemeMode mode) {
switch (mode) {
case ThemeMode.light:
return 'light';
case ThemeMode.dark:
return 'dark';
case ThemeMode.system:
String _themeToString(AppThemeOption option) {
switch (option) {
case AppThemeOption.lightBlue:
return 'light_blue';
case AppThemeOption.darkPurple:
return 'dark_purple';
case AppThemeOption.lightMint:
return 'light_mint';
case AppThemeOption.darkAmber:
return 'dark_amber';
case AppThemeOption.system:
return 'system';
}
}
ThemeMode _themeFromString(String theme) {
AppThemeOption _themeFromString(String theme) {
switch (theme) {
case 'light':
return ThemeMode.light;
case 'light_blue':
return AppThemeOption.lightBlue;
case 'dark':
return ThemeMode.dark;
case 'dark_purple':
return AppThemeOption.darkPurple;
case 'light_mint':
return AppThemeOption.lightMint;
case 'dark_amber':
return AppThemeOption.darkAmber;
case 'system':
default:
return ThemeMode.system;
return AppThemeOption.system;
}
}
ThemeData get _blueLightTheme {
final scheme = ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
);
return ThemeData(
colorScheme: scheme,
useMaterial3: true,
appBarTheme: AppBarTheme(
backgroundColor: scheme.primary,
foregroundColor: scheme.onPrimary,
),
);
}
ThemeData get _purpleDarkTheme {
final scheme = ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.dark,
);
return ThemeData(
colorScheme: scheme,
useMaterial3: true,
appBarTheme: AppBarTheme(
backgroundColor: scheme.surface,
foregroundColor: scheme.onSurface,
),
);
}
ThemeData get _mintLightTheme {
final scheme = ColorScheme.fromSeed(
seedColor: const Color(0xFF00897B),
brightness: Brightness.light,
);
return ThemeData(
colorScheme: scheme,
useMaterial3: true,
appBarTheme: AppBarTheme(
backgroundColor: scheme.primary,
foregroundColor: scheme.onPrimary,
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: scheme.secondary,
foregroundColor: scheme.onSecondary,
),
);
}
ThemeData get _amberDarkTheme {
final scheme = ColorScheme.fromSeed(
seedColor: const Color(0xFFFF8F00),
brightness: Brightness.dark,
);
return ThemeData(
colorScheme: scheme,
useMaterial3: true,
appBarTheme: AppBarTheme(
backgroundColor: scheme.surface,
foregroundColor: scheme.onSurface,
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: scheme.primary,
foregroundColor: scheme.onPrimary,
),
);
}
}

View File

@@ -6,26 +6,34 @@ import '../providers/theme_provider.dart';
class ThemeSelectorWidget extends StatelessWidget {
ThemeSelectorWidget({super.key});
final List<DropdownMenuItem> dropdownElements = [
DropdownMenuItem(
value: ThemeMode.light,
child: Text("Light"),
final List<DropdownMenuItem<AppThemeOption>> dropdownElements = [
const DropdownMenuItem(
value: AppThemeOption.lightBlue,
child: Text("Light Blue"),
),
DropdownMenuItem(
value: ThemeMode.dark,
child: Text("Dark"),
const DropdownMenuItem(
value: AppThemeOption.darkPurple,
child: Text("Dark Purple"),
),
DropdownMenuItem(
value: ThemeMode.system,
child: Text("System"),
const DropdownMenuItem(
value: AppThemeOption.lightMint,
child: Text("Light Mint"),
),
const DropdownMenuItem(
value: AppThemeOption.darkAmber,
child: Text("Dark Amber"),
),
const DropdownMenuItem(value: AppThemeOption.system, child: Text("System")),
];
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);
return Container(
decoration: BoxDecoration(color: Theme.of(context).hoverColor, borderRadius: BorderRadius.circular(8)),
decoration: BoxDecoration(
color: Theme.of(context).hoverColor,
borderRadius: BorderRadius.circular(8),
),
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
child: Row(
@@ -34,10 +42,10 @@ class ThemeSelectorWidget extends StatelessWidget {
Text("Theme"),
SizedBox(
width: 250,
child: DropdownButtonFormField(
icon: Icon(Icons.color_lens),
child: DropdownButtonFormField<AppThemeOption>(
icon: const Icon(Icons.color_lens),
items: dropdownElements,
initialValue: themeProvider.theme,
initialValue: themeProvider.selectedTheme,
onChanged: (value) {
if (value == null) return;
themeProvider.setTheme(value);
@@ -48,5 +56,4 @@ class ThemeSelectorWidget extends StatelessWidget {
),
);
}
}