Styling of Tournament list and detail page
This commit is contained in:
@@ -173,4 +173,9 @@ Folgende Dateien wurden in diesem Prompt verändert:
|
||||
- Always require the full amount of teams for initializing the bracket.
|
||||
Folgende Dateien wurden in diesem Prompt verändert:
|
||||
- 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
|
||||
@@ -243,46 +243,50 @@ class _TournamentTeamsWidgetState extends State<TournamentTeamsWidget> {
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 16),
|
||||
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>(
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(child: Text(team.tag)),
|
||||
title: Text(team.name),
|
||||
subtitle: team.description.isNotEmpty
|
||||
? Text(team.description)
|
||||
: null,
|
||||
trailing: IconButton(
|
||||
icon: const Icon(
|
||||
Icons.remove_circle_outline,
|
||||
color: Colors.red,
|
||||
),
|
||||
onPressed: () async {
|
||||
try {
|
||||
await Provider.of<TeamProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).getTeamsByTournament(widget.tournament.id);
|
||||
});
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Team konnte nicht entfernt werden: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||
).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(
|
||||
'Team konnte nicht entfernt werden: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -379,26 +383,34 @@ class DetailHeader extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
return SizedBox(
|
||||
height: 350,
|
||||
height: 250,
|
||||
width: double.maxFinite,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadiusDirectional.vertical(
|
||||
bottom: Radius.circular(8),
|
||||
borderRadius: const BorderRadiusDirectional.vertical(
|
||||
bottom: Radius.circular(16),
|
||||
),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
//TODO: Replace with proper image
|
||||
image: NetworkImage(
|
||||
"https://flutter.dev/assets/image_1.w635.f71cbb614cd16a40bfb87e128278227c.png",
|
||||
),
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
colorScheme.primaryContainer,
|
||||
colorScheme.secondaryContainer,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.fromLTRB(16, 0, 0, 12),
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 6),
|
||||
child: Column(
|
||||
verticalDirection: VerticalDirection.up,
|
||||
children: [
|
||||
const SizedBox(height: 80),
|
||||
Icon(
|
||||
Icons.emoji_events,
|
||||
size: 116,
|
||||
color: colorScheme.onPrimaryContainer.withValues(alpha: 0.7),
|
||||
),
|
||||
Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
InputChip(
|
||||
|
||||
@@ -9,22 +9,24 @@ class AvailableTournamentList extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.fromLTRB(24, 0, 24, 0),
|
||||
child: Column(
|
||||
children: [
|
||||
const Row(children: [Text('Verfügbare Turniere')]),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 350,
|
||||
child: Consumer<TournamentProvider>(
|
||||
builder: (context, provider, _) {
|
||||
return TournamentListFutureBuilder(provider: provider);
|
||||
},
|
||||
),
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.fromLTRB(16, 8, 16, 4),
|
||||
child: Text(
|
||||
'Verfügbare Turniere',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Consumer<TournamentProvider>(
|
||||
builder: (context, provider, _) {
|
||||
return TournamentListFutureBuilder(provider: provider);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -58,6 +60,7 @@ class TournamentListFutureBuilder extends StatelessWidget {
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 16),
|
||||
shrinkWrap: false,
|
||||
itemCount: list.length,
|
||||
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 {
|
||||
final Tournament tournament;
|
||||
|
||||
@@ -77,19 +89,50 @@ class TournamentListItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
leading: Icon(Icons.abc),
|
||||
title: Text(tournament.name),
|
||||
subtitle: Text(tournament.description),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TournamentDetailPage(tournament: tournament),
|
||||
final dateRange =
|
||||
'${_fmtDate(tournament.registrationStartDate)} – ${_fmtDate(tournament.registrationEndDate)}';
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
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),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user