Commit 41b242c3 by Nayeli Monserrat Velasco Lopez

Merge branch 'nayeli.velasco' into 'master'

Search delegate articulo See merge request !10
parents a1d4ef42 7eae9d62
import 'package:flutter/material.dart';
import '../http_api/ArticleApi.dart';
import '../models/ArticuloModel.dart';
class ArticleSearchDelegate extends SearchDelegate<String> {
final ArticleApi articleApi = ArticleApi();
ArticleSearchDelegate() : super(searchFieldLabel: 'Buscar artículos');
@override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
),
];
}
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, 'home');
},
);
}
@override
Widget buildResults(BuildContext context) {
return FutureBuilder<List<ArticleModel>>(
future: articleApi.searchArticles(query),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No articles found.'));
} else {
final articles = snapshot.data!;
return ListView.builder(
itemCount: articles.length,
itemBuilder: (context, index) {
final article = articles[index];
return ListTile(
title: Text(article.nombre),
subtitle: Text(article.precios.isNotEmpty ? '\$${article.precios.first.precio}' : 'No price available'),
trailing: IconButton(
icon: Icon(Icons.add_shopping_cart),
onPressed: () {
close(context, article.nombre);
},
),
);
},
);
}
},
);
}
@override
Widget buildSuggestions(BuildContext context) {
if (query.isEmpty) {
return Center(child: Text('Introduce un término de búsqueda'));
}
return FutureBuilder<List<ArticleModel>>(
future: articleApi.searchArticles(query),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No articles found.'));
} else {
final articles = snapshot.data!;
return ListView.builder(
itemCount: articles.length,
itemBuilder: (context, index) {
final article = articles[index];
return ListTile(
title: Text(article.nombre),
subtitle: Text(article.precios.isNotEmpty ? '\$${article.precios.first.precio}' : 'No price available'),
trailing: IconButton(
icon: Icon(Icons.add_shopping_cart),
onPressed: () {
close(context, article.nombre);
},
),
);
},
);
}
},
);
}
}
......@@ -2,20 +2,19 @@ import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';
import 'package:miapp_flutter/environments/archivo.dart';
import '../models/ArticuloModel.dart';
class ArticleApi {
final String apiUrl = 'articulo';
final String apiUrl = '${apiApp}/articulo';
// Método para obtener los artículos
Future<Map<String, dynamic>> getArticles(int categoryId) async {
String url = '${apiApp}/$apiUrl?categoria=$categoryId&offset=0&max=100';
String url = '$apiUrl?categoria=$categoryId&offset=0&max=100';
if (kDebugMode) {
print('Url -> $url');
}
try {
final response = await http.get(Uri.parse(url));
// Verifica el estado de la respuesta
if (response.statusCode == 200) {
return {
'statusCode': response.statusCode,
......@@ -34,4 +33,26 @@ class ArticleApi {
};
}
}
Future<List<ArticleModel>> searchArticles(String query) async {
try {
final response = await http.get(Uri.parse('$apiUrl?nombre=$query'));
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
if (response.statusCode == 200) {
try {
final Map<String, dynamic> data = json.decode(response.body);
final List<dynamic> articlesJson = data['data'];
return ArticleModel.fromJsonArray(articlesJson);
} catch (e) {
throw Exception('Error en procesamiento de datos: $e');
}
} else {
throw Exception('Error en la respuesta de la API: ${response.body}');
}
} catch (e) {
throw Exception('Error en la solicitud a la API: $e');
}
}
}
......@@ -34,6 +34,21 @@ class ArticleModel {
static List<ArticleModel> fromJsonArray(List<dynamic> jsonArray) {
return jsonArray.map((json) => ArticleModel.fromJson(json)).toList();
}
Map<String, dynamic> toJson() {
return {
'id': id,
'clave': clave,
'nombre': nombre,
'categoria': {'id': categoriaId},
'precios': precios.map((p) => p.toJson()).toList(),
'activo': activo,
};
}
static List<Map<String, dynamic>> toJsonArray(List<ArticleModel> articles) {
return articles.map((article) => article.toJson()).toList();
}
}
class Price {
......@@ -51,4 +66,11 @@ class Price {
precio: json['precio'].toDouble(),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'precio': precio,
};
}
}
import 'package:flutter/material.dart';
import '../models/ArticuloModel.dart';
class CarritoModel {
final ArticleModel articulo;
int cantidad;
double precio;
CarritoModel({
required this.articulo,
this.cantidad = 1,
required this.precio,
});
}
class CarritoProvider with ChangeNotifier {
List<CarritoModel> _carrito = [];
void addToCart(ArticleModel article) {
final existingItemIndex = _carrito.indexWhere((item) => item.articulo.id == article.id);
if (existingItemIndex >= 0) {
// Si el artículo ya está en el carrito, aumenta la cantidad
_carrito[existingItemIndex].cantidad += 1;
} else {
// Si el artículo no está en el carrito, agrégalo
final newItem = CarritoModel(
articulo: article,
precio: article.precios.isNotEmpty ? article.precios.first.precio : 0.0,
);
_carrito.add(newItem);
}
notifyListeners();
}
int get totalCarrito {
return _carrito.length;
}
List<CarritoModel> get carrito {
return [..._carrito];
}
}
......@@ -88,15 +88,17 @@ class _NewCategoryPageState extends State<NewCategoryPage> {
print('Datos de la categoría a enviar: ${json.encode(newCategory.toJson())}');
print(response);
if (response['statusCode'] == 200 || response['statusCode'] == 201) {
if (response['ok'] ) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error al crear categoría: ${response['body']}')),
SnackBar(content: Text('Categoría creada con éxito')),
);
Navigator.pushNamed(context,'home');
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Categoría creada con éxito')),
SnackBar(content: Text('Error al crear categoría: ${response['body']}')),
);
Navigator.pop(context);
}
}
},
......
import 'package:flutter/material.dart';
import 'package:miapp_flutter/src/specific_widgets/menu.dart';
import '../delegate/SearchDelegate.dart';
import 'NewCategoryPage.dart';
import 'category/CategoryListWidget.dart';
......@@ -28,17 +29,23 @@ class _HomePageState extends State<HomePage> {
String selectedPage = '';
void _handleNewCategory() {
// Navega a la página de nueva categoría
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const NewCategoryPage()),
);
}
void _startSearch() async {
showSearch(
context: context,
delegate: ArticleSearchDelegate(),
);
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2, // Número de pestañas
length: 2,
child: Scaffold(
appBar: AppBar(
title: const Text('Home Page'),
......@@ -53,6 +60,12 @@ class _HomePageState extends State<HomePage> {
);
},
),
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: _startSearch,
),
],
bottom: const TabBar(
tabs: [
Tab(icon: Icon(Icons.home), text: 'Categoria'),
......
......@@ -200,6 +200,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.12.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
nm:
dependency: transitive
description:
......@@ -232,6 +240,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.8"
provider:
dependency: "direct main"
description:
name: provider
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
url: "https://pub.dev"
source: hosted
version: "6.1.2"
sky_engine:
dependency: transitive
description: flutter
......
......@@ -40,6 +40,7 @@ dependencies:
http: ^1.2.2
connectivity_plus: ^6.0.4
intl: ^0.18.0
provider: ^6.1.2
dev_dependencies:
flutter_test:
......
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