refactorización de pantallas

This commit is contained in:
2026-05-11 23:16:38 +02:00
parent 1929d86689
commit 4599678e77
48 changed files with 1446 additions and 1463 deletions
+247
View File
@@ -335,6 +335,253 @@ class BotonFarolero extends StatelessWidget {
}
}
class TarjetaFaseFarolero extends StatelessWidget {
final IconData icono;
final String titulo;
final String? subtitulo;
final Color color;
final Widget child;
final EdgeInsetsGeometry padding;
const TarjetaFaseFarolero({
super.key,
required this.icono,
required this.titulo,
this.subtitulo,
this.color = TemaApp.colorNaranja,
this.child = const SizedBox.shrink(),
this.padding = const EdgeInsets.all(18),
});
@override
Widget build(BuildContext context) {
return PanelFarolero(
padding: padding,
borderColor: color.withValues(alpha: 0.48),
color: TemaApp.colorSuperficie.withValues(alpha: 0.84),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 54,
height: 54,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
color.withValues(alpha: 0.42),
Colors.black.withValues(alpha: 0.62),
],
),
border: Border.all(color: color.withValues(alpha: 0.72)),
),
child: Icon(icono, color: color, size: 30),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
titulo,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: TemaApp.colorDorado,
fontWeight: FontWeight.w900,
),
),
if (subtitulo != null) ...[
const SizedBox(height: 3),
Text(
subtitulo!,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: TemaApp.colorTextoSecundario,
),
),
],
],
),
),
],
),
const SizedBox(height: 16),
child,
],
),
);
}
}
class EstadoJugadorFarolero extends StatelessWidget {
final String nombre;
final bool destacado;
final bool completado;
final IconData icono;
final String? subtitulo;
final VoidCallback? onTap;
const EstadoJugadorFarolero({
super.key,
required this.nombre,
this.destacado = false,
this.completado = false,
this.icono = Icons.person,
this.subtitulo,
this.onTap,
});
@override
Widget build(BuildContext context) {
final color = completado ? TemaApp.colorVerde : TemaApp.colorNaranja;
return Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(18),
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
decoration: BoxDecoration(
color: completado
? TemaApp.colorVerde.withValues(alpha: 0.14)
: TemaApp.colorTarjeta.withValues(alpha: 0.84),
borderRadius: BorderRadius.circular(18),
border: Border.all(
color: destacado
? TemaApp.colorDorado.withValues(alpha: 0.72)
: color.withValues(alpha: completado ? 0.54 : 0.28),
),
),
child: Row(
children: [
Container(
width: 42,
height: 42,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color.withValues(alpha: 0.16),
border: Border.all(color: color.withValues(alpha: 0.72)),
),
child: Icon(icono, color: color, size: 24),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
nombre,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: destacado ? FontWeight.w900 : FontWeight.w700,
),
),
if (subtitulo != null) ...[
const SizedBox(height: 2),
Text(
subtitulo!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: TemaApp.colorTextoSecundario,
),
),
],
],
),
),
Icon(
completado ? Icons.check_circle : Icons.hourglass_bottom,
color: completado ? TemaApp.colorVerde : TemaApp.colorTextoSecundario,
),
],
),
),
),
),
);
}
}
class SelectorVotoFarolero extends StatelessWidget {
final String nombre;
final bool seleccionado;
final VoidCallback onTap;
const SelectorVotoFarolero({
super.key,
required this.nombre,
required this.seleccionado,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return EstadoJugadorFarolero(
nombre: nombre,
destacado: seleccionado,
completado: seleccionado,
icono: seleccionado ? Icons.check : Icons.person_search,
onTap: onTap,
);
}
}
class TemporizadorFarolero extends StatelessWidget {
final String etiqueta;
final String tiempo;
final bool agotado;
const TemporizadorFarolero({
super.key,
required this.etiqueta,
required this.tiempo,
this.agotado = false,
});
@override
Widget build(BuildContext context) {
final color = agotado ? TemaApp.colorAcento : TemaApp.colorNaranja;
return PanelFarolero(
padding: const EdgeInsets.all(22),
borderColor: color.withValues(alpha: 0.62),
color: color.withValues(alpha: agotado ? 0.18 : 0.10),
child: Stack(
alignment: Alignment.center,
children: [
Image.asset(
'assets/ui/generated/gameplay/gameplay_phase_emblem.webp',
height: 132,
fit: BoxFit.contain,
opacity: const AlwaysStoppedAnimation(0.34),
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
etiqueta,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
Text(
tiempo,
style: Theme.of(context).textTheme.displaySmall?.copyWith(
color: color,
fontWeight: FontWeight.w900,
),
),
],
),
],
),
);
}
}
class MarcoBotonFaroleroPainter extends CustomPainter {
final LinearGradient gradient;
final bool destacado;