import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'tema_app.dart'; class FondoFarolero extends StatelessWidget { final Widget child; final bool intenso; const FondoFarolero({ super.key, required this.child, this.intenso = false, }); @override Widget build(BuildContext context) { return DecoratedBox( decoration: const BoxDecoration(gradient: TemaApp.gradienteFondo), child: CustomPaint( painter: _FondoFaroleroPainter(intenso: intenso), child: child, ), ); } } class PanelFarolero extends StatelessWidget { final Widget child; final EdgeInsetsGeometry padding; final EdgeInsetsGeometry? margin; final Color? color; final Color? borderColor; const PanelFarolero({ super.key, required this.child, this.padding = const EdgeInsets.all(16), this.margin, this.color, this.borderColor, }); @override Widget build(BuildContext context) { return Container( width: double.infinity, margin: margin, padding: padding, decoration: TemaApp.decoracionPanel(color: color, borderColor: borderColor), child: child, ); } } class LogoFarolero extends StatelessWidget { final double size; const LogoFarolero({super.key, this.size = 64}); @override Widget build(BuildContext context) { return Stack( alignment: Alignment.center, children: [ Positioned( top: 0, child: Icon( Icons.lightbulb, color: TemaApp.colorDorado.withValues(alpha: 0.32), size: size * 0.82, ), ), Text( 'FAROLERO', style: GoogleFonts.bangers( fontSize: size, color: TemaApp.colorNaranja, letterSpacing: 0, shadows: const [ Shadow(offset: Offset(3, 4), blurRadius: 0, color: Color(0xFF5E1205)), Shadow(offset: Offset(0, 0), blurRadius: 16, color: Color(0xFFFFC247)), ], ), ), ], ); } } class BotonFarolero extends StatelessWidget { final String texto; final IconData icono; final VoidCallback? onPressed; final LinearGradient gradient; final Color foreground; const BotonFarolero({ super.key, required this.texto, required this.icono, required this.onPressed, this.gradient = TemaApp.gradientePrimario, this.foreground = Colors.black, }); const BotonFarolero.secundario({ super.key, required this.texto, required this.icono, required this.onPressed, }) : gradient = const LinearGradient( colors: [TemaApp.colorPurpura, Color(0xFF2B1736)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), foreground = Colors.white; const BotonFarolero.oscuro({ super.key, required this.texto, required this.icono, required this.onPressed, }) : gradient = const LinearGradient( colors: [Color(0xFF151F27), Color(0xFF090E13)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), foreground = TemaApp.colorTexto; @override Widget build(BuildContext context) { final habilitado = onPressed != null; return Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(8), onTap: onPressed, child: Ink( height: 54, decoration: BoxDecoration( gradient: habilitado ? gradient : const LinearGradient( colors: [TemaApp.colorTarjeta, TemaApp.colorSuperficie], ), borderRadius: BorderRadius.circular(8), border: Border.all( color: habilitado ? TemaApp.colorDorado.withValues(alpha: 0.74) : TemaApp.colorBorde, ), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.34), blurRadius: 14, offset: const Offset(0, 8), ), ], ), child: Row( children: [ SizedBox( width: 58, child: Icon(icono, color: foreground, size: 28), ), Expanded( child: Text( texto.toUpperCase(), textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleMedium?.copyWith( color: foreground, fontSize: 18, fontWeight: FontWeight.w800, ), ), ), const SizedBox(width: 58), ], ), ), ), ); } } class AccesoFarolero extends StatelessWidget { final String etiqueta; final IconData icono; final VoidCallback onPressed; const AccesoFarolero({ super.key, required this.etiqueta, required this.icono, required this.onPressed, }); @override Widget build(BuildContext context) { return Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(8), onTap: onPressed, child: Ink( height: 66, decoration: TemaApp.decoracionPanel(color: TemaApp.colorSuperficie), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icono, color: TemaApp.colorNaranja, size: 22), const SizedBox(height: 5), Text( etiqueta.toUpperCase(), maxLines: 1, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: TemaApp.colorDorado, fontSize: 11, fontWeight: FontWeight.w700, ), ), ], ), ), ), ); } } class TarjetaPalabraFarolero extends StatelessWidget { final String palabra; const TarjetaPalabraFarolero({super.key, required this.palabra}); @override Widget build(BuildContext context) { return Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 28), decoration: BoxDecoration( color: const Color(0xFFC48642), borderRadius: BorderRadius.circular(8), border: Border.all(color: const Color(0xFF6B3519), width: 2), boxShadow: [ BoxShadow( color: TemaApp.colorNaranja.withValues(alpha: 0.28), blurRadius: 24, ), ], ), child: Text( palabra.toUpperCase(), textAlign: TextAlign.center, style: GoogleFonts.oswald( color: const Color(0xFF1B0C05), fontSize: 42, fontWeight: FontWeight.w900, letterSpacing: 0, ), ), ); } } class AvatarFarolero extends StatelessWidget { final String texto; final String? assetPath; final Color color; final double size; const AvatarFarolero({ super.key, required this.texto, this.assetPath, this.color = TemaApp.colorNaranja, this.size = 40, }); @override Widget build(BuildContext context) { return Container( width: size, height: size, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [color.withValues(alpha: 0.9), TemaApp.colorSuperficie], ), border: Border.all(color: TemaApp.colorDorado, width: 2), ), child: Center( child: assetPath == null ? Text( texto, style: TextStyle( color: TemaApp.colorTexto, fontWeight: FontWeight.bold, fontSize: size * 0.36, ), ) : ClipOval( child: Image.asset( assetPath!, width: size, height: size, fit: BoxFit.cover, ), ), ), ); } } class _FondoFaroleroPainter extends CustomPainter { final bool intenso; const _FondoFaroleroPainter({required this.intenso}); @override void paint(Canvas canvas, Size size) { final paint = Paint()..isAntiAlias = true; final alto = size.height; final ancho = size.width; paint.color = const Color(0xFF152845).withValues(alpha: intenso ? 0.34 : 0.22); canvas.drawCircle(Offset(ancho * 0.78, alto * 0.16), 18, paint); paint.color = const Color(0xFF07101A).withValues(alpha: 0.82); final colinas = Path() ..moveTo(0, alto * 0.34) ..quadraticBezierTo(ancho * 0.28, alto * 0.21, ancho * 0.55, alto * 0.33) ..quadraticBezierTo(ancho * 0.82, alto * 0.43, ancho, alto * 0.26) ..lineTo(ancho, alto) ..lineTo(0, alto) ..close(); canvas.drawPath(colinas, paint); _dibujarCasas(canvas, size, paint); _dibujarFarol(canvas, size, paint); paint.shader = RadialGradient( colors: [ TemaApp.colorNaranja.withValues(alpha: intenso ? 0.26 : 0.16), Colors.transparent, ], ).createShader(Rect.fromCircle(center: Offset(ancho * 0.52, alto * 0.36), radius: 160)); canvas.drawCircle(Offset(ancho * 0.52, alto * 0.36), 160, paint); paint.shader = null; } void _dibujarCasas(Canvas canvas, Size size, Paint paint) { final alto = size.height; final ancho = size.width; paint.color = const Color(0xFF020407).withValues(alpha: 0.72); for (var i = 0; i < 5; i++) { final w = ancho * (0.16 + i * 0.018); final h = alto * (0.18 + (i % 2) * 0.05); final x = -30 + i * ancho * 0.24; final y = alto * (0.72 - i * 0.02); final casa = Rect.fromLTWH(x, y - h, w, h); canvas.drawRect(casa, paint); final tejado = Path() ..moveTo(x - 8, y - h) ..lineTo(x + w * 0.48, y - h - 38) ..lineTo(x + w + 8, y - h) ..close(); canvas.drawPath(tejado, paint); final ventana = Paint() ..color = TemaApp.colorNaranja.withValues(alpha: 0.38) ..isAntiAlias = true; for (var j = 0; j < 2; j++) { canvas.drawRRect( RRect.fromRectAndRadius( Rect.fromLTWH(x + 18 + j * 34, y - h + 36, 12, 22), const Radius.circular(2), ), ventana, ); } } } void _dibujarFarol(Canvas canvas, Size size, Paint paint) { final alto = size.height; final ancho = size.width; final centro = Offset(ancho * 0.5, alto * 0.28); final glow = Paint() ..shader = RadialGradient( colors: [ TemaApp.colorNaranja.withValues(alpha: 0.44), Colors.transparent, ], ).createShader(Rect.fromCircle(center: centro, radius: 92)); canvas.drawCircle(centro, 92, glow); paint ..shader = null ..style = PaintingStyle.stroke ..strokeWidth = 3 ..color = const Color(0xFF050507).withValues(alpha: 0.82); canvas.drawArc( Rect.fromCircle(center: centro.translate(0, -16), radius: 35), math.pi, math.pi, false, paint, ); paint.style = PaintingStyle.fill; canvas.drawRRect( RRect.fromRectAndRadius( Rect.fromCenter(center: centro, width: 38, height: 54), const Radius.circular(5), ), paint, ); paint.color = TemaApp.colorNaranja.withValues(alpha: 0.82); canvas.drawRRect( RRect.fromRectAndRadius( Rect.fromCenter(center: centro, width: 21, height: 34), const Radius.circular(4), ), paint, ); } @override bool shouldRepaint(covariant _FondoFaroleroPainter oldDelegate) { return oldDelegate.intenso != intenso; } }