import 'package:flutter/material.dart'; import 'package:city_repository/city_repository.dart'; import 'package:injector/injector.dart'; import 'package:intl_phone_field/helpers.dart'; import 'package:shimmer/shimmer.dart'; class CityListScreen extends StatefulWidget { const CityListScreen({Key? key}) : super(key: key); @override State createState() => _CityListScreenState(); } class _CityListScreenState extends State { final _searchController = TextEditingController(); final cityRepository = Injector.appInstance.get(); List? _cities; List? _filteredCities; bool _isLoading = true; @override void initState() { super.initState(); _loadCities(); } void _loadCities() { cityRepository.getCities().then((List element) { setState(() { _cities = element; _filteredCities = _cities; _isLoading = false; }); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Ciudad'), ), body: Column( children: [ TextField( controller: _searchController, onChanged: (value) { _filterCities(value); }, decoration: const InputDecoration( hintText: 'Busca una ciudad', prefixIcon: Icon(Icons.search), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.grey), ), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.grey), ), ), ), _isLoading ? _buildShimmerEffect() : Expanded( child: _filteredCities != null && _filteredCities!.isNotEmpty ? ListView.builder( itemCount: _filteredCities!.length, itemBuilder: (BuildContext context, int index) { return Container( decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Colors.grey.withOpacity(0.2)), ), ), child: ListTile( title: Text( _filteredCities![index].cityName, style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black87, ), ), subtitle: Text( "${_filteredCities![index].stateOfCity}, ${_filteredCities![index].countryOfCity}", style: const TextStyle(color: Colors.black54), ), onTap: () { Navigator.pop(context, _filteredCities![index].cityName); }, ), ); }, ) : const Center( child: Text('No se encontraron coincidencias'), ), ), ], ), ); } void _filterCities(String query) { if (_cities != null) { setState(() { _filteredCities = _cities! .where((city) => removeDiacritics(city.cityName.toLowerCase()) .contains(removeDiacritics(query.toLowerCase()))) .toList(); }); } } Widget _buildShimmerEffect() { return Expanded( child: Shimmer.fromColors( baseColor: Colors.grey[300]!, highlightColor: Colors.grey[100]!, child: ListView.builder( itemCount: 8, itemBuilder: (_, __) => const ListTileShimmer(), ), ), ); } } class ListTileShimmer extends StatelessWidget { const ListTileShimmer({super.key}); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( border: Border( bottom: BorderSide(color: Colors.grey.withOpacity(0.4)), ), ), child: ListTile( title: Row( children: [ Container( width: MediaQuery.of(context).size.width * 0.8, height: 20.0, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), ), ], ), subtitle: Row( children: [ Container( width: MediaQuery.of(context).size.width * 0.3, height: 15.0, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), ), const SizedBox(width: 5), Container( width: MediaQuery.of(context).size.width * 0.3, height: 15.0, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), ) ], ), ), ); } }