Commit 83a0633f by yenisleydi

Tarea 6

parent 66a26e6a
import 'dart:convert'; // Importa el paquete para trabajar con JSON.
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:primer_practica/src/http_api/category_service.dart';
import 'package:primer_practica/src/models/categoryModel.dart';
class CategoryController {
final Connectivity _connectivity = Connectivity(); // Crea una instancia de Connectivity para verificar el estado de la red.
Future<Map<String, dynamic>> getCategories() async {
// Inicializa la respuesta por defecto.
Map<String, dynamic> mapResp = {
'ok': false,
'message': 'No hay categorias',
'data': null
};
// Verifica la conectividad.
ConnectivityResult connectivityResult = (await _connectivity.checkConnectivity()) as ConnectivityResult;
// Si hay conexión a internet.
if (connectivityResult != ConnectivityResult.none) {
if (connectivityResult == ConnectivityResult.wifi || connectivityResult == ConnectivityResult.mobile) {
CategoryService categoryApi = CategoryService(); // Crea una instancia de CategoryApi.
Map<String, dynamic> respGet = await categoryApi.getCategories(); // Obtiene las categorías desde la API.
// Si la respuesta de la API es exitosa.
if (respGet['statusCode'] == 200) {
try {
var decodeResp = json.decode(respGet['body']); // Decodifica la respuesta JSON.
List<CategoryModel> listCategories = CategoryModel.fromJsonArray(decodeResp['data']); // Convierte los datos en una lista de categorías.
mapResp['ok'] = true; // Marca la operación como exitosa.
mapResp['message'] = "${listCategories.length} categorias encontradas"; // Actualiza el mensaje con el número de categorías encontradas.
mapResp['data'] = listCategories; // Asigna los datos de las categorías a la respuesta.
} catch (e) {
mapResp['message'] = "Error en operador $e"; // Captura y asigna cualquier error durante la decodificación.
}
} else {
mapResp['message'] = "${respGet['body']}"; // Asigna el mensaje de error de la API a la respuesta.
}
}
}
return mapResp; // Retorna la respuesta
}
}
import 'package:flutter/foundation.dart'; // Para usar kDebugMode import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:primer_practica/environments/urls.dart' as api; import 'package:primer_practica/environments/urls.dart' as api;
class CategoryService { class CategoryService {
static const String apiBaseUrl = 'categoria'; // Cambia esto a la URL base de tu API static const String apiBaseUrl = 'categoria';
// Método para obtener las categorías // Método para obtener las categorías
Future<Map<String, dynamic>> getCategories({int offset = 0, int max = 100}) async { Future<Map<String, dynamic>> getCategories({int offset = 0, int max = 100}) async {
String url = '${{api.apiApp}}/$apiBaseUrl?offset=$offset&max=$max'; String url = '${api.apiApp}/$apiBaseUrl?offset=$offset&max=$max';
if (kDebugMode) { if (kDebugMode) {
print('Url -> $url'); print('Url -> $url');
......
import 'package:connectivity_plus/connectivity_plus.dart';
Future<void> checkConnecticity() async {
final ConnectivityResult connectivityResult = await (Connectivity().checkConnectivity());
// This condition is for demo purposes only to explain every connection type.
// Use conditions which work for your requirements.
if (connectivityResult==ConnectivityResult.mobile) {
// Mobile network available.
} else if (connectivityResult==ConnectivityResult.wifi) {
// Wi-fi is available.
// Note for Android:
// When both mobile and Wi-Fi are turned on system will return Wi-Fi only as active network type
} else if (connectivityResult==ConnectivityResult.ethernet) {
// Ethernet connection available.
} else if (connectivityResult==ConnectivityResult.vpn) {
// Vpn connection active.
// Note for iOS and macOS:
// There is no separate network interface type for [vpn].
// It returns [other] on any device (also simulator)
} else if (connectivityResult==ConnectivityResult.bluetooth) {
// Bluetooth connection available.
} else if (connectivityResult==ConnectivityResult.other) {
// Connected to a network which is not in the above mentioned networks.
} else if (connectivityResult==ConnectivityResult.none) {
// No available network types
}
}
...@@ -3,51 +3,72 @@ ...@@ -3,51 +3,72 @@
class CategoryModel { class CategoryModel {
int id; int id;
int? version; int? version;
String clave; String? key;
String nombre; String? name;
int? fechaCreado; int? createdDate;
String categoria; CategoryModel? parentCategory;
bool? activo; List<CategoryModel>? subCategories;
bool? active;
CategoryModel({ CategoryModel({
required this.id, required this.id,
this.version, this.version,
required this.clave, this.key,
required this.nombre, this.name,
this.fechaCreado, this.createdDate,
required this.categoria, this.parentCategory,
this.activo, this.subCategories,
this.active,
}); });
// Método para crear una instancia de CategoryModel desde un JSON // Método para crear una instancia de CategoryModel desde un JSON
factory CategoryModel.fromJson(Map<String, dynamic> json) => CategoryModel( factory CategoryModel.fromJson(Map<String, dynamic> json) {
id: json['id'], return CategoryModel(
version: json['version'] ?? 0, id: json['id'],
clave: json['clave'] ?? '', version: json['version'],
nombre: json['nombre'] ?? '', key: json['clave'],
fechaCreado: json['fechaCreado'], name: json['nombre'],
categoria: json['categoria'] ?? '', createdDate: json['fechaCreado'],
activo: json['activo'], parentCategory: json['categoria'] != null
); ? CategoryModel.fromJson(json['categoria'])
: null,
subCategories: json['categorias'] != null
? CategoryModel.fromJsonArray(json['categorias'])
: [],
active: json['activo'],
);
}
// Método para convertir una instancia de CategoryModel a JSON // Este metodo sirve para para convertir una instancia de CategoryModel a JSON
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() {
'id': id, return {
'version': version, "id": id,
'clave': clave, "version": version,
'nombre': nombre, "clave": key,
'fechaCreado': fechaCreado, "nombre": name,
'categoria': categoria, "fechaCreado": createdDate,
'activo': activo, "categoria": parentCategory?.toJson(),
}; "categorias": subCategories != null
? CategoryModel.toJsonArray(subCategories!)
: [],
"activo": active,
};
}
// Método para crear una lista de CategoryModel desde una lista de JSONs // Método para crear una lista de CategoryModel desde un JSON
static List<CategoryModel> fromJsonArray(List<dynamic> json) { static List<CategoryModel> fromJsonArray(json) {
return json.map((data) => CategoryModel.fromJson(data)).toList(); if (json == null) return [];
var list = json as List;
List<CategoryModel> listResult =
list.map((data) => CategoryModel.fromJson(data)).toList();
return listResult;
} }
// Método para convertir una lista de CategoryModel a una lista de JSONs static toJsonArray(List<CategoryModel> list) {
static List<Map<String, dynamic>> toJsonArray(List<CategoryModel> list) { List<Map<String, dynamic>> listMap = [];
return list.map((item) => item.toJson()).toList(); for (CategoryModel item in list) {
listMap.add(item.toJson());
}
return listMap;
} }
} }
import 'package:flutter/material.dart';
import 'package:primer_practica/src/controllers/categoty_controller.dart';
import 'package:primer_practica/src/shared_widgets/widget_mensajes.dart' as msg_shared;
import 'package:primer_practica/src/models/categoryModel.dart';
class ListaCategorias extends StatelessWidget {
final CategoryController categoryCtrl = CategoryController(); // Crea una instancia del controlador de categorías
@override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: FutureBuilder(
future: categoryCtrl.getCategories(), // Llama al método getCategories del controlador
builder: (context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
if (snapshot.hasData) {
if (snapshot.data!['ok']) {
if (snapshot.data!['data'].length > 0) {
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
CategoryModel category = snapshot.data!['data'][index];
return Card(
child: ListTile(
title: Text(category.name?? 'No Name'), // Muestra el nombre de la categoría
leading: const Icon(Icons.touch_app),
onTap: () {
// Navegar al listado de servicios
},
),
);
},
itemCount: snapshot.data!['data'].length,
);
} else {
return msg_shared.alertWait("No se encontraron categorías");
}
} else {
return msg_shared.alertDanger("Error: ${snapshot.data!['message']}");
}
} else if (snapshot.hasError) {
return msg_shared.alertDanger("Error: ${snapshot.error.toString()}");
} else {
return const Center(
child: CircularProgressIndicator(), // Muestra un indicador de progreso mientras se cargan los datos
);
}
},
),
),
);
}
}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:primer_practica/src/pages/category/lista_categorias.dart'; // Importa el widget de la lista de categorías
class HomePage extends StatelessWidget { class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key); const HomePage({Key? key}) : super(key: key);
...@@ -12,8 +13,8 @@ class HomePage extends StatelessWidget { ...@@ -12,8 +13,8 @@ class HomePage extends StatelessWidget {
actions: [ actions: [
IconButton( IconButton(
icon: const Icon(Icons.search), icon: const Icon(Icons.search),
onPressed: (){ onPressed: () {
// Acción de búsqueda
}, },
) )
], ],
...@@ -40,21 +41,7 @@ class HomePage extends StatelessWidget { ...@@ -40,21 +41,7 @@ class HomePage extends StatelessWidget {
], ],
), ),
), ),
body: Center( body: ListaCategorias(), // Usa el widget de la lista de categorías en el body
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Hola home page'),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, 'articles');
},
child: const Text('Ir a Articles Page'),
),
],
),
),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: () { onPressed: () {
Navigator.pushNamed(context, 'login'); Navigator.pushNamed(context, 'login');
......
...@@ -10,13 +10,13 @@ class LoginPage extends StatelessWidget { ...@@ -10,13 +10,13 @@ class LoginPage extends StatelessWidget {
title: const Text('Login Page'), // Título de la barra title: const Text('Login Page'), // Título de la barra
), ),
body: Padding( // Espacia el contenido del cuerpo body: Padding( // Espacia el contenido del cuerpo
padding: const EdgeInsets.all(180.0), // Padding alrededor del contenido padding: const EdgeInsets.all(160.90), // Padding alrededor del contenido
child: Center( // Centra el contenido en la pantalla child: Center( // Centra el contenido en la pantalla
child: Column( // Organiza los widgets en una columna vertical child: Column( // Organiza los widgets en una columna vertical
mainAxisAlignment: MainAxisAlignment.center, // Centra verticalmente mainAxisAlignment: MainAxisAlignment.center, // Centra verticalmente
children: [ // Lista de widgets en la columna children: [ // Lista de widgets en la columna
Image.asset('assets/img/logo_visorus.jpg', height: 100), // Muestra el logo con altura de 100 Image.asset('assets/img/logo_visorus.jpg', height: 90), // Muestra el logo con altura de 100
const SizedBox(height: 80), // Espacio de 80 píxeles entre el logo y el primer campo de texto const SizedBox(height: 40), // Espacio de 80 píxeles entre el logo y el primer campo de texto
TextField( // Campo de texto para el usuario TextField( // Campo de texto para el usuario
decoration: const InputDecoration( decoration: const InputDecoration(
labelText: 'Usuario', // Etiqueta del campo de texto labelText: 'Usuario', // Etiqueta del campo de texto
...@@ -31,7 +31,7 @@ class LoginPage extends StatelessWidget { ...@@ -31,7 +31,7 @@ class LoginPage extends StatelessWidget {
border: OutlineInputBorder(), // Borde del campo de texto border: OutlineInputBorder(), // Borde del campo de texto
), ),
), ),
const SizedBox(height: 20), // Espacio de 20 píxeles antes del botón const SizedBox(height: 30), // Espacio de 20 píxeles antes del botón
ElevatedButton( ElevatedButton(
onPressed: () { // Acción al presionar el botón onPressed: () { // Acción al presionar el botón
Navigator.pushNamed(context, 'home'); // Navega a la página 'home' Navigator.pushNamed(context, 'home'); // Navega a la página 'home'
......
import 'package:flutter/material.dart';
// Widget para mostrar alertas de error
Widget alertDanger(String message) {
return Container(
// El contenedor se expande a todo el ancho disponible
width: double.infinity,
// padding alrededor del contenido
padding: const EdgeInsets.all(8.0),
//color de fondo del contenedor
color: const Color.fromRGBO(192, 57, 43, 0.5),
child: Row(
// fila para los íconos y el texto
children: <Widget>[
const Icon(
Icons.error, // Icono de error
color: Colors.white, // Color del icono
),
const SizedBox(
width: 10.0, // Espacio horizontal entre el icono y el texto
),
Expanded(
// Expande el widget de texto para llenar el espacio restante
child: Text(
message, // Mensaje de error
style: const TextStyle(color: Colors.white),
),
)
],
));
}
// Widget para mostrar alertas de éxito
Widget alertSuccess(String message) {
return Container(
// El contenedor se expande a todo el ancho disponible
width: double.infinity,
padding: const EdgeInsets.all(8.0),
color: Colors.lightGreen,
child: Row(
children: <Widget>[
const Icon(
Icons.check_circle_outline,
color: Colors.white,
),
const SizedBox(
width: 10.0,
),
Expanded(
child: Text(
message,
style: const TextStyle(color: Colors.white),
),
)
],
));
}
// Widget para mostrar alertas de información
Widget alertWait(String message) {
return Container(
// El contenedor se expande a todo el ancho disponible
width: double.infinity,
padding: const EdgeInsets.all(8.0),
color: Colors.lightBlueAccent,
child: Row(
children: <Widget>[
const Icon(
Icons.info,
color: Colors.white,
),
const SizedBox(
width: 10.0,
),
Expanded(
child: Text(
message,
style: const TextStyle(color: Colors.white),
),
)
],
));
}
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import connectivity_plus import connectivity_plus_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
} }
...@@ -53,18 +53,50 @@ packages: ...@@ -53,18 +53,50 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: connectivity_plus name: connectivity_plus
sha256: "3e7d1d9dbae40ae82cbe6c23c518f0c4ffe32764ee9749b9a99d32cbac8734f6" sha256: "3f8fe4e504c2d33696dac671a54909743bc6a902a9bb0902306f7a2aed7e528e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.4" version: "2.3.9"
connectivity_plus_linux:
dependency: transitive
description:
name: connectivity_plus_linux
sha256: "3caf859d001f10407b8e48134c761483e4495ae38094ffcca97193f6c271f5e2"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
connectivity_plus_macos:
dependency: transitive
description:
name: connectivity_plus_macos
sha256: "488d2de1e47e1224ad486e501b20b088686ba1f4ee9c4420ecbc3b9824f0b920"
url: "https://pub.dev"
source: hosted
version: "1.2.6"
connectivity_plus_platform_interface: connectivity_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: connectivity_plus_platform_interface name: connectivity_plus_platform_interface
sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
url: "https://pub.dev"
source: hosted
version: "1.2.4"
connectivity_plus_web:
dependency: transitive
description:
name: connectivity_plus_web
sha256: "81332be1b4baf8898fed17bb4fdef27abb7c6fd990bf98c54fd978478adf2f1a"
url: "https://pub.dev"
source: hosted
version: "1.2.5"
connectivity_plus_windows:
dependency: transitive
description:
name: connectivity_plus_windows
sha256: "535b0404b4d5605c4dd8453d67e5d6d2ea0dd36e3b477f50f31af51b0aeab9dd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "1.2.2"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -136,6 +168,14 @@ packages: ...@@ -136,6 +168,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.2" version: "4.0.2"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
......
...@@ -31,7 +31,7 @@ dependencies: ...@@ -31,7 +31,7 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
http: ^1.2.2 http: ^1.2.2
connectivity_plus: ^6.0.4 connectivity_plus: ^2.3.6
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <connectivity_plus/connectivity_plus_windows_plugin.h> #include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
ConnectivityPlusWindowsPluginRegisterWithRegistrar( ConnectivityPlusWindowsPluginRegisterWithRegistrar(
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus connectivity_plus_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment