import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:provider/provider.dart'; import 'package:shimmer/shimmer.dart' as shimmer; import '../estado/estado_radio.dart'; import '../widgets/tarjeta_emisora.dart'; /// Pantalla principal: emisoras populares y por gĂ©nero. class PantallaInicio extends StatefulWidget { const PantallaInicio({super.key}); @override State createState() => _PantallaInicioState(); } class _PantallaInicioState extends State { static const _generos = [ 'pop', 'rock', 'jazz', 'classical', 'electronic', 'news', 'talk', 'hip-hop', 'country', 'metal', 'reggae', 'latin', ]; String? _generoSeleccionado; @override Widget build(BuildContext context) { final estado = context.watch(); final theme = Theme.of(context); return RefreshIndicator( onRefresh: estado.cargarPopulares, child: CustomScrollView( slivers: [ SliverToBoxAdapter( child: _seccionTendencias(estado, theme), ), SliverToBoxAdapter( child: _chipGeneros(theme), ), if (estado.error != null) SliverToBoxAdapter( child: _errorBanner(estado, theme), ), _gridEmisoras(estado, theme), ], ), ); } Widget _seccionTendencias(EstadoRadio estado, ThemeData theme) { return Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('đŸ”„ Tendencias', style: theme.textTheme.titleMedium), const SizedBox(height: 8), SizedBox( height: 56, child: estado.cargandoPopulares ? ListView.separated( scrollDirection: Axis.horizontal, itemCount: 5, separatorBuilder: (_, __) => const SizedBox(width: 8), itemBuilder: (_, __) => _ChipShimmer(theme: theme), ) : ListView.separated( scrollDirection: Axis.horizontal, itemCount: estado.tendencias.length, separatorBuilder: (_, __) => const SizedBox(width: 8), itemBuilder: (context, i) { final e = estado.tendencias[i]; return ActionChip( avatar: const Icon(Icons.radio, size: 18), label: Text(e.nombre, maxLines: 1), onPressed: () => context.read().reproducir(e), ).animate().fadeIn(delay: (i * 50).ms); }, ), ), ], ), ); } Widget _chipGeneros(ThemeData theme) { return Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('GĂ©neros', style: theme.textTheme.titleMedium), const SizedBox(height: 8), Wrap( spacing: 8, runSpacing: 4, children: _generos.map((g) { final seleccionado = _generoSeleccionado == g; return FilterChip( label: Text(g), selected: seleccionado, onSelected: (_) { setState(() { _generoSeleccionado = seleccionado ? null : g; }); if (!seleccionado) { context.read().buscar(tag: g); } else { context.read().cargarPopulares(); } }, ); }).toList(), ), ], ), ); } Widget _errorBanner(EstadoRadio estado, ThemeData theme) { return Padding( padding: const EdgeInsets.all(16), child: Card( color: theme.colorScheme.errorContainer, child: Padding( padding: const EdgeInsets.all(12), child: Row( children: [ Icon(Icons.wifi_off, color: theme.colorScheme.onErrorContainer), const SizedBox(width: 8), Expanded( child: Text( estado.error!, style: TextStyle(color: theme.colorScheme.onErrorContainer), ), ), TextButton( onPressed: estado.cargarPopulares, child: const Text('Reintentar'), ), ], ), ), ), ); } Widget _gridEmisoras(EstadoRadio estado, ThemeData theme) { final emisoras = _generoSeleccionado != null ? estado.resultadosBusqueda : estado.emisorasInicio; final cargando = estado.cargandoPopulares || (_generoSeleccionado != null && estado.cargandoBusqueda); if (cargando) { return SliverGrid( delegate: SliverChildBuilderDelegate( (_, __) => const TarjetaEmisoraShimmer(), childCount: 12, ), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.85, crossAxisSpacing: 8, mainAxisSpacing: 8, ), ); } if (emisoras.isEmpty) { return const SliverFillRemaining( child: Center(child: Text('No hay emisoras disponibles')), ); } return SliverPadding( padding: const EdgeInsets.all(16), sliver: SliverGrid( delegate: SliverChildBuilderDelegate( (context, i) => TarjetaEmisora( emisora: emisoras[i], onTap: () => context.read().reproducir(emisoras[i]), ).animate().fadeIn(delay: (i * 30).ms).slideY(begin: 0.1), childCount: emisoras.length, ), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.85, crossAxisSpacing: 8, mainAxisSpacing: 8, ), ), ); } } class _ChipShimmer extends StatelessWidget { final ThemeData theme; const _ChipShimmer({required this.theme}); @override Widget build(BuildContext context) { return shimmer.Shimmer.fromColors( baseColor: theme.colorScheme.surfaceContainerHighest, highlightColor: theme.colorScheme.surface, child: Container( width: 120, height: 56, decoration: BoxDecoration( color: theme.colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(20), ), ), ); } }