Separate Providers
This commit is contained in:
@@ -3,7 +3,8 @@ import 'package:frontend_splatournament_manager/pages/home_page.dart';
|
|||||||
import 'package:frontend_splatournament_manager/pages/login_page.dart';
|
import 'package:frontend_splatournament_manager/pages/login_page.dart';
|
||||||
import 'package:frontend_splatournament_manager/pages/settings_page.dart';
|
import 'package:frontend_splatournament_manager/pages/settings_page.dart';
|
||||||
import 'package:frontend_splatournament_manager/providers/auth_provider.dart';
|
import 'package:frontend_splatournament_manager/providers/auth_provider.dart';
|
||||||
import 'package:frontend_splatournament_manager/state_provider.dart';
|
import 'package:frontend_splatournament_manager/providers/theme_provider.dart';
|
||||||
|
import 'package:frontend_splatournament_manager/providers/tournament_provider.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
@@ -11,7 +12,8 @@ void main() {
|
|||||||
runApp(
|
runApp(
|
||||||
MultiProvider(
|
MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider(create: (_) => StateProvider()),
|
ChangeNotifierProvider(create: (_) => ThemeProvider()),
|
||||||
|
ChangeNotifierProvider(create: (_) => TournamentProvider()),
|
||||||
ChangeNotifierProvider(create: (_) => AuthProvider()),
|
ChangeNotifierProvider(create: (_) => AuthProvider()),
|
||||||
],
|
],
|
||||||
child: const SplatournamentApp(),
|
child: const SplatournamentApp(),
|
||||||
@@ -23,11 +25,11 @@ class SplatournamentApp extends StatelessWidget {
|
|||||||
const SplatournamentApp({super.key});
|
const SplatournamentApp({super.key});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final stateProvider = Provider.of<StateProvider>(context);
|
final themeProvider = Provider.of<ThemeProvider>(context);
|
||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
title: 'Splatournament Manager',
|
title: 'Splatournament Manager',
|
||||||
routerConfig: routes,
|
routerConfig: routes,
|
||||||
themeMode: stateProvider.theme,
|
themeMode: themeProvider.theme,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:frontend_splatournament_manager/state_provider.dart';
|
import 'package:frontend_splatournament_manager/providers/tournament_provider.dart';
|
||||||
import 'package:frontend_splatournament_manager/widgets/available_tournament_list.dart';
|
import 'package:frontend_splatournament_manager/widgets/available_tournament_list.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -13,16 +13,20 @@ class HomePage extends StatelessWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text("Splatournament"),
|
title: Text("Splatournament"),
|
||||||
actions: [
|
actions: [
|
||||||
Consumer<StateProvider>(
|
IconButton(
|
||||||
builder:
|
onPressed: () async {
|
||||||
(BuildContext context, StateProvider value, Widget? child) {
|
final tournamentProvider =
|
||||||
return IconButton(
|
Provider.of<TournamentProvider>(context, listen: false);
|
||||||
onPressed: () {
|
try {
|
||||||
value.notifyState();
|
await tournamentProvider.refreshAvailableTournaments();
|
||||||
},
|
} catch (_) {
|
||||||
icon: Icon(Icons.refresh),
|
if (!context.mounted) return;
|
||||||
);
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
},
|
SnackBar(content: Text('Failed to refresh tournaments')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.refresh),
|
||||||
),
|
),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ThemeProvider extends ChangeNotifier {
|
||||||
|
ThemeMode _themeMode = ThemeMode.system;
|
||||||
|
|
||||||
|
ThemeMode get theme => _themeMode;
|
||||||
|
|
||||||
|
void setTheme(ThemeMode mode) {
|
||||||
|
_themeMode = mode;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
class TournamentProvider extends ChangeNotifier {
|
||||||
|
static const String baseUrl = "http://10.0.2.2:3000";
|
||||||
|
|
||||||
|
List<Tournament> _availableTournaments = [];
|
||||||
|
Future<List<Tournament>>? _initialLoadFuture;
|
||||||
|
|
||||||
|
List<Tournament> get availableTournaments => _availableTournaments;
|
||||||
|
|
||||||
|
Future<List<Tournament>> _fetchTournaments() async {
|
||||||
|
final response = await http.get(Uri.parse('$baseUrl/tournaments'));
|
||||||
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
|
throw Exception('Failed to load tournaments (${response.statusCode})');
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<dynamic> list = json.decode(response.body);
|
||||||
|
return list.map((json) => Tournament.fromJson(json)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Tournament>> fetchAvailableTournaments() async {
|
||||||
|
_availableTournaments = await _fetchTournaments();
|
||||||
|
notifyListeners();
|
||||||
|
return _availableTournaments;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Tournament>> ensureTournamentsLoaded() {
|
||||||
|
_initialLoadFuture ??= fetchAvailableTournaments();
|
||||||
|
return _initialLoadFuture!;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Tournament>> refreshAvailableTournaments() {
|
||||||
|
_initialLoadFuture = fetchAvailableTournaments();
|
||||||
|
return _initialLoadFuture!;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
|
||||||
import 'package:http/http.dart' as http;
|
|
||||||
|
|
||||||
class StateProvider extends ChangeNotifier {
|
|
||||||
static const String baseUrl = "http://10.0.2.2:3000";
|
|
||||||
ThemeMode _themeMode = ThemeMode.system;
|
|
||||||
|
|
||||||
ThemeMode get theme => _themeMode;
|
|
||||||
|
|
||||||
void setTheme(ThemeMode mode) {
|
|
||||||
_themeMode = mode;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
List<Tournament>? _availableTournaments;
|
|
||||||
void notifyState(){
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
Future<List<Tournament>> fetchAvailableTournaments() async {
|
|
||||||
try {
|
|
||||||
var response = await http.get(Uri.parse('$baseUrl/tournaments'));
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
final List<dynamic> list = json.decode(response.body);
|
|
||||||
_availableTournaments = list.map((json) => Tournament.fromJson(json)).toList();
|
|
||||||
return _availableTournaments!;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
_availableTournaments = null;
|
|
||||||
return Future.error(e);
|
|
||||||
}
|
|
||||||
return[];
|
|
||||||
}
|
|
||||||
List<Tournament> get availableTournaments => _availableTournaments ?? [];
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
||||||
import 'package:frontend_splatournament_manager/pages/tournament_detail_page.dart';
|
import 'package:frontend_splatournament_manager/pages/tournament_detail_page.dart';
|
||||||
import 'package:frontend_splatournament_manager/state_provider.dart';
|
import 'package:frontend_splatournament_manager/providers/tournament_provider.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class AvailableTournamentList extends StatelessWidget {
|
class AvailableTournamentList extends StatelessWidget {
|
||||||
@@ -17,13 +17,10 @@ class AvailableTournamentList extends StatelessWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 350,
|
height: 350,
|
||||||
child: Consumer<StateProvider>(
|
child: Consumer<TournamentProvider>(
|
||||||
builder:
|
builder: (context, provider, _) {
|
||||||
(
|
return TournamentListFutureBuilder(provider: provider);
|
||||||
BuildContext context,
|
},
|
||||||
StateProvider provider,
|
|
||||||
Widget? child,
|
|
||||||
) => TournamentListFutureBuilder(provider: provider),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -33,22 +30,30 @@ class AvailableTournamentList extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TournamentListFutureBuilder extends StatelessWidget {
|
class TournamentListFutureBuilder extends StatelessWidget {
|
||||||
final StateProvider provider;
|
final TournamentProvider provider;
|
||||||
|
|
||||||
const TournamentListFutureBuilder({super.key, required this.provider});
|
const TournamentListFutureBuilder({super.key, required this.provider});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder(
|
return FutureBuilder<List<Tournament>>(
|
||||||
future: provider.fetchAvailableTournaments(),
|
future: provider.ensureTournamentsLoaded(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) {
|
final list = provider.availableTournaments;
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
print(list);
|
||||||
} else if (!snapshot.hasData ||
|
if (snapshot.connectionState == ConnectionState.waiting &&
|
||||||
snapshot.connectionState == ConnectionState.waiting) {
|
list.isEmpty) {
|
||||||
return Center(child: CircularProgressIndicator());
|
return Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
var list = snapshot.data!;
|
|
||||||
|
if (snapshot.hasError && list.isEmpty) {
|
||||||
|
return Center(child: Text('Error: ${snapshot.error}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.isEmpty) {
|
||||||
|
return Center(child: Text('No tournaments found'));
|
||||||
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
shrinkWrap: false,
|
shrinkWrap: false,
|
||||||
itemCount: list.length,
|
itemCount: list.length,
|
||||||
@@ -85,4 +90,3 @@ class TournamentListItem extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../state_provider.dart';
|
import '../providers/theme_provider.dart';
|
||||||
|
|
||||||
class ThemeSelectorWidget extends StatelessWidget {
|
class ThemeSelectorWidget extends StatelessWidget {
|
||||||
ThemeSelectorWidget({super.key});
|
ThemeSelectorWidget({super.key});
|
||||||
@@ -23,7 +23,7 @@ class ThemeSelectorWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final stateProvider = Provider.of<StateProvider>(context);
|
final themeProvider = Provider.of<ThemeProvider>(context);
|
||||||
return Container(
|
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),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@@ -37,10 +37,10 @@ class ThemeSelectorWidget extends StatelessWidget {
|
|||||||
child: DropdownButtonFormField(
|
child: DropdownButtonFormField(
|
||||||
icon: Icon(Icons.color_lens),
|
icon: Icon(Icons.color_lens),
|
||||||
items: dropdownElements,
|
items: dropdownElements,
|
||||||
initialValue: stateProvider.theme,
|
initialValue: themeProvider.theme,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
stateProvider.setTheme(value);
|
themeProvider.setTheme(value);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user