diff --git a/lib/src/delegates/article_search_delegate.dart b/lib/src/delegates/article_search_delegate.dart index b672b0e..c02b3dd 100644 --- a/lib/src/delegates/article_search_delegate.dart +++ b/lib/src/delegates/article_search_delegate.dart @@ -70,8 +70,8 @@ class ArticleSearchDelegate extends SearchDelegate { icon: Icon(Icons.shopping_cart), onPressed: () { final carritoProvider = Provider.of(context, listen: false); - carritoProvider.agregarCarrito(article); // Llama al método correcto - close(context, null); // Cierra el SearchDelegate + carritoProvider.agregarCarrito(article); + close(context, null); }, ), ); diff --git a/lib/src/http_api/articles_api.dart b/lib/src/http_api/articles_api.dart index 36fdca5..c27898a 100644 --- a/lib/src/http_api/articles_api.dart +++ b/lib/src/http_api/articles_api.dart @@ -1,6 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:primer_practica/environments/urls.dart' as api; +import 'dart:convert'; class ArticlesApi { Future> getArticles() async { @@ -19,7 +20,7 @@ class ArticlesApi { } Future> searchArticles(String query) async { - String url = '${api.apiApp}/articulo?nombre="$query"'; + String url = '${api.apiApp}/articulo?nombre="$query"'; if (kDebugMode) { print('Url -> $url'); @@ -32,4 +33,37 @@ class ArticlesApi { return {"statusCode": 501, "body": '$e'}; } } + + Future> addArticle({ + required String clave, + required int categoria, + required String nombre, + required List precios, + required bool activo, + }) async { + String url = '${api.apiApp}/articulo'; + final payload = { + 'clave': clave, + 'categoria': categoria, + 'nombre': nombre, + 'precios': precios.map((precio) => {'precio': precio}).toList(), + 'activo': activo, + }; + + if (kDebugMode) { + print('Url -> $url'); + print('Payload -> $payload'); + } + + try { + final resp = await http.post( + Uri.parse(url), + headers: {'Content-Type': 'application/json'}, + body: json.encode(payload), + ); + return {"statusCode": resp.statusCode, "body": resp.body}; + } catch (e) { + return {"statusCode": 501, "body": '$e'}; + } + } } diff --git a/lib/src/http_api/category_service.dart b/lib/src/http_api/category_service.dart index 678c9e7..e13e676 100644 --- a/lib/src/http_api/category_service.dart +++ b/lib/src/http_api/category_service.dart @@ -36,7 +36,7 @@ class CategoryService { //conversión del objeto a Json final categoryJson = category.toJson(); - // Imprime la URL y el cuerpo de la solicitud + if (kDebugMode) { print('Url -> $url'); print('Body -> $categoryJson'); @@ -45,8 +45,8 @@ class CategoryService { try { // Realiza la solicitud POST al servidor final response = await http.post( - Uri.parse(url), // Convierte la URL a un objeto Uri - headers: {'Content-Type': 'application/json'}, // Establece el tipo de contenido como JSON + Uri.parse(url), + headers: {'Content-Type': 'application/json'}, body: json.encode(categoryJson), ); diff --git a/lib/src/models/carrito_model.dart b/lib/src/models/carrito_model.dart index ee9f71d..9e28ab2 100644 --- a/lib/src/models/carrito_model.dart +++ b/lib/src/models/carrito_model.dart @@ -23,7 +23,7 @@ class CarritoModel { return CarritoModel( articulo: ArticlesModel.fromJson(json['articulo']), cantidad: json['cantidad'], - precio: json['precio'], // Asegúrate de que se maneje correctamente el precio + precio: json['precio'], ); } } diff --git a/lib/src/pages/articles_page.dart b/lib/src/pages/articles_page.dart index 86c2cfd..d479e05 100644 --- a/lib/src/pages/articles_page.dart +++ b/lib/src/pages/articles_page.dart @@ -1,19 +1,19 @@ import 'package:flutter/material.dart'; import 'package:primer_practica/src/controllers/articles_controller.dart'; import 'package:primer_practica/src/models/articles_model.dart'; +import 'package:primer_practica/src/pages/formulario_articulos.dart'; class ArticlePage extends StatefulWidget { - final int categoryId; const ArticlePage({Key? key, required this.categoryId}) : super(key: key); + @override _ArticlePageState createState() => _ArticlePageState(); } class _ArticlePageState extends State { final ArticleController _articleController = ArticleController(); - late Future> _articlesFuture; @override @@ -30,15 +30,14 @@ class _ArticlePageState extends State { backgroundColor: Colors.indigoAccent, foregroundColor: Colors.white, ), - body: FutureBuilder>( future: _articlesFuture, builder: (context, snapshot) { if (snapshot.hasData) { if (snapshot.data!['ok']) { if (snapshot.data!['data'] != null && (snapshot.data!['data'] as List).isNotEmpty) { - List articles = snapshot.data!['data'] as List; - //Lista de articulos + List articles = (snapshot.data!['data'] as List).cast(); + // Lista de artículos return ListView.builder( itemCount: articles.length, itemBuilder: (context, index) { @@ -47,7 +46,6 @@ class _ArticlePageState extends State { child: ListTile( title: Text(article.nombre), subtitle: Text('id :${article.categoriaId}'), - //subtitle: Text('Clave: ${article.clave}'), trailing: Text('\$${article.precios.isNotEmpty ? article.precios.first.precio.toStringAsFixed(2) : 'N/A'}'), ), ); @@ -66,6 +64,22 @@ class _ArticlePageState extends State { } }, ), + floatingActionButton: FloatingActionButton( + onPressed: () async { + final result = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => FormularioArticulos()), + ); + if (result == true) { + setState(() { + _articlesFuture = _articleController.getArticles(widget.categoryId); + }); + } + }, + child: const Icon(Icons.add), + tooltip: 'Agregar artículo', + ), + floatingActionButtonLocation: FloatingActionButtonLocation.endFloat, ); } -} \ No newline at end of file +} diff --git a/lib/src/pages/formulario_articulos.dart b/lib/src/pages/formulario_articulos.dart new file mode 100644 index 0000000..6e58ff9 --- /dev/null +++ b/lib/src/pages/formulario_articulos.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:primer_practica/src/http_api/articles_api.dart'; // Asegúrate de importar la clase correcta + +class FormularioArticulos extends StatefulWidget { + @override + _FormularioArticulosState createState() => _FormularioArticulosState(); +} + +class _FormularioArticulosState extends State { + final _formKey = GlobalKey(); + String _clave = ''; + int _categoria = 1; + String _nombre = ''; + List _precios = [0.0, 0.0]; + bool _activo = true; + final ArticlesApi _articlesApi = ArticlesApi(); + + Future _guardarArticulo() async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + final result = await _articlesApi.addArticle( + clave: _clave, + categoria: _categoria, + nombre: _nombre, + precios: _precios, + activo: _activo, + ); + + if (result['statusCode'] == 200) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Artículo guardado exitosamente')), + ); + Navigator.pop(context); // Regresa a la lista de artículos + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error al guardar el artículo')), + ); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Formulario de Artículo'), + ), + body: Padding( + padding: EdgeInsets.all(16.0), + child: Form( + key: _formKey, + child: ListView( + children: [ + _buildTextField( + label: 'Clave', + onSaved: (value) => _clave = value!, + inputType: TextInputType.text, + ), + _buildTextField( + label: 'Categoría', + onSaved: (value) => _categoria = int.parse(value!), + inputType: TextInputType.number, + ), + _buildTextField( + label: 'Nombre', + onSaved: (value) => _nombre = value!, + inputType: TextInputType.text, + ), + _buildTextField( + label: 'Precio 1', + onSaved: (value) => _precios[0] = double.parse(value!), + inputType: TextInputType.number, + ), + _buildTextField( + label: 'Precio 2', + onSaved: (value) => _precios[1] = double.parse(value!), + inputType: TextInputType.number, + ), + SizedBox(height: 30), + Center( + child: ElevatedButton( + onPressed: _guardarArticulo, + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + textStyle: TextStyle(fontSize: 16), + ), + child: Text('Guardar'), + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildTextField({ + required String label, + required FormFieldSetter onSaved, + required TextInputType inputType, + }) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12.0), + child: TextFormField( + decoration: InputDecoration( + labelText: label, + border: OutlineInputBorder(), + contentPadding: EdgeInsets.symmetric(vertical: 15, horizontal: 10), + ), + keyboardType: inputType, + onSaved: onSaved, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Este campo es obligatorio'; + } + return null; + }, + ), + ); + } +} diff --git a/lib/src/pages/home_page.dart b/lib/src/pages/home_page.dart index 5f62e1e..15832ba 100644 --- a/lib/src/pages/home_page.dart +++ b/lib/src/pages/home_page.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:primer_practica/src/pages/category/lista_categorias.dart'; import 'package:primer_practica/custom/custom_app_bar.dart'; -import 'package:primer_practica/src/providers/carrito_providers.dart'; -import 'package:provider/provider.dart'; +//import 'package:primer_practica/src/providers/carrito_providers.dart'; +//import 'package:provider/provider.dart'; class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key);