// lib/features/recycling_guide/presentation/screens/recycling_guide_screen.dart // Pantalla principal — Persona C la agrega al router así: // GoRoute(path: '/guia', builder: (_, __) => const RecyclingGuideScreen()) import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/recycling_provider.dart'; import '../widgets/category_card.dart'; import '../widgets/search_result_tile.dart'; import 'category_detail_screen.dart'; class RecyclingGuideScreen extends ConsumerStatefulWidget { const RecyclingGuideScreen({super.key}); @override ConsumerState createState() => _RecyclingGuideScreenState(); } class _RecyclingGuideScreenState extends ConsumerState { final _searchCtrl = TextEditingController(); bool _buscando = false; @override void dispose() { _searchCtrl.dispose(); super.dispose(); } void _onSearchChanged(String query) { setState(() => _buscando = query.trim().isNotEmpty); ref.read(recyclingSearchProvider.notifier).buscar(query); } void _limpiarBusqueda() { _searchCtrl.clear(); setState(() => _buscando = false); ref.read(recyclingSearchProvider.notifier).limpiar(); FocusScope.of(context).unfocus(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Guía de separación'), actions: [ // Badge offline — refuerza que funciona sin internet Container( margin: const EdgeInsets.only(right: 12), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.green.withOpacity(0.2), borderRadius: BorderRadius.circular(12), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.offline_bolt, size: 14, color: Colors.white), SizedBox(width: 4), Text( 'sin internet', style: TextStyle(fontSize: 11, color: Colors.white), ), ], ), ), ], ), body: Column( children: [ // ── Buscador ──────────────────────────────────────────── Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 8), child: TextField( controller: _searchCtrl, onChanged: _onSearchChanged, decoration: InputDecoration( hintText: '¿Dónde va el aceite? ¿y la pila?', prefixIcon: const Icon(Icons.search), suffixIcon: _buscando ? IconButton( icon: const Icon(Icons.close), onPressed: _limpiarBusqueda, ) : null, ), ), ), // ── Contenido dinámico ────────────────────────────────── Expanded( child: _buscando ? _SearchResults() : _CategoryList(), ), ], ), ); } } // ── Lista de categorías ────────────────────────────────────────────── class _CategoryList extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(recyclingCategoriesProvider); return async.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('Error: $e')), data: (categorias) => ListView.separated( padding: const EdgeInsets.fromLTRB(16, 8, 16, 24), itemCount: categorias.length, separatorBuilder: (_, __) => const SizedBox(height: 12), itemBuilder: (context, i) => CategoryCard( categoria: categorias[i], onTap: () => Navigator.push( context, MaterialPageRoute( builder: (_) => CategoryDetailScreen(categoria: categorias[i]), ), ), ), ), ); } } // ── Resultados de búsqueda ─────────────────────────────────────────── class _SearchResults extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final estado = ref.watch(recyclingSearchProvider); if (estado is Idle) { return const SizedBox.shrink(); } else if (estado is Loading) { return const Center(child: CircularProgressIndicator()); } else if (estado is Done) { if (estado.results.isEmpty) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.search_off, size: 48, color: Colors.grey[400]), const SizedBox(height: 12), Text( 'No encontramos ese residuo.', style: TextStyle(color: Colors.grey[600]), ), ], ), ); } return ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8), itemCount: estado.results.length, itemBuilder: (_, i) => SearchResultTile(resultado: estado.results[i]), ); } return const SizedBox.shrink(); } }