Styling of Tournament list and detail page

This commit is contained in:
2026-03-13 15:25:44 +01:00
parent 95897ccc07
commit dfe99a85a1
3 changed files with 133 additions and 73 deletions

View File

@@ -174,3 +174,8 @@ Folgende Dateien wurden in diesem Prompt verändert:
Folgende Dateien wurden in diesem Prompt verändert: Folgende Dateien wurden in diesem Prompt verändert:
- backend_splatournament_manager/src/app.ts - backend_splatournament_manager/src/app.ts
- frontend_splatournament_manager/lib/pages/tournament_bracket_page.dart - frontend_splatournament_manager/lib/pages/tournament_bracket_page.dart
- Style the tournament list and detail page to look closer to the rest of the app.
Folgende Dateien wurden in diesem Prompt verändert:
- frontend_splatournament_manager/lib/widgets/available_tournament_list.dart
- frontend_splatournament_manager/lib/pages/tournament_detail_page.dart

View File

@@ -243,17 +243,20 @@ class _TournamentTeamsWidgetState extends State<TournamentTeamsWidget> {
); );
} }
return ListView.builder( return ListView.builder(
padding: const EdgeInsets.fromLTRB(16, 4, 16, 16),
itemCount: teams.length, itemCount: teams.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final team = teams[index]; final team = teams[index];
return ListTile( return Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
leading: CircleAvatar(child: Text(team.tag)), leading: CircleAvatar(child: Text(team.tag)),
title: Text(team.name), title: Text(team.name),
subtitle: team.description.isNotEmpty subtitle: team.description.isNotEmpty
? Text(team.description) ? Text(team.description)
: null, : null,
trailing: IconButton( trailing: IconButton(
icon: Icon( icon: const Icon(
Icons.remove_circle_outline, Icons.remove_circle_outline,
color: Colors.red, color: Colors.red,
), ),
@@ -284,6 +287,7 @@ class _TournamentTeamsWidgetState extends State<TournamentTeamsWidget> {
} }
}, },
), ),
),
); );
}, },
); );
@@ -379,26 +383,34 @@ class DetailHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return SizedBox( return SizedBox(
height: 350, height: 250,
width: double.maxFinite, width: double.maxFinite,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadiusDirectional.vertical( borderRadius: const BorderRadiusDirectional.vertical(
bottom: Radius.circular(8), bottom: Radius.circular(16),
), ),
image: DecorationImage( gradient: LinearGradient(
fit: BoxFit.cover, colors: [
//TODO: Replace with proper image colorScheme.primaryContainer,
image: NetworkImage( colorScheme.secondaryContainer,
"https://flutter.dev/assets/image_1.w635.f71cbb614cd16a40bfb87e128278227c.png", ],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
), ),
), ),
), padding: const EdgeInsets.fromLTRB(16, 0, 16, 6),
padding: EdgeInsets.fromLTRB(16, 0, 0, 12),
child: Column( child: Column(
verticalDirection: VerticalDirection.up,
children: [ children: [
const SizedBox(height: 80),
Icon(
Icons.emoji_events,
size: 116,
color: colorScheme.onPrimaryContainer.withValues(alpha: 0.7),
),
Spacer(),
Row( Row(
children: [ children: [
InputChip( InputChip(

View File

@@ -9,14 +9,17 @@ class AvailableTournamentList extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Column(
padding: EdgeInsets.fromLTRB(24, 0, 24, 0), crossAxisAlignment: CrossAxisAlignment.start,
child: Column(
children: [ children: [
const Row(children: [Text('Verfügbare Turniere')]), const Padding(
SizedBox( padding: EdgeInsets.fromLTRB(16, 8, 16, 4),
width: double.infinity, child: Text(
height: 350, 'Verfügbare Turniere',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
Expanded(
child: Consumer<TournamentProvider>( child: Consumer<TournamentProvider>(
builder: (context, provider, _) { builder: (context, provider, _) {
return TournamentListFutureBuilder(provider: provider); return TournamentListFutureBuilder(provider: provider);
@@ -24,7 +27,6 @@ class AvailableTournamentList extends StatelessWidget {
), ),
), ),
], ],
),
); );
} }
} }
@@ -58,6 +60,7 @@ class TournamentListFutureBuilder extends StatelessWidget {
} }
return ListView.builder( return ListView.builder(
padding: const EdgeInsets.fromLTRB(16, 4, 16, 16),
shrinkWrap: false, shrinkWrap: false,
itemCount: list.length, itemCount: list.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@@ -70,6 +73,15 @@ class TournamentListFutureBuilder extends StatelessWidget {
} }
} }
String _fmtDate(String iso) {
try {
final d = DateTime.parse(iso);
return '${d.day.toString().padLeft(2, '0')}.${d.month.toString().padLeft(2, '0')}.${d.year}';
} catch (_) {
return iso;
}
}
class TournamentListItem extends StatelessWidget { class TournamentListItem extends StatelessWidget {
final Tournament tournament; final Tournament tournament;
@@ -77,19 +89,50 @@ class TournamentListItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( final dateRange =
contentPadding: EdgeInsets.all(0), '${_fmtDate(tournament.registrationStartDate)} ${_fmtDate(tournament.registrationEndDate)}';
leading: Icon(Icons.abc), return Card(
title: Text(tournament.name), margin: const EdgeInsets.only(bottom: 12),
subtitle: Text(tournament.description), child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => TournamentDetailPage(tournament: tournament), builder: (context) =>
TournamentDetailPage(tournament: tournament),
), ),
); );
}, },
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
CircleAvatar(
child: const Icon(Icons.emoji_events),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
tournament.name,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 4),
Text(
'${tournament.currentTeamAmount}/${tournament.maxTeamAmount} Teams\n$dateRange',
style: const TextStyle(fontSize: 13),
),
],
),
),
const Icon(Icons.chevron_right),
],
),
),
),
); );
} }
} }