Add service and provider for Teams
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:frontend_splatournament_manager/pages/home_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/providers/auth_provider.dart';
|
||||
import 'package:frontend_splatournament_manager/providers/team_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';
|
||||
@@ -15,6 +16,7 @@ void main() {
|
||||
ChangeNotifierProvider(create: (_) => ThemeProvider()),
|
||||
ChangeNotifierProvider(create: (_) => TournamentProvider()),
|
||||
ChangeNotifierProvider(create: (_) => AuthProvider()),
|
||||
ChangeNotifierProvider(create: (_) => TeamProvider()),
|
||||
],
|
||||
child: const SplatournamentApp(),
|
||||
),
|
||||
@@ -22,6 +24,7 @@ void main() {
|
||||
}
|
||||
|
||||
class SplatournamentApp extends StatelessWidget {
|
||||
static const String baseUrl = "http://10.0.2.2:3000";
|
||||
const SplatournamentApp({super.key});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -41,12 +44,17 @@ class SplatournamentApp extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var routes = GoRouter(
|
||||
initialLocation: '/login',
|
||||
routes: [
|
||||
GoRoute(path: "/login", builder: (context, state) => const LoginPage()),
|
||||
GoRoute(path: "/", builder: (context, state) => HomePage(),routes: [
|
||||
GoRoute(path: "settings", builder: (context, state) => SettingsPage(),)
|
||||
])
|
||||
]
|
||||
);
|
||||
GoRoute(
|
||||
path: "/",
|
||||
builder: (context, state) => HomePage(),
|
||||
routes: [
|
||||
GoRoute(path: "settings", builder: (context, state) => SettingsPage()),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:frontend_splatournament_manager/models/team.dart';
|
||||
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
||||
import 'package:frontend_splatournament_manager/providers/team_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class TournamentDetailPage extends StatefulWidget {
|
||||
final Tournament tournament;
|
||||
@@ -72,15 +75,89 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
||||
}
|
||||
}
|
||||
|
||||
class TournamentTeamsWidget extends StatelessWidget{
|
||||
const TournamentTeamsWidget({super.key, required Tournament tournament});
|
||||
class TournamentTeamsWidget extends StatefulWidget {
|
||||
final Tournament tournament;
|
||||
|
||||
const TournamentTeamsWidget({super.key, required this.tournament});
|
||||
|
||||
@override
|
||||
State<TournamentTeamsWidget> createState() => _TournamentTeamsWidgetState();
|
||||
}
|
||||
|
||||
class _TournamentTeamsWidgetState extends State<TournamentTeamsWidget> {
|
||||
late Future<List<Team>> _teamsFuture;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_teamsFuture = Provider.of<TeamProvider>(context, listen: false)
|
||||
.getTeamsByTournament(widget.tournament.id);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Column( children: [
|
||||
//TODO: Show participating Teams
|
||||
Text("Teams"),
|
||||
],),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
|
||||
child: Text(
|
||||
'Registered Teams',
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 17),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: FutureBuilder<List<Team>>(
|
||||
future: _teamsFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
}
|
||||
if (snapshot.hasError) {
|
||||
return Center(child: Text('Error: ${snapshot.error}'));
|
||||
}
|
||||
final teams = snapshot.data ?? [];
|
||||
if (teams.isEmpty) {
|
||||
return Center(child: Text('No teams registered yet.'));
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: teams.length,
|
||||
itemBuilder: (context, index) {
|
||||
final team = teams[index];
|
||||
return ListTile(
|
||||
leading: CircleAvatar(child: Text(team.tag)),
|
||||
title: Text(team.name),
|
||||
subtitle: team.description.isNotEmpty
|
||||
? Text(team.description)
|
||||
: null,
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.remove_circle_outline, color: Colors.red),
|
||||
onPressed: () async {
|
||||
try {
|
||||
await Provider.of<TeamProvider>(context, listen: false)
|
||||
.removeTeamFromTournament(widget.tournament.id, team.id);
|
||||
setState(() {
|
||||
_teamsFuture =
|
||||
Provider.of<TeamProvider>(context, listen: false)
|
||||
.getTeamsByTournament(widget.tournament.id);
|
||||
});
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to remove team: $e')),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:frontend_splatournament_manager/models/team.dart';
|
||||
import 'package:frontend_splatournament_manager/services/team_service.dart';
|
||||
|
||||
class TeamProvider extends ChangeNotifier {
|
||||
final TeamService _teamService = TeamService();
|
||||
|
||||
List<Team> _teams = [];
|
||||
List<Team> get teams => _teams;
|
||||
|
||||
Future<List<Team>> fetchAllTeams() async {
|
||||
_teams = await _teamService.getAllTeams();
|
||||
notifyListeners();
|
||||
return _teams;
|
||||
}
|
||||
|
||||
Future<Team> createTeam({
|
||||
required String name,
|
||||
required String tag,
|
||||
String description = '',
|
||||
}) async {
|
||||
final team = await _teamService.createTeam(
|
||||
name: name,
|
||||
tag: tag,
|
||||
description: description,
|
||||
);
|
||||
_teams = [..._teams, team];
|
||||
notifyListeners();
|
||||
return team;
|
||||
}
|
||||
|
||||
Future<void> updateTeam(
|
||||
int id, {
|
||||
String? name,
|
||||
String? tag,
|
||||
String? description,
|
||||
}) async {
|
||||
await _teamService.updateTeam(id, name: name, tag: tag, description: description);
|
||||
await fetchAllTeams();
|
||||
}
|
||||
|
||||
Future<void> deleteTeam(int id) async {
|
||||
await _teamService.deleteTeam(id);
|
||||
_teams = _teams.where((t) => t.id != id).toList();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<List<Team>> getTeamsByTournament(int tournamentId) async {
|
||||
return _teamService.getTeamsByTournament(tournamentId);
|
||||
}
|
||||
|
||||
Future<void> registerTeamForTournament(int tournamentId, int teamId) async {
|
||||
await _teamService.registerTeamForTournament(tournamentId, teamId);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> removeTeamFromTournament(int tournamentId, int teamId) async {
|
||||
await _teamService.removeTeamFromTournament(tournamentId, teamId);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../main.dart';
|
||||
|
||||
class TournamentProvider extends ChangeNotifier {
|
||||
static const String baseUrl = "http://10.0.2.2:3000";
|
||||
final String baseUrl = SplatournamentApp.baseUrl;
|
||||
|
||||
List<Tournament> _availableTournaments = [];
|
||||
Future<List<Tournament>>? _initialLoadFuture;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'dart:convert';
|
||||
import 'package:frontend_splatournament_manager/main.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class AuthService {
|
||||
static const String baseUrl = "http://10.0.2.2:3000";
|
||||
|
||||
final String baseUrl = SplatournamentApp.baseUrl;
|
||||
Future<Map<String, dynamic>> register(String username, String password) async {
|
||||
final response = await http.post(
|
||||
Uri.parse('$baseUrl/register'),
|
||||
|
||||
127
frontend_splatournament_manager/lib/services/team_service.dart
Normal file
127
frontend_splatournament_manager/lib/services/team_service.dart
Normal file
@@ -0,0 +1,127 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:frontend_splatournament_manager/main.dart';
|
||||
import 'package:frontend_splatournament_manager/models/team.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class TeamService {
|
||||
final String baseUrl = SplatournamentApp.baseUrl;
|
||||
|
||||
Future<List<Team>> getAllTeams() async {
|
||||
final response = await http.get(Uri.parse('$baseUrl/teams'));
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
throw Exception('Failed to load teams (${response.statusCode})');
|
||||
}
|
||||
final List<dynamic> list = json.decode(response.body);
|
||||
return list.map((j) => Team.fromJson(j as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
Future<Team> getTeamById(int id) async {
|
||||
final response = await http.get(Uri.parse('$baseUrl/teams/$id'));
|
||||
if (response.statusCode == HttpStatus.notFound) {
|
||||
throw Exception('Team not found');
|
||||
}
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
throw Exception('Failed to load team (${response.statusCode})');
|
||||
}
|
||||
return Team.fromJson(json.decode(response.body) as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<Team> createTeam({
|
||||
required String name,
|
||||
required String tag,
|
||||
String description = '',
|
||||
}) async {
|
||||
final response = await http.post(
|
||||
Uri.parse('$baseUrl/teams'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({'name': name, 'tag': tag, 'description': description}),
|
||||
);
|
||||
if (response.statusCode != HttpStatus.created) {
|
||||
final body = json.decode(response.body);
|
||||
throw Exception(body['error'] ?? 'Failed to create team');
|
||||
}
|
||||
return Team.fromJson(json.decode(response.body) as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Future<void> updateTeam(
|
||||
int id, {
|
||||
String? name,
|
||||
String? tag,
|
||||
String? description,
|
||||
}) async {
|
||||
final response = await http.put(
|
||||
Uri.parse('$baseUrl/teams/$id'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({
|
||||
'name': ?name,
|
||||
'tag': ?tag,
|
||||
'description': ?description,
|
||||
}),
|
||||
);
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
final body = json.decode(response.body);
|
||||
throw Exception(body['error'] ?? 'Failed to update team');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteTeam(int id) async {
|
||||
final response = await http.delete(Uri.parse('$baseUrl/teams/$id'));
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
final body = json.decode(response.body);
|
||||
throw Exception(body['error'] ?? 'Failed to delete team');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Team>> getTeamsByTournament(int tournamentId) async {
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/tournaments/$tournamentId/teams'),
|
||||
);
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
throw Exception(
|
||||
'Failed to load teams for tournament (${response.statusCode})',
|
||||
);
|
||||
}
|
||||
final List<dynamic> list = json.decode(response.body);
|
||||
return list.map((j) => Team.fromJson(j as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
Future<void> registerTeamForTournament(int tournamentId, int teamId) async {
|
||||
final response = await http.post(
|
||||
Uri.parse('$baseUrl/tournaments/$tournamentId/teams'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({'teamId': teamId}),
|
||||
);
|
||||
if (response.statusCode == 409) {
|
||||
throw Exception('Team is already registered for this tournament');
|
||||
}
|
||||
if (response.statusCode != HttpStatus.created) {
|
||||
final body = json.decode(response.body);
|
||||
throw Exception(body['error'] ?? 'Failed to register team');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> removeTeamFromTournament(int tournamentId, int teamId) async {
|
||||
final response = await http.delete(
|
||||
Uri.parse('$baseUrl/tournaments/$tournamentId/teams/$teamId'),
|
||||
);
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
final body = json.decode(response.body);
|
||||
throw Exception(body['error'] ?? 'Failed to remove team from tournament');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> getTournamentsByTeam(int teamId) async {
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/teams/$teamId/tournaments'),
|
||||
);
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
throw Exception(
|
||||
'Failed to load tournaments for team (${response.statusCode})',
|
||||
);
|
||||
}
|
||||
final List<dynamic> list = json.decode(response.body);
|
||||
return list.cast<Map<String, dynamic>>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user