RankingsTab.dart (5209B)
1 import 'package:flutter/cupertino.dart'; 2 import 'package:flutter/material.dart'; 3 import 'package:flutter_svg/flutter_svg.dart'; 4 import 'package:rs_flutter_app/components/SearchBar.dart'; 5 6 import '../../repos/repositories.dart'; 7 8 class RankingsTab extends StatefulWidget { 9 final RailwayStationsRepository railwayStationsRepository; 10 11 RankingsTab({@required this.railwayStationsRepository}) 12 : assert(railwayStationsRepository != null); 13 14 @override 15 RankingsTabState createState() => RankingsTabState(); 16 } 17 18 class RankingsTabState extends State<RankingsTab> 19 with AutomaticKeepAliveClientMixin<RankingsTab> { 20 final filterTextController = TextEditingController(); 21 List<List<String>> scores; 22 String filterText; 23 24 List<List<String>> filter() { 25 var scoresL = scores; 26 if (filterText != null && filterText != "") { 27 scoresL = scores 28 .where( 29 (score) => (filterText != null && 30 filterText != "" && 31 score[1].toLowerCase().contains(filterText.toLowerCase())), 32 ) 33 .toList(growable: false); 34 } 35 return scoresL; 36 } 37 38 Future<List<List<String>>> getScores() async { 39 if (scores == null) { 40 List<List<String>> scoresL = 41 await widget.railwayStationsRepository.getScores(); 42 43 scoresL.removeAt(0); 44 scoresL.sort( 45 (a, b) => (int.parse(b.first)).compareTo(int.parse(a.first)), 46 ); 47 scores = scoresL; 48 } 49 return scores; 50 } 51 52 void handleFilter() { 53 setState(() { 54 filterText = filterTextController.text; 55 }); 56 } 57 58 @override 59 initState() { 60 super.initState(); 61 filterTextController.addListener(handleFilter); 62 } 63 64 @override 65 void dispose() { 66 filterTextController.removeListener(handleFilter); 67 super.dispose(); 68 } 69 70 @override 71 Widget build(BuildContext context) { 72 super.build(context); 73 74 return Scaffold( 75 appBar: AppBar( 76 title: Text("Rangliste"), 77 bottom: PreferredSize( 78 preferredSize: Size.fromHeight(56), 79 child: Padding( 80 padding: EdgeInsets.all(8), 81 child: SearchBar( 82 filterTextController: filterTextController, 83 ), 84 ), 85 ), 86 ), 87 body: FutureBuilder( 88 future: getScores(), 89 builder: 90 (BuildContext context, AsyncSnapshot<List<List<String>>> snapshot) { 91 if (snapshot.hasError) { 92 // TODO handle error 93 debugPrint(snapshot.error.toString()); 94 } 95 96 if (!snapshot.hasData) { 97 return Center( 98 child: CircularProgressIndicator(), 99 ); 100 } 101 102 var filtered = filter(); 103 104 if (filtered == null || filtered.isEmpty) { 105 return Container(); 106 } 107 108 if (scores.isEmpty) { 109 return Container(); 110 } 111 112 return ListView.separated( 113 itemCount: filtered.length, 114 separatorBuilder: (BuildContext context, int index) { 115 return Divider(); 116 }, 117 itemBuilder: (BuildContext context, int index) { 118 if (scores 119 .indexWhere((score) => score[1] == filtered[index][1]) == 120 0) { 121 return ListTile( 122 leading: SvgPicture.asset( 123 "assets/crown_gold.svg", 124 semanticsLabel: 'Golden Crown', 125 width: 50, 126 height: 50, 127 ), 128 title: Text(filtered[index][1]), 129 ); 130 } else if (scores 131 .indexWhere((score) => score[1] == filtered[index][1]) == 132 1) { 133 return ListTile( 134 leading: SvgPicture.asset( 135 "assets/crown_silver.svg", 136 semanticsLabel: 'Silver Crown', 137 width: 50, 138 height: 50, 139 ), 140 title: Text(filtered[index][1]), 141 ); 142 } else if (scores 143 .indexWhere((score) => score[1] == filtered[index][1]) == 144 2) { 145 return ListTile( 146 leading: SvgPicture.asset( 147 "assets/crown_bronze.svg", 148 semanticsLabel: 'Bronze Crown', 149 width: 50, 150 height: 50, 151 ), 152 title: Text(filtered[index][1]), 153 ); 154 } else { 155 return ListTile( 156 leading: SizedBox( 157 width: 50, 158 height: 50, 159 child: Center( 160 child: Text( 161 "${(scores.indexWhere((score) => score[1] == filtered[index][1]) + 1)}.", 162 style: TextStyle( 163 fontWeight: FontWeight.bold, 164 ), 165 ), 166 ), 167 ), 168 title: Text(filtered[index][1]), 169 ); 170 } 171 }, 172 ); 173 }, 174 ), 175 ); 176 } 177 178 @override 179 bool get wantKeepAlive => true; 180 }