Prueba diseño
All checks were successful
Build & Deploy Farolero / Análisis de código (push) Successful in 19s
Build & Deploy Farolero / Build APK + AAB release (push) Successful in 1m29s

This commit is contained in:
2026-05-10 14:36:36 +02:00
parent 23658ca214
commit b7a00d1394

View File

@@ -34,7 +34,10 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_confetti = ConfettiController(duration: const Duration(seconds: 3)); _confetti = ConfettiController(duration: const Duration(seconds: 5));
Future.delayed(const Duration(milliseconds: 450), () {
if (mounted) _confetti.play();
});
} }
@override @override
@@ -56,6 +59,7 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
backgroundColor: const Color(0xFF05070D),
body: FondoFarolero( body: FondoFarolero(
intenso: true, intenso: true,
child: Stack( child: Stack(
@@ -76,9 +80,9 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
child: ConfettiWidget( child: ConfettiWidget(
confettiController: _confetti, confettiController: _confetti,
blastDirectionality: BlastDirectionality.explosive, blastDirectionality: BlastDirectionality.explosive,
emissionFrequency: 0.06, emissionFrequency: 0.09,
numberOfParticles: 18, numberOfParticles: 28,
gravity: 0.22, gravity: 0.18,
colors: const [ colors: const [
TemaApp.colorDorado, TemaApp.colorDorado,
TemaApp.colorNaranja, TemaApp.colorNaranja,
@@ -87,6 +91,24 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
], ],
), ),
), ),
Positioned.fill(
child: IgnorePointer(
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.transparent,
Colors.black.withValues(alpha: 0.10),
Colors.black.withValues(alpha: 0.52),
],
stops: const [0.0, 0.54, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
),
),
),
SafeArea( SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(20, 22, 20, 28), padding: const EdgeInsets.fromLTRB(20, 22, 20, 28),
@@ -103,12 +125,15 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
? TemaApp.colorVerde ? TemaApp.colorVerde
: TemaApp.colorAcento, : TemaApp.colorAcento,
), ),
const SizedBox(height: 18), Transform.translate(
offset: const Offset(0, -18),
child: Column(
children: [
if (_progreso == null) if (_progreso == null)
const _TarjetaRecompensaCargando() const _TarjetaRecompensaCargando()
else else
_TarjetaProgresoGamificacion(progreso: _progreso!), _TarjetaProgresoGamificacion(progreso: _progreso!),
const SizedBox(height: 16), const SizedBox(height: 18),
_TarjetaSecreto( _TarjetaSecreto(
palabra: partida.palabraSecreta, palabra: partida.palabraSecreta,
categoria: BancoPalabras.nombreBonitoCategoria( categoria: BancoPalabras.nombreBonitoCategoria(
@@ -116,14 +141,14 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
l10n, l10n,
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 18),
_TarjetaImpostores( _TarjetaImpostores(
titulo: impostores.length == 1 titulo: impostores.length == 1
? l10n.theImpostorWas ? l10n.theImpostorWas
: l10n.theImpostorsWere, : l10n.theImpostorsWere,
impostores: impostores, impostores: impostores,
), ),
const SizedBox(height: 16), const SizedBox(height: 18),
if (partida.historialVotaciones.isNotEmpty) if (partida.historialVotaciones.isNotEmpty)
_TarjetaHistorialVotos(partida: partida, l10n: l10n), _TarjetaHistorialVotos(partida: partida, l10n: l10n),
const SizedBox(height: 24), const SizedBox(height: 24),
@@ -146,6 +171,9 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
], ],
), ),
), ),
],
),
),
), ),
], ],
), ),
@@ -192,8 +220,9 @@ class _HeroResultado extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final apertura = String.fromCharCode(0x00A1);
final tituloLimpio = titulo final tituloLimpio = titulo
.replaceAll('¡', '') .replaceAll(apertura, '')
.replaceAll('!', '') .replaceAll('!', '')
.trim() .trim()
.toUpperCase(); .toUpperCase();
@@ -201,7 +230,7 @@ class _HeroResultado extends StatelessWidget {
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
SizedBox( SizedBox(
height: 330, height: 420,
width: double.infinity, width: double.infinity,
child: CustomPaint(painter: _HeroCinematicoPainter(color: color)), child: CustomPaint(painter: _HeroCinematicoPainter(color: color)),
), ),
@@ -212,6 +241,7 @@ class _HeroResultado extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium?.copyWith( style: Theme.of(context).textTheme.headlineMedium?.copyWith(
color: TemaApp.colorDorado, color: TemaApp.colorDorado,
fontSize: 38,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
letterSpacing: -0.5, letterSpacing: -0.5,
shadows: [ shadows: [
@@ -222,58 +252,54 @@ class _HeroResultado extends StatelessWidget {
], ],
), ),
).animate().fadeIn(duration: 260.ms).slideY(begin: -0.18), ).animate().fadeIn(duration: 260.ms).slideY(begin: -0.18),
const SizedBox(height: 42), const SizedBox(height: 62),
Text( Text(
'RESULTADOS', 'RESULTADOS',
style: Theme.of(context).textTheme.labelLarge?.copyWith( style: Theme.of(context).textTheme.labelLarge?.copyWith(
color: TemaApp.colorDorado, color: TemaApp.colorDorado,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
letterSpacing: 4, letterSpacing: 5,
), ),
).animate().fadeIn(duration: 350.ms).slideY(begin: -0.25), ).animate().fadeIn(duration: 350.ms).slideY(begin: -0.25),
const SizedBox(height: 18), const SizedBox(height: 20),
Stack(
alignment: Alignment.center,
children: [
Image.asset(
'assets/rewards/medal_unlock_burst.png',
width: 210,
height: 210,
fit: BoxFit.cover,
),
Container( Container(
width: 132, width: 154,
height: 132, height: 154,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
gradient: RadialGradient( gradient: RadialGradient(
colors: [ colors: [
color.withValues(alpha: 0.55), color.withValues(alpha: 0.36),
TemaApp.colorSuperficie, const Color(0xFF111116),
Colors.black.withValues(alpha: 0.72), Colors.black.withValues(alpha: 0.88),
], ],
), ),
border: Border.all(color: TemaApp.colorDorado, width: 3), border: Border.all(color: TemaApp.colorDorado, width: 4),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: color.withValues(alpha: 0.72), color: TemaApp.colorNaranja.withValues(alpha: 0.75),
blurRadius: 38, blurRadius: 52,
spreadRadius: 4, spreadRadius: 7,
), ),
BoxShadow( BoxShadow(
color: TemaApp.colorDorado.withValues(alpha: 0.32), color: color.withValues(alpha: 0.62),
blurRadius: 22, blurRadius: 36,
spreadRadius: 1, spreadRadius: 2,
), ),
], ],
), ),
child: Stack( child: _IconoResultadoPremium(icono: icono),
alignment: Alignment.center,
children: [
Icon(icono, size: 72, color: TemaApp.colorDorado),
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Colors.white.withValues(alpha: 0.08),
),
),
),
), ),
], ],
),
) )
.animate() .animate()
.scale( .scale(
@@ -282,17 +308,17 @@ class _HeroResultado extends StatelessWidget {
curve: Curves.elasticOut, curve: Curves.elasticOut,
) )
.shimmer(delay: 700.ms, duration: 1500.ms), .shimmer(delay: 700.ms, duration: 1500.ms),
const SizedBox(height: 14), const SizedBox(height: 12),
Text( Text(
'¡$tituloLimpio!', '$apertura$tituloLimpio!',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium?.copyWith( style: Theme.of(context).textTheme.headlineMedium?.copyWith(
color: color, color: color,
fontSize: 31, fontSize: 34,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
letterSpacing: 1.2, letterSpacing: 1.2,
shadows: [ shadows: [
Shadow(color: color.withValues(alpha: 0.85), blurRadius: 22), Shadow(color: color.withValues(alpha: 0.90), blurRadius: 24),
], ],
), ),
).animate().fadeIn(delay: 180.ms).slideY(begin: 0.25), ).animate().fadeIn(delay: 180.ms).slideY(begin: 0.25),
@@ -303,6 +329,47 @@ class _HeroResultado extends StatelessWidget {
} }
} }
class _IconoResultadoPremium extends StatelessWidget {
final IconData icono;
const _IconoResultadoPremium({required this.icono});
@override
Widget build(BuildContext context) {
if (icono != Icons.theater_comedy) {
return Icon(icono, size: 82, color: TemaApp.colorDorado);
}
return Stack(
alignment: Alignment.center,
children: [
Transform.translate(
offset: const Offset(-18, 12),
child: Transform.rotate(
angle: -0.10,
child: Icon(
Icons.mood,
size: 66,
color: TemaApp.colorDorado.withValues(alpha: 0.98),
),
),
),
Transform.translate(
offset: const Offset(20, -13),
child: Transform.rotate(
angle: 0.12,
child: Icon(
Icons.sentiment_dissatisfied,
size: 70,
color: TemaApp.colorDorado.withValues(alpha: 0.98),
),
),
),
],
);
}
}
class _TarjetaProgresoGamificacion extends StatelessWidget { class _TarjetaProgresoGamificacion extends StatelessWidget {
final ProgresoGamificacionUsuario progreso; final ProgresoGamificacionUsuario progreso;
@@ -320,15 +387,42 @@ class _TarjetaProgresoGamificacion extends StatelessWidget {
children: [ children: [
Row( Row(
children: [ children: [
const Icon(Icons.local_fire_department, color: TemaApp.colorNaranja), Container(
const SizedBox(width: 8), width: 52,
height: 52,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
TemaApp.colorNaranja.withValues(alpha: 0.95),
TemaApp.colorDorado.withValues(alpha: 0.78),
],
begin: Alignment.bottomLeft,
end: Alignment.topRight,
),
boxShadow: [
BoxShadow(
color: TemaApp.colorNaranja.withValues(alpha: 0.42),
blurRadius: 22,
),
],
),
child: const Icon(
Icons.local_fire_department,
color: Color(0xFF1B1010),
size: 30,
),
),
const SizedBox(width: 14),
Expanded( Expanded(
child: Text( child: Text(
'RECOMPENSAS DE PARTIDA', 'RECOMPENSAS DE PARTIDA',
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: TemaApp.colorDorado, color: TemaApp.colorDorado,
fontSize: 20,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
letterSpacing: 1, letterSpacing: 1.1,
height: 1.05,
), ),
), ),
), ),
@@ -337,7 +431,7 @@ class _TarjetaProgresoGamificacion extends StatelessWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
_BarraFuegoPremium(antes: antes, despues: despues), _BarraFuegoPremium(antes: antes, despues: despues),
const SizedBox(height: 16), const SizedBox(height: 20),
if (nuevas.isEmpty) if (nuevas.isEmpty)
Text( Text(
'Sin medallas nuevas esta vez. Seguí acumulando fuego.', 'Sin medallas nuevas esta vez. Seguí acumulando fuego.',
@@ -408,10 +502,10 @@ class _PanelRecompensa extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ClipRRect( return ClipRRect(
borderRadius: BorderRadius.circular(28), borderRadius: BorderRadius.circular(32),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(24),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
colors: [ colors: [
@@ -421,23 +515,23 @@ class _PanelRecompensa extends StatelessWidget {
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
), ),
borderRadius: BorderRadius.circular(28), borderRadius: BorderRadius.circular(32),
border: Border.all(color: TemaApp.colorDorado.withValues(alpha: 0.58)), border: Border.all(color: TemaApp.colorDorado.withValues(alpha: 0.58)),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: TemaApp.colorNaranja.withValues(alpha: 0.20), color: TemaApp.colorNaranja.withValues(alpha: 0.25),
blurRadius: 36, blurRadius: 44,
offset: const Offset(0, 18), offset: const Offset(0, 22),
), ),
BoxShadow( BoxShadow(
color: Colors.black.withValues(alpha: 0.50), color: Colors.black.withValues(alpha: 0.50),
blurRadius: 22, blurRadius: 28,
offset: const Offset(0, 10), offset: const Offset(0, 14),
), ),
], ],
), ),
foregroundDecoration: BoxDecoration( foregroundDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(28), borderRadius: BorderRadius.circular(32),
gradient: LinearGradient( gradient: LinearGradient(
colors: [ colors: [
Colors.white.withValues(alpha: 0.06), Colors.white.withValues(alpha: 0.06),
@@ -463,9 +557,14 @@ class _DeltaFuego extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final texto = valor >= 0 ? '+$valor' : '$valor'; final texto = valor >= 0 ? '+$valor' : '$valor';
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: TemaApp.colorNaranja.withValues(alpha: 0.18), gradient: LinearGradient(
colors: [
TemaApp.colorNaranja.withValues(alpha: 0.28),
TemaApp.colorDorado.withValues(alpha: 0.14),
],
),
borderRadius: BorderRadius.circular(999), borderRadius: BorderRadius.circular(999),
border: Border.all(color: TemaApp.colorNaranja), border: Border.all(color: TemaApp.colorNaranja),
boxShadow: [ boxShadow: [
@@ -479,11 +578,11 @@ class _DeltaFuego extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Icon(Icons.local_fire_department, const Icon(Icons.local_fire_department,
color: TemaApp.colorNaranja, size: 18), color: TemaApp.colorNaranja, size: 24),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
texto, texto,
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.headlineSmall?.copyWith(
color: TemaApp.colorDorado, color: TemaApp.colorDorado,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
), ),
@@ -529,9 +628,9 @@ class _BarraFuegoPremium extends StatelessWidget {
), ),
], ],
), ),
const SizedBox(height: 8), const SizedBox(height: 12),
Container( Container(
height: 30, height: 38,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.72), color: Colors.black.withValues(alpha: 0.72),
borderRadius: BorderRadius.circular(999), borderRadius: BorderRadius.circular(999),
@@ -579,6 +678,23 @@ class _BarraFuegoPremium extends StatelessWidget {
), ),
), ),
), ),
Positioned(
left: 12,
right: 12,
top: 5,
child: Container(
height: 6,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(999),
gradient: LinearGradient(
colors: [
Colors.white.withValues(alpha: 0.62),
Colors.transparent,
],
),
),
),
),
], ],
), ),
), ),
@@ -714,13 +830,23 @@ class _TarjetaImpostores extends StatelessWidget {
return _PanelRecompensa( return _PanelRecompensa(
child: Column( child: Column(
children: [ children: [
Text( Row(
'🎭 $titulo', mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.theater_comedy, color: TemaApp.colorAcento),
const SizedBox(width: 8),
Flexible(
child: Text(
titulo,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
color: Colors.white, color: Colors.white,
), ),
), ),
),
],
),
const SizedBox(height: 10), const SizedBox(height: 10),
...impostores.map( ...impostores.map(
(j) => Padding( (j) => Padding(