Last active
August 31, 2020 00:39
-
-
Save roipeker/bb329c8dd839facc99db7136777cd1e5 to your computer and use it in GitHub Desktop.
Demo Jornada de partidos con GetX ( roi-getx-partidos.surge.sh )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// roipeker 2020 | |
/// | |
/// LIVE DEMO: https://roi-getx-partidos.surge.sh/ | |
import 'package:dio/dio.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:get/get.dart'; | |
class AppSamplePartidos extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return GetMaterialApp( | |
debugShowCheckedModeBanner: false, | |
home: _HomePartidos(), | |
initialBinding: BindingsBuilder(() { | |
final api = Get.put(Api(), permanent: true); | |
Get.put(HomePartidosController(api)); | |
}), | |
); | |
} | |
} | |
/// model | |
class Temporada { | |
List<PartidoModel> jornada; | |
@override | |
String toString() => 'Temporada{jornada: $jornada}'; | |
Temporada({this.jornada}); | |
factory Temporada.fromJson(Map<String, dynamic> json) => Temporada( | |
// cambia esto para que lea los Keys si queres matenerlo asi. | |
jornada: List<PartidoModel>.from(json["Jornada 38"].map( | |
(x) => PartidoModel.fromJson(x), | |
)), | |
); | |
} | |
class PartidoModel { | |
PartidoModel({ | |
this.awayGoals, | |
this.escudoAway, | |
this.escudoHome, | |
this.homeGoals, | |
this.id, | |
this.name, | |
this.scoreAway, | |
this.scoreHome, | |
this.teamAway, | |
this.teamHome, | |
}); | |
List<String> awayGoals; | |
String escudoAway; | |
String escudoHome; | |
List<String> homeGoals; | |
String id; | |
String name; | |
String scoreAway; | |
String scoreHome; | |
String teamAway; | |
String teamHome; | |
factory PartidoModel.fromJson(Map<String, dynamic> json) => PartidoModel( | |
awayGoals: List<String>.from(json["away_goals"].map((x) => x)), | |
escudoAway: json["escudo_away"], | |
escudoHome: json["escudo_home"], | |
homeGoals: List<String>.from(json["home_goals"].map((x) => x)), | |
id: json["id"], | |
name: json["name"], | |
scoreAway: json["score_away"], | |
scoreHome: json["score_home"], | |
teamAway: json["team_away"], | |
teamHome: json["team_home"], | |
); | |
@override | |
String toString() { | |
return 'PartidoModel {awayGoals: $awayGoals, escudoAway: $escudoAway, escudoHome: $escudoHome, id: $id, name: $name, scoreAway: $scoreAway, scoreHome: $scoreHome, teamAway: $teamAway, teamHome: $teamHome}'; | |
} | |
} | |
/// api | |
class Api { | |
final _dio = Dio( | |
BaseOptions( | |
baseUrl: 'https://scracdcs.herokuapp.com/', | |
), | |
); | |
Future<Temporada> getData() async { | |
final request = await _dio.get('json'); | |
return Temporada.fromJson(request.data['Temporada'][0]); | |
} | |
} | |
class HomePartidosController extends GetxController { | |
final _isLoading = false.obs; | |
get isLoading => _isLoading.value; | |
// arranca null | |
final partidoSelected = Rx<PartidoModel>(); | |
Temporada model; | |
final Api api; | |
HomePartidosController(this.api); | |
@override | |
void onReady() { | |
_getData(); | |
} | |
void _getData() async { | |
_isLoading.value = true; | |
model = await api.getData(); | |
_isLoading.value = false; | |
} | |
List<PartidoModel> get partidos => model?.jornada; | |
} | |
class _HomePartidos extends GetView<HomePartidosController> { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text('Partidos'), | |
), | |
body: Obx( | |
() { | |
if (controller.isLoading) { | |
return Center( | |
child: Text( | |
'cargando ...', | |
style: Get.textTheme.headline2, | |
), | |
); | |
} | |
if (controller.partidos == null) { | |
return Text('esperando API request.'); | |
} | |
return Row( | |
children: [ | |
/// crea menu para seleccionar partido | |
Flexible( | |
flex: 2, | |
child: _PartidoMenu(partidos: controller.partidos), | |
), | |
VerticalDivider(width: 1, thickness: 1), | |
Flexible( | |
flex: 4, | |
// child: _PartidoMenu(partidos: controller.partidos), | |
child: _PartidoView(), | |
), | |
], | |
); | |
}, | |
), | |
); | |
} | |
} | |
class _PartidoMenu extends StatelessWidget { | |
final List<PartidoModel> partidos; | |
const _PartidoMenu({Key key, this.partidos}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
child: Scrollbar( | |
child: ListView.separated( | |
separatorBuilder: (context, index) => | |
Divider(height: 1, thickness: 1), | |
itemBuilder: (context, index) => | |
_PartidoMenuItem(data: partidos[index]), | |
itemCount: partidos.length, | |
), | |
), | |
); | |
} | |
} | |
class _PartidoMenuItem extends GetView<HomePartidosController> { | |
final PartidoModel data; | |
const _PartidoMenuItem({Key key, this.data}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return ListTile( | |
onTap: () => controller.partidoSelected(data), | |
title: Text(data.name, overflow: TextOverflow.ellipsis), | |
subtitle: Text( | |
'${data.teamHome} vs ${data.teamAway}', | |
overflow: TextOverflow.ellipsis, | |
), | |
leading: SizedBox( | |
width: 32, | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |
children: [ | |
Image.network( | |
data.escudoHome, | |
width: 24, | |
fit: BoxFit.contain, | |
), | |
Image.network( | |
data.escudoAway, | |
width: 24, | |
fit: BoxFit.contain, | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class _PartidoView extends GetView<HomePartidosController> { | |
@override | |
Widget build(BuildContext context) { | |
// usamos reactive. | |
return Scrollbar( | |
child: SingleChildScrollView( | |
child: Container( | |
// color: Colors.white, | |
padding: EdgeInsets.all(8), | |
child: Obx( | |
() { | |
final partido = controller.partidoSelected.value; | |
if (partido == null) { | |
return Center( | |
child: Text( | |
'Selecciona un partido en el menu', | |
style: | |
Get.textTheme.headline6.copyWith(color: Colors.black38), | |
), | |
); | |
} | |
return Row( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Expanded( | |
child: _EquipoView( | |
escudo: partido.escudoHome, | |
name: partido.teamHome, | |
score: partido.scoreHome, | |
goals: partido.homeGoals, | |
), | |
), | |
Container( | |
height: 120, | |
width: 1, | |
color: Get.theme.dividerColor.withOpacity(.1), | |
), | |
Expanded( | |
child: _EquipoView( | |
escudo: partido.escudoAway, | |
name: partido.teamAway, | |
score: partido.scoreAway, | |
goals: partido.awayGoals, | |
), | |
), | |
], | |
); | |
}, | |
), | |
), | |
), | |
); | |
} | |
} | |
class _EquipoView extends StatelessWidget { | |
final String name; | |
final String score; | |
final String escudo; | |
final List<String> goals; | |
const _EquipoView({Key key, this.name, this.score, this.escudo, this.goals}) | |
: super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
List golesChilds = <Widget>[]; | |
if (goals.isNotEmpty) { | |
golesChilds = [ | |
SizedBox(height: 12), | |
Text( | |
'GOLES', | |
textAlign: TextAlign.left, | |
style: Get.textTheme.bodyText1.copyWith(fontSize: 12), | |
), | |
SizedBox(height: 12), | |
Wrap( | |
spacing: 6, | |
runSpacing: 6, | |
children: [ | |
...goals.map((e) => Chip( | |
padding: EdgeInsets.zero, | |
backgroundColor: Colors.blue.shade700, | |
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, | |
label: Text( | |
e, | |
style: Get.textTheme.caption.copyWith(color: Colors.white), | |
), | |
)), | |
], | |
), | |
]; | |
} else { | |
golesChilds = [ | |
SizedBox(height: 20), | |
Text( | |
'Sin goles', | |
textAlign: TextAlign.center, | |
style: Get.textTheme.headline6.copyWith(color: Colors.black26), | |
), | |
]; | |
} | |
return Container( | |
padding: EdgeInsets.all(8), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.start, | |
crossAxisAlignment: CrossAxisAlignment.stretch, | |
children: [ | |
Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: [ | |
Image.network( | |
escudo, | |
width: 32, | |
fit: BoxFit.contain, | |
), | |
SizedBox(width: 10), | |
Flexible( | |
child: Text( | |
name, | |
overflow: TextOverflow.fade, | |
textAlign: TextAlign.center, | |
maxLines: 2, | |
style: Get.textTheme.headline5, | |
), | |
), | |
], | |
), | |
SizedBox(height: 24), | |
Text( | |
score, | |
textAlign: TextAlign.center, | |
style: Get.textTheme.headline1, | |
), | |
...golesChilds, | |
], | |
), | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Temporada": [ | |
{ | |
"Jornada 38": [ | |
{ | |
"away_goals": [ | |
"AnsuFati 24'", | |
"L.Messi 34'75'", | |
"L.Suárez 44'", | |
"NélsonSemedo 57'" | |
], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/fc-barcelona-1.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/deportivo-alaves.png", | |
"home_goals": [], | |
"id": "550235", | |
"name": "Alavés en Barcelona", | |
"score_away": "5", | |
"score_home": "0", | |
"team_away": "Barcelona", | |
"team_home": "Alavés" | |
}, | |
{ | |
"away_goals": [], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/real-betis.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/real-valladolid.png", | |
"home_goals": [ | |
"SergiGuardiola 45+1'", | |
"ÓscarPlano 63'" | |
], | |
"id": "550240", | |
"name": "Real Valladolid en Real Betis", | |
"score_away": "0", | |
"score_home": "2", | |
"team_away": "Real Betis", | |
"team_home": "Real Valladolid" | |
}, | |
{ | |
"away_goals": [], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/eibar.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/villarreal-2015834514682758915.png", | |
"home_goals": [ | |
"A.ZamboAnguissa 71'", | |
"GerardMoreno 86'89'", | |
"MoiGómez 90+4'" | |
], | |
"id": "550237", | |
"name": "Villarreal en Eibar", | |
"score_away": "0", | |
"score_home": "4", | |
"team_away": "Eibar", | |
"team_home": "Villarreal" | |
}, | |
{ | |
"away_goals": [], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/celta-de-vigo-6513619208928969762.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/espanyol.png", | |
"home_goals": [], | |
"id": "550236", | |
"name": "Espanyol en Celta Vigo", | |
"score_away": "0", | |
"score_home": "0", | |
"team_away": "Celta Vigo", | |
"team_home": "Espanyol" | |
}, | |
{ | |
"away_goals": [ | |
"SergioRamos 9'", | |
"Asensio 52'" | |
], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/real-madrid-cf.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/leganes.png", | |
"home_goals": [ | |
"BryanGil 45+1'", | |
"R.Assalé78'" | |
], | |
"id": "550241", | |
"name": "Leganes en Real Madrid", | |
"score_away": "2", | |
"score_home": "2", | |
"team_away": "Real Madrid", | |
"team_home": "Leganes" | |
}, | |
{ | |
"away_goals": [ | |
"L.Agbenyenu 45+1'", | |
"A.Budimir 65'" | |
], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/majorque.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/osasuna.png", | |
"home_goals": [ | |
"Adrián 21'", | |
"IñigoPérez 68'" | |
], | |
"id": "550239", | |
"name": "Osasuna en Mallorca", | |
"score_away": "2", | |
"score_home": "2", | |
"team_away": "Mallorca", | |
"team_home": "Osasuna" | |
}, | |
{ | |
"away_goals": [], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/athletic-bilbao.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/grenade.png", | |
"home_goals": [ | |
"Soldado 29'", | |
"AntonioPuertas 55'", | |
"CarlosFernández 67'", | |
"Montoro 90+3'" | |
], | |
"id": "550234", | |
"name": "Granada en Athletic Bilbao", | |
"score_away": "0", | |
"score_home": "4", | |
"team_away": "Athletic Bilbao", | |
"team_home": "Granada" | |
}, | |
{ | |
"away_goals": [ | |
"A.Januzaj 87'" | |
], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/real-sociedad.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/atletico-madrid.png", | |
"home_goals": [ | |
"Koke 30'" | |
], | |
"id": "550242", | |
"name": "Atletico Madrid en Real Sociedad", | |
"score_away": "1", | |
"score_home": "1", | |
"team_away": "Real Sociedad", | |
"team_home": "Atletico Madrid" | |
}, | |
{ | |
"away_goals": [], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/valence.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/sevilla.png", | |
"home_goals": [ | |
"Reguilón 55'" | |
], | |
"id": "550243", | |
"name": "Sevilla FC en Valencia", | |
"score_away": "0", | |
"score_home": "1", | |
"team_away": "Valencia", | |
"team_home": "Sevilla FC" | |
}, | |
{ | |
"away_goals": [], | |
"escudo_away": "https://assets-es.imgfoot.com/media/cache/60x60/club/getafe.png", | |
"escudo_home": "https://assets-es.imgfoot.com/media/cache/60x60/club/levante-2263322039917214311.png", | |
"home_goals": [ | |
"Coke 90+9'" | |
], | |
"id": "550238", | |
"name": "Levante en Getafe", | |
"score_away": "0", | |
"score_home": "1", | |
"team_away": "Getafe", | |
"team_home": "Levante" | |
} | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment