El web també ens ofereix la possibilitat d'obtenir la llista de dones d'un àmbit concret, indicant-ne el codi. En aquest cas, el resultat és una llista amb el mateix format que quan es consulten les dones catalanes o les dones joves.
Tenim els àmbits en un diccionari que associa cada codi amb el descriptor de l'àmbit, farem un desplegable que ens permeti seleccionar un àmbit i faci la crida corresponent.
Per a la crida, podem modificar la classe CridaLlistaDones; atès que les crides tornen el mateix format de resultats i són molt semblants, només cal afegir un paràmetre a l'adreça URL. A la funció demanarLlistaDones mirarem si el paràmetre és el que correspon a les dones catalanes (tipus=cat) o a les dones joves (tipus=joves); en cas contrari, farem la crida per llegir la llista de dones de l'àmbit.
crida_llista_dones.dart
import 'dart:convert'; import 'package:dones_destacades/data/dades_rebudes_dones.dart'; import 'package:http/http.dart' as http; // No el troba automàticament, s'ha d'entrar a mà
class CridaLlistaDones{
Future<DadesRebudesDones?> demanarLlistaDones(String tip) async{
String amb = "";
if(tip.isEmpty){
// Si, pel motiu que sigui, la clau és buida, retorna les catalanes
tip = "cat";
} else {
if((tip != "cat") && (tip != "joves")){
amb = "ambit&ambit=";
}
}
final llistaDonesRebuda = await
http.get(Uri.parse("https://recursos.citcea.upc.edu/dones/service.php?tipus=$amb$tip"));
if(llistaDonesRebuda.statusCode == 200){
var jsonDecodificat = jsonDecode(llistaDonesRebuda.body);
DadesRebudesDones dadesRebudesDones = DadesRebudesDones.fromJson(jsonDecodificat);
return dadesRebudesDones;
} else {
return null;
}
}
}
A la pantalla principal hi afegirem el desplegable; a més, caldrà definir una variable.
pant_principal.dart
import 'package:dones_destacades/data/crida_llista_ambits.dart'; import 'package:dones_destacades/data/crida_llista_dones.dart'; import 'package:dones_destacades/data/dades_dona_llista.dart'; import 'package:dones_destacades/data/dades_rebudes_dones.dart'; import 'package:dones_destacades/screens/pant_detalls.dart'; import 'package:flutter/material.dart'; import 'package:html_unescape/html_unescape.dart'; // No ho posa automàticament
class PantPrincipal extends StatefulWidget {
const PantPrincipal({super.key});
@override
State<PantPrincipal> createState(){
return _PantPrincipalState();
}
}
class _PantPrincipalState extends State<PantPrincipal> {
Map<String, String> _dadesAmbits = {};
Future<DadesRebudesDones?>? _dadesDones;
CridaLlistaDones cridaLlistaDones = CridaLlistaDones();
CridaLlistaAmbits cridaLlistaAmbits = CridaLlistaAmbits();
bool _carregat = false;
String titol = "Dones destacades";
String? _opcioSeleccionada;
@override
void initState() {
super.initState();
_carregarDades();
}
Future<void> _carregarDades() async {
final dades = await cridaLlistaAmbits.demanarLlistaAmbits();
setState(() {
_dadesAmbits = dades;
_carregat = true;
});
}
@override
Widget build(BuildContext context) {
var unescape = HtmlUnescape();
return Scaffold(
appBar: AppBar(title: Text("Dones destacades"),),
body: Column(
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: () {
setState(() {
_dadesDones = cridaLlistaDones.demanarLlistaDones("cat");
titol = "Dones catalanes";
});
},
icon: Image.asset("assets/images/senyera.gif", height: 20, width: 20, fit: BoxFit.fill,),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextButton(
onPressed: () {
setState(() {
_dadesDones = cridaLlistaDones.demanarLlistaDones("joves");
titol = "Dones joves";
});
},
child: Text("s. XXI"),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: () => Navigator.push(context, MaterialPageRoute(
builder: (context) => PantDetalls(
persona: "dia",
dadesAmbits: _dadesAmbits,
carregat: _carregat
),
)),
icon: Icon(Icons.calendar_month)
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: () => Navigator.push(context, MaterialPageRoute(
builder: (context) => PantDetalls(
persona: "aleat",
dadesAmbits: _dadesAmbits,
carregat: _carregat
),
)),
icon: Icon(Icons.casino_outlined)
),
),
],
),
if(_carregat && _dadesAmbits.isNotEmpty) DropdownButton<String>(
value: _opcioSeleccionada,
hint: const Text('Escull un àmbit'),
isExpanded: true,
items: _dadesAmbits.keys.map((String clau) {
return DropdownMenuItem<String>(
value: clau,
child: Text(unescape.convert(_dadesAmbits[clau]!)),
);
}).toList(),
onChanged: (String? novaClauSeleccionada) {
setState(() {
// Si, pel motiu que sigui, la clau és un nul, retorna les catalanes
_dadesDones = cridaLlistaDones.demanarLlistaDones(novaClauSeleccionada ?? 'cat');
titol = unescape.convert(_dadesAmbits[novaClauSeleccionada]!);
});
},
),
Container(
alignment: Alignment.topLeft,
padding: const EdgeInsets.all(8),
child: Text(titol, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold))
),
mostraLlista()
],
),
);
}
FutureBuilder<DadesRebudesDones?> mostraLlista() {
return FutureBuilder(future: _dadesDones, builder: (context, snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return CircularProgressIndicator();
} else if(snapshot.hasError){
return Text("Error: ${snapshot.error}");
} else if(snapshot.hasData){
var llistaDones = snapshot.data?.llistaDadesDonaLlista;
return Expanded(
child: ListView.builder(
itemCount: llistaDones?.length ?? 0,
itemBuilder: (context, index) {
if(llistaDones != null){
return mostraElement(llistaDones[index]);
} else {
return Text("Error a la llista");
}
},
),
);
} else {
return Text("No s'han trobat resultats");
}
});
}
Padding mostraElement(DadesDonaLlista donaDeLaLlista) {
var unescape = HtmlUnescape();
String ambitAct = "";
if(_carregat){
ambitAct = _dadesAmbits[donaDeLaLlista.ambit].toString();
}
return Padding(
padding: const EdgeInsets.all(5.0),
child: GestureDetector(
onTap: () => Navigator.push(context, MaterialPageRoute(
builder: (context) => PantDetalls(
persona: donaDeLaLlista.id,
dadesAmbits: _dadesAmbits,
carregat: _carregat
),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(unescape.convert(donaDeLaLlista.nom),
style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold)),
Text(unescape.convert(donaDeLaLlista.professio),
style: TextStyle(fontSize: 13)),
if(_carregat && ambitAct.isNotEmpty)
Text("Àmbit: ${unescape.convert(ambitAct)}", style: TextStyle(fontSize: 13)),
]
)
)
);
}
}

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.