add carousel view

This commit is contained in:
2026-03-11 22:17:42 +01:00
parent 14c72b06d4
commit 383795bff6
6 changed files with 185 additions and 8 deletions

View File

@@ -4,6 +4,7 @@ import 'package:frontend_splatournament_manager/providers/team_provider.dart';
import 'package:frontend_splatournament_manager/widgets/available_tournament_list.dart';
import 'package:frontend_splatournament_manager/widgets/teams_list_widget.dart';
import 'package:frontend_splatournament_manager/widgets/my_teams_widget.dart';
import 'package:frontend_splatournament_manager/widgets/my_tournaments_carousel.dart';
import 'package:frontend_splatournament_manager/pages/create_tournament_page.dart';
import 'package:frontend_splatournament_manager/pages/create_team_page.dart';
import 'package:go_router/go_router.dart';
@@ -91,9 +92,11 @@ class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin
index: _selectedIndex,
children: [
// Tournaments View
Container(
padding: const EdgeInsets.fromLTRB(0, 12, 0, 36),
child: Column(children: [const Spacer(), const AvailableTournamentList()]),
Column(
children: [
const MyTournamentsCarousel(),
const Expanded(child: AvailableTournamentList()),
],
),
// Teams View with tabs
TabBarView(

View File

@@ -104,7 +104,7 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Tournament"),
title: Text(widget.tournament.name, style: TextStyle(overflow: TextOverflow.ellipsis)),
backgroundColor: Theme.of(context).colorScheme.surface.withAlpha(180),
elevation: 3,
actions: [

View File

@@ -88,5 +88,21 @@ class TeamProvider extends ChangeNotifier {
Future<List<Map<String, dynamic>>> getTeamMembers(int teamId) {
return _teamService.getTeamMembers(teamId);
}
Future<List<Map<String, dynamic>>> getMyTeamsTournaments() async {
final userTeams = await getUserTeams();
final Set<Map<String, dynamic>> tournamentsSet = {};
for (final team in userTeams) {
try {
final tournaments = await _teamService.getTournamentsByTeam(team.id);
tournamentsSet.addAll(tournaments);
} catch (e) {
// If a team has no tournaments, continue with others
}
}
return tournamentsSet.toList();
}
}

View File

@@ -0,0 +1,139 @@
import 'package:flutter/material.dart';
import 'package:frontend_splatournament_manager/providers/team_provider.dart';
import 'package:frontend_splatournament_manager/models/tournament.dart';
import 'package:frontend_splatournament_manager/pages/tournament_detail_page.dart';
import 'package:provider/provider.dart';
class MyTournamentsCarousel extends StatelessWidget {
const MyTournamentsCarousel({super.key});
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Map<String, dynamic>>>(
future: Provider.of<TeamProvider>(context, listen: false).getMyTeamsTournaments(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const SizedBox(
height: 180,
child: Center(child: CircularProgressIndicator()),
);
}
if (snapshot.hasError) {
return const SizedBox.shrink();
}
final tournaments = snapshot.data ?? [];
if (tournaments.isEmpty) {
return const SizedBox.shrink();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Text(
'My Tournaments',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
SizedBox(
height: 150,
child: PageView.builder(
controller: PageController(viewportFraction: 0.9),
itemCount: tournaments.length,
itemBuilder: (context, index) {
final tournament = Tournament.fromJson(tournaments[index]);
return _TournamentCard(tournament: tournament);
},
),
),
const SizedBox(height: 16),
],
);
},
);
}
}
class _TournamentCard extends StatelessWidget {
final Tournament tournament;
const _TournamentCard({required this.tournament});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.symmetric(horizontal: 8),
elevation: 4,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TournamentDetailPage(tournament: tournament),
),
);
},
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
const Icon(Icons.emoji_events, size: 32),
const SizedBox(width: 12),
Expanded(
child: Text(
tournament.name,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
const SizedBox(height: 8),
Text(
tournament.description,
style: const TextStyle(fontSize: 16),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 8),
Row(
children: [
Icon(
tournament.isRegistrationOpen
? Icons.check_circle
: Icons.cancel,
size: 18,
),
const SizedBox(width: 4),
Text(
tournament.isRegistrationOpen
? 'Registration Open'
: 'Registration Closed',
style: const TextStyle(fontSize: 14),
),
const Spacer(),
Text(
'${tournament.currentTeamAmount}/${tournament.maxTeamAmount} teams',
style: const TextStyle(fontSize: 14),
),
],
),
],
),
),
),
);
}
}