Files
winded/lib/features/teams/presentation/widgets/player_tile.dart
T
philip b239ae3e5f Initial commit: Flutter app + PHP/MySQL backend on Hostinger
Replaces Firebase with a self-hosted PHP/MySQL API served from
winded.prymsolutions.com. Includes full backend (schema, auth, events,
teams, brackets, suggestions, stats, media, file upload) and updated
Flutter repositories and domain models.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 20:13:57 -07:00

144 lines
3.8 KiB
Dart

import 'package:flutter/material.dart';
import '../../domain/player.dart';
/// ListTile-style row for one player in a team roster.
class PlayerTile extends StatelessWidget {
const PlayerTile({super.key, required this.player});
final Player player;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final scheme = theme.colorScheme;
final initial = player.name.isEmpty ? '?' : player.name.characters.first;
return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
leading: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (player.jerseyNumber != null) ...<Widget>[
_JerseyBadge(number: player.jerseyNumber!),
const SizedBox(width: 8),
],
CircleAvatar(
backgroundColor: scheme.secondaryContainer,
foregroundColor: scheme.onSecondaryContainer,
child: Text(
initial.toUpperCase(),
style: const TextStyle(fontWeight: FontWeight.w700),
),
),
],
),
title: Text(
player.name,
style: theme.textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w600,
),
),
subtitle: player.position == null
? null
: Text(
player.position!,
style: theme.textTheme.bodySmall?.copyWith(
color: scheme.onSurfaceVariant,
),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
_StatPill(
icon: Icons.sports_soccer,
value: player.goalsScored,
color: scheme.primary,
tooltip: 'Goals',
),
const SizedBox(width: 8),
_StatPill(
icon: Icons.handshake_outlined,
value: player.assists,
color: scheme.tertiary,
tooltip: 'Assists',
),
],
),
);
}
}
class _JerseyBadge extends StatelessWidget {
const _JerseyBadge({required this.number});
final int number;
@override
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
return Container(
constraints: const BoxConstraints(minWidth: 36),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: scheme.primary.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: scheme.primary.withValues(alpha: 0.4)),
),
child: Text(
'#$number',
textAlign: TextAlign.center,
style: TextStyle(
color: scheme.primary,
fontWeight: FontWeight.w800,
fontSize: 13,
),
),
);
}
}
class _StatPill extends StatelessWidget {
const _StatPill({
required this.icon,
required this.value,
required this.color,
required this.tooltip,
});
final IconData icon;
final int value;
final Color color;
final String tooltip;
@override
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
return Tooltip(
message: tooltip,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: scheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(999),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 14, color: color),
const SizedBox(width: 4),
Text(
'$value',
style: TextStyle(
color: scheme.onSurface,
fontWeight: FontWeight.w600,
fontSize: 12.5,
),
),
],
),
),
);
}
}